@lunora/studio 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (174) hide show
  1. package/__assets__/package-og.svg +1 -1
  2. package/dist/index.d.ts +29 -18
  3. package/dist/index.js +29 -29
  4. package/dist/mount.d.ts +1 -1
  5. package/dist/mount.js +1 -1
  6. package/dist/{packem_shared/ApiTab-W3no0KOj.js → packem_chunks/ApiTab.js} +5 -5
  7. package/dist/{packem_shared/AuditPanel-Bq4o_IqT.js → packem_chunks/AuditPanel.js} +24 -36
  8. package/dist/{packem_shared/ExportImportPanel-dxY56TDF.js → packem_chunks/ExportImportPanel.js} +13 -9
  9. package/dist/{packem_shared/FileBrowser-Dhy4zES8.js → packem_chunks/FileBrowser.js} +15 -15
  10. package/dist/{packem_shared/FunctionRunner--fQJRPAD.js → packem_chunks/FunctionRunner.js} +10 -10
  11. package/dist/{packem_shared/FunctionStatsPanel-BjRUA_G3.js → packem_chunks/FunctionStatsPanel.js} +147 -204
  12. package/dist/{packem_shared/HealthPanel-PxclMWmA.js → packem_chunks/HealthPanel.js} +37 -29
  13. package/dist/{packem_shared/InsightsPanel-CWS_C-xW.js → packem_chunks/InsightsPanel.js} +107 -69
  14. package/dist/{packem_shared/LogsPanel-CTW8CFcM.js → packem_chunks/LogsPanel.js} +41 -53
  15. package/dist/{packem_shared/MailPanel-BwkvfIHF.js → packem_chunks/MailPanel.js} +37 -44
  16. package/dist/{packem_shared/MetricsPanel-BLuOhZQ4.js → packem_chunks/MetricsPanel.js} +41 -322
  17. package/dist/{packem_shared/MigrationsPanel-DT3lnwHF.js → packem_chunks/MigrationsPanel.js} +39 -46
  18. package/dist/{packem_shared/PitrPanel-CdErL7EJ.js → packem_chunks/PitrPanel.js} +9 -9
  19. package/dist/{packem_shared/SchemaViewer-LJDcmNIO.js → packem_chunks/SchemaViewer.js} +15 -15
  20. package/dist/{packem_shared/SecurityAdvisorPanel-C_ETsPih.js → packem_chunks/SecurityAdvisorPanel.js} +44 -31
  21. package/dist/packem_chunks/SettingsPanel.js +390 -0
  22. package/dist/{packem_shared/sql-editor-panel-BFRpzj6r.js → packem_chunks/SqlEditorPanel.js} +12 -252
  23. package/dist/{packem_shared/TableEditor-ChfUOZec.js → packem_chunks/TableEditor.js} +10 -68
  24. package/dist/packem_chunks/analytics-panel.js +261 -0
  25. package/dist/packem_chunks/auth-config-panel.js +179 -0
  26. package/dist/packem_chunks/auth-sessions-panel.js +175 -0
  27. package/dist/packem_chunks/dashboards-panel.js +779 -0
  28. package/dist/packem_chunks/fanout-panel.js +481 -0
  29. package/dist/packem_chunks/flags-panel.js +176 -0
  30. package/dist/packem_chunks/kv-browser.js +1896 -0
  31. package/dist/packem_chunks/log-drains-panel.js +273 -0
  32. package/dist/packem_chunks/organizations-panel.js +670 -0
  33. package/dist/packem_chunks/payments-panel.js +185 -0
  34. package/dist/packem_chunks/permissions-panel.js +804 -0
  35. package/dist/packem_chunks/queues-panel.js +147 -0
  36. package/dist/packem_chunks/rls-panel.js +313 -0
  37. package/dist/packem_chunks/schedule-panel.js +831 -0
  38. package/dist/packem_chunks/sparkline.js +79 -0
  39. package/dist/packem_chunks/storage-rules-panel.js +138 -0
  40. package/dist/packem_chunks/subscriptions-panel.js +236 -0
  41. package/dist/packem_chunks/users-panel.js +1265 -0
  42. package/dist/packem_chunks/vector-browser.js +281 -0
  43. package/dist/packem_chunks/workflows-panel.js +562 -0
  44. package/dist/packem_shared/{ADMIN_FUNCTIONS-DmBqMZ-z.js → ADMIN_FUNCTIONS-CdaxLGkE.js} +3 -0
  45. package/dist/packem_shared/{ApiDocsPanel-C5-yJ1p7.js → ApiDocsPanel-B6u_wnz-.js} +2 -2
  46. package/dist/packem_shared/{ApiReferencePanel-1vubqG5s.js → ApiReferencePanel-Drz4UO0a.js} +2 -1
  47. package/dist/packem_shared/{CommandPalette-BtgkBzZI.js → CommandPalette-B5BertvU.js} +1 -1
  48. package/dist/packem_shared/{DataBrowser-CtBe1So9.js → DataBrowser-ANTHLWWh.js} +198 -247
  49. package/dist/packem_shared/{GlobalDataBrowser-BTEmGrph.js → GlobalDataBrowser-CjgTG_wa.js} +37 -66
  50. package/dist/packem_shared/HomePanel-c2FodE9t.js +14 -0
  51. package/dist/packem_shared/{OpenRpcReferencePanel-vbcYbv3V.js → OpenRpcReferencePanel-CspFdbUT.js} +2 -1
  52. package/dist/packem_shared/{ScheduledJobs-CabfKbyM.js → ScheduledJobs-BEJXtsBn.js} +163 -60
  53. package/dist/packem_shared/Studio-CVTtA_sB.js +16 -0
  54. package/dist/packem_shared/{StudioApp-CHOZA-z-.js → StudioApp-BSYV2fz6.js} +277 -3
  55. package/dist/packem_shared/{advisor-view-CGcfMiPq.js → advisor-view-DzqyvUU3.js} +1 -1
  56. package/dist/packem_shared/{app.d-CCmwDEVs.d.ts → app.d-B6MyY_al.d.ts} +1 -1
  57. package/dist/packem_shared/{bar-chart-CzJAgqkp.js → bar-chart-Bb__F5-u.js} +1 -1
  58. package/dist/packem_shared/browser-storage-d03UsV7v.js +249 -0
  59. package/dist/packem_shared/{cf-links-2cktDedA.js → cf-links-BZfRdxSE.js} +1 -1
  60. package/dist/packem_shared/{data-grid-B5CaV3wS.js → data-grid-Dsg6nRjo.js} +1 -1
  61. package/dist/packem_shared/data-view-params-Cd6yRVbv.js +96 -0
  62. package/dist/packem_shared/{grid-features-CzUfqgsM.js → grid-features-D7nNzBYm.js} +4 -99
  63. package/dist/packem_shared/{HomePanel-Cw16stjq.js → home-panel-aOR_drVv.js} +833 -469
  64. package/dist/packem_shared/{internal-rXJEAhXS.js → internal-FcNZ3beb.js} +1 -1
  65. package/dist/packem_shared/modal-shell-hyaJvIJ6.js +100 -0
  66. package/dist/packem_shared/{reference-view-B4E49Lip.js → reference-view-Doy1XlQq.js} +4 -44
  67. package/dist/packem_shared/select-UkNYCT3s.js +273 -0
  68. package/dist/packem_shared/skeleton-CGhL0p20.js +45 -0
  69. package/dist/packem_shared/{sparkline-10dG-_f0.js → sparkline-KgMPHS4u.js} +1 -1
  70. package/dist/packem_shared/studio-dMTJ-kRR.js +3987 -0
  71. package/dist/packem_shared/{table-_RzNvy3R.js → table-DsCa9Qp9.js} +1 -1
  72. package/dist/packem_shared/{table-list-sidebar-Bg7uzbvC.js → table-list-sidebar-VMo0ftxD.js} +1 -1
  73. package/dist/packem_shared/use-admin-query-BViPA3US.js +105 -0
  74. package/dist/packem_shared/use-auth-capabilities-BHkoBnbZ.js +32 -0
  75. package/dist/standalone/chunk-2DS7JLWL.js +13 -0
  76. package/dist/standalone/chunk-2K47A3P6.js +1 -0
  77. package/dist/standalone/chunk-2NGUNNGW.js +1 -0
  78. package/dist/standalone/chunk-2PDQ4KZ6.js +1 -0
  79. package/dist/standalone/chunk-3BP4BTLR.js +4 -0
  80. package/dist/standalone/chunk-3OA7PECS.js +6 -0
  81. package/dist/standalone/chunk-4QHKBC77.js +1 -0
  82. package/dist/standalone/chunk-57LYXHXH.js +1 -0
  83. package/dist/standalone/chunk-5NSZVXCS.js +1 -0
  84. package/dist/standalone/chunk-5OIBXYZM.js +1 -0
  85. package/dist/standalone/chunk-63XKJQTQ.js +1 -0
  86. package/dist/standalone/chunk-6RC6L33K.js +4 -0
  87. package/dist/standalone/chunk-6VTGE3WJ.js +1 -0
  88. package/dist/standalone/chunk-7PBZKXYA.js +1 -0
  89. package/dist/standalone/chunk-7POIIWC5.js +3 -0
  90. package/dist/standalone/chunk-7RYIQKZA.js +1 -0
  91. package/dist/standalone/chunk-7TJJXVSE.js +1 -0
  92. package/dist/standalone/chunk-AB6QGMBF.js +1 -0
  93. package/dist/standalone/chunk-AHILM3ZP.js +1 -0
  94. package/dist/standalone/chunk-AQGOX5DK.js +1 -0
  95. package/dist/standalone/chunk-ASLGNHAX.js +1 -0
  96. package/dist/standalone/chunk-BHTPZS7L.js +4 -0
  97. package/dist/standalone/chunk-BJGBHGK3.js +1 -0
  98. package/dist/standalone/chunk-D7HKX4DI.js +1 -0
  99. package/dist/standalone/chunk-DGWTR4G7.js +1 -0
  100. package/dist/standalone/chunk-DSX53PBM.js +1 -0
  101. package/dist/standalone/chunk-DV2MNASX.js +1 -0
  102. package/dist/standalone/chunk-DWDILV2E.js +1 -0
  103. package/dist/standalone/chunk-E7AVZZKO.js +1 -0
  104. package/dist/standalone/chunk-EGJX34WM.js +1 -0
  105. package/dist/standalone/chunk-FCR3HKFV.js +1 -0
  106. package/dist/standalone/chunk-FKO3HO6I.js +4 -0
  107. package/dist/standalone/chunk-FQKNJSRA.js +76 -0
  108. package/dist/standalone/chunk-G2TFEWEQ.js +4 -0
  109. package/dist/standalone/chunk-GABMIICA.js +1 -0
  110. package/dist/standalone/chunk-GTM65MVX.js +1 -0
  111. package/dist/standalone/chunk-GZXPPJVK.js +1 -0
  112. package/dist/standalone/chunk-HFBRE65A.js +1 -0
  113. package/dist/standalone/chunk-HFMQNUBC.js +1 -0
  114. package/dist/standalone/chunk-HG7Q5B3H.js +1 -0
  115. package/dist/standalone/chunk-HTQL7AXU.js +1 -0
  116. package/dist/standalone/chunk-HV7G6DFP.js +5 -0
  117. package/dist/standalone/chunk-ITLLHEVG.js +1 -0
  118. package/dist/standalone/chunk-J6J54MBP.js +1 -0
  119. package/dist/standalone/chunk-JSEXCW5Q.js +1 -0
  120. package/dist/standalone/chunk-KEGAWN6Y.js +1 -0
  121. package/dist/standalone/chunk-KG3QTFWE.js +1 -0
  122. package/dist/standalone/chunk-KGS7KM4A.js +2 -0
  123. package/dist/standalone/chunk-KODWGUAB.js +1 -0
  124. package/dist/standalone/chunk-KZ6INM5M.js +1 -0
  125. package/dist/standalone/chunk-MGFEVTRI.js +1 -0
  126. package/dist/standalone/chunk-N2QDG3MW.js +1 -0
  127. package/dist/standalone/chunk-N4JI6VQD.js +1 -0
  128. package/dist/standalone/chunk-NNISYDNI.js +1 -0
  129. package/dist/standalone/chunk-O4PXDNR3.js +1 -0
  130. package/dist/standalone/chunk-O77VNUFD.js +1 -0
  131. package/dist/standalone/chunk-OD2POGPJ.js +1 -0
  132. package/dist/standalone/chunk-OXCK3ZUG.js +1 -0
  133. package/dist/standalone/chunk-P7DSVO4U.js +1 -0
  134. package/dist/standalone/chunk-PKAM3N5C.js +1 -0
  135. package/dist/standalone/chunk-QGXGBHQO.js +1 -0
  136. package/dist/standalone/chunk-QHA3TAEJ.js +1 -0
  137. package/dist/standalone/chunk-QQWC62X7.js +1 -0
  138. package/dist/standalone/chunk-RMYA7NAH.js +1 -0
  139. package/dist/standalone/chunk-RRCPZMC2.js +22 -0
  140. package/dist/standalone/chunk-S53RUBW5.js +1 -0
  141. package/dist/standalone/chunk-SB4GT6PK.js +1 -0
  142. package/dist/standalone/chunk-SEU5V7I6.js +1 -0
  143. package/dist/standalone/chunk-SHIOUDOT.js +1 -0
  144. package/dist/standalone/chunk-SIDRSX7Y.js +1 -0
  145. package/dist/standalone/chunk-SVR644RF.js +1 -0
  146. package/dist/standalone/chunk-TAD43CG5.js +1 -0
  147. package/dist/standalone/chunk-TBMYIZIO.js +1 -0
  148. package/dist/standalone/chunk-TICVNLPM.js +1 -0
  149. package/dist/standalone/chunk-TQ36RWOP.js +1 -0
  150. package/dist/standalone/chunk-UGMRUEBU.js +1 -0
  151. package/dist/standalone/chunk-UII66UVF.js +1 -0
  152. package/dist/standalone/chunk-VJPQUBN6.js +8 -0
  153. package/dist/standalone/chunk-VLXV72QE.js +1 -0
  154. package/dist/standalone/chunk-VMJKJWG6.js +1 -0
  155. package/dist/standalone/chunk-VPDPN5RR.js +2 -0
  156. package/dist/standalone/chunk-VSEGZA3J.js +1 -0
  157. package/dist/standalone/chunk-VXBZQIGY.js +4 -0
  158. package/dist/standalone/chunk-W7PCVQTE.js +1 -0
  159. package/dist/standalone/chunk-XLILSHPE.js +1 -0
  160. package/dist/standalone/chunk-XURNGQSS.js +1 -0
  161. package/dist/standalone/chunk-YJGANMU7.js +18 -0
  162. package/dist/standalone/chunk-YQQJ4N6U.js +1 -0
  163. package/dist/standalone/chunk-ZH7UES4T.js +2 -0
  164. package/dist/standalone/chunk-ZPUO7FNI.js +1 -0
  165. package/dist/standalone/chunk-ZQCVDXDL.js +1 -0
  166. package/dist/standalone/studio.js +104 -246
  167. package/dist/styles.css +1 -1
  168. package/package.json +13 -12
  169. package/dist/packem_shared/SettingsPanel-C0uLRf5P.js +0 -176
  170. package/dist/packem_shared/SqlEditorPanel-CguV7otm.js +0 -13
  171. package/dist/packem_shared/Studio-DFWAlcuf.js +0 -33
  172. package/dist/packem_shared/studio-Bj8psK1c.js +0 -10303
  173. package/dist/packem_shared/use-live-admin-Dq6g3daN.js +0 -73
  174. package/dist/packem_shared/use-live-shard-seed-Cuk3dnH0.js +0 -76
@@ -0,0 +1,1265 @@
1
+ import { useLunora } from '@lunora/react';
2
+ import { useState, useEffect } from 'react';
3
+ import { B as Badge } from '../packem_shared/badge-B2PKA1-5.js';
4
+ import { B as Button } from '../packem_shared/button-BhsN2uZH.js';
5
+ import { C as Card, a as CardContent } from '../packem_shared/card-DURq3ElK.js';
6
+ import { E as EmptyState } from '../packem_shared/empty-state-DY_oe0k6.js';
7
+ import { I as Input } from '../packem_shared/input-XH4r1Pt1.js';
8
+ import { T as Table, a as TableHeader, b as TableRow, c as TableHead, d as TableBody, e as TableCell } from '../packem_shared/table-DsCa9Qp9.js';
9
+ import { a as useClientQuery } from '../packem_shared/use-admin-query-BViPA3US.js';
10
+ import { u as useAuthCapabilities } from '../packem_shared/use-auth-capabilities-BHkoBnbZ.js';
11
+ import { useAutoRefresh } from '../packem_shared/DEFAULT_AUTO_REFRESH_MS-Vxwaxx51.js';
12
+ import useDebounced from '../packem_shared/useDebounced-Dxncpg6z.js';
13
+ import { useT } from '../packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js';
14
+ import { f as fireAndForget, e as errorMessage, g as formatTimestamp, d as formatCell } from '../packem_shared/internal-FcNZ3beb.js';
15
+ import { L as Label } from '../packem_shared/label-D8ykjn5J.js';
16
+ import { M as ModalShell } from '../packem_shared/modal-shell-hyaJvIJ6.js';
17
+ import { jsxDEV, Fragment } from 'react/jsx-dev-runtime';
18
+ import { c } from 'react/compiler-runtime';
19
+
20
+ const UserCreateDialog = ({
21
+ onClose,
22
+ onCreated
23
+ }) => {
24
+ const client = useLunora();
25
+ const t = useT();
26
+ const [email, setEmail] = useState("");
27
+ const [name, setName] = useState("");
28
+ const [password, setPassword] = useState("");
29
+ const [role, setRole] = useState("");
30
+ const [busy, setBusy] = useState(false);
31
+ const [error, setError] = useState(null);
32
+ const onEmailChange = (event) => {
33
+ setEmail(event.target.value);
34
+ };
35
+ const onNameChange = (event_0) => {
36
+ setName(event_0.target.value);
37
+ };
38
+ const onPasswordChange = (event_1) => {
39
+ setPassword(event_1.target.value);
40
+ };
41
+ const onRoleChange = (event_2) => {
42
+ setRole(event_2.target.value);
43
+ };
44
+ const submit = async () => {
45
+ setBusy(true);
46
+ setError(null);
47
+ try {
48
+ await client.createAuthUser({
49
+ email: email.trim(),
50
+ name: name.trim(),
51
+ password: password === "" ? void 0 : password,
52
+ role: role.trim() === "" ? void 0 : role.trim()
53
+ });
54
+ onCreated();
55
+ onClose();
56
+ } catch (error_) {
57
+ setError(errorMessage(error_));
58
+ } finally {
59
+ setBusy(false);
60
+ }
61
+ };
62
+ const onSubmit = () => {
63
+ fireAndForget(submit());
64
+ };
65
+ return /* @__PURE__ */ jsxDEV(ModalShell, {
66
+ label: t("Create user"),
67
+ onClose,
68
+ panelTestId: "uc-dialog",
69
+ testId: "uc-overlay",
70
+ variant: "dialog",
71
+ children: [/* @__PURE__ */ jsxDEV("h2", {
72
+ className: "text-sm font-semibold text-foreground",
73
+ children: t("Create user")
74
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
75
+ className: "flex flex-col gap-1",
76
+ children: [/* @__PURE__ */ jsxDEV(Label, {
77
+ htmlFor: "uc-email",
78
+ children: t("email")
79
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
80
+ "data-testid": "uc-email",
81
+ id: "uc-email",
82
+ onChange: onEmailChange,
83
+ type: "email",
84
+ value: email
85
+ }, void 0, false)]
86
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
87
+ className: "flex flex-col gap-1",
88
+ children: [/* @__PURE__ */ jsxDEV(Label, {
89
+ htmlFor: "uc-name",
90
+ children: t("name")
91
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
92
+ "data-testid": "uc-name",
93
+ id: "uc-name",
94
+ onChange: onNameChange,
95
+ value: name
96
+ }, void 0, false)]
97
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
98
+ className: "flex flex-col gap-1",
99
+ children: [/* @__PURE__ */ jsxDEV(Label, {
100
+ htmlFor: "uc-password",
101
+ children: t("Password (optional)")
102
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
103
+ "data-testid": "uc-password",
104
+ id: "uc-password",
105
+ onChange: onPasswordChange,
106
+ type: "password",
107
+ value: password
108
+ }, void 0, false)]
109
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
110
+ className: "flex flex-col gap-1",
111
+ children: [/* @__PURE__ */ jsxDEV(Label, {
112
+ htmlFor: "uc-role",
113
+ children: t("Role (optional)")
114
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
115
+ "data-testid": "uc-role",
116
+ id: "uc-role",
117
+ onChange: onRoleChange,
118
+ value: role
119
+ }, void 0, false)]
120
+ }, void 0, true), error !== null && /* @__PURE__ */ jsxDEV("p", {
121
+ className: "text-sm text-destructive",
122
+ "data-testid": "uc-error",
123
+ role: "alert",
124
+ children: error
125
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
126
+ className: "flex justify-end gap-2 pt-1",
127
+ children: [/* @__PURE__ */ jsxDEV(Button, {
128
+ "data-testid": "uc-cancel",
129
+ onClick: onClose,
130
+ size: "sm",
131
+ type: "button",
132
+ variant: "outline",
133
+ children: t("Cancel")
134
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
135
+ "data-testid": "uc-submit",
136
+ disabled: busy || email.trim() === "" || name.trim() === "",
137
+ onClick: onSubmit,
138
+ size: "sm",
139
+ type: "button",
140
+ children: busy ? t("Creating…") : t("Create")
141
+ }, void 0, false)]
142
+ }, void 0, true)]
143
+ }, void 0, true);
144
+ };
145
+
146
+ const SectionHeading = (t0) => {
147
+ const $ = c(2);
148
+ const {
149
+ children
150
+ } = t0;
151
+ let t1;
152
+ if ($[0] !== children) {
153
+ t1 = /* @__PURE__ */ jsxDEV("h3", {
154
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
155
+ children
156
+ }, void 0, false);
157
+ $[0] = children;
158
+ $[1] = t1;
159
+ } else {
160
+ t1 = $[1];
161
+ }
162
+ return t1;
163
+ };
164
+ const UserSessionsPanel = (t0) => {
165
+ const $ = c(29);
166
+ const {
167
+ busy,
168
+ runAction,
169
+ userId,
170
+ version
171
+ } = t0;
172
+ const client = useLunora();
173
+ const t = useT();
174
+ const [sessions, setSessions] = useState(null);
175
+ const [error, setError] = useState(null);
176
+ let t1;
177
+ if ($[0] !== client || $[1] !== userId) {
178
+ t1 = () => {
179
+ fireAndForget((async () => {
180
+ setError(null);
181
+ try {
182
+ const page = await client.listAuthSessions({
183
+ limit: 50,
184
+ userId
185
+ });
186
+ setSessions(page.rows);
187
+ } catch (t22) {
188
+ const error_ = t22;
189
+ setSessions(null);
190
+ setError(errorMessage(error_));
191
+ }
192
+ })());
193
+ };
194
+ $[0] = client;
195
+ $[1] = userId;
196
+ $[2] = t1;
197
+ } else {
198
+ t1 = $[2];
199
+ }
200
+ let t2;
201
+ if ($[3] !== client || $[4] !== userId || $[5] !== version) {
202
+ t2 = [client, userId, version];
203
+ $[3] = client;
204
+ $[4] = userId;
205
+ $[5] = version;
206
+ $[6] = t2;
207
+ } else {
208
+ t2 = $[6];
209
+ }
210
+ useEffect(t1, t2);
211
+ let t3;
212
+ if ($[7] !== client || $[8] !== runAction) {
213
+ t3 = (sessionId) => {
214
+ runAction(() => client.revokeAuthSession({
215
+ sessionId
216
+ }));
217
+ };
218
+ $[7] = client;
219
+ $[8] = runAction;
220
+ $[9] = t3;
221
+ } else {
222
+ t3 = $[9];
223
+ }
224
+ const onRevoke = t3;
225
+ let t4;
226
+ if ($[10] !== t) {
227
+ t4 = t("Sessions");
228
+ $[10] = t;
229
+ $[11] = t4;
230
+ } else {
231
+ t4 = $[11];
232
+ }
233
+ let t5;
234
+ if ($[12] !== t4) {
235
+ t5 = /* @__PURE__ */ jsxDEV(SectionHeading, {
236
+ children: t4
237
+ }, void 0, false);
238
+ $[12] = t4;
239
+ $[13] = t5;
240
+ } else {
241
+ t5 = $[13];
242
+ }
243
+ let t6;
244
+ if ($[14] !== error) {
245
+ t6 = error !== null && /* @__PURE__ */ jsxDEV("p", {
246
+ className: "text-sm text-destructive",
247
+ "data-testid": "ud-sessions-error",
248
+ role: "alert",
249
+ children: error
250
+ }, void 0, false);
251
+ $[14] = error;
252
+ $[15] = t6;
253
+ } else {
254
+ t6 = $[15];
255
+ }
256
+ let t7;
257
+ if ($[16] !== sessions || $[17] !== t) {
258
+ t7 = sessions !== null && sessions.length === 0 && /* @__PURE__ */ jsxDEV("p", {
259
+ className: "text-sm text-muted-foreground",
260
+ "data-testid": "ud-sessions-empty",
261
+ children: t("No active sessions.")
262
+ }, void 0, false);
263
+ $[16] = sessions;
264
+ $[17] = t;
265
+ $[18] = t7;
266
+ } else {
267
+ t7 = $[18];
268
+ }
269
+ let t8;
270
+ if ($[19] !== busy || $[20] !== onRevoke || $[21] !== sessions || $[22] !== t) {
271
+ t8 = sessions !== null && sessions.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
272
+ className: "overflow-hidden py-0",
273
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
274
+ className: "px-0",
275
+ children: /* @__PURE__ */ jsxDEV(Table, {
276
+ "data-testid": "ud-sessions-table",
277
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
278
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
279
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
280
+ children: t("expires")
281
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
282
+ children: t("ip")
283
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
284
+ children: t("user agent")
285
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
286
+ "aria-label": t("Actions")
287
+ }, void 0, false)]
288
+ }, void 0, true)
289
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
290
+ children: sessions.map((session) => /* @__PURE__ */ jsxDEV(TableRow, {
291
+ "data-testid": `ud-session-${session.id}`,
292
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
293
+ className: "text-muted-foreground tabular-nums",
294
+ children: formatTimestamp(session.expiresAt)
295
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
296
+ children: session.ipAddress ?? ""
297
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
298
+ className: "max-w-40 truncate",
299
+ children: session.userAgent ?? ""
300
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
301
+ children: /* @__PURE__ */ jsxDEV(Button, {
302
+ "data-testid": `ud-revoke-${session.id}`,
303
+ disabled: busy,
304
+ onClick: () => {
305
+ onRevoke(session.id);
306
+ },
307
+ size: "xs",
308
+ type: "button",
309
+ variant: "ghost",
310
+ children: t("Revoke")
311
+ }, void 0, false)
312
+ }, void 0, false)]
313
+ }, session.id, true))
314
+ }, void 0, false)]
315
+ }, void 0, true)
316
+ }, void 0, false)
317
+ }, void 0, false);
318
+ $[19] = busy;
319
+ $[20] = onRevoke;
320
+ $[21] = sessions;
321
+ $[22] = t;
322
+ $[23] = t8;
323
+ } else {
324
+ t8 = $[23];
325
+ }
326
+ let t9;
327
+ if ($[24] !== t5 || $[25] !== t6 || $[26] !== t7 || $[27] !== t8) {
328
+ t9 = /* @__PURE__ */ jsxDEV("div", {
329
+ className: "flex flex-col gap-2",
330
+ "data-testid": "ud-sessions",
331
+ children: [t5, t6, t7, t8]
332
+ }, void 0, true);
333
+ $[24] = t5;
334
+ $[25] = t6;
335
+ $[26] = t7;
336
+ $[27] = t8;
337
+ $[28] = t9;
338
+ } else {
339
+ t9 = $[28];
340
+ }
341
+ return t9;
342
+ };
343
+ const UserAccountsPanel = (t0) => {
344
+ const $ = c(30);
345
+ const {
346
+ busy,
347
+ runAction,
348
+ userId,
349
+ version
350
+ } = t0;
351
+ const client = useLunora();
352
+ const t = useT();
353
+ const [accounts, setAccounts] = useState(null);
354
+ const [error, setError] = useState(null);
355
+ let t1;
356
+ if ($[0] !== client || $[1] !== userId) {
357
+ t1 = () => {
358
+ fireAndForget((async () => {
359
+ setError(null);
360
+ try {
361
+ setAccounts(await client.listAuthAccounts({
362
+ userId
363
+ }));
364
+ } catch (t22) {
365
+ const error_ = t22;
366
+ setAccounts(null);
367
+ setError(errorMessage(error_));
368
+ }
369
+ })());
370
+ };
371
+ $[0] = client;
372
+ $[1] = userId;
373
+ $[2] = t1;
374
+ } else {
375
+ t1 = $[2];
376
+ }
377
+ let t2;
378
+ if ($[3] !== client || $[4] !== userId || $[5] !== version) {
379
+ t2 = [client, userId, version];
380
+ $[3] = client;
381
+ $[4] = userId;
382
+ $[5] = version;
383
+ $[6] = t2;
384
+ } else {
385
+ t2 = $[6];
386
+ }
387
+ useEffect(t1, t2);
388
+ let t3;
389
+ if ($[7] !== client || $[8] !== runAction || $[9] !== userId) {
390
+ t3 = (accountId) => {
391
+ runAction(() => client.unlinkAuthAccount({
392
+ accountId,
393
+ userId
394
+ }));
395
+ };
396
+ $[7] = client;
397
+ $[8] = runAction;
398
+ $[9] = userId;
399
+ $[10] = t3;
400
+ } else {
401
+ t3 = $[10];
402
+ }
403
+ const onUnlink = t3;
404
+ let t4;
405
+ if ($[11] !== t) {
406
+ t4 = t("Linked accounts");
407
+ $[11] = t;
408
+ $[12] = t4;
409
+ } else {
410
+ t4 = $[12];
411
+ }
412
+ let t5;
413
+ if ($[13] !== t4) {
414
+ t5 = /* @__PURE__ */ jsxDEV(SectionHeading, {
415
+ children: t4
416
+ }, void 0, false);
417
+ $[13] = t4;
418
+ $[14] = t5;
419
+ } else {
420
+ t5 = $[14];
421
+ }
422
+ let t6;
423
+ if ($[15] !== error) {
424
+ t6 = error !== null && /* @__PURE__ */ jsxDEV("p", {
425
+ className: "text-sm text-destructive",
426
+ role: "alert",
427
+ children: error
428
+ }, void 0, false);
429
+ $[15] = error;
430
+ $[16] = t6;
431
+ } else {
432
+ t6 = $[16];
433
+ }
434
+ let t7;
435
+ if ($[17] !== accounts || $[18] !== t) {
436
+ t7 = accounts !== null && accounts.length === 0 && /* @__PURE__ */ jsxDEV("p", {
437
+ className: "text-sm text-muted-foreground",
438
+ children: t("No linked accounts.")
439
+ }, void 0, false);
440
+ $[17] = accounts;
441
+ $[18] = t;
442
+ $[19] = t7;
443
+ } else {
444
+ t7 = $[19];
445
+ }
446
+ let t8;
447
+ if ($[20] !== accounts || $[21] !== busy || $[22] !== onUnlink || $[23] !== t) {
448
+ t8 = accounts !== null && accounts.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
449
+ className: "overflow-hidden py-0",
450
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
451
+ className: "px-0",
452
+ children: /* @__PURE__ */ jsxDEV(Table, {
453
+ "data-testid": "ud-accounts-table",
454
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
455
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
456
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
457
+ children: t("provider")
458
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
459
+ children: t("created")
460
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
461
+ "aria-label": t("Actions")
462
+ }, void 0, false)]
463
+ }, void 0, true)
464
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
465
+ children: accounts.map((account) => {
466
+ const id = formatCell(account.id);
467
+ return /* @__PURE__ */ jsxDEV(TableRow, {
468
+ "data-testid": `ud-account-${id}`,
469
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
470
+ children: formatCell(account.providerId)
471
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
472
+ className: "text-muted-foreground tabular-nums",
473
+ children: formatTimestamp(account.createdAt)
474
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
475
+ children: /* @__PURE__ */ jsxDEV(Button, {
476
+ "data-testid": `ud-unlink-${id}`,
477
+ disabled: busy,
478
+ onClick: () => {
479
+ onUnlink(id);
480
+ },
481
+ size: "xs",
482
+ type: "button",
483
+ variant: "ghost",
484
+ children: t("Unlink")
485
+ }, void 0, false)
486
+ }, void 0, false)]
487
+ }, id, true);
488
+ })
489
+ }, void 0, false)]
490
+ }, void 0, true)
491
+ }, void 0, false)
492
+ }, void 0, false);
493
+ $[20] = accounts;
494
+ $[21] = busy;
495
+ $[22] = onUnlink;
496
+ $[23] = t;
497
+ $[24] = t8;
498
+ } else {
499
+ t8 = $[24];
500
+ }
501
+ let t9;
502
+ if ($[25] !== t5 || $[26] !== t6 || $[27] !== t7 || $[28] !== t8) {
503
+ t9 = /* @__PURE__ */ jsxDEV("div", {
504
+ className: "flex flex-col gap-2",
505
+ "data-testid": "ud-accounts",
506
+ children: [t5, t6, t7, t8]
507
+ }, void 0, true);
508
+ $[25] = t5;
509
+ $[26] = t6;
510
+ $[27] = t7;
511
+ $[28] = t8;
512
+ $[29] = t9;
513
+ } else {
514
+ t9 = $[29];
515
+ }
516
+ return t9;
517
+ };
518
+ const UserSecurityPanel = (t0) => {
519
+ const $ = c(40);
520
+ const {
521
+ busy,
522
+ capabilities,
523
+ runAction,
524
+ userId,
525
+ version
526
+ } = t0;
527
+ const client = useLunora();
528
+ const t = useT();
529
+ const [passkeys, setPasskeys] = useState(null);
530
+ let t1;
531
+ if ($[0] !== capabilities.passkey || $[1] !== client || $[2] !== userId) {
532
+ t1 = () => {
533
+ if (!capabilities.passkey) {
534
+ return;
535
+ }
536
+ fireAndForget((async () => {
537
+ try {
538
+ setPasskeys(await client.listAuthPasskeys({
539
+ userId
540
+ }));
541
+ } catch {
542
+ setPasskeys(null);
543
+ }
544
+ })());
545
+ };
546
+ $[0] = capabilities.passkey;
547
+ $[1] = client;
548
+ $[2] = userId;
549
+ $[3] = t1;
550
+ } else {
551
+ t1 = $[3];
552
+ }
553
+ let t2;
554
+ if ($[4] !== capabilities.passkey || $[5] !== client || $[6] !== userId || $[7] !== version) {
555
+ t2 = [capabilities.passkey, client, userId, version];
556
+ $[4] = capabilities.passkey;
557
+ $[5] = client;
558
+ $[6] = userId;
559
+ $[7] = version;
560
+ $[8] = t2;
561
+ } else {
562
+ t2 = $[8];
563
+ }
564
+ useEffect(t1, t2);
565
+ let t3;
566
+ if ($[9] !== client || $[10] !== runAction || $[11] !== userId) {
567
+ t3 = () => {
568
+ runAction(() => client.disableAuthTwoFactor({
569
+ userId
570
+ }));
571
+ };
572
+ $[9] = client;
573
+ $[10] = runAction;
574
+ $[11] = userId;
575
+ $[12] = t3;
576
+ } else {
577
+ t3 = $[12];
578
+ }
579
+ const onDisable2fa = t3;
580
+ let t4;
581
+ if ($[13] !== client || $[14] !== runAction) {
582
+ t4 = (passkeyId) => {
583
+ runAction(() => client.deleteAuthPasskey({
584
+ passkeyId
585
+ }));
586
+ };
587
+ $[13] = client;
588
+ $[14] = runAction;
589
+ $[15] = t4;
590
+ } else {
591
+ t4 = $[15];
592
+ }
593
+ const onDeletePasskey = t4;
594
+ let t5;
595
+ if ($[16] !== t) {
596
+ t5 = t("Security");
597
+ $[16] = t;
598
+ $[17] = t5;
599
+ } else {
600
+ t5 = $[17];
601
+ }
602
+ let t6;
603
+ if ($[18] !== t5) {
604
+ t6 = /* @__PURE__ */ jsxDEV(SectionHeading, {
605
+ children: t5
606
+ }, void 0, false);
607
+ $[18] = t5;
608
+ $[19] = t6;
609
+ } else {
610
+ t6 = $[19];
611
+ }
612
+ let t7;
613
+ if ($[20] !== busy || $[21] !== capabilities.twoFactor || $[22] !== onDisable2fa || $[23] !== t) {
614
+ t7 = capabilities.twoFactor && /* @__PURE__ */ jsxDEV(Button, {
615
+ "data-testid": "ud-disable-2fa",
616
+ disabled: busy,
617
+ onClick: onDisable2fa,
618
+ size: "sm",
619
+ type: "button",
620
+ variant: "outline",
621
+ children: t("Disable two-factor")
622
+ }, void 0, false);
623
+ $[20] = busy;
624
+ $[21] = capabilities.twoFactor;
625
+ $[22] = onDisable2fa;
626
+ $[23] = t;
627
+ $[24] = t7;
628
+ } else {
629
+ t7 = $[24];
630
+ }
631
+ let t8;
632
+ if ($[25] !== capabilities.passkey || $[26] !== passkeys || $[27] !== t) {
633
+ t8 = capabilities.passkey && passkeys !== null && passkeys.length === 0 && /* @__PURE__ */ jsxDEV("p", {
634
+ className: "text-sm text-muted-foreground",
635
+ children: t("No passkeys.")
636
+ }, void 0, false);
637
+ $[25] = capabilities.passkey;
638
+ $[26] = passkeys;
639
+ $[27] = t;
640
+ $[28] = t8;
641
+ } else {
642
+ t8 = $[28];
643
+ }
644
+ let t9;
645
+ if ($[29] !== busy || $[30] !== capabilities.passkey || $[31] !== onDeletePasskey || $[32] !== passkeys || $[33] !== t) {
646
+ t9 = capabilities.passkey && passkeys !== null && passkeys.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
647
+ className: "overflow-hidden py-0",
648
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
649
+ className: "px-0",
650
+ children: /* @__PURE__ */ jsxDEV(Table, {
651
+ "data-testid": "ud-passkeys-table",
652
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
653
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
654
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
655
+ children: t("name")
656
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
657
+ children: t("created")
658
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
659
+ "aria-label": t("Actions")
660
+ }, void 0, false)]
661
+ }, void 0, true)
662
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
663
+ children: passkeys.map((passkey) => {
664
+ const id = formatCell(passkey.id);
665
+ return /* @__PURE__ */ jsxDEV(TableRow, {
666
+ "data-testid": `ud-passkey-${id}`,
667
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
668
+ children: formatCell(passkey.name) || id
669
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
670
+ className: "text-muted-foreground tabular-nums",
671
+ children: formatTimestamp(passkey.createdAt)
672
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
673
+ children: /* @__PURE__ */ jsxDEV(Button, {
674
+ "data-testid": `ud-delete-passkey-${id}`,
675
+ disabled: busy,
676
+ onClick: () => {
677
+ onDeletePasskey(id);
678
+ },
679
+ size: "xs",
680
+ type: "button",
681
+ variant: "ghost",
682
+ children: t("Delete")
683
+ }, void 0, false)
684
+ }, void 0, false)]
685
+ }, id, true);
686
+ })
687
+ }, void 0, false)]
688
+ }, void 0, true)
689
+ }, void 0, false)
690
+ }, void 0, false);
691
+ $[29] = busy;
692
+ $[30] = capabilities.passkey;
693
+ $[31] = onDeletePasskey;
694
+ $[32] = passkeys;
695
+ $[33] = t;
696
+ $[34] = t9;
697
+ } else {
698
+ t9 = $[34];
699
+ }
700
+ let t10;
701
+ if ($[35] !== t6 || $[36] !== t7 || $[37] !== t8 || $[38] !== t9) {
702
+ t10 = /* @__PURE__ */ jsxDEV("div", {
703
+ className: "flex flex-col gap-2",
704
+ "data-testid": "ud-security",
705
+ children: [t6, t7, t8, t9]
706
+ }, void 0, true);
707
+ $[35] = t6;
708
+ $[36] = t7;
709
+ $[37] = t8;
710
+ $[38] = t9;
711
+ $[39] = t10;
712
+ } else {
713
+ t10 = $[39];
714
+ }
715
+ return t10;
716
+ };
717
+
718
+ const TIMESTAMP_RE = /(?:at|expires)$/iu;
719
+ const SUMMARY_FIELDS = /* @__PURE__ */ new Set(["banExpires", "banned", "banReason", "email", "emailVerified", "id", "name", "role"]);
720
+ const formatField = (key, value) => {
721
+ if (typeof value === "number" && TIMESTAMP_RE.test(key)) {
722
+ return formatTimestamp(value);
723
+ }
724
+ return formatCell(value);
725
+ };
726
+ const UserDetailDrawer = ({
727
+ capabilities,
728
+ onChanged,
729
+ onClose,
730
+ user
731
+ }) => {
732
+ const client = useLunora();
733
+ const t = useT();
734
+ const banned = user.banned === true;
735
+ const [actionError, setActionError] = useState(null);
736
+ const [busy, setBusy] = useState(false);
737
+ const [version, setVersion] = useState(0);
738
+ const [roleInput, setRoleInput] = useState(typeof user.role === "string" ? user.role : "");
739
+ const [banReason, setBanReason] = useState("");
740
+ const [banDays, setBanDays] = useState("");
741
+ const [newPassword, setNewPassword] = useState("");
742
+ const [impersonationToken, setImpersonationToken] = useState(null);
743
+ const [confirmDelete, setConfirmDelete] = useState(false);
744
+ const runAction = (action, options) => {
745
+ fireAndForget((async () => {
746
+ setBusy(true);
747
+ setActionError(null);
748
+ try {
749
+ const result = await action();
750
+ if (options?.refresh !== false) {
751
+ setVersion((value) => value + 1);
752
+ onChanged();
753
+ }
754
+ options?.onResult?.(result);
755
+ } catch (error_) {
756
+ setActionError(errorMessage(error_));
757
+ } finally {
758
+ setBusy(false);
759
+ }
760
+ })());
761
+ };
762
+ const onRoleInputChange = (event) => {
763
+ setRoleInput(event.target.value);
764
+ };
765
+ const onBanReasonChange = (event_0) => {
766
+ setBanReason(event_0.target.value);
767
+ };
768
+ const onBanDaysChange = (event_1) => {
769
+ setBanDays(event_1.target.value);
770
+ };
771
+ const onNewPasswordChange = (event_2) => {
772
+ setNewPassword(event_2.target.value);
773
+ };
774
+ const onSetRole = () => {
775
+ const role = roleInput.trim();
776
+ if (role === "") {
777
+ return;
778
+ }
779
+ runAction(async () => {
780
+ await client.setAuthUserRole({
781
+ role,
782
+ userId: user.id
783
+ });
784
+ });
785
+ };
786
+ const onBan = () => {
787
+ const days = Number.parseInt(banDays, 10);
788
+ const expiresInSeconds = Number.isFinite(days) && days > 0 ? days * 86400 : void 0;
789
+ runAction(async () => {
790
+ await client.banAuthUser({
791
+ expiresInSeconds,
792
+ reason: banReason.trim() === "" ? void 0 : banReason.trim(),
793
+ userId: user.id
794
+ });
795
+ });
796
+ };
797
+ const onUnban = () => {
798
+ runAction(async () => {
799
+ await client.unbanAuthUser({
800
+ userId: user.id
801
+ });
802
+ });
803
+ };
804
+ const onSetPassword = () => {
805
+ runAction(async () => {
806
+ await client.setAuthUserPassword({
807
+ newPassword,
808
+ userId: user.id
809
+ });
810
+ setNewPassword("");
811
+ });
812
+ };
813
+ const onImpersonate = () => {
814
+ runAction(() => client.impersonateAuthUser({
815
+ userId: user.id
816
+ }), {
817
+ onResult: (result_0) => {
818
+ setImpersonationToken(result_0.token);
819
+ },
820
+ refresh: false
821
+ });
822
+ };
823
+ const onRevokeAll = () => {
824
+ runAction(async () => {
825
+ await client.revokeAuthUserSessions({
826
+ userId: user.id
827
+ });
828
+ });
829
+ };
830
+ const onDelete = () => {
831
+ runAction(async () => {
832
+ await client.removeAuthUser({
833
+ userId: user.id
834
+ });
835
+ onClose();
836
+ });
837
+ };
838
+ const onConfirmDelete = () => {
839
+ setConfirmDelete(true);
840
+ };
841
+ const onCancelDelete = () => {
842
+ setConfirmDelete(false);
843
+ };
844
+ const rawFields = Object.entries(user).filter(([key]) => !SUMMARY_FIELDS.has(key));
845
+ return /* @__PURE__ */ jsxDEV(ModalShell, {
846
+ label: t("User details"),
847
+ onClose,
848
+ panelTestId: "ud-panel",
849
+ testId: "ud-overlay",
850
+ variant: "drawer",
851
+ children: [/* @__PURE__ */ jsxDEV("div", {
852
+ className: "flex items-start justify-between gap-2",
853
+ children: [/* @__PURE__ */ jsxDEV("div", {
854
+ className: "flex flex-col gap-1",
855
+ children: [/* @__PURE__ */ jsxDEV("h2", {
856
+ className: "text-sm font-semibold text-foreground",
857
+ children: user.name ?? user.email ?? user.id
858
+ }, void 0, false), /* @__PURE__ */ jsxDEV("p", {
859
+ className: "font-mono text-xs text-muted-foreground",
860
+ children: user.id
861
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
862
+ className: "flex flex-wrap items-center gap-1.5 pt-1",
863
+ children: [typeof user.role === "string" && user.role !== "" && /* @__PURE__ */ jsxDEV(Badge, {
864
+ variant: "secondary",
865
+ children: user.role
866
+ }, void 0, false), banned ? /* @__PURE__ */ jsxDEV(Badge, {
867
+ variant: "destructive",
868
+ children: t("Banned")
869
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
870
+ variant: "outline",
871
+ children: t("Active")
872
+ }, void 0, false), user.emailVerified === true ? /* @__PURE__ */ jsxDEV(Badge, {
873
+ variant: "secondary",
874
+ children: t("verified")
875
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
876
+ variant: "outline",
877
+ children: t("unverified")
878
+ }, void 0, false)]
879
+ }, void 0, true)]
880
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
881
+ "data-testid": "ud-close",
882
+ onClick: onClose,
883
+ size: "sm",
884
+ type: "button",
885
+ variant: "ghost",
886
+ children: t("Close")
887
+ }, void 0, false)]
888
+ }, void 0, true), actionError !== null && /* @__PURE__ */ jsxDEV("p", {
889
+ className: "text-sm text-destructive",
890
+ "data-testid": "ud-action-error",
891
+ role: "alert",
892
+ children: actionError
893
+ }, void 0, false), capabilities.admin && /* @__PURE__ */ jsxDEV(Card, {
894
+ className: "gap-0 py-0",
895
+ children: [/* @__PURE__ */ jsxDEV("header", {
896
+ className: "border-b border-border px-4 py-3",
897
+ children: /* @__PURE__ */ jsxDEV("span", {
898
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
899
+ children: t("Actions")
900
+ }, void 0, false)
901
+ }, void 0, false), /* @__PURE__ */ jsxDEV(CardContent, {
902
+ className: "flex flex-col gap-3 p-3",
903
+ children: [/* @__PURE__ */ jsxDEV("div", {
904
+ className: "flex items-end gap-2",
905
+ children: [/* @__PURE__ */ jsxDEV("div", {
906
+ className: "flex flex-1 flex-col gap-1",
907
+ children: [/* @__PURE__ */ jsxDEV(Label, {
908
+ htmlFor: "ud-role",
909
+ children: t("Role")
910
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
911
+ "data-testid": "ud-role-input",
912
+ id: "ud-role",
913
+ onChange: onRoleInputChange,
914
+ value: roleInput
915
+ }, void 0, false)]
916
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
917
+ "data-testid": "ud-set-role",
918
+ disabled: busy || roleInput.trim() === "",
919
+ onClick: onSetRole,
920
+ size: "sm",
921
+ type: "button",
922
+ variant: "outline",
923
+ children: t("Set role")
924
+ }, void 0, false)]
925
+ }, void 0, true), banned ? /* @__PURE__ */ jsxDEV(Button, {
926
+ "data-testid": "ud-unban",
927
+ disabled: busy,
928
+ onClick: onUnban,
929
+ size: "sm",
930
+ type: "button",
931
+ variant: "outline",
932
+ children: t("Unban")
933
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
934
+ className: "flex items-end gap-2",
935
+ children: [/* @__PURE__ */ jsxDEV("div", {
936
+ className: "flex flex-1 flex-col gap-1",
937
+ children: [/* @__PURE__ */ jsxDEV(Label, {
938
+ htmlFor: "ud-ban-reason",
939
+ children: t("Ban reason (optional)")
940
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
941
+ "data-testid": "ud-ban-reason",
942
+ id: "ud-ban-reason",
943
+ onChange: onBanReasonChange,
944
+ value: banReason
945
+ }, void 0, false)]
946
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
947
+ className: "flex w-24 flex-col gap-1",
948
+ children: [/* @__PURE__ */ jsxDEV(Label, {
949
+ htmlFor: "ud-ban-days",
950
+ children: t("Days")
951
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
952
+ "data-testid": "ud-ban-days",
953
+ id: "ud-ban-days",
954
+ onChange: onBanDaysChange,
955
+ type: "number",
956
+ value: banDays
957
+ }, void 0, false)]
958
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
959
+ "data-testid": "ud-ban",
960
+ disabled: busy,
961
+ onClick: onBan,
962
+ size: "sm",
963
+ type: "button",
964
+ variant: "destructive",
965
+ children: t("Ban user")
966
+ }, void 0, false)]
967
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
968
+ className: "flex items-end gap-2",
969
+ children: [/* @__PURE__ */ jsxDEV("div", {
970
+ className: "flex flex-1 flex-col gap-1",
971
+ children: [/* @__PURE__ */ jsxDEV(Label, {
972
+ htmlFor: "ud-password",
973
+ children: t("New password")
974
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
975
+ "data-testid": "ud-password",
976
+ id: "ud-password",
977
+ onChange: onNewPasswordChange,
978
+ type: "password",
979
+ value: newPassword
980
+ }, void 0, false)]
981
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
982
+ "data-testid": "ud-set-password",
983
+ disabled: busy || newPassword === "",
984
+ onClick: onSetPassword,
985
+ size: "sm",
986
+ type: "button",
987
+ variant: "outline",
988
+ children: t("Set password")
989
+ }, void 0, false)]
990
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
991
+ className: "flex flex-wrap gap-2",
992
+ children: [/* @__PURE__ */ jsxDEV(Button, {
993
+ "data-testid": "ud-impersonate",
994
+ disabled: busy,
995
+ onClick: onImpersonate,
996
+ size: "sm",
997
+ type: "button",
998
+ variant: "outline",
999
+ children: t("Impersonate")
1000
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
1001
+ "data-testid": "ud-revoke-all",
1002
+ disabled: busy,
1003
+ onClick: onRevokeAll,
1004
+ size: "sm",
1005
+ type: "button",
1006
+ variant: "outline",
1007
+ children: t("Revoke all sessions")
1008
+ }, void 0, false), confirmDelete ? /* @__PURE__ */ jsxDEV(Fragment, {
1009
+ children: [/* @__PURE__ */ jsxDEV(Button, {
1010
+ "data-testid": "ud-delete-confirm",
1011
+ disabled: busy,
1012
+ onClick: onDelete,
1013
+ size: "sm",
1014
+ type: "button",
1015
+ variant: "destructive",
1016
+ children: t("Confirm delete")
1017
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
1018
+ "data-testid": "ud-delete-cancel",
1019
+ onClick: onCancelDelete,
1020
+ size: "sm",
1021
+ type: "button",
1022
+ variant: "ghost",
1023
+ children: t("Cancel")
1024
+ }, void 0, false)]
1025
+ }, void 0, true) : /* @__PURE__ */ jsxDEV(Button, {
1026
+ "data-testid": "ud-delete",
1027
+ disabled: busy,
1028
+ onClick: onConfirmDelete,
1029
+ size: "sm",
1030
+ type: "button",
1031
+ variant: "destructive",
1032
+ children: t("Delete user")
1033
+ }, void 0, false)]
1034
+ }, void 0, true), impersonationToken !== null && /* @__PURE__ */ jsxDEV("div", {
1035
+ className: "flex flex-col gap-1",
1036
+ "data-testid": "ud-impersonation",
1037
+ children: [/* @__PURE__ */ jsxDEV(Label, {
1038
+ htmlFor: "ud-token",
1039
+ children: t("Impersonation token")
1040
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1041
+ "data-testid": "ud-token",
1042
+ id: "ud-token",
1043
+ readOnly: true,
1044
+ value: impersonationToken
1045
+ }, void 0, false)]
1046
+ }, void 0, true)]
1047
+ }, void 0, true)]
1048
+ }, void 0, true), /* @__PURE__ */ jsxDEV(UserSessionsPanel, {
1049
+ busy,
1050
+ runAction,
1051
+ userId: user.id,
1052
+ version
1053
+ }, void 0, false), capabilities.accounts && /* @__PURE__ */ jsxDEV(UserAccountsPanel, {
1054
+ busy,
1055
+ runAction,
1056
+ userId: user.id,
1057
+ version
1058
+ }, void 0, false), (capabilities.twoFactor || capabilities.passkey) && /* @__PURE__ */ jsxDEV(UserSecurityPanel, {
1059
+ busy,
1060
+ capabilities,
1061
+ runAction,
1062
+ userId: user.id,
1063
+ version
1064
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
1065
+ className: "flex flex-col gap-1",
1066
+ "data-testid": "ud-fields",
1067
+ children: [/* @__PURE__ */ jsxDEV("h3", {
1068
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
1069
+ children: t("Fields")
1070
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dl", {
1071
+ className: "flex flex-col",
1072
+ children: rawFields.map(([key_0, value_0]) => /* @__PURE__ */ jsxDEV("div", {
1073
+ className: "flex flex-col border-t border-border py-1.5",
1074
+ children: [/* @__PURE__ */ jsxDEV("dt", {
1075
+ className: "text-xs font-semibold text-muted-foreground",
1076
+ children: key_0
1077
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dd", {
1078
+ className: "m-0 font-mono text-xs break-words",
1079
+ children: formatField(key_0, value_0)
1080
+ }, void 0, false)]
1081
+ }, key_0, true))
1082
+ }, void 0, false)]
1083
+ }, void 0, true)]
1084
+ }, void 0, true);
1085
+ };
1086
+
1087
+ const DEFAULT_PAGE_SIZE = 50;
1088
+ const UsersPanel = ({
1089
+ pageSize = DEFAULT_PAGE_SIZE
1090
+ } = {}) => {
1091
+ const client = useLunora();
1092
+ const t = useT();
1093
+ const [search, setSearch] = useState("");
1094
+ const [roleFilter, setRoleFilter] = useState("");
1095
+ const debouncedSearch = useDebounced(search);
1096
+ const [selectedUserId, setSelectedUserId] = useState(null);
1097
+ const [createOpen, setCreateOpen] = useState(false);
1098
+ const {
1099
+ capabilities
1100
+ } = useAuthCapabilities();
1101
+ const trimmedSearch = debouncedSearch.trim();
1102
+ const trimmedRole = roleFilter.trim();
1103
+ const usersQuery = useClientQuery(["lunora-auth-users", trimmedSearch, trimmedRole, pageSize], () => client.listAuthUsers({
1104
+ filterField: trimmedRole === "" ? void 0 : "role",
1105
+ filterValue: trimmedRole === "" ? void 0 : trimmedRole,
1106
+ limit: pageSize,
1107
+ search: trimmedSearch === "" ? void 0 : trimmedSearch
1108
+ }), {
1109
+ keepPreviousData: true
1110
+ });
1111
+ const users = usersQuery.data?.rows ?? null;
1112
+ const usersError = usersQuery.error;
1113
+ const reloadUsers = () => {
1114
+ usersQuery.refetch();
1115
+ };
1116
+ useAutoRefresh(() => {
1117
+ usersQuery.refetch();
1118
+ }, true);
1119
+ const selectedUser = selectedUserId === null ? null : users?.find((user) => user.id === selectedUserId) ?? null;
1120
+ return /* @__PURE__ */ jsxDEV("div", {
1121
+ className: "flex flex-col gap-4",
1122
+ "data-testid": "lunora-users",
1123
+ children: [/* @__PURE__ */ jsxDEV("div", {
1124
+ className: "flex flex-wrap items-center gap-2",
1125
+ children: [/* @__PURE__ */ jsxDEV(Input, {
1126
+ "aria-label": t("Search users"),
1127
+ className: "w-56",
1128
+ "data-testid": "us-search",
1129
+ onChange: (event) => {
1130
+ setSearch(event.target.value);
1131
+ },
1132
+ placeholder: t("Search by email or name…"),
1133
+ value: search
1134
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1135
+ "aria-label": t("Filter by role"),
1136
+ className: "w-40",
1137
+ "data-testid": "us-role-filter",
1138
+ onChange: (event_0) => {
1139
+ setRoleFilter(event_0.target.value);
1140
+ },
1141
+ placeholder: t("Filter by role"),
1142
+ value: roleFilter
1143
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
1144
+ "data-testid": "us-new",
1145
+ onClick: () => {
1146
+ setCreateOpen(true);
1147
+ },
1148
+ size: "sm",
1149
+ type: "button",
1150
+ children: t("New user")
1151
+ }, void 0, false)]
1152
+ }, void 0, true), usersError !== null && /* @__PURE__ */ jsxDEV("p", {
1153
+ className: "text-sm text-destructive",
1154
+ "data-testid": "us-users-error",
1155
+ role: "alert",
1156
+ children: usersError
1157
+ }, void 0, false), users !== null && users.length === 0 && /* @__PURE__ */ jsxDEV(EmptyState, {
1158
+ description: t("Users who sign up to your app will appear here."),
1159
+ icon: /* @__PURE__ */ jsxDEV("svg", {
1160
+ "aria-hidden": "true",
1161
+ fill: "none",
1162
+ stroke: "currentColor",
1163
+ strokeLinecap: "round",
1164
+ strokeLinejoin: "round",
1165
+ strokeWidth: 1.6,
1166
+ viewBox: "0 0 24 24",
1167
+ children: /* @__PURE__ */ jsxDEV("path", {
1168
+ d: "M16 20v-2a4 4 0 0 0-4-4H7a4 4 0 0 0-4 4v2M9.5 10a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Zm11.5 10v-2a4 4 0 0 0-3-3.85"
1169
+ }, void 0, false)
1170
+ }, void 0, false),
1171
+ testId: "us-empty",
1172
+ title: t("No users.")
1173
+ }, void 0, false), users !== null && users.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
1174
+ className: "overflow-hidden py-0",
1175
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
1176
+ className: "px-0",
1177
+ children: /* @__PURE__ */ jsxDEV(Table, {
1178
+ "data-testid": "us-table",
1179
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
1180
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
1181
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
1182
+ children: t("id")
1183
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1184
+ children: t("email")
1185
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1186
+ children: t("name")
1187
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1188
+ children: t("role")
1189
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1190
+ children: t("status")
1191
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1192
+ children: t("verified")
1193
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1194
+ children: t("created")
1195
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1196
+ "aria-label": t("Actions")
1197
+ }, void 0, false)]
1198
+ }, void 0, true)
1199
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
1200
+ children: users.map((user_0) => /* @__PURE__ */ jsxDEV(TableRow, {
1201
+ "data-testid": `us-row-${user_0.id}`,
1202
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
1203
+ className: "font-mono text-xs",
1204
+ children: user_0.id
1205
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1206
+ children: user_0.email ?? ""
1207
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1208
+ children: user_0.name ?? ""
1209
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1210
+ children: typeof user_0.role === "string" && user_0.role !== "" ? /* @__PURE__ */ jsxDEV(Badge, {
1211
+ variant: "secondary",
1212
+ children: user_0.role
1213
+ }, void 0, false) : ""
1214
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1215
+ children: user_0.banned === true ? /* @__PURE__ */ jsxDEV(Badge, {
1216
+ variant: "destructive",
1217
+ children: t("Banned")
1218
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
1219
+ variant: "success",
1220
+ children: t("Active")
1221
+ }, void 0, false)
1222
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1223
+ children: user_0.emailVerified === true ? /* @__PURE__ */ jsxDEV(Badge, {
1224
+ variant: "success",
1225
+ children: t("yes")
1226
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
1227
+ variant: "outline",
1228
+ children: t("no")
1229
+ }, void 0, false)
1230
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1231
+ className: "text-muted-foreground tabular-nums",
1232
+ children: formatTimestamp(user_0.createdAt)
1233
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1234
+ children: /* @__PURE__ */ jsxDEV(Button, {
1235
+ "data-testid": `us-manage-${user_0.id}`,
1236
+ onClick: () => {
1237
+ setSelectedUserId(user_0.id);
1238
+ },
1239
+ size: "xs",
1240
+ type: "button",
1241
+ variant: "ghost",
1242
+ children: t("Manage")
1243
+ }, void 0, false)
1244
+ }, void 0, false)]
1245
+ }, user_0.id, true))
1246
+ }, void 0, false)]
1247
+ }, void 0, true)
1248
+ }, void 0, false)
1249
+ }, void 0, false), selectedUser !== null && /* @__PURE__ */ jsxDEV(UserDetailDrawer, {
1250
+ capabilities,
1251
+ onChanged: reloadUsers,
1252
+ onClose: () => {
1253
+ setSelectedUserId(null);
1254
+ },
1255
+ user: selectedUser
1256
+ }, void 0, false), createOpen && /* @__PURE__ */ jsxDEV(UserCreateDialog, {
1257
+ onClose: () => {
1258
+ setCreateOpen(false);
1259
+ },
1260
+ onCreated: reloadUsers
1261
+ }, void 0, false)]
1262
+ }, void 0, true);
1263
+ };
1264
+
1265
+ export { UsersPanel };