@atzentis/auth-sdk 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +271 -64
- package/dist/index.js +508 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
|
+
interface HttpClientConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
retry?: Partial<RetryConfig>;
|
|
7
|
+
rateLimit?: Partial<RateLimitConfig>;
|
|
8
|
+
}
|
|
9
|
+
interface RequestConfig {
|
|
10
|
+
method: HttpMethod;
|
|
11
|
+
path: string;
|
|
12
|
+
body?: unknown;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
15
|
+
timeout?: number;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
skipAuth?: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface ApiResponse<T> {
|
|
20
|
+
data: T;
|
|
21
|
+
status: number;
|
|
22
|
+
headers: Headers;
|
|
23
|
+
}
|
|
24
|
+
type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
|
|
25
|
+
type ResponseInterceptor = (response: ApiResponse<unknown>) => ApiResponse<unknown> | Promise<ApiResponse<unknown>>;
|
|
26
|
+
type ErrorInterceptor = (error: unknown) => unknown | Promise<unknown>;
|
|
27
|
+
interface RetryConfig {
|
|
28
|
+
maxRetries: number;
|
|
29
|
+
baseDelay: number;
|
|
30
|
+
maxDelay: number;
|
|
31
|
+
factor: number;
|
|
32
|
+
jitter: boolean;
|
|
33
|
+
retryableStatuses: number[];
|
|
34
|
+
retryPost: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface RateLimitConfig {
|
|
37
|
+
autoRetry: boolean;
|
|
38
|
+
maxRetryAfter: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare class HttpClient {
|
|
42
|
+
private readonly config;
|
|
43
|
+
private readonly retryConfig;
|
|
44
|
+
private readonly rateLimitConfig;
|
|
45
|
+
private requestInterceptors;
|
|
46
|
+
private responseInterceptors;
|
|
47
|
+
private errorInterceptors;
|
|
48
|
+
constructor(config: HttpClientConfig);
|
|
49
|
+
get<T>(path: string, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
50
|
+
post<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
51
|
+
put<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
52
|
+
patch<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
53
|
+
delete<T>(path: string, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
54
|
+
getBaseUrl(): string;
|
|
55
|
+
addRequestInterceptor(fn: RequestInterceptor): void;
|
|
56
|
+
removeRequestInterceptor(fn: RequestInterceptor): void;
|
|
57
|
+
addResponseInterceptor(fn: ResponseInterceptor): void;
|
|
58
|
+
removeResponseInterceptor(fn: ResponseInterceptor): void;
|
|
59
|
+
addErrorInterceptor(fn: ErrorInterceptor): void;
|
|
60
|
+
removeErrorInterceptor(fn: ErrorInterceptor): void;
|
|
61
|
+
private request;
|
|
62
|
+
private executeFetch;
|
|
63
|
+
}
|
|
64
|
+
|
|
1
65
|
interface User {
|
|
2
66
|
id: string;
|
|
3
67
|
email: string;
|
|
@@ -143,6 +207,112 @@ interface LoginAlert {
|
|
|
143
207
|
riskScore: number;
|
|
144
208
|
}
|
|
145
209
|
|
|
210
|
+
interface SendOTPRequest {
|
|
211
|
+
phoneNumber: string;
|
|
212
|
+
captchaToken?: string;
|
|
213
|
+
}
|
|
214
|
+
interface SendOTPResponse {
|
|
215
|
+
success: boolean;
|
|
216
|
+
expiresIn: number;
|
|
217
|
+
maskedPhone: string;
|
|
218
|
+
}
|
|
219
|
+
interface VerifyOTPRequest {
|
|
220
|
+
phoneNumber: string;
|
|
221
|
+
code: string;
|
|
222
|
+
}
|
|
223
|
+
interface VerifyOTPResponse {
|
|
224
|
+
accessToken: string;
|
|
225
|
+
refreshToken: string;
|
|
226
|
+
expiresIn: number;
|
|
227
|
+
user: User;
|
|
228
|
+
newUser: boolean;
|
|
229
|
+
loginEvent?: LoginEvent;
|
|
230
|
+
}
|
|
231
|
+
interface PhoneSignInRequest {
|
|
232
|
+
phoneNumber: string;
|
|
233
|
+
password: string;
|
|
234
|
+
captchaToken?: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
declare class PhoneService {
|
|
238
|
+
private readonly httpClient;
|
|
239
|
+
private readonly storeTokensFn;
|
|
240
|
+
private readonly setLastLoginMethodFn;
|
|
241
|
+
constructor(httpClient: HttpClient, storeTokens: (accessToken: string, refreshToken: string) => Promise<void>, setLastLoginMethod: (method: string) => Promise<void>);
|
|
242
|
+
sendOTP(request: SendOTPRequest): Promise<SendOTPResponse>;
|
|
243
|
+
verify(request: VerifyOTPRequest): Promise<VerifyOTPResponse>;
|
|
244
|
+
signIn(request: PhoneSignInRequest): Promise<LoginResponse>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
interface Session {
|
|
248
|
+
id: string;
|
|
249
|
+
userId: string;
|
|
250
|
+
organizationId: string;
|
|
251
|
+
createdAt: string;
|
|
252
|
+
expiresAt: string;
|
|
253
|
+
ip: string;
|
|
254
|
+
userAgent: string;
|
|
255
|
+
device?: DeviceSummary;
|
|
256
|
+
lastActivityAt?: string;
|
|
257
|
+
}
|
|
258
|
+
interface DeviceSummary {
|
|
259
|
+
id: string;
|
|
260
|
+
name: string;
|
|
261
|
+
deviceType: "mobile" | "desktop" | "tablet";
|
|
262
|
+
isTrusted: boolean;
|
|
263
|
+
}
|
|
264
|
+
interface ListSessionsRequest {
|
|
265
|
+
limit?: number;
|
|
266
|
+
offset?: number;
|
|
267
|
+
}
|
|
268
|
+
interface ListSessionsResponse {
|
|
269
|
+
data: Session[];
|
|
270
|
+
total: number;
|
|
271
|
+
limit: number;
|
|
272
|
+
offset: number;
|
|
273
|
+
}
|
|
274
|
+
interface RevokeAllSessionsOptions {
|
|
275
|
+
exceptCurrent?: boolean;
|
|
276
|
+
}
|
|
277
|
+
interface RevokeAllSessionsResponse {
|
|
278
|
+
revokedCount: number;
|
|
279
|
+
}
|
|
280
|
+
interface DeviceSession {
|
|
281
|
+
sessionToken: string;
|
|
282
|
+
user: User;
|
|
283
|
+
isActive: boolean;
|
|
284
|
+
productId?: string;
|
|
285
|
+
createdAt: string;
|
|
286
|
+
}
|
|
287
|
+
interface SetActiveSessionRequest {
|
|
288
|
+
sessionToken: string;
|
|
289
|
+
}
|
|
290
|
+
interface SetActiveSessionResponse {
|
|
291
|
+
accessToken: string;
|
|
292
|
+
refreshToken: string;
|
|
293
|
+
expiresIn: number;
|
|
294
|
+
user: User;
|
|
295
|
+
}
|
|
296
|
+
declare function hasDevice(session: Session): session is Session & {
|
|
297
|
+
device: DeviceSummary;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
declare class SessionService {
|
|
301
|
+
private readonly httpClient;
|
|
302
|
+
private readonly storeTokens;
|
|
303
|
+
constructor(httpClient: HttpClient, storeTokens: (accessToken: string, refreshToken: string) => Promise<void>);
|
|
304
|
+
getCurrent(): Promise<Session>;
|
|
305
|
+
list(options?: ListSessionsRequest): Promise<ListSessionsResponse>;
|
|
306
|
+
revoke(sessionId: string): Promise<void>;
|
|
307
|
+
revokeAll(options?: RevokeAllSessionsOptions): Promise<RevokeAllSessionsResponse>;
|
|
308
|
+
listDeviceSessions(): Promise<DeviceSession[]>;
|
|
309
|
+
setActive(request: SetActiveSessionRequest): Promise<SetActiveSessionResponse>;
|
|
310
|
+
revokeDeviceSession(request: {
|
|
311
|
+
sessionToken: string;
|
|
312
|
+
}): Promise<void>;
|
|
313
|
+
getCurrentDevice(): Promise<DeviceSummary | null>;
|
|
314
|
+
}
|
|
315
|
+
|
|
146
316
|
interface ITokenStorage {
|
|
147
317
|
get(key: string): Promise<string | null>;
|
|
148
318
|
set(key: string, value: string): Promise<void>;
|
|
@@ -173,91 +343,109 @@ declare class AuthClient {
|
|
|
173
343
|
private readonly httpClient;
|
|
174
344
|
private readonly storage;
|
|
175
345
|
private readonly authService;
|
|
346
|
+
private readonly backgroundRefresh;
|
|
347
|
+
readonly phone: PhoneService;
|
|
348
|
+
readonly sessions: SessionService;
|
|
176
349
|
constructor(config: AuthConfig);
|
|
177
350
|
login(credentials: LoginCredentials): Promise<LoginResponse>;
|
|
178
351
|
signup(data: SignupData): Promise<SignupResponse>;
|
|
352
|
+
loginWithUsername(credentials: UsernameLoginCredentials): Promise<LoginResponse>;
|
|
353
|
+
isUsernameAvailable(username: string): Promise<boolean>;
|
|
354
|
+
getOAuthUrl(request: GetOAuthUrlRequest): string;
|
|
355
|
+
verifyOAuthCode(request: VerifyOAuthCodeRequest): Promise<LoginResponse>;
|
|
356
|
+
sendMagicLink(request: SendMagicLinkRequest): Promise<void>;
|
|
357
|
+
verifyMagicLink(request: VerifyMagicLinkRequest): Promise<LoginResponse>;
|
|
358
|
+
sendVerificationEmail(request: SendVerificationEmailRequest): Promise<void>;
|
|
359
|
+
verifyEmail(request: VerifyEmailRequest): Promise<VerifyEmailResponse>;
|
|
360
|
+
requestPasswordReset(request: RequestPasswordResetRequest): Promise<void>;
|
|
361
|
+
resetPassword(request: ResetPasswordRequest): Promise<ResetPasswordResponse>;
|
|
362
|
+
getAccessToken(): Promise<string | null>;
|
|
363
|
+
refreshToken(): Promise<RefreshTokenResponse>;
|
|
364
|
+
isAuthenticated(): Promise<boolean>;
|
|
365
|
+
getLastLoginMethod(): Promise<string | null>;
|
|
366
|
+
logout(): Promise<void>;
|
|
367
|
+
logoutAllDevices(): Promise<void>;
|
|
368
|
+
private startRefreshIfEnabled;
|
|
179
369
|
private handleLoginEvent;
|
|
180
370
|
}
|
|
181
371
|
|
|
182
|
-
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
183
|
-
interface HttpClientConfig {
|
|
184
|
-
baseUrl: string;
|
|
185
|
-
timeout?: number;
|
|
186
|
-
headers?: Record<string, string>;
|
|
187
|
-
retry?: Partial<RetryConfig>;
|
|
188
|
-
rateLimit?: Partial<RateLimitConfig>;
|
|
189
|
-
}
|
|
190
|
-
interface RequestConfig {
|
|
191
|
-
method: HttpMethod;
|
|
192
|
-
path: string;
|
|
193
|
-
body?: unknown;
|
|
194
|
-
headers?: Record<string, string>;
|
|
195
|
-
params?: Record<string, string | number | boolean | undefined>;
|
|
196
|
-
timeout?: number;
|
|
197
|
-
signal?: AbortSignal;
|
|
198
|
-
skipAuth?: boolean;
|
|
199
|
-
}
|
|
200
|
-
interface ApiResponse<T> {
|
|
201
|
-
data: T;
|
|
202
|
-
status: number;
|
|
203
|
-
headers: Headers;
|
|
204
|
-
}
|
|
205
|
-
type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
|
|
206
|
-
type ResponseInterceptor = (response: ApiResponse<unknown>) => ApiResponse<unknown> | Promise<ApiResponse<unknown>>;
|
|
207
|
-
type ErrorInterceptor = (error: unknown) => unknown | Promise<unknown>;
|
|
208
|
-
interface RetryConfig {
|
|
209
|
-
maxRetries: number;
|
|
210
|
-
baseDelay: number;
|
|
211
|
-
maxDelay: number;
|
|
212
|
-
factor: number;
|
|
213
|
-
jitter: boolean;
|
|
214
|
-
retryableStatuses: number[];
|
|
215
|
-
retryPost: boolean;
|
|
216
|
-
}
|
|
217
|
-
interface RateLimitConfig {
|
|
218
|
-
autoRetry: boolean;
|
|
219
|
-
maxRetryAfter: number;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
declare class HttpClient {
|
|
223
|
-
private readonly config;
|
|
224
|
-
private readonly retryConfig;
|
|
225
|
-
private readonly rateLimitConfig;
|
|
226
|
-
private requestInterceptors;
|
|
227
|
-
private responseInterceptors;
|
|
228
|
-
private errorInterceptors;
|
|
229
|
-
constructor(config: HttpClientConfig);
|
|
230
|
-
get<T>(path: string, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
231
|
-
post<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
232
|
-
put<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
233
|
-
patch<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
234
|
-
delete<T>(path: string, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
|
|
235
|
-
addRequestInterceptor(fn: RequestInterceptor): void;
|
|
236
|
-
removeRequestInterceptor(fn: RequestInterceptor): void;
|
|
237
|
-
addResponseInterceptor(fn: ResponseInterceptor): void;
|
|
238
|
-
removeResponseInterceptor(fn: ResponseInterceptor): void;
|
|
239
|
-
addErrorInterceptor(fn: ErrorInterceptor): void;
|
|
240
|
-
removeErrorInterceptor(fn: ErrorInterceptor): void;
|
|
241
|
-
private request;
|
|
242
|
-
private executeFetch;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
372
|
declare class AuthService {
|
|
246
373
|
private readonly httpClient;
|
|
247
374
|
private readonly storage;
|
|
248
375
|
private readonly tokenStorageKey;
|
|
249
376
|
private readonly refreshTokenStorageKey;
|
|
377
|
+
private readonly sessionStorageKey;
|
|
250
378
|
private readonly lastLoginMethodKey;
|
|
379
|
+
private refreshPromise;
|
|
251
380
|
constructor(httpClient: HttpClient, storage: ITokenStorage, options?: {
|
|
252
381
|
tokenStorageKey?: string;
|
|
253
382
|
refreshTokenStorageKey?: string;
|
|
383
|
+
sessionStorageKey?: string;
|
|
254
384
|
lastLoginMethodKey?: string;
|
|
255
385
|
});
|
|
256
386
|
login(credentials: LoginCredentials): Promise<LoginResponse>;
|
|
257
387
|
signup(data: SignupData): Promise<SignupResponse>;
|
|
388
|
+
loginWithUsername(credentials: UsernameLoginCredentials): Promise<LoginResponse>;
|
|
389
|
+
isUsernameAvailable(username: string): Promise<boolean>;
|
|
390
|
+
getOAuthUrl(request: {
|
|
391
|
+
provider: string;
|
|
392
|
+
redirectUri: string;
|
|
393
|
+
state: string;
|
|
394
|
+
scopes?: string[];
|
|
395
|
+
}): string;
|
|
396
|
+
verifyOAuthCode(request: {
|
|
397
|
+
provider: string;
|
|
398
|
+
code: string;
|
|
399
|
+
redirectUri: string;
|
|
400
|
+
}): Promise<LoginResponse>;
|
|
401
|
+
sendMagicLink(request: SendMagicLinkRequest): Promise<void>;
|
|
402
|
+
verifyMagicLink(request: VerifyMagicLinkRequest): Promise<LoginResponse>;
|
|
403
|
+
sendVerificationEmail(request: SendVerificationEmailRequest): Promise<void>;
|
|
404
|
+
verifyEmail(request: VerifyEmailRequest): Promise<VerifyEmailResponse>;
|
|
405
|
+
requestPasswordReset(request: RequestPasswordResetRequest): Promise<void>;
|
|
406
|
+
resetPassword(request: ResetPasswordRequest): Promise<ResetPasswordResponse>;
|
|
407
|
+
getAccessToken(): Promise<string | null>;
|
|
408
|
+
refreshToken(): Promise<RefreshTokenResponse>;
|
|
409
|
+
isAuthenticated(): Promise<boolean>;
|
|
410
|
+
getLastLoginMethod(): Promise<string | null>;
|
|
411
|
+
logout(): Promise<void>;
|
|
412
|
+
logoutAllDevices(): Promise<void>;
|
|
258
413
|
storeTokens(accessToken: string, refreshToken: string): Promise<void>;
|
|
259
414
|
setLastLoginMethod(method: string): Promise<void>;
|
|
415
|
+
clearTokens(): Promise<void>;
|
|
416
|
+
private executeRefresh;
|
|
260
417
|
}
|
|
418
|
+
declare function decodeJwtPayload(token: string): {
|
|
419
|
+
sub: string;
|
|
420
|
+
email: string;
|
|
421
|
+
name: string;
|
|
422
|
+
exp: number;
|
|
423
|
+
iat: number;
|
|
424
|
+
org?: string;
|
|
425
|
+
roles?: string[];
|
|
426
|
+
} | null;
|
|
427
|
+
|
|
428
|
+
declare class BackgroundRefresh {
|
|
429
|
+
private readonly refreshFn;
|
|
430
|
+
private readonly threshold;
|
|
431
|
+
private readonly callbacks;
|
|
432
|
+
private timerId;
|
|
433
|
+
private retryTimerId;
|
|
434
|
+
constructor(refreshFn: () => Promise<{
|
|
435
|
+
accessToken: string;
|
|
436
|
+
expiresIn: number;
|
|
437
|
+
}>, threshold: number, callbacks?: {
|
|
438
|
+
onTokenRefreshed?: (token: string) => void;
|
|
439
|
+
onSessionExpired?: () => void;
|
|
440
|
+
});
|
|
441
|
+
start(expiresIn: number): void;
|
|
442
|
+
stop(): void;
|
|
443
|
+
isRunning(): boolean;
|
|
444
|
+
private executeRefresh;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
declare function validateUsername(username: string): void;
|
|
448
|
+
declare function validatePhoneNumber(phoneNumber: string): void;
|
|
261
449
|
|
|
262
450
|
interface AuthInterceptorConfig {
|
|
263
451
|
tokenProvider?: () => string | null;
|
|
@@ -397,6 +585,25 @@ declare class BrowserDeviceSignalCollector implements IDeviceSignalCollector {
|
|
|
397
585
|
getFingerprint(): Promise<string>;
|
|
398
586
|
}
|
|
399
587
|
|
|
588
|
+
interface CookieStorageOptions {
|
|
589
|
+
secure?: boolean;
|
|
590
|
+
sameSite?: "strict" | "lax" | "none";
|
|
591
|
+
domain?: string;
|
|
592
|
+
path?: string;
|
|
593
|
+
maxAge?: number;
|
|
594
|
+
}
|
|
595
|
+
declare class CookieStorage implements ITokenStorage {
|
|
596
|
+
private readonly secure;
|
|
597
|
+
private readonly sameSite;
|
|
598
|
+
private readonly domain?;
|
|
599
|
+
private readonly path;
|
|
600
|
+
private readonly maxAge?;
|
|
601
|
+
constructor(options?: CookieStorageOptions);
|
|
602
|
+
get(key: string): Promise<string | null>;
|
|
603
|
+
set(key: string, value: string): Promise<void>;
|
|
604
|
+
remove(key: string): Promise<void>;
|
|
605
|
+
}
|
|
606
|
+
|
|
400
607
|
declare class LocalStorageAdapter implements ITokenStorage {
|
|
401
608
|
get(key: string): Promise<string | null>;
|
|
402
609
|
set(key: string, value: string): Promise<void>;
|
|
@@ -410,4 +617,4 @@ declare class MemoryStorage implements ITokenStorage {
|
|
|
410
617
|
remove(key: string): Promise<void>;
|
|
411
618
|
}
|
|
412
619
|
|
|
413
|
-
export { type ApiResponse, AuthClient, type AuthConfig, AuthError, AuthErrorCode, type AuthErrorOptions, type AuthInterceptorConfig, AuthService, AuthenticationError, BrowserDeviceSignalCollector, ConflictError, DEFAULT_LAST_LOGIN_METHOD_KEY, DEFAULT_REFRESH_TOKEN_STORAGE_KEY, DEFAULT_SESSION_STORAGE_KEY, DEFAULT_TOKEN_STORAGE_KEY, type DecodedToken, type DeviceSignals, type ErrorInterceptor, ForbiddenError, type GetOAuthUrlRequest, HttpClient, type HttpClientConfig, type HttpMethod, type IDeviceSignalCollector, type ITokenStorage, LocalStorageAdapter, type LoginAlert, type LoginCredentials, type LoginEvent, type LoginResponse, MemoryStorage, NetworkError, NotFoundError, type OAuthProvider, type Organization, type RateLimitConfig, RateLimitError, type RefreshTokenResponse, type RequestConfig, type RequestInterceptor, type RequestPasswordResetRequest, type ResetPasswordRequest, type ResetPasswordResponse, type ResponseInterceptor, type RetryConfig, type SendMagicLinkRequest, type SendVerificationEmailRequest, ServerError, type SignupData, type SignupResponse, TimeoutError, UnprocessableError, type User, type UsernameLoginCredentials, ValidationError, type VerifyEmailRequest, type VerifyEmailResponse, type VerifyMagicLinkRequest, type VerifyOAuthCodeRequest, type VerifyOAuthCodeResponse, createAuthInterceptor, createDeviceSignalInterceptor, createErrorFromResponse };
|
|
620
|
+
export { type ApiResponse, AuthClient, type AuthConfig, AuthError, AuthErrorCode, type AuthErrorOptions, type AuthInterceptorConfig, AuthService, AuthenticationError, BackgroundRefresh, BrowserDeviceSignalCollector, ConflictError, CookieStorage, type CookieStorageOptions, DEFAULT_LAST_LOGIN_METHOD_KEY, DEFAULT_REFRESH_TOKEN_STORAGE_KEY, DEFAULT_SESSION_STORAGE_KEY, DEFAULT_TOKEN_STORAGE_KEY, type DecodedToken, type DeviceSession, type DeviceSignals, type DeviceSummary, type ErrorInterceptor, ForbiddenError, type GetOAuthUrlRequest, HttpClient, type HttpClientConfig, type HttpMethod, type IDeviceSignalCollector, type ITokenStorage, type ListSessionsRequest, type ListSessionsResponse, LocalStorageAdapter, type LoginAlert, type LoginCredentials, type LoginEvent, type LoginResponse, MemoryStorage, NetworkError, NotFoundError, type OAuthProvider, type Organization, PhoneService, type PhoneSignInRequest, type RateLimitConfig, RateLimitError, type RefreshTokenResponse, type RequestConfig, type RequestInterceptor, type RequestPasswordResetRequest, type ResetPasswordRequest, type ResetPasswordResponse, type ResponseInterceptor, type RetryConfig, type RevokeAllSessionsOptions, type RevokeAllSessionsResponse, type SendMagicLinkRequest, type SendOTPRequest, type SendOTPResponse, type SendVerificationEmailRequest, ServerError, type Session, SessionService, type SetActiveSessionRequest, type SetActiveSessionResponse, type SignupData, type SignupResponse, TimeoutError, UnprocessableError, type User, type UsernameLoginCredentials, ValidationError, type VerifyEmailRequest, type VerifyEmailResponse, type VerifyMagicLinkRequest, type VerifyOAuthCodeRequest, type VerifyOAuthCodeResponse, type VerifyOTPRequest, type VerifyOTPResponse, createAuthInterceptor, createDeviceSignalInterceptor, createErrorFromResponse, decodeJwtPayload, hasDevice, validatePhoneNumber, validateUsername };
|
package/dist/index.js
CHANGED
|
@@ -297,6 +297,9 @@ var HttpClient = class {
|
|
|
297
297
|
async delete(path, config) {
|
|
298
298
|
return this.request({ ...config, method: "DELETE", path });
|
|
299
299
|
}
|
|
300
|
+
getBaseUrl() {
|
|
301
|
+
return this.config.baseUrl;
|
|
302
|
+
}
|
|
300
303
|
// --- Interceptor Management ---
|
|
301
304
|
addRequestInterceptor(fn) {
|
|
302
305
|
this.requestInterceptors.push(fn);
|
|
@@ -458,20 +461,66 @@ var DEFAULT_REFRESH_TOKEN_STORAGE_KEY = "atz_refresh_token";
|
|
|
458
461
|
var DEFAULT_SESSION_STORAGE_KEY = "atz_session";
|
|
459
462
|
var DEFAULT_LAST_LOGIN_METHOD_KEY = "atz_last_login_method";
|
|
460
463
|
|
|
464
|
+
// src/services/validators.ts
|
|
465
|
+
var USERNAME_MIN_LENGTH = 3;
|
|
466
|
+
var USERNAME_MAX_LENGTH = 20;
|
|
467
|
+
var USERNAME_PATTERN = /^[a-z0-9]+$/;
|
|
468
|
+
var PHONE_E164_PATTERN = /^\+\d{10,15}$/;
|
|
469
|
+
var SUPPORTED_COUNTRY_CODES = ["+30", "+49"];
|
|
470
|
+
function validateUsername(username) {
|
|
471
|
+
if (username.length < USERNAME_MIN_LENGTH) {
|
|
472
|
+
throw new ValidationError({
|
|
473
|
+
code: "USERNAME_INVALID",
|
|
474
|
+
message: `Username must be at least ${USERNAME_MIN_LENGTH} characters`
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
if (username.length > USERNAME_MAX_LENGTH) {
|
|
478
|
+
throw new ValidationError({
|
|
479
|
+
code: "USERNAME_INVALID",
|
|
480
|
+
message: `Username must be at most ${USERNAME_MAX_LENGTH} characters`
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
if (!USERNAME_PATTERN.test(username)) {
|
|
484
|
+
throw new ValidationError({
|
|
485
|
+
code: "USERNAME_INVALID",
|
|
486
|
+
message: "Username must contain only lowercase letters and numbers"
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function validatePhoneNumber(phoneNumber) {
|
|
491
|
+
if (!PHONE_E164_PATTERN.test(phoneNumber)) {
|
|
492
|
+
throw new ValidationError({
|
|
493
|
+
code: "INVALID_PHONE_NUMBER",
|
|
494
|
+
message: "Phone number must be in E.164 format (e.g. +301234567890)"
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
const hasValidCountryCode = SUPPORTED_COUNTRY_CODES.some((code) => phoneNumber.startsWith(code));
|
|
498
|
+
if (!hasValidCountryCode) {
|
|
499
|
+
throw new ValidationError({
|
|
500
|
+
code: "INVALID_PHONE_NUMBER",
|
|
501
|
+
message: `Phone number must start with one of: ${SUPPORTED_COUNTRY_CODES.join(", ")}`
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
461
506
|
// src/services/auth.ts
|
|
462
507
|
var AuthService = class {
|
|
463
508
|
httpClient;
|
|
464
509
|
storage;
|
|
465
510
|
tokenStorageKey;
|
|
466
511
|
refreshTokenStorageKey;
|
|
512
|
+
sessionStorageKey;
|
|
467
513
|
lastLoginMethodKey;
|
|
514
|
+
refreshPromise = null;
|
|
468
515
|
constructor(httpClient, storage, options) {
|
|
469
516
|
this.httpClient = httpClient;
|
|
470
517
|
this.storage = storage;
|
|
471
518
|
this.tokenStorageKey = options?.tokenStorageKey ?? DEFAULT_TOKEN_STORAGE_KEY;
|
|
472
519
|
this.refreshTokenStorageKey = options?.refreshTokenStorageKey ?? DEFAULT_REFRESH_TOKEN_STORAGE_KEY;
|
|
520
|
+
this.sessionStorageKey = options?.sessionStorageKey ?? DEFAULT_SESSION_STORAGE_KEY;
|
|
473
521
|
this.lastLoginMethodKey = options?.lastLoginMethodKey ?? DEFAULT_LAST_LOGIN_METHOD_KEY;
|
|
474
522
|
}
|
|
523
|
+
// --- Email/Password Login & Signup (T02-001) ---
|
|
475
524
|
async login(credentials) {
|
|
476
525
|
const { data } = await this.httpClient.post("/auth/login", credentials, {
|
|
477
526
|
skipAuth: true
|
|
@@ -488,6 +537,123 @@ var AuthService = class {
|
|
|
488
537
|
await this.setLastLoginMethod("email");
|
|
489
538
|
return response;
|
|
490
539
|
}
|
|
540
|
+
// --- Username Login (T02-002) ---
|
|
541
|
+
async loginWithUsername(credentials) {
|
|
542
|
+
validateUsername(credentials.username);
|
|
543
|
+
const { data } = await this.httpClient.post(
|
|
544
|
+
"/auth/login/username",
|
|
545
|
+
credentials,
|
|
546
|
+
{ skipAuth: true }
|
|
547
|
+
);
|
|
548
|
+
await this.storeTokens(data.accessToken, data.refreshToken);
|
|
549
|
+
await this.setLastLoginMethod("username");
|
|
550
|
+
return data;
|
|
551
|
+
}
|
|
552
|
+
async isUsernameAvailable(username) {
|
|
553
|
+
validateUsername(username);
|
|
554
|
+
const { data } = await this.httpClient.get("/auth/username/available", {
|
|
555
|
+
params: { username }
|
|
556
|
+
});
|
|
557
|
+
return data.available;
|
|
558
|
+
}
|
|
559
|
+
// --- OAuth (T02-004) ---
|
|
560
|
+
getOAuthUrl(request) {
|
|
561
|
+
const baseUrl = this.httpClient.getBaseUrl();
|
|
562
|
+
const params = new URLSearchParams({
|
|
563
|
+
provider: request.provider,
|
|
564
|
+
redirect_uri: request.redirectUri,
|
|
565
|
+
state: request.state
|
|
566
|
+
});
|
|
567
|
+
if (request.scopes?.length) {
|
|
568
|
+
params.set("scopes", request.scopes.join(","));
|
|
569
|
+
}
|
|
570
|
+
return `${baseUrl}/auth/oauth/authorize?${params.toString()}`;
|
|
571
|
+
}
|
|
572
|
+
async verifyOAuthCode(request) {
|
|
573
|
+
const { data } = await this.httpClient.post("/auth/oauth/verify", request, {
|
|
574
|
+
skipAuth: true
|
|
575
|
+
});
|
|
576
|
+
await this.storeTokens(data.accessToken, data.refreshToken);
|
|
577
|
+
await this.setLastLoginMethod("oauth");
|
|
578
|
+
return data;
|
|
579
|
+
}
|
|
580
|
+
// --- Magic Link (T02-005) ---
|
|
581
|
+
async sendMagicLink(request) {
|
|
582
|
+
await this.httpClient.post("/auth/magic-link/send", request, { skipAuth: true });
|
|
583
|
+
}
|
|
584
|
+
async verifyMagicLink(request) {
|
|
585
|
+
const { data } = await this.httpClient.post("/auth/magic-link/verify", request, {
|
|
586
|
+
skipAuth: true
|
|
587
|
+
});
|
|
588
|
+
await this.storeTokens(data.accessToken, data.refreshToken);
|
|
589
|
+
await this.setLastLoginMethod("magic_link");
|
|
590
|
+
return data;
|
|
591
|
+
}
|
|
592
|
+
// --- Email Verification (T02-006) ---
|
|
593
|
+
async sendVerificationEmail(request) {
|
|
594
|
+
await this.httpClient.post("/auth/email/send-verification", request);
|
|
595
|
+
}
|
|
596
|
+
async verifyEmail(request) {
|
|
597
|
+
const { data } = await this.httpClient.post(
|
|
598
|
+
"/auth/email/verify",
|
|
599
|
+
request,
|
|
600
|
+
{ skipAuth: true }
|
|
601
|
+
);
|
|
602
|
+
return data;
|
|
603
|
+
}
|
|
604
|
+
// --- Password Reset (T02-007) ---
|
|
605
|
+
async requestPasswordReset(request) {
|
|
606
|
+
await this.httpClient.post("/auth/password/reset-request", request, { skipAuth: true });
|
|
607
|
+
}
|
|
608
|
+
async resetPassword(request) {
|
|
609
|
+
const { data } = await this.httpClient.post(
|
|
610
|
+
"/auth/password/reset",
|
|
611
|
+
request,
|
|
612
|
+
{ skipAuth: true }
|
|
613
|
+
);
|
|
614
|
+
return data;
|
|
615
|
+
}
|
|
616
|
+
// --- Token Management (T02-009) ---
|
|
617
|
+
async getAccessToken() {
|
|
618
|
+
return this.storage.get(this.tokenStorageKey);
|
|
619
|
+
}
|
|
620
|
+
async refreshToken() {
|
|
621
|
+
if (this.refreshPromise) {
|
|
622
|
+
return this.refreshPromise;
|
|
623
|
+
}
|
|
624
|
+
this.refreshPromise = this.executeRefresh();
|
|
625
|
+
try {
|
|
626
|
+
return await this.refreshPromise;
|
|
627
|
+
} finally {
|
|
628
|
+
this.refreshPromise = null;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
async isAuthenticated() {
|
|
632
|
+
const token = await this.storage.get(this.tokenStorageKey);
|
|
633
|
+
if (!token) return false;
|
|
634
|
+
const decoded = decodeJwtPayload(token);
|
|
635
|
+
if (!decoded) return false;
|
|
636
|
+
return decoded.exp * 1e3 > Date.now();
|
|
637
|
+
}
|
|
638
|
+
async getLastLoginMethod() {
|
|
639
|
+
return this.storage.get(this.lastLoginMethodKey);
|
|
640
|
+
}
|
|
641
|
+
// --- Logout (T02-010) ---
|
|
642
|
+
async logout() {
|
|
643
|
+
try {
|
|
644
|
+
await this.httpClient.post("/auth/logout", {});
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
await this.clearTokens();
|
|
648
|
+
}
|
|
649
|
+
async logoutAllDevices() {
|
|
650
|
+
try {
|
|
651
|
+
await this.httpClient.post("/auth/logout/all", {});
|
|
652
|
+
} catch {
|
|
653
|
+
}
|
|
654
|
+
await this.clearTokens();
|
|
655
|
+
}
|
|
656
|
+
// --- Storage Helpers ---
|
|
491
657
|
async storeTokens(accessToken, refreshToken) {
|
|
492
658
|
await this.storage.set(this.tokenStorageKey, accessToken);
|
|
493
659
|
await this.storage.set(this.refreshTokenStorageKey, refreshToken);
|
|
@@ -495,7 +661,240 @@ var AuthService = class {
|
|
|
495
661
|
async setLastLoginMethod(method) {
|
|
496
662
|
await this.storage.set(this.lastLoginMethodKey, method);
|
|
497
663
|
}
|
|
664
|
+
async clearTokens() {
|
|
665
|
+
await this.storage.remove(this.tokenStorageKey);
|
|
666
|
+
await this.storage.remove(this.refreshTokenStorageKey);
|
|
667
|
+
await this.storage.remove(this.sessionStorageKey);
|
|
668
|
+
await this.storage.remove(this.lastLoginMethodKey);
|
|
669
|
+
}
|
|
670
|
+
// --- Private ---
|
|
671
|
+
async executeRefresh() {
|
|
672
|
+
const currentRefreshToken = await this.storage.get(this.refreshTokenStorageKey);
|
|
673
|
+
const { data } = await this.httpClient.post("/auth/token/refresh", {
|
|
674
|
+
refreshToken: currentRefreshToken
|
|
675
|
+
});
|
|
676
|
+
await this.storeTokens(data.accessToken, data.refreshToken);
|
|
677
|
+
return data;
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
function decodeJwtPayload(token) {
|
|
681
|
+
try {
|
|
682
|
+
const parts = token.split(".");
|
|
683
|
+
if (parts.length !== 3) return null;
|
|
684
|
+
const payload = parts[1];
|
|
685
|
+
const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
686
|
+
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
687
|
+
const decoded = atob(padded);
|
|
688
|
+
return JSON.parse(decoded);
|
|
689
|
+
} catch {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// src/services/refresh.ts
|
|
695
|
+
var BackgroundRefresh = class {
|
|
696
|
+
constructor(refreshFn, threshold, callbacks = {}) {
|
|
697
|
+
this.refreshFn = refreshFn;
|
|
698
|
+
this.threshold = threshold;
|
|
699
|
+
this.callbacks = callbacks;
|
|
700
|
+
}
|
|
701
|
+
timerId = null;
|
|
702
|
+
retryTimerId = null;
|
|
703
|
+
start(expiresIn) {
|
|
704
|
+
if (typeof setTimeout === "undefined") return;
|
|
705
|
+
this.stop();
|
|
706
|
+
const delayMs = (expiresIn - this.threshold) * 1e3;
|
|
707
|
+
if (delayMs <= 0) {
|
|
708
|
+
this.executeRefresh();
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
this.timerId = setTimeout(() => {
|
|
712
|
+
this.executeRefresh();
|
|
713
|
+
}, delayMs);
|
|
714
|
+
}
|
|
715
|
+
stop() {
|
|
716
|
+
if (this.timerId !== null) {
|
|
717
|
+
clearTimeout(this.timerId);
|
|
718
|
+
this.timerId = null;
|
|
719
|
+
}
|
|
720
|
+
if (this.retryTimerId !== null) {
|
|
721
|
+
clearTimeout(this.retryTimerId);
|
|
722
|
+
this.retryTimerId = null;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
isRunning() {
|
|
726
|
+
return this.timerId !== null;
|
|
727
|
+
}
|
|
728
|
+
async executeRefresh() {
|
|
729
|
+
try {
|
|
730
|
+
const result = await this.refreshFn();
|
|
731
|
+
this.callbacks.onTokenRefreshed?.(result.accessToken);
|
|
732
|
+
this.start(result.expiresIn);
|
|
733
|
+
} catch {
|
|
734
|
+
this.timerId = null;
|
|
735
|
+
this.retryTimerId = setTimeout(async () => {
|
|
736
|
+
this.retryTimerId = null;
|
|
737
|
+
try {
|
|
738
|
+
const result = await this.refreshFn();
|
|
739
|
+
this.callbacks.onTokenRefreshed?.(result.accessToken);
|
|
740
|
+
this.start(result.expiresIn);
|
|
741
|
+
} catch {
|
|
742
|
+
this.callbacks.onSessionExpired?.();
|
|
743
|
+
}
|
|
744
|
+
}, 5e3);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
// src/services/phone.ts
|
|
750
|
+
var PhoneService = class {
|
|
751
|
+
httpClient;
|
|
752
|
+
storeTokensFn;
|
|
753
|
+
setLastLoginMethodFn;
|
|
754
|
+
constructor(httpClient, storeTokens, setLastLoginMethod) {
|
|
755
|
+
this.httpClient = httpClient;
|
|
756
|
+
this.storeTokensFn = storeTokens;
|
|
757
|
+
this.setLastLoginMethodFn = setLastLoginMethod;
|
|
758
|
+
}
|
|
759
|
+
async sendOTP(request) {
|
|
760
|
+
validatePhoneNumber(request.phoneNumber);
|
|
761
|
+
const { data } = await this.httpClient.post("/auth/phone/send-otp", request, {
|
|
762
|
+
skipAuth: true
|
|
763
|
+
});
|
|
764
|
+
return data;
|
|
765
|
+
}
|
|
766
|
+
async verify(request) {
|
|
767
|
+
validatePhoneNumber(request.phoneNumber);
|
|
768
|
+
const { data } = await this.httpClient.post("/auth/phone/verify", request, {
|
|
769
|
+
skipAuth: true
|
|
770
|
+
});
|
|
771
|
+
await this.storeTokensFn(data.accessToken, data.refreshToken);
|
|
772
|
+
await this.setLastLoginMethodFn("phone");
|
|
773
|
+
return data;
|
|
774
|
+
}
|
|
775
|
+
async signIn(request) {
|
|
776
|
+
validatePhoneNumber(request.phoneNumber);
|
|
777
|
+
const { data } = await this.httpClient.post("/auth/phone/sign-in", request, {
|
|
778
|
+
skipAuth: true
|
|
779
|
+
});
|
|
780
|
+
await this.storeTokensFn(data.accessToken, data.refreshToken);
|
|
781
|
+
await this.setLastLoginMethodFn("phone");
|
|
782
|
+
return data;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
// src/services/session.ts
|
|
787
|
+
var SessionService = class {
|
|
788
|
+
httpClient;
|
|
789
|
+
storeTokens;
|
|
790
|
+
constructor(httpClient, storeTokens) {
|
|
791
|
+
this.httpClient = httpClient;
|
|
792
|
+
this.storeTokens = storeTokens;
|
|
793
|
+
}
|
|
794
|
+
// --- Session CRUD (T03-001) ---
|
|
795
|
+
async getCurrent() {
|
|
796
|
+
const { data } = await this.httpClient.get("/auth/sessions/current");
|
|
797
|
+
return data;
|
|
798
|
+
}
|
|
799
|
+
async list(options) {
|
|
800
|
+
const params = {};
|
|
801
|
+
if (options?.limit !== void 0) params.limit = options.limit;
|
|
802
|
+
if (options?.offset !== void 0) params.offset = options.offset;
|
|
803
|
+
const { data } = await this.httpClient.get("/auth/sessions", { params });
|
|
804
|
+
return data;
|
|
805
|
+
}
|
|
806
|
+
async revoke(sessionId) {
|
|
807
|
+
await this.httpClient.delete(`/auth/sessions/${sessionId}`);
|
|
808
|
+
}
|
|
809
|
+
// --- Revoke All (T03-002) ---
|
|
810
|
+
async revokeAll(options) {
|
|
811
|
+
const { data } = await this.httpClient.post(
|
|
812
|
+
"/auth/sessions/revoke-all",
|
|
813
|
+
{ exceptCurrent: options?.exceptCurrent ?? true }
|
|
814
|
+
);
|
|
815
|
+
return data;
|
|
816
|
+
}
|
|
817
|
+
// --- Multi-Session (T03-003, T03-004) ---
|
|
818
|
+
async listDeviceSessions() {
|
|
819
|
+
const { data } = await this.httpClient.get("/auth/sessions/device");
|
|
820
|
+
return data;
|
|
821
|
+
}
|
|
822
|
+
async setActive(request) {
|
|
823
|
+
const { data } = await this.httpClient.post(
|
|
824
|
+
"/auth/sessions/set-active",
|
|
825
|
+
request
|
|
826
|
+
);
|
|
827
|
+
await this.storeTokens(data.accessToken, data.refreshToken);
|
|
828
|
+
return data;
|
|
829
|
+
}
|
|
830
|
+
async revokeDeviceSession(request) {
|
|
831
|
+
await this.httpClient.delete(`/auth/sessions/device/${request.sessionToken}`);
|
|
832
|
+
}
|
|
833
|
+
// --- Device Summary (T03-007) ---
|
|
834
|
+
async getCurrentDevice() {
|
|
835
|
+
const session = await this.getCurrent();
|
|
836
|
+
return session.device ?? null;
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
// src/storage/cookie-storage.ts
|
|
841
|
+
var CookieStorage = class {
|
|
842
|
+
secure;
|
|
843
|
+
sameSite;
|
|
844
|
+
domain;
|
|
845
|
+
path;
|
|
846
|
+
maxAge;
|
|
847
|
+
constructor(options) {
|
|
848
|
+
this.secure = options?.secure ?? true;
|
|
849
|
+
this.sameSite = options?.sameSite ?? "lax";
|
|
850
|
+
this.domain = options?.domain;
|
|
851
|
+
this.path = options?.path ?? "/";
|
|
852
|
+
this.maxAge = options?.maxAge;
|
|
853
|
+
}
|
|
854
|
+
async get(key) {
|
|
855
|
+
if (typeof document === "undefined") return null;
|
|
856
|
+
const cookies = document.cookie.split(";");
|
|
857
|
+
for (const cookie of cookies) {
|
|
858
|
+
const [cookieKey, ...cookieValueParts] = cookie.trim().split("=");
|
|
859
|
+
if (cookieKey === key) {
|
|
860
|
+
const value = cookieValueParts.join("=");
|
|
861
|
+
try {
|
|
862
|
+
return decodeURIComponent(value);
|
|
863
|
+
} catch {
|
|
864
|
+
return value;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
async set(key, value) {
|
|
871
|
+
if (typeof document === "undefined") return;
|
|
872
|
+
let cookie = `${key}=${encodeURIComponent(value)}`;
|
|
873
|
+
cookie += `; path=${this.path}`;
|
|
874
|
+
cookie += `; SameSite=${capitalize(this.sameSite)}`;
|
|
875
|
+
if (this.secure) {
|
|
876
|
+
cookie += "; Secure";
|
|
877
|
+
}
|
|
878
|
+
if (this.domain) {
|
|
879
|
+
cookie += `; Domain=${this.domain}`;
|
|
880
|
+
}
|
|
881
|
+
if (this.maxAge !== void 0) {
|
|
882
|
+
cookie += `; Max-Age=${this.maxAge}`;
|
|
883
|
+
}
|
|
884
|
+
document.cookie = cookie;
|
|
885
|
+
}
|
|
886
|
+
async remove(key) {
|
|
887
|
+
if (typeof document === "undefined") return;
|
|
888
|
+
let cookie = `${key}=; path=${this.path}; Max-Age=0`;
|
|
889
|
+
if (this.domain) {
|
|
890
|
+
cookie += `; Domain=${this.domain}`;
|
|
891
|
+
}
|
|
892
|
+
document.cookie = cookie;
|
|
893
|
+
}
|
|
498
894
|
};
|
|
895
|
+
function capitalize(str) {
|
|
896
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
897
|
+
}
|
|
499
898
|
|
|
500
899
|
// src/storage/local-storage-adapter.ts
|
|
501
900
|
var LocalStorageAdapter = class {
|
|
@@ -534,6 +933,9 @@ var AuthClient = class {
|
|
|
534
933
|
httpClient;
|
|
535
934
|
storage;
|
|
536
935
|
authService;
|
|
936
|
+
backgroundRefresh;
|
|
937
|
+
phone;
|
|
938
|
+
sessions;
|
|
537
939
|
constructor(config) {
|
|
538
940
|
this.config = config;
|
|
539
941
|
this.storage = config.storage ?? new MemoryStorage();
|
|
@@ -546,9 +948,7 @@ var AuthClient = class {
|
|
|
546
948
|
const storage = this.storage;
|
|
547
949
|
this.httpClient.addRequestInterceptor(
|
|
548
950
|
createAuthInterceptor({
|
|
549
|
-
tokenProvider: () =>
|
|
550
|
-
return null;
|
|
551
|
-
},
|
|
951
|
+
tokenProvider: () => null,
|
|
552
952
|
apiKey: config.apiKey
|
|
553
953
|
})
|
|
554
954
|
);
|
|
@@ -574,14 +974,112 @@ var AuthClient = class {
|
|
|
574
974
|
tokenStorageKey,
|
|
575
975
|
refreshTokenStorageKey
|
|
576
976
|
});
|
|
977
|
+
this.phone = new PhoneService(
|
|
978
|
+
this.httpClient,
|
|
979
|
+
(accessToken, refreshToken) => this.authService.storeTokens(accessToken, refreshToken),
|
|
980
|
+
(method) => this.authService.setLastLoginMethod(method)
|
|
981
|
+
);
|
|
982
|
+
this.sessions = new SessionService(
|
|
983
|
+
this.httpClient,
|
|
984
|
+
(accessToken, refreshToken) => this.authService.storeTokens(accessToken, refreshToken)
|
|
985
|
+
);
|
|
986
|
+
this.backgroundRefresh = new BackgroundRefresh(
|
|
987
|
+
async () => {
|
|
988
|
+
const result = await this.authService.refreshToken();
|
|
989
|
+
return { accessToken: result.accessToken, expiresIn: result.expiresIn };
|
|
990
|
+
},
|
|
991
|
+
config.refreshThreshold ?? 300,
|
|
992
|
+
{
|
|
993
|
+
onTokenRefreshed: config.onTokenRefreshed,
|
|
994
|
+
onSessionExpired: config.onSessionExpired
|
|
995
|
+
}
|
|
996
|
+
);
|
|
577
997
|
}
|
|
998
|
+
// --- Email/Password (T02-001) ---
|
|
578
999
|
async login(credentials) {
|
|
579
1000
|
const response = await this.authService.login(credentials);
|
|
580
1001
|
this.handleLoginEvent(response);
|
|
1002
|
+
this.startRefreshIfEnabled(response.expiresIn);
|
|
581
1003
|
return response;
|
|
582
1004
|
}
|
|
583
1005
|
async signup(data) {
|
|
584
|
-
|
|
1006
|
+
const response = await this.authService.signup(data);
|
|
1007
|
+
this.startRefreshIfEnabled(response.expiresIn);
|
|
1008
|
+
return response;
|
|
1009
|
+
}
|
|
1010
|
+
// --- Username (T02-002) ---
|
|
1011
|
+
async loginWithUsername(credentials) {
|
|
1012
|
+
const response = await this.authService.loginWithUsername(credentials);
|
|
1013
|
+
this.handleLoginEvent(response);
|
|
1014
|
+
this.startRefreshIfEnabled(response.expiresIn);
|
|
1015
|
+
return response;
|
|
1016
|
+
}
|
|
1017
|
+
async isUsernameAvailable(username) {
|
|
1018
|
+
return this.authService.isUsernameAvailable(username);
|
|
1019
|
+
}
|
|
1020
|
+
// --- OAuth (T02-004) ---
|
|
1021
|
+
getOAuthUrl(request) {
|
|
1022
|
+
return this.authService.getOAuthUrl(request);
|
|
1023
|
+
}
|
|
1024
|
+
async verifyOAuthCode(request) {
|
|
1025
|
+
const response = await this.authService.verifyOAuthCode(request);
|
|
1026
|
+
this.handleLoginEvent(response);
|
|
1027
|
+
this.startRefreshIfEnabled(response.expiresIn);
|
|
1028
|
+
return response;
|
|
1029
|
+
}
|
|
1030
|
+
// --- Magic Link (T02-005) ---
|
|
1031
|
+
async sendMagicLink(request) {
|
|
1032
|
+
return this.authService.sendMagicLink(request);
|
|
1033
|
+
}
|
|
1034
|
+
async verifyMagicLink(request) {
|
|
1035
|
+
const response = await this.authService.verifyMagicLink(request);
|
|
1036
|
+
this.handleLoginEvent(response);
|
|
1037
|
+
this.startRefreshIfEnabled(response.expiresIn);
|
|
1038
|
+
return response;
|
|
1039
|
+
}
|
|
1040
|
+
// --- Email Verification (T02-006) ---
|
|
1041
|
+
async sendVerificationEmail(request) {
|
|
1042
|
+
return this.authService.sendVerificationEmail(request);
|
|
1043
|
+
}
|
|
1044
|
+
async verifyEmail(request) {
|
|
1045
|
+
return this.authService.verifyEmail(request);
|
|
1046
|
+
}
|
|
1047
|
+
// --- Password Reset (T02-007) ---
|
|
1048
|
+
async requestPasswordReset(request) {
|
|
1049
|
+
return this.authService.requestPasswordReset(request);
|
|
1050
|
+
}
|
|
1051
|
+
async resetPassword(request) {
|
|
1052
|
+
return this.authService.resetPassword(request);
|
|
1053
|
+
}
|
|
1054
|
+
// --- Token Management (T02-009) ---
|
|
1055
|
+
async getAccessToken() {
|
|
1056
|
+
return this.authService.getAccessToken();
|
|
1057
|
+
}
|
|
1058
|
+
async refreshToken() {
|
|
1059
|
+
return this.authService.refreshToken();
|
|
1060
|
+
}
|
|
1061
|
+
async isAuthenticated() {
|
|
1062
|
+
return this.authService.isAuthenticated();
|
|
1063
|
+
}
|
|
1064
|
+
async getLastLoginMethod() {
|
|
1065
|
+
return this.authService.getLastLoginMethod();
|
|
1066
|
+
}
|
|
1067
|
+
// --- Logout (T02-010) ---
|
|
1068
|
+
async logout() {
|
|
1069
|
+
this.backgroundRefresh.stop();
|
|
1070
|
+
await this.authService.logout();
|
|
1071
|
+
this.config.onSessionExpired?.();
|
|
1072
|
+
}
|
|
1073
|
+
async logoutAllDevices() {
|
|
1074
|
+
this.backgroundRefresh.stop();
|
|
1075
|
+
await this.authService.logoutAllDevices();
|
|
1076
|
+
this.config.onSessionExpired?.();
|
|
1077
|
+
}
|
|
1078
|
+
// --- Private ---
|
|
1079
|
+
startRefreshIfEnabled(expiresIn) {
|
|
1080
|
+
if (this.config.autoRefreshToken !== false) {
|
|
1081
|
+
this.backgroundRefresh.start(expiresIn);
|
|
1082
|
+
}
|
|
585
1083
|
}
|
|
586
1084
|
handleLoginEvent(response) {
|
|
587
1085
|
if (response.loginEvent && response.loginEvent.riskScore >= RISK_ALERT_THRESHOLD && this.config.onNewDeviceAlert) {
|
|
@@ -597,6 +1095,11 @@ var AuthClient = class {
|
|
|
597
1095
|
}
|
|
598
1096
|
};
|
|
599
1097
|
|
|
1098
|
+
// src/types/session.ts
|
|
1099
|
+
function hasDevice(session) {
|
|
1100
|
+
return session.device !== void 0;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
600
1103
|
// src/errors/codes.ts
|
|
601
1104
|
var AuthErrorCode = /* @__PURE__ */ ((AuthErrorCode2) => {
|
|
602
1105
|
AuthErrorCode2["InvalidCredentials"] = "INVALID_CREDENTIALS";
|
|
@@ -639,6 +1142,6 @@ var AuthErrorCode = /* @__PURE__ */ ((AuthErrorCode2) => {
|
|
|
639
1142
|
return AuthErrorCode2;
|
|
640
1143
|
})(AuthErrorCode || {});
|
|
641
1144
|
|
|
642
|
-
export { AuthClient, AuthError, AuthErrorCode, AuthService, AuthenticationError, BrowserDeviceSignalCollector, ConflictError, DEFAULT_LAST_LOGIN_METHOD_KEY, DEFAULT_REFRESH_TOKEN_STORAGE_KEY, DEFAULT_SESSION_STORAGE_KEY, DEFAULT_TOKEN_STORAGE_KEY, ForbiddenError, HttpClient, LocalStorageAdapter, MemoryStorage, NetworkError, NotFoundError, RateLimitError, ServerError, TimeoutError, UnprocessableError, ValidationError, createAuthInterceptor, createDeviceSignalInterceptor, createErrorFromResponse };
|
|
1145
|
+
export { AuthClient, AuthError, AuthErrorCode, AuthService, AuthenticationError, BackgroundRefresh, BrowserDeviceSignalCollector, ConflictError, CookieStorage, DEFAULT_LAST_LOGIN_METHOD_KEY, DEFAULT_REFRESH_TOKEN_STORAGE_KEY, DEFAULT_SESSION_STORAGE_KEY, DEFAULT_TOKEN_STORAGE_KEY, ForbiddenError, HttpClient, LocalStorageAdapter, MemoryStorage, NetworkError, NotFoundError, PhoneService, RateLimitError, ServerError, SessionService, TimeoutError, UnprocessableError, ValidationError, createAuthInterceptor, createDeviceSignalInterceptor, createErrorFromResponse, decodeJwtPayload, hasDevice, validatePhoneNumber, validateUsername };
|
|
643
1146
|
//# sourceMappingURL=index.js.map
|
|
644
1147
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/device/browser-collector.ts","../src/errors/auth-error.ts","../src/errors/errors.ts","../src/errors/factory.ts","../src/http/rate-limit.ts","../src/http/retry.ts","../src/http/client.ts","../src/http/interceptors/auth.ts","../src/http/interceptors/device-signals.ts","../src/types/config.ts","../src/services/auth.ts","../src/storage/local-storage-adapter.ts","../src/storage/memory-storage.ts","../src/client.ts","../src/errors/codes.ts"],"names":["AuthErrorCode"],"mappings":";AAIA,IAAM,aAAA,GAA+B;AAAA,EACnC,MAAA,EAAQ,EAAA;AAAA,EACR,QAAA,EAAU,EAAA;AAAA,EACV,QAAA,EAAU,EAAA;AAAA,EACV,QAAA,EAAU,EAAA;AAAA,EACV,UAAA,EAAY,EAAA;AAAA,EACZ,YAAA,EAAc;AAChB,CAAA;AAEA,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,UAAA,CAAW,CAAC,CAAA;AAC/B,IAAA,IAAA,GAAA,CAAQ,IAAA,IAAQ,KAAK,IAAA,GAAO,IAAA;AAC5B,IAAA,IAAA,IAAQ,CAAA;AAAA,EACV;AACA,EAAA,OAAO,IAAA,CAAK,IAAI,IAAI,CAAA,CAAE,SAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AACpD;AAEA,eAAe,WAAW,KAAA,EAAgC;AACxD,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,UAAA,CAAW,MAAA,EAAQ,MAAA,EAAQ,WAAW,UAAA,EAAY;AAC3D,MAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA;AACjC,MAAA,MAAM,aAAa,MAAM,UAAA,CAAW,OAAO,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,CAAA;AACxE,MAAA,MAAM,YAAY,KAAA,CAAM,IAAA,CAAK,IAAI,UAAA,CAAW,UAAU,CAAC,CAAA;AACvD,MAAA,OAAO,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAAA,IACtE;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,WAAW,KAAK,CAAA;AACzB;AAEO,IAAM,+BAAN,MAAqE;AAAA,EAClE,MAAA,GAA+B,IAAA;AAAA,EAC/B,iBAAA,GAAmC,IAAA;AAAA,EAE3C,MAAM,OAAA,GAAkC;AACtC,IAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAA,CAAK,MAAA;AAE7B,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,cAAc,WAAA,EAAa;AACrE,MAAA,IAAA,CAAK,MAAA,GAAS,aAAA;AACd,MAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACd;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,QAAQ,CAAA,EAAG,MAAA,CAAO,KAAK,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,CAAA;AAAA,MACxC,QAAA,EAAU,IAAA,CAAK,cAAA,EAAe,CAAE,iBAAgB,CAAE,QAAA;AAAA,MAClD,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,UAAU,CAAA;AAAA,MACpC,YAAA,EAAc,MAAA,CAAO,cAAA,IAAkB,MAAM;AAAA,KAC/C;AAEA,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,MAAM,cAAA,GAAkC;AACtC,IAAA,IAAI,IAAA,CAAK,iBAAA,EAAmB,OAAO,IAAA,CAAK,iBAAA;AAExC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,OAAA,EAAQ;AACnC,IAAA,MAAM,GAAA,GAAM;AAAA,MACV,OAAA,CAAQ,MAAA;AAAA,MACR,OAAA,CAAQ,QAAA;AAAA,MACR,OAAA,CAAQ,QAAA;AAAA,MACR,OAAA,CAAQ,QAAA;AAAA,MACR,OAAA,CAAQ,UAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACV,CAAE,KAAK,GAAG,CAAA;AAEV,IAAA,IAAA,CAAK,iBAAA,GAAoB,MAAM,UAAA,CAAW,GAAG,CAAA;AAC7C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AACF;;;AClEO,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAM;AAAA,EAC1B,IAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EAET,YAAY,OAAA,EAA2B;AACrC,IAAA,KAAA,CAAM,QAAQ,OAAO,CAAA;AACrB,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AACZ,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AACpB,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAC1B,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AACzB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAEA,MAAA,GAAkC;AAChC,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,WAAW,IAAA,CAAK;AAAA,KAClB;AAAA,EACF;AACF;;;AC9BO,IAAM,eAAA,GAAN,cAA8B,SAAA,CAAU;AAAA,EAC7C,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,SAAA,CAAU;AAAA,EACjD,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,cAAA,GAAN,cAA6B,SAAA,CAAU;AAAA,EAC5C,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,SAAA,CAAU;AAAA,EAC3C,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,SAAA,CAAU;AAAA,EAC3C,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,kBAAA,GAAN,cAAiC,SAAA,CAAU;AAAA,EAChD,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACd;AACF;AAMO,IAAM,cAAA,GAAN,cAA6B,SAAA,CAAU;AAAA,EACnC,UAAA;AAAA,EAET,YAAY,OAAA,EAAgC;AAC1C,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAAA,EAC5B;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO,EAAE,GAAG,KAAA,CAAM,QAAO,EAAG,UAAA,EAAY,KAAK,UAAA,EAAW;AAAA,EAC1D;AACF;AAEO,IAAM,WAAA,GAAN,cAA0B,SAAA,CAAU;AAAA,EACzC,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,YAAY,OAAA,CAAQ,UAAA,IAAc,KAAK,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF;AASO,IAAM,YAAA,GAAN,cAA2B,SAAA,CAAU;AAAA,EAC1C,YAAY,OAAA,EAA8B;AACxC,IAAA,KAAA,CAAM;AAAA,MACJ,IAAA,EAAM,QAAQ,IAAA,IAAS,eAAA;AAAA,MACvB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,UAAA,EAAY,CAAA;AAAA,MACZ,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,WAAW,OAAA,CAAQ;AAAA,KACpB,CAAA;AACD,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EACd;AACF;AAQO,IAAM,YAAA,GAAN,cAA2B,SAAA,CAAU;AAAA,EACjC,QAAA;AAAA,EAET,YAAY,OAAA,EAA8B;AACxC,IAAA,KAAA,CAAM;AAAA,MACJ,IAAA,EAAM,SAAA;AAAA,MACN,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,CAAA,wBAAA,EAA2B,QAAQ,QAAQ,CAAA,EAAA,CAAA;AAAA,MACvE,UAAA,EAAY,CAAA;AAAA,MACZ,WAAW,OAAA,CAAQ;AAAA,KACpB,CAAA;AACD,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC1B;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO,EAAE,GAAG,KAAA,CAAM,QAAO,EAAG,QAAA,EAAU,KAAK,QAAA,EAAS;AAAA,EACtD;AACF;;;AChGA,SAAS,UAAU,IAAA,EAA0B;AAC3C,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,aAAa,IAAA,EAAM;AACzD,IAAA,MAAM,GAAA,GAAM,IAAA;AACZ,IAAA,OAAO;AAAA,MACL,MAAM,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,GAAW,IAAI,IAAA,GAAO,MAAA;AAAA,MAChD,SAAS,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,GAAW,IAAI,OAAA,GAAU,eAAA;AAAA,MACzD,OAAA,EACE,OAAO,GAAA,CAAI,OAAA,KAAY,YAAY,GAAA,CAAI,OAAA,KAAY,IAAA,GAC9C,GAAA,CAAI,OAAA,GACL;AAAA,KACR;AAAA,EACF;AACA,EAAA,OAAO,EAAE,SAAS,eAAA,EAAgB;AACpC;AAEO,SAAS,sBAAsB,MAAA,EAA+B;AACnE,EAAA,IAAI,CAAC,QAAQ,OAAO,EAAA;AAEpB,EAAA,MAAM,OAAA,GAAU,OAAO,MAAM,CAAA;AAC7B,EAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,OAAO,GAAG,OAAO,OAAA;AAEnC,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,MAAM,CAAA;AAC5B,EAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAA,EAAG;AACjC,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAA,CAAA,CAAM,IAAA,CAAK,OAAA,EAAQ,GAAI,IAAA,CAAK,GAAA,EAAI,IAAK,GAAI,CAAC,CAAA;AAAA,EACpE;AAEA,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,uBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,EACW;AACX,EAAA,MAAM,MAAA,GAAS,UAAU,IAAI,CAAA;AAC7B,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,MAAA;AACjD,EAAA,MAAM,IAAA,GAAQ,OAAO,IAAA,IAAQ,eAAA;AAC7B,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,CAAA,KAAA,EAAQ,MAAM,CAAA,CAAA;AAChD,EAAA,MAAM,UAAU,MAAA,CAAO,OAAA;AACvB,EAAA,MAAM,IAAA,GAAO,EAAE,IAAA,EAAM,OAAA,EAAS,SAAS,SAAA,EAAU;AAEjD,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,MAAA,KAAW,GAAA;AACd,MAAA,OAAO,IAAI,gBAAgB,IAAI,CAAA;AAAA,IACjC,KAAK,MAAA,KAAW,GAAA;AACd,MAAA,OAAO,IAAI,oBAAoB,IAAI,CAAA;AAAA,IACrC,KAAK,MAAA,KAAW,GAAA;AACd,MAAA,OAAO,IAAI,eAAe,IAAI,CAAA;AAAA,IAChC,KAAK,MAAA,KAAW,GAAA;AACd,MAAA,OAAO,IAAI,cAAc,IAAI,CAAA;AAAA,IAC/B,KAAK,MAAA,KAAW,GAAA;AACd,MAAA,OAAO,IAAI,cAAc,IAAI,CAAA;AAAA,IAC/B,KAAK,MAAA,KAAW,GAAA;AACd,MAAA,OAAO,IAAI,mBAAmB,IAAI,CAAA;AAAA,IACpC,KAAK,WAAW,GAAA,EAAK;AACnB,MAAA,MAAM,UAAA,GAAa,qBAAA,CAAsB,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAC,CAAA;AACnE,MAAA,OAAO,IAAI,cAAA,CAAe,EAAE,GAAG,IAAA,EAAM,YAAY,CAAA;AAAA,IACnD;AAAA,IACA,MAAK,MAAA,IAAU,GAAA,IAAO,MAAA,GAAS,GAAA;AAC7B,MAAA,OAAO,IAAI,YAAY,IAAI,CAAA;AAAA,IAC7B;AACE,MAAA,OAAO,IAAI,SAAA,CAAU,EAAE,GAAG,IAAA,EAAM,UAAA,EAAY,QAAQ,CAAA;AAAA;AAE1D;;;AChFO,IAAM,yBAAA,GAA6C;AAAA,EACxD,SAAA,EAAW,IAAA;AAAA,EACX,aAAA,EAAe;AACjB,CAAA;AAEO,SAAS,qBAAqB,MAAA,EAAoD;AACvF,EAAA,OAAO,EAAE,GAAG,yBAAA,EAA2B,GAAG,MAAA,EAAO;AACnD;;;ACPO,IAAM,oBAAA,GAAoC;AAAA,EAC/C,UAAA,EAAY,CAAA;AAAA,EACZ,SAAA,EAAW,GAAA;AAAA,EACX,QAAA,EAAU,GAAA;AAAA,EACV,MAAA,EAAQ,CAAA;AAAA,EACR,MAAA,EAAQ,IAAA;AAAA,EACR,iBAAA,EAAmB,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtC,SAAA,EAAW;AACb,CAAA;AAEO,SAAS,iBAAiB,MAAA,EAA4C;AAC3E,EAAA,OAAO,EAAE,GAAG,oBAAA,EAAsB,GAAG,MAAA,EAAO;AAC9C;AAEO,SAAS,WAAA,CACd,KAAA,EACA,OAAA,EACA,MAAA,EACA,MAAA,EACS;AACT,EAAA,IAAI,OAAA,IAAW,MAAA,CAAO,UAAA,EAAY,OAAO,KAAA;AACzC,EAAA,IAAI,MAAA,KAAW,MAAA,IAAU,CAAC,MAAA,CAAO,WAAW,OAAO,KAAA;AAGnD,EAAA,IAAI,KAAA,YAAiB,WAAW,OAAO,IAAA;AAGvC,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,gBAAgB,KAAA,EAAO;AAC/D,IAAA,MAAM,aAAc,KAAA,CAAiC,UAAA;AACrD,IAAA,OAAO,MAAA,CAAO,iBAAA,CAAkB,QAAA,CAAS,UAAU,CAAA;AAAA,EACrD;AAEA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,cAAA,CAAe,SAAiB,MAAA,EAA6B;AAC3E,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,GAAY,MAAA,CAAO,MAAA,IAAU,OAAA;AACxD,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,OAAO,QAAQ,CAAA;AAEnD,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,KAAA;AAE3B,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,IAAA,CAAK,QAAQ,CAAA;AACzC;AAEO,SAAS,MAAM,EAAA,EAA2B;AAC/C,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;;;ACjCO,IAAM,aAAN,MAAiB;AAAA,EACL,MAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACT,sBAA4C,EAAC;AAAA,EAC7C,uBAA8C,EAAC;AAAA,EAC/C,oBAAwC,EAAC;AAAA,EAEjD,YAAY,MAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,WAAA,GAAc,gBAAA,CAAiB,MAAA,CAAO,KAAK,CAAA;AAChD,IAAA,IAAA,CAAK,eAAA,GAAkB,oBAAA,CAAqB,MAAA,CAAO,SAAS,CAAA;AAAA,EAC9D;AAAA;AAAA,EAIA,MAAM,GAAA,CACJ,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,QAAW,EAAE,GAAG,QAAQ,MAAA,EAAQ,KAAA,EAAO,MAAM,CAAA;AAAA,EAC3D;AAAA,EAEA,MAAM,IAAA,CACJ,IAAA,EACA,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,QAAW,EAAE,GAAG,QAAQ,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,EAClE;AAAA,EAEA,MAAM,GAAA,CACJ,IAAA,EACA,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,QAAW,EAAE,GAAG,QAAQ,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,EACjE;AAAA,EAEA,MAAM,KAAA,CACJ,IAAA,EACA,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,QAAW,EAAE,GAAG,QAAQ,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,EACnE;AAAA,EAEA,MAAM,MAAA,CACJ,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,QAAW,EAAE,GAAG,QAAQ,MAAA,EAAQ,QAAA,EAAU,MAAM,CAAA;AAAA,EAC9D;AAAA;AAAA,EAIA,sBAAsB,EAAA,EAA8B;AAClD,IAAA,IAAA,CAAK,mBAAA,CAAoB,KAAK,EAAE,CAAA;AAAA,EAClC;AAAA,EAEA,yBAAyB,EAAA,EAA8B;AACrD,IAAA,IAAA,CAAK,sBAAsB,IAAA,CAAK,mBAAA,CAAoB,OAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA;AAAA,EAC5E;AAAA,EAEA,uBAAuB,EAAA,EAA+B;AACpD,IAAA,IAAA,CAAK,oBAAA,CAAqB,KAAK,EAAE,CAAA;AAAA,EACnC;AAAA,EAEA,0BAA0B,EAAA,EAA+B;AACvD,IAAA,IAAA,CAAK,uBAAuB,IAAA,CAAK,oBAAA,CAAqB,OAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA;AAAA,EAC9E;AAAA,EAEA,oBAAoB,EAAA,EAA4B;AAC9C,IAAA,IAAA,CAAK,iBAAA,CAAkB,KAAK,EAAE,CAAA;AAAA,EAChC;AAAA,EAEA,uBAAuB,EAAA,EAA4B;AACjD,IAAA,IAAA,CAAK,oBAAoB,IAAA,CAAK,iBAAA,CAAkB,OAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA;AAAA,EACxE;AAAA;AAAA,EAIA,MAAc,QAAW,aAAA,EAAuD;AAE9E,IAAA,IAAI,MAAA,GAAS,EAAE,GAAG,aAAA,EAAc;AAChC,IAAA,KAAA,MAAW,WAAA,IAAe,KAAK,mBAAA,EAAqB;AAClD,MAAA,MAAA,GAAS,MAAM,YAAY,MAAM,CAAA;AAAA,IACnC;AAGA,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,OAAO,IAAA,EAAM,IAAA,CAAK,OAAO,OAAO,CAAA;AACpD,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AACxD,QAAA,IAAI,UAAU,MAAA,EAAW;AACvB,UAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,GAAG,KAAK,MAAA,CAAO,OAAA;AAAA,MACf,GAAG,MAAA,CAAO;AAAA,KACZ;AACA,IAAA,IAAI,MAAA,CAAO,SAAS,MAAA,EAAW;AAC7B,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAAA,IAC5B;AAGA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,WAAA,CAAY,UAAA,GAAa,CAAA;AAClD,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,GAAU,WAAA,EAAa,OAAA,EAAA,EAAW;AACtD,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,IAAA,CAAK,YAAA,CAAgB,GAAA,EAAK,OAAA,EAAS,QAAQ,OAAO,CAAA;AAAA,MACjE,SAAS,KAAA,EAAO;AAEd,QAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,QAAA,KAAA,MAAW,WAAA,IAAe,KAAK,iBAAA,EAAmB;AAChD,UAAA,cAAA,GAAiB,MAAM,YAAY,cAAc,CAAA;AAAA,QACnD;AAGA,QAAA,IAAI,0BAA0B,cAAA,EAAgB;AAC5C,UAAA,IACE,IAAA,CAAK,gBAAgB,SAAA,IACrB,cAAA,CAAe,cAAc,IAAA,CAAK,eAAA,CAAgB,aAAA,IAClD,OAAA,KAAY,CAAA,EACZ;AACA,YAAA,MAAM,KAAA,CAAM,cAAA,CAAe,UAAA,GAAa,GAAI,CAAA;AAC5C,YAAA;AAAA,UACF;AACA,UAAA,MAAM,cAAA;AAAA,QACR;AAGA,QAAA,IAAI,YAAY,cAAA,EAAgB,OAAA,EAAS,OAAO,MAAA,EAAQ,IAAA,CAAK,WAAW,CAAA,EAAG;AACzE,UAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,EAAS,IAAA,CAAK,WAAW,CAAA;AACtD,UAAA,MAAM,MAAM,KAAK,CAAA;AACjB,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,cAAA;AAAA,MACR;AAAA,IACF;AAGA,IAAA,MAAM,IAAI,YAAA,CAAa,EAAE,OAAA,EAAS,wBAAwB,CAAA;AAAA,EAC5D;AAAA,EAEA,MAAc,YAAA,CACZ,GAAA,EACA,OAAA,EACA,QACA,QAAA,EACyB;AACzB,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,IAAA,CAAK,OAAO,OAAA,IAAW,GAAA;AACzD,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,YAAY,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,OAAO,CAAA;AAE9D,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA,QAC3C,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,OAAA;AAAA,QACA,IAAA,EAAM,OAAO,IAAA,KAAS,KAAA,CAAA,GAAY,KAAK,SAAA,CAAU,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,QAChE,MAAA,EAAQ,MAAA,CAAO,MAAA,IAAU,UAAA,CAAW;AAAA,OACrC,CAAA;AAED,MAAA,YAAA,CAAa,SAAS,CAAA;AAGtB,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,IAAI,IAAA;AACJ,QAAA,IAAI;AACF,UAAA,IAAA,GAAO,MAAM,SAAS,IAAA,EAAK;AAAA,QAC7B,CAAA,CAAA,MAAQ;AACN,UAAA,IAAA,GAAO,EAAE,OAAA,EAAS,QAAA,CAAS,UAAA,EAAW;AAAA,QACxC;AACA,QAAA,MAAM,uBAAA,CAAwB,QAAA,CAAS,MAAA,EAAQ,IAAA,EAAM,SAAS,OAAO,CAAA;AAAA,MACvE;AAGA,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,IAAA,GAAO,KAAA,CAAA;AAAA,MACT,CAAA,MAAO;AACL,QAAA,IAAA,GAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,MAC9B;AAEA,MAAA,IAAI,MAAA,GAA+B;AAAA,QACjC,IAAA;AAAA,QACA,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,SAAS,QAAA,CAAS;AAAA,OACpB;AAGA,MAAA,KAAA,MAAW,WAAA,IAAe,KAAK,oBAAA,EAAsB;AACnD,QAAA,MAAA,GAAS,MAAM,YAAY,MAAM,CAAA;AAAA,MACnC;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,YAAA,CAAa,SAAS,CAAA;AAEtB,MAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AAChE,QAAA,MAAM,IAAI,YAAA,CAAa,EAAE,QAAA,EAAU,SAAS,CAAA;AAAA,MAC9C;AAEA,MAAA,IAAI,iBAAiB,SAAA,EAAW;AAC9B,QAAA,MAAM,IAAI,YAAA,CAAa,EAAE,OAAA,EAAS,KAAA,CAAM,SAAS,CAAA;AAAA,MACnD;AAEA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AACF;;;AC7NO,SAAS,sBAAsB,MAAA,EAAmD;AACvF,EAAA,OAAO,CAAC,OAAA,KAAY;AAClB,IAAA,IAAI,OAAA,CAAQ,UAAU,OAAO,OAAA;AAE7B,IAAA,MAAM,OAAA,GAAU,EAAE,GAAG,OAAA,CAAQ,OAAA,EAAQ;AAErC,IAAA,IAAI,OAAO,aAAA,EAAe;AACxB,MAAA,MAAM,KAAA,GAAQ,OAAO,aAAA,EAAc;AACnC,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,OAAA,CAAQ,aAAA,GAAgB,UAAU,KAAK,CAAA,CAAA;AAAA,MACzC;AAAA,IACF;AAEA,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,OAAA,CAAQ,WAAW,IAAI,MAAA,CAAO,MAAA;AAAA,IAChC;AAEA,IAAA,OAAO,EAAE,GAAG,OAAA,EAAS,OAAA,EAAQ;AAAA,EAC/B,CAAA;AACF;;;ACvBO,SAAS,8BACd,SAAA,EACoB;AACpB,EAAA,OAAO,OAAO,OAAA,KAAY;AACxB,IAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,OAAA,EAAQ;AAGxC,IAAA,IAAI,CAAC,QAAQ,MAAA,IAAU,CAAC,QAAQ,QAAA,IAAY,CAAC,QAAQ,QAAA,EAAU;AAC7D,MAAA,OAAO,OAAA;AAAA,IACT;AAEA,IAAA,MAAM,WAAA,GAAc,MAAM,SAAA,CAAU,cAAA,EAAe;AAEnD,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,GAAG,OAAA,CAAQ,OAAA;AAAA,MACX,mBAAmB,OAAA,CAAQ,MAAA;AAAA,MAC3B,qBAAqB,OAAA,CAAQ,QAAA;AAAA,MAC7B,qBAAqB,OAAA,CAAQ,QAAA;AAAA,MAC7B,qBAAqB,OAAA,CAAQ,QAAA;AAAA,MAC7B,wBAAwB,OAAA,CAAQ,UAAA;AAAA,MAChC,kBAAkB,OAAA,CAAQ,YAAA;AAAA,MAC1B,sBAAA,EAAwB;AAAA,KAC1B;AAEA,IAAA,OAAO,EAAE,GAAG,OAAA,EAAS,OAAA,EAAQ;AAAA,EAC/B,CAAA;AACF;;;ACCO,IAAM,yBAAA,GAA4B;AAClC,IAAM,iCAAA,GAAoC;AAC1C,IAAM,2BAAA,GAA8B;AACpC,IAAM,6BAAA,GAAgC;;;ACxBtC,IAAM,cAAN,MAAkB;AAAA,EACN,UAAA;AAAA,EACA,OAAA;AAAA,EACA,eAAA;AAAA,EACA,sBAAA;AAAA,EACA,kBAAA;AAAA,EAEjB,WAAA,CACE,UAAA,EACA,OAAA,EACA,OAAA,EAKA;AACA,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,eAAA,GAAkB,SAAS,eAAA,IAAmB,yBAAA;AACnD,IAAA,IAAA,CAAK,sBAAA,GACH,SAAS,sBAAA,IAA0B,iCAAA;AACrC,IAAA,IAAA,CAAK,kBAAA,GAAqB,SAAS,kBAAA,IAAsB,6BAAA;AAAA,EAC3D;AAAA,EAEA,MAAM,MAAM,WAAA,EAAuD;AACjE,IAAA,MAAM,EAAE,MAAK,GAAI,MAAM,KAAK,UAAA,CAAW,IAAA,CAAoB,eAAe,WAAA,EAAa;AAAA,MACrF,QAAA,EAAU;AAAA,KACX,CAAA;AAED,IAAA,MAAM,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,WAAA,EAAa,KAAK,YAAY,CAAA;AAC1D,IAAA,MAAM,IAAA,CAAK,mBAAmB,OAAO,CAAA;AAErC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,IAAA,EAA2C;AACtD,IAAA,MAAM,EAAE,MAAM,QAAA,EAAS,GAAI,MAAM,IAAA,CAAK,UAAA,CAAW,IAAA,CAAqB,cAAA,EAAgB,IAAA,EAAM;AAAA,MAC1F,QAAA,EAAU;AAAA,KACX,CAAA;AAED,IAAA,MAAM,IAAA,CAAK,WAAA,CAAY,QAAA,CAAS,WAAA,EAAa,SAAS,YAAY,CAAA;AAClE,IAAA,MAAM,IAAA,CAAK,mBAAmB,OAAO,CAAA;AAErC,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAA,CAAY,WAAA,EAAqB,YAAA,EAAqC;AAC1E,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,iBAAiB,WAAW,CAAA;AACxD,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,wBAAwB,YAAY,CAAA;AAAA,EAClE;AAAA,EAEA,MAAM,mBAAmB,MAAA,EAA+B;AACtD,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,oBAAoB,MAAM,CAAA;AAAA,EACxD;AACF;;;AC7DO,IAAM,sBAAN,MAAmD;AAAA,EACxD,MAAM,IAAI,GAAA,EAAqC;AAC7C,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,IAAA;AAC1C,IAAA,OAAO,MAAA,CAAO,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AAAA,EACxC;AAAA,EAEA,MAAM,GAAA,CAAI,GAAA,EAAa,KAAA,EAA8B;AACnD,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,IAAA,MAAA,CAAO,YAAA,CAAa,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAAA,EACxC;AAAA,EAEA,MAAM,OAAO,GAAA,EAA4B;AACvC,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,IAAA,MAAA,CAAO,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,EACpC;AACF;;;ACfO,IAAM,gBAAN,MAA6C;AAAA,EAC1C,KAAA,uBAAY,GAAA,EAAoB;AAAA,EAExC,MAAM,IAAI,GAAA,EAAqC;AAC7C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA;AAAA,EAChC;AAAA,EAEA,MAAM,GAAA,CAAI,GAAA,EAAa,KAAA,EAA8B;AACnD,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,OAAO,GAAA,EAA4B;AACvC,IAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,EACvB;AACF;;;ACNA,IAAM,oBAAA,GAAuB,EAAA;AAEtB,IAAM,aAAN,MAAiB;AAAA,EACL,MAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,MAAA,EAAoB;AAC9B,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,IAAI,aAAA,EAAc;AAEnD,IAAA,MAAM,eAAA,GAAkB,OAAO,eAAA,IAAmB,yBAAA;AAClD,IAAA,MAAM,yBAAyB,MAAA,CAAO,eAAA,GAClC,CAAA,EAAG,MAAA,CAAO,eAAe,CAAA,QAAA,CAAA,GACzB,iCAAA;AAEJ,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,UAAA,CAAW;AAAA,MAC/B,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,SAAS,MAAA,CAAO;AAAA,KACjB,CAAA;AAGD,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,IAAA,IAAA,CAAK,UAAA,CAAW,qBAAA;AAAA,MACd,qBAAA,CAAsB;AAAA,QACpB,eAAe,MAAM;AAGnB,UAAA,OAAO,IAAA;AAAA,QACT,CAAA;AAAA,QACA,QAAQ,MAAA,CAAO;AAAA,OAChB;AAAA,KACH;AAGA,IAAA,IAAA,CAAK,UAAA,CAAW,qBAAA,CAAsB,OAAO,OAAA,KAAY;AACvD,MAAA,IAAI,OAAA,CAAQ,UAAU,OAAO,OAAA;AAC7B,MAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA;AAC/C,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,OAAO;AAAA,UACL,GAAG,OAAA;AAAA,UACH,OAAA,EAAS;AAAA,YACP,GAAG,OAAA,CAAQ,OAAA;AAAA,YACX,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA;AAChC,SACF;AAAA,MACF;AACA,MAAA,OAAO,OAAA;AAAA,IACT,CAAC,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,yBAAyB,KAAA,EAAO;AACzC,MAAA,MAAM,SAAA,GAAY,IAAI,4BAAA,EAA6B;AACnD,MAAA,IAAA,CAAK,UAAA,CAAW,qBAAA,CAAsB,6BAAA,CAA8B,SAAS,CAAC,CAAA;AAAA,IAChF;AAEA,IAAA,IAAA,CAAK,cAAc,IAAI,WAAA,CAAY,IAAA,CAAK,UAAA,EAAY,KAAK,OAAA,EAAS;AAAA,MAChE,eAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,MAAM,WAAA,EAAuD;AACjE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,CAAY,MAAM,WAAW,CAAA;AACzD,IAAA,IAAA,CAAK,iBAAiB,QAAQ,CAAA;AAC9B,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,IAAA,EAA2C;AACtD,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAI,CAAA;AAAA,EACrC;AAAA,EAEQ,iBAAiB,QAAA,EAA+B;AACtD,IAAA,IACE,QAAA,CAAS,cACT,QAAA,CAAS,UAAA,CAAW,aAAa,oBAAA,IACjC,IAAA,CAAK,OAAO,gBAAA,EACZ;AACA,MAAA,MAAM,QAAQ,QAAA,CAAS,UAAA;AACvB,MAAA,IAAA,CAAK,OAAO,gBAAA,CAAiB;AAAA,QAC3B,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,WAAW,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,EACF;AACF;;;ACnGO,IAAK,aAAA,qBAAAA,cAAAA,KAAL;AAEL,EAAAA,eAAA,oBAAA,CAAA,GAAqB,qBAAA;AACrB,EAAAA,eAAA,kBAAA,CAAA,GAAmB,oBAAA;AACnB,EAAAA,eAAA,mBAAA,CAAA,GAAoB,qBAAA;AAGpB,EAAAA,eAAA,oBAAA,CAAA,GAAqB,sBAAA;AACrB,EAAAA,eAAA,YAAA,CAAA,GAAa,aAAA;AACb,EAAAA,eAAA,YAAA,CAAA,GAAa,aAAA;AACb,EAAAA,eAAA,gBAAA,CAAA,GAAiB,kBAAA;AACjB,EAAAA,eAAA,kBAAA,CAAA,GAAmB,qBAAA;AACnB,EAAAA,eAAA,eAAA,CAAA,GAAgB,gBAAA;AAGhB,EAAAA,eAAA,eAAA,CAAA,GAAgB,gBAAA;AAChB,EAAAA,eAAA,iBAAA,CAAA,GAAkB,kBAAA;AAClB,EAAAA,eAAA,kBAAA,CAAA,GAAmB,mBAAA;AAGnB,EAAAA,eAAA,gBAAA,CAAA,GAAiB,kBAAA;AACjB,EAAAA,eAAA,oBAAA,CAAA,GAAqB,uBAAA;AACrB,EAAAA,eAAA,gBAAA,CAAA,GAAiB,iBAAA;AAGjB,EAAAA,eAAA,qBAAA,CAAA,GAAsB,uBAAA;AAGtB,EAAAA,eAAA,iBAAA,CAAA,GAAkB,kBAAA;AAClB,EAAAA,eAAA,gBAAA,CAAA,GAAiB,iBAAA;AAGjB,EAAAA,eAAA,kBAAA,CAAA,GAAmB,mBAAA;AAGnB,EAAAA,eAAA,gBAAA,CAAA,GAAiB,iBAAA;AACjB,EAAAA,eAAA,cAAA,CAAA,GAAe,eAAA;AACf,EAAAA,eAAA,cAAA,CAAA,GAAe,eAAA;AAGf,EAAAA,eAAA,kBAAA,CAAA,GAAmB,mBAAA;AACnB,EAAAA,eAAA,sBAAA,CAAA,GAAuB,wBAAA;AACvB,EAAAA,eAAA,kBAAA,CAAA,GAAmB,mBAAA;AAGnB,EAAAA,eAAA,aAAA,CAAA,GAAc,cAAA;AACd,EAAAA,eAAA,cAAA,CAAA,GAAe,eAAA;AACf,EAAAA,eAAA,SAAA,CAAA,GAAU,SAAA;AAGV,EAAAA,eAAA,cAAA,CAAA,GAAe,gBAAA;AACf,EAAAA,eAAA,mBAAA,CAAA,GAAoB,qBAAA;AACpB,EAAAA,eAAA,cAAA,CAAA,GAAe,eAAA;AACf,EAAAA,eAAA,cAAA,CAAA,GAAe,eAAA;AAGf,EAAAA,eAAA,2BAAA,CAAA,GAA4B,oBAAA;AAC5B,EAAAA,eAAA,qBAAA,CAAA,GAAsB,uBAAA;AAGtB,EAAAA,eAAA,aAAA,CAAA,GAAc,eAAA;AACd,EAAAA,eAAA,YAAA,CAAA,GAAa,aAAA;AACb,EAAAA,eAAA,YAAA,CAAA,GAAa,aAAA;AA9DH,EAAA,OAAAA,cAAAA;AAAA,CAAA,EAAA,aAAA,IAAA,EAAA","file":"index.js","sourcesContent":["// Browser Device Signal Collector — SSR-safe\n\nimport type { DeviceSignals, IDeviceSignalCollector } from \"./types\";\n\nconst EMPTY_SIGNALS: DeviceSignals = {\n screen: \"\",\n timezone: \"\",\n platform: \"\",\n language: \"\",\n colorDepth: \"\",\n touchSupport: \"\",\n};\n\nfunction simpleHash(input: string): string {\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash |= 0;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\nasync function sha256Hash(input: string): Promise<string> {\n try {\n if (typeof globalThis.crypto?.subtle?.digest === \"function\") {\n const encoder = new TextEncoder();\n const data = encoder.encode(input);\n const hashBuffer = await globalThis.crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n } catch {\n // Fallback below\n }\n return simpleHash(input);\n}\n\nexport class BrowserDeviceSignalCollector implements IDeviceSignalCollector {\n private cached: DeviceSignals | null = null;\n private cachedFingerprint: string | null = null;\n\n async collect(): Promise<DeviceSignals> {\n if (this.cached) return this.cached;\n\n if (typeof window === \"undefined\" || typeof navigator === \"undefined\") {\n this.cached = EMPTY_SIGNALS;\n return this.cached;\n }\n\n this.cached = {\n screen: `${screen.width}x${screen.height}`,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n platform: navigator.platform,\n language: navigator.language,\n colorDepth: String(screen.colorDepth),\n touchSupport: String(\"ontouchstart\" in window),\n };\n\n return this.cached;\n }\n\n async getFingerprint(): Promise<string> {\n if (this.cachedFingerprint) return this.cachedFingerprint;\n\n const signals = await this.collect();\n const raw = [\n signals.screen,\n signals.timezone,\n signals.platform,\n signals.language,\n signals.colorDepth,\n signals.touchSupport,\n ].join(\"|\");\n\n this.cachedFingerprint = await sha256Hash(raw);\n return this.cachedFingerprint;\n }\n}\n","// Base Auth Error\n\nimport type { AuthErrorCode } from \"./codes\";\n\nexport interface AuthErrorOptions {\n code: AuthErrorCode;\n message: string;\n statusCode: number;\n details?: Record<string, unknown>;\n requestId?: string;\n}\n\nexport class AuthError extends Error {\n readonly code: AuthErrorCode;\n readonly statusCode: number;\n readonly details?: Record<string, unknown>;\n readonly requestId?: string;\n\n constructor(options: AuthErrorOptions) {\n super(options.message);\n this.name = \"AuthError\";\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.details = options.details;\n this.requestId = options.requestId;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n requestId: this.requestId,\n };\n }\n}\n","// Error Subclasses\n\nimport { AuthError, type AuthErrorOptions } from \"./auth-error\";\nimport type { AuthErrorCode } from \"./codes\";\n\ntype SubclassOptions = Omit<AuthErrorOptions, \"statusCode\"> & { statusCode?: number };\n\nexport class ValidationError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 400 });\n this.name = \"ValidationError\";\n }\n}\n\nexport class AuthenticationError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 401 });\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class ForbiddenError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 403 });\n this.name = \"ForbiddenError\";\n }\n}\n\nexport class NotFoundError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 404 });\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ConflictError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 409 });\n this.name = \"ConflictError\";\n }\n}\n\nexport class UnprocessableError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 422 });\n this.name = \"UnprocessableError\";\n }\n}\n\nexport interface RateLimitErrorOptions extends SubclassOptions {\n retryAfter: number;\n}\n\nexport class RateLimitError extends AuthError {\n readonly retryAfter: number;\n\n constructor(options: RateLimitErrorOptions) {\n super({ ...options, statusCode: options.statusCode ?? 429 });\n this.name = \"RateLimitError\";\n this.retryAfter = options.retryAfter;\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), retryAfter: this.retryAfter };\n }\n}\n\nexport class ServerError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 500 });\n this.name = \"ServerError\";\n }\n}\n\nexport interface NetworkErrorOptions {\n message: string;\n code?: AuthErrorCode;\n details?: Record<string, unknown>;\n requestId?: string;\n}\n\nexport class NetworkError extends AuthError {\n constructor(options: NetworkErrorOptions) {\n super({\n code: options.code ?? (\"NETWORK_ERROR\" as AuthErrorCode),\n message: options.message,\n statusCode: 0,\n details: options.details,\n requestId: options.requestId,\n });\n this.name = \"NetworkError\";\n }\n}\n\nexport interface TimeoutErrorOptions {\n duration: number;\n message?: string;\n requestId?: string;\n}\n\nexport class TimeoutError extends AuthError {\n readonly duration: number;\n\n constructor(options: TimeoutErrorOptions) {\n super({\n code: \"TIMEOUT\" as AuthErrorCode,\n message: options.message ?? `Request timed out after ${options.duration}ms`,\n statusCode: 0,\n requestId: options.requestId,\n });\n this.name = \"TimeoutError\";\n this.duration = options.duration;\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), duration: this.duration };\n }\n}\n","// Error Factory — maps HTTP responses to typed errors\n\nimport { AuthError } from \"./auth-error\";\nimport type { AuthErrorCode } from \"./codes\";\nimport {\n AuthenticationError,\n ConflictError,\n ForbiddenError,\n NotFoundError,\n RateLimitError,\n ServerError,\n UnprocessableError,\n ValidationError,\n} from \"./errors\";\n\ninterface ErrorBody {\n code?: string;\n message?: string;\n details?: Record<string, unknown>;\n}\n\nfunction parseBody(body: unknown): ErrorBody {\n if (body && typeof body === \"object\" && \"message\" in body) {\n const obj = body as Record<string, unknown>;\n return {\n code: typeof obj.code === \"string\" ? obj.code : undefined,\n message: typeof obj.message === \"string\" ? obj.message : \"Unknown error\",\n details:\n typeof obj.details === \"object\" && obj.details !== null\n ? (obj.details as Record<string, unknown>)\n : undefined,\n };\n }\n return { message: \"Unknown error\" };\n}\n\nexport function parseRetryAfterHeader(header: string | null): number {\n if (!header) return 60;\n\n const seconds = Number(header);\n if (!Number.isNaN(seconds)) return seconds;\n\n const date = new Date(header);\n if (!Number.isNaN(date.getTime())) {\n return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1000));\n }\n\n return 60;\n}\n\nexport function createErrorFromResponse(\n status: number,\n body: unknown,\n headers: Headers,\n): AuthError {\n const parsed = parseBody(body);\n const requestId = headers.get(\"x-request-id\") ?? undefined;\n const code = (parsed.code ?? \"NETWORK_ERROR\") as AuthErrorCode;\n const message = parsed.message ?? `HTTP ${status}`;\n const details = parsed.details;\n const base = { code, message, details, requestId };\n\n switch (true) {\n case status === 400:\n return new ValidationError(base);\n case status === 401:\n return new AuthenticationError(base);\n case status === 403:\n return new ForbiddenError(base);\n case status === 404:\n return new NotFoundError(base);\n case status === 409:\n return new ConflictError(base);\n case status === 422:\n return new UnprocessableError(base);\n case status === 429: {\n const retryAfter = parseRetryAfterHeader(headers.get(\"retry-after\"));\n return new RateLimitError({ ...base, retryAfter });\n }\n case status >= 500 && status < 600:\n return new ServerError(base);\n default:\n return new AuthError({ ...base, statusCode: status });\n }\n}\n","// Rate Limit Handling\n\nimport type { RateLimitConfig } from \"./types\";\n\nexport const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig = {\n autoRetry: true,\n maxRetryAfter: 60,\n};\n\nexport function mergeRateLimitConfig(config?: Partial<RateLimitConfig>): RateLimitConfig {\n return { ...DEFAULT_RATE_LIMIT_CONFIG, ...config };\n}\n\nexport function parseRetryAfter(header: string | null): number {\n if (!header) return 60;\n\n const seconds = Number(header);\n if (!Number.isNaN(seconds)) return seconds;\n\n const date = new Date(header);\n if (!Number.isNaN(date.getTime())) {\n return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1000));\n }\n\n return 60;\n}\n","// Retry Logic with Exponential Backoff\n\nimport type { RetryConfig } from \"./types\";\n\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n factor: 2,\n jitter: true,\n retryableStatuses: [500, 502, 503, 504],\n retryPost: false,\n};\n\nexport function mergeRetryConfig(config?: Partial<RetryConfig>): RetryConfig {\n return { ...DEFAULT_RETRY_CONFIG, ...config };\n}\n\nexport function shouldRetry(\n error: unknown,\n attempt: number,\n method: string,\n config: RetryConfig,\n): boolean {\n if (attempt >= config.maxRetries) return false;\n if (method === \"POST\" && !config.retryPost) return false;\n\n // Network error (TypeError from fetch)\n if (error instanceof TypeError) return true;\n\n // Check statusCode on error objects\n if (error && typeof error === \"object\" && \"statusCode\" in error) {\n const statusCode = (error as { statusCode: number }).statusCode;\n return config.retryableStatuses.includes(statusCode);\n }\n\n return false;\n}\n\nexport function calculateDelay(attempt: number, config: RetryConfig): number {\n const exponential = config.baseDelay * config.factor ** attempt;\n const delay = Math.min(exponential, config.maxDelay);\n\n if (!config.jitter) return delay;\n\n return Math.round(delay * Math.random());\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// HTTP Client — zero-dependency fetch wrapper\n\nimport { NetworkError, RateLimitError, TimeoutError } from \"../errors/errors\";\nimport { createErrorFromResponse } from \"../errors/factory\";\nimport { mergeRateLimitConfig } from \"./rate-limit\";\nimport { calculateDelay, mergeRetryConfig, shouldRetry, sleep } from \"./retry\";\nimport type {\n ApiResponse,\n ErrorInterceptor,\n HttpClientConfig,\n RateLimitConfig,\n RequestConfig,\n RequestInterceptor,\n ResponseInterceptor,\n RetryConfig,\n} from \"./types\";\n\nexport class HttpClient {\n private readonly config: HttpClientConfig;\n private readonly retryConfig: RetryConfig;\n private readonly rateLimitConfig: RateLimitConfig;\n private requestInterceptors: RequestInterceptor[] = [];\n private responseInterceptors: ResponseInterceptor[] = [];\n private errorInterceptors: ErrorInterceptor[] = [];\n\n constructor(config: HttpClientConfig) {\n this.config = config;\n this.retryConfig = mergeRetryConfig(config.retry);\n this.rateLimitConfig = mergeRateLimitConfig(config.rateLimit);\n }\n\n // --- Public HTTP Methods ---\n\n async get<T>(\n path: string,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"GET\", path });\n }\n\n async post<T>(\n path: string,\n body?: unknown,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"POST\", path, body });\n }\n\n async put<T>(\n path: string,\n body?: unknown,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"PUT\", path, body });\n }\n\n async patch<T>(\n path: string,\n body?: unknown,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"PATCH\", path, body });\n }\n\n async delete<T>(\n path: string,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"DELETE\", path });\n }\n\n // --- Interceptor Management ---\n\n addRequestInterceptor(fn: RequestInterceptor): void {\n this.requestInterceptors.push(fn);\n }\n\n removeRequestInterceptor(fn: RequestInterceptor): void {\n this.requestInterceptors = this.requestInterceptors.filter((i) => i !== fn);\n }\n\n addResponseInterceptor(fn: ResponseInterceptor): void {\n this.responseInterceptors.push(fn);\n }\n\n removeResponseInterceptor(fn: ResponseInterceptor): void {\n this.responseInterceptors = this.responseInterceptors.filter((i) => i !== fn);\n }\n\n addErrorInterceptor(fn: ErrorInterceptor): void {\n this.errorInterceptors.push(fn);\n }\n\n removeErrorInterceptor(fn: ErrorInterceptor): void {\n this.errorInterceptors = this.errorInterceptors.filter((i) => i !== fn);\n }\n\n // --- Internal ---\n\n private async request<T>(initialConfig: RequestConfig): Promise<ApiResponse<T>> {\n // Run request interceptors\n let config = { ...initialConfig };\n for (const interceptor of this.requestInterceptors) {\n config = await interceptor(config);\n }\n\n // Build URL\n const url = new URL(config.path, this.config.baseUrl);\n if (config.params) {\n for (const [key, value] of Object.entries(config.params)) {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n // Build headers\n const headers: Record<string, string> = {\n ...this.config.headers,\n ...config.headers,\n };\n if (config.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n // Retry loop\n const maxAttempts = this.retryConfig.maxRetries + 1;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await this.executeFetch<T>(url, headers, config, attempt);\n } catch (error) {\n // Run error interceptors\n let processedError = error;\n for (const interceptor of this.errorInterceptors) {\n processedError = await interceptor(processedError);\n }\n\n // Rate limit: handle 429 separately from general retry\n if (processedError instanceof RateLimitError) {\n if (\n this.rateLimitConfig.autoRetry &&\n processedError.retryAfter <= this.rateLimitConfig.maxRetryAfter &&\n attempt === 0\n ) {\n await sleep(processedError.retryAfter * 1000);\n continue;\n }\n throw processedError;\n }\n\n // General retry\n if (shouldRetry(processedError, attempt, config.method, this.retryConfig)) {\n const delay = calculateDelay(attempt, this.retryConfig);\n await sleep(delay);\n continue;\n }\n\n throw processedError;\n }\n }\n\n // Should not reach here, but satisfy TypeScript\n throw new NetworkError({ message: \"Max retries exceeded\" });\n }\n\n private async executeFetch<T>(\n url: URL,\n headers: Record<string, string>,\n config: RequestConfig,\n _attempt: number,\n ): Promise<ApiResponse<T>> {\n const timeout = config.timeout ?? this.config.timeout ?? 30_000;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url.toString(), {\n method: config.method,\n headers,\n body: config.body !== undefined ? JSON.stringify(config.body) : undefined,\n signal: config.signal ?? controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle error responses\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = { message: response.statusText };\n }\n throw createErrorFromResponse(response.status, body, response.headers);\n }\n\n // Parse successful response\n let data: T;\n if (response.status === 204) {\n data = undefined as T;\n } else {\n data = (await response.json()) as T;\n }\n\n let result: ApiResponse<unknown> = {\n data,\n status: response.status,\n headers: response.headers,\n };\n\n // Run response interceptors\n for (const interceptor of this.responseInterceptors) {\n result = await interceptor(result);\n }\n\n return result as ApiResponse<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new TimeoutError({ duration: timeout });\n }\n\n if (error instanceof TypeError) {\n throw new NetworkError({ message: error.message });\n }\n\n throw error;\n }\n }\n}\n","// Auth Header Interceptor\n\nimport type { RequestInterceptor } from \"../types\";\n\nexport interface AuthInterceptorConfig {\n tokenProvider?: () => string | null;\n apiKey?: string;\n}\n\nexport function createAuthInterceptor(config: AuthInterceptorConfig): RequestInterceptor {\n return (request) => {\n if (request.skipAuth) return request;\n\n const headers = { ...request.headers };\n\n if (config.tokenProvider) {\n const token = config.tokenProvider();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n if (config.apiKey) {\n headers[\"x-api-key\"] = config.apiKey;\n }\n\n return { ...request, headers };\n };\n}\n","// Device Signal Header Interceptor\n\nimport type { IDeviceSignalCollector } from \"../../device/types\";\nimport type { RequestInterceptor } from \"../types\";\n\nexport function createDeviceSignalInterceptor(\n collector: IDeviceSignalCollector,\n): RequestInterceptor {\n return async (request) => {\n const signals = await collector.collect();\n\n // Skip if no signals collected (SSR)\n if (!signals.screen && !signals.timezone && !signals.platform) {\n return request;\n }\n\n const fingerprint = await collector.getFingerprint();\n\n const headers: Record<string, string> = {\n ...request.headers,\n \"x-device-screen\": signals.screen,\n \"x-device-timezone\": signals.timezone,\n \"x-device-platform\": signals.platform,\n \"x-device-language\": signals.language,\n \"x-device-color-depth\": signals.colorDepth,\n \"x-device-touch\": signals.touchSupport,\n \"x-device-fingerprint\": fingerprint,\n };\n\n return { ...request, headers };\n };\n}\n","// Auth Client Configuration v2.0\n\nimport type { ITokenStorage } from \"../storage/types\";\nimport type { LoginAlert } from \"./auth\";\n\nexport interface AuthConfig {\n // API Configuration\n apiKey?: string;\n baseUrl: string;\n timeout?: number;\n\n // Storage Configuration\n tokenStorageKey?: string;\n sessionStorageKey?: string;\n\n // Token Management\n autoRefreshToken?: boolean;\n refreshThreshold?: number;\n\n // v2.0: Device Signal Collection\n collectDeviceSignals?: boolean;\n\n // Callbacks\n onSessionExpired?: () => void;\n onTokenRefreshed?: (token: string) => void;\n onNewDeviceAlert?: (alert: LoginAlert) => void;\n\n // Platform-specific\n storage?: ITokenStorage;\n}\n\n// Storage key defaults\nexport const DEFAULT_TOKEN_STORAGE_KEY = \"atz_auth_token\";\nexport const DEFAULT_REFRESH_TOKEN_STORAGE_KEY = \"atz_refresh_token\";\nexport const DEFAULT_SESSION_STORAGE_KEY = \"atz_session\";\nexport const DEFAULT_LAST_LOGIN_METHOD_KEY = \"atz_last_login_method\";\n","// Authentication Service\n\nimport type { HttpClient } from \"../http/client\";\nimport type { ITokenStorage } from \"../storage/types\";\nimport type { LoginCredentials, LoginResponse, SignupData, SignupResponse } from \"../types/auth\";\nimport {\n DEFAULT_LAST_LOGIN_METHOD_KEY,\n DEFAULT_REFRESH_TOKEN_STORAGE_KEY,\n DEFAULT_TOKEN_STORAGE_KEY,\n} from \"../types/config\";\n\nexport class AuthService {\n private readonly httpClient: HttpClient;\n private readonly storage: ITokenStorage;\n private readonly tokenStorageKey: string;\n private readonly refreshTokenStorageKey: string;\n private readonly lastLoginMethodKey: string;\n\n constructor(\n httpClient: HttpClient,\n storage: ITokenStorage,\n options?: {\n tokenStorageKey?: string;\n refreshTokenStorageKey?: string;\n lastLoginMethodKey?: string;\n },\n ) {\n this.httpClient = httpClient;\n this.storage = storage;\n this.tokenStorageKey = options?.tokenStorageKey ?? DEFAULT_TOKEN_STORAGE_KEY;\n this.refreshTokenStorageKey =\n options?.refreshTokenStorageKey ?? DEFAULT_REFRESH_TOKEN_STORAGE_KEY;\n this.lastLoginMethodKey = options?.lastLoginMethodKey ?? DEFAULT_LAST_LOGIN_METHOD_KEY;\n }\n\n async login(credentials: LoginCredentials): Promise<LoginResponse> {\n const { data } = await this.httpClient.post<LoginResponse>(\"/auth/login\", credentials, {\n skipAuth: true,\n });\n\n await this.storeTokens(data.accessToken, data.refreshToken);\n await this.setLastLoginMethod(\"email\");\n\n return data;\n }\n\n async signup(data: SignupData): Promise<SignupResponse> {\n const { data: response } = await this.httpClient.post<SignupResponse>(\"/auth/signup\", data, {\n skipAuth: true,\n });\n\n await this.storeTokens(response.accessToken, response.refreshToken);\n await this.setLastLoginMethod(\"email\");\n\n return response;\n }\n\n async storeTokens(accessToken: string, refreshToken: string): Promise<void> {\n await this.storage.set(this.tokenStorageKey, accessToken);\n await this.storage.set(this.refreshTokenStorageKey, refreshToken);\n }\n\n async setLastLoginMethod(method: string): Promise<void> {\n await this.storage.set(this.lastLoginMethodKey, method);\n }\n}\n","// localStorage Adapter — SSR-safe wrapper\n\nimport type { ITokenStorage } from \"./types\";\n\nexport class LocalStorageAdapter implements ITokenStorage {\n async get(key: string): Promise<string | null> {\n if (typeof window === \"undefined\") return null;\n return window.localStorage.getItem(key);\n }\n\n async set(key: string, value: string): Promise<void> {\n if (typeof window === \"undefined\") return;\n window.localStorage.setItem(key, value);\n }\n\n async remove(key: string): Promise<void> {\n if (typeof window === \"undefined\") return;\n window.localStorage.removeItem(key);\n }\n}\n","// In-memory Token Storage — SSR-safe, default implementation\n\nimport type { ITokenStorage } from \"./types\";\n\nexport class MemoryStorage implements ITokenStorage {\n private store = new Map<string, string>();\n\n async get(key: string): Promise<string | null> {\n return this.store.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.store.set(key, value);\n }\n\n async remove(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n","// AuthClient — main entry point for @atzentis/auth-sdk\n\nimport { BrowserDeviceSignalCollector } from \"./device\";\nimport { HttpClient } from \"./http/client\";\nimport { createAuthInterceptor, createDeviceSignalInterceptor } from \"./http/interceptors\";\nimport { AuthService } from \"./services/auth\";\nimport { MemoryStorage } from \"./storage\";\nimport type { ITokenStorage } from \"./storage/types\";\nimport type { LoginCredentials, LoginResponse, SignupData, SignupResponse } from \"./types/auth\";\nimport type { AuthConfig } from \"./types/config\";\nimport { DEFAULT_REFRESH_TOKEN_STORAGE_KEY, DEFAULT_TOKEN_STORAGE_KEY } from \"./types/config\";\n\nconst RISK_ALERT_THRESHOLD = 30;\n\nexport class AuthClient {\n private readonly config: AuthConfig;\n private readonly httpClient: HttpClient;\n private readonly storage: ITokenStorage;\n private readonly authService: AuthService;\n\n constructor(config: AuthConfig) {\n this.config = config;\n this.storage = config.storage ?? new MemoryStorage();\n\n const tokenStorageKey = config.tokenStorageKey ?? DEFAULT_TOKEN_STORAGE_KEY;\n const refreshTokenStorageKey = config.tokenStorageKey\n ? `${config.tokenStorageKey}_refresh`\n : DEFAULT_REFRESH_TOKEN_STORAGE_KEY;\n\n this.httpClient = new HttpClient({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n });\n\n // Add auth interceptor\n const storage = this.storage;\n this.httpClient.addRequestInterceptor(\n createAuthInterceptor({\n tokenProvider: () => {\n // Synchronous access — MemoryStorage.get returns a promise but\n // the interceptor needs a sync value. We use a cached token value.\n return null; // Token injection handled by cached value below\n },\n apiKey: config.apiKey,\n }),\n );\n\n // Auth interceptor with async token access\n this.httpClient.addRequestInterceptor(async (request) => {\n if (request.skipAuth) return request;\n const token = await storage.get(tokenStorageKey);\n if (token) {\n return {\n ...request,\n headers: {\n ...request.headers,\n Authorization: `Bearer ${token}`,\n },\n };\n }\n return request;\n });\n\n // Add device signal interceptor if enabled\n if (config.collectDeviceSignals !== false) {\n const collector = new BrowserDeviceSignalCollector();\n this.httpClient.addRequestInterceptor(createDeviceSignalInterceptor(collector));\n }\n\n this.authService = new AuthService(this.httpClient, this.storage, {\n tokenStorageKey,\n refreshTokenStorageKey,\n });\n }\n\n async login(credentials: LoginCredentials): Promise<LoginResponse> {\n const response = await this.authService.login(credentials);\n this.handleLoginEvent(response);\n return response;\n }\n\n async signup(data: SignupData): Promise<SignupResponse> {\n return this.authService.signup(data);\n }\n\n private handleLoginEvent(response: LoginResponse): void {\n if (\n response.loginEvent &&\n response.loginEvent.riskScore >= RISK_ALERT_THRESHOLD &&\n this.config.onNewDeviceAlert\n ) {\n const event = response.loginEvent;\n this.config.onNewDeviceAlert({\n deviceName: event.deviceName,\n deviceType: event.deviceType,\n city: event.city,\n country: event.country,\n riskScore: event.riskScore,\n });\n }\n }\n}\n","// Auth SDK Error Codes v2.0\n\nexport enum AuthErrorCode {\n // Authentication\n InvalidCredentials = \"INVALID_CREDENTIALS\",\n EmailNotVerified = \"EMAIL_NOT_VERIFIED\",\n TwoFactorRequired = \"TWO_FACTOR_REQUIRED\",\n\n // Phone Auth (v2.0)\n InvalidPhoneNumber = \"INVALID_PHONE_NUMBER\",\n OTPExpired = \"OTP_EXPIRED\",\n OTPInvalid = \"OTP_INVALID\",\n OTPMaxAttempts = \"OTP_MAX_ATTEMPTS\",\n PhoneNumberInUse = \"PHONE_NUMBER_IN_USE\",\n FraudDetected = \"FRAUD_DETECTED\",\n\n // Username (v2.0)\n UsernameTaken = \"USERNAME_TAKEN\",\n UsernameInvalid = \"USERNAME_INVALID\",\n UsernameReserved = \"USERNAME_RESERVED\",\n\n // Device / Login Activity (v2.0)\n DeviceNotFound = \"DEVICE_NOT_FOUND\",\n LoginEventNotFound = \"LOGIN_EVENT_NOT_FOUND\",\n ReauthRequired = \"REAUTH_REQUIRED\",\n\n // Multi-session (v2.0)\n MaxSessionsExceeded = \"MAX_SESSIONS_EXCEEDED\",\n\n // CAPTCHA (v2.0)\n CaptchaRequired = \"CAPTCHA_REQUIRED\",\n CaptchaInvalid = \"CAPTCHA_INVALID\",\n\n // Breach (v2.0)\n PasswordBreached = \"PASSWORD_BREACHED\",\n\n // Session / Token\n SessionExpired = \"SESSION_EXPIRED\",\n TokenExpired = \"TOKEN_EXPIRED\",\n InvalidToken = \"INVALID_TOKEN\",\n\n // Authorization\n UnauthorizedRole = \"UNAUTHORIZED_ROLE\",\n OrganizationNotFound = \"ORGANIZATION_NOT_FOUND\",\n PermissionDenied = \"PERMISSION_DENIED\",\n\n // Rate Limiting & Network\n RateLimited = \"RATE_LIMITED\",\n NetworkError = \"NETWORK_ERROR\",\n Timeout = \"TIMEOUT\",\n\n // User Management\n UserNotFound = \"USER_NOT_FOUND\",\n UserAlreadyExists = \"USER_ALREADY_EXISTS\",\n InvalidEmail = \"INVALID_EMAIL\",\n WeakPassword = \"WEAK_PASSWORD\",\n\n // Organization\n OrganizationLimitExceeded = \"ORG_LIMIT_EXCEEDED\",\n MemberLimitExceeded = \"MEMBER_LIMIT_EXCEEDED\",\n\n // API Keys\n KeyNotFound = \"KEY_NOT_FOUND\",\n KeyRevoked = \"KEY_REVOKED\",\n KeyExpired = \"KEY_EXPIRED\",\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/device/browser-collector.ts","../src/errors/auth-error.ts","../src/errors/errors.ts","../src/errors/factory.ts","../src/http/rate-limit.ts","../src/http/retry.ts","../src/http/client.ts","../src/http/interceptors/auth.ts","../src/http/interceptors/device-signals.ts","../src/types/config.ts","../src/services/validators.ts","../src/services/auth.ts","../src/services/refresh.ts","../src/services/phone.ts","../src/services/session.ts","../src/storage/cookie-storage.ts","../src/storage/local-storage-adapter.ts","../src/storage/memory-storage.ts","../src/client.ts","../src/types/session.ts","../src/errors/codes.ts"],"names":["AuthErrorCode"],"mappings":"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","file":"index.js","sourcesContent":["// Browser Device Signal Collector — SSR-safe\n\nimport type { DeviceSignals, IDeviceSignalCollector } from \"./types\";\n\nconst EMPTY_SIGNALS: DeviceSignals = {\n screen: \"\",\n timezone: \"\",\n platform: \"\",\n language: \"\",\n colorDepth: \"\",\n touchSupport: \"\",\n};\n\nfunction simpleHash(input: string): string {\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash |= 0;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\nasync function sha256Hash(input: string): Promise<string> {\n try {\n if (typeof globalThis.crypto?.subtle?.digest === \"function\") {\n const encoder = new TextEncoder();\n const data = encoder.encode(input);\n const hashBuffer = await globalThis.crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n } catch {\n // Fallback below\n }\n return simpleHash(input);\n}\n\nexport class BrowserDeviceSignalCollector implements IDeviceSignalCollector {\n private cached: DeviceSignals | null = null;\n private cachedFingerprint: string | null = null;\n\n async collect(): Promise<DeviceSignals> {\n if (this.cached) return this.cached;\n\n if (typeof window === \"undefined\" || typeof navigator === \"undefined\") {\n this.cached = EMPTY_SIGNALS;\n return this.cached;\n }\n\n this.cached = {\n screen: `${screen.width}x${screen.height}`,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n platform: navigator.platform,\n language: navigator.language,\n colorDepth: String(screen.colorDepth),\n touchSupport: String(\"ontouchstart\" in window),\n };\n\n return this.cached;\n }\n\n async getFingerprint(): Promise<string> {\n if (this.cachedFingerprint) return this.cachedFingerprint;\n\n const signals = await this.collect();\n const raw = [\n signals.screen,\n signals.timezone,\n signals.platform,\n signals.language,\n signals.colorDepth,\n signals.touchSupport,\n ].join(\"|\");\n\n this.cachedFingerprint = await sha256Hash(raw);\n return this.cachedFingerprint;\n }\n}\n","// Base Auth Error\n\nimport type { AuthErrorCode } from \"./codes\";\n\nexport interface AuthErrorOptions {\n code: AuthErrorCode;\n message: string;\n statusCode: number;\n details?: Record<string, unknown>;\n requestId?: string;\n}\n\nexport class AuthError extends Error {\n readonly code: AuthErrorCode;\n readonly statusCode: number;\n readonly details?: Record<string, unknown>;\n readonly requestId?: string;\n\n constructor(options: AuthErrorOptions) {\n super(options.message);\n this.name = \"AuthError\";\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.details = options.details;\n this.requestId = options.requestId;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n requestId: this.requestId,\n };\n }\n}\n","// Error Subclasses\n\nimport { AuthError, type AuthErrorOptions } from \"./auth-error\";\nimport type { AuthErrorCode } from \"./codes\";\n\ntype SubclassOptions = Omit<AuthErrorOptions, \"statusCode\"> & { statusCode?: number };\n\nexport class ValidationError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 400 });\n this.name = \"ValidationError\";\n }\n}\n\nexport class AuthenticationError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 401 });\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class ForbiddenError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 403 });\n this.name = \"ForbiddenError\";\n }\n}\n\nexport class NotFoundError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 404 });\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ConflictError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 409 });\n this.name = \"ConflictError\";\n }\n}\n\nexport class UnprocessableError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 422 });\n this.name = \"UnprocessableError\";\n }\n}\n\nexport interface RateLimitErrorOptions extends SubclassOptions {\n retryAfter: number;\n}\n\nexport class RateLimitError extends AuthError {\n readonly retryAfter: number;\n\n constructor(options: RateLimitErrorOptions) {\n super({ ...options, statusCode: options.statusCode ?? 429 });\n this.name = \"RateLimitError\";\n this.retryAfter = options.retryAfter;\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), retryAfter: this.retryAfter };\n }\n}\n\nexport class ServerError extends AuthError {\n constructor(options: SubclassOptions) {\n super({ ...options, statusCode: options.statusCode ?? 500 });\n this.name = \"ServerError\";\n }\n}\n\nexport interface NetworkErrorOptions {\n message: string;\n code?: AuthErrorCode;\n details?: Record<string, unknown>;\n requestId?: string;\n}\n\nexport class NetworkError extends AuthError {\n constructor(options: NetworkErrorOptions) {\n super({\n code: options.code ?? (\"NETWORK_ERROR\" as AuthErrorCode),\n message: options.message,\n statusCode: 0,\n details: options.details,\n requestId: options.requestId,\n });\n this.name = \"NetworkError\";\n }\n}\n\nexport interface TimeoutErrorOptions {\n duration: number;\n message?: string;\n requestId?: string;\n}\n\nexport class TimeoutError extends AuthError {\n readonly duration: number;\n\n constructor(options: TimeoutErrorOptions) {\n super({\n code: \"TIMEOUT\" as AuthErrorCode,\n message: options.message ?? `Request timed out after ${options.duration}ms`,\n statusCode: 0,\n requestId: options.requestId,\n });\n this.name = \"TimeoutError\";\n this.duration = options.duration;\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), duration: this.duration };\n }\n}\n","// Error Factory — maps HTTP responses to typed errors\n\nimport { AuthError } from \"./auth-error\";\nimport type { AuthErrorCode } from \"./codes\";\nimport {\n AuthenticationError,\n ConflictError,\n ForbiddenError,\n NotFoundError,\n RateLimitError,\n ServerError,\n UnprocessableError,\n ValidationError,\n} from \"./errors\";\n\ninterface ErrorBody {\n code?: string;\n message?: string;\n details?: Record<string, unknown>;\n}\n\nfunction parseBody(body: unknown): ErrorBody {\n if (body && typeof body === \"object\" && \"message\" in body) {\n const obj = body as Record<string, unknown>;\n return {\n code: typeof obj.code === \"string\" ? obj.code : undefined,\n message: typeof obj.message === \"string\" ? obj.message : \"Unknown error\",\n details:\n typeof obj.details === \"object\" && obj.details !== null\n ? (obj.details as Record<string, unknown>)\n : undefined,\n };\n }\n return { message: \"Unknown error\" };\n}\n\nexport function parseRetryAfterHeader(header: string | null): number {\n if (!header) return 60;\n\n const seconds = Number(header);\n if (!Number.isNaN(seconds)) return seconds;\n\n const date = new Date(header);\n if (!Number.isNaN(date.getTime())) {\n return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1000));\n }\n\n return 60;\n}\n\nexport function createErrorFromResponse(\n status: number,\n body: unknown,\n headers: Headers,\n): AuthError {\n const parsed = parseBody(body);\n const requestId = headers.get(\"x-request-id\") ?? undefined;\n const code = (parsed.code ?? \"NETWORK_ERROR\") as AuthErrorCode;\n const message = parsed.message ?? `HTTP ${status}`;\n const details = parsed.details;\n const base = { code, message, details, requestId };\n\n switch (true) {\n case status === 400:\n return new ValidationError(base);\n case status === 401:\n return new AuthenticationError(base);\n case status === 403:\n return new ForbiddenError(base);\n case status === 404:\n return new NotFoundError(base);\n case status === 409:\n return new ConflictError(base);\n case status === 422:\n return new UnprocessableError(base);\n case status === 429: {\n const retryAfter = parseRetryAfterHeader(headers.get(\"retry-after\"));\n return new RateLimitError({ ...base, retryAfter });\n }\n case status >= 500 && status < 600:\n return new ServerError(base);\n default:\n return new AuthError({ ...base, statusCode: status });\n }\n}\n","// Rate Limit Handling\n\nimport type { RateLimitConfig } from \"./types\";\n\nexport const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig = {\n autoRetry: true,\n maxRetryAfter: 60,\n};\n\nexport function mergeRateLimitConfig(config?: Partial<RateLimitConfig>): RateLimitConfig {\n return { ...DEFAULT_RATE_LIMIT_CONFIG, ...config };\n}\n\nexport function parseRetryAfter(header: string | null): number {\n if (!header) return 60;\n\n const seconds = Number(header);\n if (!Number.isNaN(seconds)) return seconds;\n\n const date = new Date(header);\n if (!Number.isNaN(date.getTime())) {\n return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1000));\n }\n\n return 60;\n}\n","// Retry Logic with Exponential Backoff\n\nimport type { RetryConfig } from \"./types\";\n\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n factor: 2,\n jitter: true,\n retryableStatuses: [500, 502, 503, 504],\n retryPost: false,\n};\n\nexport function mergeRetryConfig(config?: Partial<RetryConfig>): RetryConfig {\n return { ...DEFAULT_RETRY_CONFIG, ...config };\n}\n\nexport function shouldRetry(\n error: unknown,\n attempt: number,\n method: string,\n config: RetryConfig,\n): boolean {\n if (attempt >= config.maxRetries) return false;\n if (method === \"POST\" && !config.retryPost) return false;\n\n // Network error (TypeError from fetch)\n if (error instanceof TypeError) return true;\n\n // Check statusCode on error objects\n if (error && typeof error === \"object\" && \"statusCode\" in error) {\n const statusCode = (error as { statusCode: number }).statusCode;\n return config.retryableStatuses.includes(statusCode);\n }\n\n return false;\n}\n\nexport function calculateDelay(attempt: number, config: RetryConfig): number {\n const exponential = config.baseDelay * config.factor ** attempt;\n const delay = Math.min(exponential, config.maxDelay);\n\n if (!config.jitter) return delay;\n\n return Math.round(delay * Math.random());\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// HTTP Client — zero-dependency fetch wrapper\n\nimport { NetworkError, RateLimitError, TimeoutError } from \"../errors/errors\";\nimport { createErrorFromResponse } from \"../errors/factory\";\nimport { mergeRateLimitConfig } from \"./rate-limit\";\nimport { calculateDelay, mergeRetryConfig, shouldRetry, sleep } from \"./retry\";\nimport type {\n ApiResponse,\n ErrorInterceptor,\n HttpClientConfig,\n RateLimitConfig,\n RequestConfig,\n RequestInterceptor,\n ResponseInterceptor,\n RetryConfig,\n} from \"./types\";\n\nexport class HttpClient {\n private readonly config: HttpClientConfig;\n private readonly retryConfig: RetryConfig;\n private readonly rateLimitConfig: RateLimitConfig;\n private requestInterceptors: RequestInterceptor[] = [];\n private responseInterceptors: ResponseInterceptor[] = [];\n private errorInterceptors: ErrorInterceptor[] = [];\n\n constructor(config: HttpClientConfig) {\n this.config = config;\n this.retryConfig = mergeRetryConfig(config.retry);\n this.rateLimitConfig = mergeRateLimitConfig(config.rateLimit);\n }\n\n // --- Public HTTP Methods ---\n\n async get<T>(\n path: string,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"GET\", path });\n }\n\n async post<T>(\n path: string,\n body?: unknown,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"POST\", path, body });\n }\n\n async put<T>(\n path: string,\n body?: unknown,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"PUT\", path, body });\n }\n\n async patch<T>(\n path: string,\n body?: unknown,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"PATCH\", path, body });\n }\n\n async delete<T>(\n path: string,\n config?: Partial<Omit<RequestConfig, \"method\" | \"path\" | \"body\">>,\n ): Promise<ApiResponse<T>> {\n return this.request<T>({ ...config, method: \"DELETE\", path });\n }\n\n getBaseUrl(): string {\n return this.config.baseUrl;\n }\n\n // --- Interceptor Management ---\n\n addRequestInterceptor(fn: RequestInterceptor): void {\n this.requestInterceptors.push(fn);\n }\n\n removeRequestInterceptor(fn: RequestInterceptor): void {\n this.requestInterceptors = this.requestInterceptors.filter((i) => i !== fn);\n }\n\n addResponseInterceptor(fn: ResponseInterceptor): void {\n this.responseInterceptors.push(fn);\n }\n\n removeResponseInterceptor(fn: ResponseInterceptor): void {\n this.responseInterceptors = this.responseInterceptors.filter((i) => i !== fn);\n }\n\n addErrorInterceptor(fn: ErrorInterceptor): void {\n this.errorInterceptors.push(fn);\n }\n\n removeErrorInterceptor(fn: ErrorInterceptor): void {\n this.errorInterceptors = this.errorInterceptors.filter((i) => i !== fn);\n }\n\n // --- Internal ---\n\n private async request<T>(initialConfig: RequestConfig): Promise<ApiResponse<T>> {\n // Run request interceptors\n let config = { ...initialConfig };\n for (const interceptor of this.requestInterceptors) {\n config = await interceptor(config);\n }\n\n // Build URL\n const url = new URL(config.path, this.config.baseUrl);\n if (config.params) {\n for (const [key, value] of Object.entries(config.params)) {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n // Build headers\n const headers: Record<string, string> = {\n ...this.config.headers,\n ...config.headers,\n };\n if (config.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n // Retry loop\n const maxAttempts = this.retryConfig.maxRetries + 1;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await this.executeFetch<T>(url, headers, config, attempt);\n } catch (error) {\n // Run error interceptors\n let processedError = error;\n for (const interceptor of this.errorInterceptors) {\n processedError = await interceptor(processedError);\n }\n\n // Rate limit: handle 429 separately from general retry\n if (processedError instanceof RateLimitError) {\n if (\n this.rateLimitConfig.autoRetry &&\n processedError.retryAfter <= this.rateLimitConfig.maxRetryAfter &&\n attempt === 0\n ) {\n await sleep(processedError.retryAfter * 1000);\n continue;\n }\n throw processedError;\n }\n\n // General retry\n if (shouldRetry(processedError, attempt, config.method, this.retryConfig)) {\n const delay = calculateDelay(attempt, this.retryConfig);\n await sleep(delay);\n continue;\n }\n\n throw processedError;\n }\n }\n\n // Should not reach here, but satisfy TypeScript\n throw new NetworkError({ message: \"Max retries exceeded\" });\n }\n\n private async executeFetch<T>(\n url: URL,\n headers: Record<string, string>,\n config: RequestConfig,\n _attempt: number,\n ): Promise<ApiResponse<T>> {\n const timeout = config.timeout ?? this.config.timeout ?? 30_000;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url.toString(), {\n method: config.method,\n headers,\n body: config.body !== undefined ? JSON.stringify(config.body) : undefined,\n signal: config.signal ?? controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle error responses\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = { message: response.statusText };\n }\n throw createErrorFromResponse(response.status, body, response.headers);\n }\n\n // Parse successful response\n let data: T;\n if (response.status === 204) {\n data = undefined as T;\n } else {\n data = (await response.json()) as T;\n }\n\n let result: ApiResponse<unknown> = {\n data,\n status: response.status,\n headers: response.headers,\n };\n\n // Run response interceptors\n for (const interceptor of this.responseInterceptors) {\n result = await interceptor(result);\n }\n\n return result as ApiResponse<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new TimeoutError({ duration: timeout });\n }\n\n if (error instanceof TypeError) {\n throw new NetworkError({ message: error.message });\n }\n\n throw error;\n }\n }\n}\n","// Auth Header Interceptor\n\nimport type { RequestInterceptor } from \"../types\";\n\nexport interface AuthInterceptorConfig {\n tokenProvider?: () => string | null;\n apiKey?: string;\n}\n\nexport function createAuthInterceptor(config: AuthInterceptorConfig): RequestInterceptor {\n return (request) => {\n if (request.skipAuth) return request;\n\n const headers = { ...request.headers };\n\n if (config.tokenProvider) {\n const token = config.tokenProvider();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n if (config.apiKey) {\n headers[\"x-api-key\"] = config.apiKey;\n }\n\n return { ...request, headers };\n };\n}\n","// Device Signal Header Interceptor\n\nimport type { IDeviceSignalCollector } from \"../../device/types\";\nimport type { RequestInterceptor } from \"../types\";\n\nexport function createDeviceSignalInterceptor(\n collector: IDeviceSignalCollector,\n): RequestInterceptor {\n return async (request) => {\n const signals = await collector.collect();\n\n // Skip if no signals collected (SSR)\n if (!signals.screen && !signals.timezone && !signals.platform) {\n return request;\n }\n\n const fingerprint = await collector.getFingerprint();\n\n const headers: Record<string, string> = {\n ...request.headers,\n \"x-device-screen\": signals.screen,\n \"x-device-timezone\": signals.timezone,\n \"x-device-platform\": signals.platform,\n \"x-device-language\": signals.language,\n \"x-device-color-depth\": signals.colorDepth,\n \"x-device-touch\": signals.touchSupport,\n \"x-device-fingerprint\": fingerprint,\n };\n\n return { ...request, headers };\n };\n}\n","// Auth Client Configuration v2.0\n\nimport type { ITokenStorage } from \"../storage/types\";\nimport type { LoginAlert } from \"./auth\";\n\nexport interface AuthConfig {\n // API Configuration\n apiKey?: string;\n baseUrl: string;\n timeout?: number;\n\n // Storage Configuration\n tokenStorageKey?: string;\n sessionStorageKey?: string;\n\n // Token Management\n autoRefreshToken?: boolean;\n refreshThreshold?: number;\n\n // v2.0: Device Signal Collection\n collectDeviceSignals?: boolean;\n\n // Callbacks\n onSessionExpired?: () => void;\n onTokenRefreshed?: (token: string) => void;\n onNewDeviceAlert?: (alert: LoginAlert) => void;\n\n // Platform-specific\n storage?: ITokenStorage;\n}\n\n// Storage key defaults\nexport const DEFAULT_TOKEN_STORAGE_KEY = \"atz_auth_token\";\nexport const DEFAULT_REFRESH_TOKEN_STORAGE_KEY = \"atz_refresh_token\";\nexport const DEFAULT_SESSION_STORAGE_KEY = \"atz_session\";\nexport const DEFAULT_LAST_LOGIN_METHOD_KEY = \"atz_last_login_method\";\n","// Client-side validation helpers\n\nimport { ValidationError } from \"../errors/errors\";\n\nconst USERNAME_MIN_LENGTH = 3;\nconst USERNAME_MAX_LENGTH = 20;\nconst USERNAME_PATTERN = /^[a-z0-9]+$/;\n\nconst PHONE_E164_PATTERN = /^\\+\\d{10,15}$/;\nconst SUPPORTED_COUNTRY_CODES = [\"+30\", \"+49\"];\n\nexport function validateUsername(username: string): void {\n if (username.length < USERNAME_MIN_LENGTH) {\n throw new ValidationError({\n code: \"USERNAME_INVALID\" as never,\n message: `Username must be at least ${USERNAME_MIN_LENGTH} characters`,\n });\n }\n if (username.length > USERNAME_MAX_LENGTH) {\n throw new ValidationError({\n code: \"USERNAME_INVALID\" as never,\n message: `Username must be at most ${USERNAME_MAX_LENGTH} characters`,\n });\n }\n if (!USERNAME_PATTERN.test(username)) {\n throw new ValidationError({\n code: \"USERNAME_INVALID\" as never,\n message: \"Username must contain only lowercase letters and numbers\",\n });\n }\n}\n\nexport function validatePhoneNumber(phoneNumber: string): void {\n if (!PHONE_E164_PATTERN.test(phoneNumber)) {\n throw new ValidationError({\n code: \"INVALID_PHONE_NUMBER\" as never,\n message: \"Phone number must be in E.164 format (e.g. +301234567890)\",\n });\n }\n const hasValidCountryCode = SUPPORTED_COUNTRY_CODES.some((code) => phoneNumber.startsWith(code));\n if (!hasValidCountryCode) {\n throw new ValidationError({\n code: \"INVALID_PHONE_NUMBER\" as never,\n message: `Phone number must start with one of: ${SUPPORTED_COUNTRY_CODES.join(\", \")}`,\n });\n }\n}\n","// Authentication Service\n\nimport type { HttpClient } from \"../http/client\";\nimport type { ITokenStorage } from \"../storage/types\";\nimport type {\n LoginCredentials,\n LoginResponse,\n RefreshTokenResponse,\n RequestPasswordResetRequest,\n ResetPasswordRequest,\n ResetPasswordResponse,\n SendMagicLinkRequest,\n SendVerificationEmailRequest,\n SignupData,\n SignupResponse,\n UsernameLoginCredentials,\n VerifyEmailRequest,\n VerifyEmailResponse,\n VerifyMagicLinkRequest,\n} from \"../types/auth\";\nimport {\n DEFAULT_LAST_LOGIN_METHOD_KEY,\n DEFAULT_REFRESH_TOKEN_STORAGE_KEY,\n DEFAULT_SESSION_STORAGE_KEY,\n DEFAULT_TOKEN_STORAGE_KEY,\n} from \"../types/config\";\nimport { validateUsername } from \"./validators\";\n\nexport class AuthService {\n private readonly httpClient: HttpClient;\n private readonly storage: ITokenStorage;\n private readonly tokenStorageKey: string;\n private readonly refreshTokenStorageKey: string;\n private readonly sessionStorageKey: string;\n private readonly lastLoginMethodKey: string;\n private refreshPromise: Promise<RefreshTokenResponse> | null = null;\n\n constructor(\n httpClient: HttpClient,\n storage: ITokenStorage,\n options?: {\n tokenStorageKey?: string;\n refreshTokenStorageKey?: string;\n sessionStorageKey?: string;\n lastLoginMethodKey?: string;\n },\n ) {\n this.httpClient = httpClient;\n this.storage = storage;\n this.tokenStorageKey = options?.tokenStorageKey ?? DEFAULT_TOKEN_STORAGE_KEY;\n this.refreshTokenStorageKey =\n options?.refreshTokenStorageKey ?? DEFAULT_REFRESH_TOKEN_STORAGE_KEY;\n this.sessionStorageKey = options?.sessionStorageKey ?? DEFAULT_SESSION_STORAGE_KEY;\n this.lastLoginMethodKey = options?.lastLoginMethodKey ?? DEFAULT_LAST_LOGIN_METHOD_KEY;\n }\n\n // --- Email/Password Login & Signup (T02-001) ---\n\n async login(credentials: LoginCredentials): Promise<LoginResponse> {\n const { data } = await this.httpClient.post<LoginResponse>(\"/auth/login\", credentials, {\n skipAuth: true,\n });\n\n await this.storeTokens(data.accessToken, data.refreshToken);\n await this.setLastLoginMethod(\"email\");\n\n return data;\n }\n\n async signup(data: SignupData): Promise<SignupResponse> {\n const { data: response } = await this.httpClient.post<SignupResponse>(\"/auth/signup\", data, {\n skipAuth: true,\n });\n\n await this.storeTokens(response.accessToken, response.refreshToken);\n await this.setLastLoginMethod(\"email\");\n\n return response;\n }\n\n // --- Username Login (T02-002) ---\n\n async loginWithUsername(credentials: UsernameLoginCredentials): Promise<LoginResponse> {\n validateUsername(credentials.username);\n\n const { data } = await this.httpClient.post<LoginResponse>(\n \"/auth/login/username\",\n credentials,\n { skipAuth: true },\n );\n\n await this.storeTokens(data.accessToken, data.refreshToken);\n await this.setLastLoginMethod(\"username\");\n\n return data;\n }\n\n async isUsernameAvailable(username: string): Promise<boolean> {\n validateUsername(username);\n\n const { data } = await this.httpClient.get<{ available: boolean }>(\"/auth/username/available\", {\n params: { username },\n });\n\n return data.available;\n }\n\n // --- OAuth (T02-004) ---\n\n getOAuthUrl(request: {\n provider: string;\n redirectUri: string;\n state: string;\n scopes?: string[];\n }): string {\n const baseUrl = this.httpClient.getBaseUrl();\n const params = new URLSearchParams({\n provider: request.provider,\n redirect_uri: request.redirectUri,\n state: request.state,\n });\n if (request.scopes?.length) {\n params.set(\"scopes\", request.scopes.join(\",\"));\n }\n return `${baseUrl}/auth/oauth/authorize?${params.toString()}`;\n }\n\n async verifyOAuthCode(request: {\n provider: string;\n code: string;\n redirectUri: string;\n }): Promise<LoginResponse> {\n const { data } = await this.httpClient.post<LoginResponse>(\"/auth/oauth/verify\", request, {\n skipAuth: true,\n });\n\n await this.storeTokens(data.accessToken, data.refreshToken);\n await this.setLastLoginMethod(\"oauth\");\n\n return data;\n }\n\n // --- Magic Link (T02-005) ---\n\n async sendMagicLink(request: SendMagicLinkRequest): Promise<void> {\n await this.httpClient.post(\"/auth/magic-link/send\", request, { skipAuth: true });\n }\n\n async verifyMagicLink(request: VerifyMagicLinkRequest): Promise<LoginResponse> {\n const { data } = await this.httpClient.post<LoginResponse>(\"/auth/magic-link/verify\", request, {\n skipAuth: true,\n });\n\n await this.storeTokens(data.accessToken, data.refreshToken);\n await this.setLastLoginMethod(\"magic_link\");\n\n return data;\n }\n\n // --- Email Verification (T02-006) ---\n\n async sendVerificationEmail(request: SendVerificationEmailRequest): Promise<void> {\n await this.httpClient.post(\"/auth/email/send-verification\", request);\n }\n\n async verifyEmail(request: VerifyEmailRequest): Promise<VerifyEmailResponse> {\n const { data } = await this.httpClient.post<VerifyEmailResponse>(\n \"/auth/email/verify\",\n request,\n { skipAuth: true },\n );\n return data;\n }\n\n // --- Password Reset (T02-007) ---\n\n async requestPasswordReset(request: RequestPasswordResetRequest): Promise<void> {\n await this.httpClient.post(\"/auth/password/reset-request\", request, { skipAuth: true });\n }\n\n async resetPassword(request: ResetPasswordRequest): Promise<ResetPasswordResponse> {\n const { data } = await this.httpClient.post<ResetPasswordResponse>(\n \"/auth/password/reset\",\n request,\n { skipAuth: true },\n );\n return data;\n }\n\n // --- Token Management (T02-009) ---\n\n async getAccessToken(): Promise<string | null> {\n return this.storage.get(this.tokenStorageKey);\n }\n\n async refreshToken(): Promise<RefreshTokenResponse> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.executeRefresh();\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n async isAuthenticated(): Promise<boolean> {\n const token = await this.storage.get(this.tokenStorageKey);\n if (!token) return false;\n\n const decoded = decodeJwtPayload(token);\n if (!decoded) return false;\n\n return decoded.exp * 1000 > Date.now();\n }\n\n async getLastLoginMethod(): Promise<string | null> {\n return this.storage.get(this.lastLoginMethodKey);\n }\n\n // --- Logout (T02-010) ---\n\n async logout(): Promise<void> {\n try {\n await this.httpClient.post(\"/auth/logout\", {});\n } catch {\n // Fire-and-forget: always clear tokens even if API call fails\n }\n await this.clearTokens();\n }\n\n async logoutAllDevices(): Promise<void> {\n try {\n await this.httpClient.post(\"/auth/logout/all\", {});\n } catch {\n // Fire-and-forget: always clear tokens even if API call fails\n }\n await this.clearTokens();\n }\n\n // --- Storage Helpers ---\n\n async storeTokens(accessToken: string, refreshToken: string): Promise<void> {\n await this.storage.set(this.tokenStorageKey, accessToken);\n await this.storage.set(this.refreshTokenStorageKey, refreshToken);\n }\n\n async setLastLoginMethod(method: string): Promise<void> {\n await this.storage.set(this.lastLoginMethodKey, method);\n }\n\n async clearTokens(): Promise<void> {\n await this.storage.remove(this.tokenStorageKey);\n await this.storage.remove(this.refreshTokenStorageKey);\n await this.storage.remove(this.sessionStorageKey);\n await this.storage.remove(this.lastLoginMethodKey);\n }\n\n // --- Private ---\n\n private async executeRefresh(): Promise<RefreshTokenResponse> {\n const currentRefreshToken = await this.storage.get(this.refreshTokenStorageKey);\n const { data } = await this.httpClient.post<RefreshTokenResponse>(\"/auth/token/refresh\", {\n refreshToken: currentRefreshToken,\n });\n await this.storeTokens(data.accessToken, data.refreshToken);\n return data;\n }\n}\n\n// --- JWT Decode Utility ---\n\nexport function decodeJwtPayload(token: string): {\n sub: string;\n email: string;\n name: string;\n exp: number;\n iat: number;\n org?: string;\n roles?: string[];\n} | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return null;\n\n const payload = parts[1];\n // Base64url to base64\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n // Pad if needed\n const padded = base64 + \"=\".repeat((4 - (base64.length % 4)) % 4);\n const decoded = atob(padded);\n return JSON.parse(decoded);\n } catch {\n return null;\n }\n}\n","// Background Token Refresh — automatic token refresh before expiration\n\nexport class BackgroundRefresh {\n private timerId: ReturnType<typeof setTimeout> | null = null;\n private retryTimerId: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private readonly refreshFn: () => Promise<{\n accessToken: string;\n expiresIn: number;\n }>,\n private readonly threshold: number,\n private readonly callbacks: {\n onTokenRefreshed?: (token: string) => void;\n onSessionExpired?: () => void;\n } = {},\n ) {}\n\n start(expiresIn: number): void {\n if (typeof setTimeout === \"undefined\") return;\n\n this.stop();\n\n const delayMs = (expiresIn - this.threshold) * 1000;\n\n if (delayMs <= 0) {\n this.executeRefresh();\n return;\n }\n\n this.timerId = setTimeout(() => {\n this.executeRefresh();\n }, delayMs);\n }\n\n stop(): void {\n if (this.timerId !== null) {\n clearTimeout(this.timerId);\n this.timerId = null;\n }\n if (this.retryTimerId !== null) {\n clearTimeout(this.retryTimerId);\n this.retryTimerId = null;\n }\n }\n\n isRunning(): boolean {\n return this.timerId !== null;\n }\n\n private async executeRefresh(): Promise<void> {\n try {\n const result = await this.refreshFn();\n this.callbacks.onTokenRefreshed?.(result.accessToken);\n this.start(result.expiresIn);\n } catch {\n this.timerId = null;\n this.retryTimerId = setTimeout(async () => {\n this.retryTimerId = null;\n try {\n const result = await this.refreshFn();\n this.callbacks.onTokenRefreshed?.(result.accessToken);\n this.start(result.expiresIn);\n } catch {\n this.callbacks.onSessionExpired?.();\n }\n }, 5000);\n }\n }\n}\n","// Phone Authentication Service (v2.0)\n\nimport type { HttpClient } from \"../http/client\";\nimport type { LoginResponse } from \"../types/auth\";\nimport type {\n PhoneSignInRequest,\n SendOTPRequest,\n SendOTPResponse,\n VerifyOTPRequest,\n VerifyOTPResponse,\n} from \"../types/phone\";\nimport { validatePhoneNumber } from \"./validators\";\n\nexport class PhoneService {\n private readonly httpClient: HttpClient;\n private readonly storeTokensFn: (accessToken: string, refreshToken: string) => Promise<void>;\n private readonly setLastLoginMethodFn: (method: string) => Promise<void>;\n\n constructor(\n httpClient: HttpClient,\n storeTokens: (accessToken: string, refreshToken: string) => Promise<void>,\n setLastLoginMethod: (method: string) => Promise<void>,\n ) {\n this.httpClient = httpClient;\n this.storeTokensFn = storeTokens;\n this.setLastLoginMethodFn = setLastLoginMethod;\n }\n\n async sendOTP(request: SendOTPRequest): Promise<SendOTPResponse> {\n validatePhoneNumber(request.phoneNumber);\n\n const { data } = await this.httpClient.post<SendOTPResponse>(\"/auth/phone/send-otp\", request, {\n skipAuth: true,\n });\n return data;\n }\n\n async verify(request: VerifyOTPRequest): Promise<VerifyOTPResponse> {\n validatePhoneNumber(request.phoneNumber);\n\n const { data } = await this.httpClient.post<VerifyOTPResponse>(\"/auth/phone/verify\", request, {\n skipAuth: true,\n });\n\n await this.storeTokensFn(data.accessToken, data.refreshToken);\n await this.setLastLoginMethodFn(\"phone\");\n\n return data;\n }\n\n async signIn(request: PhoneSignInRequest): Promise<LoginResponse> {\n validatePhoneNumber(request.phoneNumber);\n\n const { data } = await this.httpClient.post<LoginResponse>(\"/auth/phone/sign-in\", request, {\n skipAuth: true,\n });\n\n await this.storeTokensFn(data.accessToken, data.refreshToken);\n await this.setLastLoginMethodFn(\"phone\");\n\n return data;\n }\n}\n","// Session Service — session CRUD, multi-session, device summary\n\nimport type { HttpClient } from \"../http/client\";\nimport type {\n DeviceSession,\n DeviceSummary,\n ListSessionsRequest,\n ListSessionsResponse,\n RevokeAllSessionsOptions,\n RevokeAllSessionsResponse,\n Session,\n SetActiveSessionRequest,\n SetActiveSessionResponse,\n} from \"../types/session\";\n\nexport class SessionService {\n private readonly httpClient: HttpClient;\n private readonly storeTokens: (accessToken: string, refreshToken: string) => Promise<void>;\n\n constructor(\n httpClient: HttpClient,\n storeTokens: (accessToken: string, refreshToken: string) => Promise<void>,\n ) {\n this.httpClient = httpClient;\n this.storeTokens = storeTokens;\n }\n\n // --- Session CRUD (T03-001) ---\n\n async getCurrent(): Promise<Session> {\n const { data } = await this.httpClient.get<Session>(\"/auth/sessions/current\");\n return data;\n }\n\n async list(options?: ListSessionsRequest): Promise<ListSessionsResponse> {\n const params: Record<string, string | number> = {};\n if (options?.limit !== undefined) params.limit = options.limit;\n if (options?.offset !== undefined) params.offset = options.offset;\n\n const { data } = await this.httpClient.get<ListSessionsResponse>(\"/auth/sessions\", { params });\n return data;\n }\n\n async revoke(sessionId: string): Promise<void> {\n await this.httpClient.delete(`/auth/sessions/${sessionId}`);\n }\n\n // --- Revoke All (T03-002) ---\n\n async revokeAll(options?: RevokeAllSessionsOptions): Promise<RevokeAllSessionsResponse> {\n const { data } = await this.httpClient.post<RevokeAllSessionsResponse>(\n \"/auth/sessions/revoke-all\",\n { exceptCurrent: options?.exceptCurrent ?? true },\n );\n return data;\n }\n\n // --- Multi-Session (T03-003, T03-004) ---\n\n async listDeviceSessions(): Promise<DeviceSession[]> {\n const { data } = await this.httpClient.get<DeviceSession[]>(\"/auth/sessions/device\");\n return data;\n }\n\n async setActive(request: SetActiveSessionRequest): Promise<SetActiveSessionResponse> {\n const { data } = await this.httpClient.post<SetActiveSessionResponse>(\n \"/auth/sessions/set-active\",\n request,\n );\n await this.storeTokens(data.accessToken, data.refreshToken);\n return data;\n }\n\n async revokeDeviceSession(request: {\n sessionToken: string;\n }): Promise<void> {\n await this.httpClient.delete(`/auth/sessions/device/${request.sessionToken}`);\n }\n\n // --- Device Summary (T03-007) ---\n\n async getCurrentDevice(): Promise<DeviceSummary | null> {\n const session = await this.getCurrent();\n return session.device ?? null;\n }\n}\n","// Cookie Storage Adapter — document.cookie wrapper with options\n\nimport type { ITokenStorage } from \"./types\";\n\nexport interface CookieStorageOptions {\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n domain?: string;\n path?: string;\n maxAge?: number;\n}\n\nexport class CookieStorage implements ITokenStorage {\n private readonly secure: boolean;\n private readonly sameSite: \"strict\" | \"lax\" | \"none\";\n private readonly domain?: string;\n private readonly path: string;\n private readonly maxAge?: number;\n\n constructor(options?: CookieStorageOptions) {\n this.secure = options?.secure ?? true;\n this.sameSite = options?.sameSite ?? \"lax\";\n this.domain = options?.domain;\n this.path = options?.path ?? \"/\";\n this.maxAge = options?.maxAge;\n }\n\n async get(key: string): Promise<string | null> {\n if (typeof document === \"undefined\") return null;\n\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [cookieKey, ...cookieValueParts] = cookie.trim().split(\"=\");\n if (cookieKey === key) {\n const value = cookieValueParts.join(\"=\");\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n }\n }\n return null;\n }\n\n async set(key: string, value: string): Promise<void> {\n if (typeof document === \"undefined\") return;\n\n let cookie = `${key}=${encodeURIComponent(value)}`;\n cookie += `; path=${this.path}`;\n cookie += `; SameSite=${capitalize(this.sameSite)}`;\n\n if (this.secure) {\n cookie += \"; Secure\";\n }\n if (this.domain) {\n cookie += `; Domain=${this.domain}`;\n }\n if (this.maxAge !== undefined) {\n cookie += `; Max-Age=${this.maxAge}`;\n }\n\n document.cookie = cookie;\n }\n\n async remove(key: string): Promise<void> {\n if (typeof document === \"undefined\") return;\n\n let cookie = `${key}=; path=${this.path}; Max-Age=0`;\n if (this.domain) {\n cookie += `; Domain=${this.domain}`;\n }\n document.cookie = cookie;\n }\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","// localStorage Adapter — SSR-safe wrapper\n\nimport type { ITokenStorage } from \"./types\";\n\nexport class LocalStorageAdapter implements ITokenStorage {\n async get(key: string): Promise<string | null> {\n if (typeof window === \"undefined\") return null;\n return window.localStorage.getItem(key);\n }\n\n async set(key: string, value: string): Promise<void> {\n if (typeof window === \"undefined\") return;\n window.localStorage.setItem(key, value);\n }\n\n async remove(key: string): Promise<void> {\n if (typeof window === \"undefined\") return;\n window.localStorage.removeItem(key);\n }\n}\n","// In-memory Token Storage — SSR-safe, default implementation\n\nimport type { ITokenStorage } from \"./types\";\n\nexport class MemoryStorage implements ITokenStorage {\n private store = new Map<string, string>();\n\n async get(key: string): Promise<string | null> {\n return this.store.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.store.set(key, value);\n }\n\n async remove(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n","// AuthClient — main entry point for @atzentis/auth-sdk\n\nimport { BrowserDeviceSignalCollector } from \"./device\";\nimport { HttpClient } from \"./http/client\";\nimport { createAuthInterceptor, createDeviceSignalInterceptor } from \"./http/interceptors\";\nimport { AuthService } from \"./services/auth\";\nimport { BackgroundRefresh } from \"./services/refresh\";\nimport { PhoneService } from \"./services/phone\";\nimport { SessionService } from \"./services/session\";\nimport { MemoryStorage } from \"./storage\";\nimport type { ITokenStorage } from \"./storage/types\";\nimport type {\n GetOAuthUrlRequest,\n LoginCredentials,\n LoginResponse,\n RefreshTokenResponse,\n RequestPasswordResetRequest,\n ResetPasswordRequest,\n ResetPasswordResponse,\n SendMagicLinkRequest,\n SendVerificationEmailRequest,\n SignupData,\n SignupResponse,\n UsernameLoginCredentials,\n VerifyEmailRequest,\n VerifyEmailResponse,\n VerifyMagicLinkRequest,\n VerifyOAuthCodeRequest,\n} from \"./types/auth\";\nimport type { AuthConfig } from \"./types/config\";\nimport { DEFAULT_REFRESH_TOKEN_STORAGE_KEY, DEFAULT_TOKEN_STORAGE_KEY } from \"./types/config\";\n\nconst RISK_ALERT_THRESHOLD = 30;\n\nexport class AuthClient {\n private readonly config: AuthConfig;\n private readonly httpClient: HttpClient;\n private readonly storage: ITokenStorage;\n private readonly authService: AuthService;\n private readonly backgroundRefresh: BackgroundRefresh;\n\n readonly phone: PhoneService;\n readonly sessions: SessionService;\n\n constructor(config: AuthConfig) {\n this.config = config;\n this.storage = config.storage ?? new MemoryStorage();\n\n const tokenStorageKey = config.tokenStorageKey ?? DEFAULT_TOKEN_STORAGE_KEY;\n const refreshTokenStorageKey = config.tokenStorageKey\n ? `${config.tokenStorageKey}_refresh`\n : DEFAULT_REFRESH_TOKEN_STORAGE_KEY;\n\n this.httpClient = new HttpClient({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n });\n\n // Add auth interceptor for API key\n const storage = this.storage;\n this.httpClient.addRequestInterceptor(\n createAuthInterceptor({\n tokenProvider: () => null,\n apiKey: config.apiKey,\n }),\n );\n\n // Auth interceptor with async token access\n this.httpClient.addRequestInterceptor(async (request) => {\n if (request.skipAuth) return request;\n const token = await storage.get(tokenStorageKey);\n if (token) {\n return {\n ...request,\n headers: {\n ...request.headers,\n Authorization: `Bearer ${token}`,\n },\n };\n }\n return request;\n });\n\n // Add device signal interceptor if enabled\n if (config.collectDeviceSignals !== false) {\n const collector = new BrowserDeviceSignalCollector();\n this.httpClient.addRequestInterceptor(createDeviceSignalInterceptor(collector));\n }\n\n this.authService = new AuthService(this.httpClient, this.storage, {\n tokenStorageKey,\n refreshTokenStorageKey,\n });\n\n this.phone = new PhoneService(\n this.httpClient,\n (accessToken, refreshToken) => this.authService.storeTokens(accessToken, refreshToken),\n (method) => this.authService.setLastLoginMethod(method),\n );\n\n this.sessions = new SessionService(this.httpClient, (accessToken, refreshToken) =>\n this.authService.storeTokens(accessToken, refreshToken),\n );\n\n this.backgroundRefresh = new BackgroundRefresh(\n async () => {\n const result = await this.authService.refreshToken();\n return { accessToken: result.accessToken, expiresIn: result.expiresIn };\n },\n config.refreshThreshold ?? 300,\n {\n onTokenRefreshed: config.onTokenRefreshed,\n onSessionExpired: config.onSessionExpired,\n },\n );\n }\n\n // --- Email/Password (T02-001) ---\n\n async login(credentials: LoginCredentials): Promise<LoginResponse> {\n const response = await this.authService.login(credentials);\n this.handleLoginEvent(response);\n this.startRefreshIfEnabled(response.expiresIn);\n return response;\n }\n\n async signup(data: SignupData): Promise<SignupResponse> {\n const response = await this.authService.signup(data);\n this.startRefreshIfEnabled(response.expiresIn);\n return response;\n }\n\n // --- Username (T02-002) ---\n\n async loginWithUsername(credentials: UsernameLoginCredentials): Promise<LoginResponse> {\n const response = await this.authService.loginWithUsername(credentials);\n this.handleLoginEvent(response);\n this.startRefreshIfEnabled(response.expiresIn);\n return response;\n }\n\n async isUsernameAvailable(username: string): Promise<boolean> {\n return this.authService.isUsernameAvailable(username);\n }\n\n // --- OAuth (T02-004) ---\n\n getOAuthUrl(request: GetOAuthUrlRequest): string {\n return this.authService.getOAuthUrl(request);\n }\n\n async verifyOAuthCode(request: VerifyOAuthCodeRequest): Promise<LoginResponse> {\n const response = await this.authService.verifyOAuthCode(request);\n this.handleLoginEvent(response);\n this.startRefreshIfEnabled(response.expiresIn);\n return response;\n }\n\n // --- Magic Link (T02-005) ---\n\n async sendMagicLink(request: SendMagicLinkRequest): Promise<void> {\n return this.authService.sendMagicLink(request);\n }\n\n async verifyMagicLink(request: VerifyMagicLinkRequest): Promise<LoginResponse> {\n const response = await this.authService.verifyMagicLink(request);\n this.handleLoginEvent(response);\n this.startRefreshIfEnabled(response.expiresIn);\n return response;\n }\n\n // --- Email Verification (T02-006) ---\n\n async sendVerificationEmail(request: SendVerificationEmailRequest): Promise<void> {\n return this.authService.sendVerificationEmail(request);\n }\n\n async verifyEmail(request: VerifyEmailRequest): Promise<VerifyEmailResponse> {\n return this.authService.verifyEmail(request);\n }\n\n // --- Password Reset (T02-007) ---\n\n async requestPasswordReset(request: RequestPasswordResetRequest): Promise<void> {\n return this.authService.requestPasswordReset(request);\n }\n\n async resetPassword(request: ResetPasswordRequest): Promise<ResetPasswordResponse> {\n return this.authService.resetPassword(request);\n }\n\n // --- Token Management (T02-009) ---\n\n async getAccessToken(): Promise<string | null> {\n return this.authService.getAccessToken();\n }\n\n async refreshToken(): Promise<RefreshTokenResponse> {\n return this.authService.refreshToken();\n }\n\n async isAuthenticated(): Promise<boolean> {\n return this.authService.isAuthenticated();\n }\n\n async getLastLoginMethod(): Promise<string | null> {\n return this.authService.getLastLoginMethod();\n }\n\n // --- Logout (T02-010) ---\n\n async logout(): Promise<void> {\n this.backgroundRefresh.stop();\n await this.authService.logout();\n this.config.onSessionExpired?.();\n }\n\n async logoutAllDevices(): Promise<void> {\n this.backgroundRefresh.stop();\n await this.authService.logoutAllDevices();\n this.config.onSessionExpired?.();\n }\n\n // --- Private ---\n\n private startRefreshIfEnabled(expiresIn: number): void {\n if (this.config.autoRefreshToken !== false) {\n this.backgroundRefresh.start(expiresIn);\n }\n }\n\n private handleLoginEvent(response: LoginResponse): void {\n if (\n response.loginEvent &&\n response.loginEvent.riskScore >= RISK_ALERT_THRESHOLD &&\n this.config.onNewDeviceAlert\n ) {\n const event = response.loginEvent;\n this.config.onNewDeviceAlert({\n deviceName: event.deviceName,\n deviceType: event.deviceType,\n city: event.city,\n country: event.country,\n riskScore: event.riskScore,\n });\n }\n }\n}\n","// Session Types v2.0\n\nimport type { User } from \"./user\";\n\n// --- Session ---\n\nexport interface Session {\n id: string;\n userId: string;\n organizationId: string;\n createdAt: string;\n expiresAt: string;\n ip: string;\n userAgent: string;\n device?: DeviceSummary;\n lastActivityAt?: string;\n}\n\n// --- Device Summary (v2.0) ---\n\nexport interface DeviceSummary {\n id: string;\n name: string;\n deviceType: \"mobile\" | \"desktop\" | \"tablet\";\n isTrusted: boolean;\n}\n\n// --- List Sessions ---\n\nexport interface ListSessionsRequest {\n limit?: number;\n offset?: number;\n}\n\nexport interface ListSessionsResponse {\n data: Session[];\n total: number;\n limit: number;\n offset: number;\n}\n\n// --- Revoke All ---\n\nexport interface RevokeAllSessionsOptions {\n exceptCurrent?: boolean;\n}\n\nexport interface RevokeAllSessionsResponse {\n revokedCount: number;\n}\n\n// --- Multi-Session (v2.0) ---\n\nexport interface DeviceSession {\n sessionToken: string;\n user: User;\n isActive: boolean;\n productId?: string;\n createdAt: string;\n}\n\nexport interface SetActiveSessionRequest {\n sessionToken: string;\n}\n\nexport interface SetActiveSessionResponse {\n accessToken: string;\n refreshToken: string;\n expiresIn: number;\n user: User;\n}\n\n// --- Type Guard ---\n\nexport function hasDevice(session: Session): session is Session & { device: DeviceSummary } {\n return session.device !== undefined;\n}\n","// Auth SDK Error Codes v2.0\n\nexport enum AuthErrorCode {\n // Authentication\n InvalidCredentials = \"INVALID_CREDENTIALS\",\n EmailNotVerified = \"EMAIL_NOT_VERIFIED\",\n TwoFactorRequired = \"TWO_FACTOR_REQUIRED\",\n\n // Phone Auth (v2.0)\n InvalidPhoneNumber = \"INVALID_PHONE_NUMBER\",\n OTPExpired = \"OTP_EXPIRED\",\n OTPInvalid = \"OTP_INVALID\",\n OTPMaxAttempts = \"OTP_MAX_ATTEMPTS\",\n PhoneNumberInUse = \"PHONE_NUMBER_IN_USE\",\n FraudDetected = \"FRAUD_DETECTED\",\n\n // Username (v2.0)\n UsernameTaken = \"USERNAME_TAKEN\",\n UsernameInvalid = \"USERNAME_INVALID\",\n UsernameReserved = \"USERNAME_RESERVED\",\n\n // Device / Login Activity (v2.0)\n DeviceNotFound = \"DEVICE_NOT_FOUND\",\n LoginEventNotFound = \"LOGIN_EVENT_NOT_FOUND\",\n ReauthRequired = \"REAUTH_REQUIRED\",\n\n // Multi-session (v2.0)\n MaxSessionsExceeded = \"MAX_SESSIONS_EXCEEDED\",\n\n // CAPTCHA (v2.0)\n CaptchaRequired = \"CAPTCHA_REQUIRED\",\n CaptchaInvalid = \"CAPTCHA_INVALID\",\n\n // Breach (v2.0)\n PasswordBreached = \"PASSWORD_BREACHED\",\n\n // Session / Token\n SessionExpired = \"SESSION_EXPIRED\",\n TokenExpired = \"TOKEN_EXPIRED\",\n InvalidToken = \"INVALID_TOKEN\",\n\n // Authorization\n UnauthorizedRole = \"UNAUTHORIZED_ROLE\",\n OrganizationNotFound = \"ORGANIZATION_NOT_FOUND\",\n PermissionDenied = \"PERMISSION_DENIED\",\n\n // Rate Limiting & Network\n RateLimited = \"RATE_LIMITED\",\n NetworkError = \"NETWORK_ERROR\",\n Timeout = \"TIMEOUT\",\n\n // User Management\n UserNotFound = \"USER_NOT_FOUND\",\n UserAlreadyExists = \"USER_ALREADY_EXISTS\",\n InvalidEmail = \"INVALID_EMAIL\",\n WeakPassword = \"WEAK_PASSWORD\",\n\n // Organization\n OrganizationLimitExceeded = \"ORG_LIMIT_EXCEEDED\",\n MemberLimitExceeded = \"MEMBER_LIMIT_EXCEEDED\",\n\n // API Keys\n KeyNotFound = \"KEY_NOT_FOUND\",\n KeyRevoked = \"KEY_REVOKED\",\n KeyExpired = \"KEY_EXPIRED\",\n}\n"]}
|