@veloxts/auth 0.3.3 → 0.3.4
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 +755 -30
- package/dist/adapter.d.ts +710 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +581 -0
- package/dist/adapter.js.map +1 -0
- package/dist/adapters/better-auth.d.ts +271 -0
- package/dist/adapters/better-auth.d.ts.map +1 -0
- package/dist/adapters/better-auth.js +341 -0
- package/dist/adapters/better-auth.js.map +1 -0
- package/dist/adapters/index.d.ts +28 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +28 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/csrf.d.ts +294 -0
- package/dist/csrf.d.ts.map +1 -0
- package/dist/csrf.js +396 -0
- package/dist/csrf.js.map +1 -0
- package/dist/guards.d.ts +139 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +247 -0
- package/dist/guards.js.map +1 -0
- package/dist/hash.d.ts +85 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +220 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +25 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -36
- package/dist/index.js.map +1 -1
- package/dist/jwt.d.ts +128 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +363 -0
- package/dist/jwt.js.map +1 -0
- package/dist/middleware.d.ts +87 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +241 -0
- package/dist/middleware.js.map +1 -0
- package/dist/plugin.d.ts +107 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +174 -0
- package/dist/plugin.js.map +1 -0
- package/dist/policies.d.ts +137 -0
- package/dist/policies.d.ts.map +1 -0
- package/dist/policies.js +240 -0
- package/dist/policies.js.map +1 -0
- package/dist/session.d.ts +494 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +795 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +251 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +33 -0
- package/dist/types.js.map +1 -0
- package/package.json +38 -7
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable Authentication Adapter System for @veloxts/auth
|
|
3
|
+
*
|
|
4
|
+
* This module provides a flexible adapter interface for integrating external
|
|
5
|
+
* authentication providers (BetterAuth, Clerk, Auth0, etc.) with VeloxTS.
|
|
6
|
+
*
|
|
7
|
+
* The adapter system abstracts provider-specific logic while maintaining
|
|
8
|
+
* full type safety and integration with VeloxTS's existing auth infrastructure.
|
|
9
|
+
*
|
|
10
|
+
* @module auth/adapter
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createAuthAdapterPlugin, defineAuthAdapter } from '@veloxts/auth';
|
|
15
|
+
* import { betterAuth } from 'better-auth';
|
|
16
|
+
*
|
|
17
|
+
* // Create a BetterAuth adapter
|
|
18
|
+
* const betterAuthAdapter = defineBetterAuthAdapter({
|
|
19
|
+
* auth: betterAuth({ database, trustedOrigins: [...] }),
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Create the plugin
|
|
23
|
+
* const authPlugin = createAuthAdapterPlugin(betterAuthAdapter);
|
|
24
|
+
*
|
|
25
|
+
* // Register with VeloxApp
|
|
26
|
+
* app.use(authPlugin);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import type { BaseContext, VeloxPlugin } from '@veloxts/core';
|
|
30
|
+
import type { MiddlewareFunction } from '@veloxts/router';
|
|
31
|
+
import type { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from 'fastify';
|
|
32
|
+
import type { AuthContext, User } from './types.js';
|
|
33
|
+
import { AuthError } from './types.js';
|
|
34
|
+
/**
|
|
35
|
+
* Error codes specific to auth adapter operations
|
|
36
|
+
*/
|
|
37
|
+
export type AuthAdapterErrorCode = 'ADAPTER_INIT_FAILED' | 'ADAPTER_SESSION_ERROR' | 'ADAPTER_ROUTE_ERROR' | 'ADAPTER_CALLBACK_ERROR' | 'ADAPTER_USER_TRANSFORM_ERROR' | 'ADAPTER_NOT_CONFIGURED' | 'ADAPTER_PROVIDER_ERROR';
|
|
38
|
+
/**
|
|
39
|
+
* Authentication adapter error
|
|
40
|
+
*
|
|
41
|
+
* Extends AuthError with adapter-specific error codes for
|
|
42
|
+
* better error handling and debugging.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* throw new AuthAdapterError(
|
|
47
|
+
* 'Failed to initialize BetterAuth adapter',
|
|
48
|
+
* 500,
|
|
49
|
+
* 'ADAPTER_INIT_FAILED',
|
|
50
|
+
* originalError
|
|
51
|
+
* );
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class AuthAdapterError extends AuthError {
|
|
55
|
+
/** Original error from the auth provider (if available) */
|
|
56
|
+
readonly cause?: Error;
|
|
57
|
+
/** Adapter-specific error code */
|
|
58
|
+
readonly code: AuthAdapterErrorCode;
|
|
59
|
+
constructor(message: string, statusCode: number, code: AuthAdapterErrorCode, cause?: Error);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Raw session data from the auth provider
|
|
63
|
+
*
|
|
64
|
+
* Auth providers return different session structures. This interface
|
|
65
|
+
* defines a normalized representation that adapters transform provider
|
|
66
|
+
* data into.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // BetterAuth returns
|
|
71
|
+
* { user: { id, email, name }, session: { id, expiresAt } }
|
|
72
|
+
*
|
|
73
|
+
* // Clerk returns
|
|
74
|
+
* { userId, sessionId, claims }
|
|
75
|
+
*
|
|
76
|
+
* // Adapters normalize to AdapterSession
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export interface AdapterSession {
|
|
80
|
+
/** Session ID from the provider */
|
|
81
|
+
sessionId: string;
|
|
82
|
+
/** User ID from the provider */
|
|
83
|
+
userId: string;
|
|
84
|
+
/** Session expiration timestamp (Unix ms) */
|
|
85
|
+
expiresAt?: number;
|
|
86
|
+
/** Whether the session is currently active */
|
|
87
|
+
isActive: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Provider-specific session data
|
|
90
|
+
*
|
|
91
|
+
* Adapters can store additional data from their provider here.
|
|
92
|
+
* This data is available but not guaranteed to follow any structure.
|
|
93
|
+
*/
|
|
94
|
+
providerData?: Record<string, unknown>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* User data from the auth provider
|
|
98
|
+
*
|
|
99
|
+
* Auth providers return different user structures. This interface
|
|
100
|
+
* defines the raw user data before transformation to VeloxTS User.
|
|
101
|
+
*/
|
|
102
|
+
export interface AdapterUser {
|
|
103
|
+
/** User ID from the provider */
|
|
104
|
+
id: string;
|
|
105
|
+
/** User email (required for VeloxTS User compatibility) */
|
|
106
|
+
email: string;
|
|
107
|
+
/** Display name (optional) */
|
|
108
|
+
name?: string;
|
|
109
|
+
/** Email verification status */
|
|
110
|
+
emailVerified?: boolean;
|
|
111
|
+
/** Profile image URL */
|
|
112
|
+
image?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Provider-specific user data
|
|
115
|
+
*
|
|
116
|
+
* Adapters can store additional data from their provider here.
|
|
117
|
+
*/
|
|
118
|
+
providerData?: Record<string, unknown>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Result of loading a session from the auth provider
|
|
122
|
+
*
|
|
123
|
+
* This is the primary return type from adapter.getSession().
|
|
124
|
+
* Contains both user and session data in a normalized format.
|
|
125
|
+
*/
|
|
126
|
+
export interface AdapterSessionResult {
|
|
127
|
+
/** User data from the provider */
|
|
128
|
+
user: AdapterUser;
|
|
129
|
+
/** Session data from the provider */
|
|
130
|
+
session: AdapterSession;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* HTTP methods supported by auth adapters
|
|
134
|
+
*/
|
|
135
|
+
export type AdapterHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
136
|
+
/**
|
|
137
|
+
* Route configuration for adapter-provided routes
|
|
138
|
+
*
|
|
139
|
+
* Auth providers often need to mount their own routes (e.g., `/api/auth/*`).
|
|
140
|
+
* This interface defines how those routes are configured.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const routes: AdapterRoute[] = [
|
|
145
|
+
* {
|
|
146
|
+
* path: '/api/auth/*',
|
|
147
|
+
* methods: ['GET', 'POST'],
|
|
148
|
+
* handler: async (request, reply) => {
|
|
149
|
+
* return auth.handler(request, reply);
|
|
150
|
+
* },
|
|
151
|
+
* },
|
|
152
|
+
* ];
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export interface AdapterRoute {
|
|
156
|
+
/**
|
|
157
|
+
* Route path pattern
|
|
158
|
+
*
|
|
159
|
+
* Supports Fastify path patterns including:
|
|
160
|
+
* - Static paths: `/api/auth/login`
|
|
161
|
+
* - Parametric paths: `/api/auth/callback/:provider`
|
|
162
|
+
* - Wildcard paths: `/api/auth/*`
|
|
163
|
+
*/
|
|
164
|
+
path: string;
|
|
165
|
+
/**
|
|
166
|
+
* HTTP methods this route handles
|
|
167
|
+
*
|
|
168
|
+
* If not specified, defaults to all methods.
|
|
169
|
+
*/
|
|
170
|
+
methods?: AdapterHttpMethod[];
|
|
171
|
+
/**
|
|
172
|
+
* Route handler function
|
|
173
|
+
*
|
|
174
|
+
* Receives Fastify request and reply objects.
|
|
175
|
+
* The adapter is responsible for returning the appropriate response.
|
|
176
|
+
*/
|
|
177
|
+
handler: RouteHandlerMethod;
|
|
178
|
+
/**
|
|
179
|
+
* Optional route description for documentation
|
|
180
|
+
*/
|
|
181
|
+
description?: string;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Base configuration shared by all auth adapters
|
|
185
|
+
*
|
|
186
|
+
* Individual adapters extend this with provider-specific configuration.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* interface BetterAuthAdapterConfig extends AuthAdapterConfig {
|
|
191
|
+
* auth: BetterAuthInstance;
|
|
192
|
+
* trustedOrigins?: string[];
|
|
193
|
+
* }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export interface AuthAdapterConfig {
|
|
197
|
+
/**
|
|
198
|
+
* Adapter name for identification and logging
|
|
199
|
+
*
|
|
200
|
+
* Should be a unique identifier like 'better-auth', 'clerk', 'auth0'.
|
|
201
|
+
*/
|
|
202
|
+
name: string;
|
|
203
|
+
/**
|
|
204
|
+
* Enable debug logging
|
|
205
|
+
*
|
|
206
|
+
* When true, the adapter logs detailed information about
|
|
207
|
+
* session loading, route handling, and errors.
|
|
208
|
+
*
|
|
209
|
+
* @default false
|
|
210
|
+
*/
|
|
211
|
+
debug?: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Transform adapter user to VeloxTS User
|
|
214
|
+
*
|
|
215
|
+
* Override this to customize how provider user data is
|
|
216
|
+
* transformed to the VeloxTS User interface.
|
|
217
|
+
*
|
|
218
|
+
* @param adapterUser - Raw user data from the provider
|
|
219
|
+
* @returns VeloxTS User object
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* transformUser: (adapterUser) => ({
|
|
224
|
+
* id: adapterUser.id,
|
|
225
|
+
* email: adapterUser.email,
|
|
226
|
+
* role: adapterUser.providerData?.role as string || 'user',
|
|
227
|
+
* permissions: adapterUser.providerData?.permissions as string[] || [],
|
|
228
|
+
* })
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
transformUser?: (adapterUser: AdapterUser) => User;
|
|
232
|
+
/**
|
|
233
|
+
* Routes to exclude from automatic session loading
|
|
234
|
+
*
|
|
235
|
+
* Useful for health check endpoints or public routes that
|
|
236
|
+
* should not trigger session loading.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* excludeRoutes: ['/api/health', '/api/public/*']
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
excludeRoutes?: string[];
|
|
244
|
+
/**
|
|
245
|
+
* Custom error handler for adapter errors
|
|
246
|
+
*
|
|
247
|
+
* Override to customize error responses sent to clients.
|
|
248
|
+
*/
|
|
249
|
+
onError?: (error: AuthAdapterError, request: FastifyRequest, reply: FastifyReply) => void | Promise<void>;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Authentication adapter interface
|
|
253
|
+
*
|
|
254
|
+
* This is the core contract that all auth adapters must implement.
|
|
255
|
+
* Adapters abstract the specifics of each auth provider while providing
|
|
256
|
+
* a consistent interface for VeloxTS.
|
|
257
|
+
*
|
|
258
|
+
* **Lifecycle:**
|
|
259
|
+
* 1. `initialize()` - Called once when plugin registers
|
|
260
|
+
* 2. `getRoutes()` - Returns routes to mount (if any)
|
|
261
|
+
* 3. `getSession()` - Called on each request to load session
|
|
262
|
+
* 4. `cleanup()` - Called on server shutdown
|
|
263
|
+
*
|
|
264
|
+
* @template TConfig - Adapter-specific configuration type
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* const myAdapter: AuthAdapter<MyAdapterConfig> = {
|
|
269
|
+
* name: 'my-adapter',
|
|
270
|
+
* version: '1.0.0',
|
|
271
|
+
*
|
|
272
|
+
* async initialize(fastify, config) {
|
|
273
|
+
* // Setup provider client
|
|
274
|
+
* },
|
|
275
|
+
*
|
|
276
|
+
* async getSession(request) {
|
|
277
|
+
* // Load session from provider
|
|
278
|
+
* const session = await provider.getSession(request);
|
|
279
|
+
* if (!session) return null;
|
|
280
|
+
*
|
|
281
|
+
* return {
|
|
282
|
+
* user: { id: session.user.id, email: session.user.email },
|
|
283
|
+
* session: { sessionId: session.id, userId: session.user.id, isActive: true },
|
|
284
|
+
* };
|
|
285
|
+
* },
|
|
286
|
+
*
|
|
287
|
+
* getRoutes() {
|
|
288
|
+
* return [{ path: '/api/auth/*', handler: providerHandler }];
|
|
289
|
+
* },
|
|
290
|
+
*
|
|
291
|
+
* async cleanup() {
|
|
292
|
+
* // Cleanup resources
|
|
293
|
+
* },
|
|
294
|
+
* };
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
export interface AuthAdapter<TConfig extends AuthAdapterConfig = AuthAdapterConfig> {
|
|
298
|
+
/**
|
|
299
|
+
* Unique adapter name
|
|
300
|
+
*
|
|
301
|
+
* Used for logging, error messages, and plugin identification.
|
|
302
|
+
*/
|
|
303
|
+
readonly name: string;
|
|
304
|
+
/**
|
|
305
|
+
* Adapter version
|
|
306
|
+
*
|
|
307
|
+
* Semantic versioning recommended.
|
|
308
|
+
*/
|
|
309
|
+
readonly version: string;
|
|
310
|
+
/**
|
|
311
|
+
* Initialize the adapter
|
|
312
|
+
*
|
|
313
|
+
* Called once when the plugin is registered with Fastify.
|
|
314
|
+
* Use this to set up provider clients, validate configuration,
|
|
315
|
+
* and prepare any resources needed for session loading.
|
|
316
|
+
*
|
|
317
|
+
* @param fastify - Fastify server instance
|
|
318
|
+
* @param config - Adapter configuration
|
|
319
|
+
* @throws {AuthAdapterError} If initialization fails
|
|
320
|
+
*/
|
|
321
|
+
initialize(fastify: FastifyInstance, config: TConfig): Promise<void> | void;
|
|
322
|
+
/**
|
|
323
|
+
* Load session from the current request
|
|
324
|
+
*
|
|
325
|
+
* Called on each request (unless excluded) to determine the
|
|
326
|
+
* current user's session. This is the primary method adapters
|
|
327
|
+
* must implement.
|
|
328
|
+
*
|
|
329
|
+
* **Implementation notes:**
|
|
330
|
+
* - Return `null` if no session exists (unauthenticated)
|
|
331
|
+
* - Validate session expiration before returning
|
|
332
|
+
* - Handle provider errors gracefully
|
|
333
|
+
*
|
|
334
|
+
* @param request - Fastify request object
|
|
335
|
+
* @returns Session result or null if not authenticated
|
|
336
|
+
* @throws {AuthAdapterError} If session loading fails
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```typescript
|
|
340
|
+
* async getSession(request) {
|
|
341
|
+
* try {
|
|
342
|
+
* const result = await provider.getSession({
|
|
343
|
+
* headers: fromNodeHeaders(request.headers),
|
|
344
|
+
* });
|
|
345
|
+
*
|
|
346
|
+
* if (!result) return null;
|
|
347
|
+
*
|
|
348
|
+
* return {
|
|
349
|
+
* user: {
|
|
350
|
+
* id: result.user.id,
|
|
351
|
+
* email: result.user.email,
|
|
352
|
+
* name: result.user.name,
|
|
353
|
+
* },
|
|
354
|
+
* session: {
|
|
355
|
+
* sessionId: result.session.id,
|
|
356
|
+
* userId: result.user.id,
|
|
357
|
+
* expiresAt: new Date(result.session.expiresAt).getTime(),
|
|
358
|
+
* isActive: true,
|
|
359
|
+
* },
|
|
360
|
+
* };
|
|
361
|
+
* } catch (error) {
|
|
362
|
+
* throw new AuthAdapterError(
|
|
363
|
+
* 'Failed to load session',
|
|
364
|
+
* 500,
|
|
365
|
+
* 'ADAPTER_SESSION_ERROR',
|
|
366
|
+
* error instanceof Error ? error : undefined
|
|
367
|
+
* );
|
|
368
|
+
* }
|
|
369
|
+
* }
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
getSession(request: FastifyRequest): Promise<AdapterSessionResult | null> | AdapterSessionResult | null;
|
|
373
|
+
/**
|
|
374
|
+
* Get routes to mount on the Fastify server
|
|
375
|
+
*
|
|
376
|
+
* Many auth providers need their own routes for:
|
|
377
|
+
* - Login/logout endpoints
|
|
378
|
+
* - OAuth callbacks
|
|
379
|
+
* - Magic link handlers
|
|
380
|
+
* - Session management
|
|
381
|
+
*
|
|
382
|
+
* Return an empty array if no routes are needed.
|
|
383
|
+
*
|
|
384
|
+
* @returns Array of route configurations
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```typescript
|
|
388
|
+
* getRoutes() {
|
|
389
|
+
* return [
|
|
390
|
+
* {
|
|
391
|
+
* path: '/api/auth/*',
|
|
392
|
+
* methods: ['GET', 'POST'],
|
|
393
|
+
* handler: async (request, reply) => {
|
|
394
|
+
* return provider.handler(request.raw, reply.raw);
|
|
395
|
+
* },
|
|
396
|
+
* description: 'BetterAuth handler',
|
|
397
|
+
* },
|
|
398
|
+
* ];
|
|
399
|
+
* }
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
getRoutes(): AdapterRoute[];
|
|
403
|
+
/**
|
|
404
|
+
* Handle OAuth or other callback requests (optional)
|
|
405
|
+
*
|
|
406
|
+
* Some providers require special handling for callbacks.
|
|
407
|
+
* Implement this if your provider needs custom callback logic
|
|
408
|
+
* beyond what getRoutes() provides.
|
|
409
|
+
*
|
|
410
|
+
* @param request - Fastify request object
|
|
411
|
+
* @param reply - Fastify reply object
|
|
412
|
+
* @param callbackType - Type of callback (e.g., 'oauth', 'magic-link')
|
|
413
|
+
* @returns Response data or void if reply was already sent
|
|
414
|
+
*/
|
|
415
|
+
handleCallback?(request: FastifyRequest, reply: FastifyReply, callbackType: string): Promise<unknown> | unknown;
|
|
416
|
+
/**
|
|
417
|
+
* Clean up adapter resources
|
|
418
|
+
*
|
|
419
|
+
* Called during server shutdown. Use this to close connections,
|
|
420
|
+
* clear caches, or perform any necessary cleanup.
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```typescript
|
|
424
|
+
* async cleanup() {
|
|
425
|
+
* await providerClient.close();
|
|
426
|
+
* console.log('Adapter resources cleaned up');
|
|
427
|
+
* }
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
cleanup?(): Promise<void> | void;
|
|
431
|
+
/**
|
|
432
|
+
* Validate session (optional)
|
|
433
|
+
*
|
|
434
|
+
* Override to add custom session validation logic beyond
|
|
435
|
+
* what getSession() provides.
|
|
436
|
+
*
|
|
437
|
+
* @param session - Session to validate
|
|
438
|
+
* @returns true if session is valid
|
|
439
|
+
*/
|
|
440
|
+
validateSession?(session: AdapterSessionResult): Promise<boolean> | boolean;
|
|
441
|
+
/**
|
|
442
|
+
* Refresh session (optional)
|
|
443
|
+
*
|
|
444
|
+
* Override to support session refresh/extension.
|
|
445
|
+
*
|
|
446
|
+
* @param request - Fastify request object
|
|
447
|
+
* @param session - Current session to refresh
|
|
448
|
+
* @returns Updated session or null if refresh failed
|
|
449
|
+
*/
|
|
450
|
+
refreshSession?(request: FastifyRequest, session: AdapterSessionResult): Promise<AdapterSessionResult | null> | AdapterSessionResult | null;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Defines an auth adapter with proper typing
|
|
454
|
+
*
|
|
455
|
+
* This is a helper function that provides better TypeScript inference
|
|
456
|
+
* and validates adapter implementation at definition time.
|
|
457
|
+
*
|
|
458
|
+
* @template TConfig - Adapter-specific configuration type
|
|
459
|
+
* @param adapter - Adapter implementation
|
|
460
|
+
* @returns The same adapter with proper types
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```typescript
|
|
464
|
+
* interface BetterAuthConfig extends AuthAdapterConfig {
|
|
465
|
+
* auth: BetterAuthInstance;
|
|
466
|
+
* }
|
|
467
|
+
*
|
|
468
|
+
* export const betterAuthAdapter = defineAuthAdapter<BetterAuthConfig>({
|
|
469
|
+
* name: 'better-auth',
|
|
470
|
+
* version: '1.0.0',
|
|
471
|
+
*
|
|
472
|
+
* async initialize(fastify, config) {
|
|
473
|
+
* // Store auth instance for later use
|
|
474
|
+
* },
|
|
475
|
+
*
|
|
476
|
+
* async getSession(request) {
|
|
477
|
+
* // Load session using BetterAuth
|
|
478
|
+
* },
|
|
479
|
+
*
|
|
480
|
+
* getRoutes() {
|
|
481
|
+
* return [{ path: '/api/auth/*', handler: ... }];
|
|
482
|
+
* },
|
|
483
|
+
* });
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
export declare function defineAuthAdapter<TConfig extends AuthAdapterConfig = AuthAdapterConfig>(adapter: AuthAdapter<TConfig>): AuthAdapter<TConfig>;
|
|
487
|
+
/**
|
|
488
|
+
* Plugin options for the auth adapter plugin
|
|
489
|
+
*/
|
|
490
|
+
export interface AuthAdapterPluginOptions<TConfig extends AuthAdapterConfig = AuthAdapterConfig> {
|
|
491
|
+
/**
|
|
492
|
+
* The auth adapter instance
|
|
493
|
+
*/
|
|
494
|
+
adapter: AuthAdapter<TConfig>;
|
|
495
|
+
/**
|
|
496
|
+
* Adapter-specific configuration
|
|
497
|
+
*/
|
|
498
|
+
config: TConfig;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Creates a VeloxTS plugin from an auth adapter
|
|
502
|
+
*
|
|
503
|
+
* This factory function wraps an auth adapter in a Fastify plugin
|
|
504
|
+
* that integrates with VeloxTS's plugin system. It handles:
|
|
505
|
+
*
|
|
506
|
+
* - Adapter initialization
|
|
507
|
+
* - Route mounting
|
|
508
|
+
* - Session loading via preHandler hook
|
|
509
|
+
* - Request decoration with auth context
|
|
510
|
+
* - Cleanup on shutdown
|
|
511
|
+
*
|
|
512
|
+
* @template TConfig - Adapter-specific configuration type
|
|
513
|
+
* @param options - Plugin options with adapter and config
|
|
514
|
+
* @returns VeloxTS plugin ready for registration
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* ```typescript
|
|
518
|
+
* import { createAuthAdapterPlugin } from '@veloxts/auth';
|
|
519
|
+
* import { betterAuthAdapter } from './adapters/better-auth';
|
|
520
|
+
*
|
|
521
|
+
* const authPlugin = createAuthAdapterPlugin({
|
|
522
|
+
* adapter: betterAuthAdapter,
|
|
523
|
+
* config: {
|
|
524
|
+
* name: 'better-auth',
|
|
525
|
+
* auth: betterAuth({
|
|
526
|
+
* database: db,
|
|
527
|
+
* trustedOrigins: ['http://localhost:3000'],
|
|
528
|
+
* }),
|
|
529
|
+
* debug: process.env.NODE_ENV === 'development',
|
|
530
|
+
* },
|
|
531
|
+
* });
|
|
532
|
+
*
|
|
533
|
+
* // Register with VeloxApp
|
|
534
|
+
* app.use(authPlugin);
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
export declare function createAuthAdapterPlugin<TConfig extends AuthAdapterConfig>(options: AuthAdapterPluginOptions<TConfig>): VeloxPlugin<AuthAdapterPluginOptions<TConfig>>;
|
|
538
|
+
/**
|
|
539
|
+
* Options for adapter-based auth middleware
|
|
540
|
+
*/
|
|
541
|
+
export interface AdapterMiddlewareOptions {
|
|
542
|
+
/**
|
|
543
|
+
* Allow unauthenticated requests
|
|
544
|
+
*
|
|
545
|
+
* When true, requests without valid sessions continue
|
|
546
|
+
* with ctx.user undefined. When false (default),
|
|
547
|
+
* unauthenticated requests throw a 401 error.
|
|
548
|
+
*
|
|
549
|
+
* @default false
|
|
550
|
+
*/
|
|
551
|
+
optional?: boolean;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Context extension for adapter-based authentication
|
|
555
|
+
*/
|
|
556
|
+
export interface AdapterAuthContext {
|
|
557
|
+
/** Authenticated user (undefined if optional and not authenticated) */
|
|
558
|
+
user?: User;
|
|
559
|
+
/** Whether the request is authenticated */
|
|
560
|
+
isAuthenticated: boolean;
|
|
561
|
+
/** Auth context from request */
|
|
562
|
+
auth: AuthContext;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Creates middleware for adapter-based authentication
|
|
566
|
+
*
|
|
567
|
+
* Use this middleware in procedures to require or optionally
|
|
568
|
+
* check authentication via the adapter.
|
|
569
|
+
*
|
|
570
|
+
* @returns Middleware factory functions
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```typescript
|
|
574
|
+
* const auth = createAdapterAuthMiddleware();
|
|
575
|
+
*
|
|
576
|
+
* // Require authentication
|
|
577
|
+
* const getProfile = procedure()
|
|
578
|
+
* .use(auth.requireAuth())
|
|
579
|
+
* .query(async ({ ctx }) => {
|
|
580
|
+
* return ctx.user; // User is guaranteed to exist
|
|
581
|
+
* });
|
|
582
|
+
*
|
|
583
|
+
* // Optional authentication
|
|
584
|
+
* const getPosts = procedure()
|
|
585
|
+
* .use(auth.optionalAuth())
|
|
586
|
+
* .query(async ({ ctx }) => {
|
|
587
|
+
* // ctx.user may be undefined
|
|
588
|
+
* return fetchPosts(ctx.user?.id);
|
|
589
|
+
* });
|
|
590
|
+
* ```
|
|
591
|
+
*/
|
|
592
|
+
export declare function createAdapterAuthMiddleware(): {
|
|
593
|
+
middleware: <TInput, TContext extends BaseContext, TOutput>(options?: AdapterMiddlewareOptions) => MiddlewareFunction<TInput, TContext, TContext & AdapterAuthContext, TOutput>;
|
|
594
|
+
requireAuth: <TInput, TContext extends BaseContext, TOutput>() => MiddlewareFunction<TInput, TContext, TContext & {
|
|
595
|
+
user: User;
|
|
596
|
+
isAuthenticated: true;
|
|
597
|
+
auth: AuthContext;
|
|
598
|
+
}, TOutput>;
|
|
599
|
+
optionalAuth: <TInput, TContext extends BaseContext, TOutput>() => MiddlewareFunction<TInput, TContext, TContext & {
|
|
600
|
+
user?: User;
|
|
601
|
+
isAuthenticated: boolean;
|
|
602
|
+
auth: AuthContext;
|
|
603
|
+
}, TOutput>;
|
|
604
|
+
};
|
|
605
|
+
/**
|
|
606
|
+
* Infers the configuration type from an adapter
|
|
607
|
+
*
|
|
608
|
+
* @template T - Adapter type
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```typescript
|
|
612
|
+
* const myAdapter = defineAuthAdapter<MyConfig>({ ... });
|
|
613
|
+
* type Config = InferAdapterConfig<typeof myAdapter>;
|
|
614
|
+
* // Config = MyConfig
|
|
615
|
+
* ```
|
|
616
|
+
*/
|
|
617
|
+
export type InferAdapterConfig<T> = T extends AuthAdapter<infer C> ? C : never;
|
|
618
|
+
/**
|
|
619
|
+
* Type guard to check if a value is a valid AuthAdapter
|
|
620
|
+
*
|
|
621
|
+
* @param value - Value to check
|
|
622
|
+
* @returns true if value is a valid AuthAdapter
|
|
623
|
+
*
|
|
624
|
+
* @example
|
|
625
|
+
* ```typescript
|
|
626
|
+
* if (isAuthAdapter(maybeAdapter)) {
|
|
627
|
+
* const plugin = createAuthAdapterPlugin({
|
|
628
|
+
* adapter: maybeAdapter,
|
|
629
|
+
* config: { name: 'test' },
|
|
630
|
+
* });
|
|
631
|
+
* }
|
|
632
|
+
* ```
|
|
633
|
+
*/
|
|
634
|
+
export declare function isAuthAdapter(value: unknown): value is AuthAdapter;
|
|
635
|
+
/**
|
|
636
|
+
* Abstract base class for auth adapters
|
|
637
|
+
*
|
|
638
|
+
* Provides common functionality that most adapters need,
|
|
639
|
+
* reducing boilerplate in adapter implementations.
|
|
640
|
+
*
|
|
641
|
+
* @template TConfig - Adapter-specific configuration type
|
|
642
|
+
*
|
|
643
|
+
* @example
|
|
644
|
+
* ```typescript
|
|
645
|
+
* class MyAdapter extends BaseAuthAdapter<MyConfig> {
|
|
646
|
+
* constructor() {
|
|
647
|
+
* super('my-adapter', '1.0.0');
|
|
648
|
+
* }
|
|
649
|
+
*
|
|
650
|
+
* async initialize(fastify: FastifyInstance, config: MyConfig) {
|
|
651
|
+
* // Custom initialization
|
|
652
|
+
* }
|
|
653
|
+
*
|
|
654
|
+
* async getSession(request: FastifyRequest) {
|
|
655
|
+
* // Custom session loading
|
|
656
|
+
* }
|
|
657
|
+
*
|
|
658
|
+
* getRoutes() {
|
|
659
|
+
* return []; // Or custom routes
|
|
660
|
+
* }
|
|
661
|
+
* }
|
|
662
|
+
* ```
|
|
663
|
+
*/
|
|
664
|
+
export declare abstract class BaseAuthAdapter<TConfig extends AuthAdapterConfig = AuthAdapterConfig> implements AuthAdapter<TConfig> {
|
|
665
|
+
readonly name: string;
|
|
666
|
+
readonly version: string;
|
|
667
|
+
protected fastify: FastifyInstance | null;
|
|
668
|
+
protected config: TConfig | null;
|
|
669
|
+
constructor(name: string, version: string);
|
|
670
|
+
/**
|
|
671
|
+
* Initialize the adapter
|
|
672
|
+
*
|
|
673
|
+
* Stores fastify and config references for subclass use.
|
|
674
|
+
* Override in subclass but call super.initialize() first.
|
|
675
|
+
*/
|
|
676
|
+
initialize(fastify: FastifyInstance, config: TConfig): Promise<void>;
|
|
677
|
+
/**
|
|
678
|
+
* Get session from request
|
|
679
|
+
*
|
|
680
|
+
* Must be implemented by subclass.
|
|
681
|
+
*/
|
|
682
|
+
abstract getSession(request: FastifyRequest): Promise<AdapterSessionResult | null> | AdapterSessionResult | null;
|
|
683
|
+
/**
|
|
684
|
+
* Get routes to mount
|
|
685
|
+
*
|
|
686
|
+
* Default implementation returns empty array.
|
|
687
|
+
* Override to provide adapter-specific routes.
|
|
688
|
+
*/
|
|
689
|
+
getRoutes(): AdapterRoute[];
|
|
690
|
+
/**
|
|
691
|
+
* Clean up adapter resources
|
|
692
|
+
*
|
|
693
|
+
* Default implementation does nothing.
|
|
694
|
+
* Override to clean up provider resources.
|
|
695
|
+
*/
|
|
696
|
+
cleanup(): Promise<void>;
|
|
697
|
+
/**
|
|
698
|
+
* Log a debug message (if debug is enabled)
|
|
699
|
+
*/
|
|
700
|
+
protected debug(message: string): void;
|
|
701
|
+
/**
|
|
702
|
+
* Log an info message
|
|
703
|
+
*/
|
|
704
|
+
protected info(message: string): void;
|
|
705
|
+
/**
|
|
706
|
+
* Log an error
|
|
707
|
+
*/
|
|
708
|
+
protected error(message: string, cause?: Error): void;
|
|
709
|
+
}
|
|
710
|
+
//# sourceMappingURL=adapter.d.ts.map
|