@cfast/auth 0.0.1 → 0.1.0

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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as AuthConfig, b as AuthEnvConfig, c as AuthInstance } from './types-ghXti5CW.js';
2
- export { d as AuthContext, A as AuthUser, e as AuthenticatedContext } from './types-ghXti5CW.js';
3
- import '@cfast/permissions';
1
+ import { a as AuthConfig, b as AuthEnvConfig, c as AuthInstance, A as AuthUser } from './types-ghXti5CW.js';
2
+ export { d as AuthContext, e as AuthenticatedContext } from './types-ghXti5CW.js';
3
+ import { Grant } from '@cfast/permissions';
4
4
 
5
5
  /**
6
6
  * Creates a pre-configured auth factory for Cloudflare Workers.
@@ -164,4 +164,43 @@ declare function createAuthRouteHandlers(getAuth: () => AuthInstance): {
164
164
  }) => Promise<Response>;
165
165
  };
166
166
 
167
- export { AuthConfig, AuthEnvConfig, AuthInstance, createAuth, createAuthRouteHandlers, createImpersonationManager, createRoleManager };
167
+ /**
168
+ * Adapter type matching @cfast/admin's AdminAuthConfig interface.
169
+ * Duplicated here to avoid a circular dependency on @cfast/admin.
170
+ */
171
+ type AdminAuthBridge = {
172
+ requireUser(request: Request): Promise<{
173
+ user: AuthUser;
174
+ grants: Grant[];
175
+ }>;
176
+ hasRole(user: {
177
+ roles: string[];
178
+ }, role: string): boolean;
179
+ getRoles(userId: string): Promise<string[]>;
180
+ setRole(userId: string, role: string): Promise<void>;
181
+ removeRole(userId: string, role: string): Promise<void>;
182
+ setRoles(userId: string, roles: string[]): Promise<void>;
183
+ };
184
+ /**
185
+ * Creates an admin auth adapter from a cfast auth instance factory.
186
+ *
187
+ * Replaces ~150 lines of manual adapter boilerplate with a single call.
188
+ * The factory is called per-operation to ensure fresh env bindings on Workers.
189
+ *
190
+ * @param getAuth - Factory that returns an initialized AuthInstance.
191
+ * @returns An object satisfying `@cfast/admin`'s `AdminAuthConfig` interface.
192
+ *
193
+ * @example
194
+ * ```ts
195
+ * import { createAdminAuth } from "@cfast/auth";
196
+ *
197
+ * const auth = createAdminAuth(() =>
198
+ * initAuth({ d1: env.get().DB, appUrl: env.get().APP_URL })
199
+ * );
200
+ *
201
+ * const admin = createAdmin({ auth, db: createDbForAdmin, schema });
202
+ * ```
203
+ */
204
+ declare function createAdminAuth(getAuth: () => AuthInstance): AdminAuthBridge;
205
+
206
+ export { AuthConfig, AuthEnvConfig, AuthInstance, AuthUser, createAdminAuth, createAuth, createAuthRouteHandlers, createImpersonationManager, createRoleManager };
package/dist/index.js CHANGED
@@ -252,7 +252,33 @@ function createAuthRouteHandlers(getAuth) {
252
252
  }
253
253
  return { loader: handleRequest, action: handleRequest };
254
254
  }
255
+
256
+ // src/admin-auth.ts
257
+ function createAdminAuth(getAuth) {
258
+ return {
259
+ async requireUser(request) {
260
+ const ctx = await getAuth().requireUser(request);
261
+ return { user: ctx.user, grants: ctx.grants };
262
+ },
263
+ hasRole(user, role) {
264
+ return user.roles.includes(role);
265
+ },
266
+ async getRoles(userId) {
267
+ return getAuth().getRoles(userId);
268
+ },
269
+ async setRole(userId, role) {
270
+ await getAuth().setRole(userId, role);
271
+ },
272
+ async removeRole(userId, role) {
273
+ await getAuth().removeRole(userId, role);
274
+ },
275
+ async setRoles(userId, roles) {
276
+ await getAuth().setRoles(userId, roles);
277
+ }
278
+ };
279
+ }
255
280
  export {
281
+ createAdminAuth,
256
282
  createAuth,
257
283
  createAuthRouteHandlers,
258
284
  createImpersonationManager,
package/llms.txt ADDED
@@ -0,0 +1,188 @@
1
+ # @cfast/auth
2
+
3
+ > Authentication for Cloudflare Workers: magic email links, passkeys, roles, impersonation. Built on Better Auth.
4
+
5
+ ## When to use
6
+
7
+ Use `@cfast/auth` to add authentication to a cfast app. It handles login (magic link + passkeys), session management, role assignment, and user impersonation. It produces the `user` and `grants` objects that `@cfast/db` needs for permission-aware queries.
8
+
9
+ ## Key concepts
10
+
11
+ - **Two-phase initialization.** `createAuth(config)` returns an `initAuth` factory. Call `initAuth({ d1, appUrl })` per-request to get an `AuthInstance`.
12
+ - **Roles bridge auth and permissions.** Auth assigns roles to users. `@cfast/permissions` defines what roles can do. The `grants` from auth feed directly into `createDb()`.
13
+ - **Cookie-based redirect-back.** Unauthenticated users get a `cfast_redirect_to` cookie before redirecting to `/login`. After login, the cookie restores their intended destination.
14
+
15
+ ## API Reference
16
+
17
+ ### Server: createAuth(config) => initAuth
18
+
19
+ ```typescript
20
+ import { createAuth } from "@cfast/auth";
21
+
22
+ export const initAuth = createAuth({
23
+ permissions: Permissions, // from definePermissions()
24
+ magicLink?: {
25
+ sendMagicLink: (params: { email: string; url: string }) => Promise<void>,
26
+ },
27
+ passkeys?: { rpName: string; rpId: string },
28
+ session?: { expiresIn?: string }, // e.g. "30d"
29
+ redirects?: { afterLogin?: string; loginPath?: string },
30
+ anonymousRoles?: string[],
31
+ defaultRoles?: string[], // default: ["reader"]
32
+ roleGrants?: Record<string, string[]>, // who can assign which roles
33
+ impersonation?: { allowedRoles?: string[] },
34
+ templates?: { magicLink?: (props: { url: string; email: string }) => string },
35
+ });
36
+ ```
37
+
38
+ ### initAuth(env) => AuthInstance
39
+
40
+ ```typescript
41
+ const auth: AuthInstance = initAuth({ d1: env.DB, appUrl: "https://myapp.com" });
42
+ ```
43
+
44
+ ### AuthInstance methods
45
+
46
+ ```typescript
47
+ auth.createContext(request): Promise<AuthContext>
48
+ // { user: AuthUser | null, grants: Grant[] }
49
+
50
+ auth.requireUser(request): Promise<AuthenticatedContext>
51
+ // { user: AuthUser, grants: Grant[] } -- throws 302 redirect if not authenticated
52
+
53
+ auth.getRoles(userId): Promise<string[]>
54
+ auth.setRole(userId, role, caller?): Promise<void>
55
+ auth.setRoles(userId, roles, caller?): Promise<void>
56
+ auth.removeRole(userId, role): Promise<void>
57
+
58
+ auth.impersonate(adminUserId, targetUserId): Promise<void>
59
+ auth.stopImpersonating(adminUserId): Promise<void>
60
+
61
+ auth.sendMagicLink({ email, callbackURL? }): Promise<void>
62
+ auth.handler(request): Promise<Response> // forwards to Better Auth
63
+ ```
64
+
65
+ ### AuthUser type
66
+
67
+ ```typescript
68
+ type AuthUser = {
69
+ id: string;
70
+ email: string;
71
+ name: string;
72
+ avatarUrl: string | null;
73
+ roles: string[];
74
+ isImpersonating?: boolean;
75
+ realUser?: { id: string; name: string };
76
+ };
77
+ ```
78
+
79
+ ### createAdminAuth(getAuth): AdminAuthBridge
80
+
81
+ ```typescript
82
+ import { createAdminAuth } from "@cfast/auth";
83
+
84
+ function createAdminAuth(getAuth: () => AuthInstance): AdminAuthBridge
85
+ ```
86
+
87
+ Creates an admin auth adapter from a cfast auth instance factory. Replaces ~150 lines of manual adapter boilerplate with a single call. The factory is called per-operation to ensure fresh env bindings on Workers.
88
+
89
+ Returns an object satisfying `@cfast/admin`'s `AdminAuthConfig` interface with: `requireUser`, `hasRole`, `getRoles`, `setRole`, `removeRole`, `setRoles`.
90
+
91
+ ```typescript
92
+ const auth = createAdminAuth(() =>
93
+ initAuth({ d1: env.get().DB, appUrl: env.get().APP_URL })
94
+ );
95
+ const admin = createAdmin({ auth, db: createDbForAdmin, schema });
96
+ ```
97
+
98
+ ### Client exports (`@cfast/auth/client`)
99
+
100
+ ```typescript
101
+ // Providers
102
+ <AuthClientProvider authClient={authClient}> // wraps app root
103
+ <AuthProvider user={user}> // wraps layout routes
104
+ <AuthGuard user={user}> // layout component, provides user to children
105
+
106
+ // Hooks
107
+ useCurrentUser(): AuthUser | null // user from nearest AuthGuard/AuthProvider
108
+ useAuth(): UseAuthReturn // { signOut, registerPasskey, deletePasskey, stopImpersonating, authClient }
109
+
110
+ // Login
111
+ <LoginPage authClient={authClient} components? title? subtitle? />
112
+ createAuthClient(): AuthClientInstance
113
+ ```
114
+
115
+ ### LoginComponents slots
116
+
117
+ ```typescript
118
+ type LoginComponents = {
119
+ Layout?, EmailInput?, PasskeyButton?, MagicLinkButton?,
120
+ SuccessMessage?, ErrorMessage?,
121
+ };
122
+ ```
123
+
124
+ ### Route plugin (`@cfast/auth/plugin`)
125
+
126
+ ```typescript
127
+ import { authRoutes } from "@cfast/auth/plugin";
128
+ // In routes.ts:
129
+ export default [...authRoutes({ handlerFile: "routes/auth.$.tsx" }), ...otherRoutes];
130
+ ```
131
+
132
+ ### Schema (`@cfast/auth/schema`)
133
+
134
+ Drizzle tables: `user`, `session`, `passkey`, `role`, `impersonation_log`.
135
+
136
+ ## Usage Examples
137
+
138
+ ### Protect a layout route
139
+
140
+ ```typescript
141
+ // routes/_protected.tsx
142
+ import { AuthGuard } from "@cfast/auth/client";
143
+
144
+ export async function loader({ request, context }) {
145
+ const auth = initAuth({ d1: context.env.DB, appUrl: context.env.APP_URL });
146
+ const { user, grants } = await auth.requireUser(request);
147
+ return { user };
148
+ }
149
+
150
+ export default function ProtectedLayout() {
151
+ const { user } = useLoaderData<typeof loader>();
152
+ return <AuthGuard user={user}><Outlet /></AuthGuard>;
153
+ }
154
+ ```
155
+
156
+ ### Auth -> Db flow in a loader
157
+
158
+ ```typescript
159
+ export async function loader({ request, context }) {
160
+ const auth = initAuth({ d1: context.env.DB, appUrl: context.env.APP_URL });
161
+ const { user, grants } = await auth.requireUser(request);
162
+
163
+ const db = createDb({ d1: context.env.DB, schema, grants, user });
164
+ const posts = await db.query(postsTable).findMany().run({});
165
+ return { user, posts };
166
+ }
167
+ ```
168
+
169
+ ### Role management
170
+
171
+ ```typescript
172
+ await auth.setRole(userId, "editor");
173
+ await auth.setRoles(userId, ["editor", "moderator"]);
174
+ await auth.removeRole(userId, "editor");
175
+ ```
176
+
177
+ ## Integration
178
+
179
+ - **@cfast/permissions** -- `createAuth({ permissions })` takes the permissions config. Roles defined in permissions are the same roles assigned to users. `auth.requireUser()` returns `grants` resolved from the user's roles.
180
+ - **@cfast/db** -- Pass `{ user, grants }` from `auth.requireUser()` directly to `createDb()`. Role changes via `auth.setRole()` take effect on the next request.
181
+ - **@cfast/ui/joy** -- Provides `joyLoginComponents` for Joy UI styled login page slots.
182
+
183
+ ## Common Mistakes
184
+
185
+ - **Calling `createAuth()` per-request** -- `createAuth()` is called once at module level. Only `initAuth()` is called per-request with the D1 binding.
186
+ - **Forgetting to add auth routes** -- The magic link callback and passkey endpoints need `authRoutes()` in your `routes.ts`.
187
+ - **Using `unsafe()` instead of roles for admin** -- Admins should have a proper role with grants, not bypass permissions entirely.
188
+ - **Not wrapping the app with `AuthClientProvider`** -- `useAuth()` and `LoginPage` require the provider at the app root.
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "@cfast/auth",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "Authentication for Cloudflare Workers: magic email, passkeys, roles, and impersonation",
5
+ "keywords": [
6
+ "cfast",
7
+ "cloudflare-workers",
8
+ "authentication",
9
+ "passkeys",
10
+ "magic-link"
11
+ ],
5
12
  "license": "MIT",
6
13
  "repository": {
7
14
  "type": "git",
@@ -30,19 +37,27 @@
30
37
  }
31
38
  },
32
39
  "files": [
33
- "dist"
40
+ "dist",
41
+ "llms.txt"
34
42
  ],
35
43
  "sideEffects": false,
36
44
  "publishConfig": {
37
45
  "access": "public"
38
46
  },
47
+ "scripts": {
48
+ "build": "tsup src/index.ts src/client.ts src/plugin.ts src/schema.ts --format esm --dts",
49
+ "dev": "tsup src/index.ts src/client.ts src/plugin.ts src/schema.ts --format esm --dts --watch",
50
+ "test": "vitest run",
51
+ "typecheck": "tsc --noEmit",
52
+ "lint": "eslint src/"
53
+ },
39
54
  "peerDependencies": {
40
55
  "better-auth": ">=1",
41
56
  "drizzle-orm": ">=0.35",
42
57
  "react": ">=18"
43
58
  },
44
59
  "dependencies": {
45
- "@cfast/permissions": "0.0.1"
60
+ "@cfast/permissions": "workspace:*"
46
61
  },
47
62
  "devDependencies": {
48
63
  "@cloudflare/workers-types": "^4.20260305.1",
@@ -55,12 +70,5 @@
55
70
  "tsup": "^8",
56
71
  "typescript": "^5.7",
57
72
  "vitest": "^4.1.0"
58
- },
59
- "scripts": {
60
- "build": "tsup src/index.ts src/client.ts src/plugin.ts src/schema.ts --format esm --dts",
61
- "dev": "tsup src/index.ts src/client.ts src/plugin.ts src/schema.ts --format esm --dts --watch",
62
- "test": "vitest run",
63
- "typecheck": "tsc --noEmit",
64
- "lint": "eslint src/"
65
73
  }
66
- }
74
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
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.
@@ -1,64 +0,0 @@
1
- import { Permissions, Grant } from '@cfast/permissions';
2
-
3
- type AuthUser = {
4
- id: string;
5
- email: string;
6
- name: string;
7
- avatarUrl: string | null;
8
- roles: string[];
9
- isImpersonating?: boolean;
10
- realUser?: {
11
- id: string;
12
- name: string;
13
- };
14
- };
15
- type AuthContext = {
16
- user: AuthUser | null;
17
- grants: Grant[];
18
- };
19
- type AuthenticatedContext = {
20
- user: AuthUser;
21
- grants: Grant[];
22
- };
23
- type AuthConfig = {
24
- permissions: Permissions;
25
- schema?: Record<string, unknown>;
26
- passkeys?: {
27
- rpName: string;
28
- rpId: string;
29
- };
30
- magicLink?: {
31
- sendMagicLink: (params: {
32
- email: string;
33
- url: string;
34
- }) => Promise<void>;
35
- };
36
- session?: {
37
- expiresIn?: string;
38
- };
39
- redirects?: {
40
- afterLogin?: string;
41
- loginPath?: string;
42
- };
43
- anonymousRoles?: string[];
44
- defaultRoles?: string[];
45
- roleTableName?: string;
46
- };
47
- type AuthEnvConfig = {
48
- d1: D1Database;
49
- appUrl: string;
50
- };
51
- type AuthInstance = {
52
- createContext: (request: Request) => Promise<AuthContext>;
53
- requireUser: (request: Request) => Promise<AuthenticatedContext>;
54
- getRoles: (userId: string) => Promise<string[]>;
55
- setRole: (userId: string, role: string) => Promise<void>;
56
- setRoles: (userId: string, roles: string[]) => Promise<void>;
57
- removeRole: (userId: string, role: string) => Promise<void>;
58
- /** Handle auth API requests (forwards to Better Auth) */
59
- handler: (request: Request) => Promise<Response>;
60
- /** The underlying Better Auth instance */
61
- api: unknown;
62
- };
63
-
64
- export type { AuthUser as A, AuthConfig as a, AuthEnvConfig as b, AuthInstance as c, AuthContext as d, AuthenticatedContext as e };
@@ -1,63 +0,0 @@
1
- import { Permissions, Grant } from '@cfast/permissions';
2
-
3
- type AuthUser = {
4
- id: string;
5
- email: string;
6
- name: string;
7
- avatarUrl: string | null;
8
- roles: string[];
9
- isImpersonating?: boolean;
10
- realUser?: {
11
- id: string;
12
- name: string;
13
- };
14
- };
15
- type AuthContext = {
16
- user: AuthUser | null;
17
- grants: Grant[];
18
- };
19
- type AuthenticatedContext = {
20
- user: AuthUser;
21
- grants: Grant[];
22
- };
23
- type AuthConfig = {
24
- permissions: Permissions;
25
- schema?: Record<string, unknown>;
26
- passkeys?: {
27
- rpName: string;
28
- rpId: string;
29
- };
30
- magicLink?: {
31
- sendMagicLink: (params: {
32
- email: string;
33
- url: string;
34
- }) => Promise<void>;
35
- };
36
- session?: {
37
- expiresIn?: string;
38
- };
39
- redirects?: {
40
- afterLogin?: string;
41
- loginPath?: string;
42
- };
43
- anonymousRoles?: string[];
44
- defaultRoles?: string[];
45
- };
46
- type AuthEnvConfig = {
47
- d1: D1Database;
48
- appUrl: string;
49
- };
50
- type AuthInstance = {
51
- createContext: (request: Request) => Promise<AuthContext>;
52
- requireUser: (request: Request) => Promise<AuthenticatedContext>;
53
- getRoles: (userId: string) => Promise<string[]>;
54
- setRole: (userId: string, role: string) => Promise<void>;
55
- setRoles: (userId: string, roles: string[]) => Promise<void>;
56
- removeRole: (userId: string, role: string) => Promise<void>;
57
- /** Handle auth API requests (forwards to Better Auth) */
58
- handler: (request: Request) => Promise<Response>;
59
- /** The underlying Better Auth instance */
60
- api: unknown;
61
- };
62
-
63
- export type { AuthUser as A, AuthConfig as a, AuthEnvConfig as b, AuthInstance as c, AuthContext as d, AuthenticatedContext as e };
@@ -1,74 +0,0 @@
1
- import { Permissions, Grant } from '@cfast/permissions';
2
-
3
- type AuthUser = {
4
- id: string;
5
- email: string;
6
- name: string;
7
- avatarUrl: string | null;
8
- roles: string[];
9
- isImpersonating?: boolean;
10
- realUser?: {
11
- id: string;
12
- name: string;
13
- };
14
- };
15
- type AuthContext = {
16
- user: AuthUser | null;
17
- grants: Grant[];
18
- };
19
- type AuthenticatedContext = {
20
- user: AuthUser;
21
- grants: Grant[];
22
- };
23
- type AuthConfig = {
24
- permissions: Permissions;
25
- schema?: Record<string, unknown>;
26
- passkeys?: {
27
- rpName: string;
28
- rpId: string;
29
- };
30
- magicLink?: {
31
- sendMagicLink: (params: {
32
- email: string;
33
- url: string;
34
- }) => Promise<void>;
35
- };
36
- session?: {
37
- expiresIn?: string;
38
- };
39
- redirects?: {
40
- afterLogin?: string;
41
- loginPath?: string;
42
- };
43
- anonymousRoles?: string[];
44
- defaultRoles?: string[];
45
- roleTableName?: string;
46
- roleGrants?: Record<string, string[]>;
47
- impersonation?: {
48
- allowedRoles?: string[];
49
- };
50
- };
51
- type AuthEnvConfig = {
52
- d1: D1Database;
53
- appUrl: string;
54
- };
55
- type AuthInstance = {
56
- createContext: (request: Request) => Promise<AuthContext>;
57
- requireUser: (request: Request) => Promise<AuthenticatedContext>;
58
- getRoles: (userId: string) => Promise<string[]>;
59
- setRole: (userId: string, role: string, caller?: {
60
- callerRoles?: string[];
61
- }) => Promise<void>;
62
- setRoles: (userId: string, roles: string[], caller?: {
63
- callerRoles?: string[];
64
- }) => Promise<void>;
65
- removeRole: (userId: string, role: string) => Promise<void>;
66
- impersonate: (adminUserId: string, targetUserId: string) => Promise<void>;
67
- stopImpersonating: (adminUserId: string) => Promise<void>;
68
- /** Handle auth API requests (forwards to Better Auth) */
69
- handler: (request: Request) => Promise<Response>;
70
- /** The underlying Better Auth instance */
71
- api: unknown;
72
- };
73
-
74
- export type { AuthUser as A, AuthConfig as a, AuthEnvConfig as b, AuthInstance as c, AuthContext as d, AuthenticatedContext as e };
@@ -1,85 +0,0 @@
1
- import { Permissions, Grant } from '@cfast/permissions';
2
-
3
- type AuthUser = {
4
- id: string;
5
- email: string;
6
- name: string;
7
- avatarUrl: string | null;
8
- roles: string[];
9
- isImpersonating?: boolean;
10
- realUser?: {
11
- id: string;
12
- name: string;
13
- };
14
- };
15
- type AuthContext = {
16
- user: AuthUser | null;
17
- grants: Grant[];
18
- };
19
- type AuthenticatedContext = {
20
- user: AuthUser;
21
- grants: Grant[];
22
- };
23
- type AuthConfig = {
24
- permissions: Permissions;
25
- schema?: Record<string, unknown>;
26
- passkeys?: {
27
- rpName: string;
28
- rpId: string;
29
- };
30
- magicLink?: {
31
- sendMagicLink: (params: {
32
- email: string;
33
- url: string;
34
- }) => Promise<void>;
35
- };
36
- session?: {
37
- expiresIn?: string;
38
- };
39
- redirects?: {
40
- afterLogin?: string;
41
- loginPath?: string;
42
- };
43
- anonymousRoles?: string[];
44
- defaultRoles?: string[];
45
- roleTableName?: string;
46
- roleGrants?: Record<string, string[]>;
47
- impersonation?: {
48
- allowedRoles?: string[];
49
- };
50
- templates?: {
51
- magicLink?: (props: {
52
- url: string;
53
- email: string;
54
- }) => string;
55
- };
56
- };
57
- type AuthEnvConfig = {
58
- d1: D1Database;
59
- appUrl: string;
60
- };
61
- type AuthInstance = {
62
- createContext: (request: Request) => Promise<AuthContext>;
63
- requireUser: (request: Request) => Promise<AuthenticatedContext>;
64
- getRoles: (userId: string) => Promise<string[]>;
65
- setRole: (userId: string, role: string, caller?: {
66
- callerRoles?: string[];
67
- }) => Promise<void>;
68
- setRoles: (userId: string, roles: string[], caller?: {
69
- callerRoles?: string[];
70
- }) => Promise<void>;
71
- removeRole: (userId: string, role: string) => Promise<void>;
72
- impersonate: (adminUserId: string, targetUserId: string) => Promise<void>;
73
- stopImpersonating: (adminUserId: string) => Promise<void>;
74
- /** Send a magic link email to the given address */
75
- sendMagicLink: (params: {
76
- email: string;
77
- callbackURL?: string;
78
- }) => Promise<void>;
79
- /** Handle auth API requests (forwards to Better Auth) */
80
- handler: (request: Request) => Promise<Response>;
81
- /** The underlying Better Auth instance */
82
- api: unknown;
83
- };
84
-
85
- export type { AuthUser as A, AuthConfig as a, AuthEnvConfig as b, AuthInstance as c, AuthContext as d, AuthenticatedContext as e };
@@ -1,62 +0,0 @@
1
- import { Permissions, Grant } from '@cfast/permissions';
2
-
3
- type AuthUser = {
4
- id: string;
5
- email: string;
6
- name: string;
7
- avatarUrl: string | null;
8
- roles: string[];
9
- isImpersonating?: boolean;
10
- realUser?: {
11
- id: string;
12
- name: string;
13
- };
14
- };
15
- type AuthContext = {
16
- user: AuthUser | null;
17
- grants: Grant[];
18
- };
19
- type AuthenticatedContext = {
20
- user: AuthUser;
21
- grants: Grant[];
22
- };
23
- type AuthConfig = {
24
- permissions: Permissions;
25
- passkeys?: {
26
- rpName: string;
27
- rpId: string;
28
- };
29
- magicLink?: {
30
- sendMagicLink: (params: {
31
- email: string;
32
- url: string;
33
- }) => Promise<void>;
34
- };
35
- session?: {
36
- expiresIn?: string;
37
- };
38
- redirects?: {
39
- afterLogin?: string;
40
- loginPath?: string;
41
- };
42
- anonymousRoles?: string[];
43
- defaultRoles?: string[];
44
- };
45
- type AuthEnvConfig = {
46
- d1: D1Database;
47
- appUrl: string;
48
- };
49
- type AuthInstance = {
50
- createContext: (request: Request) => Promise<AuthContext>;
51
- requireUser: (request: Request) => Promise<AuthenticatedContext>;
52
- getRoles: (userId: string) => Promise<string[]>;
53
- setRole: (userId: string, role: string) => Promise<void>;
54
- setRoles: (userId: string, roles: string[]) => Promise<void>;
55
- removeRole: (userId: string, role: string) => Promise<void>;
56
- /** Handle auth API requests (forwards to Better Auth) */
57
- handler: (request: Request) => Promise<Response>;
58
- /** The underlying Better Auth instance */
59
- api: unknown;
60
- };
61
-
62
- export type { AuthUser as A, AuthConfig as a, AuthEnvConfig as b, AuthInstance as c, AuthContext as d, AuthenticatedContext as e };