@cfast/auth 0.0.1
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/LICENSE +21 -0
- package/README.md +394 -0
- package/dist/client.d.ts +123 -0
- package/dist/client.js +226 -0
- package/dist/index.d.ts +167 -0
- package/dist/index.js +260 -0
- package/dist/plugin.d.ts +41 -0
- package/dist/plugin.js +14 -0
- package/dist/schema.d.ts +1052 -0
- package/dist/schema.js +85 -0
- package/dist/types-19GeiMs4.d.ts +64 -0
- package/dist/types-8eZilolN.d.ts +63 -0
- package/dist/types-DZ7AeznW.d.ts +74 -0
- package/dist/types-DdbPIOVK.d.ts +85 -0
- package/dist/types-DrnTPiku.d.ts +62 -0
- package/dist/types-ghXti5CW.d.ts +191 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Schmidt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# @cfast/auth
|
|
2
|
+
|
|
3
|
+
**Authentication for Cloudflare Workers. Magic email, passkeys, roles, impersonation. Built on Better Auth.**
|
|
4
|
+
|
|
5
|
+
`@cfast/auth` is a pre-configured [Better Auth](https://better-auth.com) setup purpose-built for Cloudflare Workers with D1. It takes the decisions out of authentication: magic email links and passkeys for login, Mailgun for delivery, D1 for storage, and a complete role management system that plugs directly into `@cfast/permissions`.
|
|
6
|
+
|
|
7
|
+
You don't configure an auth library. You tell cfast what roles your app has, and auth just works.
|
|
8
|
+
|
|
9
|
+
## Design Goals
|
|
10
|
+
|
|
11
|
+
- **Zero-config for the common case.** Magic email + passkeys out of the box. No OAuth provider configuration unless you want it.
|
|
12
|
+
- **Email-first login.** The user enters their email, then chooses between passkey or magic link. Both methods are passwordless.
|
|
13
|
+
- **Overridable UI.** Default components use MUI Joy UI. Override individual component slots to customize the login experience without rebuilding from scratch.
|
|
14
|
+
- **Cookie-based redirect-back.** When an unauthenticated user hits a protected route, the intended path is stored in a cookie and restored after login.
|
|
15
|
+
- **Roles are the bridge.** `@cfast/auth` assigns roles to users. `@cfast/permissions` defines what those roles can do. The two packages share the same role type definitions.
|
|
16
|
+
- **Workers-native.** Session storage on D1, email via Mailgun (Worker-friendly HTTP API), passkeys via WebAuthn. No Node.js dependencies.
|
|
17
|
+
- **Admin-ready.** Role management and user impersonation built in, not bolted on.
|
|
18
|
+
|
|
19
|
+
## API
|
|
20
|
+
|
|
21
|
+
### Server Setup
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createAuth } from "@cfast/auth";
|
|
25
|
+
import { permissions } from "./permissions"; // from @cfast/permissions
|
|
26
|
+
|
|
27
|
+
export const initAuth = createAuth({
|
|
28
|
+
permissions, // Roles are inferred from your permission definitions
|
|
29
|
+
magicLink: {
|
|
30
|
+
sendMagicLink: async ({ email, url }) => {
|
|
31
|
+
// Send email with your provider (Mailgun, Resend, etc.)
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
passkeys: {
|
|
35
|
+
rpName: "MyApp",
|
|
36
|
+
rpId: "myapp.com",
|
|
37
|
+
},
|
|
38
|
+
session: {
|
|
39
|
+
expiresIn: "30d",
|
|
40
|
+
},
|
|
41
|
+
redirects: {
|
|
42
|
+
afterLogin: "/", // default redirect after successful login
|
|
43
|
+
loginPath: "/login", // where to send unauthenticated users
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// In your request handler, initialize with D1:
|
|
48
|
+
const auth = initAuth({ d1: env.DB, appUrl: "https://myapp.com" });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Route Integration (routes.ts Helper)
|
|
52
|
+
|
|
53
|
+
Auth routes (magic link callback, passkey endpoints) are added via a helper in your `routes.ts`. You create a handler file that forwards requests to Better Auth.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// app/routes.ts
|
|
57
|
+
import type { RouteConfig } from "@react-router/dev/routes";
|
|
58
|
+
import { authRoutes } from "@cfast/auth/plugin";
|
|
59
|
+
|
|
60
|
+
export default [
|
|
61
|
+
...authRoutes({ handlerFile: "routes/auth.$.tsx" }),
|
|
62
|
+
// ... other routes
|
|
63
|
+
] satisfies RouteConfig;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The handler file (`routes/auth.$.tsx`) uses `createAuthRouteHandlers`:
|
|
67
|
+
```typescript
|
|
68
|
+
import { createAuthRouteHandlers } from "@cfast/auth";
|
|
69
|
+
const { loader, action } = createAuthRouteHandlers(() => getAuth());
|
|
70
|
+
export { loader, action };
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Protecting Routes with AuthGuard
|
|
74
|
+
|
|
75
|
+
`AuthGuard` is a layout-level component. It takes a `user` prop from the loader and provides it to all child routes via context.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// routes/_protected.tsx
|
|
79
|
+
import { AuthGuard } from "@cfast/auth/client";
|
|
80
|
+
import { requireAuthContext } from "~/auth.helpers.server";
|
|
81
|
+
import { Outlet, useLoaderData } from "react-router";
|
|
82
|
+
|
|
83
|
+
export async function loader({ request }) {
|
|
84
|
+
const ctx = await requireAuthContext(request);
|
|
85
|
+
// Sets a cfast_redirect_to cookie with the current path
|
|
86
|
+
// Throws a redirect to /login if not authenticated
|
|
87
|
+
return { user: ctx.user };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default function ProtectedLayout() {
|
|
91
|
+
const { user } = useLoaderData<typeof loader>();
|
|
92
|
+
return (
|
|
93
|
+
<AuthGuard user={user}>
|
|
94
|
+
<Outlet />
|
|
95
|
+
</AuthGuard>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Any route nested under `_protected` is automatically guarded. The login page lives outside this layout as a normal route file.
|
|
101
|
+
|
|
102
|
+
### Client-Side Providers
|
|
103
|
+
|
|
104
|
+
Two providers wrap the app root:
|
|
105
|
+
|
|
106
|
+
- **`AuthClientProvider`** — holds the Better Auth client instance. Required for `useAuth()`.
|
|
107
|
+
- **`AuthProvider`** — holds the current user from loader data. Required for `useCurrentUser()`.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// root.tsx
|
|
111
|
+
import { AuthClientProvider } from "@cfast/auth/client";
|
|
112
|
+
import { authClient } from "~/auth.client";
|
|
113
|
+
import { Outlet } from "react-router";
|
|
114
|
+
|
|
115
|
+
export default function App() {
|
|
116
|
+
return (
|
|
117
|
+
<AuthClientProvider authClient={authClient}>
|
|
118
|
+
<Outlet />
|
|
119
|
+
</AuthClientProvider>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`AuthProvider` is typically used inside layout routes (via `AuthGuard`) rather than at the root, since user data comes from loaders.
|
|
125
|
+
|
|
126
|
+
### useCurrentUser Hook
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { useCurrentUser } from "@cfast/auth/client";
|
|
130
|
+
|
|
131
|
+
function Header() {
|
|
132
|
+
const user = useCurrentUser();
|
|
133
|
+
// Inside AuthGuard: returns User (non-null, type-enforced)
|
|
134
|
+
// Outside AuthGuard: returns User | null
|
|
135
|
+
return <span>{user?.email}</span>;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Login Page
|
|
140
|
+
|
|
141
|
+
The consumer creates their own login route and renders `<LoginPage>`. The component accepts an `authClient` prop and a `components` prop for UI slot overrides. Default slots render plain HTML — use `@cfast/ui/joy` for Joy UI styling.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// routes/login.tsx
|
|
145
|
+
import { LoginPage } from "@cfast/auth/client";
|
|
146
|
+
import { joyLoginComponents } from "@cfast/ui/joy";
|
|
147
|
+
import { authClient } from "~/auth.client";
|
|
148
|
+
|
|
149
|
+
export default function Login() {
|
|
150
|
+
return (
|
|
151
|
+
<LoginPage
|
|
152
|
+
authClient={authClient}
|
|
153
|
+
components={joyLoginComponents}
|
|
154
|
+
title="Sign In"
|
|
155
|
+
subtitle="Sign in to My App"
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The login page shows:
|
|
162
|
+
1. An email input
|
|
163
|
+
2. A "Send Magic Link" button
|
|
164
|
+
3. A "Sign in with Passkey" button
|
|
165
|
+
4. Success/error feedback messages
|
|
166
|
+
|
|
167
|
+
### Component Slot Overrides
|
|
168
|
+
|
|
169
|
+
Override individual pieces of the login UI. Unspecified slots use the plain HTML defaults.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { LoginPage } from "@cfast/auth/client";
|
|
173
|
+
import type { LoginComponents } from "@cfast/auth/client";
|
|
174
|
+
|
|
175
|
+
const components: LoginComponents = {
|
|
176
|
+
Layout: ({ children }) => <MyCustomCard>{children}</MyCustomCard>,
|
|
177
|
+
EmailInput: ({ value, onChange, error }) => (
|
|
178
|
+
<MyInput value={value} onChange={onChange} error={error} />
|
|
179
|
+
),
|
|
180
|
+
PasskeyButton: ({ onClick, loading }) => (
|
|
181
|
+
<MyButton onClick={onClick} loading={loading}>Use Passkey</MyButton>
|
|
182
|
+
),
|
|
183
|
+
MagicLinkButton: ({ onClick, loading }) => (
|
|
184
|
+
<MyButton onClick={onClick} loading={loading}>Email Me a Link</MyButton>
|
|
185
|
+
),
|
|
186
|
+
SuccessMessage: ({ email }) => (
|
|
187
|
+
<MyAlert>Check {email} for your login link</MyAlert>
|
|
188
|
+
),
|
|
189
|
+
ErrorMessage: ({ error }) => (
|
|
190
|
+
<MyAlert color="danger">{error}</MyAlert>
|
|
191
|
+
),
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export default function Login() {
|
|
195
|
+
return <LoginPage authClient={authClient} components={components} />;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
For Joy UI, use the pre-built `joyLoginComponents` from `@cfast/ui/joy` instead of writing custom slots.
|
|
200
|
+
|
|
201
|
+
### Redirect Flow
|
|
202
|
+
|
|
203
|
+
The full redirect cycle:
|
|
204
|
+
|
|
205
|
+
1. **User visits `/dashboard/settings` unauthenticated** — the `_protected` layout loader calls `auth.requireUser(request)` — sets a `cfast_redirect_to=/dashboard/settings` cookie — throws a redirect to `/login`.
|
|
206
|
+
|
|
207
|
+
2. **User is on `/login`** — enters email — clicks "Send Magic Link" or "Sign in with Passkey".
|
|
208
|
+
|
|
209
|
+
3. **Magic Link path:** user clicks link in email — hits `/auth/callback` (injected by plugin) — server verifies token, creates session, reads `cfast_redirect_to` cookie, clears it, redirects to `/dashboard/settings`.
|
|
210
|
+
|
|
211
|
+
4. **Passkey path:** WebAuthn ceremony completes on client — server verifies, creates session — client-side redirect reads cookie and navigates to `/dashboard/settings`.
|
|
212
|
+
|
|
213
|
+
5. **Direct visit to `/login`** (no prior redirect) — no cookie set — after login, redirects to the `afterLogin` default from config (defaults to `/`).
|
|
214
|
+
|
|
215
|
+
The `cfast_redirect_to` cookie is `HttpOnly`, `Secure`, `SameSite=Lax`, with a 10-minute TTL.
|
|
216
|
+
|
|
217
|
+
### useAuth Hook
|
|
218
|
+
|
|
219
|
+
`useAuth()` provides auth actions from the `AuthClientProvider` context. Takes no arguments.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { useAuth } from "@cfast/auth/client";
|
|
223
|
+
|
|
224
|
+
const {
|
|
225
|
+
signOut, // Sign out the current user
|
|
226
|
+
registerPasskey, // Register a new passkey (WebAuthn)
|
|
227
|
+
deletePasskey, // Delete a passkey by ID
|
|
228
|
+
stopImpersonating, // Stop impersonating (admin only)
|
|
229
|
+
authClient, // Raw Better Auth client for escape-hatch usage
|
|
230
|
+
} = useAuth();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Authentication Methods
|
|
234
|
+
|
|
235
|
+
#### Magic Email Link
|
|
236
|
+
```typescript
|
|
237
|
+
// Server: send magic link
|
|
238
|
+
await auth.sendMagicLink({ email: "user@example.com" });
|
|
239
|
+
|
|
240
|
+
// With custom callback URL:
|
|
241
|
+
await auth.sendMagicLink({ email: "user@example.com", callbackURL: "/welcome" });
|
|
242
|
+
|
|
243
|
+
// The link hits /auth/callback (injected by plugin)
|
|
244
|
+
// Auth handles verification and creates/updates the user + session automatically
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### Passkeys (WebAuthn)
|
|
248
|
+
```typescript
|
|
249
|
+
// Client: register a passkey (from a settings page, after login)
|
|
250
|
+
import { useAuth } from "@cfast/auth/client";
|
|
251
|
+
|
|
252
|
+
function SecuritySettings({ passkeys }) {
|
|
253
|
+
// passkeys come from loader data (server query), not from the hook
|
|
254
|
+
const { registerPasskey, deletePasskey } = useAuth();
|
|
255
|
+
|
|
256
|
+
return (
|
|
257
|
+
<div>
|
|
258
|
+
<button onClick={() => registerPasskey()}>Add Passkey</button>
|
|
259
|
+
{passkeys.map((pk) => (
|
|
260
|
+
<div key={pk.id}>
|
|
261
|
+
{pk.name} - {pk.createdAt}
|
|
262
|
+
<button onClick={() => deletePasskey(pk.id)}>Remove</button>
|
|
263
|
+
</div>
|
|
264
|
+
))}
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Client: sign in with passkey (from the login page, handled by LoginPage component)
|
|
270
|
+
// The LoginPage component manages the WebAuthn ceremony internally
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Role Management
|
|
274
|
+
|
|
275
|
+
Roles are shared with `@cfast/permissions`. Assigning a role to a user immediately changes what they can do across the entire app:
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Promote a user to editor
|
|
279
|
+
await auth.setRole(userId, "editor");
|
|
280
|
+
|
|
281
|
+
// Assign multiple roles
|
|
282
|
+
await auth.setRoles(userId, ["editor", "moderator"]);
|
|
283
|
+
|
|
284
|
+
// In React Router loaders, the user's roles are always available:
|
|
285
|
+
export async function loader({ request }) {
|
|
286
|
+
const user = await auth.requireUser(request);
|
|
287
|
+
// user.roles -> ["editor"]
|
|
288
|
+
// This user object feeds into createDb({ user }) — it determines
|
|
289
|
+
// which permission grants apply to every Operation
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Role Grant Rules
|
|
294
|
+
|
|
295
|
+
Control who can assign which roles. An editor shouldn't be able to promote someone to admin:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
export const auth = createAuth({
|
|
299
|
+
permissions,
|
|
300
|
+
roleGrants: {
|
|
301
|
+
admin: ["admin", "editor", "user"], // Admins can assign any role
|
|
302
|
+
editor: ["user"], // Editors can only assign "user"
|
|
303
|
+
// Users can't assign roles at all (not listed)
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### User Impersonation
|
|
309
|
+
|
|
310
|
+
For debugging and support. Admins can see exactly what a user sees:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// Server: start impersonation (requires admin role by default)
|
|
314
|
+
await auth.impersonate(adminUserId, targetUserId);
|
|
315
|
+
|
|
316
|
+
// The admin's session now behaves as the target user
|
|
317
|
+
// All permission checks use the target user's roles
|
|
318
|
+
// An "impersonating" flag is set so the UI can show a banner
|
|
319
|
+
|
|
320
|
+
// Client: check impersonation state via useCurrentUser
|
|
321
|
+
const user = useCurrentUser();
|
|
322
|
+
// user.isImpersonating — true when admin is impersonating
|
|
323
|
+
// user.realUser — { id, name } of the admin doing the impersonating
|
|
324
|
+
|
|
325
|
+
// Client: stop impersonating via useAuth
|
|
326
|
+
const { stopImpersonating } = useAuth();
|
|
327
|
+
await stopImpersonating();
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Email Templates
|
|
331
|
+
|
|
332
|
+
Auth emails (magic links) can use custom HTML templates. The template function receives the magic link URL and email address and returns an HTML string:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
createAuth({
|
|
336
|
+
// ...
|
|
337
|
+
templates: {
|
|
338
|
+
magicLink: ({ url, email }) =>
|
|
339
|
+
`<p>Hi ${email}, <a href="${url}">click here to sign in</a>.</p>`,
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Templates are plain functions returning strings — no React or Node.js dependencies required, so they work in Workers.
|
|
345
|
+
|
|
346
|
+
## Package Exports
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
@cfast/auth
|
|
350
|
+
├── . → Server: createAuth, createRoleManager,
|
|
351
|
+
│ createImpersonationManager, createAuthRouteHandlers, types
|
|
352
|
+
├── /client → Client: AuthProvider, AuthClientProvider, AuthGuard,
|
|
353
|
+
│ LoginPage, useCurrentUser, useAuth, createAuthClient,
|
|
354
|
+
│ LoginComponents, UseAuthReturn, AuthClientInstance types
|
|
355
|
+
├── /plugin → Route helper: authRoutes() for routes.ts
|
|
356
|
+
└── /schema → Drizzle schema: auth tables for migrations
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Server code stays out of client bundles. The `/plugin` entrypoint is only used in `routes.ts` (build-time). The `/schema` entrypoint lets `@cfast/db` include auth tables in migrations without importing the full auth package.
|
|
360
|
+
|
|
361
|
+
## Integration
|
|
362
|
+
|
|
363
|
+
The auth → db → operations flow:
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// In a React Router loader:
|
|
367
|
+
export async function loader({ request, context }) {
|
|
368
|
+
const user = await auth.requireUser(request);
|
|
369
|
+
|
|
370
|
+
const db = createDb({
|
|
371
|
+
d1: context.env.DB,
|
|
372
|
+
schema,
|
|
373
|
+
permissions,
|
|
374
|
+
user, // ← from auth. Determines which grants apply to every Operation.
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// Operations now check permissions against this user's roles automatically
|
|
378
|
+
const posts = db.query(postsTable).findMany();
|
|
379
|
+
const results = await posts.run({}); // permission filters applied based on user.roles
|
|
380
|
+
return { user, posts: results };
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Changing a user's role (via `auth.setRole`) immediately affects which Operations they can run. No cache to clear, no separate sync step — the next `createDb({ user })` call picks up the new roles.
|
|
385
|
+
|
|
386
|
+
## Schema
|
|
387
|
+
|
|
388
|
+
`@cfast/auth` adds its tables to your Drizzle schema automatically. The tables follow Better Auth conventions but are managed through cfast's migration system:
|
|
389
|
+
|
|
390
|
+
- `user` - Users with email, name, avatar
|
|
391
|
+
- `session` - Active sessions
|
|
392
|
+
- `passkey` - Registered WebAuthn credentials
|
|
393
|
+
- `role` - User-to-role assignments
|
|
394
|
+
- `impersonation_log` - Audit trail for impersonation events
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { A as AuthUser } from './types-ghXti5CW.js';
|
|
3
|
+
import { ReactNode, ComponentType } from 'react';
|
|
4
|
+
export { createAuthClient } from 'better-auth/react';
|
|
5
|
+
export { magicLinkClient } from 'better-auth/client/plugins';
|
|
6
|
+
import '@cfast/permissions';
|
|
7
|
+
|
|
8
|
+
type AuthProviderProps = {
|
|
9
|
+
user: AuthUser | null;
|
|
10
|
+
loginPath?: string;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
};
|
|
13
|
+
type AuthClientInstance = {
|
|
14
|
+
signOut: () => Promise<unknown>;
|
|
15
|
+
passkey?: {
|
|
16
|
+
addPasskey: () => Promise<{
|
|
17
|
+
error?: {
|
|
18
|
+
message?: string;
|
|
19
|
+
} | null;
|
|
20
|
+
} | undefined>;
|
|
21
|
+
deletePasskey: (opts: {
|
|
22
|
+
id: string;
|
|
23
|
+
}) => Promise<{
|
|
24
|
+
error?: {
|
|
25
|
+
message?: string;
|
|
26
|
+
} | null;
|
|
27
|
+
} | undefined>;
|
|
28
|
+
};
|
|
29
|
+
admin?: {
|
|
30
|
+
stopImpersonating: () => Promise<unknown>;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
type AuthClientProviderProps = {
|
|
34
|
+
authClient: AuthClientInstance;
|
|
35
|
+
children: ReactNode;
|
|
36
|
+
};
|
|
37
|
+
type UseAuthReturn = {
|
|
38
|
+
signOut: () => Promise<void>;
|
|
39
|
+
registerPasskey: () => Promise<{
|
|
40
|
+
error?: {
|
|
41
|
+
message?: string;
|
|
42
|
+
} | null;
|
|
43
|
+
} | undefined>;
|
|
44
|
+
deletePasskey: (id: string) => Promise<{
|
|
45
|
+
error?: {
|
|
46
|
+
message?: string;
|
|
47
|
+
} | null;
|
|
48
|
+
} | undefined>;
|
|
49
|
+
stopImpersonating: () => Promise<void>;
|
|
50
|
+
authClient: AuthClientInstance;
|
|
51
|
+
};
|
|
52
|
+
type LoginComponents = {
|
|
53
|
+
Layout?: ComponentType<{
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
}>;
|
|
56
|
+
EmailInput?: ComponentType<{
|
|
57
|
+
value: string;
|
|
58
|
+
onChange: (value: string) => void;
|
|
59
|
+
error?: string;
|
|
60
|
+
}>;
|
|
61
|
+
PasskeyButton?: ComponentType<{
|
|
62
|
+
onClick: () => void;
|
|
63
|
+
loading: boolean;
|
|
64
|
+
}>;
|
|
65
|
+
MagicLinkButton?: ComponentType<{
|
|
66
|
+
onClick: () => void;
|
|
67
|
+
loading: boolean;
|
|
68
|
+
}>;
|
|
69
|
+
SuccessMessage?: ComponentType<{
|
|
70
|
+
email: string;
|
|
71
|
+
}>;
|
|
72
|
+
ErrorMessage?: ComponentType<{
|
|
73
|
+
error: string;
|
|
74
|
+
}>;
|
|
75
|
+
};
|
|
76
|
+
type LoginPageProps = {
|
|
77
|
+
authClient: {
|
|
78
|
+
signIn: {
|
|
79
|
+
magicLink: (opts: {
|
|
80
|
+
email: string;
|
|
81
|
+
}) => Promise<{
|
|
82
|
+
error?: {
|
|
83
|
+
message?: string;
|
|
84
|
+
} | null;
|
|
85
|
+
}>;
|
|
86
|
+
passkey?: () => Promise<{
|
|
87
|
+
error?: {
|
|
88
|
+
message?: string;
|
|
89
|
+
} | null;
|
|
90
|
+
} | undefined>;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
components?: LoginComponents;
|
|
94
|
+
title?: string;
|
|
95
|
+
subtitle?: string;
|
|
96
|
+
onSuccess?: () => void;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
declare function AuthProvider({ user, loginPath, children, }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
100
|
+
/**
|
|
101
|
+
* Access the current user from the nearest AuthProvider.
|
|
102
|
+
* Returns `AuthUser | null` — null when not authenticated.
|
|
103
|
+
*
|
|
104
|
+
* Must be used within an `<AuthProvider>`.
|
|
105
|
+
*/
|
|
106
|
+
declare function useCurrentUser(): AuthUser | null;
|
|
107
|
+
/**
|
|
108
|
+
* Access the login path configured in the nearest AuthProvider.
|
|
109
|
+
*/
|
|
110
|
+
declare function useLoginPath(): string;
|
|
111
|
+
|
|
112
|
+
type AuthGuardProps = {
|
|
113
|
+
user: AuthUser;
|
|
114
|
+
children: ReactNode;
|
|
115
|
+
};
|
|
116
|
+
declare function AuthGuard({ user, children }: AuthGuardProps): react_jsx_runtime.JSX.Element;
|
|
117
|
+
|
|
118
|
+
declare function AuthClientProvider({ authClient, children, }: AuthClientProviderProps): react_jsx_runtime.JSX.Element;
|
|
119
|
+
declare function useAuth(): UseAuthReturn;
|
|
120
|
+
|
|
121
|
+
declare function LoginPage({ authClient, components, title, subtitle, onSuccess, }: LoginPageProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
|
|
123
|
+
export { type AuthClientInstance, AuthClientProvider, type AuthClientProviderProps, AuthGuard, type AuthGuardProps, AuthProvider, type AuthProviderProps, type LoginComponents, LoginPage, type LoginPageProps, type UseAuthReturn, useAuth, useCurrentUser, useLoginPath };
|