@thetechfossil/auth2 1.2.19 → 1.2.20

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 +204 -3
  5. package/dist/index.components.js.map +1 -1
  6. package/dist/index.components.mjs +204 -3
  7. package/dist/index.components.mjs.map +1 -1
  8. package/dist/index.d.mts +110 -3
  9. package/dist/index.d.ts +110 -3
  10. package/dist/index.js +399 -22
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +400 -24
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/index.next.d.mts +53 -1
  15. package/dist/index.next.d.ts +53 -1
  16. package/dist/index.next.js +261 -18
  17. package/dist/index.next.js.map +1 -1
  18. package/dist/index.next.mjs +261 -18
  19. package/dist/index.next.mjs.map +1 -1
  20. package/dist/index.next.server.d.mts +80 -2
  21. package/dist/index.next.server.d.ts +80 -2
  22. package/dist/index.next.server.js +335 -1
  23. package/dist/index.next.server.js.map +1 -1
  24. package/dist/index.next.server.mjs +332 -2
  25. package/dist/index.next.server.mjs.map +1 -1
  26. package/dist/index.node.d.mts +80 -2
  27. package/dist/index.node.d.ts +80 -2
  28. package/dist/index.node.js +335 -1
  29. package/dist/index.node.js.map +1 -1
  30. package/dist/index.node.mjs +332 -2
  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');
@@ -133,16 +134,134 @@ var HttpClient = class {
133
134
  }
134
135
  }
135
136
  };
137
+ var SocketService = class {
138
+ constructor(config) {
139
+ this.socket = null;
140
+ this.token = null;
141
+ this.eventHandlers = /* @__PURE__ */ new Map();
142
+ this.isConnecting = false;
143
+ this.config = {
144
+ autoConnect: false,
145
+ reconnection: true,
146
+ reconnectionAttempts: 5,
147
+ reconnectionDelay: 1e3,
148
+ ...config
149
+ };
150
+ }
151
+ connect(token) {
152
+ if (this.socket?.connected || this.isConnecting) {
153
+ return;
154
+ }
155
+ this.token = token;
156
+ this.isConnecting = true;
157
+ this.socket = socket_ioClient.io(this.config.baseUrl, {
158
+ auth: { token },
159
+ autoConnect: true,
160
+ reconnection: this.config.reconnection,
161
+ reconnectionAttempts: this.config.reconnectionAttempts,
162
+ reconnectionDelay: this.config.reconnectionDelay,
163
+ transports: ["websocket", "polling"]
164
+ });
165
+ this.setupEventListeners();
166
+ }
167
+ setupEventListeners() {
168
+ if (!this.socket) return;
169
+ this.socket.on("connect", () => {
170
+ this.isConnecting = false;
171
+ console.log("[Auth SDK] Socket connected");
172
+ this.emit("connected", {});
173
+ });
174
+ this.socket.on("disconnect", (reason) => {
175
+ console.log("[Auth SDK] Socket disconnected:", reason);
176
+ this.emit("disconnected", { reason });
177
+ });
178
+ this.socket.on("connect_error", (error) => {
179
+ this.isConnecting = false;
180
+ console.error("[Auth SDK] Socket connection error:", error.message);
181
+ this.emit("error", { error: error.message });
182
+ });
183
+ this.socket.on("user:updated", (data) => {
184
+ this.emit("user:updated", data);
185
+ });
186
+ this.socket.on("session:revoked", (data) => {
187
+ this.emit("session:revoked", data);
188
+ });
189
+ this.socket.on("session:all-revoked", () => {
190
+ this.emit("session:all-revoked", {});
191
+ });
192
+ this.socket.on("auth:password-changed", () => {
193
+ this.emit("auth:password-changed", {});
194
+ });
195
+ this.socket.on("auth:2fa-changed", (data) => {
196
+ this.emit("auth:2fa-changed", data);
197
+ });
198
+ this.socket.on("user:refresh", () => {
199
+ this.emit("user:refresh", {});
200
+ });
201
+ }
202
+ disconnect() {
203
+ if (this.socket) {
204
+ this.socket.disconnect();
205
+ this.socket = null;
206
+ this.token = null;
207
+ this.isConnecting = false;
208
+ }
209
+ }
210
+ isConnected() {
211
+ return this.socket?.connected ?? false;
212
+ }
213
+ // Event subscription
214
+ on(event, handler) {
215
+ if (!this.eventHandlers.has(event)) {
216
+ this.eventHandlers.set(event, /* @__PURE__ */ new Set());
217
+ }
218
+ this.eventHandlers.get(event).add(handler);
219
+ return () => {
220
+ this.eventHandlers.get(event)?.delete(handler);
221
+ };
222
+ }
223
+ off(event, handler) {
224
+ if (handler) {
225
+ this.eventHandlers.get(event)?.delete(handler);
226
+ } else {
227
+ this.eventHandlers.delete(event);
228
+ }
229
+ }
230
+ emit(event, data) {
231
+ const handlers = this.eventHandlers.get(event);
232
+ if (handlers) {
233
+ handlers.forEach((handler) => {
234
+ try {
235
+ handler(data);
236
+ } catch (error) {
237
+ console.error(`[Auth SDK] Error in event handler for ${event}:`, error);
238
+ }
239
+ });
240
+ }
241
+ }
242
+ // Request fresh user data from server
243
+ requestUserRefresh() {
244
+ if (this.socket?.connected) {
245
+ this.socket.emit("request:user");
246
+ }
247
+ }
248
+ };
136
249
  var AuthService = class {
250
+ // 5 minutes cache
137
251
  constructor(config) {
138
252
  this.token = null;
139
253
  this.upfilesClient = null;
254
+ this.cachedUser = null;
255
+ this.userCacheTimestamp = 0;
256
+ this.USER_CACHE_TTL = 5 * 60 * 1e3;
140
257
  this.config = {
141
258
  localStorageKey: "auth_token",
142
259
  csrfEnabled: true,
260
+ enableSocket: true,
143
261
  ...config
144
262
  };
145
263
  this.httpClient = new HttpClient(this.config.baseUrl);
264
+ this.socketService = new SocketService({ baseUrl: this.config.baseUrl });
146
265
  this.loadTokenFromStorage();
147
266
  if (this.config.upfilesConfig) {
148
267
  this.upfilesClient = new upfiles.UpfilesClient({
@@ -159,6 +278,9 @@ var AuthService = class {
159
278
  this.httpClient.setFrontendBaseUrl(frontendBaseUrl);
160
279
  }
161
280
  }
281
+ if (this.token && this.config.enableSocket !== false) {
282
+ this.connectSocket();
283
+ }
162
284
  }
163
285
  loadTokenFromStorage() {
164
286
  if (typeof window !== "undefined" && this.config.localStorageKey) {
@@ -191,6 +313,57 @@ var AuthService = class {
191
313
  }
192
314
  }
193
315
  }
316
+ // Socket connection management
317
+ connectSocket() {
318
+ if (this.token && this.config.enableSocket !== false && typeof window !== "undefined") {
319
+ this.socketService.connect(this.token);
320
+ }
321
+ }
322
+ disconnectSocket() {
323
+ this.socketService.disconnect();
324
+ }
325
+ // Socket event subscription
326
+ onUserUpdated(handler) {
327
+ return this.socketService.on("user:updated", (data) => {
328
+ if (data.user) {
329
+ this.cachedUser = data.user;
330
+ this.userCacheTimestamp = Date.now();
331
+ }
332
+ handler(data);
333
+ });
334
+ }
335
+ onSessionRevoked(handler) {
336
+ return this.socketService.on("session:revoked", handler);
337
+ }
338
+ onAllSessionsRevoked(handler) {
339
+ return this.socketService.on("session:all-revoked", handler);
340
+ }
341
+ onPasswordChanged(handler) {
342
+ return this.socketService.on("auth:password-changed", handler);
343
+ }
344
+ on2FAChanged(handler) {
345
+ return this.socketService.on("auth:2fa-changed", handler);
346
+ }
347
+ onSocketConnected(handler) {
348
+ return this.socketService.on("connected", handler);
349
+ }
350
+ onSocketDisconnected(handler) {
351
+ return this.socketService.on("disconnected", handler);
352
+ }
353
+ onSocketError(handler) {
354
+ return this.socketService.on("error", handler);
355
+ }
356
+ isSocketConnected() {
357
+ return this.socketService.isConnected();
358
+ }
359
+ // Cache management
360
+ clearUserCache() {
361
+ this.cachedUser = null;
362
+ this.userCacheTimestamp = 0;
363
+ }
364
+ isCacheValid() {
365
+ return this.cachedUser !== null && Date.now() - this.userCacheTimestamp < this.USER_CACHE_TTL;
366
+ }
194
367
  isAuthenticated() {
195
368
  return !!this.token;
196
369
  }
@@ -256,6 +429,11 @@ var AuthService = class {
256
429
  this.token = response.token;
257
430
  this.httpClient.setAuthToken(response.token);
258
431
  this.saveTokenToStorage(response.token);
432
+ if (response.user) {
433
+ this.cachedUser = response.user;
434
+ this.userCacheTimestamp = Date.now();
435
+ }
436
+ this.connectSocket();
259
437
  return response;
260
438
  }
261
439
  if (response.success && (response.message === "OTP sent to your email." || response.message === "OTP sent to your phone number.")) {
@@ -265,6 +443,11 @@ var AuthService = class {
265
443
  this.token = response.token;
266
444
  this.httpClient.setAuthToken(response.token);
267
445
  this.saveTokenToStorage(response.token);
446
+ if (response.user) {
447
+ this.cachedUser = response.user;
448
+ this.userCacheTimestamp = Date.now();
449
+ }
450
+ this.connectSocket();
268
451
  return response;
269
452
  }
270
453
  throw new Error(response.message || "Login failed");
@@ -308,21 +491,29 @@ var AuthService = class {
308
491
  }
309
492
  }
310
493
  async logout() {
494
+ this.disconnectSocket();
311
495
  try {
312
496
  await this.httpClient.post("/api/v1/auth/logout", {});
313
497
  } catch (error) {
314
498
  console.warn("Failed to call logout endpoint:", error);
315
499
  }
316
500
  this.token = null;
501
+ this.cachedUser = null;
502
+ this.userCacheTimestamp = 0;
317
503
  this.httpClient.removeAuthToken();
318
504
  this.httpClient.removeCsrfToken();
319
505
  this.removeTokenFromStorage();
320
506
  }
321
- async getProfile() {
507
+ async getProfile(forceRefresh = false) {
322
508
  if (!this.token) {
323
509
  throw new Error("Not authenticated");
324
510
  }
511
+ if (!forceRefresh && this.isCacheValid() && this.cachedUser) {
512
+ return this.cachedUser;
513
+ }
325
514
  const response = await this.httpClient.get("/api/v1/user/me");
515
+ this.cachedUser = response.user;
516
+ this.userCacheTimestamp = Date.now();
326
517
  return response.user;
327
518
  }
328
519
  async updateProfile(data) {
@@ -486,6 +677,16 @@ var AuthService = class {
486
677
  );
487
678
  return response;
488
679
  }
680
+ async adminCreateUser(data) {
681
+ if (!this.token) {
682
+ throw new Error("Not authenticated");
683
+ }
684
+ const response = await this.httpClient.post(
685
+ "/api/v1/admin/create-user",
686
+ data
687
+ );
688
+ return response;
689
+ }
489
690
  async adminVerifyUser(userId) {
490
691
  if (!this.token) {
491
692
  throw new Error("Not authenticated");
@@ -578,21 +779,49 @@ var AuthProvider = ({ children, config }) => {
578
779
  const [user, setUser] = React.useState(null);
579
780
  const [isLoaded, setIsLoaded] = React.useState(false);
580
781
  const [loading, setLoading] = React.useState(false);
581
- const checkAuthStatus = React.useCallback(async () => {
782
+ const [isSocketConnected, setIsSocketConnected] = React.useState(false);
783
+ React.useEffect(() => {
784
+ const unsubUserUpdated = authService.onUserUpdated(({ user: updatedUser }) => {
785
+ if (updatedUser) {
786
+ setUser(updatedUser);
787
+ }
788
+ });
789
+ const unsubSessionRevoked = authService.onSessionRevoked(() => {
790
+ authService.logout().then(() => {
791
+ setUser(null);
792
+ });
793
+ });
794
+ const unsubAllSessionsRevoked = authService.onAllSessionsRevoked(() => {
795
+ authService.logout().then(() => {
796
+ setUser(null);
797
+ });
798
+ });
799
+ const unsubPasswordChanged = authService.onPasswordChanged(() => {
800
+ authService.logout().then(() => {
801
+ setUser(null);
802
+ });
803
+ });
804
+ const unsubConnected = authService.onSocketConnected(() => {
805
+ setIsSocketConnected(true);
806
+ });
807
+ const unsubDisconnected = authService.onSocketDisconnected(() => {
808
+ setIsSocketConnected(false);
809
+ });
810
+ return () => {
811
+ unsubUserUpdated();
812
+ unsubSessionRevoked();
813
+ unsubAllSessionsRevoked();
814
+ unsubPasswordChanged();
815
+ unsubConnected();
816
+ unsubDisconnected();
817
+ };
818
+ }, [authService]);
819
+ React.useEffect(() => {
582
820
  const authenticated = authService.isAuthenticated();
583
821
  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
- }
822
+ const currentUser = authService.getCurrentUser();
823
+ if (currentUser) {
824
+ setUser(currentUser);
596
825
  }
597
826
  } else {
598
827
  setUser(null);
@@ -600,8 +829,21 @@ var AuthProvider = ({ children, config }) => {
600
829
  setIsLoaded(true);
601
830
  }, [authService]);
602
831
  React.useEffect(() => {
603
- checkAuthStatus();
604
- }, [checkAuthStatus]);
832
+ if (!isLoaded) return;
833
+ const authenticated = authService.isAuthenticated();
834
+ if (!authenticated) return;
835
+ const fetchFreshUser = async () => {
836
+ try {
837
+ const freshUser = await authService.getProfile();
838
+ setUser(freshUser);
839
+ } catch (error) {
840
+ console.warn("[Auth SDK] Failed to fetch fresh user profile:", error);
841
+ }
842
+ };
843
+ if (isSocketConnected) {
844
+ fetchFreshUser();
845
+ }
846
+ }, [authService, isLoaded, isSocketConnected]);
605
847
  const signIn = React.useCallback(async (data) => {
606
848
  setLoading(true);
607
849
  try {
@@ -823,6 +1065,7 @@ var AuthProvider = ({ children, config }) => {
823
1065
  isLoaded,
824
1066
  isSignedIn: !!user,
825
1067
  loading,
1068
+ isSocketConnected,
826
1069
  signIn,
827
1070
  signUp,
828
1071
  signOut,
@@ -3707,15 +3950,15 @@ var VerifyEmail = ({ token, onSuccess, onError }) => {
3707
3950
  const [message, setMessage] = React.useState("");
3708
3951
  React.useEffect(() => {
3709
3952
  const verify = async () => {
3710
- const verifyToken = token || (typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null);
3711
- if (!verifyToken) {
3953
+ const verifyToken2 = token || (typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null);
3954
+ if (!verifyToken2) {
3712
3955
  setStatus("error");
3713
3956
  setMessage("No verification token provided");
3714
3957
  onError?.("No verification token provided");
3715
3958
  return;
3716
3959
  }
3717
3960
  try {
3718
- const response = await verifyEmailToken(verifyToken);
3961
+ const response = await verifyEmailToken(verifyToken2);
3719
3962
  if (response.success) {
3720
3963
  setStatus("success");
3721
3964
  setMessage("Email verified successfully! Redirecting...");
@@ -4474,11 +4717,11 @@ var ChangePassword = ({ onSuccess, appearance }) => {
4474
4717
 
4475
4718
  // src/react/components/utils/injectModalStyles.ts
4476
4719
  var injectModalStyles = () => {
4477
- if (document.getElementById("ttf-auth-modal-styles")) {
4720
+ if (document.getElementById("ktw-auth-modal-styles")) {
4478
4721
  return;
4479
4722
  }
4480
4723
  const styleElement = document.createElement("style");
4481
- styleElement.id = "ttf-auth-modal-styles";
4724
+ styleElement.id = "ktw-auth-modal-styles";
4482
4725
  styleElement.textContent = `
4483
4726
  /* ImageManager Modal Styles - Critical for proper modal display */
4484
4727
  /* Radix UI Dialog styles - Force visibility */
@@ -5016,7 +5259,11 @@ __export(react_exports, {
5016
5259
  // src/node/index.ts
5017
5260
  var node_exports = {};
5018
5261
  __export(node_exports, {
5019
- AuthClient: () => AuthClient
5262
+ AuthClient: () => AuthClient,
5263
+ TokenVerifier: () => TokenVerifier,
5264
+ createTokenVerifier: () => createTokenVerifier,
5265
+ getTokenVerifier: () => getTokenVerifier,
5266
+ verifyToken: () => verifyToken
5020
5267
  });
5021
5268
 
5022
5269
  // src/node/auth-client.ts
@@ -5097,6 +5344,135 @@ var AuthClient = class extends AuthService {
5097
5344
  }
5098
5345
  };
5099
5346
 
5347
+ // src/node/token-verifier.ts
5348
+ var TokenVerifier = class {
5349
+ constructor(config) {
5350
+ this.cache = /* @__PURE__ */ new Map();
5351
+ this.cleanupInterval = null;
5352
+ this.config = {
5353
+ cacheTTL: 6e4,
5354
+ // 1 minute default
5355
+ cacheEnabled: true,
5356
+ ...config
5357
+ };
5358
+ if (this.config.cacheEnabled) {
5359
+ this.startCleanup();
5360
+ }
5361
+ }
5362
+ /**
5363
+ * Verify a JWT token and get user data
5364
+ * Returns cached user if available and valid
5365
+ */
5366
+ async verifyToken(token) {
5367
+ if (!token) {
5368
+ return null;
5369
+ }
5370
+ if (this.config.cacheEnabled) {
5371
+ const cached = this.getFromCache(token);
5372
+ if (cached) {
5373
+ return cached;
5374
+ }
5375
+ }
5376
+ try {
5377
+ const response = await fetch(`${this.config.authServiceUrl}/api/v1/user/me`, {
5378
+ headers: {
5379
+ "Authorization": `Bearer ${token}`,
5380
+ "Content-Type": "application/json"
5381
+ }
5382
+ });
5383
+ if (!response.ok) {
5384
+ this.cache.delete(token);
5385
+ return null;
5386
+ }
5387
+ const data = await response.json();
5388
+ const user = data.user || null;
5389
+ if (user && this.config.cacheEnabled) {
5390
+ this.setCache(token, user);
5391
+ }
5392
+ return user;
5393
+ } catch (error) {
5394
+ console.error("[TokenVerifier] Auth service verification failed:", error);
5395
+ return null;
5396
+ }
5397
+ }
5398
+ /**
5399
+ * Invalidate cache for a specific token
5400
+ */
5401
+ invalidateToken(token) {
5402
+ this.cache.delete(token);
5403
+ }
5404
+ /**
5405
+ * Clear all cached tokens
5406
+ */
5407
+ clearCache() {
5408
+ this.cache.clear();
5409
+ }
5410
+ /**
5411
+ * Get cache statistics
5412
+ */
5413
+ getCacheStats() {
5414
+ return {
5415
+ size: this.cache.size,
5416
+ enabled: this.config.cacheEnabled,
5417
+ ttl: this.config.cacheTTL
5418
+ };
5419
+ }
5420
+ /**
5421
+ * Stop the cleanup interval (call when shutting down)
5422
+ */
5423
+ destroy() {
5424
+ if (this.cleanupInterval) {
5425
+ clearInterval(this.cleanupInterval);
5426
+ this.cleanupInterval = null;
5427
+ }
5428
+ this.cache.clear();
5429
+ }
5430
+ getFromCache(token) {
5431
+ const entry = this.cache.get(token);
5432
+ if (!entry) {
5433
+ return null;
5434
+ }
5435
+ if (Date.now() > entry.expiresAt) {
5436
+ this.cache.delete(token);
5437
+ return null;
5438
+ }
5439
+ return entry.user;
5440
+ }
5441
+ setCache(token, user) {
5442
+ this.cache.set(token, {
5443
+ user,
5444
+ expiresAt: Date.now() + this.config.cacheTTL
5445
+ });
5446
+ }
5447
+ startCleanup() {
5448
+ this.cleanupInterval = setInterval(() => {
5449
+ const now = Date.now();
5450
+ for (const [token, entry] of this.cache.entries()) {
5451
+ if (now > entry.expiresAt) {
5452
+ this.cache.delete(token);
5453
+ }
5454
+ }
5455
+ }, 6e4);
5456
+ if (this.cleanupInterval && this.cleanupInterval.unref) {
5457
+ this.cleanupInterval.unref();
5458
+ }
5459
+ }
5460
+ };
5461
+ var defaultVerifier = null;
5462
+ function createTokenVerifier(config) {
5463
+ defaultVerifier = new TokenVerifier(config);
5464
+ return defaultVerifier;
5465
+ }
5466
+ function getTokenVerifier() {
5467
+ if (!defaultVerifier) {
5468
+ throw new Error("TokenVerifier not initialized. Call createTokenVerifier() first.");
5469
+ }
5470
+ return defaultVerifier;
5471
+ }
5472
+ async function verifyToken(token) {
5473
+ return getTokenVerifier().verifyToken(token);
5474
+ }
5475
+
5100
5476
  Object.defineProperty(exports, "ConnectProjectDialog", {
5101
5477
  enumerable: true,
5102
5478
  get: function () { return upfiles.ConnectProjectDialog; }
@@ -5135,6 +5511,7 @@ exports.ResetPassword = ResetPassword;
5135
5511
  exports.SignIn = SignIn;
5136
5512
  exports.SignOut = SignOut;
5137
5513
  exports.SignUp = SignUp;
5514
+ exports.SocketService = SocketService;
5138
5515
  exports.UserButton = UserButton;
5139
5516
  exports.UserProfile = UserProfile;
5140
5517
  exports.VerifyEmail = VerifyEmail;