@pixygon/auth 1.0.0 → 1.1.0
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 +1 -1
- package/dist/{chunk-E34M2RJD.mjs → chunk-ELVIBXBG.mjs} +61 -4
- package/dist/components/index.d.mts +5 -5
- package/dist/components/index.d.ts +5 -5
- package/dist/components/index.js +115 -86
- package/dist/components/index.mjs +100 -83
- package/dist/{index-CIK2MKl9.d.mts → index-CuhQGwDH.d.mts} +32 -3
- package/dist/{index-CIK2MKl9.d.ts → index-CuhQGwDH.d.ts} +32 -3
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +62 -4
- package/dist/index.mjs +3 -1
- package/package.json +1 -1
- package/src/api/client.ts +34 -1
- package/src/components/ForgotPasswordForm.tsx +26 -23
- package/src/components/LoginForm.tsx +18 -15
- package/src/components/PixygonAuth.tsx +11 -0
- package/src/components/RegisterForm.tsx +21 -18
- package/src/components/VerifyForm.tsx +19 -16
- package/src/hooks/index.ts +2 -0
- package/src/index.ts +9 -0
- package/src/providers/AuthProvider.tsx +12 -0
- package/src/types/index.ts +51 -2
- package/src/utils/storage.ts +15 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Type definitions for the Pixygon authentication system
|
|
4
4
|
*/
|
|
5
5
|
type UserRole = 'user' | 'creator' | 'admin' | 'superadmin';
|
|
6
|
-
type SubscriptionTier = 'free' | '
|
|
6
|
+
type SubscriptionTier = 'free' | 'plus' | 'family' | 'basic' | 'pro' | 'enterprise';
|
|
7
7
|
interface User {
|
|
8
8
|
_id: string;
|
|
9
9
|
userName: string;
|
|
@@ -107,14 +107,36 @@ interface ResendVerificationRequest {
|
|
|
107
107
|
interface ResendVerificationResponse {
|
|
108
108
|
message: string;
|
|
109
109
|
}
|
|
110
|
+
interface ChangePasswordRequest {
|
|
111
|
+
currentPassword: string;
|
|
112
|
+
newPassword: string;
|
|
113
|
+
}
|
|
114
|
+
interface ChangePasswordResponse {
|
|
115
|
+
status: string;
|
|
116
|
+
}
|
|
117
|
+
interface LogoutResponse {
|
|
118
|
+
status: string;
|
|
119
|
+
}
|
|
110
120
|
type AuthErrorCode = 'INVALID_CREDENTIALS' | 'USER_NOT_FOUND' | 'USER_EXISTS' | 'EMAIL_NOT_VERIFIED' | 'INVALID_VERIFICATION_CODE' | 'EXPIRED_VERIFICATION_CODE' | 'INVALID_RECOVERY_CODE' | 'EXPIRED_RECOVERY_CODE' | 'TOKEN_EXPIRED' | 'TOKEN_INVALID' | 'REFRESH_TOKEN_EXPIRED' | 'NETWORK_ERROR' | 'SERVER_ERROR' | 'UNKNOWN_ERROR';
|
|
111
121
|
interface AuthError {
|
|
112
122
|
code: AuthErrorCode;
|
|
113
123
|
message: string;
|
|
114
124
|
details?: Record<string, unknown>;
|
|
115
125
|
}
|
|
126
|
+
interface AuthTheme {
|
|
127
|
+
primaryColor?: string;
|
|
128
|
+
backgroundColor?: string;
|
|
129
|
+
surfaceColor?: string;
|
|
130
|
+
textColor?: string;
|
|
131
|
+
textSecondary?: string;
|
|
132
|
+
errorColor?: string;
|
|
133
|
+
successColor?: string;
|
|
134
|
+
borderRadius?: string;
|
|
135
|
+
fontFamily?: string;
|
|
136
|
+
}
|
|
137
|
+
declare const DEFAULT_THEME: Required<AuthTheme>;
|
|
116
138
|
interface AuthConfig {
|
|
117
|
-
/** Base URL for the auth API (e.g., https://pixygon
|
|
139
|
+
/** Base URL for the auth API (e.g., https://api.pixygon.com/v1) */
|
|
118
140
|
baseUrl: string;
|
|
119
141
|
/** App identifier for token storage keys */
|
|
120
142
|
appId: string;
|
|
@@ -136,6 +158,8 @@ interface AuthConfig {
|
|
|
136
158
|
storage?: AuthStorage;
|
|
137
159
|
/** Enable debug logging (default: false) */
|
|
138
160
|
debug?: boolean;
|
|
161
|
+
/** Theme customization for branded components */
|
|
162
|
+
theme?: AuthTheme;
|
|
139
163
|
}
|
|
140
164
|
interface AuthStorage {
|
|
141
165
|
getItem: (key: string) => string | null | Promise<string | null>;
|
|
@@ -150,6 +174,7 @@ interface AuthContextValue extends AuthState {
|
|
|
150
174
|
resendVerification: (data: ResendVerificationRequest) => Promise<ResendVerificationResponse>;
|
|
151
175
|
forgotPassword: (data: ForgotPasswordRequest) => Promise<ForgotPasswordResponse>;
|
|
152
176
|
recoverPassword: (data: RecoverPasswordRequest) => Promise<RecoverPasswordResponse>;
|
|
177
|
+
changePassword: (data: ChangePasswordRequest) => Promise<ChangePasswordResponse>;
|
|
153
178
|
refreshTokens: () => Promise<void>;
|
|
154
179
|
getAccessToken: () => string | null;
|
|
155
180
|
isAuthenticated: boolean;
|
|
@@ -164,6 +189,7 @@ interface LoginFormProps {
|
|
|
164
189
|
onNavigateForgotPassword?: () => void;
|
|
165
190
|
showBranding?: boolean;
|
|
166
191
|
className?: string;
|
|
192
|
+
theme?: AuthTheme;
|
|
167
193
|
}
|
|
168
194
|
interface RegisterFormProps {
|
|
169
195
|
onSuccess?: (user: User) => void;
|
|
@@ -171,6 +197,7 @@ interface RegisterFormProps {
|
|
|
171
197
|
onNavigateLogin?: () => void;
|
|
172
198
|
showBranding?: boolean;
|
|
173
199
|
className?: string;
|
|
200
|
+
theme?: AuthTheme;
|
|
174
201
|
}
|
|
175
202
|
interface VerifyFormProps {
|
|
176
203
|
userName: string;
|
|
@@ -179,6 +206,7 @@ interface VerifyFormProps {
|
|
|
179
206
|
onNavigateLogin?: () => void;
|
|
180
207
|
showBranding?: boolean;
|
|
181
208
|
className?: string;
|
|
209
|
+
theme?: AuthTheme;
|
|
182
210
|
}
|
|
183
211
|
interface ForgotPasswordFormProps {
|
|
184
212
|
onSuccess?: () => void;
|
|
@@ -186,6 +214,7 @@ interface ForgotPasswordFormProps {
|
|
|
186
214
|
onNavigateLogin?: () => void;
|
|
187
215
|
showBranding?: boolean;
|
|
188
216
|
className?: string;
|
|
217
|
+
theme?: AuthTheme;
|
|
189
218
|
}
|
|
190
219
|
interface PixygonAuthProps {
|
|
191
220
|
mode: 'login' | 'register' | 'verify' | 'forgot-password' | 'recover-password';
|
|
@@ -198,4 +227,4 @@ interface PixygonAuthProps {
|
|
|
198
227
|
className?: string;
|
|
199
228
|
}
|
|
200
229
|
|
|
201
|
-
export type
|
|
230
|
+
export { type AuthContextValue as A, type ChangePasswordRequest as C, DEFAULT_THEME as D, type ForgotPasswordRequest as F, type LoginRequest as L, type PixygonAuthProps as P, type RegisterRequest as R, type SubscriptionTier as S, type TokenPair as T, type User as U, type VerifyRequest as V, type AuthConfig as a, type AuthError as b, type AuthStatus as c, type UserRole as d, type AuthStorage as e, type LoginResponse as f, type RegisterResponse as g, type VerifyResponse as h, type ResendVerificationRequest as i, type ResendVerificationResponse as j, type ForgotPasswordResponse as k, type RecoverPasswordRequest as l, type RecoverPasswordResponse as m, type RefreshTokenRequest as n, type RefreshTokenResponse as o, type ChangePasswordResponse as p, type LogoutResponse as q, type AuthErrorCode as r, type AuthState as s, type AuthTheme as t, type ForgotPasswordFormProps as u, type LoginFormProps as v, type RegisterFormProps as w, type TokenPayload as x, type VerifyFormProps as y };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AuthContextValue, a as AuthConfig, U as User, b as AuthError, c as AuthStatus, d as UserRole, e as AuthStorage, T as TokenPair, L as LoginRequest, f as LoginResponse, R as RegisterRequest, g as RegisterResponse, V as VerifyRequest, h as VerifyResponse, i as ResendVerificationRequest, j as ResendVerificationResponse, F as ForgotPasswordRequest, k as ForgotPasswordResponse, l as RecoverPasswordRequest, m as RecoverPasswordResponse, n as RefreshTokenRequest, o as RefreshTokenResponse } from './index-
|
|
2
|
-
export {
|
|
1
|
+
import { A as AuthContextValue, a as AuthConfig, U as User, b as AuthError, c as AuthStatus, d as UserRole, e as AuthStorage, T as TokenPair, L as LoginRequest, f as LoginResponse, R as RegisterRequest, g as RegisterResponse, V as VerifyRequest, h as VerifyResponse, i as ResendVerificationRequest, j as ResendVerificationResponse, F as ForgotPasswordRequest, k as ForgotPasswordResponse, l as RecoverPasswordRequest, m as RecoverPasswordResponse, n as RefreshTokenRequest, o as RefreshTokenResponse, C as ChangePasswordRequest, p as ChangePasswordResponse, q as LogoutResponse } from './index-CuhQGwDH.mjs';
|
|
2
|
+
export { r as AuthErrorCode, s as AuthState, t as AuthTheme, D as DEFAULT_THEME, u as ForgotPasswordFormProps, v as LoginFormProps, P as PixygonAuthProps, w as RegisterFormProps, S as SubscriptionTier, x as TokenPayload, y as VerifyFormProps } from './index-CuhQGwDH.mjs';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode } from 'react';
|
|
@@ -67,6 +67,7 @@ interface UseAuthReturn {
|
|
|
67
67
|
resendVerification: ReturnType<typeof useAuthContext>['resendVerification'];
|
|
68
68
|
forgotPassword: ReturnType<typeof useAuthContext>['forgotPassword'];
|
|
69
69
|
recoverPassword: ReturnType<typeof useAuthContext>['recoverPassword'];
|
|
70
|
+
changePassword: ReturnType<typeof useAuthContext>['changePassword'];
|
|
70
71
|
hasRole: (role: UserRole | UserRole[]) => boolean;
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
@@ -222,6 +223,8 @@ interface AuthApiClient {
|
|
|
222
223
|
forgotPassword: (data: ForgotPasswordRequest) => Promise<ForgotPasswordResponse>;
|
|
223
224
|
recoverPassword: (data: RecoverPasswordRequest) => Promise<RecoverPasswordResponse>;
|
|
224
225
|
refreshToken: (data: RefreshTokenRequest) => Promise<RefreshTokenResponse>;
|
|
226
|
+
changePassword: (data: ChangePasswordRequest) => Promise<ChangePasswordResponse>;
|
|
227
|
+
logout: () => Promise<LogoutResponse>;
|
|
225
228
|
getMe: () => Promise<User>;
|
|
226
229
|
updateProfile: (data: Partial<User>) => Promise<User>;
|
|
227
230
|
setAccessToken: (token: string | null) => void;
|
|
@@ -230,4 +233,4 @@ interface AuthApiClient {
|
|
|
230
233
|
}
|
|
231
234
|
declare function createAuthApiClient(config: AuthConfig, tokenStorage: TokenStorage): AuthApiClient;
|
|
232
235
|
|
|
233
|
-
export { type AuthApiClient, AuthConfig, AuthContext, AuthContextValue, AuthError, AuthProvider, type AuthProviderProps, AuthStatus, AuthStorage, ForgotPasswordRequest, ForgotPasswordResponse, LoginRequest, LoginResponse, RecoverPasswordRequest, RecoverPasswordResponse, RefreshTokenRequest, RefreshTokenResponse, RegisterRequest, RegisterResponse, ResendVerificationRequest, ResendVerificationResponse, TokenPair, type TokenStorage, type UseAuthErrorReturn, type UseAuthReturn, type UseAuthStatusReturn, type UseProfileSyncReturn, type UseRequireAuthOptions, type UseRequireAuthReturn, type UseTokenReturn, type UseUserReturn, User, type UserProfile, UserRole, VerifyRequest, VerifyResponse, createAuthApiClient, createTokenStorage, useAuth, useAuthContext, useAuthError, useAuthStatus, useProfileSync, useRequireAuth, useToken, useUser };
|
|
236
|
+
export { type AuthApiClient, AuthConfig, AuthContext, AuthContextValue, AuthError, AuthProvider, type AuthProviderProps, AuthStatus, AuthStorage, ChangePasswordRequest, ChangePasswordResponse, ForgotPasswordRequest, ForgotPasswordResponse, LoginRequest, LoginResponse, LogoutResponse, RecoverPasswordRequest, RecoverPasswordResponse, RefreshTokenRequest, RefreshTokenResponse, RegisterRequest, RegisterResponse, ResendVerificationRequest, ResendVerificationResponse, TokenPair, type TokenStorage, type UseAuthErrorReturn, type UseAuthReturn, type UseAuthStatusReturn, type UseProfileSyncReturn, type UseRequireAuthOptions, type UseRequireAuthReturn, type UseTokenReturn, type UseUserReturn, User, type UserProfile, UserRole, VerifyRequest, VerifyResponse, createAuthApiClient, createTokenStorage, useAuth, useAuthContext, useAuthError, useAuthStatus, useProfileSync, useRequireAuth, useToken, useUser };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AuthContextValue, a as AuthConfig, U as User, b as AuthError, c as AuthStatus, d as UserRole, e as AuthStorage, T as TokenPair, L as LoginRequest, f as LoginResponse, R as RegisterRequest, g as RegisterResponse, V as VerifyRequest, h as VerifyResponse, i as ResendVerificationRequest, j as ResendVerificationResponse, F as ForgotPasswordRequest, k as ForgotPasswordResponse, l as RecoverPasswordRequest, m as RecoverPasswordResponse, n as RefreshTokenRequest, o as RefreshTokenResponse } from './index-
|
|
2
|
-
export {
|
|
1
|
+
import { A as AuthContextValue, a as AuthConfig, U as User, b as AuthError, c as AuthStatus, d as UserRole, e as AuthStorage, T as TokenPair, L as LoginRequest, f as LoginResponse, R as RegisterRequest, g as RegisterResponse, V as VerifyRequest, h as VerifyResponse, i as ResendVerificationRequest, j as ResendVerificationResponse, F as ForgotPasswordRequest, k as ForgotPasswordResponse, l as RecoverPasswordRequest, m as RecoverPasswordResponse, n as RefreshTokenRequest, o as RefreshTokenResponse, C as ChangePasswordRequest, p as ChangePasswordResponse, q as LogoutResponse } from './index-CuhQGwDH.js';
|
|
2
|
+
export { r as AuthErrorCode, s as AuthState, t as AuthTheme, D as DEFAULT_THEME, u as ForgotPasswordFormProps, v as LoginFormProps, P as PixygonAuthProps, w as RegisterFormProps, S as SubscriptionTier, x as TokenPayload, y as VerifyFormProps } from './index-CuhQGwDH.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode } from 'react';
|
|
@@ -67,6 +67,7 @@ interface UseAuthReturn {
|
|
|
67
67
|
resendVerification: ReturnType<typeof useAuthContext>['resendVerification'];
|
|
68
68
|
forgotPassword: ReturnType<typeof useAuthContext>['forgotPassword'];
|
|
69
69
|
recoverPassword: ReturnType<typeof useAuthContext>['recoverPassword'];
|
|
70
|
+
changePassword: ReturnType<typeof useAuthContext>['changePassword'];
|
|
70
71
|
hasRole: (role: UserRole | UserRole[]) => boolean;
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
@@ -222,6 +223,8 @@ interface AuthApiClient {
|
|
|
222
223
|
forgotPassword: (data: ForgotPasswordRequest) => Promise<ForgotPasswordResponse>;
|
|
223
224
|
recoverPassword: (data: RecoverPasswordRequest) => Promise<RecoverPasswordResponse>;
|
|
224
225
|
refreshToken: (data: RefreshTokenRequest) => Promise<RefreshTokenResponse>;
|
|
226
|
+
changePassword: (data: ChangePasswordRequest) => Promise<ChangePasswordResponse>;
|
|
227
|
+
logout: () => Promise<LogoutResponse>;
|
|
225
228
|
getMe: () => Promise<User>;
|
|
226
229
|
updateProfile: (data: Partial<User>) => Promise<User>;
|
|
227
230
|
setAccessToken: (token: string | null) => void;
|
|
@@ -230,4 +233,4 @@ interface AuthApiClient {
|
|
|
230
233
|
}
|
|
231
234
|
declare function createAuthApiClient(config: AuthConfig, tokenStorage: TokenStorage): AuthApiClient;
|
|
232
235
|
|
|
233
|
-
export { type AuthApiClient, AuthConfig, AuthContext, AuthContextValue, AuthError, AuthProvider, type AuthProviderProps, AuthStatus, AuthStorage, ForgotPasswordRequest, ForgotPasswordResponse, LoginRequest, LoginResponse, RecoverPasswordRequest, RecoverPasswordResponse, RefreshTokenRequest, RefreshTokenResponse, RegisterRequest, RegisterResponse, ResendVerificationRequest, ResendVerificationResponse, TokenPair, type TokenStorage, type UseAuthErrorReturn, type UseAuthReturn, type UseAuthStatusReturn, type UseProfileSyncReturn, type UseRequireAuthOptions, type UseRequireAuthReturn, type UseTokenReturn, type UseUserReturn, User, type UserProfile, UserRole, VerifyRequest, VerifyResponse, createAuthApiClient, createTokenStorage, useAuth, useAuthContext, useAuthError, useAuthStatus, useProfileSync, useRequireAuth, useToken, useUser };
|
|
236
|
+
export { type AuthApiClient, AuthConfig, AuthContext, AuthContextValue, AuthError, AuthProvider, type AuthProviderProps, AuthStatus, AuthStorage, ChangePasswordRequest, ChangePasswordResponse, ForgotPasswordRequest, ForgotPasswordResponse, LoginRequest, LoginResponse, LogoutResponse, RecoverPasswordRequest, RecoverPasswordResponse, RefreshTokenRequest, RefreshTokenResponse, RegisterRequest, RegisterResponse, ResendVerificationRequest, ResendVerificationResponse, TokenPair, type TokenStorage, type UseAuthErrorReturn, type UseAuthReturn, type UseAuthStatusReturn, type UseProfileSyncReturn, type UseRequireAuthOptions, type UseRequireAuthReturn, type UseTokenReturn, type UseUserReturn, User, type UserProfile, UserRole, VerifyRequest, VerifyResponse, createAuthApiClient, createTokenStorage, useAuth, useAuthContext, useAuthError, useAuthStatus, useProfileSync, useRequireAuth, useToken, useUser };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AuthContext: () => AuthContext,
|
|
24
24
|
AuthProvider: () => AuthProvider,
|
|
25
|
+
DEFAULT_THEME: () => DEFAULT_THEME,
|
|
25
26
|
createAuthApiClient: () => createAuthApiClient,
|
|
26
27
|
createTokenStorage: () => createTokenStorage,
|
|
27
28
|
useAuth: () => useAuth,
|
|
@@ -35,6 +36,19 @@ __export(index_exports, {
|
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(index_exports);
|
|
37
38
|
|
|
39
|
+
// src/types/index.ts
|
|
40
|
+
var DEFAULT_THEME = {
|
|
41
|
+
primaryColor: "#6366f1",
|
|
42
|
+
backgroundColor: "#0f0f0f",
|
|
43
|
+
surfaceColor: "#262626",
|
|
44
|
+
textColor: "#ffffff",
|
|
45
|
+
textSecondary: "#a3a3a3",
|
|
46
|
+
errorColor: "#ef4444",
|
|
47
|
+
successColor: "#22c55e",
|
|
48
|
+
borderRadius: "1rem",
|
|
49
|
+
fontFamily: "inherit"
|
|
50
|
+
};
|
|
51
|
+
|
|
38
52
|
// src/providers/AuthProvider.tsx
|
|
39
53
|
var import_react = require("react");
|
|
40
54
|
|
|
@@ -48,15 +62,25 @@ var getKeys = (appId) => ({
|
|
|
48
62
|
var defaultStorage = {
|
|
49
63
|
getItem: (key) => {
|
|
50
64
|
if (typeof window === "undefined") return null;
|
|
51
|
-
|
|
65
|
+
try {
|
|
66
|
+
return localStorage.getItem(key);
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
52
70
|
},
|
|
53
71
|
setItem: (key, value) => {
|
|
54
72
|
if (typeof window === "undefined") return;
|
|
55
|
-
|
|
73
|
+
try {
|
|
74
|
+
localStorage.setItem(key, value);
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
56
77
|
},
|
|
57
78
|
removeItem: (key) => {
|
|
58
79
|
if (typeof window === "undefined") return;
|
|
59
|
-
|
|
80
|
+
try {
|
|
81
|
+
localStorage.removeItem(key);
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
60
84
|
}
|
|
61
85
|
};
|
|
62
86
|
function createTokenStorage(appId, storage = defaultStorage) {
|
|
@@ -316,6 +340,9 @@ function createAuthApiClient(config, tokenStorage) {
|
|
|
316
340
|
method: "POST",
|
|
317
341
|
body: JSON.stringify(data)
|
|
318
342
|
});
|
|
343
|
+
if (!response.user || !response.token) {
|
|
344
|
+
throw createAuthError(401, response.message || "Login failed");
|
|
345
|
+
}
|
|
319
346
|
currentAccessToken = response.token;
|
|
320
347
|
await tokenStorage.setTokens(
|
|
321
348
|
response.token,
|
|
@@ -324,7 +351,7 @@ function createAuthApiClient(config, tokenStorage) {
|
|
|
324
351
|
response.user
|
|
325
352
|
);
|
|
326
353
|
config.onLogin?.(response.user);
|
|
327
|
-
log("Login successful:", response.user
|
|
354
|
+
log("Login successful:", response.user?.userName);
|
|
328
355
|
return response;
|
|
329
356
|
},
|
|
330
357
|
async register(data) {
|
|
@@ -389,6 +416,26 @@ function createAuthApiClient(config, tokenStorage) {
|
|
|
389
416
|
});
|
|
390
417
|
return response;
|
|
391
418
|
},
|
|
419
|
+
async changePassword(data) {
|
|
420
|
+
const response = await request("/auth/changePassword", {
|
|
421
|
+
method: "POST",
|
|
422
|
+
body: JSON.stringify(data)
|
|
423
|
+
});
|
|
424
|
+
log("Password changed successfully");
|
|
425
|
+
return response;
|
|
426
|
+
},
|
|
427
|
+
async logout() {
|
|
428
|
+
try {
|
|
429
|
+
const response = await request("/auth/logout", {
|
|
430
|
+
method: "POST"
|
|
431
|
+
});
|
|
432
|
+
log("Logout successful");
|
|
433
|
+
return response;
|
|
434
|
+
} catch (error) {
|
|
435
|
+
log("Logout request failed, continuing with local cleanup:", error);
|
|
436
|
+
return { status: "ok" };
|
|
437
|
+
}
|
|
438
|
+
},
|
|
392
439
|
// ========================================================================
|
|
393
440
|
// User Endpoints
|
|
394
441
|
// ========================================================================
|
|
@@ -679,8 +726,15 @@ function AuthProvider({ config: userConfig, children }) {
|
|
|
679
726
|
},
|
|
680
727
|
[apiClient]
|
|
681
728
|
);
|
|
729
|
+
const changePassword = (0, import_react.useCallback)(
|
|
730
|
+
async (data) => {
|
|
731
|
+
return apiClient.changePassword(data);
|
|
732
|
+
},
|
|
733
|
+
[apiClient]
|
|
734
|
+
);
|
|
682
735
|
const logout = (0, import_react.useCallback)(async () => {
|
|
683
736
|
log("Logging out...");
|
|
737
|
+
await apiClient.logout();
|
|
684
738
|
await tokenStorage.clear();
|
|
685
739
|
apiClient.setAccessToken(null);
|
|
686
740
|
setState({
|
|
@@ -729,6 +783,7 @@ function AuthProvider({ config: userConfig, children }) {
|
|
|
729
783
|
resendVerification,
|
|
730
784
|
forgotPassword,
|
|
731
785
|
recoverPassword,
|
|
786
|
+
changePassword,
|
|
732
787
|
refreshTokens,
|
|
733
788
|
// Utilities
|
|
734
789
|
getAccessToken,
|
|
@@ -745,6 +800,7 @@ function AuthProvider({ config: userConfig, children }) {
|
|
|
745
800
|
resendVerification,
|
|
746
801
|
forgotPassword,
|
|
747
802
|
recoverPassword,
|
|
803
|
+
changePassword,
|
|
748
804
|
refreshTokens,
|
|
749
805
|
getAccessToken,
|
|
750
806
|
hasRole,
|
|
@@ -923,6 +979,7 @@ function useAuth() {
|
|
|
923
979
|
resendVerification: context.resendVerification,
|
|
924
980
|
forgotPassword: context.forgotPassword,
|
|
925
981
|
recoverPassword: context.recoverPassword,
|
|
982
|
+
changePassword: context.changePassword,
|
|
926
983
|
// Utilities
|
|
927
984
|
hasRole: context.hasRole
|
|
928
985
|
}),
|
|
@@ -1024,6 +1081,7 @@ function useAuthError() {
|
|
|
1024
1081
|
0 && (module.exports = {
|
|
1025
1082
|
AuthContext,
|
|
1026
1083
|
AuthProvider,
|
|
1084
|
+
DEFAULT_THEME,
|
|
1027
1085
|
createAuthApiClient,
|
|
1028
1086
|
createTokenStorage,
|
|
1029
1087
|
useAuth,
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext,
|
|
3
3
|
AuthProvider,
|
|
4
|
+
DEFAULT_THEME,
|
|
4
5
|
createAuthApiClient,
|
|
5
6
|
createTokenStorage,
|
|
6
7
|
useAuth,
|
|
@@ -11,10 +12,11 @@ import {
|
|
|
11
12
|
useRequireAuth,
|
|
12
13
|
useToken,
|
|
13
14
|
useUser
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ELVIBXBG.mjs";
|
|
15
16
|
export {
|
|
16
17
|
AuthContext,
|
|
17
18
|
AuthProvider,
|
|
19
|
+
DEFAULT_THEME,
|
|
18
20
|
createAuthApiClient,
|
|
19
21
|
createTokenStorage,
|
|
20
22
|
useAuth,
|
package/package.json
CHANGED
package/src/api/client.ts
CHANGED
|
@@ -21,6 +21,9 @@ import type {
|
|
|
21
21
|
RefreshTokenResponse,
|
|
22
22
|
ResendVerificationRequest,
|
|
23
23
|
ResendVerificationResponse,
|
|
24
|
+
ChangePasswordRequest,
|
|
25
|
+
ChangePasswordResponse,
|
|
26
|
+
LogoutResponse,
|
|
24
27
|
User,
|
|
25
28
|
} from '../types';
|
|
26
29
|
import type { TokenStorage } from '../utils/storage';
|
|
@@ -77,6 +80,8 @@ export interface AuthApiClient {
|
|
|
77
80
|
forgotPassword: (data: ForgotPasswordRequest) => Promise<ForgotPasswordResponse>;
|
|
78
81
|
recoverPassword: (data: RecoverPasswordRequest) => Promise<RecoverPasswordResponse>;
|
|
79
82
|
refreshToken: (data: RefreshTokenRequest) => Promise<RefreshTokenResponse>;
|
|
83
|
+
changePassword: (data: ChangePasswordRequest) => Promise<ChangePasswordResponse>;
|
|
84
|
+
logout: () => Promise<LogoutResponse>;
|
|
80
85
|
|
|
81
86
|
// User endpoints
|
|
82
87
|
getMe: () => Promise<User>;
|
|
@@ -229,6 +234,11 @@ export function createAuthApiClient(config: AuthConfig, tokenStorage: TokenStora
|
|
|
229
234
|
body: JSON.stringify(data),
|
|
230
235
|
});
|
|
231
236
|
|
|
237
|
+
// Server may return 2xx with a message instead of user (e.g. invalid credentials)
|
|
238
|
+
if (!response.user || !response.token) {
|
|
239
|
+
throw createAuthError(401, (response as any).message || 'Login failed');
|
|
240
|
+
}
|
|
241
|
+
|
|
232
242
|
currentAccessToken = response.token;
|
|
233
243
|
await tokenStorage.setTokens(
|
|
234
244
|
response.token,
|
|
@@ -238,7 +248,7 @@ export function createAuthApiClient(config: AuthConfig, tokenStorage: TokenStora
|
|
|
238
248
|
);
|
|
239
249
|
|
|
240
250
|
config.onLogin?.(response.user);
|
|
241
|
-
log('Login successful:', response.user
|
|
251
|
+
log('Login successful:', response.user?.userName);
|
|
242
252
|
|
|
243
253
|
return response;
|
|
244
254
|
},
|
|
@@ -320,6 +330,29 @@ export function createAuthApiClient(config: AuthConfig, tokenStorage: TokenStora
|
|
|
320
330
|
return response;
|
|
321
331
|
},
|
|
322
332
|
|
|
333
|
+
async changePassword(data: ChangePasswordRequest): Promise<ChangePasswordResponse> {
|
|
334
|
+
const response = await request<ChangePasswordResponse>('/auth/changePassword', {
|
|
335
|
+
method: 'POST',
|
|
336
|
+
body: JSON.stringify(data),
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
log('Password changed successfully');
|
|
340
|
+
return response;
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
async logout(): Promise<LogoutResponse> {
|
|
344
|
+
try {
|
|
345
|
+
const response = await request<LogoutResponse>('/auth/logout', {
|
|
346
|
+
method: 'POST',
|
|
347
|
+
});
|
|
348
|
+
log('Logout successful');
|
|
349
|
+
return response;
|
|
350
|
+
} catch (error) {
|
|
351
|
+
log('Logout request failed, continuing with local cleanup:', error);
|
|
352
|
+
return { status: 'ok' };
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
|
|
323
356
|
// ========================================================================
|
|
324
357
|
// User Endpoints
|
|
325
358
|
// ========================================================================
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { useState, useCallback, type FormEvent } from 'react';
|
|
7
7
|
import { useAuth } from '../hooks';
|
|
8
8
|
import type { ForgotPasswordFormProps, AuthError } from '../types';
|
|
9
|
+
import { DEFAULT_THEME } from '../types';
|
|
9
10
|
|
|
10
11
|
export function ForgotPasswordForm({
|
|
11
12
|
onSuccess,
|
|
@@ -13,7 +14,9 @@ export function ForgotPasswordForm({
|
|
|
13
14
|
onNavigateLogin,
|
|
14
15
|
showBranding = true,
|
|
15
16
|
className = '',
|
|
17
|
+
theme,
|
|
16
18
|
}: ForgotPasswordFormProps) {
|
|
19
|
+
const t = { ...DEFAULT_THEME, ...theme };
|
|
17
20
|
const { forgotPassword, isLoading, error } = useAuth();
|
|
18
21
|
|
|
19
22
|
const [email, setEmail] = useState('');
|
|
@@ -54,11 +57,11 @@ export function ForgotPasswordForm({
|
|
|
54
57
|
<div className={`pixygon-auth-container ${className}`}>
|
|
55
58
|
<style>{`
|
|
56
59
|
.pixygon-auth-container {
|
|
57
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
58
|
-
background:
|
|
59
|
-
color:
|
|
60
|
+
font-family: ${t.fontFamily === 'inherit' ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" : t.fontFamily};
|
|
61
|
+
background: ${t.backgroundColor};
|
|
62
|
+
color: ${t.textColor};
|
|
60
63
|
padding: 2rem;
|
|
61
|
-
border-radius:
|
|
64
|
+
border-radius: ${t.borderRadius};
|
|
62
65
|
max-width: 400px;
|
|
63
66
|
width: 100%;
|
|
64
67
|
margin: 0 auto;
|
|
@@ -84,13 +87,13 @@ export function ForgotPasswordForm({
|
|
|
84
87
|
|
|
85
88
|
.pixygon-auth-subtitle {
|
|
86
89
|
font-size: 0.875rem;
|
|
87
|
-
color:
|
|
90
|
+
color: ${t.textSecondary};
|
|
88
91
|
margin: 0;
|
|
89
92
|
line-height: 1.5;
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
.pixygon-auth-link {
|
|
93
|
-
color:
|
|
96
|
+
color: ${t.primaryColor};
|
|
94
97
|
text-decoration: none;
|
|
95
98
|
font-size: 0.875rem;
|
|
96
99
|
cursor: pointer;
|
|
@@ -109,7 +112,7 @@ export function ForgotPasswordForm({
|
|
|
109
112
|
text-align: center;
|
|
110
113
|
margin-top: 1.5rem;
|
|
111
114
|
font-size: 0.875rem;
|
|
112
|
-
color:
|
|
115
|
+
color: ${t.textSecondary};
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
.pixygon-auth-branding {
|
|
@@ -130,7 +133,7 @@ export function ForgotPasswordForm({
|
|
|
130
133
|
fill="none"
|
|
131
134
|
xmlns="http://www.w3.org/2000/svg"
|
|
132
135
|
>
|
|
133
|
-
<circle cx="50" cy="50" r="45" fill=
|
|
136
|
+
<circle cx="50" cy="50" r="45" fill={t.successColor} />
|
|
134
137
|
<path
|
|
135
138
|
d="M30 50L45 65L70 35"
|
|
136
139
|
stroke="white"
|
|
@@ -171,11 +174,11 @@ export function ForgotPasswordForm({
|
|
|
171
174
|
<div className={`pixygon-auth-container ${className}`}>
|
|
172
175
|
<style>{`
|
|
173
176
|
.pixygon-auth-container {
|
|
174
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
175
|
-
background:
|
|
176
|
-
color:
|
|
177
|
+
font-family: ${t.fontFamily === 'inherit' ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" : t.fontFamily};
|
|
178
|
+
background: ${t.backgroundColor};
|
|
179
|
+
color: ${t.textColor};
|
|
177
180
|
padding: 2rem;
|
|
178
|
-
border-radius:
|
|
181
|
+
border-radius: ${t.borderRadius};
|
|
179
182
|
max-width: 400px;
|
|
180
183
|
width: 100%;
|
|
181
184
|
margin: 0 auto;
|
|
@@ -201,7 +204,7 @@ export function ForgotPasswordForm({
|
|
|
201
204
|
|
|
202
205
|
.pixygon-auth-subtitle {
|
|
203
206
|
font-size: 0.875rem;
|
|
204
|
-
color:
|
|
207
|
+
color: ${t.textSecondary};
|
|
205
208
|
margin: 0;
|
|
206
209
|
}
|
|
207
210
|
|
|
@@ -220,31 +223,31 @@ export function ForgotPasswordForm({
|
|
|
220
223
|
.pixygon-auth-label {
|
|
221
224
|
font-size: 0.875rem;
|
|
222
225
|
font-weight: 500;
|
|
223
|
-
color:
|
|
226
|
+
color: ${t.textSecondary};
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
.pixygon-auth-input {
|
|
227
|
-
background:
|
|
230
|
+
background: ${t.surfaceColor};
|
|
228
231
|
border: 1px solid #404040;
|
|
229
232
|
border-radius: 0.5rem;
|
|
230
233
|
padding: 0.75rem 1rem;
|
|
231
234
|
font-size: 1rem;
|
|
232
|
-
color:
|
|
235
|
+
color: ${t.textColor};
|
|
233
236
|
outline: none;
|
|
234
237
|
transition: border-color 0.2s, box-shadow 0.2s;
|
|
235
238
|
}
|
|
236
239
|
|
|
237
240
|
.pixygon-auth-input:focus {
|
|
238
|
-
border-color:
|
|
241
|
+
border-color: ${t.primaryColor};
|
|
239
242
|
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
|
240
243
|
}
|
|
241
244
|
|
|
242
245
|
.pixygon-auth-input.error {
|
|
243
|
-
border-color:
|
|
246
|
+
border-color: ${t.errorColor};
|
|
244
247
|
}
|
|
245
248
|
|
|
246
249
|
.pixygon-auth-button {
|
|
247
|
-
background:
|
|
250
|
+
background: ${t.primaryColor};
|
|
248
251
|
color: white;
|
|
249
252
|
border: none;
|
|
250
253
|
border-radius: 0.5rem;
|
|
@@ -271,7 +274,7 @@ export function ForgotPasswordForm({
|
|
|
271
274
|
|
|
272
275
|
.pixygon-auth-error {
|
|
273
276
|
background: rgba(239, 68, 68, 0.1);
|
|
274
|
-
border: 1px solid
|
|
277
|
+
border: 1px solid ${t.errorColor};
|
|
275
278
|
border-radius: 0.5rem;
|
|
276
279
|
padding: 0.75rem 1rem;
|
|
277
280
|
color: #fca5a5;
|
|
@@ -279,7 +282,7 @@ export function ForgotPasswordForm({
|
|
|
279
282
|
}
|
|
280
283
|
|
|
281
284
|
.pixygon-auth-link {
|
|
282
|
-
color:
|
|
285
|
+
color: ${t.primaryColor};
|
|
283
286
|
text-decoration: none;
|
|
284
287
|
font-size: 0.875rem;
|
|
285
288
|
cursor: pointer;
|
|
@@ -298,7 +301,7 @@ export function ForgotPasswordForm({
|
|
|
298
301
|
text-align: center;
|
|
299
302
|
margin-top: 1.5rem;
|
|
300
303
|
font-size: 0.875rem;
|
|
301
|
-
color:
|
|
304
|
+
color: ${t.textSecondary};
|
|
302
305
|
}
|
|
303
306
|
|
|
304
307
|
.pixygon-auth-branding {
|
|
@@ -332,7 +335,7 @@ export function ForgotPasswordForm({
|
|
|
332
335
|
fill="none"
|
|
333
336
|
xmlns="http://www.w3.org/2000/svg"
|
|
334
337
|
>
|
|
335
|
-
<circle cx="50" cy="50" r="45" fill=
|
|
338
|
+
<circle cx="50" cy="50" r="45" fill={t.primaryColor} />
|
|
336
339
|
<path
|
|
337
340
|
d="M30 45L45 30L70 55L55 70L30 45Z"
|
|
338
341
|
fill="white"
|