ab-ecosystem-sso 0.1.6 → 0.1.8
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 +280 -0
- package/dist/ab-ecosystem-sso.cjs +27 -23
- package/dist/ab-ecosystem-sso.js +5671 -3775
- package/dist/index.d.ts +212 -7
- package/dist/style.css +1 -1
- package/package.json +1 -1
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.
|