@fonderie/react-admin-screens 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,20 +4,49 @@ import { TemplateEditorScreen, TemplateListScreen } from "@fonderie/react-courie
4
4
  import { useState as useState5 } from "react";
5
5
 
6
6
  // src/styles.ts
7
+ var t = {
8
+ text: "var(--fonderie-text,#171717)",
9
+ muted: "var(--fonderie-text-muted,#5c5c5c)",
10
+ bg: "var(--fonderie-bg,#fafafa)",
11
+ surface: "var(--fonderie-surface,#fff)",
12
+ surfaceAlt: "var(--fonderie-surface-alt,#fafafa)",
13
+ border: "var(--fonderie-border,#e0e0e0)",
14
+ borderLight: "var(--fonderie-border-light,#f5f5f5)",
15
+ accent: "var(--fonderie-accent,#00d294)",
16
+ accentStrong: "var(--fonderie-accent-strong,#009767)",
17
+ warning: "var(--fonderie-warning,#f5a623)",
18
+ danger: "var(--fonderie-danger,#e00)",
19
+ font: 'var(--fonderie-font,Inter,"Inter Fallback",-apple-system,BlinkMacSystemFont,"Helvetica Neue",system-ui,sans-serif)',
20
+ mono: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace)',
21
+ radius: "var(--fonderie-radius,4px)",
22
+ radiusLg: "var(--fonderie-radius-lg,8px)",
23
+ trackingDisplay: "var(--fonderie-tracking-display,-0.05em)",
24
+ shadowCard: "var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))"
25
+ };
7
26
  var styles = {
8
27
  shell: {
9
28
  display: "flex",
10
29
  minHeight: "100vh",
11
- fontFamily: "system-ui, sans-serif",
12
- color: "#111"
30
+ fontFamily: t.font,
31
+ color: t.text,
32
+ background: t.bg
33
+ },
34
+ // The sidebar sits on the raised surface against the page canvas, which is
35
+ // what separates the two without a heavy rule between them.
36
+ nav: {
37
+ width: 220,
38
+ borderRight: `1px solid ${t.border}`,
39
+ padding: 16,
40
+ flexShrink: 0,
41
+ background: t.surface
13
42
  },
14
- nav: { width: 220, borderRight: "1px solid #eee", padding: 16, flexShrink: 0 },
15
43
  navGroup: {
16
44
  fontSize: 11,
17
45
  textTransform: "uppercase",
18
46
  letterSpacing: 0.6,
19
- color: "#888",
20
- margin: "16px 0 6px"
47
+ color: t.muted,
48
+ margin: "16px 0 6px",
49
+ fontWeight: 600
21
50
  },
22
51
  navItem: {
23
52
  display: "block",
@@ -25,51 +54,79 @@ var styles = {
25
54
  textAlign: "left",
26
55
  background: "none",
27
56
  border: "none",
28
- borderRadius: 6,
57
+ borderRadius: t.radius,
29
58
  padding: "6px 8px",
30
59
  cursor: "pointer",
31
60
  fontSize: 14,
32
- color: "#111"
61
+ color: t.text,
62
+ fontFamily: "inherit"
33
63
  },
34
- navItemActive: { background: "#f3f4f6", fontWeight: 600 },
64
+ navItemActive: { background: t.surfaceAlt, fontWeight: 600, color: t.accentStrong },
35
65
  main: { flex: 1, padding: 24, maxWidth: 960 },
36
66
  container: { padding: 24, maxWidth: 960 },
37
- title: { fontSize: 20, fontWeight: 700, marginTop: 0, marginBottom: 12 },
38
- subtitle: { fontSize: 15, fontWeight: 600, marginTop: 24, marginBottom: 8 },
39
- status: { padding: 12, color: "#666" },
40
- error: { color: "#e11d48", marginBottom: 12, fontSize: 14 },
41
- ok: { color: "#15803d", fontWeight: 600 },
42
- bad: { color: "#e11d48", fontWeight: 600 },
43
- advice: { color: "#b45309" },
44
- muted: { color: "#666", fontSize: 13 },
45
- mono: { fontFamily: "ui-monospace, monospace", fontSize: 13 },
67
+ title: {
68
+ fontSize: 20,
69
+ fontWeight: 600,
70
+ marginTop: 0,
71
+ marginBottom: 12,
72
+ letterSpacing: t.trackingDisplay
73
+ },
74
+ subtitle: {
75
+ fontSize: 15,
76
+ fontWeight: 600,
77
+ marginTop: 24,
78
+ marginBottom: 8,
79
+ letterSpacing: t.trackingDisplay
80
+ },
81
+ status: { padding: 12, color: t.muted },
82
+ error: { color: t.danger, marginBottom: 12, fontSize: 14 },
83
+ ok: { color: t.accentStrong, fontWeight: 600 },
84
+ bad: { color: t.danger, fontWeight: 600 },
85
+ advice: { color: t.warning },
86
+ muted: { color: t.muted, fontSize: 13 },
87
+ mono: { fontFamily: t.mono, fontSize: 13 },
46
88
  table: { width: "100%", borderCollapse: "collapse", fontSize: 14 },
47
89
  th: {
48
90
  textAlign: "left",
49
- borderBottom: "1px solid #ddd",
91
+ borderBottom: `1px solid ${t.border}`,
50
92
  padding: "6px 8px",
51
93
  fontWeight: 600,
52
- color: "#444"
94
+ color: t.muted
53
95
  },
54
- td: { borderBottom: "1px solid #eee", padding: "6px 8px", verticalAlign: "top" },
96
+ td: { borderBottom: `1px solid ${t.borderLight}`, padding: "6px 8px", verticalAlign: "top" },
55
97
  list: { listStyle: "none", padding: 0, margin: 0 },
56
- row: { borderBottom: "1px solid #eee", padding: "8px 0" },
98
+ row: { borderBottom: `1px solid ${t.borderLight}`, padding: "8px 0" },
57
99
  badge: {
58
100
  display: "inline-block",
59
101
  borderRadius: 999,
60
102
  padding: "1px 8px",
61
103
  fontSize: 12,
62
- background: "#f3f4f6"
104
+ background: t.surfaceAlt,
105
+ border: `1px solid ${t.border}`,
106
+ color: t.muted
63
107
  },
64
108
  button: {
65
- background: "none",
66
- border: "1px solid #ddd",
67
- borderRadius: 8,
109
+ background: t.surface,
110
+ border: `1px solid ${t.border}`,
111
+ borderRadius: t.radius,
68
112
  padding: "4px 10px",
69
113
  cursor: "pointer",
70
- fontSize: 13
114
+ fontSize: 13,
115
+ color: t.text,
116
+ fontFamily: "inherit",
117
+ boxShadow: t.shadowCard
118
+ },
119
+ toolbar: { display: "flex", gap: 8, alignItems: "center", marginBottom: 12 },
120
+ // Surfaces the screens compose themselves, kept here so a card looks the
121
+ // same on every page rather than being re-invented per screen.
122
+ card: {
123
+ background: t.surface,
124
+ border: `1px solid ${t.border}`,
125
+ borderRadius: t.radiusLg,
126
+ padding: 16,
127
+ boxShadow: t.shadowCard
71
128
  },
72
- toolbar: { display: "flex", gap: 8, alignItems: "center", marginBottom: 12 }
129
+ accent: { color: t.accent }
73
130
  };
74
131
 
75
132
  // src/screens/AdminLogScreen.tsx
@@ -307,10 +364,74 @@ function RoutesScreen({ client }) {
307
364
  ] });
308
365
  }
309
366
 
367
+ // src/screens/MigrationsScreen.tsx
368
+ import { useAdminMigrations } from "@fonderie/react-admin";
369
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
370
+ function why(m, everApplied) {
371
+ if (m.pending.length === 0) return null;
372
+ if (m.blockedBy) return `Apply "${m.blockedBy}" first \u2014 it runs before this one and is behind.`;
373
+ if (everApplied && m.pending.some((p) => p.impact === "destructive"))
374
+ return "Contains a migration that deletes data. No down-migration brings it back \u2014 apply this one through CI or `npm run migrate`.";
375
+ return null;
376
+ }
377
+ function MigrationsScreen({ client }) {
378
+ const { report, isLoading, error, refresh, apply } = useAdminMigrations(client);
379
+ const behind = report?.modules.filter((m) => m.pending.length > 0) ?? [];
380
+ return /* @__PURE__ */ jsxs7("div", { style: styles.container, children: [
381
+ /* @__PURE__ */ jsx7("h1", { style: styles.title, children: "Migrations" }),
382
+ error ? /* @__PURE__ */ jsx7("p", { style: styles.error, role: "alert", children: error.status === 403 ? "Applying migrations needs a token with the write scope." : error.explanation }) : null,
383
+ /* @__PURE__ */ jsxs7("p", { children: [
384
+ /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => void refresh(), disabled: isLoading, children: isLoading ? "Checking\u2026" : "Refresh" }),
385
+ " ",
386
+ report && !report.everApplied ? /* @__PURE__ */ jsx7("span", { style: styles.advice, children: "This database has never been migrated \u2014 treating it as a first install, so nothing is held back." }) : null
387
+ ] }),
388
+ report && behind.length === 0 ? /* @__PURE__ */ jsx7("p", { style: styles.ok, children: "Every module is up to date." }) : null,
389
+ behind.map((m) => {
390
+ const blocked = why(m, report?.everApplied ?? false);
391
+ const files = m.pending.map((p) => p.file);
392
+ return /* @__PURE__ */ jsxs7("section", { style: { marginBottom: 24 }, children: [
393
+ /* @__PURE__ */ jsxs7("h2", { style: styles.subtitle, children: [
394
+ m.name,
395
+ " \u2014 ",
396
+ m.pending.length,
397
+ " pending"
398
+ ] }),
399
+ /* @__PURE__ */ jsx7("ul", { children: m.pending.map((p) => /* @__PURE__ */ jsxs7("li", { children: [
400
+ /* @__PURE__ */ jsx7("code", { children: p.file }),
401
+ " ",
402
+ p.impact === "destructive" ? /* @__PURE__ */ jsx7("span", { style: styles.bad, children: "destructive" }) : /* @__PURE__ */ jsx7("span", { style: styles.advice, children: "additive" }),
403
+ p.destructive.length > 0 ? /* @__PURE__ */ jsx7("ul", { children: p.destructive.map((s) => /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsx7("code", { children: s.slice(0, 120) }) }, s)) }) : null
404
+ ] }, p.file)) }),
405
+ blocked ? /* @__PURE__ */ jsx7("p", { style: styles.advice, children: blocked }) : /* @__PURE__ */ jsxs7(
406
+ "button",
407
+ {
408
+ type: "button",
409
+ style: styles.button,
410
+ disabled: isLoading || !m.appliable,
411
+ onClick: () => {
412
+ if (window.confirm(
413
+ `Apply ${m.pending.length} migration(s) to "${m.name}"? This changes the database schema.`
414
+ ))
415
+ void apply(m.name, files).catch(() => {
416
+ });
417
+ },
418
+ children: [
419
+ "Apply ",
420
+ m.pending.length,
421
+ " migration",
422
+ m.pending.length === 1 ? "" : "s"
423
+ ]
424
+ }
425
+ )
426
+ ] }, m.name);
427
+ })
428
+ ] });
429
+ }
430
+
310
431
  // src/screens/TokensScreen.tsx
311
432
  import { useAdminTokens } from "@fonderie/react-admin";
312
433
  import { useState } from "react";
313
- import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
434
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
314
435
  var ALL = ["read", "write", "secrets"];
315
436
  function TokensScreen({ client }) {
316
437
  const { report, isLoading, error, issue, revoke } = useAdminTokens(client);
@@ -319,25 +440,25 @@ function TokensScreen({ client }) {
319
440
  const [days, setDays] = useState("");
320
441
  const [minted, setMinted] = useState(null);
321
442
  const toggle = (s) => setScopes((prev) => prev.includes(s) ? prev.filter((x) => x !== s) : [...prev, s]);
322
- return /* @__PURE__ */ jsxs7("div", { style: styles.container, children: [
323
- /* @__PURE__ */ jsx7("h1", { style: styles.title, children: "Access" }),
324
- error ? /* @__PURE__ */ jsx7("p", { style: styles.error, role: "alert", children: error.status === 401 ? "Issuing and revoking need the root token (the one in your deployment config)." : error.explanation }) : null,
325
- /* @__PURE__ */ jsx7("h2", { style: styles.subtitle, children: "Root token" }),
326
- report ? /* @__PURE__ */ jsxs7("p", { children: [
327
- report.admin.ok ? /* @__PURE__ */ jsx7("span", { style: styles.ok, children: "strong" }) : /* @__PURE__ */ jsx7("span", { style: styles.bad, children: "weak" }),
328
- report.admin.problems.map((p) => /* @__PURE__ */ jsx7("div", { style: styles.bad, children: p.message }, p.message))
443
+ return /* @__PURE__ */ jsxs8("div", { style: styles.container, children: [
444
+ /* @__PURE__ */ jsx8("h1", { style: styles.title, children: "Access" }),
445
+ error ? /* @__PURE__ */ jsx8("p", { style: styles.error, role: "alert", children: error.status === 401 ? "Issuing and revoking need the root token (the one in your deployment config)." : error.explanation }) : null,
446
+ /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Root token" }),
447
+ report ? /* @__PURE__ */ jsxs8("p", { children: [
448
+ report.admin.ok ? /* @__PURE__ */ jsx8("span", { style: styles.ok, children: "strong" }) : /* @__PURE__ */ jsx8("span", { style: styles.bad, children: "weak" }),
449
+ report.admin.problems.map((p) => /* @__PURE__ */ jsx8("div", { style: styles.bad, children: p.message }, p.message))
329
450
  ] }) : null,
330
- /* @__PURE__ */ jsx7("h2", { style: styles.subtitle, children: "Issued tokens" }),
331
- report?.issued === null ? /* @__PURE__ */ jsx7("p", { style: styles.muted, children: "Issuing is off \u2014 give AdminModule a store and run its migrations." }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
332
- minted ? /* @__PURE__ */ jsxs7("p", { style: styles.ok, children: [
451
+ /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Issued tokens" }),
452
+ report?.issued === null ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "Issuing is off \u2014 give AdminModule a store and run its migrations." }) : /* @__PURE__ */ jsxs8(Fragment4, { children: [
453
+ minted ? /* @__PURE__ */ jsxs8("p", { style: styles.ok, children: [
333
454
  "Copy this now \u2014 it is never shown again.",
334
455
  " ",
335
- /* @__PURE__ */ jsx7("span", { style: styles.mono, children: minted.token }),
456
+ /* @__PURE__ */ jsx8("span", { style: styles.mono, children: minted.token }),
336
457
  " (",
337
458
  minted.name,
338
459
  ")"
339
460
  ] }) : null,
340
- /* @__PURE__ */ jsxs7(
461
+ /* @__PURE__ */ jsxs8(
341
462
  "form",
342
463
  {
343
464
  style: styles.toolbar,
@@ -348,15 +469,15 @@ function TokensScreen({ client }) {
348
469
  name: name.trim(),
349
470
  scopes,
350
471
  ...days && Number.isInteger(d) && d > 0 ? { expiresInDays: d } : {}
351
- }).then((t) => {
352
- setMinted({ name: t.name, token: t.token });
472
+ }).then((t2) => {
473
+ setMinted({ name: t2.name, token: t2.token });
353
474
  setName("");
354
475
  setDays("");
355
476
  }).catch(() => {
356
477
  });
357
478
  },
358
479
  children: [
359
- /* @__PURE__ */ jsx7(
480
+ /* @__PURE__ */ jsx8(
360
481
  "input",
361
482
  {
362
483
  value: name,
@@ -366,12 +487,12 @@ function TokensScreen({ client }) {
366
487
  "aria-label": "Name"
367
488
  }
368
489
  ),
369
- ALL.map((s) => /* @__PURE__ */ jsxs7("label", { style: { ...styles.badge, cursor: "pointer" }, children: [
370
- /* @__PURE__ */ jsx7("input", { type: "checkbox", checked: scopes.includes(s), onChange: () => toggle(s) }),
490
+ ALL.map((s) => /* @__PURE__ */ jsxs8("label", { style: { ...styles.badge, cursor: "pointer" }, children: [
491
+ /* @__PURE__ */ jsx8("input", { type: "checkbox", checked: scopes.includes(s), onChange: () => toggle(s) }),
371
492
  " ",
372
493
  s
373
494
  ] }, s)),
374
- /* @__PURE__ */ jsx7(
495
+ /* @__PURE__ */ jsx8(
375
496
  "input",
376
497
  {
377
498
  value: days,
@@ -381,7 +502,7 @@ function TokensScreen({ client }) {
381
502
  "aria-label": "Days"
382
503
  }
383
504
  ),
384
- /* @__PURE__ */ jsx7(
505
+ /* @__PURE__ */ jsx8(
385
506
  "button",
386
507
  {
387
508
  type: "submit",
@@ -393,51 +514,51 @@ function TokensScreen({ client }) {
393
514
  ]
394
515
  }
395
516
  ),
396
- report?.issued && report.issued.length > 0 ? /* @__PURE__ */ jsxs7("table", { style: styles.table, children: [
397
- /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs7("tr", { children: [
398
- /* @__PURE__ */ jsx7("th", { style: styles.th, children: "Name" }),
399
- /* @__PURE__ */ jsx7("th", { style: styles.th, children: "Scopes" }),
400
- /* @__PURE__ */ jsx7("th", { style: styles.th, children: "Created" }),
401
- /* @__PURE__ */ jsx7("th", { style: styles.th, children: "Expires" }),
402
- /* @__PURE__ */ jsx7("th", { style: styles.th, children: "Last used" }),
403
- /* @__PURE__ */ jsx7("th", { style: styles.th })
517
+ report?.issued && report.issued.length > 0 ? /* @__PURE__ */ jsxs8("table", { style: styles.table, children: [
518
+ /* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
519
+ /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Name" }),
520
+ /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Scopes" }),
521
+ /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Created" }),
522
+ /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Expires" }),
523
+ /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Last used" }),
524
+ /* @__PURE__ */ jsx8("th", { style: styles.th })
404
525
  ] }) }),
405
- /* @__PURE__ */ jsx7("tbody", { children: report.issued.map((t) => /* @__PURE__ */ jsxs7("tr", { children: [
406
- /* @__PURE__ */ jsxs7("td", { style: styles.td, children: [
407
- t.name,
408
- t.revokedAt ? /* @__PURE__ */ jsx7("span", { style: styles.badge, children: " revoked" }) : null
526
+ /* @__PURE__ */ jsx8("tbody", { children: report.issued.map((t2) => /* @__PURE__ */ jsxs8("tr", { children: [
527
+ /* @__PURE__ */ jsxs8("td", { style: styles.td, children: [
528
+ t2.name,
529
+ t2.revokedAt ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: " revoked" }) : null
409
530
  ] }),
410
- /* @__PURE__ */ jsx7("td", { style: { ...styles.td, ...styles.mono }, children: t.scopes.join(", ") }),
411
- /* @__PURE__ */ jsxs7("td", { style: { ...styles.td, ...styles.muted }, children: [
412
- new Date(t.createdAt).toLocaleDateString(),
531
+ /* @__PURE__ */ jsx8("td", { style: { ...styles.td, ...styles.mono }, children: t2.scopes.join(", ") }),
532
+ /* @__PURE__ */ jsxs8("td", { style: { ...styles.td, ...styles.muted }, children: [
533
+ new Date(t2.createdAt).toLocaleDateString(),
413
534
  " \xB7 ",
414
- t.createdBy
535
+ t2.createdBy
415
536
  ] }),
416
- /* @__PURE__ */ jsx7("td", { style: { ...styles.td, ...styles.muted }, children: t.expiresAt ? new Date(t.expiresAt).toLocaleDateString() : "never" }),
417
- /* @__PURE__ */ jsx7("td", { style: { ...styles.td, ...styles.muted }, children: t.lastUsedAt ? new Date(t.lastUsedAt).toLocaleString() : "never" }),
418
- /* @__PURE__ */ jsx7("td", { style: styles.td, children: t.revokedAt ? null : /* @__PURE__ */ jsx7(
537
+ /* @__PURE__ */ jsx8("td", { style: { ...styles.td, ...styles.muted }, children: t2.expiresAt ? new Date(t2.expiresAt).toLocaleDateString() : "never" }),
538
+ /* @__PURE__ */ jsx8("td", { style: { ...styles.td, ...styles.muted }, children: t2.lastUsedAt ? new Date(t2.lastUsedAt).toLocaleString() : "never" }),
539
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: t2.revokedAt ? null : /* @__PURE__ */ jsx8(
419
540
  "button",
420
541
  {
421
542
  type: "button",
422
543
  style: styles.button,
423
544
  onClick: () => {
424
545
  if (window.confirm(
425
- `Revoke "${t.name}"? Anything using it stops working immediately.`
546
+ `Revoke "${t2.name}"? Anything using it stops working immediately.`
426
547
  ))
427
- void revoke(t.id).catch(() => {
548
+ void revoke(t2.id).catch(() => {
428
549
  });
429
550
  },
430
551
  children: "Revoke"
431
552
  }
432
553
  ) })
433
- ] }, t.id)) })
434
- ] }) : /* @__PURE__ */ jsx7("p", { style: styles.muted, children: "None issued." })
554
+ ] }, t2.id)) })
555
+ ] }) : /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "None issued." })
435
556
  ] }),
436
- /* @__PURE__ */ jsx7("h2", { style: styles.subtitle, children: "Legacy per-brick tokens" }),
437
- report && report.legacy.length === 0 ? /* @__PURE__ */ jsx7("p", { style: styles.muted, children: "None \u2014 every brick's admin surface goes through this token." }) : /* @__PURE__ */ jsx7("ul", { style: styles.list, children: report?.legacy.map((l) => /* @__PURE__ */ jsxs7("li", { style: styles.row, children: [
438
- /* @__PURE__ */ jsx7("span", { style: styles.mono, children: l.module }),
557
+ /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Legacy per-brick tokens" }),
558
+ report && report.legacy.length === 0 ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "None \u2014 every brick's admin surface goes through this token." }) : /* @__PURE__ */ jsx8("ul", { style: styles.list, children: report?.legacy.map((l) => /* @__PURE__ */ jsxs8("li", { style: styles.row, children: [
559
+ /* @__PURE__ */ jsx8("span", { style: styles.mono, children: l.module }),
439
560
  " ",
440
- /* @__PURE__ */ jsx7("span", { style: styles.muted, children: "still registers its standalone routes with its own token (deprecated)" })
561
+ /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "still registers its standalone routes with its own token (deprecated)" })
441
562
  ] }, l.module)) })
442
563
  ] });
443
564
  }
@@ -450,7 +571,7 @@ import {
450
571
  useAdminUsers
451
572
  } from "@fonderie/react-admin";
452
573
  import { useState as useState2 } from "react";
453
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
574
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
454
575
  function UsersScreen({ client, pageSize = 50 }) {
455
576
  const [input, setInput] = useState2("");
456
577
  const [selected, setSelected] = useState2(null);
@@ -462,14 +583,14 @@ function UsersScreen({ client, pageSize = 50 }) {
462
583
  const userId = user?.id ?? null;
463
584
  const sessions = useAdminUserSessions(client, userId);
464
585
  const history = useAdminLoginHistory(client, userId, { limit: 20 });
465
- const yesNo = (v) => v ? /* @__PURE__ */ jsx8("span", { style: styles.ok, children: "yes" }) : /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "no" });
586
+ const yesNo = (v) => v ? /* @__PURE__ */ jsx9("span", { style: styles.ok, children: "yes" }) : /* @__PURE__ */ jsx9("span", { style: styles.muted, children: "no" });
466
587
  const clear = () => {
467
588
  setSelected(null);
468
589
  setInput("");
469
590
  };
470
- return /* @__PURE__ */ jsxs8("div", { style: styles.container, children: [
471
- /* @__PURE__ */ jsx8("h1", { style: styles.title, children: "Users" }),
472
- /* @__PURE__ */ jsxs8(
591
+ return /* @__PURE__ */ jsxs9("div", { style: styles.container, children: [
592
+ /* @__PURE__ */ jsx9("h1", { style: styles.title, children: "Users" }),
593
+ /* @__PURE__ */ jsxs9(
473
594
  "form",
474
595
  {
475
596
  style: styles.toolbar,
@@ -479,7 +600,7 @@ function UsersScreen({ client, pageSize = 50 }) {
479
600
  setSelected(email ? { email } : null);
480
601
  },
481
602
  children: [
482
- /* @__PURE__ */ jsx8(
603
+ /* @__PURE__ */ jsx9(
483
604
  "input",
484
605
  {
485
606
  type: "email",
@@ -490,8 +611,8 @@ function UsersScreen({ client, pageSize = 50 }) {
490
611
  "aria-label": "Email"
491
612
  }
492
613
  ),
493
- /* @__PURE__ */ jsx8("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Look up" }),
494
- selected ? /* @__PURE__ */ jsx8("button", { type: "button", style: styles.button, onClick: clear, children: "\u2190 All users" }) : /* @__PURE__ */ jsx8(
614
+ /* @__PURE__ */ jsx9("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Look up" }),
615
+ selected ? /* @__PURE__ */ jsx9("button", { type: "button", style: styles.button, onClick: clear, children: "\u2190 All users" }) : /* @__PURE__ */ jsx9(
495
616
  "button",
496
617
  {
497
618
  type: "button",
@@ -504,18 +625,18 @@ function UsersScreen({ client, pageSize = 50 }) {
504
625
  ]
505
626
  }
506
627
  ),
507
- error ? /* @__PURE__ */ jsx8("p", { style: styles.error, role: "alert", children: error.status === 404 ? "No user with that email." : error.explanation }) : null,
508
- !selected ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
509
- list.error ? /* @__PURE__ */ jsx8("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
510
- list.users.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "No users yet." }) : /* @__PURE__ */ jsxs8("table", { style: styles.table, children: [
511
- /* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
512
- /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Email" }),
513
- /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Name" }),
514
- /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Created" }),
515
- /* @__PURE__ */ jsx8("th", { style: styles.th, children: "Status" })
628
+ error ? /* @__PURE__ */ jsx9("p", { style: styles.error, role: "alert", children: error.status === 404 ? "No user with that email." : error.explanation }) : null,
629
+ !selected ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
630
+ list.error ? /* @__PURE__ */ jsx9("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
631
+ list.users.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx9("p", { style: styles.muted, children: "No users yet." }) : /* @__PURE__ */ jsxs9("table", { style: styles.table, children: [
632
+ /* @__PURE__ */ jsx9("thead", { children: /* @__PURE__ */ jsxs9("tr", { children: [
633
+ /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Email" }),
634
+ /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Name" }),
635
+ /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Created" }),
636
+ /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Status" })
516
637
  ] }) }),
517
- /* @__PURE__ */ jsx8("tbody", { children: list.users.map((u) => /* @__PURE__ */ jsxs8("tr", { children: [
518
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: /* @__PURE__ */ jsx8(
638
+ /* @__PURE__ */ jsx9("tbody", { children: list.users.map((u) => /* @__PURE__ */ jsxs9("tr", { children: [
639
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: /* @__PURE__ */ jsx9(
519
640
  "button",
520
641
  {
521
642
  type: "button",
@@ -524,17 +645,17 @@ function UsersScreen({ client, pageSize = 50 }) {
524
645
  children: u.email
525
646
  }
526
647
  ) }),
527
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: `${u.firstName ?? ""} ${u.lastName ?? ""}`.trim() || /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "\u2014" }) }),
528
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: new Date(u.createdAt).toLocaleDateString() }),
529
- /* @__PURE__ */ jsxs8("td", { style: styles.td, children: [
530
- u.suspended ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: "suspended" }) : null,
531
- u.deletedAt ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: "deleted" }) : null,
532
- !u.suspended && !u.deletedAt ? /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "active" }) : null
648
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: `${u.firstName ?? ""} ${u.lastName ?? ""}`.trim() || /* @__PURE__ */ jsx9("span", { style: styles.muted, children: "\u2014" }) }),
649
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: new Date(u.createdAt).toLocaleDateString() }),
650
+ /* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
651
+ u.suspended ? /* @__PURE__ */ jsx9("span", { style: styles.badge, children: "suspended" }) : null,
652
+ u.deletedAt ? /* @__PURE__ */ jsx9("span", { style: styles.badge, children: "deleted" }) : null,
653
+ !u.suspended && !u.deletedAt ? /* @__PURE__ */ jsx9("span", { style: styles.muted, children: "active" }) : null
533
654
  ] })
534
655
  ] }, u.id)) })
535
656
  ] }),
536
- list.isLoading ? /* @__PURE__ */ jsx8("p", { style: styles.status, children: "Loading\u2026" }) : null,
537
- list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx8(
657
+ list.isLoading ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: "Loading\u2026" }) : null,
658
+ list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx9(
538
659
  "button",
539
660
  {
540
661
  type: "button",
@@ -544,48 +665,48 @@ function UsersScreen({ client, pageSize = 50 }) {
544
665
  }
545
666
  ) : null
546
667
  ] }) : null,
547
- user ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
548
- /* @__PURE__ */ jsxs8("h2", { style: styles.subtitle, children: [
668
+ user ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
669
+ /* @__PURE__ */ jsxs9("h2", { style: styles.subtitle, children: [
549
670
  user.firstName || user.lastName ? `${user.firstName} ${user.lastName}`.trim() : user.email,
550
671
  " ",
551
- user.suspended ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: "suspended" }) : null,
552
- user.deletedAt ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: "deleted" }) : null
672
+ user.suspended ? /* @__PURE__ */ jsx9("span", { style: styles.badge, children: "suspended" }) : null,
673
+ user.deletedAt ? /* @__PURE__ */ jsx9("span", { style: styles.badge, children: "deleted" }) : null
553
674
  ] }),
554
- /* @__PURE__ */ jsx8("table", { style: styles.table, children: /* @__PURE__ */ jsxs8("tbody", { children: [
555
- /* @__PURE__ */ jsxs8("tr", { children: [
556
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: "id" }),
557
- /* @__PURE__ */ jsx8("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
675
+ /* @__PURE__ */ jsx9("table", { style: styles.table, children: /* @__PURE__ */ jsxs9("tbody", { children: [
676
+ /* @__PURE__ */ jsxs9("tr", { children: [
677
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: "id" }),
678
+ /* @__PURE__ */ jsx9("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
558
679
  ] }),
559
- /* @__PURE__ */ jsxs8("tr", { children: [
560
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: "email" }),
561
- /* @__PURE__ */ jsxs8("td", { style: styles.td, children: [
680
+ /* @__PURE__ */ jsxs9("tr", { children: [
681
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: "email" }),
682
+ /* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
562
683
  user.email,
563
684
  " \xB7 verified ",
564
685
  yesNo(user.isEmailVerified)
565
686
  ] })
566
687
  ] }),
567
- /* @__PURE__ */ jsxs8("tr", { children: [
568
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: "MFA" }),
569
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
688
+ /* @__PURE__ */ jsxs9("tr", { children: [
689
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: "MFA" }),
690
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
570
691
  ] }),
571
- /* @__PURE__ */ jsxs8("tr", { children: [
572
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: "provider" }),
573
- /* @__PURE__ */ jsxs8("td", { style: styles.td, children: [
692
+ /* @__PURE__ */ jsxs9("tr", { children: [
693
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: "provider" }),
694
+ /* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
574
695
  user.provider || "password",
575
696
  user.hasPassword ? "" : " \xB7 no password set"
576
697
  ] })
577
698
  ] }),
578
- /* @__PURE__ */ jsxs8("tr", { children: [
579
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: "last login" }),
580
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: user.lastLogin ? new Date(user.lastLogin).toLocaleString() : /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "never" }) })
699
+ /* @__PURE__ */ jsxs9("tr", { children: [
700
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: "last login" }),
701
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: user.lastLogin ? new Date(user.lastLogin).toLocaleString() : /* @__PURE__ */ jsx9("span", { style: styles.muted, children: "never" }) })
581
702
  ] }),
582
- /* @__PURE__ */ jsxs8("tr", { children: [
583
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: "created" }),
584
- /* @__PURE__ */ jsx8("td", { style: styles.td, children: new Date(user.createdAt).toLocaleString() })
703
+ /* @__PURE__ */ jsxs9("tr", { children: [
704
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: "created" }),
705
+ /* @__PURE__ */ jsx9("td", { style: styles.td, children: new Date(user.createdAt).toLocaleString() })
585
706
  ] })
586
707
  ] }) }),
587
- /* @__PURE__ */ jsxs8("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
588
- user.suspended ? /* @__PURE__ */ jsx8(
708
+ /* @__PURE__ */ jsxs9("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
709
+ user.suspended ? /* @__PURE__ */ jsx9(
589
710
  "button",
590
711
  {
591
712
  type: "button",
@@ -594,7 +715,7 @@ function UsersScreen({ client, pageSize = 50 }) {
594
715
  disabled: isLoading,
595
716
  children: "Unsuspend"
596
717
  }
597
- ) : /* @__PURE__ */ jsx8(
718
+ ) : /* @__PURE__ */ jsx9(
598
719
  "button",
599
720
  {
600
721
  type: "button",
@@ -604,7 +725,7 @@ function UsersScreen({ client, pageSize = 50 }) {
604
725
  children: "Suspend"
605
726
  }
606
727
  ),
607
- /* @__PURE__ */ jsx8(
728
+ /* @__PURE__ */ jsx9(
608
729
  "button",
609
730
  {
610
731
  type: "button",
@@ -615,26 +736,26 @@ function UsersScreen({ client, pageSize = 50 }) {
615
736
  }
616
737
  )
617
738
  ] }),
618
- /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Live sessions" }),
619
- sessions.sessions.length === 0 ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "None." }) : /* @__PURE__ */ jsx8("ul", { style: styles.list, children: sessions.sessions.map((s) => /* @__PURE__ */ jsxs8("li", { style: styles.row, children: [
620
- /* @__PURE__ */ jsx8("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
739
+ /* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: "Live sessions" }),
740
+ sessions.sessions.length === 0 ? /* @__PURE__ */ jsx9("p", { style: styles.muted, children: "None." }) : /* @__PURE__ */ jsx9("ul", { style: styles.list, children: sessions.sessions.map((s) => /* @__PURE__ */ jsxs9("li", { style: styles.row, children: [
741
+ /* @__PURE__ */ jsx9("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
621
742
  " ",
622
- /* @__PURE__ */ jsx8("span", { style: styles.muted, children: s.userAgent ?? "" }),
743
+ /* @__PURE__ */ jsx9("span", { style: styles.muted, children: s.userAgent ?? "" }),
623
744
  " ",
624
- /* @__PURE__ */ jsxs8("span", { style: styles.muted, children: [
745
+ /* @__PURE__ */ jsxs9("span", { style: styles.muted, children: [
625
746
  "since ",
626
747
  new Date(s.createdAt).toLocaleString()
627
748
  ] })
628
749
  ] }, s.id)) }),
629
- /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Recent sign-ins" }),
630
- history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "None recorded." }) : /* @__PURE__ */ jsx8("ul", { style: styles.list, children: history.events.map((e) => /* @__PURE__ */ jsxs8("li", { style: styles.row, children: [
631
- /* @__PURE__ */ jsx8("span", { style: e.outcome === "success" ? styles.ok : styles.bad, children: e.outcome }),
750
+ /* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: "Recent sign-ins" }),
751
+ history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ jsx9("p", { style: styles.muted, children: "None recorded." }) : /* @__PURE__ */ jsx9("ul", { style: styles.list, children: history.events.map((e) => /* @__PURE__ */ jsxs9("li", { style: styles.row, children: [
752
+ /* @__PURE__ */ jsx9("span", { style: e.outcome === "success" ? styles.ok : styles.bad, children: e.outcome }),
632
753
  " ",
633
- /* @__PURE__ */ jsx8("span", { style: styles.muted, children: e.method }),
754
+ /* @__PURE__ */ jsx9("span", { style: styles.muted, children: e.method }),
634
755
  " ",
635
- /* @__PURE__ */ jsx8("span", { style: styles.muted, children: new Date(e.createdAt).toLocaleString() })
756
+ /* @__PURE__ */ jsx9("span", { style: styles.muted, children: new Date(e.createdAt).toLocaleString() })
636
757
  ] }, e.id)) }),
637
- history.hasMore && !history.isLoading ? /* @__PURE__ */ jsx8(
758
+ history.hasMore && !history.isLoading ? /* @__PURE__ */ jsx9(
638
759
  "button",
639
760
  {
640
761
  type: "button",
@@ -649,14 +770,14 @@ function UsersScreen({ client, pageSize = 50 }) {
649
770
 
650
771
  // src/screens/CatalogScreen.tsx
651
772
  import { useAdminCatalog } from "@fonderie/react-admin";
652
- import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
773
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
653
774
  function CatalogScreen({ client }) {
654
775
  const { catalog, isLoading, error, refresh, deletePlan } = useAdminCatalog(client);
655
776
  const money = (v) => v == null ? "\u2014" : (v / 100).toFixed(2);
656
- return /* @__PURE__ */ jsxs9("div", { style: styles.container, children: [
657
- /* @__PURE__ */ jsxs9("div", { style: styles.toolbar, children: [
658
- /* @__PURE__ */ jsx9("h1", { style: { ...styles.title, marginBottom: 0 }, children: "Catalog" }),
659
- /* @__PURE__ */ jsx9(
777
+ return /* @__PURE__ */ jsxs10("div", { style: styles.container, children: [
778
+ /* @__PURE__ */ jsxs10("div", { style: styles.toolbar, children: [
779
+ /* @__PURE__ */ jsx10("h1", { style: { ...styles.title, marginBottom: 0 }, children: "Catalog" }),
780
+ /* @__PURE__ */ jsx10(
660
781
  "button",
661
782
  {
662
783
  type: "button",
@@ -667,37 +788,37 @@ function CatalogScreen({ client }) {
667
788
  }
668
789
  )
669
790
  ] }),
670
- error ? /* @__PURE__ */ jsx9("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
671
- isLoading && !catalog ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: "Loading\u2026" }) : null,
672
- catalog ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
673
- /* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: "Configured (code)" }),
674
- /* @__PURE__ */ jsx9("pre", { style: { ...styles.mono, background: "#f9fafb", padding: 12, overflowX: "auto" }, children: JSON.stringify(catalog.configured, null, 2) }),
675
- /* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: "Stored (database)" }),
676
- catalog.stored.length === 0 ? /* @__PURE__ */ jsx9("p", { style: styles.muted, children: "No stored plans." }) : /* @__PURE__ */ jsxs9("table", { style: styles.table, children: [
677
- /* @__PURE__ */ jsx9("thead", { children: /* @__PURE__ */ jsxs9("tr", { children: [
678
- /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Plan" }),
679
- /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Tier" }),
680
- /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Seats" }),
681
- /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Monthly" }),
682
- /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Yearly" }),
683
- /* @__PURE__ */ jsx9("th", { style: styles.th, children: "Trial" }),
684
- /* @__PURE__ */ jsx9("th", { style: styles.th })
791
+ error ? /* @__PURE__ */ jsx10("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
792
+ isLoading && !catalog ? /* @__PURE__ */ jsx10("p", { style: styles.status, children: "Loading\u2026" }) : null,
793
+ catalog ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
794
+ /* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Configured (code)" }),
795
+ /* @__PURE__ */ jsx10("pre", { style: { ...styles.mono, background: "var(--fonderie-surface-alt,#fafafa)", padding: 12, overflowX: "auto" }, children: JSON.stringify(catalog.configured, null, 2) }),
796
+ /* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Stored (database)" }),
797
+ catalog.stored.length === 0 ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "No stored plans." }) : /* @__PURE__ */ jsxs10("table", { style: styles.table, children: [
798
+ /* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
799
+ /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Plan" }),
800
+ /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Tier" }),
801
+ /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Seats" }),
802
+ /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Monthly" }),
803
+ /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Yearly" }),
804
+ /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Trial" }),
805
+ /* @__PURE__ */ jsx10("th", { style: styles.th })
685
806
  ] }) }),
686
- /* @__PURE__ */ jsx9("tbody", { children: catalog.stored.map((p) => /* @__PURE__ */ jsxs9("tr", { children: [
687
- /* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
688
- /* @__PURE__ */ jsx9("strong", { children: p.name }),
689
- p.description ? /* @__PURE__ */ jsx9("div", { style: styles.muted, children: p.description }) : null
807
+ /* @__PURE__ */ jsx10("tbody", { children: catalog.stored.map((p) => /* @__PURE__ */ jsxs10("tr", { children: [
808
+ /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
809
+ /* @__PURE__ */ jsx10("strong", { children: p.name }),
810
+ p.description ? /* @__PURE__ */ jsx10("div", { style: styles.muted, children: p.description }) : null
690
811
  ] }),
691
- /* @__PURE__ */ jsx9("td", { style: styles.td, children: p.tier }),
692
- /* @__PURE__ */ jsx9("td", { style: styles.td, children: p.seats ?? "\u221E" }),
693
- /* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
812
+ /* @__PURE__ */ jsx10("td", { style: styles.td, children: p.tier }),
813
+ /* @__PURE__ */ jsx10("td", { style: styles.td, children: p.seats ?? "\u221E" }),
814
+ /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
694
815
  money(p.pricing?.monthly),
695
816
  " ",
696
817
  p.pricing?.currency ?? ""
697
818
  ] }),
698
- /* @__PURE__ */ jsx9("td", { style: styles.td, children: money(p.pricing?.yearly) }),
699
- /* @__PURE__ */ jsx9("td", { style: styles.td, children: p.trialDays ? `${p.trialDays} d` : "\u2014" }),
700
- /* @__PURE__ */ jsx9("td", { style: styles.td, children: /* @__PURE__ */ jsx9(
819
+ /* @__PURE__ */ jsx10("td", { style: styles.td, children: money(p.pricing?.yearly) }),
820
+ /* @__PURE__ */ jsx10("td", { style: styles.td, children: p.trialDays ? `${p.trialDays} d` : "\u2014" }),
821
+ /* @__PURE__ */ jsx10("td", { style: styles.td, children: /* @__PURE__ */ jsx10(
701
822
  "button",
702
823
  {
703
824
  type: "button",
@@ -719,7 +840,7 @@ function CatalogScreen({ client }) {
719
840
  // src/screens/SubscriberScreen.tsx
720
841
  import { useAdminSubscriber, useAdminSubscribers } from "@fonderie/react-admin";
721
842
  import { useState as useState3 } from "react";
722
- import { Fragment as Fragment7, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
843
+ import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
723
844
  function SubscriberScreen({ client, pageSize = 50 }) {
724
845
  const [type, setType] = useState3("user");
725
846
  const [idInput, setIdInput] = useState3("");
@@ -729,15 +850,15 @@ function SubscriberScreen({ client, pageSize = 50 }) {
729
850
  const [amount, setAmount] = useState3("");
730
851
  const [note, setNote] = useState3("");
731
852
  const [granted, setGranted] = useState3(null);
732
- const open = (t, id) => {
853
+ const open = (t2, id) => {
733
854
  setGranted(null);
734
- setType(t);
855
+ setType(t2);
735
856
  setIdInput(id);
736
- setSubscriber({ type: t, id });
857
+ setSubscriber({ type: t2, id });
737
858
  };
738
- return /* @__PURE__ */ jsxs10("div", { style: styles.container, children: [
739
- /* @__PURE__ */ jsx10("h1", { style: styles.title, children: "Subscriber" }),
740
- /* @__PURE__ */ jsxs10(
859
+ return /* @__PURE__ */ jsxs11("div", { style: styles.container, children: [
860
+ /* @__PURE__ */ jsx11("h1", { style: styles.title, children: "Subscriber" }),
861
+ /* @__PURE__ */ jsxs11(
741
862
  "form",
742
863
  {
743
864
  style: styles.toolbar,
@@ -747,7 +868,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
747
868
  setSubscriber(idInput.trim() ? { type, id: idInput.trim() } : null);
748
869
  },
749
870
  children: [
750
- /* @__PURE__ */ jsxs10(
871
+ /* @__PURE__ */ jsxs11(
751
872
  "select",
752
873
  {
753
874
  value: type,
@@ -755,12 +876,12 @@ function SubscriberScreen({ client, pageSize = 50 }) {
755
876
  style: styles.button,
756
877
  "aria-label": "Type",
757
878
  children: [
758
- /* @__PURE__ */ jsx10("option", { value: "user", children: "user" }),
759
- /* @__PURE__ */ jsx10("option", { value: "workspace", children: "workspace" })
879
+ /* @__PURE__ */ jsx11("option", { value: "user", children: "user" }),
880
+ /* @__PURE__ */ jsx11("option", { value: "workspace", children: "workspace" })
760
881
  ]
761
882
  }
762
883
  ),
763
- /* @__PURE__ */ jsx10(
884
+ /* @__PURE__ */ jsx11(
764
885
  "input",
765
886
  {
766
887
  value: idInput,
@@ -770,8 +891,8 @@ function SubscriberScreen({ client, pageSize = 50 }) {
770
891
  "aria-label": "Subscriber id"
771
892
  }
772
893
  ),
773
- /* @__PURE__ */ jsx10("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Look up" }),
774
- subscriber ? /* @__PURE__ */ jsx10(
894
+ /* @__PURE__ */ jsx11("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Look up" }),
895
+ subscriber ? /* @__PURE__ */ jsx11(
775
896
  "button",
776
897
  {
777
898
  type: "button",
@@ -783,7 +904,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
783
904
  },
784
905
  children: "\u2190 All subscribers"
785
906
  }
786
- ) : /* @__PURE__ */ jsx10(
907
+ ) : /* @__PURE__ */ jsx11(
787
908
  "button",
788
909
  {
789
910
  type: "button",
@@ -796,18 +917,18 @@ function SubscriberScreen({ client, pageSize = 50 }) {
796
917
  ]
797
918
  }
798
919
  ),
799
- error ? /* @__PURE__ */ jsx10("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
800
- !subscriber ? /* @__PURE__ */ jsxs10(Fragment7, { children: [
801
- list.error ? /* @__PURE__ */ jsx10("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
802
- list.subscriptions.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "No subscribers yet." }) : /* @__PURE__ */ jsxs10("table", { style: styles.table, children: [
803
- /* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
804
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Subscriber" }),
805
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Plan" }),
806
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Status" }),
807
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Renews" })
920
+ error ? /* @__PURE__ */ jsx11("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
921
+ !subscriber ? /* @__PURE__ */ jsxs11(Fragment7, { children: [
922
+ list.error ? /* @__PURE__ */ jsx11("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
923
+ list.subscriptions.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "No subscribers yet." }) : /* @__PURE__ */ jsxs11("table", { style: styles.table, children: [
924
+ /* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs11("tr", { children: [
925
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Subscriber" }),
926
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Plan" }),
927
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Status" }),
928
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Renews" })
808
929
  ] }) }),
809
- /* @__PURE__ */ jsx10("tbody", { children: list.subscriptions.map((s) => /* @__PURE__ */ jsxs10("tr", { children: [
810
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: /* @__PURE__ */ jsxs10(
930
+ /* @__PURE__ */ jsx11("tbody", { children: list.subscriptions.map((s) => /* @__PURE__ */ jsxs11("tr", { children: [
931
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: /* @__PURE__ */ jsxs11(
811
932
  "button",
812
933
  {
813
934
  type: "button",
@@ -820,20 +941,20 @@ function SubscriberScreen({ client, pageSize = 50 }) {
820
941
  ]
821
942
  }
822
943
  ) }),
823
- /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
824
- /* @__PURE__ */ jsx10("strong", { children: s.plan }),
944
+ /* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
945
+ /* @__PURE__ */ jsx11("strong", { children: s.plan }),
825
946
  " \xB7 ",
826
947
  s.interval
827
948
  ] }),
828
- /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
949
+ /* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
829
950
  s.status,
830
- s.cancelAtPeriodEnd ? /* @__PURE__ */ jsx10("span", { style: styles.badge, children: "cancels" }) : null
951
+ s.cancelAtPeriodEnd ? /* @__PURE__ */ jsx11("span", { style: styles.badge, children: "cancels" }) : null
831
952
  ] }),
832
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: s.currentPeriodEnd ? new Date(s.currentPeriodEnd).toLocaleDateString() : /* @__PURE__ */ jsx10("span", { style: styles.muted, children: "\u2014" }) })
953
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: s.currentPeriodEnd ? new Date(s.currentPeriodEnd).toLocaleDateString() : /* @__PURE__ */ jsx11("span", { style: styles.muted, children: "\u2014" }) })
833
954
  ] }, s.id)) })
834
955
  ] }),
835
- list.isLoading ? /* @__PURE__ */ jsx10("p", { style: styles.status, children: "Loading\u2026" }) : null,
836
- list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx10(
956
+ list.isLoading ? /* @__PURE__ */ jsx11("p", { style: styles.status, children: "Loading\u2026" }) : null,
957
+ list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx11(
837
958
  "button",
838
959
  {
839
960
  type: "button",
@@ -843,27 +964,27 @@ function SubscriberScreen({ client, pageSize = 50 }) {
843
964
  }
844
965
  ) : null
845
966
  ] }) : null,
846
- subscriber && !isLoading ? /* @__PURE__ */ jsxs10(Fragment7, { children: [
847
- /* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Subscription" }),
848
- subscription ? /* @__PURE__ */ jsx10("table", { style: styles.table, children: /* @__PURE__ */ jsxs10("tbody", { children: [
849
- /* @__PURE__ */ jsxs10("tr", { children: [
850
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: "plan" }),
851
- /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
852
- /* @__PURE__ */ jsx10("strong", { children: subscription.plan }),
967
+ subscriber && !isLoading ? /* @__PURE__ */ jsxs11(Fragment7, { children: [
968
+ /* @__PURE__ */ jsx11("h2", { style: styles.subtitle, children: "Subscription" }),
969
+ subscription ? /* @__PURE__ */ jsx11("table", { style: styles.table, children: /* @__PURE__ */ jsxs11("tbody", { children: [
970
+ /* @__PURE__ */ jsxs11("tr", { children: [
971
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: "plan" }),
972
+ /* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
973
+ /* @__PURE__ */ jsx11("strong", { children: subscription.plan }),
853
974
  " \xB7 ",
854
975
  subscription.interval
855
976
  ] })
856
977
  ] }),
857
- /* @__PURE__ */ jsxs10("tr", { children: [
858
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: "status" }),
859
- /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
978
+ /* @__PURE__ */ jsxs11("tr", { children: [
979
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: "status" }),
980
+ /* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
860
981
  subscription.status,
861
982
  subscription.cancelAtPeriodEnd ? " \xB7 cancels at period end" : ""
862
983
  ] })
863
984
  ] }),
864
- /* @__PURE__ */ jsxs10("tr", { children: [
865
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: "period" }),
866
- /* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
985
+ /* @__PURE__ */ jsxs11("tr", { children: [
986
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: "period" }),
987
+ /* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
867
988
  subscription.currentPeriodStart ? new Date(subscription.currentPeriodStart).toLocaleDateString() : "\u2014",
868
989
  " ",
869
990
  "\u2192",
@@ -871,19 +992,19 @@ function SubscriberScreen({ client, pageSize = 50 }) {
871
992
  subscription.currentPeriodEnd ? new Date(subscription.currentPeriodEnd).toLocaleDateString() : "\u2014"
872
993
  ] })
873
994
  ] }),
874
- /* @__PURE__ */ jsxs10("tr", { children: [
875
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: "provider" }),
876
- /* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.mono }, children: subscription.providerSubscriptionId ?? "\u2014" })
995
+ /* @__PURE__ */ jsxs11("tr", { children: [
996
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: "provider" }),
997
+ /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: subscription.providerSubscriptionId ?? "\u2014" })
877
998
  ] })
878
- ] }) }) : /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "No subscription." }),
879
- /* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Wallet" }),
880
- wallet ? /* @__PURE__ */ jsxs10(Fragment7, { children: [
881
- /* @__PURE__ */ jsxs10("p", { children: [
882
- /* @__PURE__ */ jsx10("strong", { children: wallet.balance }),
999
+ ] }) }) : /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "No subscription." }),
1000
+ /* @__PURE__ */ jsx11("h2", { style: styles.subtitle, children: "Wallet" }),
1001
+ wallet ? /* @__PURE__ */ jsxs11(Fragment7, { children: [
1002
+ /* @__PURE__ */ jsxs11("p", { children: [
1003
+ /* @__PURE__ */ jsx11("strong", { children: wallet.balance }),
883
1004
  " ",
884
1005
  wallet.currency,
885
1006
  " ",
886
- /* @__PURE__ */ jsxs10("span", { style: styles.muted, children: [
1007
+ /* @__PURE__ */ jsxs11("span", { style: styles.muted, children: [
887
1008
  "(granted ",
888
1009
  wallet.granted ?? "0",
889
1010
  " \xB7 purchased ",
@@ -892,7 +1013,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
892
1013
  wallet.precision
893
1014
  ] })
894
1015
  ] }),
895
- /* @__PURE__ */ jsxs10(
1016
+ /* @__PURE__ */ jsxs11(
896
1017
  "form",
897
1018
  {
898
1019
  style: styles.toolbar,
@@ -911,7 +1032,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
911
1032
  });
912
1033
  },
913
1034
  children: [
914
- /* @__PURE__ */ jsx10(
1035
+ /* @__PURE__ */ jsx11(
915
1036
  "input",
916
1037
  {
917
1038
  value: amount,
@@ -921,7 +1042,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
921
1042
  "aria-label": "Amount"
922
1043
  }
923
1044
  ),
924
- /* @__PURE__ */ jsx10(
1045
+ /* @__PURE__ */ jsx11(
925
1046
  "input",
926
1047
  {
927
1048
  value: note,
@@ -931,27 +1052,27 @@ function SubscriberScreen({ client, pageSize = 50 }) {
931
1052
  "aria-label": "Reason"
932
1053
  }
933
1054
  ),
934
- /* @__PURE__ */ jsx10("button", { type: "submit", style: styles.button, disabled: !/^\d+$/.test(amount.trim()), children: "Grant" }),
935
- granted ? /* @__PURE__ */ jsx10("span", { style: styles.ok, children: granted }) : null
1055
+ /* @__PURE__ */ jsx11("button", { type: "submit", style: styles.button, disabled: !/^\d+$/.test(amount.trim()), children: "Grant" }),
1056
+ granted ? /* @__PURE__ */ jsx11("span", { style: styles.ok, children: granted }) : null
936
1057
  ]
937
1058
  }
938
1059
  ),
939
- /* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Ledger" }),
940
- ledger.length === 0 ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "Nothing moved yet." }) : /* @__PURE__ */ jsxs10("table", { style: styles.table, children: [
941
- /* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
942
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "When" }),
943
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Kind" }),
944
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Amount" }),
945
- /* @__PURE__ */ jsx10("th", { style: styles.th, children: "Note" })
1060
+ /* @__PURE__ */ jsx11("h2", { style: styles.subtitle, children: "Ledger" }),
1061
+ ledger.length === 0 ? /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "Nothing moved yet." }) : /* @__PURE__ */ jsxs11("table", { style: styles.table, children: [
1062
+ /* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs11("tr", { children: [
1063
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "When" }),
1064
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Kind" }),
1065
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Amount" }),
1066
+ /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Note" })
946
1067
  ] }) }),
947
- /* @__PURE__ */ jsx10("tbody", { children: ledger.map((t) => /* @__PURE__ */ jsxs10("tr", { children: [
948
- /* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children: new Date(t.createdAt).toLocaleString() }),
949
- /* @__PURE__ */ jsx10("td", { style: styles.td, children: t.type }),
950
- /* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.mono }, children: t.amount }),
951
- /* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children: t.description ?? "" })
952
- ] }, t.id)) })
1068
+ /* @__PURE__ */ jsx11("tbody", { children: ledger.map((t2) => /* @__PURE__ */ jsxs11("tr", { children: [
1069
+ /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted }, children: new Date(t2.createdAt).toLocaleString() }),
1070
+ /* @__PURE__ */ jsx11("td", { style: styles.td, children: t2.type }),
1071
+ /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: t2.amount }),
1072
+ /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted }, children: t2.description ?? "" })
1073
+ ] }, t2.id)) })
953
1074
  ] }),
954
- hasMoreLedger ? /* @__PURE__ */ jsx10(
1075
+ hasMoreLedger ? /* @__PURE__ */ jsx11(
955
1076
  "button",
956
1077
  {
957
1078
  type: "button",
@@ -960,7 +1081,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
960
1081
  children: "Load more"
961
1082
  }
962
1083
  ) : null
963
- ] }) : /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "No wallet \u2014 billing has no wallet configuration." })
1084
+ ] }) : /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "No wallet \u2014 billing has no wallet configuration." })
964
1085
  ] }) : null
965
1086
  ] });
966
1087
  }
@@ -968,7 +1089,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
968
1089
  // src/screens/AuditScreen.tsx
969
1090
  import { useAdminAudit } from "@fonderie/react-admin";
970
1091
  import { useState as useState4 } from "react";
971
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1092
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
972
1093
  function AuditScreen({ client, pageSize = 50 }) {
973
1094
  const [draft, setDraft] = useState4({ workspaceId: "", type: "", actorId: "" });
974
1095
  const [filter, setFilter] = useState4(
@@ -978,7 +1099,7 @@ function AuditScreen({ client, pageSize = 50 }) {
978
1099
  ...filter,
979
1100
  limit: pageSize
980
1101
  });
981
- const field = (key, placeholder) => /* @__PURE__ */ jsx11(
1102
+ const field = (key, placeholder) => /* @__PURE__ */ jsx12(
982
1103
  "input",
983
1104
  {
984
1105
  value: draft[key],
@@ -988,9 +1109,9 @@ function AuditScreen({ client, pageSize = 50 }) {
988
1109
  "aria-label": placeholder
989
1110
  }
990
1111
  );
991
- return /* @__PURE__ */ jsxs11("div", { style: styles.container, children: [
992
- /* @__PURE__ */ jsx11("h1", { style: styles.title, children: "Audit" }),
993
- /* @__PURE__ */ jsxs11(
1112
+ return /* @__PURE__ */ jsxs12("div", { style: styles.container, children: [
1113
+ /* @__PURE__ */ jsx12("h1", { style: styles.title, children: "Audit" }),
1114
+ /* @__PURE__ */ jsxs12(
994
1115
  "form",
995
1116
  {
996
1117
  style: styles.toolbar,
@@ -1006,8 +1127,8 @@ function AuditScreen({ client, pageSize = 50 }) {
1006
1127
  field("workspaceId", "workspace id (all if empty)"),
1007
1128
  field("type", "event type"),
1008
1129
  field("actorId", "actor id"),
1009
- /* @__PURE__ */ jsx11("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Filter" }),
1010
- /* @__PURE__ */ jsx11(
1130
+ /* @__PURE__ */ jsx12("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Filter" }),
1131
+ /* @__PURE__ */ jsx12(
1011
1132
  "button",
1012
1133
  {
1013
1134
  type: "button",
@@ -1020,25 +1141,25 @@ function AuditScreen({ client, pageSize = 50 }) {
1020
1141
  ]
1021
1142
  }
1022
1143
  ),
1023
- error ? /* @__PURE__ */ jsx11("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
1024
- events.length === 0 && !isLoading ? /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "Nothing recorded for this filter." }) : /* @__PURE__ */ jsxs11("table", { style: styles.table, children: [
1025
- /* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs11("tr", { children: [
1026
- /* @__PURE__ */ jsx11("th", { style: styles.th, children: "When" }),
1027
- /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Type" }),
1028
- /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Workspace" }),
1029
- /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Actor" }),
1030
- /* @__PURE__ */ jsx11("th", { style: styles.th, children: "Request" })
1144
+ error ? /* @__PURE__ */ jsx12("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
1145
+ events.length === 0 && !isLoading ? /* @__PURE__ */ jsx12("p", { style: styles.muted, children: "Nothing recorded for this filter." }) : /* @__PURE__ */ jsxs12("table", { style: styles.table, children: [
1146
+ /* @__PURE__ */ jsx12("thead", { children: /* @__PURE__ */ jsxs12("tr", { children: [
1147
+ /* @__PURE__ */ jsx12("th", { style: styles.th, children: "When" }),
1148
+ /* @__PURE__ */ jsx12("th", { style: styles.th, children: "Type" }),
1149
+ /* @__PURE__ */ jsx12("th", { style: styles.th, children: "Workspace" }),
1150
+ /* @__PURE__ */ jsx12("th", { style: styles.th, children: "Actor" }),
1151
+ /* @__PURE__ */ jsx12("th", { style: styles.th, children: "Request" })
1031
1152
  ] }) }),
1032
- /* @__PURE__ */ jsx11("tbody", { children: events.map((e) => /* @__PURE__ */ jsxs11("tr", { children: [
1033
- /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted }, children: new Date(e.createdAt).toLocaleString() }),
1034
- /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: e.type }),
1035
- /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: String(e.payload["workspaceId"] ?? "\u2014") }),
1036
- /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: e.actorId ?? "\u2014" }),
1037
- /* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted }, children: e.requestId ?? "" })
1153
+ /* @__PURE__ */ jsx12("tbody", { children: events.map((e) => /* @__PURE__ */ jsxs12("tr", { children: [
1154
+ /* @__PURE__ */ jsx12("td", { style: { ...styles.td, ...styles.muted }, children: new Date(e.createdAt).toLocaleString() }),
1155
+ /* @__PURE__ */ jsx12("td", { style: { ...styles.td, ...styles.mono }, children: e.type }),
1156
+ /* @__PURE__ */ jsx12("td", { style: { ...styles.td, ...styles.mono }, children: String(e.payload["workspaceId"] ?? "\u2014") }),
1157
+ /* @__PURE__ */ jsx12("td", { style: { ...styles.td, ...styles.mono }, children: e.actorId ?? "\u2014" }),
1158
+ /* @__PURE__ */ jsx12("td", { style: { ...styles.td, ...styles.muted }, children: e.requestId ?? "" })
1038
1159
  ] }, e.id)) })
1039
1160
  ] }),
1040
- isLoading ? /* @__PURE__ */ jsx11("p", { style: styles.status, children: "Loading\u2026" }) : null,
1041
- hasMore && !isLoading ? /* @__PURE__ */ jsx11(
1161
+ isLoading ? /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Loading\u2026" }) : null,
1162
+ hasMore && !isLoading ? /* @__PURE__ */ jsx12(
1042
1163
  "button",
1043
1164
  {
1044
1165
  type: "button",
@@ -1051,7 +1172,7 @@ function AuditScreen({ client, pageSize = 50 }) {
1051
1172
  }
1052
1173
 
1053
1174
  // src/screens/AdminShell.tsx
1054
- import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1175
+ import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1055
1176
  var NAV = [
1056
1177
  { group: "Today", items: [{ page: "attention", label: "Attention" }] },
1057
1178
  {
@@ -1078,7 +1199,8 @@ var NAV = [
1078
1199
  items: [
1079
1200
  { page: "audit", label: "Audit", needs: "audit" },
1080
1201
  { page: "log", label: "Admin log" },
1081
- { page: "tokens", label: "Access" }
1202
+ { page: "tokens", label: "Access" },
1203
+ { page: "migrations", label: "Migrations" }
1082
1204
  ]
1083
1205
  }
1084
1206
  ];
@@ -1110,42 +1232,45 @@ function AdminShell({
1110
1232
  let body;
1111
1233
  switch (current) {
1112
1234
  case "attention":
1113
- body = /* @__PURE__ */ jsx12(AttentionScreen, { client });
1235
+ body = /* @__PURE__ */ jsx13(AttentionScreen, { client });
1114
1236
  break;
1115
1237
  case "modules":
1116
- body = /* @__PURE__ */ jsx12(ModulesScreen, { client });
1238
+ body = /* @__PURE__ */ jsx13(ModulesScreen, { client });
1117
1239
  break;
1118
1240
  case "doctor":
1119
- body = /* @__PURE__ */ jsx12(DoctorScreen, { client });
1241
+ body = /* @__PURE__ */ jsx13(DoctorScreen, { client });
1120
1242
  break;
1121
1243
  case "config":
1122
- body = /* @__PURE__ */ jsx12(ConfigScreen, { client });
1244
+ body = /* @__PURE__ */ jsx13(ConfigScreen, { client });
1123
1245
  break;
1124
1246
  case "routes":
1125
- body = /* @__PURE__ */ jsx12(RoutesScreen, { client });
1247
+ body = /* @__PURE__ */ jsx13(RoutesScreen, { client });
1126
1248
  break;
1127
1249
  case "tokens":
1128
- body = /* @__PURE__ */ jsx12(TokensScreen, { client });
1250
+ body = /* @__PURE__ */ jsx13(TokensScreen, { client });
1251
+ break;
1252
+ case "migrations":
1253
+ body = /* @__PURE__ */ jsx13(MigrationsScreen, { client });
1129
1254
  break;
1130
1255
  case "log":
1131
- body = /* @__PURE__ */ jsx12(AdminLogScreen, { client });
1256
+ body = /* @__PURE__ */ jsx13(AdminLogScreen, { client });
1132
1257
  break;
1133
1258
  case "catalog":
1134
- body = billingClient ? /* @__PURE__ */ jsx12(CatalogScreen, { client: billingClient }) : /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Pass a BillingAdminClient to see the catalog here." });
1259
+ body = billingClient ? /* @__PURE__ */ jsx13(CatalogScreen, { client: billingClient }) : /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Pass a BillingAdminClient to see the catalog here." });
1135
1260
  break;
1136
1261
  case "subscriber":
1137
- body = billingClient ? /* @__PURE__ */ jsx12(SubscriberScreen, { client: billingClient }) : /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Pass a BillingAdminClient to look up subscribers here." });
1262
+ body = billingClient ? /* @__PURE__ */ jsx13(SubscriberScreen, { client: billingClient }) : /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Pass a BillingAdminClient to look up subscribers here." });
1138
1263
  break;
1139
1264
  case "audit":
1140
- body = auditClient ? /* @__PURE__ */ jsx12(AuditScreen, { client: auditClient }) : /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Pass an AuditAdminClient to see the audit trail here." });
1265
+ body = auditClient ? /* @__PURE__ */ jsx13(AuditScreen, { client: auditClient }) : /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Pass an AuditAdminClient to see the audit trail here." });
1141
1266
  break;
1142
1267
  case "users":
1143
- body = authClient ? /* @__PURE__ */ jsx12(UsersScreen, { client: authClient }) : /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Pass an AuthAdminClient to look up users here." });
1268
+ body = authClient ? /* @__PURE__ */ jsx13(UsersScreen, { client: authClient }) : /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Pass an AuthAdminClient to look up users here." });
1144
1269
  break;
1145
1270
  case "settings":
1146
- body = !configClient ? /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ jsxs12(Fragment8, { children: [
1147
- /* @__PURE__ */ jsx12("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
1148
- /* @__PURE__ */ jsx12(
1271
+ body = !configClient ? /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
1272
+ /* @__PURE__ */ jsx13("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
1273
+ /* @__PURE__ */ jsx13(
1149
1274
  ConfigEditorScreen,
1150
1275
  {
1151
1276
  client: configClient,
@@ -1155,7 +1280,7 @@ function AdminShell({
1155
1280
  onSaved: () => setEditing(null)
1156
1281
  }
1157
1282
  )
1158
- ] }) : /* @__PURE__ */ jsx12(
1283
+ ] }) : /* @__PURE__ */ jsx13(
1159
1284
  ConfigListScreen,
1160
1285
  {
1161
1286
  client: configClient,
@@ -1166,9 +1291,9 @@ function AdminShell({
1166
1291
  );
1167
1292
  break;
1168
1293
  case "templates":
1169
- body = !courierClient ? /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ jsxs12(Fragment8, { children: [
1170
- /* @__PURE__ */ jsx12("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
1171
- /* @__PURE__ */ jsx12(
1294
+ body = !courierClient ? /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
1295
+ /* @__PURE__ */ jsx13("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
1296
+ /* @__PURE__ */ jsx13(
1172
1297
  TemplateEditorScreen,
1173
1298
  {
1174
1299
  client: courierClient,
@@ -1176,22 +1301,22 @@ function AdminShell({
1176
1301
  onSaved: () => setEditing(null)
1177
1302
  }
1178
1303
  )
1179
- ] }) : /* @__PURE__ */ jsx12(
1304
+ ] }) : /* @__PURE__ */ jsx13(
1180
1305
  TemplateListScreen,
1181
1306
  {
1182
1307
  client: courierClient,
1183
- onSelectTemplate: (t) => setEditing({ kind: "template", type: t.type })
1308
+ onSelectTemplate: (t2) => setEditing({ kind: "template", type: t2.type })
1184
1309
  }
1185
1310
  );
1186
1311
  break;
1187
1312
  }
1188
- return /* @__PURE__ */ jsxs12("div", { style: styles.shell, children: [
1189
- /* @__PURE__ */ jsx12("nav", { style: styles.nav, "aria-label": "Admin", children: NAV.map((g) => {
1313
+ return /* @__PURE__ */ jsxs13("div", { style: styles.shell, children: [
1314
+ /* @__PURE__ */ jsx13("nav", { style: styles.nav, "aria-label": "Admin", children: NAV.map((g) => {
1190
1315
  const items = g.items.filter((i) => !i.needs || has[i.needs]);
1191
1316
  if (items.length === 0) return null;
1192
- return /* @__PURE__ */ jsxs12("div", { children: [
1193
- /* @__PURE__ */ jsx12("div", { style: styles.navGroup, children: g.group }),
1194
- items.map((i) => /* @__PURE__ */ jsx12(
1317
+ return /* @__PURE__ */ jsxs13("div", { children: [
1318
+ /* @__PURE__ */ jsx13("div", { style: styles.navGroup, children: g.group }),
1319
+ items.map((i) => /* @__PURE__ */ jsx13(
1195
1320
  "button",
1196
1321
  {
1197
1322
  type: "button",
@@ -1207,7 +1332,7 @@ function AdminShell({
1207
1332
  ))
1208
1333
  ] }, g.group);
1209
1334
  }) }),
1210
- /* @__PURE__ */ jsx12("main", { style: styles.main, children: body })
1335
+ /* @__PURE__ */ jsx13("main", { style: styles.main, children: body })
1211
1336
  ] });
1212
1337
  }
1213
1338
  export {
@@ -1218,6 +1343,7 @@ export {
1218
1343
  CatalogScreen,
1219
1344
  ConfigScreen,
1220
1345
  DoctorScreen,
1346
+ MigrationsScreen,
1221
1347
  ModulesScreen,
1222
1348
  RoutesScreen,
1223
1349
  SubscriberScreen,