cilantro-react 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 +147 -7
- package/dist/AuthGuard-siMJeYPD.d.mts +42 -0
- package/dist/AuthGuard-siMJeYPD.d.ts +42 -0
- package/dist/index.d.mts +134 -23
- package/dist/index.d.ts +134 -23
- package/dist/index.js +633 -272
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +610 -254
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +19 -0
- package/dist/next.d.ts +19 -0
- package/dist/next.js +494 -0
- package/dist/next.js.map +1 -0
- package/dist/next.mjs +465 -0
- package/dist/next.mjs.map +1 -0
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ React SDK/UI for [Cilantro Smart Wallet](https://www.npmjs.com/package/cilantro-
|
|
|
14
14
|
- [Storage Adapters](#storage-adapters)
|
|
15
15
|
- [Hooks](#hooks)
|
|
16
16
|
- [useAuth](#useauth)
|
|
17
|
+
- [useReturnUrl](#usereturnurl)
|
|
17
18
|
- [useWallet](#usewallet)
|
|
18
19
|
- [useSigners](#usesigners)
|
|
19
20
|
- [usePasskey](#usepasskey)
|
|
@@ -23,8 +24,11 @@ React SDK/UI for [Cilantro Smart Wallet](https://www.npmjs.com/package/cilantro-
|
|
|
23
24
|
- [Components](#components)
|
|
24
25
|
- [Auth Components](#auth-components)
|
|
25
26
|
- [LoginForm](#loginform)
|
|
27
|
+
- [RegisterForm](#registerform)
|
|
26
28
|
- [LogoutButton](#logoutbutton)
|
|
27
29
|
- [AuthGuard](#authguard)
|
|
30
|
+
- [AuthShell](#authshell)
|
|
31
|
+
- [NextAuthGuard (Next.js)](#nextauthguard-nextjs)
|
|
28
32
|
- [Wallet Components](#wallet-components)
|
|
29
33
|
- [WalletSelector](#walletselector)
|
|
30
34
|
- [CreateWalletForm](#createwalletform)
|
|
@@ -144,10 +148,16 @@ const storage = createIndexedDBAdapter();
|
|
|
144
148
|
| `apiKey` | `string` | No* | — | Platform API key for server-side operations |
|
|
145
149
|
| `baseURL` | `string` | No | `https://api.cilantro.gg` | API base URL |
|
|
146
150
|
| `storageAdapter` | `DeviceKeyStorage` | No | IndexedDB | Storage adapter for device keys |
|
|
151
|
+
| `syncJwtToCookie` | `boolean` | No | `false` | When true, sync JWT to a cookie for Next.js/middleware |
|
|
152
|
+
| `jwtCookieName` | `string` | No | `cilantro_jwt` | Cookie name when `syncJwtToCookie` is true |
|
|
147
153
|
| `children` | `ReactNode` | Yes | — | App content |
|
|
148
154
|
|
|
149
155
|
*Either `apiKey` or JWT (obtained via login) is required for authenticated requests.
|
|
150
156
|
|
|
157
|
+
### SDK Auth (automatic)
|
|
158
|
+
|
|
159
|
+
**CilantroProvider configures the underlying cilantro-sdk authentication when the user is logged in.** Once you have a JWT in context (from login or session restore), all cilantro-sdk calls in the same app use that auth automatically. You do **not** need to call `setSdkAuth` or similar before each request; the provider handles it.
|
|
160
|
+
|
|
151
161
|
### Storage Adapters
|
|
152
162
|
|
|
153
163
|
For email and phone signers, device keys must be stored. Choose an adapter:
|
|
@@ -171,6 +181,28 @@ const storage = createLocalStorageAdapter();
|
|
|
171
181
|
const storage = createMemoryAdapter();
|
|
172
182
|
```
|
|
173
183
|
|
|
184
|
+
### Next.js / Middleware
|
|
185
|
+
|
|
186
|
+
For Next.js apps, middleware runs on the server and cannot access `localStorage`. To protect routes or read the JWT in middleware:
|
|
187
|
+
|
|
188
|
+
1. Enable JWT cookie sync: `<CilantroProvider syncJwtToCookie>`
|
|
189
|
+
2. In middleware, read the cookie (default name: `cilantro_jwt`) to check auth.
|
|
190
|
+
3. Optionally redirect unauthenticated users. Example:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
// middleware.ts
|
|
194
|
+
import { NextResponse } from 'next/server';
|
|
195
|
+
import type { NextRequest } from 'next/server';
|
|
196
|
+
|
|
197
|
+
export function middleware(request: NextRequest) {
|
|
198
|
+
const token = request.cookies.get('cilantro_jwt')?.value;
|
|
199
|
+
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
|
|
200
|
+
return NextResponse.redirect(new URL('/login', request.url));
|
|
201
|
+
}
|
|
202
|
+
return NextResponse.next();
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
174
206
|
---
|
|
175
207
|
|
|
176
208
|
## Hooks
|
|
@@ -183,12 +215,16 @@ Authentication state and actions.
|
|
|
183
215
|
import { useAuth } from 'cilantro-react';
|
|
184
216
|
|
|
185
217
|
function MyComponent() {
|
|
186
|
-
const { user, jwt, isLoading, isAuthenticated, login, logout } = useAuth();
|
|
218
|
+
const { user, jwt, isLoading, isAuthenticated, login, register, logout, clearSessionDueToAuthError } = useAuth();
|
|
187
219
|
|
|
188
220
|
const handleLogin = async () => {
|
|
189
221
|
await login({ usernameOrEmail: 'user@example.com', password: 'password123' });
|
|
190
222
|
};
|
|
191
223
|
|
|
224
|
+
const handleRegister = async () => {
|
|
225
|
+
await register('johndoe', 'john@example.com', 'password123');
|
|
226
|
+
};
|
|
227
|
+
|
|
192
228
|
return (
|
|
193
229
|
<div>
|
|
194
230
|
{isLoading && <p>Loading...</p>}
|
|
@@ -210,11 +246,35 @@ function MyComponent() {
|
|
|
210
246
|
| Property | Type | Description |
|
|
211
247
|
|----------|------|-------------|
|
|
212
248
|
| `user` | `User \| null` | Current user object (`{ username?, email?, userType? }`) |
|
|
213
|
-
| `jwt` | `string \| null` | JWT token (null when not authenticated) |
|
|
249
|
+
| `jwt` | `string \| null` | JWT token (null when not authenticated). Prefer this name. |
|
|
250
|
+
| `token` | `string \| null` | Alias for `jwt`. Same value. |
|
|
214
251
|
| `isLoading` | `boolean` | True while restoring session from storage |
|
|
215
252
|
| `isAuthenticated` | `boolean` | True when user has valid JWT |
|
|
216
253
|
| `login` | `(params: { usernameOrEmail: string; password: string }) => Promise<void>` | Log in; throws on error |
|
|
254
|
+
| `register` | `(username: string, email: string, password: string, isActive?: boolean) => Promise<void>` | Register and auto-login |
|
|
217
255
|
| `logout` | `() => void` | Clear session and token |
|
|
256
|
+
| `clearSessionDueToAuthError` | `() => void` | Clear session when API returns 401/403; calls `onSessionExpired` |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### useReturnUrl
|
|
261
|
+
|
|
262
|
+
Read `returnUrl` from URL search params for redirect-after-auth flows.
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
import { useReturnUrl } from 'cilantro-react';
|
|
266
|
+
|
|
267
|
+
function LoginPage() {
|
|
268
|
+
const { returnPath, redirect, rawReturnUrl } = useReturnUrl({ param: 'returnUrl', defaultPath: '/' });
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<LoginForm
|
|
272
|
+
redirectAfterSuccess={returnPath}
|
|
273
|
+
onRedirect={(path) => router.replace(path)}
|
|
274
|
+
/>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
```
|
|
218
278
|
|
|
219
279
|
---
|
|
220
280
|
|
|
@@ -226,7 +286,7 @@ Wallet state and actions.
|
|
|
226
286
|
import { useWallet } from 'cilantro-react';
|
|
227
287
|
|
|
228
288
|
function WalletManager() {
|
|
229
|
-
const { wallet, wallets, createWallet, selectWallet, isLoading } = useWallet();
|
|
289
|
+
const { wallet, wallets, createWallet, selectWallet, refreshWallets, isLoading, error } = useWallet();
|
|
230
290
|
|
|
231
291
|
const handleCreate = async () => {
|
|
232
292
|
const result = await createWallet({ name: 'My New Wallet' });
|
|
@@ -236,6 +296,7 @@ function WalletManager() {
|
|
|
236
296
|
return (
|
|
237
297
|
<div>
|
|
238
298
|
{isLoading && <p>Loading wallets...</p>}
|
|
299
|
+
{error && <p className="text-red-500">{error}</p>}
|
|
239
300
|
<p>Current wallet: {wallet?.walletName ?? 'None selected'}</p>
|
|
240
301
|
<ul>
|
|
241
302
|
{wallets.map((w) => (
|
|
@@ -245,6 +306,7 @@ function WalletManager() {
|
|
|
245
306
|
))}
|
|
246
307
|
</ul>
|
|
247
308
|
<button onClick={handleCreate}>Create Wallet</button>
|
|
309
|
+
<button onClick={refreshWallets}>Refresh</button>
|
|
248
310
|
</div>
|
|
249
311
|
);
|
|
250
312
|
}
|
|
@@ -258,7 +320,9 @@ function WalletManager() {
|
|
|
258
320
|
| `wallets` | `WalletData[]` | All wallets for the authenticated user |
|
|
259
321
|
| `createWallet` | `(params: { name: string; userId?: string }) => Promise<WalletControllerCreateResult>` | Create a new wallet |
|
|
260
322
|
| `selectWallet` | `(walletId: string) => void` | Select a wallet by ID |
|
|
323
|
+
| `refreshWallets` | `() => Promise<void>` | Refresh wallet list from API |
|
|
261
324
|
| `isLoading` | `boolean` | True while loading wallets |
|
|
325
|
+
| `error` | `string \| null` | Error from wallet operations (e.g. fetch failed) |
|
|
262
326
|
|
|
263
327
|
---
|
|
264
328
|
|
|
@@ -524,6 +588,8 @@ import { LoginForm } from 'cilantro-react';
|
|
|
524
588
|
<LoginForm
|
|
525
589
|
onSuccess={() => console.log('Logged in!')}
|
|
526
590
|
onError={(err) => console.error(err.message)}
|
|
591
|
+
redirectAfterSuccess="/dashboard"
|
|
592
|
+
onRedirect={(path) => router.replace(path)}
|
|
527
593
|
title="Welcome back"
|
|
528
594
|
description="Sign in to your account"
|
|
529
595
|
submitLabel="Sign in"
|
|
@@ -538,6 +604,9 @@ import { LoginForm } from 'cilantro-react';
|
|
|
538
604
|
|------|------|---------|-------------|
|
|
539
605
|
| `onSuccess` | `() => void` | — | Called after successful login |
|
|
540
606
|
| `onError` | `(error: Error) => void` | — | Called on login error |
|
|
607
|
+
| `redirectAfterSuccess` | `string` | — | Redirect to this path after login. If unset, reads from URL `?returnUrl=` |
|
|
608
|
+
| `onRedirect` | `(path: string) => void` | — | Custom redirect for SPA routers |
|
|
609
|
+
| `returnUrlParam` | `string` | `"returnUrl"` | Query param to read return URL from |
|
|
541
610
|
| `title` | `string` | `"Sign in"` | Form title |
|
|
542
611
|
| `description` | `string` | — | Form description |
|
|
543
612
|
| `submitLabel` | `string` | `"Sign in"` | Submit button label |
|
|
@@ -557,6 +626,8 @@ import { LogoutButton } from 'cilantro-react';
|
|
|
557
626
|
|
|
558
627
|
<LogoutButton
|
|
559
628
|
onLogout={() => console.log('Logged out')}
|
|
629
|
+
redirectAfterLogout="/login"
|
|
630
|
+
onRedirect={(path) => router.replace(path)}
|
|
560
631
|
confirmBeforeLogout={true}
|
|
561
632
|
>
|
|
562
633
|
Sign out
|
|
@@ -568,6 +639,8 @@ import { LogoutButton } from 'cilantro-react';
|
|
|
568
639
|
| Prop | Type | Default | Description |
|
|
569
640
|
|------|------|---------|-------------|
|
|
570
641
|
| `onLogout` | `() => void` | — | Called after logout |
|
|
642
|
+
| `redirectAfterLogout` | `string` | — | Redirect to this path after logout |
|
|
643
|
+
| `onRedirect` | `(path: string) => void` | — | Custom redirect for SPA routers |
|
|
571
644
|
| `confirmBeforeLogout` | `boolean` | `false` | Show confirmation dialog |
|
|
572
645
|
| `className` | `string` | — | Button class |
|
|
573
646
|
| `children` | `ReactNode` | `"Log out"` | Button content |
|
|
@@ -591,11 +664,23 @@ import { AuthGuard, LoginForm } from 'cilantro-react';
|
|
|
591
664
|
<ProtectedContent />
|
|
592
665
|
</AuthGuard>
|
|
593
666
|
|
|
594
|
-
// Redirect
|
|
667
|
+
// Redirect to login page (appends ?returnUrl=currentPath for redirect-after-login)
|
|
595
668
|
<AuthGuard redirectTo="/login">
|
|
596
669
|
<ProtectedContent />
|
|
597
670
|
</AuthGuard>
|
|
598
671
|
|
|
672
|
+
// Next.js / React Router: use onRedirect for client-side navigation (no full page reload)
|
|
673
|
+
import { useRouter } from 'next/navigation';
|
|
674
|
+
const router = useRouter();
|
|
675
|
+
<AuthGuard redirectTo="/login" onRedirect={(path) => router.replace(path)}>
|
|
676
|
+
<ProtectedContent />
|
|
677
|
+
</AuthGuard>
|
|
678
|
+
|
|
679
|
+
// Polished UX: centered or fullscreen layout for auth fallback
|
|
680
|
+
<AuthGuard layout="centered"> {/* or "fullscreen" */}
|
|
681
|
+
<ProtectedContent />
|
|
682
|
+
</AuthGuard>
|
|
683
|
+
|
|
599
684
|
// Hide content when not authenticated (no fallback)
|
|
600
685
|
<AuthGuard showFallback={false}>
|
|
601
686
|
<ProtectedContent />
|
|
@@ -613,7 +698,10 @@ import { AuthGuard, LoginForm } from 'cilantro-react';
|
|
|
613
698
|
|------|------|---------|-------------|
|
|
614
699
|
| `children` | `ReactNode` | — | Content to show when authenticated |
|
|
615
700
|
| `fallback` | `ReactNode` | `<LoginForm />` | Content when not authenticated |
|
|
616
|
-
| `redirectTo` | `string` | — | Redirect
|
|
701
|
+
| `redirectTo` | `string` | — | Redirect unauthenticated users to this path (appends `?returnUrl=`) |
|
|
702
|
+
| `onRedirect` | `(path: string) => void` | — | Custom redirect for SPA routers (e.g. `router.replace`) |
|
|
703
|
+
| `returnUrlParam` | `string` | `"returnUrl"` | Query param name for return URL |
|
|
704
|
+
| `layout` | `"inline" \| "centered" \| "fullscreen"` | `"inline"` | Layout for fallback content |
|
|
617
705
|
| `showFallback` | `boolean` | `true` | Whether to show fallback or null |
|
|
618
706
|
| `useSkeleton` | `boolean` | `false` | Show skeleton while loading auth state |
|
|
619
707
|
| `className` | `string` | — | Root element class |
|
|
@@ -621,6 +709,52 @@ import { AuthGuard, LoginForm } from 'cilantro-react';
|
|
|
621
709
|
|
|
622
710
|
---
|
|
623
711
|
|
|
712
|
+
#### RegisterForm
|
|
713
|
+
|
|
714
|
+
Registration form with username, email, and password. Auto-login after success.
|
|
715
|
+
|
|
716
|
+
```tsx
|
|
717
|
+
import { RegisterForm } from 'cilantro-react';
|
|
718
|
+
|
|
719
|
+
<RegisterForm
|
|
720
|
+
onSuccess={() => console.log('Registered!')}
|
|
721
|
+
redirectAfterSuccess="/dashboard"
|
|
722
|
+
onRedirect={(path) => router.replace(path)} // For Next.js/React Router
|
|
723
|
+
renderSwitchToLogin={() => <a href="/login">Already have an account? Sign in</a>}
|
|
724
|
+
/>
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
---
|
|
728
|
+
|
|
729
|
+
#### AuthShell
|
|
730
|
+
|
|
731
|
+
Full-page centered layout for auth screens. Use for standalone login/register pages.
|
|
732
|
+
|
|
733
|
+
```tsx
|
|
734
|
+
import { AuthShell, LoginForm } from 'cilantro-react';
|
|
735
|
+
|
|
736
|
+
<AuthShell logo={<img src="/logo.svg" alt="App" />} maxWidth="sm">
|
|
737
|
+
<LoginForm redirectAfterSuccess="/dashboard" />
|
|
738
|
+
</AuthShell>
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
#### NextAuthGuard (Next.js)
|
|
744
|
+
|
|
745
|
+
Drop-in AuthGuard for Next.js App Router. Uses `router.replace()` for client-side redirects.
|
|
746
|
+
Requires `next` to be installed.
|
|
747
|
+
|
|
748
|
+
```tsx
|
|
749
|
+
import { NextAuthGuard } from 'cilantro-react/next';
|
|
750
|
+
|
|
751
|
+
<NextAuthGuard redirectTo="/login" layout="fullscreen">
|
|
752
|
+
<ProtectedContent />
|
|
753
|
+
</NextAuthGuard>
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
624
758
|
### Wallet Components
|
|
625
759
|
|
|
626
760
|
#### WalletSelector
|
|
@@ -1191,11 +1325,17 @@ const adapted = adaptSolanaConnection(connection);
|
|
|
1191
1325
|
|----------|-------------|
|
|
1192
1326
|
| `extractErrorMessage(error)` | Normalize unknown errors to string |
|
|
1193
1327
|
| `extractResponseData(response)` | Unwrap SDK response shapes |
|
|
1194
|
-
| `normalizeWallet(dto)` | Normalize wallet data from SDK |
|
|
1328
|
+
| `normalizeWallet(dto)` | Normalize wallet data from SDK (ensures `id` and `address`) |
|
|
1195
1329
|
| `normalizeSigner(dto)` | Normalize signer data from SDK |
|
|
1196
|
-
| `
|
|
1330
|
+
| `getWalletId(wallet)` | Get wallet ID from wallet-like object (`id ?? walletId`) |
|
|
1331
|
+
| `getWalletAddress(wallet)` | Get wallet address from wallet-like object (`address ?? walletAddress`) |
|
|
1332
|
+
| `isJwtExpired(token, bufferSeconds?)` | Check if JWT is expired. Uses `exp` claim; optional buffer (default 60s) treats tokens near expiry as expired. Exported for apps that sync JWT to cookies or need expiry checks. |
|
|
1197
1333
|
| `isAuthError(error)` | Check if error is an auth error |
|
|
1198
1334
|
|
|
1335
|
+
### Wallet shape
|
|
1336
|
+
|
|
1337
|
+
Wallet data from the SDK may use `walletId`/`walletAddress` or `id`/`address`. The library normalizes at boundaries so **`id`** and **`address`** are preferred. Use `getWalletId(wallet)` and `getWalletAddress(wallet)` when you need to handle both shapes consistently.
|
|
1338
|
+
|
|
1199
1339
|
---
|
|
1200
1340
|
|
|
1201
1341
|
## Types
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface AuthGuardClassNames {
|
|
5
|
+
root?: string;
|
|
6
|
+
fallback?: string;
|
|
7
|
+
skeleton?: string;
|
|
8
|
+
loading?: string;
|
|
9
|
+
/** Centered/fullscreen layout wrapper */
|
|
10
|
+
layout?: string;
|
|
11
|
+
}
|
|
12
|
+
type AuthGuardLayout = "inline" | "centered" | "fullscreen";
|
|
13
|
+
interface AuthGuardProps {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
/** Shown when not authenticated. Default: <LoginForm /> */
|
|
16
|
+
fallback?: ReactNode;
|
|
17
|
+
/** Redirect unauthenticated users to this path (e.g. "/login"). Uses onRedirect if provided, else window.location. */
|
|
18
|
+
redirectTo?: string;
|
|
19
|
+
/** Custom redirect function for SPA routers (Next.js, React Router). e.g. (path) => router.replace(path) */
|
|
20
|
+
onRedirect?: (path: string) => void;
|
|
21
|
+
/** Query param for return URL when redirecting. Default: "returnUrl" */
|
|
22
|
+
returnUrlParam?: string;
|
|
23
|
+
/** Layout for fallback content. "centered" and "fullscreen" give polished auth UX. */
|
|
24
|
+
layout?: AuthGuardLayout;
|
|
25
|
+
/** Root class when showing fallback */
|
|
26
|
+
className?: string;
|
|
27
|
+
classNames?: AuthGuardClassNames;
|
|
28
|
+
/** When true, show fallback (login) instead of redirecting. When false, redirect when redirectTo is set, else render null. */
|
|
29
|
+
showFallback?: boolean;
|
|
30
|
+
/** When true, show skeleton while loading. When false, show "Loading..." text. */
|
|
31
|
+
useSkeleton?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Wraps content and shows fallback (e.g. LoginForm) when the user is not authenticated.
|
|
35
|
+
* Use inside CilantroProvider.
|
|
36
|
+
*
|
|
37
|
+
* For Next.js: pass onRedirect={(path) => router.replace(path)} and redirectTo="/login".
|
|
38
|
+
* For return-after-login flow: set redirectTo="/login"; AuthGuard will redirect with ?returnUrl=currentPath.
|
|
39
|
+
*/
|
|
40
|
+
declare function AuthGuard({ children, fallback, redirectTo, onRedirect, returnUrlParam, layout, className, classNames, showFallback, useSkeleton, }: AuthGuardProps): react_jsx_runtime.JSX.Element | null;
|
|
41
|
+
|
|
42
|
+
export { AuthGuard as A, type AuthGuardClassNames as a, type AuthGuardLayout as b, type AuthGuardProps as c };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface AuthGuardClassNames {
|
|
5
|
+
root?: string;
|
|
6
|
+
fallback?: string;
|
|
7
|
+
skeleton?: string;
|
|
8
|
+
loading?: string;
|
|
9
|
+
/** Centered/fullscreen layout wrapper */
|
|
10
|
+
layout?: string;
|
|
11
|
+
}
|
|
12
|
+
type AuthGuardLayout = "inline" | "centered" | "fullscreen";
|
|
13
|
+
interface AuthGuardProps {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
/** Shown when not authenticated. Default: <LoginForm /> */
|
|
16
|
+
fallback?: ReactNode;
|
|
17
|
+
/** Redirect unauthenticated users to this path (e.g. "/login"). Uses onRedirect if provided, else window.location. */
|
|
18
|
+
redirectTo?: string;
|
|
19
|
+
/** Custom redirect function for SPA routers (Next.js, React Router). e.g. (path) => router.replace(path) */
|
|
20
|
+
onRedirect?: (path: string) => void;
|
|
21
|
+
/** Query param for return URL when redirecting. Default: "returnUrl" */
|
|
22
|
+
returnUrlParam?: string;
|
|
23
|
+
/** Layout for fallback content. "centered" and "fullscreen" give polished auth UX. */
|
|
24
|
+
layout?: AuthGuardLayout;
|
|
25
|
+
/** Root class when showing fallback */
|
|
26
|
+
className?: string;
|
|
27
|
+
classNames?: AuthGuardClassNames;
|
|
28
|
+
/** When true, show fallback (login) instead of redirecting. When false, redirect when redirectTo is set, else render null. */
|
|
29
|
+
showFallback?: boolean;
|
|
30
|
+
/** When true, show skeleton while loading. When false, show "Loading..." text. */
|
|
31
|
+
useSkeleton?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Wraps content and shows fallback (e.g. LoginForm) when the user is not authenticated.
|
|
35
|
+
* Use inside CilantroProvider.
|
|
36
|
+
*
|
|
37
|
+
* For Next.js: pass onRedirect={(path) => router.replace(path)} and redirectTo="/login".
|
|
38
|
+
* For return-after-login flow: set redirectTo="/login"; AuthGuard will redirect with ?returnUrl=currentPath.
|
|
39
|
+
*/
|
|
40
|
+
declare function AuthGuard({ children, fallback, redirectTo, onRedirect, returnUrlParam, layout, className, classNames, showFallback, useSkeleton, }: AuthGuardProps): react_jsx_runtime.JSX.Element | null;
|
|
41
|
+
|
|
42
|
+
export { AuthGuard as A, type AuthGuardClassNames as a, type AuthGuardLayout as b, type AuthGuardProps as c };
|
package/dist/index.d.mts
CHANGED
|
@@ -5,6 +5,7 @@ import { WalletControllerFindAllResult, WalletControllerCreateResult, WalletCont
|
|
|
5
5
|
export { WalletControllerFindAllResult, WalletControllerFindOneResult, WalletControllerListSignersResult, WalletControllerSubmitTransactionResult } from 'cilantro-sdk/wallet';
|
|
6
6
|
import { createIndexedDBAdapter, SignerInfo } from 'cilantro-sdk/helpers';
|
|
7
7
|
export { createIndexedDBAdapter, createLocalStorageAdapter, createMemoryAdapter } from 'cilantro-sdk/helpers';
|
|
8
|
+
export { A as AuthGuard, a as AuthGuardClassNames, b as AuthGuardLayout, c as AuthGuardProps } from './AuthGuard-siMJeYPD.mjs';
|
|
8
9
|
import { PublicKey, Transaction, Connection } from '@solana/web3.js';
|
|
9
10
|
export { AuthControllerLogin200Data } from 'cilantro-sdk/auth';
|
|
10
11
|
export { TransactionControllerSendRawPasskeyTransactionResult } from 'cilantro-sdk/transactions';
|
|
@@ -62,12 +63,16 @@ interface CilantroContextProviderProps {
|
|
|
62
63
|
storageAdapter?: DeviceKeyStorage | null;
|
|
63
64
|
jwtStorageKey?: string;
|
|
64
65
|
walletStorageKey?: string;
|
|
66
|
+
/** When true, sync JWT to a cookie (same name as jwtStorageKey) for Next.js/middleware. Default: false. */
|
|
67
|
+
syncJwtToCookie?: boolean;
|
|
68
|
+
/** Cookie name for JWT when syncJwtToCookie is true. Default: cilantro_jwt. */
|
|
69
|
+
jwtCookieName?: string;
|
|
65
70
|
onLoginSuccess?: () => void;
|
|
66
71
|
onLogout?: () => void;
|
|
67
72
|
onRegisterSuccess?: () => void;
|
|
68
73
|
onSessionExpired?: () => void;
|
|
69
74
|
}
|
|
70
|
-
declare function CilantroContextProvider({ children, apiKey, baseURL, storageAdapter, jwtStorageKey, walletStorageKey, onLoginSuccess, onLogout, onRegisterSuccess, onSessionExpired, }: CilantroContextProviderProps): react_jsx_runtime.JSX.Element;
|
|
75
|
+
declare function CilantroContextProvider({ children, apiKey, baseURL, storageAdapter, jwtStorageKey, walletStorageKey, syncJwtToCookie, jwtCookieName, onLoginSuccess, onLogout, onRegisterSuccess, onSessionExpired, }: CilantroContextProviderProps): react_jsx_runtime.JSX.Element;
|
|
71
76
|
declare function useCilantroContext(): CilantroContextValue;
|
|
72
77
|
|
|
73
78
|
interface CilantroProviderProps {
|
|
@@ -86,15 +91,21 @@ interface CilantroProviderProps {
|
|
|
86
91
|
jwtStorageKey?: string;
|
|
87
92
|
/** localStorage key for selected wallet id (default: cilantro_selected_wallet_id) */
|
|
88
93
|
walletStorageKey?: string;
|
|
94
|
+
/** When true, sync JWT to a cookie for Next.js/middleware. Default: false. */
|
|
95
|
+
syncJwtToCookie?: boolean;
|
|
96
|
+
/** Cookie name for JWT when syncJwtToCookie is true. Default: cilantro_jwt. */
|
|
97
|
+
jwtCookieName?: string;
|
|
89
98
|
onLoginSuccess?: () => void;
|
|
90
99
|
onLogout?: () => void;
|
|
91
100
|
onRegisterSuccess?: () => void;
|
|
92
101
|
onSessionExpired?: () => void;
|
|
93
102
|
}
|
|
94
|
-
declare function CilantroProvider({ children, apiKey: apiKeyProp, baseURL, storageAdapter, platformApiKey, apiUrl, jwtStorageKey, walletStorageKey, onLoginSuccess, onLogout, onRegisterSuccess, onSessionExpired, }: CilantroProviderProps): react_jsx_runtime.JSX.Element;
|
|
103
|
+
declare function CilantroProvider({ children, apiKey: apiKeyProp, baseURL, storageAdapter, platformApiKey, apiUrl, jwtStorageKey, walletStorageKey, syncJwtToCookie, jwtCookieName, onLoginSuccess, onLogout, onRegisterSuccess, onSessionExpired, }: CilantroProviderProps): react_jsx_runtime.JSX.Element;
|
|
95
104
|
|
|
96
105
|
interface CilantroAuthContextType {
|
|
97
106
|
user: User | null;
|
|
107
|
+
/** JWT token. Alias for token. */
|
|
108
|
+
jwt: string | null;
|
|
98
109
|
token: string | null;
|
|
99
110
|
isAuthenticated: boolean;
|
|
100
111
|
login: (usernameOrEmail: string, password: string) => Promise<void>;
|
|
@@ -106,6 +117,9 @@ interface CilantroAuthContextType {
|
|
|
106
117
|
declare function useCilantroAuth(): CilantroAuthContextType;
|
|
107
118
|
|
|
108
119
|
interface WalletContextType {
|
|
120
|
+
/** Selected wallet. Primary name. */
|
|
121
|
+
wallet: WalletData | null;
|
|
122
|
+
/** @deprecated Use wallet instead. Alias for backward compat. */
|
|
109
123
|
selectedWallet: WalletData | null;
|
|
110
124
|
wallets: WalletData[];
|
|
111
125
|
selectWallet: (walletId: string) => void;
|
|
@@ -124,19 +138,54 @@ interface UseCilantroConfigResult {
|
|
|
124
138
|
declare function useCilantroConfig(): UseCilantroConfigResult;
|
|
125
139
|
|
|
126
140
|
interface UseAuthResult {
|
|
141
|
+
/** Current user (from JWT payload or login response). */
|
|
127
142
|
user: User | null;
|
|
143
|
+
/** JWT token. Prefer this name. */
|
|
128
144
|
jwt: string | null;
|
|
145
|
+
/** Alias for jwt. Same value. */
|
|
146
|
+
token: string | null;
|
|
129
147
|
isLoading: boolean;
|
|
130
148
|
isAuthenticated: boolean;
|
|
131
149
|
login: (params: {
|
|
132
150
|
usernameOrEmail: string;
|
|
133
151
|
password: string;
|
|
134
152
|
}) => Promise<void>;
|
|
153
|
+
/** Register a new user and auto-login. */
|
|
154
|
+
register: (username: string, email: string, password: string, isActive?: boolean) => Promise<void>;
|
|
135
155
|
logout: () => void;
|
|
156
|
+
/** Clear session when API returns 401/403. Call onSessionExpired. */
|
|
157
|
+
clearSessionDueToAuthError: () => void;
|
|
136
158
|
}
|
|
137
159
|
declare function useAuth(): UseAuthResult;
|
|
138
160
|
|
|
161
|
+
interface UseReturnUrlOptions {
|
|
162
|
+
/** Query param name for return URL. Default: "returnUrl" */
|
|
163
|
+
param?: string;
|
|
164
|
+
/** Default path when no returnUrl in URL. Default: "/" */
|
|
165
|
+
defaultPath?: string;
|
|
166
|
+
/** Only allow relative paths (no protocol). Default: true */
|
|
167
|
+
allowRelativeOnly?: boolean;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Read returnUrl from URL search params and provide a safe redirect path.
|
|
171
|
+
* Use with LoginForm/RegisterForm to redirect users back after auth.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* // In LoginForm wrapper - redirect to returnUrl after login
|
|
175
|
+
* const { returnPath, redirect } = useReturnUrl();
|
|
176
|
+
* <LoginForm onSuccess={() => redirect()} redirectAfterSuccess={returnPath} onRedirect={router.replace} />
|
|
177
|
+
*/
|
|
178
|
+
declare function useReturnUrl(options?: UseReturnUrlOptions): {
|
|
179
|
+
/** Safe path to redirect to (from URL or defaultPath) */
|
|
180
|
+
returnPath: string;
|
|
181
|
+
/** Redirect to returnPath using window.location (or pass custom fn) */
|
|
182
|
+
redirect: (customRedirect?: (path: string) => void) => void;
|
|
183
|
+
/** Raw value from URL (may be empty) */
|
|
184
|
+
rawReturnUrl: string | null;
|
|
185
|
+
};
|
|
186
|
+
|
|
139
187
|
interface UseWalletResult {
|
|
188
|
+
/** Selected wallet. Use this as primary. */
|
|
140
189
|
wallet: WalletData | null;
|
|
141
190
|
wallets: WalletData[];
|
|
142
191
|
createWallet: (params: {
|
|
@@ -144,7 +193,11 @@ interface UseWalletResult {
|
|
|
144
193
|
userId?: string;
|
|
145
194
|
}) => Promise<WalletControllerCreateResult>;
|
|
146
195
|
selectWallet: (walletId: string) => void;
|
|
196
|
+
/** Refresh wallet list from API. */
|
|
197
|
+
refreshWallets: () => Promise<void>;
|
|
147
198
|
isLoading: boolean;
|
|
199
|
+
/** Error from wallet operations (e.g. fetch failed). */
|
|
200
|
+
error: string | null;
|
|
148
201
|
}
|
|
149
202
|
declare function useWallet(_walletId?: string): UseWalletResult;
|
|
150
203
|
|
|
@@ -277,6 +330,12 @@ interface LoginFormProps {
|
|
|
277
330
|
style?: React.CSSProperties;
|
|
278
331
|
onSuccess?: () => void;
|
|
279
332
|
onError?: (error: Error) => void;
|
|
333
|
+
/** Redirect to this path after successful login. If not set, reads from URL ?returnUrl= (when returnUrlParam provided). */
|
|
334
|
+
redirectAfterSuccess?: string;
|
|
335
|
+
/** Custom redirect function for SPA routers. e.g. (path) => router.replace(path) */
|
|
336
|
+
onRedirect?: (path: string) => void;
|
|
337
|
+
/** Query param to read returnUrl from URL. Default: "returnUrl". Used when redirectAfterSuccess not set. */
|
|
338
|
+
returnUrlParam?: string;
|
|
280
339
|
rememberMe?: boolean;
|
|
281
340
|
/** Override submit button label */
|
|
282
341
|
submitLabel?: string;
|
|
@@ -287,41 +346,78 @@ interface LoginFormProps {
|
|
|
287
346
|
/** Render "Create account" link (e.g. to switch to register). Shown below submit. */
|
|
288
347
|
renderSwitchToRegister?: () => React.ReactNode;
|
|
289
348
|
}
|
|
290
|
-
declare function LoginForm({ className, classNames, style, onSuccess, onError, submitLabel, title, description, renderSwitchToRegister, }: LoginFormProps): react_jsx_runtime.JSX.Element;
|
|
349
|
+
declare function LoginForm({ className, classNames, style, onSuccess, onError, redirectAfterSuccess, onRedirect, returnUrlParam, submitLabel, title, description, renderSwitchToRegister, }: LoginFormProps): react_jsx_runtime.JSX.Element;
|
|
350
|
+
|
|
351
|
+
interface RegisterFormClassNames {
|
|
352
|
+
root?: string;
|
|
353
|
+
header?: string;
|
|
354
|
+
title?: string;
|
|
355
|
+
description?: string;
|
|
356
|
+
form?: string;
|
|
357
|
+
label?: string;
|
|
358
|
+
input?: string;
|
|
359
|
+
submitButton?: string;
|
|
360
|
+
error?: string;
|
|
361
|
+
}
|
|
362
|
+
interface RegisterFormProps {
|
|
363
|
+
className?: string;
|
|
364
|
+
classNames?: RegisterFormClassNames;
|
|
365
|
+
style?: React.CSSProperties;
|
|
366
|
+
onSuccess?: () => void;
|
|
367
|
+
onError?: (error: Error) => void;
|
|
368
|
+
/** Redirect to this path after successful registration. If not set, reads from URL ?returnUrl= */
|
|
369
|
+
redirectAfterSuccess?: string;
|
|
370
|
+
/** Custom redirect function for SPA routers */
|
|
371
|
+
onRedirect?: (path: string) => void;
|
|
372
|
+
/** Query param to read returnUrl from URL. Default: "returnUrl" */
|
|
373
|
+
returnUrlParam?: string;
|
|
374
|
+
/** Override submit button label */
|
|
375
|
+
submitLabel?: string;
|
|
376
|
+
/** Override title */
|
|
377
|
+
title?: string;
|
|
378
|
+
/** Override description */
|
|
379
|
+
description?: string;
|
|
380
|
+
/** Render "Already have an account?" link to switch to login */
|
|
381
|
+
renderSwitchToLogin?: () => React.ReactNode;
|
|
382
|
+
}
|
|
383
|
+
declare function RegisterForm({ className, classNames, style, onSuccess, onError, redirectAfterSuccess, onRedirect, returnUrlParam, submitLabel, title, description, renderSwitchToLogin, }: RegisterFormProps): react_jsx_runtime.JSX.Element;
|
|
291
384
|
|
|
292
385
|
interface LogoutButtonProps {
|
|
293
386
|
onLogout?: () => void;
|
|
387
|
+
/** Redirect to this path after logout (e.g. "/login") */
|
|
388
|
+
redirectAfterLogout?: string;
|
|
389
|
+
/** Custom redirect for SPA routers. e.g. (path) => router.replace(path) */
|
|
390
|
+
onRedirect?: (path: string) => void;
|
|
294
391
|
confirmBeforeLogout?: boolean;
|
|
295
392
|
className?: string;
|
|
296
393
|
children?: ReactNode;
|
|
297
394
|
}
|
|
298
|
-
declare function LogoutButton({ onLogout, confirmBeforeLogout, className, children, }: LogoutButtonProps): react_jsx_runtime.JSX.Element;
|
|
395
|
+
declare function LogoutButton({ onLogout, redirectAfterLogout, onRedirect, confirmBeforeLogout, className, children, }: LogoutButtonProps): react_jsx_runtime.JSX.Element;
|
|
299
396
|
|
|
300
|
-
interface
|
|
397
|
+
interface AuthShellClassNames {
|
|
301
398
|
root?: string;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
loading?: string;
|
|
399
|
+
inner?: string;
|
|
400
|
+
logo?: string;
|
|
305
401
|
}
|
|
306
|
-
interface
|
|
402
|
+
interface AuthShellProps {
|
|
307
403
|
children: ReactNode;
|
|
308
|
-
/**
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
|
|
312
|
-
/** Root class when showing fallback */
|
|
404
|
+
/** Optional logo/brand (e.g. <img> or <Logo />) */
|
|
405
|
+
logo?: ReactNode;
|
|
406
|
+
/** Max width of the auth card area. Default: "sm" (24rem) */
|
|
407
|
+
maxWidth?: "sm" | "md" | "lg";
|
|
313
408
|
className?: string;
|
|
314
|
-
classNames?:
|
|
315
|
-
/** When true, show fallback (login) instead of children when unauthenticated. When false, render null when unauthenticated. */
|
|
316
|
-
showFallback?: boolean;
|
|
317
|
-
/** When true, show a small skeleton card while loading; when false (default), show "Loading..." text. */
|
|
318
|
-
useSkeleton?: boolean;
|
|
409
|
+
classNames?: AuthShellClassNames;
|
|
319
410
|
}
|
|
320
411
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
412
|
+
* Full-page centered layout for auth screens (login, register).
|
|
413
|
+
* Provides a polished, accessible UX with consistent spacing and optional logo.
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* <AuthShell logo={<img src="/logo.svg" alt="App" />}>
|
|
417
|
+
* <LoginForm />
|
|
418
|
+
* </AuthShell>
|
|
323
419
|
*/
|
|
324
|
-
declare function
|
|
420
|
+
declare function AuthShell({ children, logo, maxWidth, className, classNames, }: AuthShellProps): react_jsx_runtime.JSX.Element;
|
|
325
421
|
|
|
326
422
|
interface CreateEmailSignerFormProps {
|
|
327
423
|
walletId: string;
|
|
@@ -673,6 +769,21 @@ interface NormalizedWallet {
|
|
|
673
769
|
* Accepts any object with optional walletId/id, walletAddress/address, isActive.
|
|
674
770
|
*/
|
|
675
771
|
declare function normalizeWallet(dto: Record<string, unknown>): NormalizedWallet;
|
|
772
|
+
/** Wallet-like object with optional id/walletId and address/walletAddress. */
|
|
773
|
+
type WalletLike = {
|
|
774
|
+
id?: string;
|
|
775
|
+
walletId?: string;
|
|
776
|
+
address?: string;
|
|
777
|
+
walletAddress?: string;
|
|
778
|
+
} & Record<string, unknown>;
|
|
779
|
+
/**
|
|
780
|
+
* Get wallet ID from a wallet-like object. Prefer id; fallback to walletId.
|
|
781
|
+
*/
|
|
782
|
+
declare function getWalletId(wallet: WalletLike | null | undefined): string;
|
|
783
|
+
/**
|
|
784
|
+
* Get wallet address from a wallet-like object. Prefer address; fallback to walletAddress.
|
|
785
|
+
*/
|
|
786
|
+
declare function getWalletAddress(wallet: WalletLike | null | undefined): string;
|
|
676
787
|
|
|
677
788
|
declare function extractErrorMessage(error: unknown): string;
|
|
678
789
|
declare function isAuthError(error: unknown): boolean;
|
|
@@ -716,4 +827,4 @@ interface SignAndSendConnectionAdapter {
|
|
|
716
827
|
*/
|
|
717
828
|
declare function adaptSolanaConnection(connection: Connection): SignAndSendConnectionAdapter;
|
|
718
829
|
|
|
719
|
-
export { type ActionState, AddPasskeyButton, type AddPasskeyButtonProps, type ApiResponse,
|
|
830
|
+
export { type ActionState, AddPasskeyButton, type AddPasskeyButtonProps, type ApiResponse, AuthShell, type AuthShellClassNames, type AuthShellProps, type CilantroAuthContextType, type CilantroConfig, CilantroConnect, type CilantroConnectProps, CilantroContextProvider, type CilantroContextValue, CilantroProvider, type CilantroProviderProps, ConnectWalletButton, type ConnectWalletButtonProps, CreateEmailSignerForm, type CreateEmailSignerFormProps, CreatePhoneSignerForm, type CreatePhoneSignerFormProps, CreateWalletForm, type CreateWalletFormProps, type DeviceKeyStorage, ErrorBoundary, type ErrorBoundaryProps, type ErrorResponse, LoadingOverlay, type LoadingOverlayProps, LoginForm, type LoginFormClassNames, type LoginFormProps, LogoutButton, type LogoutButtonProps, type NormalizedWallet, RegisterForm, type RegisterFormClassNames, type RegisterFormProps, type ResolvedTheme, SIGNER_TYPES, SendSOLForm, type SendSOLFormProps, type SignerType as SendSOLSignerType, SendSPLForm, type SendSPLFormProps, type SignerType$2 as SendTransactionSignerType, type SignAndSendConnection, type SignAndSendConnectionAdapter, type SignAndSendResult, type SignMessageResult, type SignerData, SignerList, type SignerListClassNames, type SignerListProps, SignerSelector, type SignerSelectorClassNames, type SignerSelectorProps, type SignerType$1 as SignerType, Skeleton, type SolanaWallet, type SubmitTransactionDataDto, type SubmitTransactionResult, type Theme, ThemeProvider, type ThemeProviderProps, TransactionHistory, type TransactionHistoryProps, TransactionStatus, type TransactionStatusProps, type UseAuthResult, type UseCilantroConfigResult, type UseExternalWalletResult, type UsePasskeyResult, type UseReturnUrlOptions, type UseSendTransactionResult, type UseSignersOptions, type UseSignersResult, type UseWalletResult, type User, WalletAddress, type WalletAddressProps, WalletBalance, type WalletBalanceProps, type WalletContextType, type WalletData, type WalletDataDto$1 as WalletDataDto, type WalletDataDto as WalletDataDtoFromHook, type WalletData as WalletDataFromHook, type WalletInfo, type WalletLike, WalletSelector, type WalletSelectorClassNames, type WalletSelectorProps, adaptSolanaConnection, extractErrorMessage, extractResponseData, getSignerPublicKey, getWalletAddress, getWalletData, getWalletId, isAuthError, isJwtExpired, normalizeSigner, normalizeWallet, signAndSendTransactionWithSigner, signMessageWithSigner, signTransactionWithSigner, useAuth, useCilantroAuth, useCilantroConfig, useCilantroContext, useExternalWallet, usePasskey, useReturnUrl, useSendTransaction, useSigners, useWallet, useWallets };
|