@thetechfossil/auth2 1.2.19 → 1.2.21

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.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/dist/index.components.d.mts +1 -0
  3. package/dist/index.components.d.ts +1 -0
  4. package/dist/index.components.js +275 -11
  5. package/dist/index.components.js.map +1 -1
  6. package/dist/index.components.mjs +275 -11
  7. package/dist/index.components.mjs.map +1 -1
  8. package/dist/index.d.mts +111 -3
  9. package/dist/index.d.ts +111 -3
  10. package/dist/index.js +470 -30
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +471 -32
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/index.next.d.mts +54 -1
  15. package/dist/index.next.d.ts +54 -1
  16. package/dist/index.next.js +332 -26
  17. package/dist/index.next.js.map +1 -1
  18. package/dist/index.next.mjs +332 -26
  19. package/dist/index.next.mjs.map +1 -1
  20. package/dist/index.next.server.d.mts +81 -2
  21. package/dist/index.next.server.d.ts +81 -2
  22. package/dist/index.next.server.js +406 -9
  23. package/dist/index.next.server.js.map +1 -1
  24. package/dist/index.next.server.mjs +403 -10
  25. package/dist/index.next.server.mjs.map +1 -1
  26. package/dist/index.node.d.mts +81 -2
  27. package/dist/index.node.d.ts +81 -2
  28. package/dist/index.node.js +406 -9
  29. package/dist/index.node.js.map +1 -1
  30. package/dist/index.node.mjs +403 -10
  31. package/dist/index.node.mjs.map +1 -1
  32. package/dist/index.react-native.d.mts +227 -0
  33. package/dist/index.react-native.d.ts +227 -0
  34. package/dist/index.react-native.js +1684 -0
  35. package/dist/index.react-native.js.map +1 -0
  36. package/dist/index.react-native.mjs +1648 -0
  37. package/dist/index.react-native.mjs.map +1 -0
  38. package/package.json +119 -102
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  var axios = require('axios');
5
+ var socket_ioClient = require('socket.io-client');
5
6
  var upfiles = require('@thetechfossil/upfiles');
6
7
  var React = require('react');
7
8
  var jsxRuntime = require('react/jsx-runtime');
@@ -22,6 +23,16 @@ var __export = (target, all) => {
22
23
  for (var name in all)
23
24
  __defProp(target, name, { get: all[name], enumerable: true });
24
25
  };
26
+ var ERROR_MESSAGES = {
27
+ NETWORK_ERROR: "Unable to connect to the server. Please check your internet connection and try again.",
28
+ TIMEOUT: "The request took too long. Please try again.",
29
+ SERVER_ERROR: "Something went wrong on our end. Please try again later.",
30
+ UNAUTHORIZED: "Your session has expired. Please log in again.",
31
+ FORBIDDEN: "You do not have permission to perform this action.",
32
+ NOT_FOUND: "The requested resource was not found.",
33
+ RATE_LIMITED: "Too many requests. Please wait a moment and try again.",
34
+ UNKNOWN: "An unexpected error occurred. Please try again."
35
+ };
25
36
  var HttpClient = class {
26
37
  constructor(baseUrl, defaultHeaders = {}) {
27
38
  this.csrfToken = null;
@@ -56,7 +67,7 @@ var HttpClient = class {
56
67
  }
57
68
  return config;
58
69
  },
59
- (error) => Promise.reject(error)
70
+ (error) => Promise.reject(this.createUserFriendlyError(error))
60
71
  );
61
72
  this.axiosInstance.interceptors.response.use(
62
73
  (response) => response,
@@ -71,18 +82,71 @@ var HttpClient = class {
71
82
  }
72
83
  return this.axiosInstance(originalRequest);
73
84
  } catch (refreshError) {
74
- return Promise.reject(refreshError);
85
+ return Promise.reject(this.createUserFriendlyError(refreshError));
75
86
  }
76
87
  }
77
- if (error.response && error.response.data && error.response.data.message) {
78
- const customError = new Error(error.response.data.message);
79
- customError.response = error.response;
80
- return Promise.reject(customError);
81
- }
82
- return Promise.reject(error);
88
+ return Promise.reject(this.createUserFriendlyError(error));
83
89
  }
84
90
  );
85
91
  }
92
+ /**
93
+ * Creates a user-friendly error message from an Axios error
94
+ */
95
+ createUserFriendlyError(error) {
96
+ if (error instanceof Error && !error.isAxiosError) {
97
+ return error;
98
+ }
99
+ let message;
100
+ let statusCode;
101
+ if (axios__default.default.isAxiosError(error)) {
102
+ statusCode = error.response?.status;
103
+ const responseData = error.response?.data;
104
+ if (responseData?.message) {
105
+ message = responseData.message;
106
+ } else if (!error.response) {
107
+ if (error.code === "ECONNABORTED" || error.message.includes("timeout")) {
108
+ message = ERROR_MESSAGES.TIMEOUT;
109
+ } else if (error.code === "ERR_NETWORK" || error.message === "Network Error") {
110
+ message = ERROR_MESSAGES.NETWORK_ERROR;
111
+ } else {
112
+ message = ERROR_MESSAGES.NETWORK_ERROR;
113
+ }
114
+ } else {
115
+ switch (statusCode) {
116
+ case 400:
117
+ message = responseData?.message || "Invalid request. Please check your input.";
118
+ break;
119
+ case 401:
120
+ message = responseData?.message || ERROR_MESSAGES.UNAUTHORIZED;
121
+ break;
122
+ case 403:
123
+ message = responseData?.message || ERROR_MESSAGES.FORBIDDEN;
124
+ break;
125
+ case 404:
126
+ message = responseData?.message || ERROR_MESSAGES.NOT_FOUND;
127
+ break;
128
+ case 429:
129
+ message = ERROR_MESSAGES.RATE_LIMITED;
130
+ break;
131
+ case 500:
132
+ case 502:
133
+ case 503:
134
+ case 504:
135
+ message = ERROR_MESSAGES.SERVER_ERROR;
136
+ break;
137
+ default:
138
+ message = responseData?.message || ERROR_MESSAGES.UNKNOWN;
139
+ }
140
+ }
141
+ } else {
142
+ message = error?.message || ERROR_MESSAGES.UNKNOWN;
143
+ }
144
+ const customError = new Error(message);
145
+ customError.response = error?.response;
146
+ customError.statusCode = statusCode;
147
+ customError.originalError = error;
148
+ return customError;
149
+ }
86
150
  async get(endpoint, headers) {
87
151
  const response = await this.axiosInstance.get(endpoint, { headers });
88
152
  return response.data;
@@ -133,16 +197,134 @@ var HttpClient = class {
133
197
  }
134
198
  }
135
199
  };
200
+ var SocketService = class {
201
+ constructor(config) {
202
+ this.socket = null;
203
+ this.token = null;
204
+ this.eventHandlers = /* @__PURE__ */ new Map();
205
+ this.isConnecting = false;
206
+ this.config = {
207
+ autoConnect: false,
208
+ reconnection: true,
209
+ reconnectionAttempts: 5,
210
+ reconnectionDelay: 1e3,
211
+ ...config
212
+ };
213
+ }
214
+ connect(token) {
215
+ if (this.socket?.connected || this.isConnecting) {
216
+ return;
217
+ }
218
+ this.token = token;
219
+ this.isConnecting = true;
220
+ this.socket = socket_ioClient.io(this.config.baseUrl, {
221
+ auth: { token },
222
+ autoConnect: true,
223
+ reconnection: this.config.reconnection,
224
+ reconnectionAttempts: this.config.reconnectionAttempts,
225
+ reconnectionDelay: this.config.reconnectionDelay,
226
+ transports: ["websocket", "polling"]
227
+ });
228
+ this.setupEventListeners();
229
+ }
230
+ setupEventListeners() {
231
+ if (!this.socket) return;
232
+ this.socket.on("connect", () => {
233
+ this.isConnecting = false;
234
+ console.log("[Auth SDK] Socket connected");
235
+ this.emit("connected", {});
236
+ });
237
+ this.socket.on("disconnect", (reason) => {
238
+ console.log("[Auth SDK] Socket disconnected:", reason);
239
+ this.emit("disconnected", { reason });
240
+ });
241
+ this.socket.on("connect_error", (error) => {
242
+ this.isConnecting = false;
243
+ console.error("[Auth SDK] Socket connection error:", error.message);
244
+ this.emit("error", { error: error.message });
245
+ });
246
+ this.socket.on("user:updated", (data) => {
247
+ this.emit("user:updated", data);
248
+ });
249
+ this.socket.on("session:revoked", (data) => {
250
+ this.emit("session:revoked", data);
251
+ });
252
+ this.socket.on("session:all-revoked", () => {
253
+ this.emit("session:all-revoked", {});
254
+ });
255
+ this.socket.on("auth:password-changed", () => {
256
+ this.emit("auth:password-changed", {});
257
+ });
258
+ this.socket.on("auth:2fa-changed", (data) => {
259
+ this.emit("auth:2fa-changed", data);
260
+ });
261
+ this.socket.on("user:refresh", () => {
262
+ this.emit("user:refresh", {});
263
+ });
264
+ }
265
+ disconnect() {
266
+ if (this.socket) {
267
+ this.socket.disconnect();
268
+ this.socket = null;
269
+ this.token = null;
270
+ this.isConnecting = false;
271
+ }
272
+ }
273
+ isConnected() {
274
+ return this.socket?.connected ?? false;
275
+ }
276
+ // Event subscription
277
+ on(event, handler) {
278
+ if (!this.eventHandlers.has(event)) {
279
+ this.eventHandlers.set(event, /* @__PURE__ */ new Set());
280
+ }
281
+ this.eventHandlers.get(event).add(handler);
282
+ return () => {
283
+ this.eventHandlers.get(event)?.delete(handler);
284
+ };
285
+ }
286
+ off(event, handler) {
287
+ if (handler) {
288
+ this.eventHandlers.get(event)?.delete(handler);
289
+ } else {
290
+ this.eventHandlers.delete(event);
291
+ }
292
+ }
293
+ emit(event, data) {
294
+ const handlers = this.eventHandlers.get(event);
295
+ if (handlers) {
296
+ handlers.forEach((handler) => {
297
+ try {
298
+ handler(data);
299
+ } catch (error) {
300
+ console.error(`[Auth SDK] Error in event handler for ${event}:`, error);
301
+ }
302
+ });
303
+ }
304
+ }
305
+ // Request fresh user data from server
306
+ requestUserRefresh() {
307
+ if (this.socket?.connected) {
308
+ this.socket.emit("request:user");
309
+ }
310
+ }
311
+ };
136
312
  var AuthService = class {
313
+ // 5 minutes cache
137
314
  constructor(config) {
138
315
  this.token = null;
139
316
  this.upfilesClient = null;
317
+ this.cachedUser = null;
318
+ this.userCacheTimestamp = 0;
319
+ this.USER_CACHE_TTL = 5 * 60 * 1e3;
140
320
  this.config = {
141
321
  localStorageKey: "auth_token",
142
322
  csrfEnabled: true,
323
+ enableSocket: true,
143
324
  ...config
144
325
  };
145
326
  this.httpClient = new HttpClient(this.config.baseUrl);
327
+ this.socketService = new SocketService({ baseUrl: this.config.baseUrl });
146
328
  this.loadTokenFromStorage();
147
329
  if (this.config.upfilesConfig) {
148
330
  this.upfilesClient = new upfiles.UpfilesClient({
@@ -159,6 +341,9 @@ var AuthService = class {
159
341
  this.httpClient.setFrontendBaseUrl(frontendBaseUrl);
160
342
  }
161
343
  }
344
+ if (this.token && this.config.enableSocket !== false) {
345
+ this.connectSocket();
346
+ }
162
347
  }
163
348
  loadTokenFromStorage() {
164
349
  if (typeof window !== "undefined" && this.config.localStorageKey) {
@@ -191,6 +376,57 @@ var AuthService = class {
191
376
  }
192
377
  }
193
378
  }
379
+ // Socket connection management
380
+ connectSocket() {
381
+ if (this.token && this.config.enableSocket !== false && typeof window !== "undefined") {
382
+ this.socketService.connect(this.token);
383
+ }
384
+ }
385
+ disconnectSocket() {
386
+ this.socketService.disconnect();
387
+ }
388
+ // Socket event subscription
389
+ onUserUpdated(handler) {
390
+ return this.socketService.on("user:updated", (data) => {
391
+ if (data.user) {
392
+ this.cachedUser = data.user;
393
+ this.userCacheTimestamp = Date.now();
394
+ }
395
+ handler(data);
396
+ });
397
+ }
398
+ onSessionRevoked(handler) {
399
+ return this.socketService.on("session:revoked", handler);
400
+ }
401
+ onAllSessionsRevoked(handler) {
402
+ return this.socketService.on("session:all-revoked", handler);
403
+ }
404
+ onPasswordChanged(handler) {
405
+ return this.socketService.on("auth:password-changed", handler);
406
+ }
407
+ on2FAChanged(handler) {
408
+ return this.socketService.on("auth:2fa-changed", handler);
409
+ }
410
+ onSocketConnected(handler) {
411
+ return this.socketService.on("connected", handler);
412
+ }
413
+ onSocketDisconnected(handler) {
414
+ return this.socketService.on("disconnected", handler);
415
+ }
416
+ onSocketError(handler) {
417
+ return this.socketService.on("error", handler);
418
+ }
419
+ isSocketConnected() {
420
+ return this.socketService.isConnected();
421
+ }
422
+ // Cache management
423
+ clearUserCache() {
424
+ this.cachedUser = null;
425
+ this.userCacheTimestamp = 0;
426
+ }
427
+ isCacheValid() {
428
+ return this.cachedUser !== null && Date.now() - this.userCacheTimestamp < this.USER_CACHE_TTL;
429
+ }
194
430
  isAuthenticated() {
195
431
  return !!this.token;
196
432
  }
@@ -256,6 +492,11 @@ var AuthService = class {
256
492
  this.token = response.token;
257
493
  this.httpClient.setAuthToken(response.token);
258
494
  this.saveTokenToStorage(response.token);
495
+ if (response.user) {
496
+ this.cachedUser = response.user;
497
+ this.userCacheTimestamp = Date.now();
498
+ }
499
+ this.connectSocket();
259
500
  return response;
260
501
  }
261
502
  if (response.success && (response.message === "OTP sent to your email." || response.message === "OTP sent to your phone number.")) {
@@ -265,6 +506,11 @@ var AuthService = class {
265
506
  this.token = response.token;
266
507
  this.httpClient.setAuthToken(response.token);
267
508
  this.saveTokenToStorage(response.token);
509
+ if (response.user) {
510
+ this.cachedUser = response.user;
511
+ this.userCacheTimestamp = Date.now();
512
+ }
513
+ this.connectSocket();
268
514
  return response;
269
515
  }
270
516
  throw new Error(response.message || "Login failed");
@@ -308,21 +554,29 @@ var AuthService = class {
308
554
  }
309
555
  }
310
556
  async logout() {
557
+ this.disconnectSocket();
311
558
  try {
312
559
  await this.httpClient.post("/api/v1/auth/logout", {});
313
560
  } catch (error) {
314
561
  console.warn("Failed to call logout endpoint:", error);
315
562
  }
316
563
  this.token = null;
564
+ this.cachedUser = null;
565
+ this.userCacheTimestamp = 0;
317
566
  this.httpClient.removeAuthToken();
318
567
  this.httpClient.removeCsrfToken();
319
568
  this.removeTokenFromStorage();
320
569
  }
321
- async getProfile() {
570
+ async getProfile(forceRefresh = false) {
322
571
  if (!this.token) {
323
572
  throw new Error("Not authenticated");
324
573
  }
574
+ if (!forceRefresh && this.isCacheValid() && this.cachedUser) {
575
+ return this.cachedUser;
576
+ }
325
577
  const response = await this.httpClient.get("/api/v1/user/me");
578
+ this.cachedUser = response.user;
579
+ this.userCacheTimestamp = Date.now();
326
580
  return response.user;
327
581
  }
328
582
  async updateProfile(data) {
@@ -486,6 +740,16 @@ var AuthService = class {
486
740
  );
487
741
  return response;
488
742
  }
743
+ async adminCreateUser(data) {
744
+ if (!this.token) {
745
+ throw new Error("Not authenticated");
746
+ }
747
+ const response = await this.httpClient.post(
748
+ "/api/v1/admin/create-user",
749
+ data
750
+ );
751
+ return response;
752
+ }
489
753
  async adminVerifyUser(userId) {
490
754
  if (!this.token) {
491
755
  throw new Error("Not authenticated");
@@ -578,21 +842,49 @@ var AuthProvider = ({ children, config }) => {
578
842
  const [user, setUser] = React.useState(null);
579
843
  const [isLoaded, setIsLoaded] = React.useState(false);
580
844
  const [loading, setLoading] = React.useState(false);
581
- const checkAuthStatus = React.useCallback(async () => {
845
+ const [isSocketConnected, setIsSocketConnected] = React.useState(false);
846
+ React.useEffect(() => {
847
+ const unsubUserUpdated = authService.onUserUpdated(({ user: updatedUser }) => {
848
+ if (updatedUser) {
849
+ setUser(updatedUser);
850
+ }
851
+ });
852
+ const unsubSessionRevoked = authService.onSessionRevoked(() => {
853
+ authService.logout().then(() => {
854
+ setUser(null);
855
+ });
856
+ });
857
+ const unsubAllSessionsRevoked = authService.onAllSessionsRevoked(() => {
858
+ authService.logout().then(() => {
859
+ setUser(null);
860
+ });
861
+ });
862
+ const unsubPasswordChanged = authService.onPasswordChanged(() => {
863
+ authService.logout().then(() => {
864
+ setUser(null);
865
+ });
866
+ });
867
+ const unsubConnected = authService.onSocketConnected(() => {
868
+ setIsSocketConnected(true);
869
+ });
870
+ const unsubDisconnected = authService.onSocketDisconnected(() => {
871
+ setIsSocketConnected(false);
872
+ });
873
+ return () => {
874
+ unsubUserUpdated();
875
+ unsubSessionRevoked();
876
+ unsubAllSessionsRevoked();
877
+ unsubPasswordChanged();
878
+ unsubConnected();
879
+ unsubDisconnected();
880
+ };
881
+ }, [authService]);
882
+ React.useEffect(() => {
582
883
  const authenticated = authService.isAuthenticated();
583
884
  if (authenticated) {
584
- try {
585
- const freshUser = await authService.getProfile();
586
- setUser(freshUser);
587
- } catch (error) {
588
- console.error("Failed to fetch fresh user profile, falling back to token:", error);
589
- try {
590
- const currentUser = authService.getCurrentUser();
591
- setUser(currentUser);
592
- } catch (fallbackError) {
593
- console.error("Failed to get current user from token:", fallbackError);
594
- setUser(null);
595
- }
885
+ const currentUser = authService.getCurrentUser();
886
+ if (currentUser) {
887
+ setUser(currentUser);
596
888
  }
597
889
  } else {
598
890
  setUser(null);
@@ -600,8 +892,21 @@ var AuthProvider = ({ children, config }) => {
600
892
  setIsLoaded(true);
601
893
  }, [authService]);
602
894
  React.useEffect(() => {
603
- checkAuthStatus();
604
- }, [checkAuthStatus]);
895
+ if (!isLoaded) return;
896
+ const authenticated = authService.isAuthenticated();
897
+ if (!authenticated) return;
898
+ const fetchFreshUser = async () => {
899
+ try {
900
+ const freshUser = await authService.getProfile();
901
+ setUser(freshUser);
902
+ } catch (error) {
903
+ console.warn("[Auth SDK] Failed to fetch fresh user profile:", error);
904
+ }
905
+ };
906
+ if (isSocketConnected) {
907
+ fetchFreshUser();
908
+ }
909
+ }, [authService, isLoaded, isSocketConnected]);
605
910
  const signIn = React.useCallback(async (data) => {
606
911
  setLoading(true);
607
912
  try {
@@ -823,6 +1128,7 @@ var AuthProvider = ({ children, config }) => {
823
1128
  isLoaded,
824
1129
  isSignedIn: !!user,
825
1130
  loading,
1131
+ isSocketConnected,
826
1132
  signIn,
827
1133
  signUp,
828
1134
  signOut,
@@ -3707,15 +4013,15 @@ var VerifyEmail = ({ token, onSuccess, onError }) => {
3707
4013
  const [message, setMessage] = React.useState("");
3708
4014
  React.useEffect(() => {
3709
4015
  const verify = async () => {
3710
- const verifyToken = token || (typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null);
3711
- if (!verifyToken) {
4016
+ const verifyToken2 = token || (typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null);
4017
+ if (!verifyToken2) {
3712
4018
  setStatus("error");
3713
4019
  setMessage("No verification token provided");
3714
4020
  onError?.("No verification token provided");
3715
4021
  return;
3716
4022
  }
3717
4023
  try {
3718
- const response = await verifyEmailToken(verifyToken);
4024
+ const response = await verifyEmailToken(verifyToken2);
3719
4025
  if (response.success) {
3720
4026
  setStatus("success");
3721
4027
  setMessage("Email verified successfully! Redirecting...");
@@ -4474,11 +4780,11 @@ var ChangePassword = ({ onSuccess, appearance }) => {
4474
4780
 
4475
4781
  // src/react/components/utils/injectModalStyles.ts
4476
4782
  var injectModalStyles = () => {
4477
- if (document.getElementById("ttf-auth-modal-styles")) {
4783
+ if (document.getElementById("ktw-auth-modal-styles")) {
4478
4784
  return;
4479
4785
  }
4480
4786
  const styleElement = document.createElement("style");
4481
- styleElement.id = "ttf-auth-modal-styles";
4787
+ styleElement.id = "ktw-auth-modal-styles";
4482
4788
  styleElement.textContent = `
4483
4789
  /* ImageManager Modal Styles - Critical for proper modal display */
4484
4790
  /* Radix UI Dialog styles - Force visibility */
@@ -5016,7 +5322,11 @@ __export(react_exports, {
5016
5322
  // src/node/index.ts
5017
5323
  var node_exports = {};
5018
5324
  __export(node_exports, {
5019
- AuthClient: () => AuthClient
5325
+ AuthClient: () => AuthClient,
5326
+ TokenVerifier: () => TokenVerifier,
5327
+ createTokenVerifier: () => createTokenVerifier,
5328
+ getTokenVerifier: () => getTokenVerifier,
5329
+ verifyToken: () => verifyToken
5020
5330
  });
5021
5331
 
5022
5332
  // src/node/auth-client.ts
@@ -5097,6 +5407,135 @@ var AuthClient = class extends AuthService {
5097
5407
  }
5098
5408
  };
5099
5409
 
5410
+ // src/node/token-verifier.ts
5411
+ var TokenVerifier = class {
5412
+ constructor(config) {
5413
+ this.cache = /* @__PURE__ */ new Map();
5414
+ this.cleanupInterval = null;
5415
+ this.config = {
5416
+ cacheTTL: 6e4,
5417
+ // 1 minute default
5418
+ cacheEnabled: true,
5419
+ ...config
5420
+ };
5421
+ if (this.config.cacheEnabled) {
5422
+ this.startCleanup();
5423
+ }
5424
+ }
5425
+ /**
5426
+ * Verify a JWT token and get user data
5427
+ * Returns cached user if available and valid
5428
+ */
5429
+ async verifyToken(token) {
5430
+ if (!token) {
5431
+ return null;
5432
+ }
5433
+ if (this.config.cacheEnabled) {
5434
+ const cached = this.getFromCache(token);
5435
+ if (cached) {
5436
+ return cached;
5437
+ }
5438
+ }
5439
+ try {
5440
+ const response = await fetch(`${this.config.authServiceUrl}/api/v1/user/me`, {
5441
+ headers: {
5442
+ "Authorization": `Bearer ${token}`,
5443
+ "Content-Type": "application/json"
5444
+ }
5445
+ });
5446
+ if (!response.ok) {
5447
+ this.cache.delete(token);
5448
+ return null;
5449
+ }
5450
+ const data = await response.json();
5451
+ const user = data.user || null;
5452
+ if (user && this.config.cacheEnabled) {
5453
+ this.setCache(token, user);
5454
+ }
5455
+ return user;
5456
+ } catch (error) {
5457
+ console.error("[TokenVerifier] Auth service verification failed:", error);
5458
+ return null;
5459
+ }
5460
+ }
5461
+ /**
5462
+ * Invalidate cache for a specific token
5463
+ */
5464
+ invalidateToken(token) {
5465
+ this.cache.delete(token);
5466
+ }
5467
+ /**
5468
+ * Clear all cached tokens
5469
+ */
5470
+ clearCache() {
5471
+ this.cache.clear();
5472
+ }
5473
+ /**
5474
+ * Get cache statistics
5475
+ */
5476
+ getCacheStats() {
5477
+ return {
5478
+ size: this.cache.size,
5479
+ enabled: this.config.cacheEnabled,
5480
+ ttl: this.config.cacheTTL
5481
+ };
5482
+ }
5483
+ /**
5484
+ * Stop the cleanup interval (call when shutting down)
5485
+ */
5486
+ destroy() {
5487
+ if (this.cleanupInterval) {
5488
+ clearInterval(this.cleanupInterval);
5489
+ this.cleanupInterval = null;
5490
+ }
5491
+ this.cache.clear();
5492
+ }
5493
+ getFromCache(token) {
5494
+ const entry = this.cache.get(token);
5495
+ if (!entry) {
5496
+ return null;
5497
+ }
5498
+ if (Date.now() > entry.expiresAt) {
5499
+ this.cache.delete(token);
5500
+ return null;
5501
+ }
5502
+ return entry.user;
5503
+ }
5504
+ setCache(token, user) {
5505
+ this.cache.set(token, {
5506
+ user,
5507
+ expiresAt: Date.now() + this.config.cacheTTL
5508
+ });
5509
+ }
5510
+ startCleanup() {
5511
+ this.cleanupInterval = setInterval(() => {
5512
+ const now = Date.now();
5513
+ for (const [token, entry] of this.cache.entries()) {
5514
+ if (now > entry.expiresAt) {
5515
+ this.cache.delete(token);
5516
+ }
5517
+ }
5518
+ }, 6e4);
5519
+ if (this.cleanupInterval && this.cleanupInterval.unref) {
5520
+ this.cleanupInterval.unref();
5521
+ }
5522
+ }
5523
+ };
5524
+ var defaultVerifier = null;
5525
+ function createTokenVerifier(config) {
5526
+ defaultVerifier = new TokenVerifier(config);
5527
+ return defaultVerifier;
5528
+ }
5529
+ function getTokenVerifier() {
5530
+ if (!defaultVerifier) {
5531
+ throw new Error("TokenVerifier not initialized. Call createTokenVerifier() first.");
5532
+ }
5533
+ return defaultVerifier;
5534
+ }
5535
+ async function verifyToken(token) {
5536
+ return getTokenVerifier().verifyToken(token);
5537
+ }
5538
+
5100
5539
  Object.defineProperty(exports, "ConnectProjectDialog", {
5101
5540
  enumerable: true,
5102
5541
  get: function () { return upfiles.ConnectProjectDialog; }
@@ -5135,6 +5574,7 @@ exports.ResetPassword = ResetPassword;
5135
5574
  exports.SignIn = SignIn;
5136
5575
  exports.SignOut = SignOut;
5137
5576
  exports.SignUp = SignUp;
5577
+ exports.SocketService = SocketService;
5138
5578
  exports.UserButton = UserButton;
5139
5579
  exports.UserProfile = UserProfile;
5140
5580
  exports.VerifyEmail = VerifyEmail;