ab-ecosystem-sso 0.1.6 → 0.1.7

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 ADDED
@@ -0,0 +1,280 @@
1
+ # ab-ecosystem-sso
2
+
3
+ Drop-in React auth & account UI for the partner-ecosystem **Auth-as-a-Service** backend — login, signup, forgot-password, two-factor, session validation, and a full Account Settings modal (profile, wallet, plans & add-ons, credit wallets), all wired to the `/api/v1/projects/:projectId/...` endpoints.
4
+
5
+ - ⚛️ React 18 / 19 components, shipped as ESM + CJS with TypeScript types.
6
+ - 🎨 Self-contained, theme-aware styles (scoped so they won't leak into your app).
7
+ - 🔌 Works declaratively (`<AccountSettings />`) or imperatively (`openAccountSettings()`).
8
+ - 🧩 Low-level helpers (`getUser`, `logout`, `useSession`) for building your own UI.
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install ab-ecosystem-sso
16
+ ```
17
+
18
+ `react` and `react-dom` are **peer dependencies** (v18 or v19) — make sure they're installed in your app.
19
+
20
+ ### Import the stylesheet once
21
+
22
+ The components ship a single CSS file. Import it once at your app's entry point:
23
+
24
+ ```ts
25
+ import "ab-ecosystem-sso/styles.css";
26
+ ```
27
+
28
+ Styles are scoped (Tailwind `sso:` prefix + a `[data-aas]` root on the settings modal) so they won't collide with your app's CSS.
29
+
30
+ ---
31
+
32
+ ## Configuration
33
+
34
+ Every component/function takes:
35
+
36
+ | Prop | Description |
37
+ | --- | --- |
38
+ | `projectId` | Your project id, e.g. `436582-forms.abprojects.com`. Required. |
39
+ | `token` | The auth JWT (from the login response). Required for authenticated calls. |
40
+ | `apiBaseUrl` | API origin override, e.g. `https://partner-api.example.com`. Falls back to the `VITE_AUTH_API_BASE_URL` env var. |
41
+
42
+ ---
43
+
44
+ ## Auth screens
45
+
46
+ ### Login
47
+
48
+ ```tsx
49
+ import { Login } from "ab-ecosystem-sso";
50
+ import "ab-ecosystem-sso/styles.css";
51
+
52
+ function LoginPage() {
53
+ return (
54
+ <Login
55
+ projectId="your-project-id"
56
+ apiBaseUrl="https://your-api"
57
+ onSuccess={({ token, user }) => {
58
+ localStorage.setItem("token", token);
59
+ window.location.href = "/dashboard";
60
+ }}
61
+ onError={(err) => console.error(err)}
62
+ onForgotPassword={() => navigate("/forgot-password")}
63
+ onSignupClick={() => navigate("/signup")}
64
+ />
65
+ );
66
+ }
67
+ ```
68
+
69
+ `Login` fetches the project's `auth-config` (captcha, 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 required) and completes the flow before calling `onSuccess`.
70
+
71
+ ### Signup & Forgot password
72
+
73
+ ```tsx
74
+ import { Signup, ForgotPassword } from "ab-ecosystem-sso";
75
+
76
+ <Signup projectId="…" onSuccess={…} onLoginClick={() => navigate("/login")} />
77
+ <ForgotPassword projectId="…" onBackToLogin={() => navigate("/login")} />
78
+ ```
79
+
80
+ ### Common auth props
81
+
82
+ | Prop | Type | Notes |
83
+ | --- | --- | --- |
84
+ | `projectId` | `string` | Required. |
85
+ | `apiBaseUrl` | `string` | Optional API origin. |
86
+ | `config` | `AuthConfig` | Pre-fetched auth-config to skip the internal request. |
87
+ | `onSuccess` | `({ token, user }) => void` | Called on successful auth. |
88
+ | `onError` | `(error: Error) => void` | Called on failure. |
89
+ | `classNames` | `AuthClassNames` | Per-element class overrides (`input`, `button`, `card`, …). |
90
+
91
+ ---
92
+
93
+ ## Session validation
94
+
95
+ Wrap authenticated areas of your app in `SessionProvider`. It validates the token against `/me` and renders children only when the session is valid; otherwise it calls `onSessionInvalid` (navigate to login there).
96
+
97
+ ```tsx
98
+ import { SessionProvider } from "ab-ecosystem-sso";
99
+
100
+ <SessionProvider
101
+ projectId="your-project-id"
102
+ token={token}
103
+ apiBaseUrl="https://your-api"
104
+ onSessionInvalid={() => navigate("/login")}
105
+ >
106
+ <Dashboard />
107
+ </SessionProvider>
108
+ ```
109
+
110
+ ### Enforce an active subscription
111
+
112
+ Pass `enforceActiveSubscription` and, once authenticated, the provider checks the user's subscription. If none is active it opens the Account Settings modal on the **Plans** section — and blocks closing until a subscription exists (re-checking on each close attempt).
113
+
114
+ ```tsx
115
+ <SessionProvider … enforceActiveSubscription>
116
+ <Dashboard />
117
+ </SessionProvider>
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Account Settings modal
123
+
124
+ A full settings surface: **General** (profile), **Account** (email, change password, 2FA, sessions), **Wallet & Balance**, **Plans & Add-ons**, and **Credit Wallets**. It loads/saves via the live API when given `projectId` + `token`.
125
+
126
+ ### Imperative (recommended)
127
+
128
+ Open it from any click handler; it mounts into `<body>` and unmounts on close:
129
+
130
+ ```tsx
131
+ import { openAccountSettings } from "ab-ecosystem-sso";
132
+
133
+ <button onClick={() => openAccountSettings({
134
+ projectId: "your-project-id",
135
+ token,
136
+ apiBaseUrl: "https://your-api",
137
+ initialSection: "plans", // optional
138
+ onLogout: () => { localStorage.clear(); navigate("/login"); },
139
+ })}>
140
+ Settings
141
+ </button>
142
+ ```
143
+
144
+ `openAccountSettings(options)` returns `{ close() }` to dismiss it programmatically.
145
+
146
+ ### Declarative
147
+
148
+ ```tsx
149
+ import { AccountSettings } from "ab-ecosystem-sso";
150
+
151
+ const [open, setOpen] = useState(false);
152
+
153
+ <AccountSettings
154
+ open={open}
155
+ onOpenChange={setOpen}
156
+ projectId="your-project-id"
157
+ token={token}
158
+ apiBaseUrl="https://your-api"
159
+ initialSection="general"
160
+ onLogout={() => { localStorage.clear(); navigate("/login"); }}
161
+ />
162
+ ```
163
+
164
+ `initialSection` is one of `"general" | "account" | "billing" | "wallet" | "plans" | "credits"`.
165
+
166
+ ---
167
+
168
+ ## Logout
169
+
170
+ Three options, from most convenient to most raw:
171
+
172
+ ```tsx
173
+ import { LogoutButton, logout, logoutApi } from "ab-ecosystem-sso";
174
+
175
+ // 1) Ready-made button (no SessionProvider needed in standalone mode)
176
+ <LogoutButton
177
+ projectId="your-project-id"
178
+ token={token}
179
+ apiBaseUrl="https://your-api"
180
+ onSuccess={() => { localStorage.clear(); navigate("/login"); }}
181
+ />
182
+
183
+ // 2) A method to attach to any custom control (e.g. a profile-dropdown item)
184
+ onClick={() => logout({
185
+ projectId: "your-project-id",
186
+ token,
187
+ apiBaseUrl: "https://your-api",
188
+ onSuccess: () => { localStorage.clear(); navigate("/login"); },
189
+ })}
190
+
191
+ // 3) The raw endpoint call
192
+ await logoutApi("your-project-id", token, "https://your-api");
193
+ ```
194
+
195
+ `logout` POSTs to `/auth/logout` and always runs `onSuccess` once the request settles — so the user is logged out client-side even if the server call fails (`onError` fires for observability). Inside a `SessionProvider`, `<LogoutButton />` (no props) uses the provider's logout instead.
196
+
197
+ ---
198
+
199
+ ## Fetch the current user
200
+
201
+ Populate your own header/profile-dropdown from `/me`:
202
+
203
+ ```tsx
204
+ import { getUser } from "ab-ecosystem-sso";
205
+
206
+ const res = await getUser("your-project-id", token, "https://your-api");
207
+ const name = res.data.profile.name.first; // { success, data: { id, username, profile, mainWallet, coinWallet } }
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Two-factor setup (standalone)
213
+
214
+ For a settings page outside the modal:
215
+
216
+ ```tsx
217
+ import { TwoFactorSetup } from "ab-ecosystem-sso";
218
+
219
+ <TwoFactorSetup
220
+ projectId="your-project-id"
221
+ token={token}
222
+ apiBaseUrl="https://your-api"
223
+ onEnabled={() => …}
224
+ onDisabled={() => …}
225
+ />
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Hooks
231
+
232
+ | Hook | Returns |
233
+ | --- | --- |
234
+ | `useSession()` | `{ isAuthenticated, isValidating, logout }` — must be inside a `SessionProvider`. |
235
+ | `useOptionalSession()` | Same, or `null` when there is no provider. |
236
+ | `useAuthConfig()` | The project's auth-config (captcha, branding, card layout). |
237
+
238
+ ---
239
+
240
+ ## Theming
241
+
242
+ The UI reads CSS custom properties (design tokens), so you can retheme without touching the components. Override the `--aas-*` variables on `:root` (or a parent) after importing the stylesheet:
243
+
244
+ ```css
245
+ :root {
246
+ --aas-primary: #4f46e5;
247
+ --aas-primary-foreground: #ffffff;
248
+ --aas-background: #ffffff;
249
+ --aas-foreground: #0f172a;
250
+ --aas-muted: #f1f5f9;
251
+ --aas-muted-foreground: #64748b;
252
+ --aas-border: #e2e8f0;
253
+ --aas-radius: 0.5rem;
254
+ }
255
+ ```
256
+
257
+ Styles are dark-mode/theme aware and scoped to the components, so they won't affect the rest of your app.
258
+
259
+ ---
260
+
261
+ ## TypeScript
262
+
263
+ Everything is fully typed. Notable exports:
264
+
265
+ ```ts
266
+ import type {
267
+ LoginProps, SignupProps, ForgotPasswordProps, AuthClassNames,
268
+ AccountSettingsProps, AccountSettingsSection,
269
+ OpenAccountSettingsOptions, AccountSettingsHandle,
270
+ AuthConfig, CaptchaConfig, CardLayoutConfig,
271
+ LoginRequest, AuthResponse, LogoutOptions,
272
+ } from "ab-ecosystem-sso";
273
+ import { AuthApiError } from "ab-ecosystem-sso";
274
+ ```
275
+
276
+ ---
277
+
278
+ ## License
279
+
280
+ Proprietary — © combot.ltd. Internal partner-ecosystem use.