@lunora/studio 1.0.0-alpha.4 → 1.0.0-alpha.41

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 (187) hide show
  1. package/LICENSE.md +6 -0
  2. package/__assets__/package-og.svg +1 -1
  3. package/dist/index.d.ts +33 -18
  4. package/dist/index.js +29 -29
  5. package/dist/mount.d.ts +1 -1
  6. package/dist/mount.js +3 -2
  7. package/dist/{packem_shared/ApiTab-W3no0KOj.js → packem_chunks/ApiTab.js} +5 -5
  8. package/dist/{packem_shared/AuditPanel-Bq4o_IqT.js → packem_chunks/AuditPanel.js} +29 -41
  9. package/dist/{packem_shared/ExportImportPanel-dxY56TDF.js → packem_chunks/ExportImportPanel.js} +16 -11
  10. package/dist/{packem_shared/FileBrowser-Dhy4zES8.js → packem_chunks/FileBrowser.js} +15 -15
  11. package/dist/{packem_shared/FunctionRunner--fQJRPAD.js → packem_chunks/FunctionRunner.js} +10 -10
  12. package/dist/{packem_shared/FunctionStatsPanel-BjRUA_G3.js → packem_chunks/FunctionStatsPanel.js} +153 -208
  13. package/dist/{packem_shared/HealthPanel-PxclMWmA.js → packem_chunks/HealthPanel.js} +37 -29
  14. package/dist/{packem_shared/InsightsPanel-CWS_C-xW.js → packem_chunks/InsightsPanel.js} +108 -69
  15. package/dist/{packem_shared/LogsPanel-CTW8CFcM.js → packem_chunks/LogsPanel.js} +46 -58
  16. package/dist/{packem_shared/MailPanel-BwkvfIHF.js → packem_chunks/MailPanel.js} +45 -139
  17. package/dist/{packem_shared/MetricsPanel-BLuOhZQ4.js → packem_chunks/MetricsPanel.js} +41 -322
  18. package/dist/{packem_shared/MigrationsPanel-DT3lnwHF.js → packem_chunks/MigrationsPanel.js} +44 -51
  19. package/dist/{packem_shared/PitrPanel-CdErL7EJ.js → packem_chunks/PitrPanel.js} +9 -9
  20. package/dist/{packem_shared/SchemaViewer-LJDcmNIO.js → packem_chunks/SchemaViewer.js} +17 -16
  21. package/dist/{packem_shared/SecurityAdvisorPanel-C_ETsPih.js → packem_chunks/SecurityAdvisorPanel.js} +47 -31
  22. package/dist/packem_chunks/SettingsPanel.js +391 -0
  23. package/dist/{packem_shared/sql-editor-panel-BFRpzj6r.js → packem_chunks/SqlEditorPanel.js} +158 -387
  24. package/dist/{packem_shared/TableEditor-ChfUOZec.js → packem_chunks/TableEditor.js} +10 -68
  25. package/dist/packem_chunks/analytics-panel.js +261 -0
  26. package/dist/packem_chunks/auth-config-panel.js +365 -0
  27. package/dist/packem_chunks/auth-sessions-panel.js +175 -0
  28. package/dist/packem_chunks/containers-panel.js +247 -0
  29. package/dist/packem_chunks/dashboards-panel.js +780 -0
  30. package/dist/packem_chunks/fanout-panel.js +482 -0
  31. package/dist/packem_chunks/flags-panel.js +176 -0
  32. package/dist/packem_chunks/kv-browser.js +1896 -0
  33. package/dist/packem_chunks/log-drains-panel.js +273 -0
  34. package/dist/packem_chunks/organizations-panel.js +3178 -0
  35. package/dist/packem_chunks/payments-panel.js +186 -0
  36. package/dist/packem_chunks/permissions-panel.js +805 -0
  37. package/dist/packem_chunks/queues-panel.js +1075 -0
  38. package/dist/packem_chunks/rls-panel.js +315 -0
  39. package/dist/packem_chunks/schedule-panel.js +831 -0
  40. package/dist/packem_chunks/sparkline.js +79 -0
  41. package/dist/packem_chunks/storage-rules-panel.js +140 -0
  42. package/dist/packem_chunks/subscriptions-panel.js +238 -0
  43. package/dist/packem_chunks/users-panel.js +1731 -0
  44. package/dist/packem_chunks/vector-browser.js +281 -0
  45. package/dist/packem_chunks/workflows-panel.js +562 -0
  46. package/dist/packem_shared/{ADMIN_FUNCTIONS-DmBqMZ-z.js → ADMIN_FUNCTIONS-BHHJi3Gb.js} +7 -0
  47. package/dist/packem_shared/{ApiDocsPanel-C5-yJ1p7.js → ApiDocsPanel-CBma-lnp.js} +2 -2
  48. package/dist/packem_shared/{ApiReferencePanel-1vubqG5s.js → ApiReferencePanel-CQM3pPN7.js} +2 -1
  49. package/dist/packem_shared/{CommandPalette-BtgkBzZI.js → CommandPalette-X2tkbyHk.js} +1 -1
  50. package/dist/packem_shared/{DataBrowser-CtBe1So9.js → DataBrowser-D2ywrdId.js} +198 -247
  51. package/dist/packem_shared/{GlobalDataBrowser-BTEmGrph.js → GlobalDataBrowser-BkTPLzAY.js} +37 -66
  52. package/dist/packem_shared/HomePanel-D1Q9LZgK.js +14 -0
  53. package/dist/packem_shared/{OpenRpcReferencePanel-vbcYbv3V.js → OpenRpcReferencePanel-Dno-hfDb.js} +2 -1
  54. package/dist/packem_shared/{ScheduledJobs-CabfKbyM.js → ScheduledJobs-Ctw4jYtU.js} +163 -60
  55. package/dist/packem_shared/Studio-lJhzDAze.js +16 -0
  56. package/dist/packem_shared/{StudioApp-CHOZA-z-.js → StudioApp-DiMkupvZ.js} +276 -11
  57. package/dist/packem_shared/{advisor-view-CGcfMiPq.js → advisor-view-BX8OhG0w.js} +6 -6
  58. package/dist/packem_shared/alert-CdAET2K_.js +68 -0
  59. package/dist/packem_shared/{app.d-CCmwDEVs.d.ts → app.d-CNLRTrWw.d.ts} +1 -1
  60. package/dist/packem_shared/{bar-chart-CzJAgqkp.js → bar-chart-DSwcWIRy.js} +5 -4
  61. package/dist/packem_shared/browser-storage-BTrX4y3B.js +215 -0
  62. package/dist/packem_shared/{cf-links-2cktDedA.js → cf-links-BZfRdxSE.js} +1 -1
  63. package/dist/packem_shared/{data-grid-B5CaV3wS.js → data-grid-CdXztApG.js} +1 -1
  64. package/dist/packem_shared/data-view-params-Cd6yRVbv.js +96 -0
  65. package/dist/packem_shared/error-alert-CXjqyGw9.js +114 -0
  66. package/dist/packem_shared/{grid-features-CzUfqgsM.js → grid-features-BF-KBDFz.js} +131 -163
  67. package/dist/packem_shared/home-panel-TFcRf9Ui.js +1889 -0
  68. package/dist/packem_shared/{internal-rXJEAhXS.js → internal-CYcbqMjX.js} +44 -3
  69. package/dist/packem_shared/modal-shell-hyaJvIJ6.js +100 -0
  70. package/dist/packem_shared/{reference-view-B4E49Lip.js → reference-view-DUiJcILV.js} +6 -45
  71. package/dist/packem_shared/scroll-area-DLhcy-ml.js +93 -0
  72. package/dist/packem_shared/select-UkNYCT3s.js +273 -0
  73. package/dist/packem_shared/skeleton-CGhL0p20.js +45 -0
  74. package/dist/packem_shared/{sparkline-10dG-_f0.js → sparkline-BnA1kC9X.js} +1 -1
  75. package/dist/packem_shared/studio-Dh9UlaF_.js +4015 -0
  76. package/dist/packem_shared/{table-_RzNvy3R.js → table-DsCa9Qp9.js} +1 -1
  77. package/dist/packem_shared/{table-list-sidebar-Bg7uzbvC.js → table-list-sidebar-UVIXQJdU.js} +1 -1
  78. package/dist/packem_shared/use-admin-query-CfHYWx5n.js +106 -0
  79. package/dist/packem_shared/use-async-submit-DJQiPc-_.js +91 -0
  80. package/dist/standalone/chunk-25AYY4H7.js +2 -0
  81. package/dist/standalone/chunk-2ANAF4ZM.js +1 -0
  82. package/dist/standalone/chunk-2K47A3P6.js +1 -0
  83. package/dist/standalone/chunk-2NGUNNGW.js +1 -0
  84. package/dist/standalone/chunk-3CJW6NWG.js +4 -0
  85. package/dist/standalone/chunk-3OA7PECS.js +6 -0
  86. package/dist/standalone/chunk-3OIHOXVV.js +1 -0
  87. package/dist/standalone/chunk-447TAUFD.js +1 -0
  88. package/dist/standalone/chunk-4QHKBC77.js +1 -0
  89. package/dist/standalone/chunk-5C4TSNE6.js +1 -0
  90. package/dist/standalone/chunk-5OIBXYZM.js +1 -0
  91. package/dist/standalone/chunk-6HSHEMZV.js +76 -0
  92. package/dist/standalone/chunk-6JIZ34MB.js +3 -0
  93. package/dist/standalone/chunk-6VO23MMW.js +4 -0
  94. package/dist/standalone/chunk-7MVSQS7B.js +1 -0
  95. package/dist/standalone/chunk-7TJJXVSE.js +1 -0
  96. package/dist/standalone/chunk-7YXOPTWI.js +1 -0
  97. package/dist/standalone/chunk-AHILM3ZP.js +1 -0
  98. package/dist/standalone/chunk-BGXOXASQ.js +1 -0
  99. package/dist/standalone/chunk-BJGBHGK3.js +1 -0
  100. package/dist/standalone/chunk-BOXSWNXZ.js +1 -0
  101. package/dist/standalone/chunk-BX5MKYOC.js +1 -0
  102. package/dist/standalone/chunk-CKSHCYGC.js +2 -0
  103. package/dist/standalone/chunk-DWDILV2E.js +1 -0
  104. package/dist/standalone/chunk-E75ANNWX.js +19 -0
  105. package/dist/standalone/chunk-EQZQOTJY.js +1 -0
  106. package/dist/standalone/chunk-GTLEWM5Y.js +1 -0
  107. package/dist/standalone/chunk-GTM65MVX.js +1 -0
  108. package/dist/standalone/chunk-GUI5GFFI.js +1 -0
  109. package/dist/standalone/chunk-HN6KJXYQ.js +1 -0
  110. package/dist/standalone/chunk-HV7G6DFP.js +5 -0
  111. package/dist/standalone/chunk-HYDJNCGW.js +1 -0
  112. package/dist/standalone/chunk-HZK5RQHG.js +1 -0
  113. package/dist/standalone/chunk-IN2SYVJB.js +1 -0
  114. package/dist/standalone/chunk-IOANPSJN.js +1 -0
  115. package/dist/standalone/chunk-ISDZPW3V.js +1 -0
  116. package/dist/standalone/chunk-IXDH4GL5.js +1 -0
  117. package/dist/standalone/chunk-J6J54MBP.js +1 -0
  118. package/dist/standalone/chunk-J73VHFCL.js +1 -0
  119. package/dist/standalone/chunk-JHKMUTIF.js +13 -0
  120. package/dist/standalone/chunk-JPRH6DPK.js +1 -0
  121. package/dist/standalone/chunk-JSEXCW5Q.js +1 -0
  122. package/dist/standalone/chunk-KA5YB3VP.js +1 -0
  123. package/dist/standalone/chunk-KBB75WNT.js +1 -0
  124. package/dist/standalone/chunk-KEGAWN6Y.js +1 -0
  125. package/dist/standalone/chunk-KJJ3WM6H.js +4 -0
  126. package/dist/standalone/chunk-KQV4NGH3.js +1 -0
  127. package/dist/standalone/chunk-KSKXW5PX.js +1 -0
  128. package/dist/standalone/chunk-KUH4P5F5.js +1 -0
  129. package/dist/standalone/chunk-KYJPPVGB.js +1 -0
  130. package/dist/standalone/chunk-KZ6INM5M.js +1 -0
  131. package/dist/standalone/chunk-L2TJVSDQ.js +1 -0
  132. package/dist/standalone/chunk-L7SK4ZZD.js +1 -0
  133. package/dist/standalone/chunk-LAK5VSPI.js +1 -0
  134. package/dist/standalone/chunk-LBN7LPVK.js +1 -0
  135. package/dist/standalone/chunk-LNZIB2MD.js +1 -0
  136. package/dist/standalone/chunk-MJWVMKQ4.js +6 -0
  137. package/dist/standalone/chunk-MLZYX5CQ.js +1 -0
  138. package/dist/standalone/chunk-N2X2OO4V.js +1 -0
  139. package/dist/standalone/chunk-NGKITPQP.js +13 -0
  140. package/dist/standalone/chunk-O3NAGRTR.js +1 -0
  141. package/dist/standalone/chunk-OZACQNKG.js +1 -0
  142. package/dist/standalone/chunk-PNDNXS5Z.js +1 -0
  143. package/dist/standalone/chunk-Q7DMUTUE.js +1 -0
  144. package/dist/standalone/chunk-QAFAJBAW.js +1 -0
  145. package/dist/standalone/chunk-QBAT52GB.js +1 -0
  146. package/dist/standalone/chunk-RHZ4M2NZ.js +1 -0
  147. package/dist/standalone/chunk-RRCPZMC2.js +22 -0
  148. package/dist/standalone/chunk-SEU5V7I6.js +1 -0
  149. package/dist/standalone/chunk-TAD43CG5.js +1 -0
  150. package/dist/standalone/chunk-TBMYIZIO.js +1 -0
  151. package/dist/standalone/chunk-TDZ44E5I.js +4 -0
  152. package/dist/standalone/chunk-THNBTMUF.js +1 -0
  153. package/dist/standalone/chunk-TIQISBGK.js +1 -0
  154. package/dist/standalone/chunk-TMYVNQ66.js +1 -0
  155. package/dist/standalone/chunk-TQ36RWOP.js +1 -0
  156. package/dist/standalone/chunk-UGUEC6BC.js +1 -0
  157. package/dist/standalone/chunk-UJB2LEI4.js +4 -0
  158. package/dist/standalone/chunk-UK64ZSUW.js +1 -0
  159. package/dist/standalone/chunk-UKDJ4H7I.js +1 -0
  160. package/dist/standalone/chunk-VLXV72QE.js +1 -0
  161. package/dist/standalone/chunk-VON7JUPG.js +1 -0
  162. package/dist/standalone/chunk-W3JK4YWR.js +1 -0
  163. package/dist/standalone/chunk-W3SHEIAL.js +3 -0
  164. package/dist/standalone/chunk-WI7GWFEG.js +1 -0
  165. package/dist/standalone/chunk-WIHXMNUY.js +1 -0
  166. package/dist/standalone/chunk-WLDVXVI2.js +1 -0
  167. package/dist/standalone/chunk-XLXNLJ4N.js +1 -0
  168. package/dist/standalone/chunk-XNJNSCLM.js +1 -0
  169. package/dist/standalone/chunk-YAECF5LW.js +1 -0
  170. package/dist/standalone/chunk-YBGC4PPD.js +1 -0
  171. package/dist/standalone/chunk-YJAPWSDC.js +4 -0
  172. package/dist/standalone/chunk-ZEJB6DXU.js +8 -0
  173. package/dist/standalone/chunk-ZFNBPAIZ.js +1 -0
  174. package/dist/standalone/chunk-ZHVTQ37P.js +1 -0
  175. package/dist/standalone/chunk-ZIGWVHCS.js +1 -0
  176. package/dist/standalone/chunk-ZPP2KOR4.js +1 -0
  177. package/dist/standalone/chunk-ZPUO7FNI.js +1 -0
  178. package/dist/standalone/studio.js +104 -246
  179. package/dist/styles.css +2 -2
  180. package/package.json +15 -13
  181. package/dist/packem_shared/HomePanel-Cw16stjq.js +0 -1273
  182. package/dist/packem_shared/SettingsPanel-C0uLRf5P.js +0 -176
  183. package/dist/packem_shared/SqlEditorPanel-CguV7otm.js +0 -13
  184. package/dist/packem_shared/Studio-DFWAlcuf.js +0 -33
  185. package/dist/packem_shared/studio-Bj8psK1c.js +0 -10303
  186. package/dist/packem_shared/use-live-admin-Dq6g3daN.js +0 -73
  187. package/dist/packem_shared/use-live-shard-seed-Cuk3dnH0.js +0 -76
@@ -0,0 +1,1731 @@
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-CfHYWx5n.js';
10
+ import { c } from 'react/compiler-runtime';
11
+ import { a as useAuthConfig, u as useAsyncSubmit } from '../packem_shared/use-async-submit-DJQiPc-_.js';
12
+ import { useAutoRefresh } from '../packem_shared/DEFAULT_AUTO_REFRESH_MS-Vxwaxx51.js';
13
+ import useDebounced from '../packem_shared/useDebounced-Dxncpg6z.js';
14
+ import { useT } from '../packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js';
15
+ import { i as formatTimestamp, h as formatCell, f as fireAndForget, e as errorMessage } from '../packem_shared/internal-CYcbqMjX.js';
16
+ import { C as Checkbox } from '../packem_shared/checkbox-UNkzAxl-.js';
17
+ import { L as Label } from '../packem_shared/label-D8ykjn5J.js';
18
+ import { M as ModalShell } from '../packem_shared/modal-shell-hyaJvIJ6.js';
19
+ import { jsxDEV, Fragment } from 'react/jsx-dev-runtime';
20
+
21
+ const useAuthCapabilities = () => {
22
+ const $ = c(3);
23
+ const {
24
+ config,
25
+ ready
26
+ } = useAuthConfig();
27
+ let t0;
28
+ if ($[0] !== config.capabilities || $[1] !== ready) {
29
+ t0 = {
30
+ capabilities: config.capabilities,
31
+ ready
32
+ };
33
+ $[0] = config.capabilities;
34
+ $[1] = ready;
35
+ $[2] = t0;
36
+ } else {
37
+ t0 = $[2];
38
+ }
39
+ return t0;
40
+ };
41
+
42
+ const INPUT_TYPE_BY_FIELD = {
43
+ boolean: "checkbox",
44
+ date: "datetime-local",
45
+ number: "number",
46
+ string: "text"
47
+ };
48
+ const isFieldFilled = (field, value) => {
49
+ if (field.type === "boolean") {
50
+ return true;
51
+ }
52
+ if (typeof value !== "string" || value.trim() === "") {
53
+ return false;
54
+ }
55
+ return field.type !== "number" || !Number.isNaN(Number(value.trim()));
56
+ };
57
+ const coerceFieldValue = (field, raw) => {
58
+ if (field.type === "boolean") {
59
+ if (raw === true) {
60
+ return {
61
+ value: true
62
+ };
63
+ }
64
+ return field.required ? {
65
+ value: false
66
+ } : void 0;
67
+ }
68
+ const text = typeof raw === "string" ? raw.trim() : "";
69
+ if (text === "") {
70
+ return void 0;
71
+ }
72
+ if (field.type === "number") {
73
+ const numeric = Number(text);
74
+ return Number.isNaN(numeric) ? void 0 : {
75
+ value: numeric
76
+ };
77
+ }
78
+ return {
79
+ value: text
80
+ };
81
+ };
82
+ const UserCreateDialog = (t0) => {
83
+ const $ = c(105);
84
+ const {
85
+ onClose,
86
+ onCreated
87
+ } = t0;
88
+ const client = useLunora();
89
+ const t = useT();
90
+ const {
91
+ config
92
+ } = useAuthConfig();
93
+ const {
94
+ busy,
95
+ error,
96
+ run
97
+ } = useAsyncSubmit();
98
+ const [email, setEmail] = useState("");
99
+ const [name, setName] = useState("");
100
+ const [password, setPassword] = useState("");
101
+ const [role, setRole] = useState("");
102
+ let t1;
103
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
104
+ t1 = {};
105
+ $[0] = t1;
106
+ } else {
107
+ t1 = $[0];
108
+ }
109
+ const [fieldValues, setFieldValues] = useState(t1);
110
+ let t2;
111
+ if ($[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
112
+ t2 = (event) => {
113
+ setEmail(event.target.value);
114
+ };
115
+ $[1] = t2;
116
+ } else {
117
+ t2 = $[1];
118
+ }
119
+ const onEmailChange = t2;
120
+ let t3;
121
+ if ($[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
122
+ t3 = (event_0) => {
123
+ setName(event_0.target.value);
124
+ };
125
+ $[2] = t3;
126
+ } else {
127
+ t3 = $[2];
128
+ }
129
+ const onNameChange = t3;
130
+ let t4;
131
+ if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
132
+ t4 = (event_1) => {
133
+ setPassword(event_1.target.value);
134
+ };
135
+ $[3] = t4;
136
+ } else {
137
+ t4 = $[3];
138
+ }
139
+ const onPasswordChange = t4;
140
+ let t5;
141
+ if ($[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
142
+ t5 = (event_2) => {
143
+ setRole(event_2.target.value);
144
+ };
145
+ $[4] = t5;
146
+ } else {
147
+ t5 = $[4];
148
+ }
149
+ const onRoleChange = t5;
150
+ let t6;
151
+ if ($[5] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
152
+ t6 = (fieldName, value) => {
153
+ setFieldValues((previous) => ({
154
+ ...previous,
155
+ [fieldName]: value
156
+ }));
157
+ };
158
+ $[5] = t6;
159
+ } else {
160
+ t6 = $[5];
161
+ }
162
+ const setFieldValue = t6;
163
+ let t7;
164
+ if ($[6] !== fieldValues) {
165
+ t7 = (field) => fieldValues[field.name] ?? (field.type === "boolean" ? false : "");
166
+ $[6] = fieldValues;
167
+ $[7] = t7;
168
+ } else {
169
+ t7 = $[7];
170
+ }
171
+ const fieldValue = t7;
172
+ let t8;
173
+ if ($[8] !== config.userFields || $[9] !== fieldValue) {
174
+ let t92;
175
+ if ($[11] !== fieldValue) {
176
+ t92 = (field_0) => !field_0.required || isFieldFilled(field_0, fieldValue(field_0));
177
+ $[11] = fieldValue;
178
+ $[12] = t92;
179
+ } else {
180
+ t92 = $[12];
181
+ }
182
+ t8 = config.userFields.every(t92);
183
+ $[8] = config.userFields;
184
+ $[9] = fieldValue;
185
+ $[10] = t8;
186
+ } else {
187
+ t8 = $[10];
188
+ }
189
+ const requiredFieldsFilled = t8;
190
+ let t9;
191
+ if ($[13] !== busy || $[14] !== email || $[15] !== name || $[16] !== requiredFieldsFilled) {
192
+ t9 = !busy && email.trim() !== "" && name.trim() !== "" && requiredFieldsFilled;
193
+ $[13] = busy;
194
+ $[14] = email;
195
+ $[15] = name;
196
+ $[16] = requiredFieldsFilled;
197
+ $[17] = t9;
198
+ } else {
199
+ t9 = $[17];
200
+ }
201
+ const canSubmit = t9;
202
+ let t10;
203
+ if ($[18] !== config.userFields || $[19] !== fieldValue) {
204
+ t10 = () => {
205
+ const data = {};
206
+ for (const field_1 of config.userFields) {
207
+ const coerced = coerceFieldValue(field_1, fieldValue(field_1));
208
+ if (coerced !== void 0) {
209
+ data[field_1.name] = coerced.value;
210
+ }
211
+ }
212
+ return Object.keys(data).length === 0 ? void 0 : data;
213
+ };
214
+ $[18] = config.userFields;
215
+ $[19] = fieldValue;
216
+ $[20] = t10;
217
+ } else {
218
+ t10 = $[20];
219
+ }
220
+ const buildData = t10;
221
+ let t11;
222
+ if ($[21] !== buildData || $[22] !== client || $[23] !== email || $[24] !== name || $[25] !== onClose || $[26] !== onCreated || $[27] !== password || $[28] !== role || $[29] !== run) {
223
+ t11 = () => {
224
+ run(async () => {
225
+ await client.createAuthUser({
226
+ data: buildData(),
227
+ email: email.trim(),
228
+ name: name.trim(),
229
+ password: password === "" ? void 0 : password,
230
+ role: role.trim() === "" ? void 0 : role.trim()
231
+ });
232
+ onCreated();
233
+ onClose();
234
+ });
235
+ };
236
+ $[21] = buildData;
237
+ $[22] = client;
238
+ $[23] = email;
239
+ $[24] = name;
240
+ $[25] = onClose;
241
+ $[26] = onCreated;
242
+ $[27] = password;
243
+ $[28] = role;
244
+ $[29] = run;
245
+ $[30] = t11;
246
+ } else {
247
+ t11 = $[30];
248
+ }
249
+ const onSubmit = t11;
250
+ let t12;
251
+ if ($[31] !== t) {
252
+ t12 = t("Create user");
253
+ $[31] = t;
254
+ $[32] = t12;
255
+ } else {
256
+ t12 = $[32];
257
+ }
258
+ let t13;
259
+ if ($[33] !== t) {
260
+ t13 = t("Create user");
261
+ $[33] = t;
262
+ $[34] = t13;
263
+ } else {
264
+ t13 = $[34];
265
+ }
266
+ let t14;
267
+ if ($[35] !== t13) {
268
+ t14 = /* @__PURE__ */ jsxDEV("h2", {
269
+ className: "text-sm font-semibold text-foreground",
270
+ children: t13
271
+ }, void 0, false);
272
+ $[35] = t13;
273
+ $[36] = t14;
274
+ } else {
275
+ t14 = $[36];
276
+ }
277
+ let t15;
278
+ if ($[37] !== t) {
279
+ t15 = t("email");
280
+ $[37] = t;
281
+ $[38] = t15;
282
+ } else {
283
+ t15 = $[38];
284
+ }
285
+ let t16;
286
+ if ($[39] !== t15) {
287
+ t16 = /* @__PURE__ */ jsxDEV(Label, {
288
+ htmlFor: "uc-email",
289
+ children: t15
290
+ }, void 0, false);
291
+ $[39] = t15;
292
+ $[40] = t16;
293
+ } else {
294
+ t16 = $[40];
295
+ }
296
+ let t17;
297
+ if ($[41] !== email) {
298
+ t17 = /* @__PURE__ */ jsxDEV(Input, {
299
+ "data-testid": "uc-email",
300
+ id: "uc-email",
301
+ onChange: onEmailChange,
302
+ type: "email",
303
+ value: email
304
+ }, void 0, false);
305
+ $[41] = email;
306
+ $[42] = t17;
307
+ } else {
308
+ t17 = $[42];
309
+ }
310
+ let t18;
311
+ if ($[43] !== t16 || $[44] !== t17) {
312
+ t18 = /* @__PURE__ */ jsxDEV("div", {
313
+ className: "flex flex-col gap-1",
314
+ children: [t16, t17]
315
+ }, void 0, true);
316
+ $[43] = t16;
317
+ $[44] = t17;
318
+ $[45] = t18;
319
+ } else {
320
+ t18 = $[45];
321
+ }
322
+ let t19;
323
+ if ($[46] !== t) {
324
+ t19 = t("name");
325
+ $[46] = t;
326
+ $[47] = t19;
327
+ } else {
328
+ t19 = $[47];
329
+ }
330
+ let t20;
331
+ if ($[48] !== t19) {
332
+ t20 = /* @__PURE__ */ jsxDEV(Label, {
333
+ htmlFor: "uc-name",
334
+ children: t19
335
+ }, void 0, false);
336
+ $[48] = t19;
337
+ $[49] = t20;
338
+ } else {
339
+ t20 = $[49];
340
+ }
341
+ let t21;
342
+ if ($[50] !== name) {
343
+ t21 = /* @__PURE__ */ jsxDEV(Input, {
344
+ "data-testid": "uc-name",
345
+ id: "uc-name",
346
+ onChange: onNameChange,
347
+ value: name
348
+ }, void 0, false);
349
+ $[50] = name;
350
+ $[51] = t21;
351
+ } else {
352
+ t21 = $[51];
353
+ }
354
+ let t22;
355
+ if ($[52] !== t20 || $[53] !== t21) {
356
+ t22 = /* @__PURE__ */ jsxDEV("div", {
357
+ className: "flex flex-col gap-1",
358
+ children: [t20, t21]
359
+ }, void 0, true);
360
+ $[52] = t20;
361
+ $[53] = t21;
362
+ $[54] = t22;
363
+ } else {
364
+ t22 = $[54];
365
+ }
366
+ let t23;
367
+ if ($[55] !== t) {
368
+ t23 = t("Password (optional)");
369
+ $[55] = t;
370
+ $[56] = t23;
371
+ } else {
372
+ t23 = $[56];
373
+ }
374
+ let t24;
375
+ if ($[57] !== t23) {
376
+ t24 = /* @__PURE__ */ jsxDEV(Label, {
377
+ htmlFor: "uc-password",
378
+ children: t23
379
+ }, void 0, false);
380
+ $[57] = t23;
381
+ $[58] = t24;
382
+ } else {
383
+ t24 = $[58];
384
+ }
385
+ let t25;
386
+ if ($[59] !== password) {
387
+ t25 = /* @__PURE__ */ jsxDEV(Input, {
388
+ "data-testid": "uc-password",
389
+ id: "uc-password",
390
+ onChange: onPasswordChange,
391
+ type: "password",
392
+ value: password
393
+ }, void 0, false);
394
+ $[59] = password;
395
+ $[60] = t25;
396
+ } else {
397
+ t25 = $[60];
398
+ }
399
+ let t26;
400
+ if ($[61] !== t24 || $[62] !== t25) {
401
+ t26 = /* @__PURE__ */ jsxDEV("div", {
402
+ className: "flex flex-col gap-1",
403
+ children: [t24, t25]
404
+ }, void 0, true);
405
+ $[61] = t24;
406
+ $[62] = t25;
407
+ $[63] = t26;
408
+ } else {
409
+ t26 = $[63];
410
+ }
411
+ let t27;
412
+ if ($[64] !== t) {
413
+ t27 = t("Role (optional)");
414
+ $[64] = t;
415
+ $[65] = t27;
416
+ } else {
417
+ t27 = $[65];
418
+ }
419
+ let t28;
420
+ if ($[66] !== t27) {
421
+ t28 = /* @__PURE__ */ jsxDEV(Label, {
422
+ htmlFor: "uc-role",
423
+ children: t27
424
+ }, void 0, false);
425
+ $[66] = t27;
426
+ $[67] = t28;
427
+ } else {
428
+ t28 = $[67];
429
+ }
430
+ let t29;
431
+ if ($[68] !== role) {
432
+ t29 = /* @__PURE__ */ jsxDEV(Input, {
433
+ "data-testid": "uc-role",
434
+ id: "uc-role",
435
+ onChange: onRoleChange,
436
+ value: role
437
+ }, void 0, false);
438
+ $[68] = role;
439
+ $[69] = t29;
440
+ } else {
441
+ t29 = $[69];
442
+ }
443
+ let t30;
444
+ if ($[70] !== t28 || $[71] !== t29) {
445
+ t30 = /* @__PURE__ */ jsxDEV("div", {
446
+ className: "flex flex-col gap-1",
447
+ children: [t28, t29]
448
+ }, void 0, true);
449
+ $[70] = t28;
450
+ $[71] = t29;
451
+ $[72] = t30;
452
+ } else {
453
+ t30 = $[72];
454
+ }
455
+ let t31;
456
+ if ($[73] !== config.userFields || $[74] !== fieldValue || $[75] !== t) {
457
+ t31 = config.userFields.length > 0 && /* @__PURE__ */ jsxDEV("div", {
458
+ className: "flex flex-col gap-3 border-t border-border pt-3",
459
+ "data-testid": "uc-plugin-fields",
460
+ children: [/* @__PURE__ */ jsxDEV("span", {
461
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
462
+ children: t("Plugin fields")
463
+ }, void 0, false), config.userFields.map((field_2) => {
464
+ const inputId = `uc-field-${field_2.name}`;
465
+ const suffix = field_2.required ? "" : ` (${t("optional")})`;
466
+ if (field_2.type === "boolean") {
467
+ const checked = fieldValue(field_2) === true;
468
+ return /* @__PURE__ */ jsxDEV("label", {
469
+ className: "flex items-center gap-2",
470
+ htmlFor: inputId,
471
+ children: [/* @__PURE__ */ jsxDEV(Checkbox, {
472
+ checked,
473
+ "data-testid": inputId,
474
+ id: inputId,
475
+ onCheckedChange: (next) => {
476
+ setFieldValue(field_2.name, next);
477
+ }
478
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
479
+ className: "text-sm",
480
+ children: [field_2.name, suffix]
481
+ }, void 0, true)]
482
+ }, field_2.name, true);
483
+ }
484
+ const value_0 = fieldValue(field_2);
485
+ return /* @__PURE__ */ jsxDEV("div", {
486
+ className: "flex flex-col gap-1",
487
+ children: [/* @__PURE__ */ jsxDEV(Label, {
488
+ htmlFor: inputId,
489
+ children: [field_2.name, suffix]
490
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Input, {
491
+ "data-testid": inputId,
492
+ id: inputId,
493
+ onChange: (event_3) => {
494
+ setFieldValue(field_2.name, event_3.target.value);
495
+ },
496
+ type: INPUT_TYPE_BY_FIELD[field_2.type],
497
+ value: typeof value_0 === "string" ? value_0 : ""
498
+ }, void 0, false)]
499
+ }, field_2.name, true);
500
+ })]
501
+ }, void 0, true);
502
+ $[73] = config.userFields;
503
+ $[74] = fieldValue;
504
+ $[75] = t;
505
+ $[76] = t31;
506
+ } else {
507
+ t31 = $[76];
508
+ }
509
+ let t32;
510
+ if ($[77] !== error) {
511
+ t32 = error !== null && /* @__PURE__ */ jsxDEV("p", {
512
+ className: "text-sm text-destructive",
513
+ "data-testid": "uc-error",
514
+ role: "alert",
515
+ children: error
516
+ }, void 0, false);
517
+ $[77] = error;
518
+ $[78] = t32;
519
+ } else {
520
+ t32 = $[78];
521
+ }
522
+ let t33;
523
+ if ($[79] !== t) {
524
+ t33 = t("Cancel");
525
+ $[79] = t;
526
+ $[80] = t33;
527
+ } else {
528
+ t33 = $[80];
529
+ }
530
+ let t34;
531
+ if ($[81] !== onClose || $[82] !== t33) {
532
+ t34 = /* @__PURE__ */ jsxDEV(Button, {
533
+ "data-testid": "uc-cancel",
534
+ onClick: onClose,
535
+ size: "sm",
536
+ type: "button",
537
+ variant: "outline",
538
+ children: t33
539
+ }, void 0, false);
540
+ $[81] = onClose;
541
+ $[82] = t33;
542
+ $[83] = t34;
543
+ } else {
544
+ t34 = $[83];
545
+ }
546
+ const t35 = !canSubmit;
547
+ let t36;
548
+ if ($[84] !== busy || $[85] !== t) {
549
+ t36 = busy ? t("Creating…") : t("Create");
550
+ $[84] = busy;
551
+ $[85] = t;
552
+ $[86] = t36;
553
+ } else {
554
+ t36 = $[86];
555
+ }
556
+ let t37;
557
+ if ($[87] !== onSubmit || $[88] !== t35 || $[89] !== t36) {
558
+ t37 = /* @__PURE__ */ jsxDEV(Button, {
559
+ "data-testid": "uc-submit",
560
+ disabled: t35,
561
+ onClick: onSubmit,
562
+ size: "sm",
563
+ type: "button",
564
+ children: t36
565
+ }, void 0, false);
566
+ $[87] = onSubmit;
567
+ $[88] = t35;
568
+ $[89] = t36;
569
+ $[90] = t37;
570
+ } else {
571
+ t37 = $[90];
572
+ }
573
+ let t38;
574
+ if ($[91] !== t34 || $[92] !== t37) {
575
+ t38 = /* @__PURE__ */ jsxDEV("div", {
576
+ className: "flex justify-end gap-2 pt-1",
577
+ children: [t34, t37]
578
+ }, void 0, true);
579
+ $[91] = t34;
580
+ $[92] = t37;
581
+ $[93] = t38;
582
+ } else {
583
+ t38 = $[93];
584
+ }
585
+ let t39;
586
+ if ($[94] !== onClose || $[95] !== t12 || $[96] !== t14 || $[97] !== t18 || $[98] !== t22 || $[99] !== t26 || $[100] !== t30 || $[101] !== t31 || $[102] !== t32 || $[103] !== t38) {
587
+ t39 = /* @__PURE__ */ jsxDEV(ModalShell, {
588
+ label: t12,
589
+ onClose,
590
+ panelTestId: "uc-dialog",
591
+ testId: "uc-overlay",
592
+ variant: "dialog",
593
+ children: [t14, t18, t22, t26, t30, t31, t32, t38]
594
+ }, void 0, true);
595
+ $[94] = onClose;
596
+ $[95] = t12;
597
+ $[96] = t14;
598
+ $[97] = t18;
599
+ $[98] = t22;
600
+ $[99] = t26;
601
+ $[100] = t30;
602
+ $[101] = t31;
603
+ $[102] = t32;
604
+ $[103] = t38;
605
+ $[104] = t39;
606
+ } else {
607
+ t39 = $[104];
608
+ }
609
+ return t39;
610
+ };
611
+
612
+ const SectionHeading = (t0) => {
613
+ const $ = c(2);
614
+ const {
615
+ children
616
+ } = t0;
617
+ let t1;
618
+ if ($[0] !== children) {
619
+ t1 = /* @__PURE__ */ jsxDEV("h3", {
620
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
621
+ children
622
+ }, void 0, false);
623
+ $[0] = children;
624
+ $[1] = t1;
625
+ } else {
626
+ t1 = $[1];
627
+ }
628
+ return t1;
629
+ };
630
+ const UserSessionsPanel = (t0) => {
631
+ const $ = c(29);
632
+ const {
633
+ busy,
634
+ runAction,
635
+ userId,
636
+ version
637
+ } = t0;
638
+ const client = useLunora();
639
+ const t = useT();
640
+ const [sessions, setSessions] = useState(null);
641
+ const [error, setError] = useState(null);
642
+ let t1;
643
+ if ($[0] !== client || $[1] !== userId) {
644
+ t1 = () => {
645
+ fireAndForget((async () => {
646
+ setError(null);
647
+ try {
648
+ const page = await client.listAuthSessions({
649
+ limit: 50,
650
+ userId
651
+ });
652
+ setSessions(page.rows);
653
+ } catch (t22) {
654
+ const error_ = t22;
655
+ setSessions(null);
656
+ setError(errorMessage(error_));
657
+ }
658
+ })());
659
+ };
660
+ $[0] = client;
661
+ $[1] = userId;
662
+ $[2] = t1;
663
+ } else {
664
+ t1 = $[2];
665
+ }
666
+ let t2;
667
+ if ($[3] !== client || $[4] !== userId || $[5] !== version) {
668
+ t2 = [client, userId, version];
669
+ $[3] = client;
670
+ $[4] = userId;
671
+ $[5] = version;
672
+ $[6] = t2;
673
+ } else {
674
+ t2 = $[6];
675
+ }
676
+ useEffect(t1, t2);
677
+ let t3;
678
+ if ($[7] !== client || $[8] !== runAction) {
679
+ t3 = (sessionId) => {
680
+ runAction(() => client.revokeAuthSession({
681
+ sessionId
682
+ }));
683
+ };
684
+ $[7] = client;
685
+ $[8] = runAction;
686
+ $[9] = t3;
687
+ } else {
688
+ t3 = $[9];
689
+ }
690
+ const onRevoke = t3;
691
+ let t4;
692
+ if ($[10] !== t) {
693
+ t4 = t("Sessions");
694
+ $[10] = t;
695
+ $[11] = t4;
696
+ } else {
697
+ t4 = $[11];
698
+ }
699
+ let t5;
700
+ if ($[12] !== t4) {
701
+ t5 = /* @__PURE__ */ jsxDEV(SectionHeading, {
702
+ children: t4
703
+ }, void 0, false);
704
+ $[12] = t4;
705
+ $[13] = t5;
706
+ } else {
707
+ t5 = $[13];
708
+ }
709
+ let t6;
710
+ if ($[14] !== error) {
711
+ t6 = error !== null && /* @__PURE__ */ jsxDEV("p", {
712
+ className: "text-sm text-destructive",
713
+ "data-testid": "ud-sessions-error",
714
+ role: "alert",
715
+ children: error
716
+ }, void 0, false);
717
+ $[14] = error;
718
+ $[15] = t6;
719
+ } else {
720
+ t6 = $[15];
721
+ }
722
+ let t7;
723
+ if ($[16] !== sessions || $[17] !== t) {
724
+ t7 = sessions !== null && sessions.length === 0 && /* @__PURE__ */ jsxDEV("p", {
725
+ className: "text-sm text-muted-foreground",
726
+ "data-testid": "ud-sessions-empty",
727
+ children: t("No active sessions.")
728
+ }, void 0, false);
729
+ $[16] = sessions;
730
+ $[17] = t;
731
+ $[18] = t7;
732
+ } else {
733
+ t7 = $[18];
734
+ }
735
+ let t8;
736
+ if ($[19] !== busy || $[20] !== onRevoke || $[21] !== sessions || $[22] !== t) {
737
+ t8 = sessions !== null && sessions.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
738
+ className: "overflow-hidden py-0",
739
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
740
+ className: "px-0",
741
+ children: /* @__PURE__ */ jsxDEV(Table, {
742
+ "data-testid": "ud-sessions-table",
743
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
744
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
745
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
746
+ children: t("expires")
747
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
748
+ children: t("ip")
749
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
750
+ children: t("user agent")
751
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
752
+ "aria-label": t("Actions")
753
+ }, void 0, false)]
754
+ }, void 0, true)
755
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
756
+ children: sessions.map((session) => /* @__PURE__ */ jsxDEV(TableRow, {
757
+ "data-testid": `ud-session-${session.id}`,
758
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
759
+ className: "text-muted-foreground tabular-nums",
760
+ children: formatTimestamp(session.expiresAt)
761
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
762
+ children: session.ipAddress ?? ""
763
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
764
+ className: "max-w-40 truncate",
765
+ children: session.userAgent ?? ""
766
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
767
+ children: /* @__PURE__ */ jsxDEV(Button, {
768
+ "data-testid": `ud-revoke-${session.id}`,
769
+ disabled: busy,
770
+ onClick: () => {
771
+ onRevoke(session.id);
772
+ },
773
+ size: "xs",
774
+ type: "button",
775
+ variant: "ghost",
776
+ children: t("Revoke")
777
+ }, void 0, false)
778
+ }, void 0, false)]
779
+ }, session.id, true))
780
+ }, void 0, false)]
781
+ }, void 0, true)
782
+ }, void 0, false)
783
+ }, void 0, false);
784
+ $[19] = busy;
785
+ $[20] = onRevoke;
786
+ $[21] = sessions;
787
+ $[22] = t;
788
+ $[23] = t8;
789
+ } else {
790
+ t8 = $[23];
791
+ }
792
+ let t9;
793
+ if ($[24] !== t5 || $[25] !== t6 || $[26] !== t7 || $[27] !== t8) {
794
+ t9 = /* @__PURE__ */ jsxDEV("div", {
795
+ className: "flex flex-col gap-2",
796
+ "data-testid": "ud-sessions",
797
+ children: [t5, t6, t7, t8]
798
+ }, void 0, true);
799
+ $[24] = t5;
800
+ $[25] = t6;
801
+ $[26] = t7;
802
+ $[27] = t8;
803
+ $[28] = t9;
804
+ } else {
805
+ t9 = $[28];
806
+ }
807
+ return t9;
808
+ };
809
+ const UserAccountsPanel = (t0) => {
810
+ const $ = c(30);
811
+ const {
812
+ busy,
813
+ runAction,
814
+ userId,
815
+ version
816
+ } = t0;
817
+ const client = useLunora();
818
+ const t = useT();
819
+ const [accounts, setAccounts] = useState(null);
820
+ const [error, setError] = useState(null);
821
+ let t1;
822
+ if ($[0] !== client || $[1] !== userId) {
823
+ t1 = () => {
824
+ fireAndForget((async () => {
825
+ setError(null);
826
+ try {
827
+ setAccounts(await client.listAuthAccounts({
828
+ userId
829
+ }));
830
+ } catch (t22) {
831
+ const error_ = t22;
832
+ setAccounts(null);
833
+ setError(errorMessage(error_));
834
+ }
835
+ })());
836
+ };
837
+ $[0] = client;
838
+ $[1] = userId;
839
+ $[2] = t1;
840
+ } else {
841
+ t1 = $[2];
842
+ }
843
+ let t2;
844
+ if ($[3] !== client || $[4] !== userId || $[5] !== version) {
845
+ t2 = [client, userId, version];
846
+ $[3] = client;
847
+ $[4] = userId;
848
+ $[5] = version;
849
+ $[6] = t2;
850
+ } else {
851
+ t2 = $[6];
852
+ }
853
+ useEffect(t1, t2);
854
+ let t3;
855
+ if ($[7] !== client || $[8] !== runAction || $[9] !== userId) {
856
+ t3 = (accountId) => {
857
+ runAction(() => client.unlinkAuthAccount({
858
+ accountId,
859
+ userId
860
+ }));
861
+ };
862
+ $[7] = client;
863
+ $[8] = runAction;
864
+ $[9] = userId;
865
+ $[10] = t3;
866
+ } else {
867
+ t3 = $[10];
868
+ }
869
+ const onUnlink = t3;
870
+ let t4;
871
+ if ($[11] !== t) {
872
+ t4 = t("Linked accounts");
873
+ $[11] = t;
874
+ $[12] = t4;
875
+ } else {
876
+ t4 = $[12];
877
+ }
878
+ let t5;
879
+ if ($[13] !== t4) {
880
+ t5 = /* @__PURE__ */ jsxDEV(SectionHeading, {
881
+ children: t4
882
+ }, void 0, false);
883
+ $[13] = t4;
884
+ $[14] = t5;
885
+ } else {
886
+ t5 = $[14];
887
+ }
888
+ let t6;
889
+ if ($[15] !== error) {
890
+ t6 = error !== null && /* @__PURE__ */ jsxDEV("p", {
891
+ className: "text-sm text-destructive",
892
+ role: "alert",
893
+ children: error
894
+ }, void 0, false);
895
+ $[15] = error;
896
+ $[16] = t6;
897
+ } else {
898
+ t6 = $[16];
899
+ }
900
+ let t7;
901
+ if ($[17] !== accounts || $[18] !== t) {
902
+ t7 = accounts !== null && accounts.length === 0 && /* @__PURE__ */ jsxDEV("p", {
903
+ className: "text-sm text-muted-foreground",
904
+ children: t("No linked accounts.")
905
+ }, void 0, false);
906
+ $[17] = accounts;
907
+ $[18] = t;
908
+ $[19] = t7;
909
+ } else {
910
+ t7 = $[19];
911
+ }
912
+ let t8;
913
+ if ($[20] !== accounts || $[21] !== busy || $[22] !== onUnlink || $[23] !== t) {
914
+ t8 = accounts !== null && accounts.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
915
+ className: "overflow-hidden py-0",
916
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
917
+ className: "px-0",
918
+ children: /* @__PURE__ */ jsxDEV(Table, {
919
+ "data-testid": "ud-accounts-table",
920
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
921
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
922
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
923
+ children: t("provider")
924
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
925
+ children: t("created")
926
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
927
+ "aria-label": t("Actions")
928
+ }, void 0, false)]
929
+ }, void 0, true)
930
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
931
+ children: accounts.map((account) => {
932
+ const id = formatCell(account.id);
933
+ return /* @__PURE__ */ jsxDEV(TableRow, {
934
+ "data-testid": `ud-account-${id}`,
935
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
936
+ children: formatCell(account.providerId)
937
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
938
+ className: "text-muted-foreground tabular-nums",
939
+ children: formatTimestamp(account.createdAt)
940
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
941
+ children: /* @__PURE__ */ jsxDEV(Button, {
942
+ "data-testid": `ud-unlink-${id}`,
943
+ disabled: busy,
944
+ onClick: () => {
945
+ onUnlink(id);
946
+ },
947
+ size: "xs",
948
+ type: "button",
949
+ variant: "ghost",
950
+ children: t("Unlink")
951
+ }, void 0, false)
952
+ }, void 0, false)]
953
+ }, id, true);
954
+ })
955
+ }, void 0, false)]
956
+ }, void 0, true)
957
+ }, void 0, false)
958
+ }, void 0, false);
959
+ $[20] = accounts;
960
+ $[21] = busy;
961
+ $[22] = onUnlink;
962
+ $[23] = t;
963
+ $[24] = t8;
964
+ } else {
965
+ t8 = $[24];
966
+ }
967
+ let t9;
968
+ if ($[25] !== t5 || $[26] !== t6 || $[27] !== t7 || $[28] !== t8) {
969
+ t9 = /* @__PURE__ */ jsxDEV("div", {
970
+ className: "flex flex-col gap-2",
971
+ "data-testid": "ud-accounts",
972
+ children: [t5, t6, t7, t8]
973
+ }, void 0, true);
974
+ $[25] = t5;
975
+ $[26] = t6;
976
+ $[27] = t7;
977
+ $[28] = t8;
978
+ $[29] = t9;
979
+ } else {
980
+ t9 = $[29];
981
+ }
982
+ return t9;
983
+ };
984
+ const UserSecurityPanel = (t0) => {
985
+ const $ = c(40);
986
+ const {
987
+ busy,
988
+ capabilities,
989
+ runAction,
990
+ userId,
991
+ version
992
+ } = t0;
993
+ const client = useLunora();
994
+ const t = useT();
995
+ const [passkeys, setPasskeys] = useState(null);
996
+ let t1;
997
+ if ($[0] !== capabilities.passkey || $[1] !== client || $[2] !== userId) {
998
+ t1 = () => {
999
+ if (!capabilities.passkey) {
1000
+ return;
1001
+ }
1002
+ fireAndForget((async () => {
1003
+ try {
1004
+ setPasskeys(await client.listAuthPasskeys({
1005
+ userId
1006
+ }));
1007
+ } catch {
1008
+ setPasskeys(null);
1009
+ }
1010
+ })());
1011
+ };
1012
+ $[0] = capabilities.passkey;
1013
+ $[1] = client;
1014
+ $[2] = userId;
1015
+ $[3] = t1;
1016
+ } else {
1017
+ t1 = $[3];
1018
+ }
1019
+ let t2;
1020
+ if ($[4] !== capabilities.passkey || $[5] !== client || $[6] !== userId || $[7] !== version) {
1021
+ t2 = [capabilities.passkey, client, userId, version];
1022
+ $[4] = capabilities.passkey;
1023
+ $[5] = client;
1024
+ $[6] = userId;
1025
+ $[7] = version;
1026
+ $[8] = t2;
1027
+ } else {
1028
+ t2 = $[8];
1029
+ }
1030
+ useEffect(t1, t2);
1031
+ let t3;
1032
+ if ($[9] !== client || $[10] !== runAction || $[11] !== userId) {
1033
+ t3 = () => {
1034
+ runAction(() => client.disableAuthTwoFactor({
1035
+ userId
1036
+ }));
1037
+ };
1038
+ $[9] = client;
1039
+ $[10] = runAction;
1040
+ $[11] = userId;
1041
+ $[12] = t3;
1042
+ } else {
1043
+ t3 = $[12];
1044
+ }
1045
+ const onDisable2fa = t3;
1046
+ let t4;
1047
+ if ($[13] !== client || $[14] !== runAction) {
1048
+ t4 = (passkeyId) => {
1049
+ runAction(() => client.deleteAuthPasskey({
1050
+ passkeyId
1051
+ }));
1052
+ };
1053
+ $[13] = client;
1054
+ $[14] = runAction;
1055
+ $[15] = t4;
1056
+ } else {
1057
+ t4 = $[15];
1058
+ }
1059
+ const onDeletePasskey = t4;
1060
+ let t5;
1061
+ if ($[16] !== t) {
1062
+ t5 = t("Security");
1063
+ $[16] = t;
1064
+ $[17] = t5;
1065
+ } else {
1066
+ t5 = $[17];
1067
+ }
1068
+ let t6;
1069
+ if ($[18] !== t5) {
1070
+ t6 = /* @__PURE__ */ jsxDEV(SectionHeading, {
1071
+ children: t5
1072
+ }, void 0, false);
1073
+ $[18] = t5;
1074
+ $[19] = t6;
1075
+ } else {
1076
+ t6 = $[19];
1077
+ }
1078
+ let t7;
1079
+ if ($[20] !== busy || $[21] !== capabilities.twoFactor || $[22] !== onDisable2fa || $[23] !== t) {
1080
+ t7 = capabilities.twoFactor && /* @__PURE__ */ jsxDEV(Button, {
1081
+ "data-testid": "ud-disable-2fa",
1082
+ disabled: busy,
1083
+ onClick: onDisable2fa,
1084
+ size: "sm",
1085
+ type: "button",
1086
+ variant: "outline",
1087
+ children: t("Disable two-factor")
1088
+ }, void 0, false);
1089
+ $[20] = busy;
1090
+ $[21] = capabilities.twoFactor;
1091
+ $[22] = onDisable2fa;
1092
+ $[23] = t;
1093
+ $[24] = t7;
1094
+ } else {
1095
+ t7 = $[24];
1096
+ }
1097
+ let t8;
1098
+ if ($[25] !== capabilities.passkey || $[26] !== passkeys || $[27] !== t) {
1099
+ t8 = capabilities.passkey && passkeys !== null && passkeys.length === 0 && /* @__PURE__ */ jsxDEV("p", {
1100
+ className: "text-sm text-muted-foreground",
1101
+ children: t("No passkeys.")
1102
+ }, void 0, false);
1103
+ $[25] = capabilities.passkey;
1104
+ $[26] = passkeys;
1105
+ $[27] = t;
1106
+ $[28] = t8;
1107
+ } else {
1108
+ t8 = $[28];
1109
+ }
1110
+ let t9;
1111
+ if ($[29] !== busy || $[30] !== capabilities.passkey || $[31] !== onDeletePasskey || $[32] !== passkeys || $[33] !== t) {
1112
+ t9 = capabilities.passkey && passkeys !== null && passkeys.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
1113
+ className: "overflow-hidden py-0",
1114
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
1115
+ className: "px-0",
1116
+ children: /* @__PURE__ */ jsxDEV(Table, {
1117
+ "data-testid": "ud-passkeys-table",
1118
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
1119
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
1120
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
1121
+ children: t("name")
1122
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1123
+ children: t("created")
1124
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1125
+ "aria-label": t("Actions")
1126
+ }, void 0, false)]
1127
+ }, void 0, true)
1128
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
1129
+ children: passkeys.map((passkey) => {
1130
+ const id = formatCell(passkey.id);
1131
+ return /* @__PURE__ */ jsxDEV(TableRow, {
1132
+ "data-testid": `ud-passkey-${id}`,
1133
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
1134
+ children: formatCell(passkey.name) || id
1135
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1136
+ className: "text-muted-foreground tabular-nums",
1137
+ children: formatTimestamp(passkey.createdAt)
1138
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1139
+ children: /* @__PURE__ */ jsxDEV(Button, {
1140
+ "data-testid": `ud-delete-passkey-${id}`,
1141
+ disabled: busy,
1142
+ onClick: () => {
1143
+ onDeletePasskey(id);
1144
+ },
1145
+ size: "xs",
1146
+ type: "button",
1147
+ variant: "ghost",
1148
+ children: t("Delete")
1149
+ }, void 0, false)
1150
+ }, void 0, false)]
1151
+ }, id, true);
1152
+ })
1153
+ }, void 0, false)]
1154
+ }, void 0, true)
1155
+ }, void 0, false)
1156
+ }, void 0, false);
1157
+ $[29] = busy;
1158
+ $[30] = capabilities.passkey;
1159
+ $[31] = onDeletePasskey;
1160
+ $[32] = passkeys;
1161
+ $[33] = t;
1162
+ $[34] = t9;
1163
+ } else {
1164
+ t9 = $[34];
1165
+ }
1166
+ let t10;
1167
+ if ($[35] !== t6 || $[36] !== t7 || $[37] !== t8 || $[38] !== t9) {
1168
+ t10 = /* @__PURE__ */ jsxDEV("div", {
1169
+ className: "flex flex-col gap-2",
1170
+ "data-testid": "ud-security",
1171
+ children: [t6, t7, t8, t9]
1172
+ }, void 0, true);
1173
+ $[35] = t6;
1174
+ $[36] = t7;
1175
+ $[37] = t8;
1176
+ $[38] = t9;
1177
+ $[39] = t10;
1178
+ } else {
1179
+ t10 = $[39];
1180
+ }
1181
+ return t10;
1182
+ };
1183
+
1184
+ const TIMESTAMP_RE = /(?:at|expires)$/iu;
1185
+ const SUMMARY_FIELDS = /* @__PURE__ */ new Set(["banExpires", "banned", "banReason", "email", "emailVerified", "id", "name", "role"]);
1186
+ const formatField = (key, value) => {
1187
+ if (typeof value === "number" && TIMESTAMP_RE.test(key)) {
1188
+ return formatTimestamp(value);
1189
+ }
1190
+ return formatCell(value);
1191
+ };
1192
+ const UserDetailDrawer = ({
1193
+ capabilities,
1194
+ onChanged,
1195
+ onClose,
1196
+ user
1197
+ }) => {
1198
+ const client = useLunora();
1199
+ const t = useT();
1200
+ const banned = user.banned === true;
1201
+ const [actionError, setActionError] = useState(null);
1202
+ const [busy, setBusy] = useState(false);
1203
+ const [version, setVersion] = useState(0);
1204
+ const [roleInput, setRoleInput] = useState(typeof user.role === "string" ? user.role : "");
1205
+ const [banReason, setBanReason] = useState("");
1206
+ const [banDays, setBanDays] = useState("");
1207
+ const [newPassword, setNewPassword] = useState("");
1208
+ const [impersonationToken, setImpersonationToken] = useState(null);
1209
+ const [confirmDelete, setConfirmDelete] = useState(false);
1210
+ const runAction = (action, options) => {
1211
+ fireAndForget((async () => {
1212
+ setBusy(true);
1213
+ setActionError(null);
1214
+ try {
1215
+ const result = await action();
1216
+ if (options?.refresh !== false) {
1217
+ setVersion((value) => value + 1);
1218
+ onChanged();
1219
+ }
1220
+ options?.onResult?.(result);
1221
+ } catch (error_) {
1222
+ setActionError(errorMessage(error_));
1223
+ } finally {
1224
+ setBusy(false);
1225
+ }
1226
+ })());
1227
+ };
1228
+ const onRoleInputChange = (event) => {
1229
+ setRoleInput(event.target.value);
1230
+ };
1231
+ const onBanReasonChange = (event_0) => {
1232
+ setBanReason(event_0.target.value);
1233
+ };
1234
+ const onBanDaysChange = (event_1) => {
1235
+ setBanDays(event_1.target.value);
1236
+ };
1237
+ const onNewPasswordChange = (event_2) => {
1238
+ setNewPassword(event_2.target.value);
1239
+ };
1240
+ const onSetRole = () => {
1241
+ const role = roleInput.trim();
1242
+ if (role === "") {
1243
+ return;
1244
+ }
1245
+ runAction(async () => {
1246
+ await client.setAuthUserRole({
1247
+ role,
1248
+ userId: user.id
1249
+ });
1250
+ });
1251
+ };
1252
+ const onBan = () => {
1253
+ const days = Number.parseInt(banDays, 10);
1254
+ const expiresInSeconds = Number.isFinite(days) && days > 0 ? days * 86400 : void 0;
1255
+ runAction(async () => {
1256
+ await client.banAuthUser({
1257
+ expiresInSeconds,
1258
+ reason: banReason.trim() === "" ? void 0 : banReason.trim(),
1259
+ userId: user.id
1260
+ });
1261
+ });
1262
+ };
1263
+ const onUnban = () => {
1264
+ runAction(async () => {
1265
+ await client.unbanAuthUser({
1266
+ userId: user.id
1267
+ });
1268
+ });
1269
+ };
1270
+ const onSetPassword = () => {
1271
+ runAction(async () => {
1272
+ await client.setAuthUserPassword({
1273
+ newPassword,
1274
+ userId: user.id
1275
+ });
1276
+ setNewPassword("");
1277
+ });
1278
+ };
1279
+ const onImpersonate = () => {
1280
+ runAction(() => client.impersonateAuthUser({
1281
+ userId: user.id
1282
+ }), {
1283
+ onResult: (result_0) => {
1284
+ setImpersonationToken(result_0.token);
1285
+ },
1286
+ refresh: false
1287
+ });
1288
+ };
1289
+ const onRevokeAll = () => {
1290
+ runAction(async () => {
1291
+ await client.revokeAuthUserSessions({
1292
+ userId: user.id
1293
+ });
1294
+ });
1295
+ };
1296
+ const onDelete = () => {
1297
+ runAction(async () => {
1298
+ await client.removeAuthUser({
1299
+ userId: user.id
1300
+ });
1301
+ onClose();
1302
+ });
1303
+ };
1304
+ const onConfirmDelete = () => {
1305
+ setConfirmDelete(true);
1306
+ };
1307
+ const onCancelDelete = () => {
1308
+ setConfirmDelete(false);
1309
+ };
1310
+ const rawFields = Object.entries(user).filter(([key]) => !SUMMARY_FIELDS.has(key));
1311
+ return /* @__PURE__ */ jsxDEV(ModalShell, {
1312
+ label: t("User details"),
1313
+ onClose,
1314
+ panelTestId: "ud-panel",
1315
+ testId: "ud-overlay",
1316
+ variant: "drawer",
1317
+ children: [/* @__PURE__ */ jsxDEV("div", {
1318
+ className: "flex items-start justify-between gap-2",
1319
+ children: [/* @__PURE__ */ jsxDEV("div", {
1320
+ className: "flex flex-col gap-1",
1321
+ children: [/* @__PURE__ */ jsxDEV("h2", {
1322
+ className: "text-sm font-semibold text-foreground",
1323
+ children: user.name ?? user.email ?? user.id
1324
+ }, void 0, false), /* @__PURE__ */ jsxDEV("p", {
1325
+ className: "font-mono text-xs text-muted-foreground",
1326
+ children: user.id
1327
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
1328
+ className: "flex flex-wrap items-center gap-1.5 pt-1",
1329
+ children: [typeof user.role === "string" && user.role !== "" && /* @__PURE__ */ jsxDEV(Badge, {
1330
+ variant: "secondary",
1331
+ children: user.role
1332
+ }, void 0, false), banned ? /* @__PURE__ */ jsxDEV(Badge, {
1333
+ variant: "destructive",
1334
+ children: t("Banned")
1335
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
1336
+ variant: "outline",
1337
+ children: t("Active")
1338
+ }, void 0, false), user.emailVerified === true ? /* @__PURE__ */ jsxDEV(Badge, {
1339
+ variant: "secondary",
1340
+ children: t("verified")
1341
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
1342
+ variant: "outline",
1343
+ children: t("unverified")
1344
+ }, void 0, false)]
1345
+ }, void 0, true)]
1346
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
1347
+ "data-testid": "ud-close",
1348
+ onClick: onClose,
1349
+ size: "sm",
1350
+ type: "button",
1351
+ variant: "ghost",
1352
+ children: t("Close")
1353
+ }, void 0, false)]
1354
+ }, void 0, true), actionError !== null && /* @__PURE__ */ jsxDEV("p", {
1355
+ className: "text-sm text-destructive",
1356
+ "data-testid": "ud-action-error",
1357
+ role: "alert",
1358
+ children: actionError
1359
+ }, void 0, false), capabilities.admin && /* @__PURE__ */ jsxDEV(Card, {
1360
+ className: "gap-0 py-0",
1361
+ children: [/* @__PURE__ */ jsxDEV("header", {
1362
+ className: "border-b border-border px-4 py-3",
1363
+ children: /* @__PURE__ */ jsxDEV("span", {
1364
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
1365
+ children: t("Actions")
1366
+ }, void 0, false)
1367
+ }, void 0, false), /* @__PURE__ */ jsxDEV(CardContent, {
1368
+ className: "flex flex-col gap-3 p-3",
1369
+ children: [/* @__PURE__ */ jsxDEV("div", {
1370
+ className: "flex items-end gap-2",
1371
+ children: [/* @__PURE__ */ jsxDEV("div", {
1372
+ className: "flex flex-1 flex-col gap-1",
1373
+ children: [/* @__PURE__ */ jsxDEV(Label, {
1374
+ htmlFor: "ud-role",
1375
+ children: t("Role")
1376
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1377
+ "data-testid": "ud-role-input",
1378
+ id: "ud-role",
1379
+ onChange: onRoleInputChange,
1380
+ value: roleInput
1381
+ }, void 0, false)]
1382
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
1383
+ "data-testid": "ud-set-role",
1384
+ disabled: busy || roleInput.trim() === "",
1385
+ onClick: onSetRole,
1386
+ size: "sm",
1387
+ type: "button",
1388
+ variant: "outline",
1389
+ children: t("Set role")
1390
+ }, void 0, false)]
1391
+ }, void 0, true), banned ? /* @__PURE__ */ jsxDEV(Button, {
1392
+ "data-testid": "ud-unban",
1393
+ disabled: busy,
1394
+ onClick: onUnban,
1395
+ size: "sm",
1396
+ type: "button",
1397
+ variant: "outline",
1398
+ children: t("Unban")
1399
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
1400
+ className: "flex items-end gap-2",
1401
+ children: [/* @__PURE__ */ jsxDEV("div", {
1402
+ className: "flex flex-1 flex-col gap-1",
1403
+ children: [/* @__PURE__ */ jsxDEV(Label, {
1404
+ htmlFor: "ud-ban-reason",
1405
+ children: t("Ban reason (optional)")
1406
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1407
+ "data-testid": "ud-ban-reason",
1408
+ id: "ud-ban-reason",
1409
+ onChange: onBanReasonChange,
1410
+ value: banReason
1411
+ }, void 0, false)]
1412
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
1413
+ className: "flex w-24 flex-col gap-1",
1414
+ children: [/* @__PURE__ */ jsxDEV(Label, {
1415
+ htmlFor: "ud-ban-days",
1416
+ children: t("Days")
1417
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1418
+ "data-testid": "ud-ban-days",
1419
+ id: "ud-ban-days",
1420
+ onChange: onBanDaysChange,
1421
+ type: "number",
1422
+ value: banDays
1423
+ }, void 0, false)]
1424
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
1425
+ "data-testid": "ud-ban",
1426
+ disabled: busy,
1427
+ onClick: onBan,
1428
+ size: "sm",
1429
+ type: "button",
1430
+ variant: "destructive",
1431
+ children: t("Ban user")
1432
+ }, void 0, false)]
1433
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
1434
+ className: "flex items-end gap-2",
1435
+ children: [/* @__PURE__ */ jsxDEV("div", {
1436
+ className: "flex flex-1 flex-col gap-1",
1437
+ children: [/* @__PURE__ */ jsxDEV(Label, {
1438
+ htmlFor: "ud-password",
1439
+ children: t("New password")
1440
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1441
+ "data-testid": "ud-password",
1442
+ id: "ud-password",
1443
+ onChange: onNewPasswordChange,
1444
+ type: "password",
1445
+ value: newPassword
1446
+ }, void 0, false)]
1447
+ }, void 0, true), /* @__PURE__ */ jsxDEV(Button, {
1448
+ "data-testid": "ud-set-password",
1449
+ disabled: busy || newPassword === "",
1450
+ onClick: onSetPassword,
1451
+ size: "sm",
1452
+ type: "button",
1453
+ variant: "outline",
1454
+ children: t("Set password")
1455
+ }, void 0, false)]
1456
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
1457
+ className: "flex flex-wrap gap-2",
1458
+ children: [/* @__PURE__ */ jsxDEV(Button, {
1459
+ "data-testid": "ud-impersonate",
1460
+ disabled: busy,
1461
+ onClick: onImpersonate,
1462
+ size: "sm",
1463
+ type: "button",
1464
+ variant: "outline",
1465
+ children: t("Impersonate")
1466
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
1467
+ "data-testid": "ud-revoke-all",
1468
+ disabled: busy,
1469
+ onClick: onRevokeAll,
1470
+ size: "sm",
1471
+ type: "button",
1472
+ variant: "outline",
1473
+ children: t("Revoke all sessions")
1474
+ }, void 0, false), confirmDelete ? /* @__PURE__ */ jsxDEV(Fragment, {
1475
+ children: [/* @__PURE__ */ jsxDEV(Button, {
1476
+ "data-testid": "ud-delete-confirm",
1477
+ disabled: busy,
1478
+ onClick: onDelete,
1479
+ size: "sm",
1480
+ type: "button",
1481
+ variant: "destructive",
1482
+ children: t("Confirm delete")
1483
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
1484
+ "data-testid": "ud-delete-cancel",
1485
+ onClick: onCancelDelete,
1486
+ size: "sm",
1487
+ type: "button",
1488
+ variant: "ghost",
1489
+ children: t("Cancel")
1490
+ }, void 0, false)]
1491
+ }, void 0, true) : /* @__PURE__ */ jsxDEV(Button, {
1492
+ "data-testid": "ud-delete",
1493
+ disabled: busy,
1494
+ onClick: onConfirmDelete,
1495
+ size: "sm",
1496
+ type: "button",
1497
+ variant: "destructive",
1498
+ children: t("Delete user")
1499
+ }, void 0, false)]
1500
+ }, void 0, true), impersonationToken !== null && /* @__PURE__ */ jsxDEV("div", {
1501
+ className: "flex flex-col gap-1",
1502
+ "data-testid": "ud-impersonation",
1503
+ children: [/* @__PURE__ */ jsxDEV(Label, {
1504
+ htmlFor: "ud-token",
1505
+ children: t("Impersonation token")
1506
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1507
+ "data-testid": "ud-token",
1508
+ id: "ud-token",
1509
+ readOnly: true,
1510
+ value: impersonationToken
1511
+ }, void 0, false)]
1512
+ }, void 0, true)]
1513
+ }, void 0, true)]
1514
+ }, void 0, true), /* @__PURE__ */ jsxDEV(UserSessionsPanel, {
1515
+ busy,
1516
+ runAction,
1517
+ userId: user.id,
1518
+ version
1519
+ }, void 0, false), capabilities.accounts && /* @__PURE__ */ jsxDEV(UserAccountsPanel, {
1520
+ busy,
1521
+ runAction,
1522
+ userId: user.id,
1523
+ version
1524
+ }, void 0, false), (capabilities.twoFactor || capabilities.passkey) && /* @__PURE__ */ jsxDEV(UserSecurityPanel, {
1525
+ busy,
1526
+ capabilities,
1527
+ runAction,
1528
+ userId: user.id,
1529
+ version
1530
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
1531
+ className: "flex flex-col gap-1",
1532
+ "data-testid": "ud-fields",
1533
+ children: [/* @__PURE__ */ jsxDEV("h3", {
1534
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
1535
+ children: t("Fields")
1536
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dl", {
1537
+ className: "flex flex-col",
1538
+ children: rawFields.map(([key_0, value_0]) => /* @__PURE__ */ jsxDEV("div", {
1539
+ className: "flex flex-col border-t border-border py-1.5",
1540
+ children: [/* @__PURE__ */ jsxDEV("dt", {
1541
+ className: "text-xs font-semibold text-muted-foreground",
1542
+ children: key_0
1543
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dd", {
1544
+ className: "m-0 font-mono text-xs break-words",
1545
+ children: formatField(key_0, value_0)
1546
+ }, void 0, false)]
1547
+ }, key_0, true))
1548
+ }, void 0, false)]
1549
+ }, void 0, true)]
1550
+ }, void 0, true);
1551
+ };
1552
+
1553
+ const DEFAULT_PAGE_SIZE = 50;
1554
+ const UsersPanel = ({
1555
+ pageSize = DEFAULT_PAGE_SIZE
1556
+ } = {}) => {
1557
+ const client = useLunora();
1558
+ const t = useT();
1559
+ const [search, setSearch] = useState("");
1560
+ const [roleFilter, setRoleFilter] = useState("");
1561
+ const debouncedSearch = useDebounced(search);
1562
+ const [selectedUserId, setSelectedUserId] = useState(null);
1563
+ const [createOpen, setCreateOpen] = useState(false);
1564
+ const {
1565
+ capabilities
1566
+ } = useAuthCapabilities();
1567
+ const trimmedSearch = debouncedSearch.trim();
1568
+ const trimmedRole = roleFilter.trim();
1569
+ const usersQuery = useClientQuery(["lunora-auth-users", trimmedSearch, trimmedRole, pageSize], () => client.listAuthUsers({
1570
+ filterField: trimmedRole === "" ? void 0 : "role",
1571
+ filterValue: trimmedRole === "" ? void 0 : trimmedRole,
1572
+ limit: pageSize,
1573
+ search: trimmedSearch === "" ? void 0 : trimmedSearch
1574
+ }), {
1575
+ keepPreviousData: true
1576
+ });
1577
+ const users = usersQuery.data?.rows ?? null;
1578
+ const usersError = usersQuery.error;
1579
+ const reloadUsers = () => {
1580
+ usersQuery.refetch();
1581
+ };
1582
+ useAutoRefresh(() => {
1583
+ usersQuery.refetch();
1584
+ }, true);
1585
+ const selectedUser = selectedUserId === null ? null : users?.find((user) => user.id === selectedUserId) ?? null;
1586
+ return /* @__PURE__ */ jsxDEV("div", {
1587
+ className: "flex flex-col gap-4",
1588
+ "data-testid": "lunora-users",
1589
+ children: [/* @__PURE__ */ jsxDEV("div", {
1590
+ className: "flex flex-wrap items-center gap-2",
1591
+ children: [/* @__PURE__ */ jsxDEV(Input, {
1592
+ "aria-label": t("Search users"),
1593
+ className: "w-56",
1594
+ "data-testid": "us-search",
1595
+ onChange: (event) => {
1596
+ setSearch(event.target.value);
1597
+ },
1598
+ placeholder: t("Search by email or name…"),
1599
+ value: search
1600
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Input, {
1601
+ "aria-label": t("Filter by role"),
1602
+ className: "w-40",
1603
+ "data-testid": "us-role-filter",
1604
+ onChange: (event_0) => {
1605
+ setRoleFilter(event_0.target.value);
1606
+ },
1607
+ placeholder: t("Filter by role"),
1608
+ value: roleFilter
1609
+ }, void 0, false), /* @__PURE__ */ jsxDEV(Button, {
1610
+ "data-testid": "us-new",
1611
+ onClick: () => {
1612
+ setCreateOpen(true);
1613
+ },
1614
+ size: "sm",
1615
+ type: "button",
1616
+ children: t("New user")
1617
+ }, void 0, false)]
1618
+ }, void 0, true), usersError !== null && /* @__PURE__ */ jsxDEV("p", {
1619
+ className: "text-sm text-destructive",
1620
+ "data-testid": "us-users-error",
1621
+ role: "alert",
1622
+ children: usersError
1623
+ }, void 0, false), users !== null && users.length === 0 && /* @__PURE__ */ jsxDEV(EmptyState, {
1624
+ description: t("Users who sign up to your app will appear here."),
1625
+ icon: /* @__PURE__ */ jsxDEV("svg", {
1626
+ "aria-hidden": "true",
1627
+ fill: "none",
1628
+ stroke: "currentColor",
1629
+ strokeLinecap: "round",
1630
+ strokeLinejoin: "round",
1631
+ strokeWidth: 1.6,
1632
+ viewBox: "0 0 24 24",
1633
+ children: /* @__PURE__ */ jsxDEV("path", {
1634
+ 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"
1635
+ }, void 0, false)
1636
+ }, void 0, false),
1637
+ testId: "us-empty",
1638
+ title: t("No users.")
1639
+ }, void 0, false), users !== null && users.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
1640
+ className: "overflow-hidden py-0",
1641
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
1642
+ className: "px-0",
1643
+ children: /* @__PURE__ */ jsxDEV(Table, {
1644
+ "data-testid": "us-table",
1645
+ children: [/* @__PURE__ */ jsxDEV(TableHeader, {
1646
+ children: /* @__PURE__ */ jsxDEV(TableRow, {
1647
+ children: [/* @__PURE__ */ jsxDEV(TableHead, {
1648
+ children: t("id")
1649
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1650
+ children: t("email")
1651
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1652
+ children: t("name")
1653
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1654
+ children: t("role")
1655
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1656
+ children: t("status")
1657
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1658
+ children: t("verified")
1659
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1660
+ children: t("created")
1661
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableHead, {
1662
+ "aria-label": t("Actions")
1663
+ }, void 0, false)]
1664
+ }, void 0, true)
1665
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableBody, {
1666
+ children: users.map((user_0) => /* @__PURE__ */ jsxDEV(TableRow, {
1667
+ "data-testid": `us-row-${user_0.id}`,
1668
+ children: [/* @__PURE__ */ jsxDEV(TableCell, {
1669
+ className: "font-mono text-xs",
1670
+ children: user_0.id
1671
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1672
+ children: user_0.email ?? ""
1673
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1674
+ children: user_0.name ?? ""
1675
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1676
+ children: typeof user_0.role === "string" && user_0.role !== "" ? /* @__PURE__ */ jsxDEV(Badge, {
1677
+ variant: "secondary",
1678
+ children: user_0.role
1679
+ }, void 0, false) : ""
1680
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1681
+ children: user_0.banned === true ? /* @__PURE__ */ jsxDEV(Badge, {
1682
+ variant: "destructive",
1683
+ children: t("Banned")
1684
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
1685
+ variant: "success",
1686
+ children: t("Active")
1687
+ }, void 0, false)
1688
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1689
+ children: user_0.emailVerified === true ? /* @__PURE__ */ jsxDEV(Badge, {
1690
+ variant: "success",
1691
+ children: t("yes")
1692
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
1693
+ variant: "outline",
1694
+ children: t("no")
1695
+ }, void 0, false)
1696
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1697
+ className: "text-muted-foreground tabular-nums",
1698
+ children: formatTimestamp(user_0.createdAt)
1699
+ }, void 0, false), /* @__PURE__ */ jsxDEV(TableCell, {
1700
+ children: /* @__PURE__ */ jsxDEV(Button, {
1701
+ "data-testid": `us-manage-${user_0.id}`,
1702
+ onClick: () => {
1703
+ setSelectedUserId(user_0.id);
1704
+ },
1705
+ size: "xs",
1706
+ type: "button",
1707
+ variant: "ghost",
1708
+ children: t("Manage")
1709
+ }, void 0, false)
1710
+ }, void 0, false)]
1711
+ }, user_0.id, true))
1712
+ }, void 0, false)]
1713
+ }, void 0, true)
1714
+ }, void 0, false)
1715
+ }, void 0, false), selectedUser !== null && /* @__PURE__ */ jsxDEV(UserDetailDrawer, {
1716
+ capabilities,
1717
+ onChanged: reloadUsers,
1718
+ onClose: () => {
1719
+ setSelectedUserId(null);
1720
+ },
1721
+ user: selectedUser
1722
+ }, void 0, false), createOpen && /* @__PURE__ */ jsxDEV(UserCreateDialog, {
1723
+ onClose: () => {
1724
+ setCreateOpen(false);
1725
+ },
1726
+ onCreated: reloadUsers
1727
+ }, void 0, false)]
1728
+ }, void 0, true);
1729
+ };
1730
+
1731
+ export { UsersPanel };