@thetechfossil/auth2 1.2.5 → 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.
package/README.md CHANGED
@@ -13,6 +13,18 @@ A lightweight, easy-to-use authentication SDK for integrating with the Auth back
13
13
  - Supports custom frontend base URLs for email verification links
14
14
  - **Embedded styling** - No separate CSS imports required!
15
15
 
16
+ ## Documentation
17
+
18
+ 📚 **Complete documentation is available at:** [https://ttf-auth-docs.netlify.app/](https://ttf-auth-docs.netlify.app/)
19
+
20
+ The documentation includes:
21
+ - Getting started guides
22
+ - API reference
23
+ - Component documentation
24
+ - Architecture overview
25
+ - Environment configuration
26
+ - Integration examples for React, Next.js, and Node.js
27
+
16
28
  ## Installation
17
29
 
18
30
  ```bash
@@ -24,6 +24,15 @@ interface AuthConfig {
24
24
  localStorageKey?: string;
25
25
  token?: string;
26
26
  csrfEnabled?: boolean;
27
+ upfilesConfig?: UpfilesConfig;
28
+ }
29
+ interface UpfilesConfig {
30
+ baseUrl: string;
31
+ apiKey?: string;
32
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
33
+ presignUrl?: string;
34
+ presignPath?: string;
35
+ folderPath?: string;
27
36
  }
28
37
 
29
38
  interface RegisterFormProps {
@@ -182,4 +191,46 @@ interface PhoneInputProps {
182
191
  }
183
192
  declare const PhoneInput: React.FC<PhoneInputProps>;
184
193
 
185
- export { AuthFlow, ChangePassword, EmailVerificationPage, ForgotPassword, LoginForm, OtpForm, PhoneInput, ProtectedRoute, PublicRoute, RegisterForm, RegisterFormProps, ResetPassword, SignIn, SignOut, SignUp, UserButton, UserProfile, VerifyEmail };
194
+ interface AvatarUploaderProps {
195
+ onUploadComplete?: (avatarUrl: string) => void;
196
+ onError?: (error: Error) => void;
197
+ className?: string;
198
+ buttonClassName?: string;
199
+ dropzoneClassName?: string;
200
+ maxFileSize?: number;
201
+ accept?: string[];
202
+ upfilesConfig: {
203
+ baseUrl: string;
204
+ apiKey?: string;
205
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
206
+ presignUrl?: string;
207
+ presignPath?: string;
208
+ folderPath?: string;
209
+ };
210
+ }
211
+ declare const AvatarUploader: React.FC<AvatarUploaderProps>;
212
+
213
+ interface AvatarManagerProps {
214
+ open: boolean;
215
+ onOpenChange: (open: boolean) => void;
216
+ onAvatarUpdated?: (avatarUrl: string) => void;
217
+ onError?: (error: Error) => void;
218
+ title?: string;
219
+ description?: string;
220
+ className?: string;
221
+ gridClassName?: string;
222
+ maxFileSize?: number;
223
+ mode?: 'full' | 'browse' | 'upload';
224
+ showDelete?: boolean;
225
+ upfilesConfig: {
226
+ baseUrl: string;
227
+ apiKey?: string;
228
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
229
+ presignUrl?: string;
230
+ presignPath?: string;
231
+ folderPath?: string;
232
+ };
233
+ }
234
+ declare const AvatarManager: React.FC<AvatarManagerProps>;
235
+
236
+ export { AuthFlow, AvatarManager, AvatarManagerProps, AvatarUploader, AvatarUploaderProps, ChangePassword, EmailVerificationPage, ForgotPassword, LoginForm, OtpForm, PhoneInput, ProtectedRoute, PublicRoute, RegisterForm, RegisterFormProps, ResetPassword, SignIn, SignOut, SignUp, UserButton, UserProfile, VerifyEmail };
@@ -3,6 +3,7 @@
3
3
 
4
4
  var React2 = require('react');
5
5
  var axios = require('axios');
6
+ var upfiles = require('@thetechfossil/upfiles');
6
7
  var jsxRuntime = require('react/jsx-runtime');
7
8
  var PhoneInputWithCountry = require('react-phone-number-input');
8
9
  require('react-phone-number-input/style.css');
@@ -119,11 +120,10 @@ var HttpClient = class {
119
120
  }
120
121
  }
121
122
  };
122
-
123
- // src/core/auth-service.ts
124
123
  var AuthService = class {
125
124
  constructor(config) {
126
125
  this.token = null;
126
+ this.upfilesClient = null;
127
127
  this.config = {
128
128
  localStorageKey: "auth_token",
129
129
  csrfEnabled: true,
@@ -131,6 +131,15 @@ var AuthService = class {
131
131
  };
132
132
  this.httpClient = new HttpClient(this.config.baseUrl);
133
133
  this.loadTokenFromStorage();
134
+ if (this.config.upfilesConfig) {
135
+ this.upfilesClient = new upfiles.UpfilesClient({
136
+ baseUrl: this.config.upfilesConfig.baseUrl,
137
+ apiKey: this.config.upfilesConfig.apiKey,
138
+ apiKeyHeader: this.config.upfilesConfig.apiKeyHeader,
139
+ presignUrl: this.config.upfilesConfig.presignUrl,
140
+ presignPath: this.config.upfilesConfig.presignPath
141
+ });
142
+ }
134
143
  if (typeof window !== "undefined") {
135
144
  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;
136
145
  if (frontendBaseUrl) {
@@ -358,6 +367,28 @@ var AuthService = class {
358
367
  }
359
368
  return response;
360
369
  }
370
+ async uploadAndUpdateAvatar(file) {
371
+ if (!this.token) {
372
+ throw new Error("Not authenticated");
373
+ }
374
+ if (!this.upfilesClient) {
375
+ throw new Error("Upfiles configuration is required. Please provide upfilesConfig in AuthConfig.");
376
+ }
377
+ try {
378
+ const folderPath = this.config.upfilesConfig?.folderPath || "avatars/";
379
+ const uploadResult = await this.upfilesClient.upload(file, {
380
+ folderPath,
381
+ fetchThumbnails: true
382
+ });
383
+ const response = await this.updateAvatar(uploadResult.publicUrl);
384
+ return response;
385
+ } catch (error) {
386
+ throw new Error(`Failed to upload avatar: ${error.message || "Unknown error"}`);
387
+ }
388
+ }
389
+ getUpfilesClient() {
390
+ return this.upfilesClient;
391
+ }
361
392
  async requestEmailChange(newEmail) {
362
393
  if (!this.token) {
363
394
  throw new Error("Not authenticated");
@@ -590,6 +621,18 @@ var useAuth = (config) => {
590
621
  setLoading(false);
591
622
  }
592
623
  }, [authService]);
624
+ const uploadAndUpdateAvatar = React2.useCallback(async (file) => {
625
+ setLoading(true);
626
+ try {
627
+ const response = await authService.uploadAndUpdateAvatar(file);
628
+ if (response.success && response.user) {
629
+ setUser(response.user);
630
+ }
631
+ return response;
632
+ } finally {
633
+ setLoading(false);
634
+ }
635
+ }, [authService]);
593
636
  return {
594
637
  user,
595
638
  isAuthenticated,
@@ -602,7 +645,8 @@ var useAuth = (config) => {
602
645
  updateProfile,
603
646
  getProfile,
604
647
  getAllUsers,
605
- getUserById
648
+ getUserById,
649
+ uploadAndUpdateAvatar
606
650
  };
607
651
  };
608
652
  var ThemeContext = React2.createContext({ theme: "light", mounted: false });
@@ -4357,8 +4401,126 @@ var UserProfile = ({
4357
4401
  ] })
4358
4402
  ] });
4359
4403
  };
4404
+ var AvatarUploader = ({
4405
+ onUploadComplete,
4406
+ onError,
4407
+ className,
4408
+ buttonClassName,
4409
+ dropzoneClassName,
4410
+ maxFileSize = 5 * 1024 * 1024,
4411
+ // 5MB default
4412
+ accept = ["image/*"],
4413
+ upfilesConfig
4414
+ }) => {
4415
+ const { uploadAndUpdateAvatar } = useAuth2();
4416
+ const [uploading, setUploading] = React2.useState(false);
4417
+ const handleUploadComplete = async (files) => {
4418
+ if (files.length === 0)
4419
+ return;
4420
+ setUploading(true);
4421
+ try {
4422
+ const file = files[0];
4423
+ const response = await uploadAndUpdateAvatar(file.file);
4424
+ if (response.success && response.user?.avatar) {
4425
+ onUploadComplete?.(response.user.avatar);
4426
+ } else {
4427
+ throw new Error(response.message || "Failed to update avatar");
4428
+ }
4429
+ } catch (error) {
4430
+ const err = error instanceof Error ? error : new Error("Upload failed");
4431
+ onError?.(err);
4432
+ } finally {
4433
+ setUploading(false);
4434
+ }
4435
+ };
4436
+ const handleError = (error) => {
4437
+ onError?.(error);
4438
+ };
4439
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(
4440
+ upfiles.Uploader,
4441
+ {
4442
+ clientOptions: {
4443
+ baseUrl: upfilesConfig.baseUrl,
4444
+ apiKey: upfilesConfig.apiKey,
4445
+ apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4446
+ presignUrl: upfilesConfig.presignUrl,
4447
+ presignPath: upfilesConfig.presignPath
4448
+ },
4449
+ multiple: false,
4450
+ accept,
4451
+ maxFileSize,
4452
+ maxFiles: 1,
4453
+ onComplete: handleUploadComplete,
4454
+ onError: handleError,
4455
+ buttonClassName,
4456
+ dropzoneClassName,
4457
+ children: uploading ? "Uploading..." : "Upload Avatar"
4458
+ }
4459
+ ) });
4460
+ };
4461
+ var AvatarManager = ({
4462
+ open,
4463
+ onOpenChange,
4464
+ onAvatarUpdated,
4465
+ onError,
4466
+ title = "Select Avatar",
4467
+ description = "Choose an existing image or upload a new one",
4468
+ className,
4469
+ gridClassName,
4470
+ maxFileSize = 5 * 1024 * 1024,
4471
+ // 5MB default
4472
+ mode = "full",
4473
+ showDelete = false,
4474
+ upfilesConfig
4475
+ }) => {
4476
+ const { updateProfile } = useAuth2();
4477
+ const [updating, setUpdating] = React2.useState(false);
4478
+ const handleSelect = async (image) => {
4479
+ setUpdating(true);
4480
+ try {
4481
+ const response = await updateProfile({ avatar: image.url });
4482
+ if (response.success && response.user?.avatar) {
4483
+ onAvatarUpdated?.(response.user.avatar);
4484
+ onOpenChange(false);
4485
+ } else {
4486
+ throw new Error(response.message || "Failed to update avatar");
4487
+ }
4488
+ } catch (error) {
4489
+ const err = error instanceof Error ? error : new Error("Failed to update avatar");
4490
+ onError?.(err);
4491
+ } finally {
4492
+ setUpdating(false);
4493
+ }
4494
+ };
4495
+ return /* @__PURE__ */ jsxRuntime.jsx(
4496
+ upfiles.ImageManager,
4497
+ {
4498
+ open,
4499
+ onOpenChange,
4500
+ clientOptions: {
4501
+ baseUrl: upfilesConfig.baseUrl,
4502
+ apiKey: upfilesConfig.apiKey,
4503
+ apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4504
+ presignUrl: upfilesConfig.presignUrl,
4505
+ presignPath: upfilesConfig.presignPath
4506
+ },
4507
+ folderPath: upfilesConfig.folderPath || "avatars/",
4508
+ title,
4509
+ description,
4510
+ className,
4511
+ gridClassName,
4512
+ onSelect: handleSelect,
4513
+ maxFileSize,
4514
+ mode,
4515
+ showDelete,
4516
+ fetchThumbnails: true
4517
+ }
4518
+ );
4519
+ };
4360
4520
 
4361
4521
  exports.AuthFlow = AuthFlow;
4522
+ exports.AvatarManager = AvatarManager;
4523
+ exports.AvatarUploader = AvatarUploader;
4362
4524
  exports.ChangePassword = ChangePassword;
4363
4525
  exports.EmailVerificationPage = EmailVerificationPage;
4364
4526
  exports.ForgotPassword = ForgotPassword;