@atzentis/auth-sdk 0.0.2

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.
@@ -0,0 +1,257 @@
1
+ interface AuthConfig {
2
+ baseUrl: string;
3
+ apiKey?: string;
4
+ }
5
+ interface LoginParams {
6
+ email: string;
7
+ password: string;
8
+ }
9
+ interface RegisterParams {
10
+ email: string;
11
+ password: string;
12
+ name?: string;
13
+ }
14
+ interface User {
15
+ id: string;
16
+ email: string;
17
+ name: string | null;
18
+ createdAt: string;
19
+ }
20
+ interface Session {
21
+ user: User;
22
+ accessToken: string;
23
+ expiresAt: number;
24
+ }
25
+
26
+ declare class AuthClient {
27
+ private config;
28
+ private session;
29
+ constructor(config: AuthConfig);
30
+ login(params: LoginParams): Promise<Session>;
31
+ register(params: RegisterParams): Promise<Session>;
32
+ logout(): Promise<void>;
33
+ getSession(): Promise<Session | null>;
34
+ refreshSession(): Promise<Session>;
35
+ }
36
+
37
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
38
+ interface HttpClientConfig {
39
+ baseUrl: string;
40
+ timeout?: number;
41
+ headers?: Record<string, string>;
42
+ retry?: Partial<RetryConfig>;
43
+ rateLimit?: Partial<RateLimitConfig>;
44
+ }
45
+ interface RequestConfig {
46
+ method: HttpMethod;
47
+ path: string;
48
+ body?: unknown;
49
+ headers?: Record<string, string>;
50
+ params?: Record<string, string | number | boolean | undefined>;
51
+ timeout?: number;
52
+ signal?: AbortSignal;
53
+ skipAuth?: boolean;
54
+ }
55
+ interface ApiResponse<T> {
56
+ data: T;
57
+ status: number;
58
+ headers: Headers;
59
+ }
60
+ type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
61
+ type ResponseInterceptor = (response: ApiResponse<unknown>) => ApiResponse<unknown> | Promise<ApiResponse<unknown>>;
62
+ type ErrorInterceptor = (error: unknown) => unknown | Promise<unknown>;
63
+ interface RetryConfig {
64
+ maxRetries: number;
65
+ baseDelay: number;
66
+ maxDelay: number;
67
+ factor: number;
68
+ jitter: boolean;
69
+ retryableStatuses: number[];
70
+ retryPost: boolean;
71
+ }
72
+ interface RateLimitConfig {
73
+ autoRetry: boolean;
74
+ maxRetryAfter: number;
75
+ }
76
+
77
+ declare class HttpClient {
78
+ private readonly config;
79
+ private readonly retryConfig;
80
+ private readonly rateLimitConfig;
81
+ private requestInterceptors;
82
+ private responseInterceptors;
83
+ private errorInterceptors;
84
+ constructor(config: HttpClientConfig);
85
+ get<T>(path: string, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
86
+ post<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
87
+ put<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
88
+ patch<T>(path: string, body?: unknown, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
89
+ delete<T>(path: string, config?: Partial<Omit<RequestConfig, "method" | "path" | "body">>): Promise<ApiResponse<T>>;
90
+ addRequestInterceptor(fn: RequestInterceptor): void;
91
+ removeRequestInterceptor(fn: RequestInterceptor): void;
92
+ addResponseInterceptor(fn: ResponseInterceptor): void;
93
+ removeResponseInterceptor(fn: ResponseInterceptor): void;
94
+ addErrorInterceptor(fn: ErrorInterceptor): void;
95
+ removeErrorInterceptor(fn: ErrorInterceptor): void;
96
+ private request;
97
+ private executeFetch;
98
+ }
99
+
100
+ interface AuthInterceptorConfig {
101
+ tokenProvider?: () => string | null;
102
+ apiKey?: string;
103
+ }
104
+ declare function createAuthInterceptor(config: AuthInterceptorConfig): RequestInterceptor;
105
+
106
+ interface DeviceSignals {
107
+ screen: string;
108
+ timezone: string;
109
+ platform: string;
110
+ language: string;
111
+ colorDepth: string;
112
+ touchSupport: string;
113
+ }
114
+ interface IDeviceSignalCollector {
115
+ collect(): Promise<DeviceSignals>;
116
+ getFingerprint(): Promise<string>;
117
+ }
118
+
119
+ declare function createDeviceSignalInterceptor(collector: IDeviceSignalCollector): RequestInterceptor;
120
+
121
+ declare enum AuthErrorCode {
122
+ InvalidCredentials = "INVALID_CREDENTIALS",
123
+ EmailNotVerified = "EMAIL_NOT_VERIFIED",
124
+ TwoFactorRequired = "TWO_FACTOR_REQUIRED",
125
+ InvalidPhoneNumber = "INVALID_PHONE_NUMBER",
126
+ OTPExpired = "OTP_EXPIRED",
127
+ OTPInvalid = "OTP_INVALID",
128
+ OTPMaxAttempts = "OTP_MAX_ATTEMPTS",
129
+ PhoneNumberInUse = "PHONE_NUMBER_IN_USE",
130
+ FraudDetected = "FRAUD_DETECTED",
131
+ UsernameTaken = "USERNAME_TAKEN",
132
+ UsernameInvalid = "USERNAME_INVALID",
133
+ UsernameReserved = "USERNAME_RESERVED",
134
+ DeviceNotFound = "DEVICE_NOT_FOUND",
135
+ LoginEventNotFound = "LOGIN_EVENT_NOT_FOUND",
136
+ ReauthRequired = "REAUTH_REQUIRED",
137
+ MaxSessionsExceeded = "MAX_SESSIONS_EXCEEDED",
138
+ CaptchaRequired = "CAPTCHA_REQUIRED",
139
+ CaptchaInvalid = "CAPTCHA_INVALID",
140
+ PasswordBreached = "PASSWORD_BREACHED",
141
+ SessionExpired = "SESSION_EXPIRED",
142
+ TokenExpired = "TOKEN_EXPIRED",
143
+ InvalidToken = "INVALID_TOKEN",
144
+ UnauthorizedRole = "UNAUTHORIZED_ROLE",
145
+ OrganizationNotFound = "ORGANIZATION_NOT_FOUND",
146
+ PermissionDenied = "PERMISSION_DENIED",
147
+ RateLimited = "RATE_LIMITED",
148
+ NetworkError = "NETWORK_ERROR",
149
+ Timeout = "TIMEOUT",
150
+ UserNotFound = "USER_NOT_FOUND",
151
+ UserAlreadyExists = "USER_ALREADY_EXISTS",
152
+ InvalidEmail = "INVALID_EMAIL",
153
+ WeakPassword = "WEAK_PASSWORD",
154
+ OrganizationLimitExceeded = "ORG_LIMIT_EXCEEDED",
155
+ MemberLimitExceeded = "MEMBER_LIMIT_EXCEEDED",
156
+ KeyNotFound = "KEY_NOT_FOUND",
157
+ KeyRevoked = "KEY_REVOKED",
158
+ KeyExpired = "KEY_EXPIRED"
159
+ }
160
+
161
+ interface AuthErrorOptions {
162
+ code: AuthErrorCode;
163
+ message: string;
164
+ statusCode: number;
165
+ details?: Record<string, unknown>;
166
+ requestId?: string;
167
+ }
168
+ declare class AuthError extends Error {
169
+ readonly code: AuthErrorCode;
170
+ readonly statusCode: number;
171
+ readonly details?: Record<string, unknown>;
172
+ readonly requestId?: string;
173
+ constructor(options: AuthErrorOptions);
174
+ toJSON(): Record<string, unknown>;
175
+ }
176
+
177
+ type SubclassOptions = Omit<AuthErrorOptions, "statusCode"> & {
178
+ statusCode?: number;
179
+ };
180
+ declare class ValidationError extends AuthError {
181
+ constructor(options: SubclassOptions);
182
+ }
183
+ declare class AuthenticationError extends AuthError {
184
+ constructor(options: SubclassOptions);
185
+ }
186
+ declare class ForbiddenError extends AuthError {
187
+ constructor(options: SubclassOptions);
188
+ }
189
+ declare class NotFoundError extends AuthError {
190
+ constructor(options: SubclassOptions);
191
+ }
192
+ declare class ConflictError extends AuthError {
193
+ constructor(options: SubclassOptions);
194
+ }
195
+ declare class UnprocessableError extends AuthError {
196
+ constructor(options: SubclassOptions);
197
+ }
198
+ interface RateLimitErrorOptions extends SubclassOptions {
199
+ retryAfter: number;
200
+ }
201
+ declare class RateLimitError extends AuthError {
202
+ readonly retryAfter: number;
203
+ constructor(options: RateLimitErrorOptions);
204
+ toJSON(): Record<string, unknown>;
205
+ }
206
+ declare class ServerError extends AuthError {
207
+ constructor(options: SubclassOptions);
208
+ }
209
+ interface NetworkErrorOptions {
210
+ message: string;
211
+ code?: AuthErrorCode;
212
+ details?: Record<string, unknown>;
213
+ requestId?: string;
214
+ }
215
+ declare class NetworkError extends AuthError {
216
+ constructor(options: NetworkErrorOptions);
217
+ }
218
+ interface TimeoutErrorOptions {
219
+ duration: number;
220
+ message?: string;
221
+ requestId?: string;
222
+ }
223
+ declare class TimeoutError extends AuthError {
224
+ readonly duration: number;
225
+ constructor(options: TimeoutErrorOptions);
226
+ toJSON(): Record<string, unknown>;
227
+ }
228
+
229
+ declare function createErrorFromResponse(status: number, body: unknown, headers: Headers): AuthError;
230
+
231
+ declare class BrowserDeviceSignalCollector implements IDeviceSignalCollector {
232
+ private cached;
233
+ private cachedFingerprint;
234
+ collect(): Promise<DeviceSignals>;
235
+ getFingerprint(): Promise<string>;
236
+ }
237
+
238
+ interface ITokenStorage {
239
+ get(key: string): Promise<string | null>;
240
+ set(key: string, value: string): Promise<void>;
241
+ remove(key: string): Promise<void>;
242
+ }
243
+
244
+ declare class LocalStorageAdapter implements ITokenStorage {
245
+ get(key: string): Promise<string | null>;
246
+ set(key: string, value: string): Promise<void>;
247
+ remove(key: string): Promise<void>;
248
+ }
249
+
250
+ declare class MemoryStorage implements ITokenStorage {
251
+ private store;
252
+ get(key: string): Promise<string | null>;
253
+ set(key: string, value: string): Promise<void>;
254
+ remove(key: string): Promise<void>;
255
+ }
256
+
257
+ export { type ApiResponse, AuthClient, type AuthConfig, AuthError, AuthErrorCode, type AuthErrorOptions, type AuthInterceptorConfig, AuthenticationError, BrowserDeviceSignalCollector, ConflictError, type DeviceSignals, type ErrorInterceptor, ForbiddenError, HttpClient, type HttpClientConfig, type HttpMethod, type IDeviceSignalCollector, type ITokenStorage, LocalStorageAdapter, type LoginParams, MemoryStorage, NetworkError, NotFoundError, type RateLimitConfig, RateLimitError, type RegisterParams, type RequestConfig, type RequestInterceptor, type ResponseInterceptor, type RetryConfig, ServerError, type Session, TimeoutError, UnprocessableError, type User, ValidationError, createAuthInterceptor, createDeviceSignalInterceptor, createErrorFromResponse };
package/dist/index.js ADDED
@@ -0,0 +1,593 @@
1
+ // src/client.ts
2
+ var AuthClient = class {
3
+ config;
4
+ session = null;
5
+ constructor(config) {
6
+ this.config = config;
7
+ }
8
+ async login(params) {
9
+ const response = await fetch(`${this.config.baseUrl}/auth/login`, {
10
+ method: "POST",
11
+ headers: { "Content-Type": "application/json" },
12
+ body: JSON.stringify(params)
13
+ });
14
+ if (!response.ok) {
15
+ throw new Error("Login failed");
16
+ }
17
+ const session = await response.json();
18
+ this.session = session;
19
+ return session;
20
+ }
21
+ async register(params) {
22
+ const response = await fetch(`${this.config.baseUrl}/auth/register`, {
23
+ method: "POST",
24
+ headers: { "Content-Type": "application/json" },
25
+ body: JSON.stringify(params)
26
+ });
27
+ if (!response.ok) {
28
+ throw new Error("Registration failed");
29
+ }
30
+ const session = await response.json();
31
+ this.session = session;
32
+ return session;
33
+ }
34
+ async logout() {
35
+ await fetch(`${this.config.baseUrl}/auth/logout`, {
36
+ method: "POST",
37
+ headers: {
38
+ Authorization: `Bearer ${this.session?.accessToken}`
39
+ }
40
+ });
41
+ this.session = null;
42
+ }
43
+ async getSession() {
44
+ return this.session;
45
+ }
46
+ async refreshSession() {
47
+ if (!this.session) {
48
+ throw new Error("No session to refresh");
49
+ }
50
+ const response = await fetch(`${this.config.baseUrl}/auth/refresh`, {
51
+ method: "POST",
52
+ headers: {
53
+ Authorization: `Bearer ${this.session.accessToken}`
54
+ }
55
+ });
56
+ if (!response.ok) {
57
+ throw new Error("Session refresh failed");
58
+ }
59
+ const session = await response.json();
60
+ this.session = session;
61
+ return session;
62
+ }
63
+ };
64
+
65
+ // src/errors/auth-error.ts
66
+ var AuthError = class extends Error {
67
+ code;
68
+ statusCode;
69
+ details;
70
+ requestId;
71
+ constructor(options) {
72
+ super(options.message);
73
+ this.name = "AuthError";
74
+ this.code = options.code;
75
+ this.statusCode = options.statusCode;
76
+ this.details = options.details;
77
+ this.requestId = options.requestId;
78
+ Object.setPrototypeOf(this, new.target.prototype);
79
+ }
80
+ toJSON() {
81
+ return {
82
+ code: this.code,
83
+ message: this.message,
84
+ statusCode: this.statusCode,
85
+ details: this.details,
86
+ requestId: this.requestId
87
+ };
88
+ }
89
+ };
90
+
91
+ // src/errors/errors.ts
92
+ var ValidationError = class extends AuthError {
93
+ constructor(options) {
94
+ super({ ...options, statusCode: options.statusCode ?? 400 });
95
+ this.name = "ValidationError";
96
+ }
97
+ };
98
+ var AuthenticationError = class extends AuthError {
99
+ constructor(options) {
100
+ super({ ...options, statusCode: options.statusCode ?? 401 });
101
+ this.name = "AuthenticationError";
102
+ }
103
+ };
104
+ var ForbiddenError = class extends AuthError {
105
+ constructor(options) {
106
+ super({ ...options, statusCode: options.statusCode ?? 403 });
107
+ this.name = "ForbiddenError";
108
+ }
109
+ };
110
+ var NotFoundError = class extends AuthError {
111
+ constructor(options) {
112
+ super({ ...options, statusCode: options.statusCode ?? 404 });
113
+ this.name = "NotFoundError";
114
+ }
115
+ };
116
+ var ConflictError = class extends AuthError {
117
+ constructor(options) {
118
+ super({ ...options, statusCode: options.statusCode ?? 409 });
119
+ this.name = "ConflictError";
120
+ }
121
+ };
122
+ var UnprocessableError = class extends AuthError {
123
+ constructor(options) {
124
+ super({ ...options, statusCode: options.statusCode ?? 422 });
125
+ this.name = "UnprocessableError";
126
+ }
127
+ };
128
+ var RateLimitError = class extends AuthError {
129
+ retryAfter;
130
+ constructor(options) {
131
+ super({ ...options, statusCode: options.statusCode ?? 429 });
132
+ this.name = "RateLimitError";
133
+ this.retryAfter = options.retryAfter;
134
+ }
135
+ toJSON() {
136
+ return { ...super.toJSON(), retryAfter: this.retryAfter };
137
+ }
138
+ };
139
+ var ServerError = class extends AuthError {
140
+ constructor(options) {
141
+ super({ ...options, statusCode: options.statusCode ?? 500 });
142
+ this.name = "ServerError";
143
+ }
144
+ };
145
+ var NetworkError = class extends AuthError {
146
+ constructor(options) {
147
+ super({
148
+ code: options.code ?? "NETWORK_ERROR",
149
+ message: options.message,
150
+ statusCode: 0,
151
+ details: options.details,
152
+ requestId: options.requestId
153
+ });
154
+ this.name = "NetworkError";
155
+ }
156
+ };
157
+ var TimeoutError = class extends AuthError {
158
+ duration;
159
+ constructor(options) {
160
+ super({
161
+ code: "TIMEOUT",
162
+ message: options.message ?? `Request timed out after ${options.duration}ms`,
163
+ statusCode: 0,
164
+ requestId: options.requestId
165
+ });
166
+ this.name = "TimeoutError";
167
+ this.duration = options.duration;
168
+ }
169
+ toJSON() {
170
+ return { ...super.toJSON(), duration: this.duration };
171
+ }
172
+ };
173
+
174
+ // src/errors/factory.ts
175
+ function parseBody(body) {
176
+ if (body && typeof body === "object" && "message" in body) {
177
+ const obj = body;
178
+ return {
179
+ code: typeof obj.code === "string" ? obj.code : void 0,
180
+ message: typeof obj.message === "string" ? obj.message : "Unknown error",
181
+ details: typeof obj.details === "object" && obj.details !== null ? obj.details : void 0
182
+ };
183
+ }
184
+ return { message: "Unknown error" };
185
+ }
186
+ function parseRetryAfterHeader(header) {
187
+ if (!header) return 60;
188
+ const seconds = Number(header);
189
+ if (!Number.isNaN(seconds)) return seconds;
190
+ const date = new Date(header);
191
+ if (!Number.isNaN(date.getTime())) {
192
+ return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1e3));
193
+ }
194
+ return 60;
195
+ }
196
+ function createErrorFromResponse(status, body, headers) {
197
+ const parsed = parseBody(body);
198
+ const requestId = headers.get("x-request-id") ?? void 0;
199
+ const code = parsed.code ?? "NETWORK_ERROR";
200
+ const message = parsed.message ?? `HTTP ${status}`;
201
+ const details = parsed.details;
202
+ const base = { code, message, details, requestId };
203
+ switch (true) {
204
+ case status === 400:
205
+ return new ValidationError(base);
206
+ case status === 401:
207
+ return new AuthenticationError(base);
208
+ case status === 403:
209
+ return new ForbiddenError(base);
210
+ case status === 404:
211
+ return new NotFoundError(base);
212
+ case status === 409:
213
+ return new ConflictError(base);
214
+ case status === 422:
215
+ return new UnprocessableError(base);
216
+ case status === 429: {
217
+ const retryAfter = parseRetryAfterHeader(headers.get("retry-after"));
218
+ return new RateLimitError({ ...base, retryAfter });
219
+ }
220
+ case (status >= 500 && status < 600):
221
+ return new ServerError(base);
222
+ default:
223
+ return new AuthError({ ...base, statusCode: status });
224
+ }
225
+ }
226
+
227
+ // src/http/rate-limit.ts
228
+ var DEFAULT_RATE_LIMIT_CONFIG = {
229
+ autoRetry: true,
230
+ maxRetryAfter: 60
231
+ };
232
+ function mergeRateLimitConfig(config) {
233
+ return { ...DEFAULT_RATE_LIMIT_CONFIG, ...config };
234
+ }
235
+
236
+ // src/http/retry.ts
237
+ var DEFAULT_RETRY_CONFIG = {
238
+ maxRetries: 3,
239
+ baseDelay: 1e3,
240
+ maxDelay: 1e4,
241
+ factor: 2,
242
+ jitter: true,
243
+ retryableStatuses: [500, 502, 503, 504],
244
+ retryPost: false
245
+ };
246
+ function mergeRetryConfig(config) {
247
+ return { ...DEFAULT_RETRY_CONFIG, ...config };
248
+ }
249
+ function shouldRetry(error, attempt, method, config) {
250
+ if (attempt >= config.maxRetries) return false;
251
+ if (method === "POST" && !config.retryPost) return false;
252
+ if (error instanceof TypeError) return true;
253
+ if (error && typeof error === "object" && "statusCode" in error) {
254
+ const statusCode = error.statusCode;
255
+ return config.retryableStatuses.includes(statusCode);
256
+ }
257
+ return false;
258
+ }
259
+ function calculateDelay(attempt, config) {
260
+ const exponential = config.baseDelay * config.factor ** attempt;
261
+ const delay = Math.min(exponential, config.maxDelay);
262
+ if (!config.jitter) return delay;
263
+ return Math.round(delay * Math.random());
264
+ }
265
+ function sleep(ms) {
266
+ return new Promise((resolve) => setTimeout(resolve, ms));
267
+ }
268
+
269
+ // src/http/client.ts
270
+ var HttpClient = class {
271
+ config;
272
+ retryConfig;
273
+ rateLimitConfig;
274
+ requestInterceptors = [];
275
+ responseInterceptors = [];
276
+ errorInterceptors = [];
277
+ constructor(config) {
278
+ this.config = config;
279
+ this.retryConfig = mergeRetryConfig(config.retry);
280
+ this.rateLimitConfig = mergeRateLimitConfig(config.rateLimit);
281
+ }
282
+ // --- Public HTTP Methods ---
283
+ async get(path, config) {
284
+ return this.request({ ...config, method: "GET", path });
285
+ }
286
+ async post(path, body, config) {
287
+ return this.request({ ...config, method: "POST", path, body });
288
+ }
289
+ async put(path, body, config) {
290
+ return this.request({ ...config, method: "PUT", path, body });
291
+ }
292
+ async patch(path, body, config) {
293
+ return this.request({ ...config, method: "PATCH", path, body });
294
+ }
295
+ async delete(path, config) {
296
+ return this.request({ ...config, method: "DELETE", path });
297
+ }
298
+ // --- Interceptor Management ---
299
+ addRequestInterceptor(fn) {
300
+ this.requestInterceptors.push(fn);
301
+ }
302
+ removeRequestInterceptor(fn) {
303
+ this.requestInterceptors = this.requestInterceptors.filter((i) => i !== fn);
304
+ }
305
+ addResponseInterceptor(fn) {
306
+ this.responseInterceptors.push(fn);
307
+ }
308
+ removeResponseInterceptor(fn) {
309
+ this.responseInterceptors = this.responseInterceptors.filter((i) => i !== fn);
310
+ }
311
+ addErrorInterceptor(fn) {
312
+ this.errorInterceptors.push(fn);
313
+ }
314
+ removeErrorInterceptor(fn) {
315
+ this.errorInterceptors = this.errorInterceptors.filter((i) => i !== fn);
316
+ }
317
+ // --- Internal ---
318
+ async request(initialConfig) {
319
+ let config = { ...initialConfig };
320
+ for (const interceptor of this.requestInterceptors) {
321
+ config = await interceptor(config);
322
+ }
323
+ const url = new URL(config.path, this.config.baseUrl);
324
+ if (config.params) {
325
+ for (const [key, value] of Object.entries(config.params)) {
326
+ if (value !== void 0) {
327
+ url.searchParams.set(key, String(value));
328
+ }
329
+ }
330
+ }
331
+ const headers = {
332
+ ...this.config.headers,
333
+ ...config.headers
334
+ };
335
+ if (config.body !== void 0) {
336
+ headers["Content-Type"] = "application/json";
337
+ }
338
+ const maxAttempts = this.retryConfig.maxRetries + 1;
339
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
340
+ try {
341
+ return await this.executeFetch(url, headers, config, attempt);
342
+ } catch (error) {
343
+ let processedError = error;
344
+ for (const interceptor of this.errorInterceptors) {
345
+ processedError = await interceptor(processedError);
346
+ }
347
+ if (processedError instanceof RateLimitError) {
348
+ if (this.rateLimitConfig.autoRetry && processedError.retryAfter <= this.rateLimitConfig.maxRetryAfter && attempt === 0) {
349
+ await sleep(processedError.retryAfter * 1e3);
350
+ continue;
351
+ }
352
+ throw processedError;
353
+ }
354
+ if (shouldRetry(processedError, attempt, config.method, this.retryConfig)) {
355
+ const delay = calculateDelay(attempt, this.retryConfig);
356
+ await sleep(delay);
357
+ continue;
358
+ }
359
+ throw processedError;
360
+ }
361
+ }
362
+ throw new NetworkError({ message: "Max retries exceeded" });
363
+ }
364
+ async executeFetch(url, headers, config, _attempt) {
365
+ const timeout = config.timeout ?? this.config.timeout ?? 3e4;
366
+ const controller = new AbortController();
367
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
368
+ try {
369
+ const response = await fetch(url.toString(), {
370
+ method: config.method,
371
+ headers,
372
+ body: config.body !== void 0 ? JSON.stringify(config.body) : void 0,
373
+ signal: config.signal ?? controller.signal
374
+ });
375
+ clearTimeout(timeoutId);
376
+ if (!response.ok) {
377
+ let body;
378
+ try {
379
+ body = await response.json();
380
+ } catch {
381
+ body = { message: response.statusText };
382
+ }
383
+ throw createErrorFromResponse(response.status, body, response.headers);
384
+ }
385
+ let data;
386
+ if (response.status === 204) {
387
+ data = void 0;
388
+ } else {
389
+ data = await response.json();
390
+ }
391
+ let result = {
392
+ data,
393
+ status: response.status,
394
+ headers: response.headers
395
+ };
396
+ for (const interceptor of this.responseInterceptors) {
397
+ result = await interceptor(result);
398
+ }
399
+ return result;
400
+ } catch (error) {
401
+ clearTimeout(timeoutId);
402
+ if (error instanceof DOMException && error.name === "AbortError") {
403
+ throw new TimeoutError({ duration: timeout });
404
+ }
405
+ if (error instanceof TypeError) {
406
+ throw new NetworkError({ message: error.message });
407
+ }
408
+ throw error;
409
+ }
410
+ }
411
+ };
412
+
413
+ // src/http/interceptors/auth.ts
414
+ function createAuthInterceptor(config) {
415
+ return (request) => {
416
+ if (request.skipAuth) return request;
417
+ const headers = { ...request.headers };
418
+ if (config.tokenProvider) {
419
+ const token = config.tokenProvider();
420
+ if (token) {
421
+ headers["Authorization"] = `Bearer ${token}`;
422
+ }
423
+ }
424
+ if (config.apiKey) {
425
+ headers["x-api-key"] = config.apiKey;
426
+ }
427
+ return { ...request, headers };
428
+ };
429
+ }
430
+
431
+ // src/http/interceptors/device-signals.ts
432
+ function createDeviceSignalInterceptor(collector) {
433
+ return async (request) => {
434
+ const signals = await collector.collect();
435
+ if (!signals.screen && !signals.timezone && !signals.platform) {
436
+ return request;
437
+ }
438
+ const fingerprint = await collector.getFingerprint();
439
+ const headers = {
440
+ ...request.headers,
441
+ "x-device-screen": signals.screen,
442
+ "x-device-timezone": signals.timezone,
443
+ "x-device-platform": signals.platform,
444
+ "x-device-language": signals.language,
445
+ "x-device-color-depth": signals.colorDepth,
446
+ "x-device-touch": signals.touchSupport,
447
+ "x-device-fingerprint": fingerprint
448
+ };
449
+ return { ...request, headers };
450
+ };
451
+ }
452
+
453
+ // src/errors/codes.ts
454
+ var AuthErrorCode = /* @__PURE__ */ ((AuthErrorCode2) => {
455
+ AuthErrorCode2["InvalidCredentials"] = "INVALID_CREDENTIALS";
456
+ AuthErrorCode2["EmailNotVerified"] = "EMAIL_NOT_VERIFIED";
457
+ AuthErrorCode2["TwoFactorRequired"] = "TWO_FACTOR_REQUIRED";
458
+ AuthErrorCode2["InvalidPhoneNumber"] = "INVALID_PHONE_NUMBER";
459
+ AuthErrorCode2["OTPExpired"] = "OTP_EXPIRED";
460
+ AuthErrorCode2["OTPInvalid"] = "OTP_INVALID";
461
+ AuthErrorCode2["OTPMaxAttempts"] = "OTP_MAX_ATTEMPTS";
462
+ AuthErrorCode2["PhoneNumberInUse"] = "PHONE_NUMBER_IN_USE";
463
+ AuthErrorCode2["FraudDetected"] = "FRAUD_DETECTED";
464
+ AuthErrorCode2["UsernameTaken"] = "USERNAME_TAKEN";
465
+ AuthErrorCode2["UsernameInvalid"] = "USERNAME_INVALID";
466
+ AuthErrorCode2["UsernameReserved"] = "USERNAME_RESERVED";
467
+ AuthErrorCode2["DeviceNotFound"] = "DEVICE_NOT_FOUND";
468
+ AuthErrorCode2["LoginEventNotFound"] = "LOGIN_EVENT_NOT_FOUND";
469
+ AuthErrorCode2["ReauthRequired"] = "REAUTH_REQUIRED";
470
+ AuthErrorCode2["MaxSessionsExceeded"] = "MAX_SESSIONS_EXCEEDED";
471
+ AuthErrorCode2["CaptchaRequired"] = "CAPTCHA_REQUIRED";
472
+ AuthErrorCode2["CaptchaInvalid"] = "CAPTCHA_INVALID";
473
+ AuthErrorCode2["PasswordBreached"] = "PASSWORD_BREACHED";
474
+ AuthErrorCode2["SessionExpired"] = "SESSION_EXPIRED";
475
+ AuthErrorCode2["TokenExpired"] = "TOKEN_EXPIRED";
476
+ AuthErrorCode2["InvalidToken"] = "INVALID_TOKEN";
477
+ AuthErrorCode2["UnauthorizedRole"] = "UNAUTHORIZED_ROLE";
478
+ AuthErrorCode2["OrganizationNotFound"] = "ORGANIZATION_NOT_FOUND";
479
+ AuthErrorCode2["PermissionDenied"] = "PERMISSION_DENIED";
480
+ AuthErrorCode2["RateLimited"] = "RATE_LIMITED";
481
+ AuthErrorCode2["NetworkError"] = "NETWORK_ERROR";
482
+ AuthErrorCode2["Timeout"] = "TIMEOUT";
483
+ AuthErrorCode2["UserNotFound"] = "USER_NOT_FOUND";
484
+ AuthErrorCode2["UserAlreadyExists"] = "USER_ALREADY_EXISTS";
485
+ AuthErrorCode2["InvalidEmail"] = "INVALID_EMAIL";
486
+ AuthErrorCode2["WeakPassword"] = "WEAK_PASSWORD";
487
+ AuthErrorCode2["OrganizationLimitExceeded"] = "ORG_LIMIT_EXCEEDED";
488
+ AuthErrorCode2["MemberLimitExceeded"] = "MEMBER_LIMIT_EXCEEDED";
489
+ AuthErrorCode2["KeyNotFound"] = "KEY_NOT_FOUND";
490
+ AuthErrorCode2["KeyRevoked"] = "KEY_REVOKED";
491
+ AuthErrorCode2["KeyExpired"] = "KEY_EXPIRED";
492
+ return AuthErrorCode2;
493
+ })(AuthErrorCode || {});
494
+
495
+ // src/device/browser-collector.ts
496
+ var EMPTY_SIGNALS = {
497
+ screen: "",
498
+ timezone: "",
499
+ platform: "",
500
+ language: "",
501
+ colorDepth: "",
502
+ touchSupport: ""
503
+ };
504
+ function simpleHash(input) {
505
+ let hash = 0;
506
+ for (let i = 0; i < input.length; i++) {
507
+ const char = input.charCodeAt(i);
508
+ hash = (hash << 5) - hash + char;
509
+ hash |= 0;
510
+ }
511
+ return Math.abs(hash).toString(16).padStart(8, "0");
512
+ }
513
+ async function sha256Hash(input) {
514
+ try {
515
+ if (typeof globalThis.crypto?.subtle?.digest === "function") {
516
+ const encoder = new TextEncoder();
517
+ const data = encoder.encode(input);
518
+ const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
519
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
520
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
521
+ }
522
+ } catch {
523
+ }
524
+ return simpleHash(input);
525
+ }
526
+ var BrowserDeviceSignalCollector = class {
527
+ cached = null;
528
+ cachedFingerprint = null;
529
+ async collect() {
530
+ if (this.cached) return this.cached;
531
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
532
+ this.cached = EMPTY_SIGNALS;
533
+ return this.cached;
534
+ }
535
+ this.cached = {
536
+ screen: `${screen.width}x${screen.height}`,
537
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
538
+ platform: navigator.platform,
539
+ language: navigator.language,
540
+ colorDepth: String(screen.colorDepth),
541
+ touchSupport: String("ontouchstart" in window)
542
+ };
543
+ return this.cached;
544
+ }
545
+ async getFingerprint() {
546
+ if (this.cachedFingerprint) return this.cachedFingerprint;
547
+ const signals = await this.collect();
548
+ const raw = [
549
+ signals.screen,
550
+ signals.timezone,
551
+ signals.platform,
552
+ signals.language,
553
+ signals.colorDepth,
554
+ signals.touchSupport
555
+ ].join("|");
556
+ this.cachedFingerprint = await sha256Hash(raw);
557
+ return this.cachedFingerprint;
558
+ }
559
+ };
560
+
561
+ // src/storage/local-storage-adapter.ts
562
+ var LocalStorageAdapter = class {
563
+ async get(key) {
564
+ if (typeof window === "undefined") return null;
565
+ return window.localStorage.getItem(key);
566
+ }
567
+ async set(key, value) {
568
+ if (typeof window === "undefined") return;
569
+ window.localStorage.setItem(key, value);
570
+ }
571
+ async remove(key) {
572
+ if (typeof window === "undefined") return;
573
+ window.localStorage.removeItem(key);
574
+ }
575
+ };
576
+
577
+ // src/storage/memory-storage.ts
578
+ var MemoryStorage = class {
579
+ store = /* @__PURE__ */ new Map();
580
+ async get(key) {
581
+ return this.store.get(key) ?? null;
582
+ }
583
+ async set(key, value) {
584
+ this.store.set(key, value);
585
+ }
586
+ async remove(key) {
587
+ this.store.delete(key);
588
+ }
589
+ };
590
+
591
+ export { AuthClient, AuthError, AuthErrorCode, AuthenticationError, BrowserDeviceSignalCollector, ConflictError, ForbiddenError, HttpClient, LocalStorageAdapter, MemoryStorage, NetworkError, NotFoundError, RateLimitError, ServerError, TimeoutError, UnprocessableError, ValidationError, createAuthInterceptor, createDeviceSignalInterceptor, createErrorFromResponse };
592
+ //# sourceMappingURL=index.js.map
593
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.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/errors/codes.ts","../src/device/browser-collector.ts","../src/storage/local-storage-adapter.ts","../src/storage/memory-storage.ts"],"names":["AuthErrorCode"],"mappings":"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","file":"index.js","sourcesContent":["import type { AuthConfig, LoginParams, RegisterParams, Session } from \"./types\";\n\nexport class AuthClient {\n private config: AuthConfig;\n private session: Session | null = null;\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n async login(params: LoginParams): Promise<Session> {\n // TODO: Implement actual API call\n const response = await fetch(`${this.config.baseUrl}/auth/login`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(params),\n });\n\n if (!response.ok) {\n throw new Error(\"Login failed\");\n }\n\n const session: Session = await response.json();\n this.session = session;\n return session;\n }\n\n async register(params: RegisterParams): Promise<Session> {\n // TODO: Implement actual API call\n const response = await fetch(`${this.config.baseUrl}/auth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(params),\n });\n\n if (!response.ok) {\n throw new Error(\"Registration failed\");\n }\n\n const session: Session = await response.json();\n this.session = session;\n return session;\n }\n\n async logout(): Promise<void> {\n // TODO: Implement actual API call\n await fetch(`${this.config.baseUrl}/auth/logout`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.session?.accessToken}`,\n },\n });\n\n this.session = null;\n }\n\n async getSession(): Promise<Session | null> {\n return this.session;\n }\n\n async refreshSession(): Promise<Session> {\n // TODO: Implement session refresh\n if (!this.session) {\n throw new Error(\"No session to refresh\");\n }\n\n const response = await fetch(`${this.config.baseUrl}/auth/refresh`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.session.accessToken}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(\"Session refresh failed\");\n }\n\n const session: Session = await response.json();\n this.session = session;\n return session;\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 type { AuthErrorCode } from \"./codes\";\nimport { AuthError, type AuthErrorOptions } from \"./auth-error\";\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 type { AuthErrorCode } from \"./codes\";\nimport { AuthError } from \"./auth-error\";\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(\n config?: Partial<RateLimitConfig>,\n): 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 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","// 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","// 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"]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@atzentis/auth-sdk",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "sideEffects": false,
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "devDependencies": {
20
+ "tsup": "^8.3.0",
21
+ "typescript": "^5.7.0",
22
+ "vitest": "^2.1.0"
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "type-check": "tsc --noEmit"
30
+ }
31
+ }