@object-ui/auth 17.5.0 → 17.6.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +148 -0
  3. package/dist/ActiveOrganizationStorage.d.ts +168 -0
  4. package/dist/ActiveOrganizationStorage.d.ts.map +1 -0
  5. package/dist/ActiveOrganizationStorage.js +515 -0
  6. package/dist/AuthContext.d.ts +19 -1
  7. package/dist/AuthContext.d.ts.map +1 -1
  8. package/dist/AuthGuard.d.ts +8 -1
  9. package/dist/AuthGuard.d.ts.map +1 -1
  10. package/dist/AuthGuard.js +16 -3
  11. package/dist/AuthProvider.d.ts +1 -1
  12. package/dist/AuthProvider.d.ts.map +1 -1
  13. package/dist/AuthProvider.js +272 -7
  14. package/dist/ForgotPasswordForm.d.ts +1 -1
  15. package/dist/ForgotPasswordForm.d.ts.map +1 -1
  16. package/dist/ForgotPasswordForm.js +5 -5
  17. package/dist/LoginForm.d.ts +1 -1
  18. package/dist/LoginForm.d.ts.map +1 -1
  19. package/dist/LoginForm.js +4 -4
  20. package/dist/PreviewBanner.js +1 -1
  21. package/dist/RegisterForm.d.ts +1 -1
  22. package/dist/RegisterForm.d.ts.map +1 -1
  23. package/dist/RegisterForm.js +3 -3
  24. package/dist/SocialSignInButtons.js +2 -2
  25. package/dist/UserMenu.js +2 -2
  26. package/dist/createAuthClient.d.ts +1 -1
  27. package/dist/createAuthClient.d.ts.map +1 -1
  28. package/dist/createAuthClient.js +36 -4
  29. package/dist/createAuthenticatedFetch.d.ts +9 -9
  30. package/dist/createAuthenticatedFetch.d.ts.map +1 -1
  31. package/dist/createAuthenticatedFetch.js +49 -37
  32. package/dist/index.d.ts +20 -19
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +28 -17
  35. package/dist/invitation-status.d.ts +59 -0
  36. package/dist/invitation-status.d.ts.map +1 -0
  37. package/dist/invitation-status.js +32 -0
  38. package/dist/types.d.ts +11 -4
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/useAuth.d.ts +1 -1
  41. package/dist/useAuth.d.ts.map +1 -1
  42. package/dist/useAuth.js +5 -1
  43. package/dist/useWorkspaceAdminStatus.d.ts +85 -0
  44. package/dist/useWorkspaceAdminStatus.d.ts.map +1 -0
  45. package/dist/useWorkspaceAdminStatus.js +102 -0
  46. package/package.json +4 -4
  47. package/dist/useIsWorkspaceAdmin.d.ts +0 -21
  48. package/dist/useIsWorkspaceAdmin.d.ts.map +0 -1
  49. package/dist/useIsWorkspaceAdmin.js +0 -47
@@ -7,10 +7,112 @@ import { jsx as _jsx } from "react/jsx-runtime";
7
7
  * LICENSE file in the root directory of this source tree.
8
8
  */
9
9
  import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
10
- import { authGateEvents } from './auth-gate-events';
11
- import { AuthCtx } from './AuthContext';
12
- import { createAuthClient, TokenStorage } from './createAuthClient';
13
- import { ActiveOrganizationStorage } from './createAuthenticatedFetch';
10
+ import { authGateEvents } from './auth-gate-events.js';
11
+ import { AuthCtx } from './AuthContext.js';
12
+ import { createAuthClient, TokenStorage } from './createAuthClient.js';
13
+ import { ActiveOrganizationStorage, SessionUserScope } from './ActiveOrganizationStorage.js';
14
+ /**
15
+ * Prefix of every `MetadataProvider` seed entry in `sessionStorage`
16
+ * (`objectui:metadata:<type>:<orgId>:<principal>`, `@object-ui/app-shell`).
17
+ *
18
+ * Spelled out here rather than imported: `@object-ui/app-shell` depends on
19
+ * `@object-ui/auth`, so the constant cannot travel in that direction without a
20
+ * dependency cycle. The two ends are held together by BEHAVIOUR instead of by
21
+ * a shared symbol — `MetadataProvider.crossPrincipalSeed.test.tsx` fills the
22
+ * cache by running the real `MetadataProvider` and empties it by signing out
23
+ * through this provider, so a prefix that drifts on either side fails there
24
+ * rather than silently purging nothing.
25
+ */
26
+ const METADATA_SEED_CACHE_PREFIX = 'objectui:metadata:';
27
+ /**
28
+ * Drop the client-side caches that belong to the session being ended
29
+ * (objectui#5198).
30
+ *
31
+ * `sessionStorage` is per-TAB, not per-session, and no sign-out call site
32
+ * reloads the page — `AppSidebar`, `AppHeader`, `UserMenu` and
33
+ * `RemediationOverlay` all just call `signOut()` and let the SPA keep running.
34
+ * So without this the next person to sign in in the same tab (a shared or
35
+ * kiosk browser, a handover, a support session) is SEEDED from the previous
36
+ * user's entry, and what is in it is that user's PERMISSION-FILTERED app list —
37
+ * the server filters `GET /api/v1/meta/:type` per session. That makes it a
38
+ * cross-principal disclosure, not ordinary staleness, which is why it is
39
+ * cleared here and not left to the tab being closed.
40
+ *
41
+ * Two properties of the loop are load-bearing:
42
+ *
43
+ * - It matches by PREFIX. The keys are org-scoped (objectui#4486), so a purge
44
+ * that recomputed the scope would depend on `ActiveOrganizationStorage`
45
+ * still holding the org those entries were written under. A prefix sweep has
46
+ * no such dependency and therefore no ordering hazard of its own.
47
+ * - It runs BEFORE `ActiveOrganizationStorage.clear()` anyway, so the ordering
48
+ * stays correct for anything scope-derived added later: clearing the org
49
+ * first would leave such a purge computing the no-org scope and deleting
50
+ * nothing while the real entries survived.
51
+ *
52
+ * `MetadataProvider` additionally keys the entry by session fingerprint, so a
53
+ * blob that escapes this purge (a tab open across the upgrade, a session ended
54
+ * by expiry rather than by this call) is unreadable rather than merely
55
+ * undeleted. The two halves are deliberately independent.
56
+ *
57
+ * ## The `try` guards the SNAPSHOT, not the walk (objectui#5777)
58
+ *
59
+ * `Object.keys(sessionStorage)` can itself throw — partitioned iframes, some
60
+ * privacy modes — and that is the reason a guard exists here at all, so it
61
+ * stays. What it must NOT do is wrap the loop: a `removeItem` that throws on
62
+ * key `n` would abort the walk, leaving every still-unvisited MATCHING key
63
+ * unswept, with the failure swallowed so the caller believes the sweep
64
+ * completed. The keys this purges are a cross-principal disclosure risk on a
65
+ * shared browser (objectui#5198), not ordinary staleness — a partial sweep
66
+ * leaves an arbitrary subset of the previous principal's permission-filtered
67
+ * app list readable to whoever signs in next in this tab. So each
68
+ * `removeItem` gets its own `try`: one uncooperative key costs exactly that
69
+ * key. Same defect class and same remedy as `sweepStore` in
70
+ * `ActiveOrganizationStorage.ts` (objectui#5763) — different file and
71
+ * different caller (sign-out, not sign-in) is why it is fixed here rather
72
+ * than there.
73
+ *
74
+ * ## Reported, not quarantined — same reason as `sweepStore`
75
+ *
76
+ * This function walks keys it does not own reads for: `MetadataProvider`
77
+ * (`@object-ui/app-shell`) is the reader of the seed cache, not this
78
+ * provider — there is no local `get()` here to guard, so there is nothing to
79
+ * quarantine the way `ActiveOrganizationStorage.clear()` quarantines a key
80
+ * (objectui#5731). What IS mirrored is the reporting channel: a key whose
81
+ * `removeItem` throws is named in a `console.warn`, so a partial sweep is
82
+ * discoverable instead of silent. The caller (`signOut`, above) cannot act on
83
+ * it either way — the session is already ending — so, like `sweepStore` on
84
+ * the sign-in path, this must not throw.
85
+ */
86
+ function purgeSignedOutClientCaches() {
87
+ if (typeof sessionStorage !== 'undefined') {
88
+ let keys;
89
+ try {
90
+ // Snapshot the keys first (`Object.keys`) — removing entries during a
91
+ // live index walk shifts the ones behind it and skips half of them.
92
+ // Same idiom as the `MarketplacePackagePage` purge loop.
93
+ keys = Object.keys(sessionStorage);
94
+ }
95
+ catch {
96
+ keys = []; /* storage unavailable */
97
+ }
98
+ const unswept = [];
99
+ for (const key of keys) {
100
+ if (!key.startsWith(METADATA_SEED_CACHE_PREFIX))
101
+ continue;
102
+ try {
103
+ sessionStorage.removeItem(key);
104
+ }
105
+ catch {
106
+ unswept.push(key);
107
+ }
108
+ }
109
+ if (unswept.length > 0) {
110
+ console.warn(`[purgeSignedOutClientCaches] could not remove ${unswept.length} key(s) from sessionStorage: ` +
111
+ `${unswept.join(', ')}. The signed-out user's metadata seed cache may still be readable under these keys.`);
112
+ }
113
+ }
114
+ ActiveOrganizationStorage.clear();
115
+ }
14
116
  /**
15
117
  * Authentication context provider.
16
118
  *
@@ -49,6 +151,12 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
49
151
  const [activeOrganization, setActiveOrganization] = useState(null);
50
152
  const [activeMember, setActiveMember] = useState(null);
51
153
  const [isOrganizationsLoading, setIsOrganizationsLoading] = useState(false);
154
+ // objectui#5619 — the two halves of "the membership answer has landed".
155
+ // Kept as POSITIVE resolution flags rather than another `isLoading`: a
156
+ // loading flag reads `false` both before the request starts and after it
157
+ // finishes, and that is precisely the ambiguity this card exists to remove.
158
+ const [organizationsResolved, setOrganizationsResolved] = useState(false);
159
+ const [activeMemberResolved, setActiveMemberResolved] = useState(false);
52
160
  // Determine if we're in preview mode
53
161
  const isPreviewMode = previewMode != null;
54
162
  // If auth is disabled or in preview mode, automatically set as authenticated
@@ -60,6 +168,19 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
60
168
  // `getSession` is already reflected in the answer we are about to apply, and
61
169
  // re-entering on it would loop this provider against the server forever.
62
170
  const sessionLoadInFlight = useRef(false);
171
+ // objectui#5750 — the org id `switchOrganization` last resolved to, tracked
172
+ // independently of React state so a switch that starts before the PREVIOUS
173
+ // switch's render has committed still compares against a value, not a stale
174
+ // closure. Kept in sync with every path that can move `activeOrganization`
175
+ // (not just `switchOrganization` itself — `refreshOrganizations`'
176
+ // single-membership repair also does), via the effect below.
177
+ const activeOrgIdRef = useRef(null);
178
+ // Bumped by every `switchOrganization` call that decides to re-resolve
179
+ // identity. Lets an EARLIER switch's still-in-flight `getSession()` notice
180
+ // a LATER switch superseded it and discard its answer instead of applying
181
+ // stale, previous-organization data over the newer one (see
182
+ // `switchOrganization`).
183
+ const sessionLoadGeneration = useRef(0);
63
184
  /**
64
185
  * The ONE session loader. Runs on mount (below) and on every later
65
186
  * re-resolution — `refreshSession` on the context, and the rotation
@@ -149,7 +270,13 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
149
270
  email: 'preview@preview.local',
150
271
  name,
151
272
  role,
152
- roles: [role],
273
+ // `positions` is the published spelling (framework ADR-0090 D3); this
274
+ // line was the LAST producer of the retired `roles` key
275
+ // (objectui#5424, maintainer ruling 2026-08-22). Emitting the position
276
+ // keeps every `positions` consumer — `AuthGuard`'s `requiredRoles`,
277
+ // the approver-identity derivations, workspace-admin leg 3 — seeing a
278
+ // preview identity shaped like a protocol-17 session.
279
+ positions: [role],
153
280
  });
154
281
  setSession({
155
282
  token: 'preview-token',
@@ -238,11 +365,27 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
238
365
  setUser(null);
239
366
  setSession(null);
240
367
  setError(null);
368
+ // The organization block is the previous principal's data too: the list
369
+ // is the workspaces THAT user belongs to (the switcher renders it), and
370
+ // a lingering `activeOrganization` would additionally suppress the
371
+ // re-resolution below — `refreshOrganizations` only asks the server for
372
+ // the active org `if (orgs.length > 0 && !activeOrganization)`, so the
373
+ // next sign-in in this tab would inherit the previous user's active
374
+ // workspace in context while storage had (correctly) forgotten it.
375
+ // `activeMember` follows from the effect that watches `activeOrganization`.
376
+ // Same pairing `deleteOrganization` / `leaveOrganization` already use in
377
+ // this file: drop the in-memory reference and the stored id together.
378
+ setOrganizations([]);
379
+ setActiveOrganization(null);
241
380
  }
242
381
  catch (err) {
243
382
  setError(err instanceof Error ? err : new Error(String(err)));
244
383
  }
245
384
  finally {
385
+ // Unconditional: `createAuthClient.signOut` clears `TokenStorage` BEFORE
386
+ // it rethrows a server error, so a failed call still leaves this tab
387
+ // without a session — the caches it authenticated for must go with it.
388
+ purgeSignedOutClientCaches();
246
389
  setIsLoading(false);
247
390
  }
248
391
  }, [client]);
@@ -453,6 +596,10 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
453
596
  finally {
454
597
  if (!isCancelled?.()) {
455
598
  setIsOrganizationsLoading(false);
599
+ // In `finally`, so a failed `listOrganizations` still counts as an
600
+ // answer. It is not a good answer, but leaving it unresolved would
601
+ // strand every gate that waits on it (objectui#5619).
602
+ setOrganizationsResolved(true);
456
603
  }
457
604
  }
458
605
  }, [client, enabled, isPreviewMode, activeOrganization]);
@@ -468,12 +615,25 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
468
615
  userId: 'preview-user',
469
616
  role,
470
617
  });
618
+ // Neither mode runs `refreshOrganizations` (its effect requires a real
619
+ // `user`, and the callback itself returns early), so this is the one
620
+ // place that can close BOTH halves for them (objectui#5619).
621
+ setOrganizationsResolved(true);
622
+ setActiveMemberResolved(true);
471
623
  return;
472
624
  }
473
625
  if (!activeOrganization) {
626
+ // "No active organization" is a real answer about the member row — but
627
+ // only once the org list itself has come back, which is what
628
+ // `organizationsResolved` below contributes. On mount this branch runs
629
+ // with the pipeline not yet started, and the combined flag stays false.
474
630
  setActiveMember(null);
631
+ setActiveMemberResolved(true);
475
632
  return;
476
633
  }
634
+ // A switch re-opens the question: until `getActiveMember()` answers for the
635
+ // NEW org, `activeMember` still holds the OLD org's row.
636
+ setActiveMemberResolved(false);
477
637
  try {
478
638
  const member = await client.getActiveMember();
479
639
  setActiveMember(member);
@@ -482,7 +642,42 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
482
642
  console.warn('[AuthProvider] Failed to load active member:', err);
483
643
  setActiveMember(null);
484
644
  }
645
+ finally {
646
+ setActiveMemberResolved(true);
647
+ }
485
648
  }, [client, enabled, isPreviewMode, previewMode, activeOrganization]);
649
+ /**
650
+ * objectui#5664 — the session-user-change invariant.
651
+ *
652
+ * Declared BEFORE the two effects below on purpose: effects run in the order
653
+ * their hooks were called, so this settles "whose browser is this" before
654
+ * `refreshActiveMember` and `refreshOrganizations` read or write anything
655
+ * org-scoped. `refreshOrganizations` in particular calls
656
+ * `ActiveOrganizationStorage.set()`, which resolves its key through the
657
+ * pointer this establishes.
658
+ *
659
+ * Keyed on the session user ID rather than wired into each of the five
660
+ * places that set `user` (mount / `refreshSession` / rotation, sign-in,
661
+ * sign-up, and the two provider flows). One implementation, and a sign-in
662
+ * path added later is covered without being told to be.
663
+ *
664
+ * Preview and auth-disabled mounts are excluded because their identities are
665
+ * SYNTHETIC — a fixed `preview-user` / `guest` id. Adopting one would read as
666
+ * a user change and purge a real user's state on any browser that opened a
667
+ * marketplace demo.
668
+ *
669
+ * What "purge" means, and why it is wholesale rather than key-by-key, is in
670
+ * `ActiveOrganizationStorage.ts`: it is an allowlist sweep, so the NEXT
671
+ * un-namespaced key is covered before anyone writes it.
672
+ */
673
+ useEffect(() => {
674
+ if (!enabled || isPreviewMode)
675
+ return;
676
+ const sessionUserId = user?.id;
677
+ if (!sessionUserId)
678
+ return;
679
+ SessionUserScope.adopt(sessionUserId);
680
+ }, [user?.id, enabled, isPreviewMode]);
486
681
  useEffect(() => {
487
682
  refreshActiveMember();
488
683
  }, [refreshActiveMember]);
@@ -494,8 +689,46 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
494
689
  refreshOrganizations(() => cancelled);
495
690
  return () => { cancelled = true; };
496
691
  }, [user, enabled, isPreviewMode]); // eslint-disable-line react-hooks/exhaustive-deps
692
+ // objectui#5750 — keep `activeOrgIdRef` current for every path that can
693
+ // move `activeOrganization`, not only `switchOrganization` (e.g.
694
+ // `refreshOrganizations`' single-membership repair calls
695
+ // `client.setActiveOrganization` directly). `switchOrganization` also
696
+ // writes it synchronously on its own success, below — this effect is the
697
+ // fallback for every OTHER path, and re-affirms after commit.
698
+ useEffect(() => {
699
+ activeOrgIdRef.current = activeOrganization?.id ?? null;
700
+ }, [activeOrganization]);
701
+ /**
702
+ * objectui#5750 — `switchOrganization` now DECLARES the re-resolution
703
+ * instead of relying on the objectui#4467 rotation subscription noticing
704
+ * one by accident.
705
+ *
706
+ * Why that accident cannot be trusted here: `POST /organization/set-active`
707
+ * always returns the SIGNED `token.signature` spelling in `set-auth-token`
708
+ * (better-auth's `bearer()` fires for any response that stages a session
709
+ * cookie), which differs from the UNSIGNED `session.token` spelling the
710
+ * client normally holds — so `TokenStorage.set` reads the flip as a
711
+ * rotation and the objectui#4467 subscription re-resolves identity. That
712
+ * accidental rotation is deterministic on the RAW token, not on the
713
+ * organization — so a SECOND switch whose response lands before the FIRST
714
+ * switch's follow-up `get-session` has re-armed it (re-stored the unsigned
715
+ * spelling) writes the SAME signed value already in storage. No value
716
+ * change, no notification, no re-resolution — `user.positions` is left
717
+ * answering for the organization the FIRST switch targeted, while
718
+ * `activeOrganization` already reads as the new one. Measured in #5749/#5750.
719
+ *
720
+ * The fix does not add a second call on the common path: it SUPPRESSES the
721
+ * accidental one (via `sessionLoadInFlight`, the same flag that already
722
+ * suppresses the rotation observed inside `loadSession`'s own
723
+ * `getSession()` call) and re-resolves explicitly instead, so a switch that
724
+ * changes the active organization still spends exactly one `get-session` —
725
+ * now unconditionally, so it does not depend on which spelling happened to
726
+ * already be in storage.
727
+ */
497
728
  const switchOrganization = useCallback(async (orgId) => {
498
729
  setError(null);
730
+ const previousOrgId = activeOrgIdRef.current;
731
+ sessionLoadInFlight.current = true;
499
732
  try {
500
733
  const org = await client.setActiveOrganization(orgId);
501
734
  setActiveOrganization(org);
@@ -506,13 +739,28 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
506
739
  else {
507
740
  ActiveOrganizationStorage.clear();
508
741
  }
742
+ const newOrgId = org?.id ?? null;
743
+ if (newOrgId !== previousOrgId) {
744
+ activeOrgIdRef.current = newOrgId;
745
+ // A LATER switch may already be in flight by the time this
746
+ // `getSession()` answer comes back (no debounce guards repeat
747
+ // switches — see the WorkspaceSwitcher/OrganizationLayout callers).
748
+ // Discard this answer if a newer switch has since claimed the
749
+ // generation, rather than clobber fresher, later-organization data
750
+ // with a stale, earlier one.
751
+ const generation = ++sessionLoadGeneration.current;
752
+ await loadSession(() => sessionLoadGeneration.current !== generation);
753
+ }
509
754
  }
510
755
  catch (err) {
511
756
  const authError = err instanceof Error ? err : new Error(String(err));
512
757
  setError(authError);
513
758
  throw authError;
514
759
  }
515
- }, [client]);
760
+ finally {
761
+ sessionLoadInFlight.current = false;
762
+ }
763
+ }, [client, loadSession]);
516
764
  const createOrganization = useCallback(async (data) => {
517
765
  setError(null);
518
766
  try {
@@ -576,6 +824,22 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
576
824
  // Guest mode (enabled=false) and preview mode both have hardcoded `isAuthenticated`
577
825
  // and a no-op signOut backend, so consumers should hide sign-out UIs.
578
826
  const isAuthEnabled = enabled && !isPreviewMode;
827
+ // objectui#5619 — see `AuthContext.isMembershipResolved` for the contract.
828
+ //
829
+ // Three modes, three reasons:
830
+ // - preview / auth-disabled: no pipeline runs; `refreshActiveMember`'s first
831
+ // branch closes both halves on its own effect.
832
+ // - no user: there is no membership to fetch, so the question is answered.
833
+ // Without this the flag would sit false forever on an unauthenticated
834
+ // visitor and hang any gate that waits on it. Consumers that must also
835
+ // wait for the SESSION read `isLoading` alongside this (the hook does).
836
+ // - signed in: both halves, because "no active organization" only means
837
+ // "no member row" once the org list has actually come back.
838
+ const isMembershipResolved = !isAuthEnabled
839
+ ? activeMemberResolved
840
+ : user == null
841
+ ? true
842
+ : organizationsResolved && activeMemberResolved;
579
843
  const value = useMemo(() => ({
580
844
  user,
581
845
  session,
@@ -611,6 +875,7 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
611
875
  activeOrganization,
612
876
  activeMember,
613
877
  isOrganizationsLoading,
878
+ isMembershipResolved,
614
879
  switchOrganization,
615
880
  createOrganization,
616
881
  refreshOrganizations,
@@ -633,7 +898,7 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
633
898
  signIn, signUp, signOut, refreshSession, updateUser, forgotPassword, sendVerificationEmail, resetPassword, changePassword, setInitialPassword, hasLocalPassword, getAuthConfig, signInWithProvider,
634
899
  sendPhoneOtp, signInWithPhoneOtp, signInWithPhonePassword, requestPhonePasswordReset, resetPasswordWithPhoneOtp,
635
900
  remediationRequired, enrollTotp, verifyTotp,
636
- organizations, activeOrganization, activeMember, isOrganizationsLoading, switchOrganization, createOrganization, refreshOrganizations,
901
+ organizations, activeOrganization, activeMember, isOrganizationsLoading, isMembershipResolved, switchOrganization, createOrganization, refreshOrganizations,
637
902
  updateOrganization, deleteOrganization, leaveOrganization,
638
903
  getMembers, inviteMember, describeDelegableScope, removeMember, updateMemberRole,
639
904
  listInvitations, cancelInvitation, getInvitation, acceptInvitation, rejectInvitation, listUserInvitations,
@@ -6,7 +6,7 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  import React from 'react';
9
- import type { AuthLinkComponentProps } from './types';
9
+ import type { AuthLinkComponentProps } from './types.js';
10
10
  /** Translatable labels for the ForgotPasswordForm */
11
11
  export interface ForgotPasswordFormLabels {
12
12
  emailLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ForgotPasswordForm.d.ts","sourceRoot":"","sources":["../src/ForgotPasswordForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAYtD,qDAAqD;AACrD,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wBAAwB;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,QAAmB,EACnB,KAA6B,EAC7B,WAAyF,EACzF,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,GACZ,EAAE,uBAAuB,qBA0UzB"}
1
+ {"version":3,"file":"ForgotPasswordForm.d.ts","sourceRoot":"","sources":["../src/ForgotPasswordForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAYzD,qDAAqD;AACrD,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wBAAwB;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,QAAmB,EACnB,KAA6B,EAC7B,WAAyF,EACzF,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,GACZ,EAAE,uBAAuB,qBA0UzB"}
@@ -7,8 +7,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  * LICENSE file in the root directory of this source tree.
8
8
  */
9
9
  import { useEffect, useState } from 'react';
10
- import { useAuth } from './useAuth';
11
- import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthMailIcon, AuthSpinner, } from './authStyles';
10
+ import { useAuth } from './useAuth.js';
11
+ import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthMailIcon, AuthSpinner, } from './authStyles.js';
12
12
  const DefaultLink = ({ href, className, children }) => (_jsx("a", { href: href, className: className, children: children }));
13
13
  const DefaultKeyIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", className: "h-6 w-6", "aria-hidden": "true", children: _jsx("path", { d: "M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" }) }));
14
14
  /**
@@ -72,7 +72,7 @@ export function ForgotPasswordForm({ onSuccess, onError, loginUrl = '/login', ti
72
72
  submittingButton: labels.submittingButton ?? 'Sending…',
73
73
  successTitle: labels.successTitle ?? 'Check your email',
74
74
  successDescription: labels.successDescription ??
75
- "We've sent a password reset link to {{email}}. Please check your inbox.",
75
+ "We've sent a password reset link to {email}. Please check your inbox.",
76
76
  backToSignInText: labels.backToSignInText ?? 'Back to sign in',
77
77
  rememberPasswordText: labels.rememberPasswordText ?? 'Remember your password?',
78
78
  signInText: labels.signInText ?? 'Sign in',
@@ -156,8 +156,8 @@ export function ForgotPasswordForm({ onSuccess, onError, loginUrl = '/login', ti
156
156
  return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: _jsx("span", { className: "flex h-12 w-12 items-center justify-center rounded-2xl bg-emerald-500/10 text-emerald-600 ring-1 ring-emerald-500/15 dark:text-emerald-400", children: _jsx(AuthMailIcon, {}) }), title: l.phoneSuccessTitle, description: l.phoneSuccessDescription }), loginUrl && (_jsx("p", { className: "text-center text-sm text-muted-foreground", children: _jsxs(LinkComp, { href: loginUrl, className: AUTH_LINK_CLASS, children: ["\u2190 ", l.backToSignInText] }) }))] }));
157
157
  }
158
158
  if (submitted) {
159
- const successMsg = l.successDescription.includes('{{email}}')
160
- ? l.successDescription.replace('{{email}}', email)
159
+ const successMsg = l.successDescription.includes('{email}')
160
+ ? l.successDescription.replace('{email}', email)
161
161
  : `${l.successDescription} ${email}`;
162
162
  return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: _jsx("span", { className: "flex h-12 w-12 items-center justify-center rounded-2xl bg-emerald-500/10 text-emerald-600 ring-1 ring-emerald-500/15 dark:text-emerald-400", children: _jsx(AuthMailIcon, {}) }), title: l.successTitle, description: successMsg }), loginUrl && (_jsx("p", { className: "text-center text-sm text-muted-foreground", children: _jsxs(LinkComp, { href: loginUrl, className: AUTH_LINK_CLASS, children: ["\u2190 ", l.backToSignInText] }) }))] }));
163
163
  }
@@ -6,7 +6,7 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  import React from 'react';
9
- import type { AuthLinkComponentProps } from './types';
9
+ import type { AuthLinkComponentProps } from './types.js';
10
10
  /** Translatable labels for the LoginForm */
11
11
  export interface LoginFormLabels {
12
12
  emailLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../src/LoginForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAYtD,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8GAA8G;IAC9G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gGAAgG;IAChG,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,yHAAyH;IACzH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,OAAO,EACP,WAAyB,EACzB,iBAAsC,EACtC,KAAiC,EACjC,WAAyD,EACzD,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,EACX,aAAa,GACd,EAAE,cAAc,qBAgbhB"}
1
+ {"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../src/LoginForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAYzD,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8GAA8G;IAC9G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gGAAgG;IAChG,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,yHAAyH;IACzH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,OAAO,EACP,WAAyB,EACzB,iBAAsC,EACtC,KAAiC,EACjC,WAAyD,EACzD,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,EACX,aAAa,GACd,EAAE,cAAc,qBAgbhB"}
package/dist/LoginForm.js CHANGED
@@ -7,10 +7,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
7
7
  * LICENSE file in the root directory of this source tree.
8
8
  */
9
9
  import { useEffect, useState } from 'react';
10
- import { useAuth } from './useAuth';
11
- import { SocialSignInButtons } from './SocialSignInButtons';
12
- import { looksLikePhoneIdentifier, normalizePhoneIdentifier } from './phone-identifier';
13
- import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthSpinner, } from './authStyles';
10
+ import { useAuth } from './useAuth.js';
11
+ import { SocialSignInButtons } from './SocialSignInButtons.js';
12
+ import { looksLikePhoneIdentifier, normalizePhoneIdentifier } from './phone-identifier.js';
13
+ import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthSpinner, } from './authStyles.js';
14
14
  const DefaultLink = ({ href, className, children }) => (_jsx("a", { href: href, className: className, children: children }));
15
15
  const DefaultLockIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", className: "h-6 w-6", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] }));
16
16
  /**
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useAuth } from './useAuth';
2
+ import { useAuth } from './useAuth.js';
3
3
  /**
4
4
  * Banner component that displays a message when the app is in preview mode.
5
5
  * Only renders when preview mode is active. Uses the bannerMessage from
@@ -6,7 +6,7 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  import React from 'react';
9
- import type { AuthLinkComponentProps } from './types';
9
+ import type { AuthLinkComponentProps } from './types.js';
10
10
  /** Translatable labels for the RegisterForm */
11
11
  export interface RegisterFormLabels {
12
12
  nameLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"RegisterForm.d.ts","sourceRoot":"","sources":["../src/RegisterForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAWtD,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC;sFACkF;IAClF,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;2CAEuC;IACvC,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAwBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,sBAAsB,EACtB,OAAO,EACP,QAAmB,EACnB,KAA2B,EAC3B,WAAqD,EACrD,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,EACX,aAAa,GACd,EAAE,iBAAiB,qBAuKnB"}
1
+ {"version":3,"file":"RegisterForm.d.ts","sourceRoot":"","sources":["../src/RegisterForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAWzD,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC;sFACkF;IAClF,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;2CAEuC;IACvC,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAwBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,sBAAsB,EACtB,OAAO,EACP,QAAmB,EACnB,KAA2B,EAC3B,WAAqD,EACrD,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,EACX,aAAa,GACd,EAAE,iBAAiB,qBAuKnB"}
@@ -7,9 +7,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  * LICENSE file in the root directory of this source tree.
8
8
  */
9
9
  import { useState } from 'react';
10
- import { useAuth } from './useAuth';
11
- import { SocialSignInButtons } from './SocialSignInButtons';
12
- import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthSpinner, } from './authStyles';
10
+ import { useAuth } from './useAuth.js';
11
+ import { SocialSignInButtons } from './SocialSignInButtons.js';
12
+ import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthSpinner, } from './authStyles.js';
13
13
  const DefaultLink = ({ href, className, children }) => (_jsx("a", { href: href, className: className, children: children }));
14
14
  const DefaultUserPlusIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", className: "h-6 w-6", "aria-hidden": "true", children: [_jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }), _jsx("circle", { cx: "9", cy: "7", r: "4" }), _jsx("line", { x1: "19", y1: "8", x2: "19", y2: "14" }), _jsx("line", { x1: "22", y1: "11", x2: "16", y2: "11" })] }));
15
15
  /**
@@ -7,8 +7,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  * LICENSE file in the root directory of this source tree.
8
8
  */
9
9
  import { useEffect, useState } from 'react';
10
- import { useAuth } from './useAuth';
11
- import { AuthSpinner } from './authStyles';
10
+ import { useAuth } from './useAuth.js';
11
+ import { AuthSpinner } from './authStyles.js';
12
12
  // Brand name overrides for providers whose `name` from the server may be unset
13
13
  // or where we want to canonicalize casing.
14
14
  const PROVIDER_LABEL = {
package/dist/UserMenu.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth } from './useAuth';
3
- import { getUserInitials } from './types';
2
+ import { useAuth } from './useAuth.js';
3
+ import { getUserInitials } from './types.js';
4
4
  /**
5
5
  * User menu component displaying the authenticated user's info.
6
6
  * Shows avatar, name, email, and common actions (profile, settings, sign out).
@@ -5,7 +5,7 @@
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
- import type { AuthClient, AuthClientConfig } from './types';
8
+ import type { AuthClient, AuthClientConfig } from './types.js';
9
9
  /**
10
10
  * Simple token storage backed by localStorage.
11
11
  * Falls back to in-memory storage when localStorage is unavailable (SSR, tests).
@@ -1 +1 @@
1
- {"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,UAAU,EAAE,gBAAgB,EAE7B,MAAM,SAAS,CAAC;AAIjB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY;kBACD,MAAM,GAAG,IAAI;kCACD,IAAI;WAE/B,MAAM,GAAG,IAAI;eAST,MAAM,GAAG,IAAI;aAkBf,IAAI;IASb;;;OAGG;gCACyB,MAAM,IAAI,GAAG,MAAM,IAAI;CAMpD,CAAC;AAwIF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAqrBrE"}
1
+ {"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,UAAU,EAAE,gBAAgB,EAE7B,MAAM,YAAY,CAAC;AAKpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY;kBACD,MAAM,GAAG,IAAI;kCACD,IAAI;WAE/B,MAAM,GAAG,IAAI;eAST,MAAM,GAAG,IAAI;aAkBf,IAAI;IASb;;;OAGG;gCACyB,MAAM,IAAI,GAAG,MAAM,IAAI;CAMpD,CAAC;AA2KF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAqrBrE"}
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import { createAuthClient as createBetterAuthClient } from 'better-auth/client';
9
9
  import { organizationClient, twoFactorClient } from 'better-auth/client/plugins';
10
+ import { AUTH_INVITATION_STATUSES, isAuthInvitationStatus } from './invitation-status.js';
10
11
  const TOKEN_STORAGE_KEY = 'auth-session-token';
11
12
  /**
12
13
  * Simple token storage backed by localStorage.
@@ -109,6 +110,37 @@ function toAuthError(error, fallbackMessage) {
109
110
  err.code = error.code;
110
111
  return err;
111
112
  }
113
+ /**
114
+ * The wire boundary for invitations (objectui#3879).
115
+ *
116
+ * better-auth's client hands these routes back as `any`, so `as AuthInvitation`
117
+ * was a claim nothing checked — and with `status` narrowed to a closed union,
118
+ * an unchecked cast would make that union a comment again the day a backend
119
+ * stored a fifth value. This is the ONE place the claim is verified.
120
+ *
121
+ * It fails LOUDLY, naming the offending value, rather than degrading: a status
122
+ * outside better-auth's own `InvitationStatus` is a producer defect, and the
123
+ * alternatives all hide it — a neutral badge label renders it as UI copy in ten
124
+ * packs (the objectui#3879 symptom), and dropping the row deletes an invitation
125
+ * from an administrative ledger without saying so. Both call paths already
126
+ * render a rejection with a retry (`InvitationsPage`, `AcceptInvitationPage`),
127
+ * so the throw lands on a designed surface; `resolveOrgErrorMessage` shows the
128
+ * sentence verbatim, which is that module's own stated preference over
129
+ * swallowing an error.
130
+ */
131
+ function asAuthInvitation(raw, method) {
132
+ const status = raw?.status;
133
+ if (!isAuthInvitationStatus(status)) {
134
+ throw new Error(`${method}: unexpected invitation status ${JSON.stringify(status)} — ` +
135
+ `expected one of ${AUTH_INVITATION_STATUSES.join(' | ')}`);
136
+ }
137
+ return raw;
138
+ }
139
+ /** Same boundary, per row, for the list-returning invitation routes. */
140
+ function asAuthInvitations(raw, method) {
141
+ const rows = Array.isArray(raw) ? raw : [];
142
+ return rows.map((row) => asAuthInvitation(row, method));
143
+ }
112
144
  /**
113
145
  * Resolve a baseURL (which may be relative or absolute) into the
114
146
  * `{ origin, basePath }` pair required by the better-auth client.
@@ -753,7 +785,7 @@ export function createAuthClient(config) {
753
785
  });
754
786
  if (error)
755
787
  throw toAuthError(error, 'Failed to invite member');
756
- return data;
788
+ return asAuthInvitation(data, 'inviteMember');
757
789
  },
758
790
  async removeMember(removeData) {
759
791
  const { error } = await betterAuth.organization.removeMember({
@@ -802,7 +834,7 @@ export function createAuthClient(config) {
802
834
  });
803
835
  if (error)
804
836
  throw toAuthError(error, 'Failed to list invitations');
805
- return (data ?? []);
837
+ return asAuthInvitations(data, 'listInvitations');
806
838
  },
807
839
  async cancelInvitation(invitationId) {
808
840
  const { error } = await betterAuth.organization.cancelInvitation({ invitationId });
@@ -815,7 +847,7 @@ export function createAuthClient(config) {
815
847
  });
816
848
  if (error)
817
849
  throw toAuthError(error, 'Failed to load invitation');
818
- return data;
850
+ return asAuthInvitation(data, 'getInvitation');
819
851
  },
820
852
  async acceptInvitation(invitationId) {
821
853
  const { error } = await betterAuth.organization.acceptInvitation({ invitationId });
@@ -831,7 +863,7 @@ export function createAuthClient(config) {
831
863
  const { data, error } = await betterAuth.organization.listUserInvitations();
832
864
  if (error)
833
865
  throw toAuthError(error, 'Failed to list invitations');
834
- return (data ?? []);
866
+ return asAuthInvitations(data, 'listUserInvitations');
835
867
  },
836
868
  };
837
869
  }