astrogators-shared-ui 0.16.4 → 0.17.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
@@ -140,36 +140,36 @@ var _ = [
140
140
  x(e), w(t);
141
141
  }, D = () => {
142
142
  S(), T();
143
- }, ee = () => !!b(), O = "", k, A = null, j = (e) => {
144
- O = e.baseURL, k = e.onUnauthorized;
145
- }, M = () => A || (A = (async () => {
143
+ }, O = () => !!b(), ee = "", te, k = null, A = (e) => {
144
+ ee = e.baseURL, te = e.onUnauthorized;
145
+ }, j = () => k || (k = (async () => {
146
146
  let e = C();
147
147
  if (!e) throw Error("No refresh token available");
148
- let t = await fetch(`${O}/api/v1/auth/refresh`, {
148
+ let t = await fetch(`${ee}/api/v1/auth/refresh`, {
149
149
  method: "POST",
150
150
  headers: { "Content-Type": "application/json" },
151
151
  body: JSON.stringify({ refresh_token: e })
152
152
  });
153
- if (!t.ok) throw D(), k?.(), Error("Token refresh failed");
153
+ if (!t.ok) throw D(), te?.(), Error("Token refresh failed");
154
154
  let n = await t.json();
155
155
  return E(n.access_token, n.refresh_token), n.access_token;
156
156
  })().finally(() => {
157
- A = null;
158
- }), A), N = 30, P = [700, 1500], F = /* @__PURE__ */ new Set([
157
+ k = null;
158
+ }), k), ne = 30, M = [700, 1500], N = /* @__PURE__ */ new Set([
159
159
  502,
160
160
  503,
161
161
  504
162
- ]), te = (e) => {
162
+ ]), P = (e) => {
163
163
  let t = (e ?? "GET").toUpperCase();
164
164
  return t === "GET" || t === "HEAD" || t === "OPTIONS";
165
- }, I = (e) => e == null || typeof e == "string", ne = (e) => new Promise((t) => setTimeout(t, e)), re = async (e, t) => {
166
- let n = te(t.method) && I(t.body), r = I(t.body), i;
167
- for (let a = 0; a <= P.length; a++) {
168
- a > 0 && await ne(P[a - 1]);
169
- let o = a < P.length;
165
+ }, F = (e) => e == null || typeof e == "string", re = (e) => new Promise((t) => setTimeout(t, e)), I = async (e, t) => {
166
+ let n = P(t.method) && F(t.body), r = F(t.body), i;
167
+ for (let a = 0; a <= M.length; a++) {
168
+ a > 0 && await re(M[a - 1]);
169
+ let o = a < M.length;
170
170
  try {
171
171
  let r = await fetch(e, t);
172
- if (o && n && F.has(r.status)) continue;
172
+ if (o && n && N.has(r.status)) continue;
173
173
  return r;
174
174
  } catch (e) {
175
175
  if (i = e, o && r) continue;
@@ -180,26 +180,26 @@ var _ = [
180
180
  }, ie = (e) => {
181
181
  try {
182
182
  let t = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), { exp: n } = JSON.parse(atob(t));
183
- return typeof n == "number" && Date.now() / 1e3 >= n - N;
183
+ return typeof n == "number" && Date.now() / 1e3 >= n - ne;
184
184
  } catch {
185
185
  return !1;
186
186
  }
187
187
  }, ae = async (e, t = {}) => {
188
188
  let n = b();
189
189
  if (n && ie(n)) try {
190
- n = await M();
190
+ n = await j();
191
191
  } catch {
192
192
  n = b();
193
193
  }
194
194
  let r = { ...t.headers };
195
195
  n && (r.Authorization = `Bearer ${n}`);
196
- let i = await re(e, {
196
+ let i = await I(e, {
197
197
  ...t,
198
198
  headers: r
199
199
  });
200
200
  if (i.status !== 401 || !n) return i;
201
201
  try {
202
- return r.Authorization = `Bearer ${await M()}`, await re(e, {
202
+ return r.Authorization = `Bearer ${await j()}`, await I(e, {
203
203
  ...t,
204
204
  headers: r
205
205
  });
@@ -209,7 +209,7 @@ var _ = [
209
209
  }, oe = class {
210
210
  baseURL;
211
211
  constructor(e) {
212
- this.baseURL = e.baseURL, j({
212
+ this.baseURL = e.baseURL, A({
213
213
  baseURL: e.baseURL,
214
214
  onUnauthorized: e.onUnauthorized
215
215
  });
@@ -270,14 +270,17 @@ var _ = [
270
270
  }
271
271
  }, L, se = (e) => {
272
272
  L = new oe(e);
273
- }, R = "astrogators_ally_codes", ce = "astrogators_selected_ally_code", z = () => {
273
+ }, ce = async (e) => {
274
+ let t = await L.patch("/api/v1/users/me", e);
275
+ return t.tokens && E(t.tokens.access_token, t.tokens.refresh_token), t;
276
+ }, le = async () => (await L.post("/api/v1/auth/logout-all")).message, R = "astrogators_ally_codes", ue = "astrogators_selected_ally_code", z = () => {
274
277
  try {
275
278
  let e = localStorage.getItem(R);
276
279
  return e ? JSON.parse(e) : [];
277
280
  } catch (e) {
278
281
  return console.error("Failed to read ally codes from localStorage:", e), [];
279
282
  }
280
- }, le = (e) => {
283
+ }, de = (e) => {
281
284
  try {
282
285
  let t = z();
283
286
  if (t.some((t) => t.ally_code === e.ally_code)) return;
@@ -285,14 +288,14 @@ var _ = [
285
288
  } catch (e) {
286
289
  console.error("Failed to save ally code to localStorage:", e);
287
290
  }
288
- }, ue = (e) => {
291
+ }, fe = (e) => {
289
292
  try {
290
293
  let t = z().filter((t) => t.ally_code !== e);
291
294
  localStorage.setItem(R, JSON.stringify(t));
292
295
  } catch (e) {
293
296
  console.error("Failed to remove ally code from localStorage:", e);
294
297
  }
295
- }, de = (e) => {
298
+ }, pe = (e) => {
296
299
  try {
297
300
  let t = z().map((t) => t.ally_code === e ? {
298
301
  ...t,
@@ -302,11 +305,11 @@ var _ = [
302
305
  } catch (e) {
303
306
  console.error("Failed to update ally code last used:", e);
304
307
  }
305
- }, fe = () => localStorage.getItem(ce), B = (e) => {
306
- e ? localStorage.setItem(ce, e) : localStorage.removeItem(ce);
307
- }, pe = () => {
308
- localStorage.removeItem(R), localStorage.removeItem(ce);
309
- }, me = t(void 0), he = ({ children: e, apiBaseUrl: t }) => {
308
+ }, me = () => localStorage.getItem(ue), B = (e) => {
309
+ e ? localStorage.setItem(ue, e) : localStorage.removeItem(ue);
310
+ }, he = () => {
311
+ localStorage.removeItem(R), localStorage.removeItem(ue);
312
+ }, ge = t(void 0), _e = ({ children: e, apiBaseUrl: t }) => {
310
313
  let [n, i] = s(null), [o, c] = s(!0), [u, d] = s(!0), [f, p] = s(!0), [m, h] = s([]), [g, _] = s(null), [v, y] = s(!1), [b, x] = s({
311
314
  show: !1,
312
315
  localStorageCodes: []
@@ -324,7 +327,7 @@ var _ = [
324
327
  })();
325
328
  }, [t]);
326
329
  let S = r(async () => {
327
- if (!ee()) {
330
+ if (!O()) {
328
331
  i(null), c(!1);
329
332
  return;
330
333
  }
@@ -360,21 +363,30 @@ var _ = [
360
363
  show: !1,
361
364
  localStorageCodes: []
362
365
  });
363
- }, O = async () => {
366
+ }, ee = async () => {
364
367
  await S();
368
+ }, te = async () => {
369
+ try {
370
+ await le();
371
+ } finally {
372
+ T();
373
+ }
365
374
  }, k = async (e) => {
375
+ let t = await ce(e);
376
+ return i(t), t;
377
+ }, A = async (e) => {
366
378
  try {
367
379
  return (await L.post("/api/v1/auth/forgot-password", e)).message;
368
380
  } catch (e) {
369
381
  throw console.error("Forgot password failed:", e), e;
370
382
  }
371
- }, A = async (e) => {
383
+ }, j = async (e) => {
372
384
  try {
373
385
  return (await L.post("/api/v1/auth/reset-password", e)).message;
374
386
  } catch (e) {
375
387
  throw console.error("Reset password failed:", e), e;
376
388
  }
377
- }, j = async (e) => {
389
+ }, ne = async (e) => {
378
390
  try {
379
391
  return (await L.post("/api/v1/auth/resend-verification", e)).message;
380
392
  } catch (e) {
@@ -396,7 +408,7 @@ var _ = [
396
408
  let t = z();
397
409
  h(t), e = t.map((e) => e.ally_code);
398
410
  }
399
- let t = fe(), r = t && e.includes(t) ? t : null;
411
+ let t = me(), r = t && e.includes(t) ? t : null;
400
412
  _(r), r !== t && B(r);
401
413
  } catch (e) {
402
414
  console.error("Failed to fetch ally codes:", e), h([]);
@@ -404,12 +416,12 @@ var _ = [
404
416
  y(!1);
405
417
  }
406
418
  }, [n]), N = r(async (e) => {
407
- n && typeof e == "number" ? (await L.put(`/api/v1/users/me/ally-codes/${e}/use`, {}), await M()) : !n && typeof e == "string" && (de(e), h(z()));
419
+ n && typeof e == "number" ? (await L.put(`/api/v1/users/me/ally-codes/${e}/use`, {}), await M()) : !n && typeof e == "string" && (pe(e), h(z()));
408
420
  }, [n, M]), P = r((e) => {
409
421
  if (_(e), B(e), e && n) {
410
422
  let t = m.find((t) => "ally_code" in t && t.ally_code === e);
411
423
  t && "id" in t && N(t.id);
412
- } else e && !n && de(e);
424
+ } else e && !n && pe(e);
413
425
  }, [
414
426
  n,
415
427
  m,
@@ -422,7 +434,7 @@ var _ = [
422
434
  } else {
423
435
  let t = await L.get(`/api/v1/player-data/player/${e}`);
424
436
  if (!t) throw Error("Invalid ally code - player not found");
425
- le({
437
+ de({
426
438
  ally_code: e,
427
439
  player_name: t.data?.name ?? null,
428
440
  last_used_at: (/* @__PURE__ */ new Date()).toISOString()
@@ -432,8 +444,8 @@ var _ = [
432
444
  n,
433
445
  m.length,
434
446
  P
435
- ]), te = r(async (e) => {
436
- n && typeof e == "number" ? (await L.delete(`/api/v1/users/me/ally-codes/${e}`), h((t) => t.filter((t) => "id" in t && t.id !== e))) : !n && typeof e == "string" && (ue(e), h(z()), g === e && P(null));
447
+ ]), re = r(async (e) => {
448
+ n && typeof e == "number" ? (await L.delete(`/api/v1/users/me/ally-codes/${e}`), h((t) => t.filter((t) => "id" in t && t.id !== e))) : !n && typeof e == "string" && (fe(e), h(z()), g === e && P(null));
437
449
  }, [
438
450
  n,
439
451
  g,
@@ -443,7 +455,7 @@ var _ = [
443
455
  show: !1,
444
456
  localStorageCodes: []
445
457
  });
446
- }, []), ne = r(async () => {
458
+ }, []), ie = r(async () => {
447
459
  if (!n) return;
448
460
  let e = z();
449
461
  for (let t of e) try {
@@ -451,7 +463,7 @@ var _ = [
451
463
  } catch (e) {
452
464
  console.error(`Failed to migrate ally code ${t.ally_code}:`, e);
453
465
  }
454
- pe(), I();
466
+ he(), I();
455
467
  }, [
456
468
  n,
457
469
  F,
@@ -460,17 +472,19 @@ var _ = [
460
472
  a(() => {
461
473
  M();
462
474
  }, [M]);
463
- let re = {
475
+ let ae = {
464
476
  user: n,
465
477
  isAuthenticated: !!n,
466
478
  isLoading: o,
467
479
  login: C,
468
480
  register: w,
469
481
  logout: T,
470
- refreshUser: O,
471
- forgotPassword: k,
472
- resetPassword: A,
473
- resendVerification: j,
482
+ logoutAll: te,
483
+ refreshUser: ee,
484
+ forgotPassword: A,
485
+ resetPassword: j,
486
+ resendVerification: ne,
487
+ updateAccount: k,
474
488
  authEnabled: u,
475
489
  isLoadingFeatures: f,
476
490
  allyCodes: m,
@@ -478,25 +492,25 @@ var _ = [
478
492
  isLoadingAllyCodes: v,
479
493
  fetchAllyCodes: M,
480
494
  addAllyCode: F,
481
- removeAllyCode: te,
495
+ removeAllyCode: re,
482
496
  selectAllyCode: P,
483
497
  updateAllyCodeLastUsed: N,
484
498
  migrationPrompt: b,
485
499
  dismissMigrationPrompt: I,
486
- migrateLocalStorageCodes: ne
500
+ migrateLocalStorageCodes: ie
487
501
  };
488
- return /* @__PURE__ */ l(me.Provider, {
489
- value: re,
502
+ return /* @__PURE__ */ l(ge.Provider, {
503
+ value: ae,
490
504
  children: e
491
505
  });
492
506
  }, V = () => {
493
- let e = i(me);
507
+ let e = i(ge);
494
508
  if (e === void 0) throw Error("useAuth must be used within an AuthProvider");
495
509
  return e;
496
510
  };
497
511
  //#endregion
498
512
  //#region src/hooks/useDismissableMenu.ts
499
- function ge({ isOpen: e, onClose: t, triggerRef: n, panelRef: r }) {
513
+ function ve({ isOpen: e, onClose: t, triggerRef: n, panelRef: r }) {
500
514
  a(() => {
501
515
  if (!e) return;
502
516
  let i = (e) => {
@@ -528,9 +542,9 @@ var H = {
528
542
  groupLabel: "_groupLabel_vspnm_92",
529
543
  groupItems: "_groupItems_vspnm_97",
530
544
  groupItem: "_groupItem_vspnm_97"
531
- }, _e = ({ app: e, isCurrentApp: t, activeSectionId: n, isOpen: r, onOpenChange: i, onSectionClick: a }) => {
545
+ }, ye = ({ app: e, isCurrentApp: t, activeSectionId: n, isOpen: r, onOpenChange: i, onSectionClick: a }) => {
532
546
  let { isAuthenticated: s, user: c } = V(), d = o(null), f = o(null), p = `navmenu-panel-${e.id}`;
533
- ge({
547
+ ve({
534
548
  isOpen: r,
535
549
  onClose: () => i(!1),
536
550
  triggerRef: d,
@@ -601,10 +615,10 @@ var H = {
601
615
  })
602
616
  })]
603
617
  });
604
- }, ve = { burger: "_burger_javjr_1" }, ye = n(({ isOpen: e, onClick: t, controlsId: n }, r) => /* @__PURE__ */ l("button", {
618
+ }, be = { burger: "_burger_javjr_1" }, xe = n(({ isOpen: e, onClick: t, controlsId: n }, r) => /* @__PURE__ */ l("button", {
605
619
  ref: r,
606
620
  type: "button",
607
- className: ve.burger,
621
+ className: be.burger,
608
622
  onClick: t,
609
623
  "aria-expanded": e,
610
624
  "aria-controls": n,
@@ -633,7 +647,7 @@ var H = {
633
647
  })
634
648
  })
635
649
  }));
636
- ye.displayName = "NavBurger";
650
+ xe.displayName = "NavBurger";
637
651
  var U = {
638
652
  selectWrapper: "_selectWrapper_ir4bq_1",
639
653
  fullWidth: "_fullWidth_ir4bq_7",
@@ -645,7 +659,7 @@ var U = {
645
659
  arrow: "_arrow_ir4bq_71",
646
660
  errorText: "_errorText_ir4bq_81",
647
661
  helperText: "_helperText_ir4bq_86"
648
- }, be = e.forwardRef(({ label: e, error: t, helperText: n, options: r, placeholder: i, fullWidth: a = !1, className: o = "", id: s, ...c }, d) => {
662
+ }, Se = e.forwardRef(({ label: e, error: t, helperText: n, options: r, placeholder: i, fullWidth: a = !1, className: o = "", id: s, ...c }, d) => {
649
663
  let f = s || `select-${Math.random().toString(36).substr(2, 9)}`, p = !!t;
650
664
  return /* @__PURE__ */ u("div", {
651
665
  className: `${U.selectWrapper} ${a ? U.fullWidth : ""} ${o}`,
@@ -694,7 +708,7 @@ var U = {
694
708
  ]
695
709
  });
696
710
  });
697
- be.displayName = "Select";
711
+ Se.displayName = "Select";
698
712
  var W = {
699
713
  button: "_button_159ms_1",
700
714
  sm: "_sm_159ms_22",
@@ -731,7 +745,7 @@ var W = {
731
745
  error: "_error_15t4g_55",
732
746
  errorText: "_errorText_15t4g_63",
733
747
  helperText: "_helperText_15t4g_68"
734
- }, xe = e.forwardRef(({ label: e, error: t, helperText: n, fullWidth: r = !1, className: i = "", id: a, ...o }, s) => {
748
+ }, Ce = e.forwardRef(({ label: e, error: t, helperText: n, fullWidth: r = !1, className: i = "", id: a, ...o }, s) => {
735
749
  let c = a || `input-${Math.random().toString(36).substr(2, 9)}`, d = !!t;
736
750
  return /* @__PURE__ */ u("div", {
737
751
  className: `${K.inputWrapper} ${r ? K.fullWidth : ""} ${i}`,
@@ -761,10 +775,10 @@ var W = {
761
775
  ]
762
776
  });
763
777
  });
764
- xe.displayName = "Input";
778
+ Ce.displayName = "Input";
765
779
  //#endregion
766
780
  //#region src/utils/formatAllyCode.ts
767
- var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e.slice(6, 9)}`, Se = (e) => e.replace(/-/g, ""), J = {
781
+ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e.slice(6, 9)}`, we = (e) => e.replace(/-/g, ""), J = {
768
782
  allyCodeDropdown: "_allyCodeDropdown_1pawi_1",
769
783
  select: "_select_1pawi_8",
770
784
  manageButton: "_manageButton_1pawi_12",
@@ -777,29 +791,29 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
777
791
  codeItem: "_codeItem_1pawi_71",
778
792
  doneButton: "_doneButton_1pawi_88",
779
793
  inline: "_inline_1pawi_107"
780
- }, Ce = ({ onAllyCodeSelected: e, className: t = "", isOpen: n, onOpenChange: r, variant: i = "floating" }) => {
794
+ }, Te = ({ onAllyCodeSelected: e, className: t = "", isOpen: n, onOpenChange: r, variant: i = "floating" }) => {
781
795
  let { allyCodes: a, selectedAllyCode: c, selectAllyCode: d, removeAllyCode: f, addAllyCode: p, isLoadingAllyCodes: m } = V(), [h, g] = s(!1), _ = n ?? h, v = (e) => {
782
796
  g(e), r?.(e);
783
- }, [y, b] = s(""), [x, S] = s(""), [C, w] = s(""), [T, E] = s(!1), D = o(null), ee = o(null);
784
- ge({
797
+ }, [y, b] = s(""), [x, S] = s(""), [C, w] = s(""), [T, E] = s(!1), D = o(null), O = o(null);
798
+ ve({
785
799
  isOpen: _ && i === "floating",
786
800
  onClose: () => v(!1),
787
801
  triggerRef: D,
788
- panelRef: ee
802
+ panelRef: O
789
803
  });
790
- let O = a.map((e) => ({
804
+ let ee = a.map((e) => ({
791
805
  value: e.ally_code,
792
806
  label: e.player_name ? `${e.player_name} (${q(e.ally_code)})` : q(e.ally_code)
793
- })), k = (t) => {
807
+ })), te = (t) => {
794
808
  let n = t.target.value || null;
795
809
  d(n), e?.(n);
796
- }, A = async (e) => {
810
+ }, k = async (e) => {
797
811
  let t = a.find((t) => t.ally_code === e);
798
812
  if (t) {
799
813
  let e = "id" in t ? t.id : t.ally_code;
800
814
  await f(e);
801
815
  }
802
- }, j = async () => {
816
+ }, A = async () => {
803
817
  if (S(""), w(""), !/^\d{9}$/.test(y)) {
804
818
  S("Ally code must be exactly 9 digits");
805
819
  return;
@@ -812,21 +826,21 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
812
826
  } finally {
813
827
  E(!1);
814
828
  }
815
- }, M = a.length > 0;
829
+ }, j = a.length > 0;
816
830
  return /* @__PURE__ */ u("div", {
817
831
  className: `${J.allyCodeDropdown} ${i === "inline" ? J.inline : ""} ${t}`,
818
832
  children: [
819
- M && /* @__PURE__ */ l(be, {
820
- options: O,
833
+ j && /* @__PURE__ */ l(Se, {
834
+ options: ee,
821
835
  value: c || "",
822
- onChange: k,
836
+ onChange: te,
823
837
  placeholder: "Select ally code",
824
838
  disabled: m,
825
839
  className: J.select
826
840
  }),
827
841
  _ && /* @__PURE__ */ u("div", {
828
842
  className: J.managePanel,
829
- ref: ee,
843
+ ref: O,
830
844
  id: "ally-code-manage-panel",
831
845
  children: [
832
846
  /* @__PURE__ */ l("h4", { children: "Manage Ally Codes" }),
@@ -835,7 +849,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
835
849
  children: [
836
850
  /* @__PURE__ */ u("div", {
837
851
  className: J.addInputGroup,
838
- children: [/* @__PURE__ */ l(xe, {
852
+ children: [/* @__PURE__ */ l(Ce, {
839
853
  type: "text",
840
854
  placeholder: "9-digit ally code",
841
855
  value: y,
@@ -844,7 +858,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
844
858
  }), /* @__PURE__ */ l(G, {
845
859
  variant: "primary",
846
860
  size: "sm",
847
- onClick: j,
861
+ onClick: A,
848
862
  loading: T,
849
863
  disabled: y.length !== 9,
850
864
  children: "Add"
@@ -867,7 +881,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
867
881
  children: [/* @__PURE__ */ l("span", { children: e.player_name ? `${e.player_name} (${q(e.ally_code)})` : q(e.ally_code) }), /* @__PURE__ */ l(G, {
868
882
  variant: "ghost",
869
883
  size: "sm",
870
- onClick: () => A(e.ally_code),
884
+ onClick: () => k(e.ally_code),
871
885
  children: "Remove"
872
886
  })]
873
887
  }, e.ally_code))
@@ -891,28 +905,28 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
891
905
  "aria-expanded": _,
892
906
  "aria-controls": "ally-code-manage-panel",
893
907
  "aria-haspopup": "true",
894
- children: M ? "Manage" : "+ Add ally code"
908
+ children: j ? "Manage" : "+ Add ally code"
895
909
  })
896
910
  })
897
911
  ]
898
912
  });
899
- }, we = {
913
+ }, Ee = {
900
914
  authCluster: "_authCluster_17o10_1",
901
915
  userLink: "_userLink_17o10_7",
902
916
  adminLink: "_adminLink_17o10_16"
903
- }, Te = ({ showAuth: e = !0 }) => {
917
+ }, De = ({ showAuth: e = !0 }) => {
904
918
  let { user: t, isAuthenticated: n, logout: r, authEnabled: i } = V();
905
919
  return e ? n ? /* @__PURE__ */ u("div", {
906
- className: we.authCluster,
920
+ className: Ee.authCluster,
907
921
  children: [
908
922
  t?.role === "admin" && /* @__PURE__ */ l("a", {
909
923
  href: "/admin/users",
910
- className: we.adminLink,
924
+ className: Ee.adminLink,
911
925
  children: "Admin"
912
926
  }),
913
927
  /* @__PURE__ */ l("a", {
914
928
  href: "/profile",
915
- className: we.userLink,
929
+ className: Ee.userLink,
916
930
  children: t?.username
917
931
  }),
918
932
  /* @__PURE__ */ l(G, {
@@ -925,7 +939,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
925
939
  })
926
940
  ]
927
941
  }) : i ? /* @__PURE__ */ u("div", {
928
- className: we.authCluster,
942
+ className: Ee.authCluster,
929
943
  children: [/* @__PURE__ */ l("a", {
930
944
  href: "/login",
931
945
  children: /* @__PURE__ */ l(G, {
@@ -962,7 +976,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
962
976
  allySection: "_allySection_3ax21_112",
963
977
  extrasSection: "_extrasSection_3ax21_113",
964
978
  accountSection: "_accountSection_3ax21_114"
965
- }, Ee = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])", De = ({ isOpen: e, onClose: t, currentApp: n, activeSectionId: r, onSectionClick: i, rightExtras: c, showAuth: f, panelId: p, returnFocusRef: m }) => {
979
+ }, Oe = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])", ke = ({ isOpen: e, onClose: t, currentApp: n, activeSectionId: r, onSectionClick: i, rightExtras: c, showAuth: f, panelId: p, returnFocusRef: m }) => {
966
980
  let { isAuthenticated: h, user: v } = V(), [y, b] = s(n === "hub" ? null : n), x = o(null);
967
981
  if (a(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
968
982
  document.body.style.overflow = "unset";
@@ -974,7 +988,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
974
988
  return;
975
989
  }
976
990
  if (e.key === "Tab") {
977
- let t = x.current?.querySelectorAll(Ee);
991
+ let t = x.current?.querySelectorAll(Oe);
978
992
  if (!t || t.length === 0) return;
979
993
  let n = t[0], r = t[t.length - 1], i = document.activeElement, a = i === x.current || !x.current?.contains(i);
980
994
  e.shiftKey && (i === n || a) ? (e.preventDefault(), r.focus()) : !e.shiftKey && (i === r || a) && (e.preventDefault(), n.focus());
@@ -1057,7 +1071,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1057
1071
  }),
1058
1072
  /* @__PURE__ */ l("div", {
1059
1073
  className: Y.allySection,
1060
- children: /* @__PURE__ */ l(Ce, { variant: "inline" })
1074
+ children: /* @__PURE__ */ l(Te, { variant: "inline" })
1061
1075
  }),
1062
1076
  c && /* @__PURE__ */ l("div", {
1063
1077
  className: Y.extrasSection,
@@ -1065,17 +1079,17 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1065
1079
  }),
1066
1080
  /* @__PURE__ */ l("div", {
1067
1081
  className: Y.accountSection,
1068
- children: /* @__PURE__ */ l(Te, { showAuth: f })
1082
+ children: /* @__PURE__ */ l(De, { showAuth: f })
1069
1083
  })
1070
1084
  ]
1071
1085
  })
1072
1086
  }), document.body);
1073
- }, Oe = {
1087
+ }, Ae = {
1074
1088
  logoLink: "_logoLink_12f5f_3",
1075
1089
  appMenus: "_appMenus_12f5f_10",
1076
1090
  desktopRight: "_desktopRight_12f5f_19",
1077
1091
  extrasGroup: "_extrasGroup_12f5f_25"
1078
- }, ke = ({ currentApp: e, activeSectionId: t, onNavigate: n, rightExtras: r, showAuth: i = !0, className: d }) => {
1092
+ }, je = ({ currentApp: e, activeSectionId: t, onNavigate: n, rightExtras: r, showAuth: i = !0, className: d }) => {
1079
1093
  let [f, p] = s(null), [m, g] = s(!1), v = o(null), y = "suite-mobile-nav-panel";
1080
1094
  return a(() => {
1081
1095
  let e = window.matchMedia("(max-width: 768px)"), t = () => {
@@ -1086,12 +1100,12 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1086
1100
  className: d,
1087
1101
  logo: /* @__PURE__ */ l("a", {
1088
1102
  href: "/",
1089
- className: Oe.logoLink,
1103
+ className: Ae.logoLink,
1090
1104
  children: "The Astrogator's Table"
1091
1105
  }),
1092
1106
  leftContent: /* @__PURE__ */ l("nav", {
1093
- className: Oe.appMenus,
1094
- children: _.map((r) => /* @__PURE__ */ l(_e, {
1107
+ className: Ae.appMenus,
1108
+ children: _.map((r) => /* @__PURE__ */ l(ye, {
1095
1109
  app: r,
1096
1110
  isCurrentApp: e === r.id,
1097
1111
  activeSectionId: t,
@@ -1101,19 +1115,19 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1101
1115
  }, r.id))
1102
1116
  }),
1103
1117
  rightContent: /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ u("div", {
1104
- className: Oe.desktopRight,
1118
+ className: Ae.desktopRight,
1105
1119
  children: [
1106
1120
  r && /* @__PURE__ */ l("div", {
1107
- className: Oe.extrasGroup,
1121
+ className: Ae.extrasGroup,
1108
1122
  children: r
1109
1123
  }),
1110
- /* @__PURE__ */ l(Ce, {
1124
+ /* @__PURE__ */ l(Te, {
1111
1125
  isOpen: f === "ally",
1112
1126
  onOpenChange: (e) => p(e ? "ally" : null)
1113
1127
  }),
1114
- /* @__PURE__ */ l(Te, { showAuth: i })
1128
+ /* @__PURE__ */ l(De, { showAuth: i })
1115
1129
  ]
1116
- }), /* @__PURE__ */ l(ye, {
1130
+ }), /* @__PURE__ */ l(xe, {
1117
1131
  ref: v,
1118
1132
  isOpen: m,
1119
1133
  onClick: () => {
@@ -1121,7 +1135,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1121
1135
  },
1122
1136
  controlsId: y
1123
1137
  })] })
1124
- }), /* @__PURE__ */ l(De, {
1138
+ }), /* @__PURE__ */ l(ke, {
1125
1139
  isOpen: m,
1126
1140
  onClose: () => g(!1),
1127
1141
  currentApp: e,
@@ -1138,7 +1152,7 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1138
1152
  defaultContent: "_defaultContent_zjuj8_13",
1139
1153
  copyright: "_copyright_zjuj8_21",
1140
1154
  disclaimer: "_disclaimer_zjuj8_26"
1141
- }, Ae = ({ children: e, className: t = "" }) => /* @__PURE__ */ l("footer", {
1155
+ }, Me = ({ children: e, className: t = "" }) => /* @__PURE__ */ l("footer", {
1142
1156
  className: `${X.footer} ${t}`,
1143
1157
  children: /* @__PURE__ */ l("div", {
1144
1158
  className: X.content,
@@ -1160,11 +1174,11 @@ var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
1160
1174
  });
1161
1175
  //#endregion
1162
1176
  //#region src/utils/formatTime.ts
1163
- function je(e) {
1177
+ function Ne(e) {
1164
1178
  let t = /([zZ]|[+-]\d{2}:?\d{2})$/.test(e);
1165
1179
  return new Date(t ? e : `${e}Z`);
1166
1180
  }
1167
- function Me(e, t) {
1181
+ function Pe(e, t) {
1168
1182
  let n = Math.max(0, Math.floor((t - e.getTime()) / 1e3));
1169
1183
  if (n < 60) return `${n}s ago`;
1170
1184
  let r = Math.floor(n / 60);
@@ -1172,28 +1186,28 @@ function Me(e, t) {
1172
1186
  let i = Math.floor(r / 60);
1173
1187
  return i < 24 ? `${i}h ago` : `${Math.floor(i / 24)}d ago`;
1174
1188
  }
1175
- function Ne(e) {
1189
+ function Fe(e) {
1176
1190
  return `${Math.floor(e / 60)}:${(e % 60).toString().padStart(2, "0")}`;
1177
1191
  }
1178
- var Pe = {
1192
+ var Ie = {
1179
1193
  rosterRefresh: "_rosterRefresh_1rbul_3",
1180
1194
  updatedLabel: "_updatedLabel_1rbul_11",
1181
1195
  refreshButton: "_refreshButton_1rbul_19",
1182
1196
  spin: "_spin_1rbul_31"
1183
- }, Fe = ({ onRefresh: e, isRefreshing: t, cachedAt: n = null, refreshAvailableAt: r = null, labelPrefix: i = "Updated", className: o = "" }) => {
1197
+ }, Le = ({ onRefresh: e, isRefreshing: t, cachedAt: n = null, refreshAvailableAt: r = null, labelPrefix: i = "Updated", className: o = "" }) => {
1184
1198
  let [c, d] = s(() => Date.now()), f = !!n || r != null && r > c;
1185
1199
  a(() => {
1186
1200
  if (!f) return;
1187
1201
  let e = setInterval(() => d(Date.now()), 1e3);
1188
1202
  return () => clearInterval(e);
1189
1203
  }, [f]);
1190
- let p = r ? Math.max(0, Math.ceil((r - c) / 1e3)) : 0, m = n ? Me(je(n), c) : null, h = t || p > 0, g = p > 0 ? `Fresh data available in ${Ne(p)}` : "Refresh roster";
1204
+ let p = r ? Math.max(0, Math.ceil((r - c) / 1e3)) : 0, m = n ? Pe(Ne(n), c) : null, h = t || p > 0, g = p > 0 ? `Fresh data available in ${Fe(p)}` : "Refresh roster";
1191
1205
  return /* @__PURE__ */ u("div", {
1192
- className: `${Pe.rosterRefresh} ${o}`,
1206
+ className: `${Ie.rosterRefresh} ${o}`,
1193
1207
  children: [m && /* @__PURE__ */ l("span", {
1194
- className: Pe.updatedLabel,
1208
+ className: Ie.updatedLabel,
1195
1209
  title: g,
1196
- children: p > 0 ? `${i} ${m} · fresh in ${Ne(p)}` : `${i} ${m}`
1210
+ children: p > 0 ? `${i} ${m} · fresh in ${Fe(p)}` : `${i} ${m}`
1197
1211
  }), /* @__PURE__ */ l(G, {
1198
1212
  variant: "outline",
1199
1213
  size: "sm",
@@ -1201,9 +1215,9 @@ var Pe = {
1201
1215
  disabled: h,
1202
1216
  title: g,
1203
1217
  "aria-label": "Refresh roster",
1204
- className: Pe.refreshButton,
1218
+ className: Ie.refreshButton,
1205
1219
  children: /* @__PURE__ */ l("span", {
1206
- className: t ? Pe.spin : void 0,
1220
+ className: t ? Ie.spin : void 0,
1207
1221
  children: "⟳"
1208
1222
  })
1209
1223
  })]
@@ -1219,7 +1233,7 @@ var Pe = {
1219
1233
  "padding-md": "_padding-md_1vw8g_43",
1220
1234
  "padding-lg": "_padding-lg_1vw8g_47",
1221
1235
  hoverable: "_hoverable_1vw8g_52"
1222
- }, Ie = ({ children: e, variant: t = "default", chamfered: n = !1, chamferSize: r = "md", padding: i = "md", hoverable: a = !1, showDiagonalBorders: o = !0, edgeColor: s, className: d = "", onClick: f, style: p }) => {
1236
+ }, Re = ({ children: e, variant: t = "default", chamfered: n = !1, chamferSize: r = "md", padding: i = "md", hoverable: a = !1, showDiagonalBorders: o = !0, edgeColor: s, className: d = "", onClick: f, style: p }) => {
1223
1237
  let m = n ? r === "asymmetric" ? "chamfered-box-asymmetric" : r === "sm" ? "chamfered-box-sm" : r === "lg" ? "chamfered-box-lg" : "chamfered-box" : "", h = s ?? (n ? "var(--color-border)" : void 0), g = h ? { color: h } : void 0, _ = h ? {
1224
1238
  ...p,
1225
1239
  "--card-edge-color": h
@@ -1249,7 +1263,7 @@ var Pe = {
1249
1263
  })
1250
1264
  ] }), e]
1251
1265
  });
1252
- }, Le = {
1266
+ }, ze = {
1253
1267
  badge: "_badge_rk7t5_1",
1254
1268
  sm: "_sm_rk7t5_11",
1255
1269
  md: "_md_rk7t5_16",
@@ -1261,8 +1275,8 @@ var Pe = {
1261
1275
  warning: "_warning_rk7t5_47",
1262
1276
  error: "_error_rk7t5_52",
1263
1277
  info: "_info_rk7t5_57"
1264
- }, Re = ({ children: e, variant: t = "default", size: n = "md", className: r = "" }) => /* @__PURE__ */ l("span", {
1265
- className: `${Le.badge} ${Le[t]} ${Le[n]} ${r}`,
1278
+ }, Be = ({ children: e, variant: t = "default", size: n = "md", className: r = "" }) => /* @__PURE__ */ l("span", {
1279
+ className: `${ze.badge} ${ze[t]} ${ze[n]} ${r}`,
1266
1280
  children: e
1267
1281
  }), Q = {
1268
1282
  overlay: "_overlay_1b3yt_1",
@@ -1277,7 +1291,7 @@ var Pe = {
1277
1291
  title: "_title_1b3yt_53",
1278
1292
  closeButton: "_closeButton_1b3yt_60",
1279
1293
  content: "_content_1b3yt_78"
1280
- }, ze = ({ isOpen: e, onClose: t, title: n, children: r, size: i = "md", closeOnOverlayClick: o = !0, className: s = "" }) => (a(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
1294
+ }, Ve = ({ isOpen: e, onClose: t, title: n, children: r, size: i = "md", closeOnOverlayClick: o = !0, className: s = "" }) => (a(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
1281
1295
  document.body.style.overflow = "unset";
1282
1296
  }), [e]), a(() => {
1283
1297
  let n = (n) => {
@@ -1319,7 +1333,7 @@ var Pe = {
1319
1333
  dot: "_dot_1uhnh_34",
1320
1334
  bounce: "_bounce_1uhnh_1",
1321
1335
  visuallyHidden: "_visuallyHidden_1uhnh_91"
1322
- }, Be = ({ size: e = "md", variant: t = "spinner", className: n = "" }) => t === "dots" ? /* @__PURE__ */ u("div", {
1336
+ }, He = ({ size: e = "md", variant: t = "spinner", className: n = "" }) => t === "dots" ? /* @__PURE__ */ u("div", {
1323
1337
  className: `${$.dots} ${$[e]} ${n}`,
1324
1338
  children: [
1325
1339
  /* @__PURE__ */ l("span", { className: $.dot }),
@@ -1333,10 +1347,10 @@ var Pe = {
1333
1347
  className: $.visuallyHidden,
1334
1348
  children: "Loading..."
1335
1349
  })
1336
- }), Ve = async (e) => {
1350
+ }), Ue = async (e) => {
1337
1351
  if (e.length === 0) return {};
1338
1352
  let t = [...new Set(e)], n = await L.get(`/api/v1/users/lookup?ids=${t.join(",")}`);
1339
1353
  return Object.fromEntries(n.users.map((e) => [e.id, e.username]));
1340
1354
  };
1341
1355
  //#endregion
1342
- export { Ce as AllyCodeDropdown, oe as ApiClient, he as AuthProvider, Re as Badge, G as Button, Ie as Card, p as Container, Ae as Footer, xe as Input, Be as Loader, ze as Modal, ke as NavBar, Fe as RosterRefresh, _ as SUITE_NAV, be as Select, h as TopBar, L as apiClient, ae as authedFetch, pe as clearAllyCodes, D as clearTokens, j as configureAuthRefresh, Ve as fetchUsernames, q as formatAllyCode, Ne as formatCountdown, Me as formatRelativeTime, b as getAccessToken, z as getAllyCodesFromStorage, C as getRefreshToken, fe as getSelectedAllyCode, se as initializeApiClient, ee as isAuthenticated, g as isSuiteNavGroup, je as parseBackendTimestamp, M as refreshAccessToken, S as removeAccessToken, ue as removeAllyCodeFromStorage, T as removeRefreshToken, le as saveAllyCodeToStorage, x as setAccessToken, w as setRefreshToken, B as setSelectedAllyCode, E as setTokens, Se as unformatAllyCode, de as updateAllyCodeLastUsed, V as useAuth };
1356
+ export { Te as AllyCodeDropdown, oe as ApiClient, _e as AuthProvider, Be as Badge, G as Button, Re as Card, p as Container, Me as Footer, Ce as Input, He as Loader, Ve as Modal, je as NavBar, Le as RosterRefresh, _ as SUITE_NAV, Se as Select, h as TopBar, L as apiClient, ae as authedFetch, he as clearAllyCodes, D as clearTokens, A as configureAuthRefresh, Ue as fetchUsernames, q as formatAllyCode, Fe as formatCountdown, Pe as formatRelativeTime, b as getAccessToken, z as getAllyCodesFromStorage, C as getRefreshToken, me as getSelectedAllyCode, se as initializeApiClient, O as isAuthenticated, g as isSuiteNavGroup, Ne as parseBackendTimestamp, j as refreshAccessToken, S as removeAccessToken, fe as removeAllyCodeFromStorage, T as removeRefreshToken, de as saveAllyCodeToStorage, x as setAccessToken, w as setRefreshToken, B as setSelectedAllyCode, E as setTokens, we as unformatAllyCode, pe as updateAllyCodeLastUsed, V as useAuth };
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { User, LoginRequest, RegisterRequest, ForgotPasswordRequest, ResetPasswordRequest, ResendVerificationRequest, AllyCode, AllyCodeMigrationPrompt } from '../types';
2
+ import { User, LoginRequest, RegisterRequest, ForgotPasswordRequest, ResetPasswordRequest, ResendVerificationRequest, AllyCode, AllyCodeMigrationPrompt, UpdateAccountRequest, UpdateAccountResponse } from '../types';
3
3
  import { StoredAllyCode } from '../services/allyCodeStorage';
4
4
  export interface AuthContextValue {
5
5
  user: User | null;
@@ -8,10 +8,25 @@ export interface AuthContextValue {
8
8
  login: (credentials: LoginRequest) => Promise<void>;
9
9
  register: (data: RegisterRequest) => Promise<void>;
10
10
  logout: () => void;
11
+ /**
12
+ * Revoke every token for the account (server-side), then perform the same
13
+ * local sign-out as `logout()`. The local half always runs, even if the
14
+ * server call fails after the request lands, so the UI never stays "signed
15
+ * in" against a session the server will 401 on its next real call anyway.
16
+ */
17
+ logoutAll: () => Promise<void>;
11
18
  refreshUser: () => Promise<void>;
12
19
  forgotPassword: (data: ForgotPasswordRequest) => Promise<string>;
13
20
  resetPassword: (data: ResetPasswordRequest) => Promise<string>;
14
21
  resendVerification: (data: ResendVerificationRequest) => Promise<string>;
22
+ /**
23
+ * Change email and/or password (current_password required by the backend
24
+ * for either). Adopts the fresh tokens the change returns and updates
25
+ * `user` in place — including `is_verified` flipping back to false when the
26
+ * email changed. Throws on a wrong/missing current_password (400) or a
27
+ * locked account (403), same as every other auth action here.
28
+ */
29
+ updateAccount: (data: UpdateAccountRequest) => Promise<UpdateAccountResponse>;
15
30
  authEnabled: boolean;
16
31
  isLoadingFeatures: boolean;
17
32
  allyCodes: AllyCode[] | StoredAllyCode[];
@@ -20,4 +20,4 @@ export { fetchUsernames } from './services/users';
20
20
  export type { StoredAllyCode } from './services/allyCodeStorage';
21
21
  export { formatAllyCode, unformatAllyCode } from './utils/formatAllyCode';
22
22
  export { parseBackendTimestamp, formatRelativeTime, formatCountdown } from './utils/formatTime';
23
- export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, ApiResponse, ApiError, PaginatedResponse, ModStat, ParsedMod, ModListResponse, EvaluationScores, ModEvaluation, EvaluationRequest, EvaluationResponse, } from './types';
23
+ export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, TokenResponse, UpdateAccountRequest, UpdateAccountResponse, LogoutAllResponse, ApiResponse, ApiError, PaginatedResponse, ModStat, ParsedMod, ModListResponse, EvaluationScores, ModEvaluation, EvaluationRequest, EvaluationResponse, } from './types';
@@ -0,0 +1,21 @@
1
+ import { UpdateAccountRequest, UpdateAccountResponse } from '../types';
2
+ /**
3
+ * PATCH /users/me: change email and/or password. The backend requires
4
+ * `current_password` whenever either is set (a stolen access token alone must
5
+ * not be enough), and applies both together or not at all.
6
+ *
7
+ * A successful change revokes every outstanding token for the account,
8
+ * including the caller's own — so a fresh pair comes back in `tokens` and is
9
+ * adopted here immediately, before this function returns, so the caller's own
10
+ * session survives the change. `tokens` is `null` for a no-op body (nothing
11
+ * to change): nothing to adopt, nothing revoked.
12
+ */
13
+ export declare const updateAccount: (data: UpdateAccountRequest) => Promise<UpdateAccountResponse>;
14
+ /**
15
+ * POST /auth/logout-all: revoke every token for the account, including the
16
+ * caller's own. This only reaches the server — it does NOT clear this
17
+ * browser's stored tokens; the caller (AuthContext's `logoutAll`) does the
18
+ * local half so "revoked server-side" and "signed out here" always happen
19
+ * together.
20
+ */
21
+ export declare const logoutAllSessions: () => Promise<string>;
@@ -1,3 +1,3 @@
1
- export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, } from './user';
1
+ export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, TokenResponse, UpdateAccountRequest, UpdateAccountResponse, LogoutAllResponse, } from './user';
2
2
  export type { ApiResponse, ApiError, PaginatedResponse } from './api';
3
3
  export type { ModStat, ParsedMod, ModListResponse, EvaluationScores, ModEvaluation, EvaluationRequest, EvaluationResponse, } from './mod';
@@ -86,3 +86,27 @@ export interface AllyCodeMigrationPrompt {
86
86
  show: boolean;
87
87
  localStorageCodes: string[];
88
88
  }
89
+ export interface TokenResponse {
90
+ access_token: string;
91
+ refresh_token: string;
92
+ token_type: string;
93
+ expires_in: number;
94
+ }
95
+ export interface UpdateAccountRequest {
96
+ email?: string;
97
+ /** Required by the backend whenever `email` or `new_password` is set. */
98
+ current_password?: string;
99
+ new_password?: string;
100
+ }
101
+ /**
102
+ * PATCH /users/me response. `tokens` is set only when the email or password
103
+ * actually changed — that revokes every outstanding token for the account
104
+ * (including the caller's own), so fresh ones come back here. `null` means
105
+ * nothing changed (a no-op body, or the same email re-submitted).
106
+ */
107
+ export interface UpdateAccountResponse extends User {
108
+ tokens: TokenResponse | null;
109
+ }
110
+ export interface LogoutAllResponse {
111
+ message: string;
112
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astrogators-shared-ui",
3
- "version": "0.16.4",
3
+ "version": "0.17.0",
4
4
  "description": "Shared UI components and utilities for Astrogator's Table applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",