ab-ecosystem-sso 0.1.11 → 0.1.13

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/README.md CHANGED
@@ -13,7 +13,7 @@ Drop-in React auth & account UI for the partner-ecosystem **Auth-as-a-Service**
13
13
 
14
14
  - [Installation](#installation)
15
15
  - [Configuration basics](#configuration-basics)
16
- - [Auth screens](#auth-screens) — `Login` · `Signup` · `ForgotPassword`
16
+ - [Auth screens](#auth-screens) — `Login` · `Signup` · `ForgotPassword` · `VerifyEmail`
17
17
  - [Session management](#session-management) — `SessionProvider`, enforce subscription
18
18
  - [Account Settings modal](#account-settings-modal) — `openAccountSettings` / `AccountSettings`
19
19
  - [Logout](#logout) — `logout` · `LogoutButton` · `logoutApi`
@@ -86,6 +86,8 @@ function LoginPage() {
86
86
 
87
87
  `Login` first fetches the project's `auth-config` (captcha provider/site-key, branding, which links to show) and renders accordingly. If the account has **2FA** enabled it automatically shows a **segmented 6-digit OTP** step (with captcha when the project requires it), and only calls `onSuccess` after verification succeeds.
88
88
 
89
+ **Magic-link sign-in** works automatically: point your magic link at `/login#<access_token>` (a bare `/login#access_token=<token>` is also accepted). On mount, `Login` reads the token from the URL hash, validates it with a `/me` call, and — if valid — strips it from the URL and fires `onSuccess({ token, user })`, exactly like a password sign-in. While it validates, a loading state shows; if the token is invalid or expired, it falls back to the normal sign-in form with a short notice (and calls `onError`). No extra wiring needed beyond routing the link to your login page.
90
+
89
91
  ### `Signup` and `ForgotPassword`
90
92
 
91
93
  ```tsx
@@ -95,6 +97,41 @@ import { Signup, ForgotPassword } from "ab-ecosystem-sso";
95
97
  <ForgotPassword projectId="…" onBackToLogin={() => navigate("/login")} />
96
98
  ```
97
99
 
100
+ ### `VerifyEmail`
101
+
102
+ The email-verification screen for a `/verify/:token` route — the link you email to new users. It shows a captcha (site key from the project's auth-config), then posts the captcha + token to `/auth/verify-email`.
103
+
104
+ ```tsx
105
+ import { VerifyEmail } from "ab-ecosystem-sso";
106
+
107
+ // e.g. React Router: <Route path="/verify/:token" element={<VerifyPage />} />
108
+ function VerifyPage() {
109
+ const { token } = useParams();
110
+ return (
111
+ <VerifyEmail
112
+ projectId="your-project-id"
113
+ apiBaseUrl="https://your-api"
114
+ token={token}
115
+ onVerified={() => navigate("/login")}
116
+ onLoginClick={() => navigate("/login")}
117
+ onSignupClick={() => navigate("/signup")}
118
+ onError={(err) => console.error(err)}
119
+ />
120
+ );
121
+ }
122
+ ```
123
+
124
+ On success it calls `onVerified` (send the user to login) and shows a **Continue to sign in** button. On failure it shows a **Verification failed** card with the reason plus **Go to sign in** / **Go to sign up** buttons. Verification counts as successful only when the response is 2xx **and** `success: true`.
125
+
126
+ | Prop | Type | Notes |
127
+ | --- | --- | --- |
128
+ | `token` | `string` | The token from your route params. Falls back to the last path segment of the URL. |
129
+ | `onVerified` | `() => void` | Fires once the email is verified. |
130
+ | `onLoginClick` | `() => void` | Navigate to login (shown on success and failure). |
131
+ | `onSignupClick` | `() => void` | Navigate to signup (shown on failure). |
132
+
133
+ > Prefer passing `token` from your router. The URL fallback only exists so the component works on a plain `/verify/:token` page with no router wired up.
134
+
98
135
  ### Shared auth props
99
136
 
100
137
  | Prop | Type | Notes |
@@ -106,7 +143,7 @@ import { Signup, ForgotPassword } from "ab-ecosystem-sso";
106
143
  | `onError` | `(error: Error) => void` | On failure. |
107
144
  | `classNames` | `AuthClassNames` | Per-element class overrides: `card`, `input`, `label`, `button`, `link`, `captcha`, `error`, … |
108
145
 
109
- Per-screen extras: `Login` adds `onForgotPassword` / `onSignupClick`; `Signup` adds `onLoginClick`; `ForgotPassword` adds `onBackToLogin`.
146
+ Per-screen extras: `Login` adds `onForgotPassword` / `onSignupClick`; `Signup` adds `onLoginClick`; `ForgotPassword` adds `onBackToLogin`; `VerifyEmail` adds `token` / `onVerified` / `onLoginClick` / `onSignupClick` (and has no `onSuccess`, since no session is created).
110
147
 
111
148
  ---
112
149
 
@@ -199,6 +236,7 @@ const [open, setOpen] = useState(false);
199
236
  | `token` | `string` | Bearer token. |
200
237
  | `apiBaseUrl` | `string` | Optional API origin. |
201
238
  | `initialSection` | `"general" \| "account" \| "wallet" \| "plans" \| "credits"` | First section shown. Default `"general"`. |
239
+ | `syncUrlHash` | `boolean` | Mirror open state + active section in the URL hash. Default `true`. See [URL hash & refresh](#url-hash--refresh). |
202
240
  | `title` | `string` | Modal heading. Default `"Settings"`. |
203
241
  | `data` | `Partial<AccountSettingsData>` | Override sample data (non-API mode / previews). |
204
242
  | `onLogout` | `() => void` | Sign-out action (closes the modal, then runs this). |
@@ -209,6 +247,23 @@ const [open, setOpen] = useState(false);
209
247
 
210
248
  > In live mode the modal performs the API calls itself (save profile, change password, subscribe, recharge, etc.); the callbacks are observation hooks, not required wiring.
211
249
 
250
+ ### URL hash & refresh
251
+
252
+ While the modal is open it reflects the active section in the URL hash as `#settings-<section>` (e.g. `#settings-general`, `#settings-plans`), updating as the user switches tabs and clearing it on close. This means a **page refresh can re-open the modal on the same section**. It uses `history.replaceState`, so it never adds browser-history entries and never clobbers an unrelated `#anchor`. Opt out with `syncUrlHash={false}`.
253
+
254
+ - **Declarative** `<AccountSettings>`: keep it mounted (even while closed) and wire `open`/`onOpenChange` normally — on load it reads the hash and calls `onOpenChange(true)` for you.
255
+ - **Imperative** `openAccountSettings()`: call `restoreAccountSettings()` once on app load to re-open it after a refresh:
256
+
257
+ ```tsx
258
+ import { restoreAccountSettings } from "ab-ecosystem-sso";
259
+
260
+ useEffect(() => {
261
+ restoreAccountSettings({ projectId: "your-project-id", token, apiBaseUrl: "https://your-api" });
262
+ }, []);
263
+ ```
264
+
265
+ It opens the modal (on the hash's section) only when a `#settings-*` hash is present, and returns the modal handle (or `null`).
266
+
212
267
  ---
213
268
 
214
269
  ## Logout
@@ -344,6 +399,8 @@ Beyond the components, these functions are exported for building custom UIs:
344
399
 
345
400
  | Function | Endpoint |
346
401
  | --- | --- |
402
+ | `getAuthConfig(projectId, apiBaseUrl?)` | `GET /auth-config` → `AuthConfig` (captcha, branding, card layout; no token) |
403
+ | `verifyEmailApi(projectId, { token, captchaToken }, apiBaseUrl?)` | `POST /auth/verify-email` |
347
404
  | `getUser(projectId, token, apiBaseUrl?)` | `GET /me` (raw envelope) |
348
405
  | `getUserProfile(projectId, token, apiBaseUrl?)` | `GET /me` → `MappedProfile` |
349
406
  | `getUserWallet(projectId, token, apiBaseUrl?)` | `GET /me` → `UserWallets` |
@@ -362,7 +419,7 @@ Everything is fully typed. Notable exports:
362
419
 
363
420
  ```ts
364
421
  import type {
365
- LoginProps, SignupProps, ForgotPasswordProps, AuthClassNames,
422
+ LoginProps, SignupProps, ForgotPasswordProps, VerifyEmailProps, AuthClassNames,
366
423
  AccountSettingsProps, AccountSettingsSection, AccountSettingsData, ProfileFormValues,
367
424
  OpenAccountSettingsOptions, AccountSettingsHandle,
368
425
  AuthConfig, CaptchaConfig, CardLayoutConfig,