@lenan-soft/auth 1.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/README.md ADDED
@@ -0,0 +1,591 @@
1
+ # @lenan-soft/auth
2
+
3
+ A reusable JWT authentication library for NestJS and React/React Native applications.
4
+
5
+ ## Features
6
+
7
+ - ✅ JWT access + refresh token authentication
8
+ - ✅ NestJS dynamic module with guards, strategies, and decorators
9
+ - ✅ React hooks and context provider
10
+ - ✅ React Native support with Expo SecureStore adapter
11
+ - ✅ Interface-driven design — bring your own user entity
12
+ - ✅ TypeScript first with full type definitions
13
+ - ✅ Automatic token refresh on 401 responses
14
+ - ✅ Bcrypt password hashing
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @lenan-soft/auth
20
+ ```
21
+
22
+ ### Peer Dependencies
23
+
24
+ **For NestJS:**
25
+
26
+ ```bash
27
+ npm install @nestjs/common @nestjs/core @nestjs/jwt @nestjs/passport passport passport-jwt class-validator class-transformer reflect-metadata
28
+ ```
29
+
30
+ **For React:**
31
+
32
+ ```bash
33
+ npm install react
34
+ ```
35
+
36
+ **For React Native (Expo):**
37
+
38
+ ```bash
39
+ npx expo install expo-secure-store
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ### NestJS Backend
45
+
46
+ #### 1. Implement the User Service Interface
47
+
48
+ Create a service that implements `UserServiceInterface`:
49
+
50
+ ```typescript
51
+ // user.service.ts
52
+ import { Injectable } from "@nestjs/common";
53
+ import { InjectRepository } from "@nestjs/typeorm";
54
+ import { Repository } from "typeorm";
55
+ import { UserServiceInterface, AuthUser } from "@lenan-soft/auth/nestjs";
56
+ import { User } from "./user.entity";
57
+
58
+ @Injectable()
59
+ export class UserService implements UserServiceInterface<User> {
60
+ constructor(
61
+ @InjectRepository(User)
62
+ private readonly userRepository: Repository<User>,
63
+ ) {}
64
+
65
+ async findByEmail(email: string): Promise<User | null> {
66
+ return this.userRepository.findOne({ where: { email } });
67
+ }
68
+
69
+ async findById(id: string): Promise<User | null> {
70
+ return this.userRepository.findOne({ where: { id } });
71
+ }
72
+
73
+ async createUser(data: {
74
+ email: string;
75
+ passwordHash: string;
76
+ }): Promise<User> {
77
+ const user = this.userRepository.create({
78
+ email: data.email,
79
+ passwordHash: data.passwordHash,
80
+ hashedRefreshToken: null,
81
+ });
82
+ return this.userRepository.save(user);
83
+ }
84
+
85
+ async updateRefreshToken(
86
+ userId: string,
87
+ hashedToken: string | null,
88
+ ): Promise<void> {
89
+ await this.userRepository.update(userId, {
90
+ hashedRefreshToken: hashedToken,
91
+ });
92
+ }
93
+
94
+ async validateRefreshToken(
95
+ userId: string,
96
+ hashedToken: string,
97
+ ): Promise<boolean> {
98
+ const user = await this.findById(userId);
99
+ return user?.hashedRefreshToken === hashedToken;
100
+ }
101
+ }
102
+ ```
103
+
104
+ #### 2. Create Your User Entity
105
+
106
+ ```typescript
107
+ // user.entity.ts
108
+ import {
109
+ Entity,
110
+ PrimaryGeneratedColumn,
111
+ Column,
112
+ CreateDateColumn,
113
+ UpdateDateColumn,
114
+ } from "typeorm";
115
+ import { AuthUser } from "@lenan-soft/auth/nestjs";
116
+
117
+ @Entity("users")
118
+ export class User implements AuthUser {
119
+ @PrimaryGeneratedColumn("uuid")
120
+ id!: string;
121
+
122
+ @Column({ unique: true })
123
+ email!: string;
124
+
125
+ @Column()
126
+ passwordHash!: string;
127
+
128
+ @Column({ nullable: true })
129
+ hashedRefreshToken!: string | null;
130
+
131
+ // Add your own custom fields
132
+ @Column({ nullable: true })
133
+ firstName?: string;
134
+
135
+ @Column({ nullable: true })
136
+ lastName?: string;
137
+
138
+ @CreateDateColumn()
139
+ createdAt!: Date;
140
+
141
+ @UpdateDateColumn()
142
+ updatedAt!: Date;
143
+ }
144
+ ```
145
+
146
+ #### 3. Register the Auth Module
147
+
148
+ ```typescript
149
+ // app.module.ts
150
+ import { Module } from "@nestjs/common";
151
+ import { ConfigModule, ConfigService } from "@nestjs/config";
152
+ import { TypeOrmModule } from "@nestjs/typeorm";
153
+ import { LenanAuthModule } from "@lenan-soft/auth/nestjs";
154
+ import { UserService } from "./user/user.service";
155
+ import { User } from "./user/user.entity";
156
+
157
+ @Module({
158
+ imports: [
159
+ ConfigModule.forRoot({ isGlobal: true }),
160
+ TypeOrmModule.forRoot({
161
+ // your database config
162
+ }),
163
+ TypeOrmModule.forFeature([User]),
164
+
165
+ // Register auth module with async configuration
166
+ LenanAuthModule.registerAsync(
167
+ {
168
+ imports: [ConfigModule],
169
+ useFactory: (config: ConfigService) => ({
170
+ jwtSecret: config.getOrThrow("JWT_SECRET"),
171
+ jwtAccessExpiry: config.get("JWT_ACCESS_EXPIRY", "15m"),
172
+ jwtRefreshExpiry: config.get("JWT_REFRESH_EXPIRY", "7d"),
173
+ jwtRefreshSecret: config.get("JWT_REFRESH_SECRET"),
174
+ }),
175
+ inject: [ConfigService],
176
+ },
177
+ UserService, // Your UserService class
178
+ ),
179
+ ],
180
+ providers: [UserService],
181
+ })
182
+ export class AppModule {}
183
+ ```
184
+
185
+ #### 4. Protect Routes
186
+
187
+ ```typescript
188
+ // profile.controller.ts
189
+ import { Controller, Get, UseGuards } from "@nestjs/common";
190
+ import { JwtAuthGuard, CurrentUser, Public } from "@lenan-soft/auth/nestjs";
191
+
192
+ @Controller("profile")
193
+ @UseGuards(JwtAuthGuard) // Protect all routes in this controller
194
+ export class ProfileController {
195
+ @Get()
196
+ getProfile(@CurrentUser() user: User) {
197
+ return { user };
198
+ }
199
+
200
+ @Public() // This route is accessible without authentication
201
+ @Get("public")
202
+ getPublicInfo() {
203
+ return { message: "This is public" };
204
+ }
205
+ }
206
+ ```
207
+
208
+ #### 5. Apply Guard Globally (Optional)
209
+
210
+ ```typescript
211
+ // main.ts
212
+ import { NestFactory, Reflector } from "@nestjs/core";
213
+ import { JwtAuthGuard } from "@lenan-soft/auth/nestjs";
214
+ import { AppModule } from "./app.module";
215
+
216
+ async function bootstrap() {
217
+ const app = await NestFactory.create(AppModule);
218
+
219
+ // Apply JWT guard globally
220
+ const reflector = app.get(Reflector);
221
+ app.useGlobalGuards(new JwtAuthGuard(reflector));
222
+
223
+ await app.listen(3000);
224
+ }
225
+ bootstrap();
226
+ ```
227
+
228
+ ### React Frontend
229
+
230
+ ```tsx
231
+ // App.tsx
232
+ import { AuthProvider } from "@lenan-soft/auth/react";
233
+
234
+ function App() {
235
+ return (
236
+ <AuthProvider baseUrl="https://api.example.com">
237
+ <Router />
238
+ </AuthProvider>
239
+ );
240
+ }
241
+ ```
242
+
243
+ #### Using Auth Hooks
244
+
245
+ ```tsx
246
+ // LoginForm.tsx
247
+ import { useAuth } from "@lenan-soft/auth/react";
248
+
249
+ function LoginForm() {
250
+ const { login, isLoading, error } = useAuth();
251
+ const [email, setEmail] = useState("");
252
+ const [password, setPassword] = useState("");
253
+
254
+ const handleSubmit = async (e: React.FormEvent) => {
255
+ e.preventDefault();
256
+ try {
257
+ await login(email, password);
258
+ // Redirect to dashboard
259
+ } catch {
260
+ // Error is available via `error` state
261
+ }
262
+ };
263
+
264
+ return (
265
+ <form onSubmit={handleSubmit}>
266
+ {error && <div className="error">{error}</div>}
267
+ <input
268
+ type="email"
269
+ value={email}
270
+ onChange={(e) => setEmail(e.target.value)}
271
+ placeholder="Email"
272
+ />
273
+ <input
274
+ type="password"
275
+ value={password}
276
+ onChange={(e) => setPassword(e.target.value)}
277
+ placeholder="Password"
278
+ />
279
+ <button type="submit" disabled={isLoading}>
280
+ {isLoading ? "Logging in..." : "Login"}
281
+ </button>
282
+ </form>
283
+ );
284
+ }
285
+ ```
286
+
287
+ #### Protected Routes
288
+
289
+ ```tsx
290
+ // ProtectedRoute.tsx
291
+ import { Navigate } from "react-router-dom";
292
+ import { useAuth } from "@lenan-soft/auth/react";
293
+
294
+ function ProtectedRoute({ children }: { children: React.ReactNode }) {
295
+ const { isAuthenticated, isLoading } = useAuth();
296
+
297
+ if (isLoading) {
298
+ return <div>Loading...</div>;
299
+ }
300
+
301
+ if (!isAuthenticated) {
302
+ return <Navigate to="/login" />;
303
+ }
304
+
305
+ return <>{children}</>;
306
+ }
307
+ ```
308
+
309
+ #### Display User Info
310
+
311
+ ```tsx
312
+ // UserProfile.tsx
313
+ import { useUser } from "@lenan-soft/auth/react";
314
+
315
+ function UserProfile() {
316
+ const user = useUser();
317
+
318
+ if (!user) {
319
+ return null;
320
+ }
321
+
322
+ return (
323
+ <div>
324
+ <h2>Welcome, {user.email}!</h2>
325
+ </div>
326
+ );
327
+ }
328
+ ```
329
+
330
+ ### React Native with Expo
331
+
332
+ ```tsx
333
+ // App.tsx
334
+ import { AuthProvider } from "@lenan-soft/auth/react";
335
+ import { SecureStoreAdapter } from "@lenan-soft/auth/react/native";
336
+
337
+ const tokenStorage = new SecureStoreAdapter();
338
+
339
+ export default function App() {
340
+ return (
341
+ <AuthProvider baseUrl="https://api.example.com" tokenStorage={tokenStorage}>
342
+ <RootNavigator />
343
+ </AuthProvider>
344
+ );
345
+ }
346
+ ```
347
+
348
+ ## API Reference
349
+
350
+ ### NestJS Module
351
+
352
+ #### LenanAuthModule
353
+
354
+ ```typescript
355
+ // Sync registration
356
+ LenanAuthModule.register(options: AuthModuleOptions, userService: Type<UserServiceInterface>)
357
+
358
+ // Async registration
359
+ LenanAuthModule.registerAsync(options: AuthModuleAsyncOptions, userService: Type<UserServiceInterface>)
360
+ ```
361
+
362
+ #### AuthModuleOptions
363
+
364
+ | Option | Type | Default | Description |
365
+ | ------------------ | --------- | ------------------------ | ---------------------------------------------- |
366
+ | `jwtSecret` | `string` | required | Secret for signing JWT access tokens |
367
+ | `jwtAccessExpiry` | `string` | `'15m'` | Access token expiration |
368
+ | `jwtRefreshExpiry` | `string` | `'7d'` | Refresh token expiration |
369
+ | `jwtRefreshSecret` | `string` | `jwtSecret + '_refresh'` | Separate secret for refresh tokens |
370
+ | `useController` | `boolean` | `true` | Whether to register the default AuthController |
371
+
372
+ #### UserServiceInterface
373
+
374
+ ```typescript
375
+ interface UserServiceInterface<TUser extends AuthUser = AuthUser> {
376
+ findByEmail(email: string): Promise<TUser | null>;
377
+ findById(id: string): Promise<TUser | null>;
378
+ createUser(data: { email: string; passwordHash: string }): Promise<TUser>;
379
+ updateRefreshToken(userId: string, hashedToken: string | null): Promise<void>;
380
+ validateRefreshToken(userId: string, hashedToken: string): Promise<boolean>;
381
+ }
382
+ ```
383
+
384
+ #### Decorators
385
+
386
+ | Decorator | Description |
387
+ | -------------------- | --------------------------------------- |
388
+ | `@CurrentUser()` | Extract current user from request |
389
+ | `@CurrentUser('id')` | Extract specific user property |
390
+ | `@Public()` | Mark route as public (no auth required) |
391
+
392
+ #### Guards
393
+
394
+ | Guard | Description |
395
+ | ------------------- | --------------------------------------------- |
396
+ | `JwtAuthGuard` | Validates access tokens, respects `@Public()` |
397
+ | `RefreshTokenGuard` | Validates refresh tokens |
398
+
399
+ #### Services
400
+
401
+ | Service | Description |
402
+ | ----------------- | ---------------------------------------------------------- |
403
+ | `AuthService` | Main auth orchestration (login, register, refresh, logout) |
404
+ | `PasswordService` | Password hashing and comparison |
405
+ | `JwtTokenService` | Token generation and verification |
406
+
407
+ ### React Package
408
+
409
+ #### AuthProvider Props
410
+
411
+ | Prop | Type | Default | Description |
412
+ | ------------------- | ------------------------ | --------------------- | ----------------------------- |
413
+ | `baseUrl` | `string` | required | Base URL for auth API |
414
+ | `tokenStorage` | `TokenStorage` | `LocalStorageAdapter` | Token storage implementation |
415
+ | `endpoints` | `Partial<AuthEndpoints>` | defaults | Custom endpoint paths |
416
+ | `headers` | `Record<string, string>` | `{}` | Custom headers for requests |
417
+ | `autoRefresh` | `boolean` | `true` | Auto-refresh on mount |
418
+ | `onAuthStateChange` | `(state) => void` | - | Callback on auth state change |
419
+
420
+ #### useAuth Hook
421
+
422
+ Returns:
423
+
424
+ | Property | Type | Description |
425
+ | --------------------------------------------- | -------------------- | -------------------- |
426
+ | `user` | `TUser \| null` | Current user |
427
+ | `tokens` | `AuthTokens \| null` | Current tokens |
428
+ | `isLoading` | `boolean` | Loading state |
429
+ | `isAuthenticated` | `boolean` | Auth status |
430
+ | `error` | `string \| null` | Error message |
431
+ | `login(email, password)` | `Promise<void>` | Login function |
432
+ | `register(email, password, confirmPassword?)` | `Promise<void>` | Register function |
433
+ | `logout()` | `Promise<void>` | Logout function |
434
+ | `refreshToken()` | `Promise<void>` | Manual token refresh |
435
+ | `clearError()` | `() => void` | Clear error state |
436
+ | `client` | `AuthClient` | Direct client access |
437
+
438
+ #### useUser Hook
439
+
440
+ ```typescript
441
+ const user = useUser<MyUserType>();
442
+ // Returns TUser | null
443
+ ```
444
+
445
+ #### useIsAuthenticated Hook
446
+
447
+ ```typescript
448
+ const isAuthenticated = useIsAuthenticated();
449
+ // Returns boolean (true only when authenticated AND not loading)
450
+ ```
451
+
452
+ ### Built-in Auth Endpoints
453
+
454
+ The default `AuthController` provides:
455
+
456
+ | Method | Endpoint | Description |
457
+ | ------ | ---------------- | -------------------------------- |
458
+ | POST | `/auth/register` | Register new user |
459
+ | POST | `/auth/login` | Login with email/password |
460
+ | POST | `/auth/refresh` | Refresh tokens |
461
+ | POST | `/auth/logout` | Logout (requires auth) |
462
+ | GET | `/auth/me` | Get current user (requires auth) |
463
+
464
+ ## Token Storage Adapters
465
+
466
+ ### LocalStorageAdapter (Web)
467
+
468
+ Default for web browsers. Falls back to memory storage if localStorage is unavailable.
469
+
470
+ ```typescript
471
+ import { LocalStorageAdapter } from "@lenan-soft/auth/react";
472
+ const storage = new LocalStorageAdapter();
473
+ ```
474
+
475
+ ### MemoryStorageAdapter (Testing/SSR)
476
+
477
+ In-memory storage for testing or server-side rendering.
478
+
479
+ ```typescript
480
+ import { MemoryStorageAdapter } from "@lenan-soft/auth/react";
481
+ const storage = new MemoryStorageAdapter();
482
+ ```
483
+
484
+ ### SecureStoreAdapter (React Native)
485
+
486
+ Secure storage using Expo SecureStore.
487
+
488
+ ```typescript
489
+ import { SecureStoreAdapter } from "@lenan-soft/auth/react/native";
490
+ const storage = new SecureStoreAdapter();
491
+ ```
492
+
493
+ ### Custom Storage
494
+
495
+ Implement the `TokenStorage` interface:
496
+
497
+ ```typescript
498
+ import type { TokenStorage } from "@lenan-soft/auth/shared";
499
+
500
+ class MyCustomStorage implements TokenStorage {
501
+ async getItem(key: string): Promise<string | null> {
502
+ // Your implementation
503
+ }
504
+
505
+ async setItem(key: string, value: string): Promise<void> {
506
+ // Your implementation
507
+ }
508
+
509
+ async removeItem(key: string): Promise<void> {
510
+ // Your implementation
511
+ }
512
+ }
513
+ ```
514
+
515
+ ## Extending the User Entity
516
+
517
+ The library uses an interface-driven approach. Your user entity must implement `AuthUser`:
518
+
519
+ ```typescript
520
+ interface AuthUser {
521
+ id: string;
522
+ email: string;
523
+ passwordHash: string;
524
+ hashedRefreshToken: string | null;
525
+ }
526
+ ```
527
+
528
+ Add any additional fields you need:
529
+
530
+ ```typescript
531
+ // user.entity.ts
532
+ @Entity("users")
533
+ export class User implements AuthUser {
534
+ @PrimaryGeneratedColumn("uuid")
535
+ id!: string;
536
+
537
+ @Column({ unique: true })
538
+ email!: string;
539
+
540
+ @Column()
541
+ passwordHash!: string;
542
+
543
+ @Column({ nullable: true })
544
+ hashedRefreshToken!: string | null;
545
+
546
+ // Your custom fields
547
+ @Column({ nullable: true })
548
+ avatarUrl?: string;
549
+
550
+ @Column({ default: "user" })
551
+ role!: "user" | "admin";
552
+
553
+ @Column({ default: false })
554
+ emailVerified!: boolean;
555
+ }
556
+ ```
557
+
558
+ ## Security Considerations
559
+
560
+ 1. **JWT Secrets**: Use strong, unique secrets for production. Consider separate secrets for access and refresh tokens.
561
+
562
+ 2. **Token Expiry**: Keep access tokens short-lived (15m default). Refresh tokens can be longer (7d default).
563
+
564
+ 3. **HTTPS**: Always use HTTPS in production to protect tokens in transit.
565
+
566
+ 4. **Refresh Token Rotation**: The library rotates refresh tokens on each refresh, invalidating the old token.
567
+
568
+ 5. **Password Requirements**: Default validation requires 8+ characters with uppercase, lowercase, and numbers.
569
+
570
+ ## Development
571
+
572
+ ```bash
573
+ # Install dependencies
574
+ yarn install
575
+
576
+ # Build
577
+ yarn build
578
+
579
+ # Run tests
580
+ yarn test
581
+
582
+ # Run tests with coverage
583
+ yarn test:coverage
584
+
585
+ # Lint
586
+ yarn lint
587
+ ```
588
+
589
+ ## License
590
+
591
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_AUTH_ENDPOINTS: () => DEFAULT_AUTH_ENDPOINTS,
24
+ TOKEN_STORAGE_KEYS: () => TOKEN_STORAGE_KEYS
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/shared/types.ts
29
+ var DEFAULT_AUTH_ENDPOINTS = {
30
+ login: "/auth/login",
31
+ register: "/auth/register",
32
+ refresh: "/auth/refresh",
33
+ logout: "/auth/logout",
34
+ me: "/auth/me"
35
+ };
36
+ var TOKEN_STORAGE_KEYS = {
37
+ ACCESS_TOKEN: "lenan_access_token",
38
+ REFRESH_TOKEN: "lenan_refresh_token"
39
+ };
40
+ // Annotate the CommonJS export names for ESM import in node:
41
+ 0 && (module.exports = {
42
+ DEFAULT_AUTH_ENDPOINTS,
43
+ TOKEN_STORAGE_KEYS
44
+ });
45
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/shared/types.ts"],"sourcesContent":["// Re-export shared types from the main entry point\nexport * from \"./shared\";\n","/**\n * JWT payload structure\n */\nexport interface JwtPayload {\n /** User ID (subject) */\n sub: string;\n /** User email */\n email: string;\n /** Issued at timestamp */\n iat?: number;\n /** Expiration timestamp */\n exp?: number;\n}\n\n/**\n * Token response containing access and refresh tokens\n */\nexport interface AuthTokens {\n /** Short-lived access token */\n accessToken: string;\n /** Long-lived refresh token */\n refreshToken: string;\n}\n\n/**\n * Base user interface - minimal fields required by the auth system\n * Consumers should extend this with their own user properties\n */\nexport interface BaseUser {\n /** Unique user identifier */\n id: string;\n /** User email address */\n email: string;\n}\n\n/**\n * User with password hash - used internally for authentication\n */\nexport interface UserWithPassword extends BaseUser {\n /** Bcrypt hashed password */\n passwordHash: string;\n}\n\n/**\n * User with refresh token - used for token refresh operations\n */\nexport interface UserWithRefreshToken extends BaseUser {\n /** Hashed refresh token (nullable when logged out) */\n hashedRefreshToken: string | null;\n}\n\n/**\n * Full auth user interface combining all auth-related fields\n */\nexport interface AuthUser extends BaseUser {\n passwordHash: string;\n hashedRefreshToken: string | null;\n}\n\n/**\n * Login credentials\n */\nexport interface LoginCredentials {\n email: string;\n password: string;\n}\n\n/**\n * Registration data\n */\nexport interface RegisterData {\n email: string;\n password: string;\n}\n\n/**\n * Auth state for frontend applications\n */\nexport interface AuthState<TUser extends BaseUser = BaseUser> {\n /** Current authenticated user or null */\n user: TUser | null;\n /** Current tokens or null */\n tokens: AuthTokens | null;\n /** Whether auth state is being loaded/validated */\n isLoading: boolean;\n /** Whether user is authenticated */\n isAuthenticated: boolean;\n /** Auth error if any */\n error: string | null;\n}\n\n/**\n * Token storage interface for frontend applications\n * Implement this to use different storage backends (localStorage, SecureStore, etc.)\n */\nexport interface TokenStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * Auth client configuration for frontend HTTP client\n */\nexport interface AuthClientConfig {\n /** Base URL for auth API endpoints */\n baseUrl: string;\n /** Token storage implementation */\n tokenStorage: TokenStorage;\n /** Custom headers to include in requests */\n headers?: Record<string, string>;\n /** Access token storage key (default: 'lenan_access_token') */\n accessTokenKey?: string;\n /** Refresh token storage key (default: 'lenan_refresh_token') */\n refreshTokenKey?: string;\n}\n\n/**\n * Auth API endpoints configuration\n */\nexport interface AuthEndpoints {\n login: string;\n register: string;\n refresh: string;\n logout: string;\n me: string;\n}\n\n/**\n * Default auth endpoints\n */\nexport const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints = {\n login: \"/auth/login\",\n register: \"/auth/register\",\n refresh: \"/auth/refresh\",\n logout: \"/auth/logout\",\n me: \"/auth/me\",\n};\n\n/**\n * Default token storage keys\n */\nexport const TOKEN_STORAGE_KEYS = {\n ACCESS_TOKEN: \"lenan_access_token\",\n REFRESH_TOKEN: \"lenan_refresh_token\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmIO,IAAM,yBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,IAAI;AACN;AAKO,IAAM,qBAAqB;AAAA,EAChC,cAAc;AAAA,EACd,eAAe;AACjB;","names":[]}