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