@thetechfossil/auth2 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import { UpfilesClient } from '@thetechfossil/upfiles';
1
2
  import React, { ReactNode } from 'react';
2
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
@@ -64,6 +65,15 @@ interface AuthConfig {
64
65
  localStorageKey?: string;
65
66
  token?: string;
66
67
  csrfEnabled?: boolean;
68
+ upfilesConfig?: UpfilesConfig;
69
+ }
70
+ interface UpfilesConfig {
71
+ baseUrl: string;
72
+ apiKey?: string;
73
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
74
+ presignUrl?: string;
75
+ presignPath?: string;
76
+ folderPath?: string;
67
77
  }
68
78
  interface Session {
69
79
  id: string;
@@ -109,6 +119,7 @@ interface UseAuthReturn {
109
119
  refreshCsrfToken: () => Promise<void>;
110
120
  changePassword: (oldPassword: string, newPassword: string) => Promise<AuthResponse>;
111
121
  updateAvatar: (avatar: string) => Promise<AuthResponse>;
122
+ uploadAndUpdateAvatar: (file: File) => Promise<AuthResponse>;
112
123
  requestEmailChange: (newEmail: string) => Promise<AuthResponse>;
113
124
  verifyEmailChange: (token: string) => Promise<AuthResponse>;
114
125
  generate2FA: () => Promise<MFASetup>;
@@ -127,6 +138,7 @@ declare class AuthService {
127
138
  private httpClient;
128
139
  private config;
129
140
  private token;
141
+ private upfilesClient;
130
142
  constructor(config: AuthConfig);
131
143
  private loadTokenFromStorage;
132
144
  private saveTokenToStorage;
@@ -152,6 +164,8 @@ declare class AuthService {
152
164
  resetPassword(token: string, password: string): Promise<AuthResponse>;
153
165
  changePassword(oldPassword: string, newPassword: string): Promise<AuthResponse>;
154
166
  updateAvatar(avatar: string): Promise<AuthResponse>;
167
+ uploadAndUpdateAvatar(file: File): Promise<AuthResponse>;
168
+ getUpfilesClient(): UpfilesClient | null;
155
169
  requestEmailChange(newEmail: string): Promise<AuthResponse>;
156
170
  verifyEmailChange(token: string): Promise<AuthResponse>;
157
171
  generate2FA(): Promise<{
@@ -213,6 +227,7 @@ interface UseAuthReturnBase {
213
227
  getProfile: () => Promise<User>;
214
228
  getAllUsers: () => Promise<User[]>;
215
229
  getUserById: (id: string) => Promise<User>;
230
+ uploadAndUpdateAvatar: (file: File) => Promise<AuthResponse>;
216
231
  }
217
232
  declare const useAuth$1: (config: AuthConfig) => UseAuthReturnBase;
218
233
 
@@ -235,6 +250,7 @@ interface AuthContextValue {
235
250
  resetPassword: (token: string, password: string) => Promise<AuthResponse>;
236
251
  changePassword: (oldPassword: string, newPassword: string) => Promise<AuthResponse>;
237
252
  updateAvatar: (avatar: string) => Promise<AuthResponse>;
253
+ uploadAndUpdateAvatar: (file: File) => Promise<AuthResponse>;
238
254
  requestEmailChange: (newEmail: string) => Promise<AuthResponse>;
239
255
  verifyEmailChange: (token: string) => Promise<AuthResponse>;
240
256
  generate2FA: () => Promise<any>;
@@ -438,6 +454,48 @@ interface PhoneInputProps {
438
454
  }
439
455
  declare const PhoneInput: React.FC<PhoneInputProps>;
440
456
 
457
+ interface AvatarUploaderProps {
458
+ onUploadComplete?: (avatarUrl: string) => void;
459
+ onError?: (error: Error) => void;
460
+ className?: string;
461
+ buttonClassName?: string;
462
+ dropzoneClassName?: string;
463
+ maxFileSize?: number;
464
+ accept?: string[];
465
+ upfilesConfig: {
466
+ baseUrl: string;
467
+ apiKey?: string;
468
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
469
+ presignUrl?: string;
470
+ presignPath?: string;
471
+ folderPath?: string;
472
+ };
473
+ }
474
+ declare const AvatarUploader: React.FC<AvatarUploaderProps>;
475
+
476
+ interface AvatarManagerProps {
477
+ open: boolean;
478
+ onOpenChange: (open: boolean) => void;
479
+ onAvatarUpdated?: (avatarUrl: string) => void;
480
+ onError?: (error: Error) => void;
481
+ title?: string;
482
+ description?: string;
483
+ className?: string;
484
+ gridClassName?: string;
485
+ maxFileSize?: number;
486
+ mode?: 'full' | 'browse' | 'upload';
487
+ showDelete?: boolean;
488
+ upfilesConfig: {
489
+ baseUrl: string;
490
+ apiKey?: string;
491
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
492
+ presignUrl?: string;
493
+ presignPath?: string;
494
+ folderPath?: string;
495
+ };
496
+ }
497
+ declare const AvatarManager: React.FC<AvatarManagerProps>;
498
+
441
499
  interface UseNextAuthReturn {
442
500
  user: User | null;
443
501
  isAuthenticated: boolean;
@@ -458,4 +516,4 @@ interface UseNextAuthReturn {
458
516
  }
459
517
  declare const useNextAuth: (config: AuthConfig) => UseNextAuthReturn;
460
518
 
461
- export { AuditLog, AuthConfig, AuthFlow, AuthProvider, AuthResponse, AuthService, AuthThemeProvider, ChangePassword, CsrfTokenResponse, EmailVerificationPage, ForgotPassword, HttpClient, LinkedAccount, LoginData, LoginForm, MFASetup, OAuthConfig, OAuthProvider, OtpForm, PhoneInput, ProtectedRoute, PublicRoute, RegisterData, RegisterForm, RegisterFormProps, ResetPassword, Session, SignIn, SignOut, SignUp, UpdateUserData, UseAuthReturn, User, UserButton, UserProfile, VerifyData, VerifyEmail, useAuth, useAuth$1 as useAuthLegacy, useAuthTheme, useNextAuth };
519
+ export { AuditLog, AuthConfig, AuthFlow, AuthProvider, AuthResponse, AuthService, AuthThemeProvider, AvatarManager, AvatarManagerProps, AvatarUploader, AvatarUploaderProps, ChangePassword, CsrfTokenResponse, EmailVerificationPage, ForgotPassword, HttpClient, LinkedAccount, LoginData, LoginForm, MFASetup, OAuthConfig, OAuthProvider, OtpForm, PhoneInput, ProtectedRoute, PublicRoute, RegisterData, RegisterForm, RegisterFormProps, ResetPassword, Session, SignIn, SignOut, SignUp, UpdateUserData, UpfilesConfig, UseAuthReturn, User, UserButton, UserProfile, VerifyData, VerifyEmail, useAuth, useAuth$1 as useAuthLegacy, useAuthTheme, useNextAuth };
@@ -2,6 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  var axios = require('axios');
5
+ var upfiles = require('@thetechfossil/upfiles');
5
6
  var React3 = require('react');
6
7
  var jsxRuntime = require('react/jsx-runtime');
7
8
  var PhoneInputWithCountry = require('react-phone-number-input');
@@ -120,11 +121,10 @@ var HttpClient = class {
120
121
  }
121
122
  }
122
123
  };
123
-
124
- // src/core/auth-service.ts
125
124
  var AuthService = class {
126
125
  constructor(config) {
127
126
  this.token = null;
127
+ this.upfilesClient = null;
128
128
  this.config = {
129
129
  localStorageKey: "auth_token",
130
130
  csrfEnabled: true,
@@ -132,6 +132,15 @@ var AuthService = class {
132
132
  };
133
133
  this.httpClient = new HttpClient(this.config.baseUrl);
134
134
  this.loadTokenFromStorage();
135
+ if (this.config.upfilesConfig) {
136
+ this.upfilesClient = new upfiles.UpfilesClient({
137
+ baseUrl: this.config.upfilesConfig.baseUrl,
138
+ apiKey: this.config.upfilesConfig.apiKey,
139
+ apiKeyHeader: this.config.upfilesConfig.apiKeyHeader,
140
+ presignUrl: this.config.upfilesConfig.presignUrl,
141
+ presignPath: this.config.upfilesConfig.presignPath
142
+ });
143
+ }
135
144
  if (typeof window !== "undefined") {
136
145
  const frontendBaseUrl = process.env.NEXT_PUBLIC_FRONTEND_BASE_URL || process.env.REACT_APP_FRONTEND_BASE_URL || process.env.NEXT_PUBLIC_APP_URL || window.location.origin;
137
146
  if (frontendBaseUrl) {
@@ -359,6 +368,28 @@ var AuthService = class {
359
368
  }
360
369
  return response;
361
370
  }
371
+ async uploadAndUpdateAvatar(file) {
372
+ if (!this.token) {
373
+ throw new Error("Not authenticated");
374
+ }
375
+ if (!this.upfilesClient) {
376
+ throw new Error("Upfiles configuration is required. Please provide upfilesConfig in AuthConfig.");
377
+ }
378
+ try {
379
+ const folderPath = this.config.upfilesConfig?.folderPath || "avatars/";
380
+ const uploadResult = await this.upfilesClient.upload(file, {
381
+ folderPath,
382
+ fetchThumbnails: true
383
+ });
384
+ const response = await this.updateAvatar(uploadResult.publicUrl);
385
+ return response;
386
+ } catch (error) {
387
+ throw new Error(`Failed to upload avatar: ${error.message || "Unknown error"}`);
388
+ }
389
+ }
390
+ getUpfilesClient() {
391
+ return this.upfilesClient;
392
+ }
362
393
  async requestEmailChange(newEmail) {
363
394
  if (!this.token) {
364
395
  throw new Error("Not authenticated");
@@ -589,6 +620,18 @@ var useAuth = (config) => {
589
620
  setLoading(false);
590
621
  }
591
622
  }, [authService]);
623
+ const uploadAndUpdateAvatar = React3.useCallback(async (file) => {
624
+ setLoading(true);
625
+ try {
626
+ const response = await authService.uploadAndUpdateAvatar(file);
627
+ if (response.success && response.user) {
628
+ setUser(response.user);
629
+ }
630
+ return response;
631
+ } finally {
632
+ setLoading(false);
633
+ }
634
+ }, [authService]);
592
635
  return {
593
636
  user,
594
637
  isAuthenticated,
@@ -601,7 +644,8 @@ var useAuth = (config) => {
601
644
  updateProfile,
602
645
  getProfile,
603
646
  getAllUsers,
604
- getUserById
647
+ getUserById,
648
+ uploadAndUpdateAvatar
605
649
  };
606
650
  };
607
651
  var ThemeContext = React3.createContext({ theme: "light", mounted: false });
@@ -660,7 +704,8 @@ var AuthProvider = ({ children, config }) => {
660
704
  const authConfig = {
661
705
  baseUrl: config?.baseUrl || (typeof window !== "undefined" ? process.env.NEXT_PUBLIC_AUTH_API_URL || process.env.REACT_APP_AUTH_API_URL || "http://localhost:7000" : "http://localhost:7000"),
662
706
  localStorageKey: config?.localStorageKey || "auth_token",
663
- csrfEnabled: config?.csrfEnabled !== void 0 ? config.csrfEnabled : true
707
+ csrfEnabled: config?.csrfEnabled !== void 0 ? config.csrfEnabled : true,
708
+ upfilesConfig: config?.upfilesConfig
664
709
  };
665
710
  const [authService] = React3.useState(() => new AuthService(authConfig));
666
711
  const [user, setUser] = React3.useState(null);
@@ -810,6 +855,18 @@ var AuthProvider = ({ children, config }) => {
810
855
  setLoading(false);
811
856
  }
812
857
  }, [authService]);
858
+ const uploadAndUpdateAvatar = React3.useCallback(async (file) => {
859
+ setLoading(true);
860
+ try {
861
+ const response = await authService.uploadAndUpdateAvatar(file);
862
+ if (response.success && response.user) {
863
+ setUser(response.user);
864
+ }
865
+ return response;
866
+ } finally {
867
+ setLoading(false);
868
+ }
869
+ }, [authService]);
813
870
  const requestEmailChange = React3.useCallback(async (newEmail) => {
814
871
  setLoading(true);
815
872
  try {
@@ -907,6 +964,7 @@ var AuthProvider = ({ children, config }) => {
907
964
  resetPassword,
908
965
  changePassword,
909
966
  updateAvatar,
967
+ uploadAndUpdateAvatar,
910
968
  requestEmailChange,
911
969
  verifyEmailChange,
912
970
  generate2FA,
@@ -4667,6 +4725,122 @@ var UserProfile = ({
4667
4725
  ] })
4668
4726
  ] });
4669
4727
  };
4728
+ var AvatarUploader = ({
4729
+ onUploadComplete,
4730
+ onError,
4731
+ className,
4732
+ buttonClassName,
4733
+ dropzoneClassName,
4734
+ maxFileSize = 5 * 1024 * 1024,
4735
+ // 5MB default
4736
+ accept = ["image/*"],
4737
+ upfilesConfig
4738
+ }) => {
4739
+ const { uploadAndUpdateAvatar } = useAuth2();
4740
+ const [uploading, setUploading] = React3.useState(false);
4741
+ const handleUploadComplete = async (files) => {
4742
+ if (files.length === 0)
4743
+ return;
4744
+ setUploading(true);
4745
+ try {
4746
+ const file = files[0];
4747
+ const response = await uploadAndUpdateAvatar(file.file);
4748
+ if (response.success && response.user?.avatar) {
4749
+ onUploadComplete?.(response.user.avatar);
4750
+ } else {
4751
+ throw new Error(response.message || "Failed to update avatar");
4752
+ }
4753
+ } catch (error) {
4754
+ const err = error instanceof Error ? error : new Error("Upload failed");
4755
+ onError?.(err);
4756
+ } finally {
4757
+ setUploading(false);
4758
+ }
4759
+ };
4760
+ const handleError = (error) => {
4761
+ onError?.(error);
4762
+ };
4763
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(
4764
+ upfiles.Uploader,
4765
+ {
4766
+ clientOptions: {
4767
+ baseUrl: upfilesConfig.baseUrl,
4768
+ apiKey: upfilesConfig.apiKey,
4769
+ apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4770
+ presignUrl: upfilesConfig.presignUrl,
4771
+ presignPath: upfilesConfig.presignPath
4772
+ },
4773
+ multiple: false,
4774
+ accept,
4775
+ maxFileSize,
4776
+ maxFiles: 1,
4777
+ onComplete: handleUploadComplete,
4778
+ onError: handleError,
4779
+ buttonClassName,
4780
+ dropzoneClassName,
4781
+ children: uploading ? "Uploading..." : "Upload Avatar"
4782
+ }
4783
+ ) });
4784
+ };
4785
+ var AvatarManager = ({
4786
+ open,
4787
+ onOpenChange,
4788
+ onAvatarUpdated,
4789
+ onError,
4790
+ title = "Select Avatar",
4791
+ description = "Choose an existing image or upload a new one",
4792
+ className,
4793
+ gridClassName,
4794
+ maxFileSize = 5 * 1024 * 1024,
4795
+ // 5MB default
4796
+ mode = "full",
4797
+ showDelete = false,
4798
+ upfilesConfig
4799
+ }) => {
4800
+ const { updateProfile } = useAuth2();
4801
+ const [updating, setUpdating] = React3.useState(false);
4802
+ const handleSelect = async (image) => {
4803
+ setUpdating(true);
4804
+ try {
4805
+ const response = await updateProfile({ avatar: image.url });
4806
+ if (response.success && response.user?.avatar) {
4807
+ onAvatarUpdated?.(response.user.avatar);
4808
+ onOpenChange(false);
4809
+ } else {
4810
+ throw new Error(response.message || "Failed to update avatar");
4811
+ }
4812
+ } catch (error) {
4813
+ const err = error instanceof Error ? error : new Error("Failed to update avatar");
4814
+ onError?.(err);
4815
+ } finally {
4816
+ setUpdating(false);
4817
+ }
4818
+ };
4819
+ return /* @__PURE__ */ jsxRuntime.jsx(
4820
+ upfiles.ImageManager,
4821
+ {
4822
+ open,
4823
+ onOpenChange,
4824
+ clientOptions: {
4825
+ baseUrl: upfilesConfig.baseUrl,
4826
+ apiKey: upfilesConfig.apiKey,
4827
+ apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4828
+ presignUrl: upfilesConfig.presignUrl,
4829
+ presignPath: upfilesConfig.presignPath
4830
+ },
4831
+ folderPath: upfilesConfig.folderPath || "avatars/",
4832
+ title,
4833
+ description,
4834
+ className,
4835
+ gridClassName,
4836
+ onSelect: handleSelect,
4837
+ maxFileSize,
4838
+ mode,
4839
+ showDelete,
4840
+ fetchThumbnails: true
4841
+ }
4842
+ );
4843
+ };
4670
4844
  var isServer = typeof window === "undefined";
4671
4845
  var useNextAuth = (config) => {
4672
4846
  const [authService] = React3.useState(() => {
@@ -4863,6 +5037,8 @@ exports.AuthFlow = AuthFlow;
4863
5037
  exports.AuthProvider = AuthProvider;
4864
5038
  exports.AuthService = AuthService;
4865
5039
  exports.AuthThemeProvider = AuthThemeProvider;
5040
+ exports.AvatarManager = AvatarManager;
5041
+ exports.AvatarUploader = AvatarUploader;
4866
5042
  exports.ChangePassword = ChangePassword;
4867
5043
  exports.EmailVerificationPage = EmailVerificationPage;
4868
5044
  exports.ForgotPassword = ForgotPassword;