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

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 (110) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/InsightsErrorAlert-1cg6LDJG.js +1 -0
  3. package/.output/public/assets/InsightsPageHeader-oNIg_lcd.js +1 -0
  4. package/.output/public/assets/InsightsRolloutCard-Zsv9gBjU.js +42 -0
  5. package/.output/public/assets/{api-keys-BzKocqRy.js → api-keys-ChJjsbP2.js} +1 -1
  6. package/.output/public/assets/{api-keys-api-BHcODB7q.js → api-keys-api-LchP65vQ.js} +1 -1
  7. package/.output/public/assets/{card-Dhr_eFYj.js → card-iD7iiy4T.js} +1 -1
  8. package/.output/public/assets/{chart-no-axes-combined-Dy4WJv2U.js → chart-no-axes-combined-C0G0fQ3J.js} +1 -1
  9. package/.output/public/assets/createServerFn-DHc2erub.js +3 -0
  10. package/.output/public/assets/dialog-DX6o8qCL.js +1 -0
  11. package/.output/public/assets/{dist-C_NydL0e.js → dist-BPrb_vuw.js} +1 -1
  12. package/.output/public/assets/index-C6Nb14xG.js +10 -0
  13. package/.output/public/assets/{input-group-cSOG4wh_.js → input-group-Pa3SAbEI.js} +1 -1
  14. package/.output/public/assets/insights-C1uKy3p2.js +1 -0
  15. package/.output/public/assets/installations-Bj5AzZ3T.js +1 -0
  16. package/.output/public/assets/{installations-CE33wgbY.js → installations-DDTw9DSK.js} +2 -2
  17. package/.output/public/assets/{lazyRouteComponent-Ccp3bwBY.js → lazyRouteComponent-BN0MS05o.js} +1 -1
  18. package/.output/public/assets/{link-CI8idAUi.js → link-BG06whwB.js} +1 -1
  19. package/.output/public/assets/{loader-circle-BoxLrsOu.js → loader-circle-Bbp8LGVC.js} +1 -1
  20. package/.output/public/assets/{refresh-cw-Bqc72UZG.js → refresh-cw-DZgiAOMk.js} +1 -1
  21. package/.output/public/assets/routes-9E2okfpG.js +1 -0
  22. package/.output/public/assets/{routes-DGVXdzpw.js → routes-B3JviaDV.js} +2 -2
  23. package/.output/public/assets/{shield-check-uK3MHWJZ.js → shield-check-DoIiaaXU.js} +1 -1
  24. package/.output/public/assets/{signing-CMf4aqDO.js → signing-BKy9fIdB.js} +1 -1
  25. package/.output/public/assets/styles-C5-su40i.css +2 -0
  26. package/.output/public/assets/{table-2vcV89QB.js → table-bpgpQkPz.js} +1 -1
  27. package/.output/public/assets/useOpenInteractionType-4dPacbwb.js +1 -0
  28. package/.output/public/assets/x-Cr_sPM8E.js +1 -0
  29. package/.output/server/{__23tanstack-start-server-fn-resolver-B7ioJhtE.mjs → __23tanstack-start-server-fn-resolver-EMel9KYs.mjs} +36 -32
  30. package/.output/server/_libs/@base-ui/react+[...].mjs +1051 -1051
  31. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1554 -0
  32. package/.output/server/_libs/@tanstack/react-router+[...].mjs +1 -1
  33. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +1 -1
  34. package/.output/server/_libs/d3-array.mjs +231 -0
  35. package/.output/server/_libs/d3-color.mjs +330 -0
  36. package/.output/server/_libs/d3-format.mjs +252 -0
  37. package/.output/server/_libs/d3-interpolate.mjs +207 -0
  38. package/.output/server/_libs/d3-path.mjs +77 -0
  39. package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
  40. package/.output/server/_libs/d3-shape.mjs +818 -0
  41. package/.output/server/_libs/decimal.js-light.mjs +884 -0
  42. package/.output/server/_libs/es-toolkit.mjs +1159 -0
  43. package/.output/server/_libs/eventemitter3.mjs +236 -0
  44. package/.output/server/_libs/immer.mjs +532 -0
  45. package/.output/server/_libs/lucide-react.mjs +1 -1
  46. package/.output/server/_libs/next-themes.mjs +1 -1
  47. package/.output/server/_libs/react-redux+[...].mjs +205 -0
  48. package/.output/server/_libs/recharts+[...].mjs +14636 -0
  49. package/.output/server/_libs/sonner.mjs +1 -1
  50. package/.output/server/_libs/tanstack__react-query.mjs +1 -1
  51. package/.output/server/_runtime.mjs +10 -1
  52. package/.output/server/_ssr/InsightsErrorAlert-DzDVdfgW.mjs +169 -0
  53. package/.output/server/_ssr/{InsightsPageHeader-Df4Brj8u.mjs → InsightsPageHeader-CZ2AaQGk.mjs} +8 -120
  54. package/.output/server/_ssr/InsightsRolloutCard-DHB2iM4t.mjs +693 -0
  55. package/.output/server/_ssr/{api-keys-CZeTPQys.mjs → api-keys-BBl84_lN.mjs} +7 -7
  56. package/.output/server/_ssr/{api-keys-api-BUPQVSpk.mjs → api-keys-api-KSH04dLB.mjs} +2 -2
  57. package/.output/server/_ssr/{api-keys-rpc-Cs7tS5_j.mjs → api-keys-rpc-DBmgnW5o.mjs} +3 -3
  58. package/.output/server/_ssr/{api-rpc-tAupfGQm.mjs → api-rpc-DX5B6b-L.mjs} +25 -25
  59. package/.output/server/_ssr/{auth-rpc-DUaeOWKK.mjs → auth-rpc-gaibR719.mjs} +4 -4
  60. package/.output/server/_ssr/{auth.server-DW71WzsD.mjs → auth.server-DF_shCeq.mjs} +1 -1
  61. package/.output/server/_ssr/{bundle-signing-rpc-BhnBw0-d.mjs → bundle-signing-rpc-C01EKpb-.mjs} +2 -2
  62. package/.output/server/_ssr/{bundle-signing.server-C4NW5mWx.mjs → bundle-signing.server-Co_zHdJx.mjs} +1 -1
  63. package/.output/server/_ssr/{card-BRiPmi0C.mjs → card-gGh8F6kQ.mjs} +1 -1
  64. package/.output/server/_ssr/{config.server-afDuAwaG.mjs → config.server-NIXXHk-e.mjs} +5 -5
  65. package/.output/server/_ssr/{createSsrRpc-DjWNJ0uc.mjs → createSsrRpc-4rr4IJh3.mjs} +3 -3
  66. package/.output/server/_ssr/{deleteBundle-BTGwBgzx.mjs → deleteBundle-C71v1GBr.mjs} +1 -1
  67. package/.output/server/_ssr/{dialog-DS-nw-pA.mjs → dialog-DNtKYR5K.mjs} +1 -1
  68. package/.output/server/_ssr/{downloadBundle-CNnYxYO2.mjs → downloadBundle-A9zYC2go.mjs} +1 -1
  69. package/.output/server/_ssr/{getBundleChildren-C0vh4ZvE.mjs → getBundleChildren-CMGSGBWv.mjs} +1 -1
  70. package/.output/server/_ssr/{input-group-BpsnmvZw.mjs → input-group-Oj4kUnE4.mjs} +1 -1
  71. package/.output/server/_ssr/{insights-BdS364Xu.mjs → insights-oK2n5WBp.mjs} +13 -67
  72. package/.output/server/_ssr/insights-recovery-DSFM-YTL.mjs +21 -0
  73. package/.output/server/_ssr/insights-recovery-rpc-CgeCAs2K.mjs +16 -0
  74. package/.output/server/_ssr/{insights-rpc-38DujK0G.mjs → insights-rpc-DBf0ouen.mjs} +2 -2
  75. package/.output/server/_ssr/insightsRecovery-DFkXGFjd.mjs +108 -0
  76. package/.output/server/_ssr/{installations-CtA59MQG.mjs → installations-DBmYuVBi.mjs} +2 -2
  77. package/.output/server/_ssr/{installations-DiVKEF5T.mjs → installations-DQyJN-pZ.mjs} +9 -9
  78. package/.output/server/_ssr/{router-B9wG_9f8.mjs → router-C8J4nYEG.mjs} +13 -13
  79. package/.output/server/_ssr/{routes-CKrrS2q2.mjs → routes-C2RIYhyl.mjs} +2 -2
  80. package/.output/server/_ssr/{routes-D7Yh_jfj.mjs → routes-NlTRKPML.mjs} +21 -86
  81. package/.output/server/_ssr/{runtime.server-DacU1TBV.mjs → runtime.server-DLZpzphL.mjs} +1 -1
  82. package/.output/server/_ssr/{server-D_C2rMzf.mjs → server-hgrXpJQY.mjs} +3 -3
  83. package/.output/server/_ssr/{signing-Dz1WkZOf.mjs → signing-bfOvUMSJ.mjs} +3 -3
  84. package/.output/server/_ssr/ssr.mjs +1 -1
  85. package/.output/server/_ssr/{table-CnZmon_Z.mjs → table-QQ9cnWf2.mjs} +3 -3
  86. package/.output/server/_tanstack-start-manifest_v-BAb_a_eC.mjs +97 -0
  87. package/.output/server/index.mjs +152 -152
  88. package/package.json +5 -5
  89. package/src/components/features/insights/InsightsRolloutCard.tsx +505 -0
  90. package/src/components/features/releases/ReleaseEditorSheet.tsx +13 -0
  91. package/src/components/ui/empty.tsx +101 -0
  92. package/src/lib/insights-recovery-rpc.ts +14 -0
  93. package/src/lib/insights-recovery.ts +55 -0
  94. package/src/lib/server/insightsRecovery.ts +157 -0
  95. package/src/routes/insights.tsx +2 -0
  96. package/.output/public/assets/HashValueDisplay-CB0Eskit.js +0 -1
  97. package/.output/public/assets/InsightsPageHeader-Car5LNiZ.js +0 -1
  98. package/.output/public/assets/composite-Bp98A0Ld.js +0 -1
  99. package/.output/public/assets/createServerFn-CA8fs7QD.js +0 -3
  100. package/.output/public/assets/dialog-CUTrcPlB.js +0 -1
  101. package/.output/public/assets/index-DdAz-CXv.js +0 -10
  102. package/.output/public/assets/insights-C0PBSZ-n.js +0 -1
  103. package/.output/public/assets/installations-CStZja8x.js +0 -1
  104. package/.output/public/assets/routes-DTlwOr8I.js +0 -1
  105. package/.output/public/assets/styles-BCvbtKsm.css +0 -2
  106. package/.output/public/assets/useCompositeListItem-CHLITE_4.js +0 -1
  107. package/.output/public/assets/x-DCd0j8c6.js +0 -1
  108. package/.output/server/_ssr/HashValueDisplay-DwpGLfrl.mjs +0 -55
  109. package/.output/server/_tanstack-start-manifest_v-2MjTyxil.mjs +0 -97
  110. /package/.output/public/assets/{preload-helper-CQ36nxok.js → preload-helper-B_l5jfgx.js} +0 -0
@@ -0,0 +1,157 @@
1
+ import type {
2
+ InsightsEventCursor,
3
+ InsightsModel,
4
+ } from "@hot-updater/plugin-core";
5
+
6
+ import {
7
+ readRecoveryInput,
8
+ recoveryWindows,
9
+ type RecoveryInput,
10
+ type RecoveryReport,
11
+ type RecoverySeries,
12
+ } from "../insights-recovery";
13
+
14
+ const MAX_SCAN_ROWS = 50_000;
15
+
16
+ export async function getRecoveryReport(
17
+ model: InsightsModel,
18
+ input: RecoveryInput,
19
+ beforeReceivedAtMs = Date.now(),
20
+ ): Promise<RecoveryReport> {
21
+ readRecoveryInput(input);
22
+ const { durationMs, intervalMs } = recoveryWindows[input.window];
23
+ const sinceMs = Math.max(0, beforeReceivedAtMs - durationMs);
24
+ const bucketStart = (time: number) =>
25
+ Math.floor(time / intervalMs) * intervalMs;
26
+ const releases = new Map<
27
+ string,
28
+ {
29
+ firstAdoptedAtMs: number | null;
30
+ buckets: Map<
31
+ number,
32
+ { adopted: number; recovered: number; lastRecoveredAtMs: number }
33
+ >;
34
+ }
35
+ >();
36
+ const adoptionTotals = new Map<number, number>();
37
+ let after: InsightsEventCursor | undefined;
38
+ let scanned = 0;
39
+ let truncated = false;
40
+ let completeSinceMs = sinceMs;
41
+
42
+ while (scanned < MAX_SCAN_ROWS) {
43
+ // Keep the existing bounded scan; native adapters own cursor pagination.
44
+ const limit = Math.min(100, MAX_SCAN_ROWS - scanned);
45
+ const rows = await model.listEvents({
46
+ filter: { kind: "all" },
47
+ sinceMs,
48
+ beforeReceivedAtMs,
49
+ after,
50
+ limit: limit + 1,
51
+ });
52
+ const page = rows.slice(0, limit);
53
+ for (const row of page) {
54
+ if (row.platform !== input.platform || row.channel !== input.channel)
55
+ continue;
56
+ if (row.type !== "RECOVERED" && row.type !== "RELEASE_ADOPTED") continue;
57
+ const releaseId =
58
+ row.type === "RECOVERED" ? row.from_release_id : row.to_release_id;
59
+ // Legacy reports without an ID cannot be attributed to a deployment.
60
+ if (!releaseId) continue;
61
+ const startMs = bucketStart(row.received_at_ms);
62
+ if (row.type === "RELEASE_ADOPTED") {
63
+ adoptionTotals.set(startMs, (adoptionTotals.get(startMs) ?? 0) + 1);
64
+ }
65
+ if (input.releaseId && releaseId !== input.releaseId) continue;
66
+ let release = releases.get(releaseId);
67
+ if (!release) {
68
+ release = { firstAdoptedAtMs: null, buckets: new Map() };
69
+ releases.set(releaseId, release);
70
+ }
71
+ const bucket = release.buckets.get(startMs) ?? {
72
+ adopted: 0,
73
+ recovered: 0,
74
+ lastRecoveredAtMs: -1,
75
+ };
76
+ if (row.type === "RECOVERED") {
77
+ bucket.recovered += 1;
78
+ bucket.lastRecoveredAtMs = Math.max(
79
+ bucket.lastRecoveredAtMs,
80
+ row.received_at_ms,
81
+ );
82
+ } else {
83
+ bucket.adopted += 1;
84
+ release.firstAdoptedAtMs = Math.min(
85
+ release.firstAdoptedAtMs ?? Infinity,
86
+ row.received_at_ms,
87
+ );
88
+ }
89
+ release.buckets.set(startMs, bucket);
90
+ }
91
+ scanned += page.length;
92
+ const last = page.at(-1);
93
+ if (!last || rows.length <= limit) break;
94
+ after = { id: last.id, receivedAtMs: last.received_at_ms };
95
+ if (scanned === MAX_SCAN_ROWS) {
96
+ truncated = true;
97
+ // The boundary bucket may contain an incomplete denominator. Omit it.
98
+ completeSinceMs = bucketStart(last.received_at_ms) + intervalMs;
99
+ }
100
+ }
101
+
102
+ const series: RecoverySeries[] = [];
103
+ for (const [releaseId, release] of releases) {
104
+ const firstAdoptedAtMs =
105
+ release.firstAdoptedAtMs !== null &&
106
+ release.firstAdoptedAtMs >= completeSinceMs
107
+ ? release.firstAdoptedAtMs
108
+ : null;
109
+ const points = [];
110
+ let previousRate: number | null = null;
111
+ for (
112
+ let startMs = bucketStart(completeSinceMs);
113
+ startMs < beforeReceivedAtMs;
114
+ startMs += intervalMs
115
+ ) {
116
+ const {
117
+ adopted = 0,
118
+ recovered = 0,
119
+ lastRecoveredAtMs = -1,
120
+ } = release.buckets.get(startMs) ?? {};
121
+ const total = adopted + recovered;
122
+ const totalAdopted = adoptionTotals.get(startMs) ?? 0;
123
+ const adoptionShare =
124
+ totalAdopted === 0 ? null : (adopted / totalAdopted) * 100;
125
+ const rate = total === 0 ? null : (recovered / total) * 100;
126
+ const afterAdoption =
127
+ firstAdoptedAtMs !== null && lastRecoveredAtMs >= firstAdoptedAtMs;
128
+ const spike =
129
+ afterAdoption &&
130
+ (!truncated || previousRate !== null) &&
131
+ rate !== null &&
132
+ total >= 10 &&
133
+ recovered >= 3 &&
134
+ rate >= 10 &&
135
+ rate - (previousRate ?? 0) >= 10;
136
+ points.push({ startMs, adopted, adoptionShare, recovered, rate, spike });
137
+ if (rate !== null) previousRate = rate;
138
+ }
139
+ if (points.some(({ rate }) => rate !== null))
140
+ series.push({ releaseId, firstAdoptedAtMs, points });
141
+ }
142
+ // Surface the most recent rollback signal first, then the newest ID.
143
+ series.sort((a, b) => {
144
+ const latestSpike = (s: RecoverySeries) =>
145
+ [...s.points].reverse().find((p) => p.spike)?.startMs ?? -1;
146
+ return (
147
+ latestSpike(b) - latestSpike(a) || b.releaseId.localeCompare(a.releaseId)
148
+ );
149
+ });
150
+ return {
151
+ sinceMs: completeSinceMs,
152
+ beforeReceivedAtMs,
153
+ intervalMs,
154
+ truncated,
155
+ series,
156
+ };
157
+ }
@@ -8,6 +8,7 @@ import {
8
8
  import { InsightsControls } from "@/components/features/insights/InsightsControls";
9
9
  import { InsightsOverview } from "@/components/features/insights/InsightsOverview";
10
10
  import { InsightsPageHeader } from "@/components/features/insights/InsightsPageHeader";
11
+ import { InsightsRolloutCard } from "@/components/features/insights/InsightsRolloutCard";
11
12
  import { Button } from "@/components/ui/button";
12
13
  import {
13
14
  type InsightsWindow,
@@ -47,6 +48,7 @@ function InsightsPage() {
47
48
  }}
48
49
  window={window}
49
50
  />
51
+ <InsightsRolloutCard input={{ ...scope, window }} />
50
52
  <Button
51
53
  className="h-11 self-end lg:h-8"
52
54
  variant="outline"
@@ -1 +0,0 @@
1
- import{Gn as e,Zn as t,_ as n,g as r,xn as i,y as a}from"./createServerFn-CA8fs7QD.js";import{n as o}from"./dist-C_NydL0e.js";var s=e(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),c=e(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]),l=t(),u=(e,t=12)=>e.length>t?`${e.slice(0,Math.max(1,t-4))}…${e.slice(-4)}`:e;function d({value:e,maxLength:t=12,className:s,buttonClassName:c}){let d=e.length>t,f=u(e,t),p=async()=>{try{await navigator.clipboard.writeText(e),o.success(`Copied to clipboard`,{description:e})}catch{o.error(`Failed to copy value`)}},m=e=>{e.preventDefault(),e.stopPropagation(),p()},h=e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),p())},g=(0,l.jsx)(`span`,{translate:`no`,className:i(`font-mono text-xs tabular-nums whitespace-nowrap`,s),children:f});return(0,l.jsxs)(r,{children:[(0,l.jsx)(a,{render:(0,l.jsx)(`button`,{type:`button`,"aria-label":`Copy full value: ${e}`,translate:`no`,className:i(`ring-ring/30 bg-muted/40 border-border/70 inline-flex min-w-0 max-w-full cursor-pointer items-center rounded-md border px-1.5 py-0.5 align-top shadow-xs outline-none transition-[background-color,border-color,transform,box-shadow]`,`hover:bg-muted/70 active:scale-[0.98] active:bg-muted/85 focus-visible:ring-[2px]`,`touch-manipulation select-none motion-reduce:transition-none motion-reduce:active:scale-100`,!d&&`cursor-copy`,c),onClick:m,onKeyDown:h}),children:g}),(0,l.jsx)(n,{hidden:!d,children:(0,l.jsx)(`p`,{translate:`no`,className:`break-all font-mono text-xs tabular-nums`,children:e})})]})}export{s as i,u as n,c as r,d as t};
@@ -1 +0,0 @@
1
- import{Dr as e,Gn as t,Jn as n,Wn as r,Zn as i,_r as a,bn as o,gn as s,kr as c,m as l,t as u,yn as d}from"./createServerFn-CA8fs7QD.js";import{t as f}from"./link-CI8idAUi.js";import{t as p}from"./chart-no-axes-combined-Dy4WJv2U.js";import{a as m,i as h,n as g,o as _,p as v,r as y,t as b}from"./table-2vcV89QB.js";import{i as ee,r as te,t as x}from"./HashValueDisplay-CB0Eskit.js";import{t as S}from"./refresh-cw-Bqc72UZG.js";import{a as C,c as w,d as T,n as E,o as D,s as ne,t as re,u as ie}from"./card-Dhr_eFYj.js";var ae=t(`activity`,[[`path`,{d:`M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2`,key:`169zse`}]]),O=t(`arrow-up-right`,[[`path`,{d:`M7 7h10v10`,key:`1tivn9`}],[`path`,{d:`M7 17 17 7`,key:`1vkiza`}]]),k=t(`package-check`,[[`path`,{d:`M12 22V12`,key:`d0xqtd`}],[`path`,{d:`m16 17 2 2 4-4`,key:`uh5qu3`}],[`path`,{d:`M21 11.127V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.729l7 4a2 2 0 0 0 2 .001l1.32-.753`,key:`kpkbpo`}],[`path`,{d:`M3.29 7 12 12l8.71-5`,key:`19ckod`}],[`path`,{d:`m7.5 4.27 8.997 5.148`,key:`9yrvtv`}]]),A=u({method:`GET`}).handler(a(`ff00311d412c8cdfa8ad5b0ba1eb6aa7471d0cc12170e6cc645deb91603d42dd`)),j=u({method:`GET`}).handler(a(`d4c50f40701055145f24873dc90f3c55a5494457a6a03a743339b2ac4545eb19`)),M=u({method:`GET`}).handler(a(`3c04bc6624be6dfdd80cf96819f9c6d0455e59a7bb4c0374b6afb0162ffd15b0`)),N=u({method:`GET`}).handler(a(`6726f1ed9eda1f0cb4c1f1ad1023faee435ddcfd0b7c55ef08ca7f2f7f577370`)),P=u({method:`GET`}).handler(a(`735c501f6d5ea81a445ff2b6b2ea6a1b589e3c6f63a465a881822c80ae71e7d1`)),F=3e4,I={reportingInstallations:e=>[`insights`,`reporting-installations`,e],events:e=>[`insights`,`events`,e],installations:e=>[`insights`,`installations`,e],installation:e=>[`insights`,`installation`,e],installationEvents:e=>[`insights`,`installation-events`,e]},L=e=>n({queryKey:I.reportingInstallations(e),queryFn:()=>A({data:e}),refetchOnWindowFocus:!0,staleTime:F}),R=(e,t)=>n({queryKey:I.events(e),queryFn:()=>j({data:e}),enabled:t,refetchOnWindowFocus:!0,staleTime:F}),z=(e,t)=>n({queryKey:I.installations(e),queryFn:()=>P({data:e}),enabled:t&&e.identity.length>0,staleTime:F}),B=(e,t)=>n({queryKey:I.installation(e),queryFn:()=>N({data:{installId:e}}),enabled:t&&e.length>0,staleTime:F}),V=(e,t)=>n({queryKey:I.installationEvents(e),queryFn:()=>M({data:e}),enabled:t&&e.installId.length>0,refetchOnWindowFocus:!0,staleTime:F}),H=c(e(),1),U=i(),W={UPDATE_APPLIED:{label:`Bundle applied`,variant:`success`,icon:v},RECOVERED:{label:`Recovered`,variant:`warning`,icon:te},RELEASE_ADOPTED:{label:`Bundle adopted`,variant:`success`,icon:k},UNCHANGED:{label:`Activity reported`,variant:`secondary`,icon:ae}};function G(){let[e,t]=(0,H.useState)(`UTC`);return(0,H.useEffect)(()=>{t(Intl.DateTimeFormat().resolvedOptions().timeZone)},[]),new Intl.DateTimeFormat(`en`,{timeZone:e,timeZoneName:`shortOffset`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hourCycle:`h23`})}function K(e,t){let n=Object.fromEntries(t.formatToParts(new Date(e)).map(({type:e,value:t})=>[e,t])),r=n.timeZoneName===`GMT`?`GMT+0`:n.timeZoneName;return`${n.year}/${n.month}/${n.day} ${n.hour}:${n.minute}:${n.second} ${r}`}function q({value:e,formatter:t,touch:n=!1}){let r=new Date(e),i=K(e,t);return(0,U.jsxs)(`details`,{className:`group/time`,children:[(0,U.jsx)(`summary`,{className:`cursor-pointer list-none rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring/30 [&::-webkit-details-marker]:hidden ${n?`flex min-h-11 items-center`:``}`,children:(0,U.jsxs)(`span`,{className:`flex items-center gap-1`,children:[(0,U.jsx)(`time`,{dateTime:r.toISOString(),className:`whitespace-nowrap`,children:i}),(0,U.jsx)(ee,{"aria-hidden":`true`,className:`size-3 text-muted-foreground group-open/time:rotate-180`})]})}),(0,U.jsx)(`p`,{className:`mt-2 text-muted-foreground`,children:r.toISOString().replace(`T`,` `).replace(`Z`,` UTC`)})]})}function J({type:e}){let t=W[e],n=t.icon;return(0,U.jsxs)(ne,{variant:t.variant,className:`gap-1 whitespace-nowrap [&_svg]:size-3`,title:e===`UNCHANGED`?`App activity reported on the current bundle without a bundle transition.`:e===`RELEASE_ADOPTED`?`A different release was adopted without changing the bundle.`:void 0,children:[(0,U.jsx)(n,{"aria-hidden":`true`}),t.label]})}function Y({event:e,touch:t=!1}){return(0,U.jsxs)(`dl`,{className:`grid grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2 gap-y-2`,children:[e.fromBundleId?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`dt`,{className:`text-muted-foreground`,children:`From`}),(0,U.jsx)(`dd`,{children:(0,U.jsx)(x,{value:e.fromBundleId,buttonClassName:t?`min-h-11 px-3`:void 0})})]}):null,(0,U.jsx)(`dt`,{className:`text-muted-foreground`,children:e.type===`UNCHANGED`?`Current`:`To`}),(0,U.jsx)(`dd`,{children:(0,U.jsx)(x,{value:e.toBundleId,buttonClassName:t?`min-h-11 px-3`:void 0})})]})}function X({events:e,formatter:t,renderIdentity:n}){return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`p`,{className:`px-4 pb-2 text-xs text-muted-foreground sm:px-6`,children:`Time in your browser zone`}),(0,U.jsx)(`ol`,{"aria-label":`Events`,className:`divide-y border-y`,children:e.map(e=>(0,U.jsxs)(`li`,{className:`flex min-w-0 flex-col gap-3 px-4 py-4 sm:px-6`,children:[(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-x-4 gap-y-1`,children:[(0,U.jsx)(J,{type:e.type}),(0,U.jsx)(`div`,{className:`text-xs tabular-nums`,children:(0,U.jsx)(q,{value:e.receivedAtMs,formatter:t,touch:!0})})]}),n?.(e),(0,U.jsxs)(`dl`,{className:`flex flex-wrap gap-x-2 gap-y-1 text-sm`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`dt`,{className:`sr-only`,children:`App`}),(0,U.jsxs)(`dd`,{children:[e.platform===`ios`?`iOS`:`Android`,` `,e.appVersion]})]}),(0,U.jsxs)(`div`,{className:`min-w-0 text-muted-foreground`,children:[(0,U.jsx)(`dt`,{className:`sr-only`,children:`Channel`}),(0,U.jsx)(`dd`,{className:`wrap-anywhere`,children:e.channel})]})]}),(0,U.jsx)(`div`,{className:`text-xs`,"aria-label":`Bundle`,children:(0,U.jsx)(Y,{event:e,touch:!0})})]},e.id))})]})}function Z({fallbackTitle:e}){return(0,U.jsxs)(w,{variant:`destructive`,children:[(0,U.jsx)(r,{"aria-hidden":`true`}),(0,U.jsx)(T,{children:e}),(0,U.jsx)(ie,{children:`Refresh to try again. If this keeps happening, check your Insights provider connection.`})]})}function Q({hasPrevious:e,label:t,nextCursor:n,onNext:r,onPrevious:i,pageLength:a,pageNumber:o}){return(0,U.jsxs)(`nav`,{"aria-label":`${t} pagination`,className:`flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3 sm:px-6`,children:[(0,U.jsxs)(`span`,{className:`text-xs text-muted-foreground tabular-nums`,children:[`Page `,o,` · `,a.toLocaleString(),` rows`]}),(0,U.jsxs)(`div`,{className:`flex gap-2`,children:[(0,U.jsx)(d,{className:`h-11 min-w-11 px-3 lg:h-8 lg:min-w-0 lg:px-2`,disabled:!e,onClick:i,size:`sm`,type:`button`,variant:`outline`,children:`Previous`}),(0,U.jsx)(d,{className:`h-11 min-w-11 px-3 lg:h-8 lg:min-w-0 lg:px-2`,disabled:n===null,onClick:r,size:`sm`,type:`button`,variant:`outline`,children:`Next`})]})]})}function $({event:e,eventsLocation:t,touch:n=!1}){return(0,U.jsxs)(`div`,{className:n?`flex min-w-0 flex-wrap items-center justify-between gap-2`:`flex min-w-0 flex-col items-start gap-2`,children:[(0,U.jsxs)(f,{className:o({className:n?`-ml-2 h-auto min-h-11 min-w-0 flex-1 justify-start gap-2 whitespace-normal text-sm`:`-ml-2 max-w-full justify-start`,size:`sm`,variant:`ghost`}),to:`/installations`,search:{...t,query:e.installId||void 0,installId:e.installId},"aria-label":`View history for ${e.userId??e.username??`anonymous installation`} (${e.installId})`,children:[(0,U.jsx)(`span`,{className:n?`min-w-0 text-left wrap-anywhere`:`truncate`,children:e.userId??e.username??`Anonymous installation`}),(0,U.jsx)(O,{"aria-hidden":`true`,"data-icon":`inline-end`})]}),(0,U.jsx)(x,{value:e.installId,maxLength:13,buttonClassName:n?`min-h-11 px-3`:void 0})]})}function oe({children:e,error:t,eventsLocation:n,history:r,isFetching:i,isLoading:a,onNext:o,onPrevious:c,onRefresh:l,pageNumber:u,title:f=`All events`}){let p=G(),v=u>1;return(0,U.jsxs)(re,{className:`@container min-w-0 shadow-sm`,"aria-busy":i,children:[(0,U.jsxs)(C,{className:`gap-4 p-4 sm:p-6`,children:[(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,U.jsx)(D,{children:(0,U.jsx)(`h2`,{children:f})}),(0,U.jsxs)(d,{className:`h-11 lg:h-8`,disabled:i,onClick:l,size:`lg`,variant:`outline`,children:[(0,U.jsx)(S,{"aria-hidden":`true`,"data-icon":`inline-start`}),`Refresh`]})]}),e]}),(0,U.jsx)(E,{className:`min-w-0 p-0`,children:a?(0,U.jsxs)(`div`,{className:`flex flex-col gap-4 p-6`,role:`status`,"aria-label":`Loading events`,children:[(0,U.jsx)(s,{className:`h-12 w-full`}),(0,U.jsx)(s,{className:`h-12 w-full`}),(0,U.jsx)(s,{className:`h-12 w-full`})]}):t?(0,U.jsx)(`div`,{className:`px-6 pb-6`,children:(0,U.jsx)(Z,{error:t,fallbackTitle:`Event history unavailable`})}):r?(0,U.jsxs)(U.Fragment,{children:[r.data.length>0?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`div`,{className:`@[58rem]:hidden`,children:(0,U.jsx)(X,{events:r.data,formatter:p,renderIdentity:e=>(0,U.jsx)($,{event:e,eventsLocation:n,touch:!0})})}),(0,U.jsx)(`div`,{className:`hidden @[58rem]:block`,children:(0,U.jsxs)(b,{className:`min-w-4xl table-fixed`,children:[(0,U.jsx)(m,{children:(0,U.jsxs)(_,{className:`[&>th]:px-4 sm:[&>th]:px-6`,children:[(0,U.jsx)(h,{className:`w-64`,children:`Time`}),(0,U.jsx)(h,{className:`w-48`,children:`Event`}),(0,U.jsx)(h,{className:`w-48`,children:`User / installation`}),(0,U.jsx)(h,{className:`w-32`,children:`App`}),(0,U.jsx)(h,{className:`w-52`,children:`Bundle`})]})}),(0,U.jsx)(g,{children:r.data.map(e=>(0,U.jsxs)(_,{className:`[&>td]:px-4 [&>td]:py-4 [&>td]:align-top sm:[&>td]:px-6`,children:[(0,U.jsx)(y,{className:`whitespace-normal text-xs tabular-nums`,children:(0,U.jsx)(q,{value:e.receivedAtMs,formatter:p})}),(0,U.jsx)(y,{children:(0,U.jsx)(J,{type:e.type})}),(0,U.jsx)(y,{children:(0,U.jsx)($,{event:e,eventsLocation:n})}),(0,U.jsx)(y,{className:`whitespace-normal text-xs`,children:(0,U.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,U.jsxs)(`span`,{children:[e.platform===`ios`?`iOS`:`Android`,` `,e.appVersion]}),(0,U.jsx)(`span`,{className:`text-muted-foreground`,children:e.channel})]})}),(0,U.jsx)(y,{className:`whitespace-normal text-xs`,children:(0,U.jsx)(Y,{event:e})})]},e.id))})]})})]}):(0,U.jsx)(`div`,{className:`px-6 pb-6 text-sm text-muted-foreground`,children:v||r.nextCursor?`No events on this page`:f===`All events`?`No events recorded yet`:`No matching reports in this period`}),r.data.length>0||v||r.nextCursor?(0,U.jsx)(Q,{hasPrevious:v,label:f,nextCursor:r.nextCursor,onNext:o,onPrevious:c,pageLength:r.data.length,pageNumber:u}):null]}):null})]})}function se({view:e}){return(0,U.jsxs)(`header`,{className:`sticky top-0 z-10 flex shrink-0 flex-wrap items-center gap-3 border-b bg-background px-3 py-3 sm:bg-card/70 sm:px-4 sm:backdrop-blur-sm`,children:[(0,U.jsx)(l,{className:`-ml-1 size-11 lg:size-7`}),(0,U.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,U.jsx)(p,{"aria-hidden":`true`,className:`size-3.5 text-muted-foreground`}),(0,U.jsx)(`h1`,{className:`text-sm font-medium`,children:`Insights`})]}),(0,U.jsxs)(`nav`,{"aria-label":`Insights views`,className:`ml-auto flex gap-1`,children:[(0,U.jsx)(f,{"aria-current":e===`overview`?`page`:void 0,className:o({className:`h-11 px-3 lg:h-8 lg:px-2.5`,size:`lg`,variant:e===`overview`?`secondary`:`ghost`}),to:`/insights`,children:`Overview`}),(0,U.jsx)(f,{"aria-current":e===`events`?`page`:void 0,className:o({className:`h-11 px-3 lg:h-8 lg:px-2.5`,size:`lg`,variant:e===`events`?`secondary`:`ghost`}),to:`/installations`,children:`Events`})]})]})}export{X as a,J as c,V as d,B as f,O as h,Z as i,G as l,L as m,oe as n,Y as o,z as p,Q as r,q as s,se as t,R as u};
@@ -1 +0,0 @@
1
- import{An as e}from"./createServerFn-CA8fs7QD.js";var t=`ArrowUp`,n=`ArrowDown`,r=`ArrowLeft`,i=`ArrowRight`,a=`Home`,o=`PageUp`,s=`PageDown`,c=new Set([r,i]),l=new Set([r,i,a,`End`]),u=new Set([t,n]),d=new Set([t,n,a,`End`]),f=new Set([...c,...u]),p=new Set([...f,a,`End`]),m=new Set([`Shift`,`Control`,`Alt`,`Meta`]);function h(t){return e(t)&&t.tagName===`INPUT`}function g(t){return!!(h(t)&&t.selectionStart!=null||e(t)&&t.tagName===`TEXTAREA`)}function _(e,t,n,r){if(!e||!t||!t.scrollTo)return;let i=e.scrollLeft,a=e.scrollTop,o=e.clientWidth<e.scrollWidth,s=e.clientHeight<e.scrollHeight;if(o&&r!==`vertical`){let r=v(e,t,`left`),a=y(e),o=y(t);n===`ltr`&&(r+t.offsetWidth+o.scrollMarginRight>e.scrollLeft+e.clientWidth-a.scrollPaddingRight?i=r+t.offsetWidth+o.scrollMarginRight-e.clientWidth+a.scrollPaddingRight:r-o.scrollMarginLeft<e.scrollLeft+a.scrollPaddingLeft&&(i=r-o.scrollMarginLeft-a.scrollPaddingLeft)),n===`rtl`&&(r-o.scrollMarginRight<e.scrollLeft+a.scrollPaddingLeft?i=r-o.scrollMarginLeft-a.scrollPaddingLeft:r+t.offsetWidth+o.scrollMarginRight>e.scrollLeft+e.clientWidth-a.scrollPaddingRight&&(i=r+t.offsetWidth+o.scrollMarginRight-e.clientWidth+a.scrollPaddingRight))}if(s&&r!==`horizontal`){let n=v(e,t,`top`),r=y(e),i=y(t);n-i.scrollMarginTop<e.scrollTop+r.scrollPaddingTop?a=n-i.scrollMarginTop-r.scrollPaddingTop:n+t.offsetHeight+i.scrollMarginBottom>e.scrollTop+e.clientHeight-r.scrollPaddingBottom&&(a=n+t.offsetHeight+i.scrollMarginBottom-e.clientHeight+r.scrollPaddingBottom)}e.scrollTo({left:i,top:a,behavior:`auto`})}function v(e,t,n){let r=n===`left`?`offsetLeft`:`offsetTop`,i=0;for(;t.offsetParent&&(i+=t[r],t.offsetParent!==e);)t=t.offsetParent;return i}function y(e){let t=getComputedStyle(e);return{scrollMarginTop:parseFloat(t.scrollMarginTop)||0,scrollMarginRight:parseFloat(t.scrollMarginRight)||0,scrollMarginBottom:parseFloat(t.scrollMarginBottom)||0,scrollMarginLeft:parseFloat(t.scrollMarginLeft)||0,scrollPaddingTop:parseFloat(t.scrollPaddingTop)||0,scrollPaddingRight:parseFloat(t.scrollPaddingRight)||0,scrollPaddingBottom:parseFloat(t.scrollPaddingBottom)||0,scrollPaddingLeft:parseFloat(t.scrollPaddingLeft)||0}}export{t as a,c,s as d,o as f,_ as g,g as h,i,l,d as m,f as n,p as o,u as p,r,a as s,n as t,m as u};