@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.
@@ -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' | 'basic' | 'pro' | 'family' | 'enterprise';
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-server.onrender.com/v1) */
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 { AuthContextValue as A, ForgotPasswordRequest as F, LoginRequest as L, PixygonAuthProps as P, RegisterRequest as R, SubscriptionTier as S, TokenPair as T, User as U, VerifyRequest as V, AuthConfig as a, AuthError as b, AuthStatus as c, UserRole as d, AuthStorage as e, LoginResponse as f, RegisterResponse as g, VerifyResponse as h, ResendVerificationRequest as i, ResendVerificationResponse as j, ForgotPasswordResponse as k, RecoverPasswordRequest as l, RecoverPasswordResponse as m, RefreshTokenRequest as n, RefreshTokenResponse as o, AuthErrorCode as p, AuthState as q, ForgotPasswordFormProps as r, LoginFormProps as s, RegisterFormProps as t, TokenPayload as u, VerifyFormProps as v };
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-CIK2MKl9.mjs';
2
- export { p as AuthErrorCode, q as AuthState, r as ForgotPasswordFormProps, s as LoginFormProps, P as PixygonAuthProps, t as RegisterFormProps, S as SubscriptionTier, u as TokenPayload, v as VerifyFormProps } from './index-CIK2MKl9.mjs';
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-CIK2MKl9.js';
2
- export { p as AuthErrorCode, q as AuthState, r as ForgotPasswordFormProps, s as LoginFormProps, P as PixygonAuthProps, t as RegisterFormProps, S as SubscriptionTier, u as TokenPayload, v as VerifyFormProps } from './index-CIK2MKl9.js';
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
- return localStorage.getItem(key);
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
- localStorage.setItem(key, value);
73
+ try {
74
+ localStorage.setItem(key, value);
75
+ } catch {
76
+ }
56
77
  },
57
78
  removeItem: (key) => {
58
79
  if (typeof window === "undefined") return;
59
- localStorage.removeItem(key);
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.userName);
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-E34M2RJD.mjs";
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixygon/auth",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Shared authentication package for all Pixygon applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
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.userName);
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: #0f0f0f;
59
- color: #ffffff;
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: 1rem;
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: #a3a3a3;
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: #6366f1;
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: #a3a3a3;
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="#22c55e" />
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: #0f0f0f;
176
- color: #ffffff;
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: 1rem;
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: #a3a3a3;
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: #a3a3a3;
226
+ color: ${t.textSecondary};
224
227
  }
225
228
 
226
229
  .pixygon-auth-input {
227
- background: #262626;
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: #ffffff;
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: #6366f1;
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: #ef4444;
246
+ border-color: ${t.errorColor};
244
247
  }
245
248
 
246
249
  .pixygon-auth-button {
247
- background: #6366f1;
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 #ef4444;
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: #6366f1;
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: #a3a3a3;
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="#6366f1" />
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"