@payez/next-mvp 4.0.21 → 4.0.23

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.
@@ -217,7 +217,7 @@ async function getBetterAuthInstance() {
217
217
  if (cachedInstance)
218
218
  return cachedInstance;
219
219
  if (!initPromise) {
220
- initPromise = (0, idp_client_config_1.getIDPClientConfig)().then(config => {
220
+ initPromise = (0, idp_client_config_1.getIDPClientConfig)(true).then(config => {
221
221
  const instance = createBetterAuthInstance(config);
222
222
  exports.__betterAuthInstance = cachedInstance = instance;
223
223
  console.log('[BETTER_AUTH] Instance created for', config.clientSlug || config.clientId);
@@ -4,9 +4,8 @@ interface AuthProviderProps {
4
4
  children: ReactNode;
5
5
  config?: Partial<AuthConfig>;
6
6
  /**
7
- * If true, providers will be fetched dynamically from NextAuth
7
+ * If true, providers will be loaded dynamically from IDP config
8
8
  * instead of using the static providers array from config.
9
- * Defaults to true for dynamic provider loading from IDP.
10
9
  */
11
10
  useDynamicProviders?: boolean;
12
11
  }
@@ -18,7 +18,7 @@ const defaultConfig = {
18
18
  enableEmailSignup: true,
19
19
  allowPasswordReset: true,
20
20
  };
21
- // Map NextAuth provider IDs to our FederatedProvider type
21
+ // Map provider IDs to our FederatedProvider type
22
22
  const PROVIDER_MAP = {
23
23
  'google': 'google',
24
24
  'apple': 'apple',
@@ -42,7 +42,7 @@ function AuthProvider({ children, config, useDynamicProviders = true }) {
42
42
  },
43
43
  },
44
44
  }));
45
- // Fetch dynamic providers from NextAuth on mount
45
+ // Load available providers on mount
46
46
  (0, react_1.useEffect)(() => {
47
47
  if (!useDynamicProviders)
48
48
  return;
@@ -956,6 +956,14 @@ export declare const useSession: () => {
956
956
  code?: string | undefined;
957
957
  message?: string | undefined;
958
958
  }, FetchOptions["throw"] extends true ? true : false>>;
959
+ /**
960
+ * Sign in with a specific OAuth provider via direct redirect.
961
+ *
962
+ * better-auth exposes per-provider endpoints at /api/auth/sign-in/{provider}
963
+ * (e.g. /api/auth/sign-in/google). The generic signIn.social() method POSTs
964
+ * to /api/auth/sign-in/social which doesn't exist — use this instead.
965
+ */
966
+ export declare function signInWithProvider(provider: string, callbackURL?: string): void;
959
967
  /**
960
968
  * NextAuth-compatible useSession wrapper.
961
969
  *
@@ -10,6 +10,7 @@
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.signOut = exports.signIn = exports.useSession = exports.authClient = void 0;
13
+ exports.signInWithProvider = signInWithProvider;
13
14
  exports.useSessionCompat = useSessionCompat;
14
15
  exports.signOutCompat = signOutCompat;
15
16
  const react_1 = require("better-auth/react");
@@ -19,6 +20,20 @@ exports.authClient = (0, react_1.createAuthClient)({
19
20
  });
20
21
  // Convenience exports
21
22
  exports.useSession = exports.authClient.useSession, exports.signIn = exports.authClient.signIn, exports.signOut = exports.authClient.signOut;
23
+ /**
24
+ * Sign in with a specific OAuth provider via direct redirect.
25
+ *
26
+ * better-auth exposes per-provider endpoints at /api/auth/sign-in/{provider}
27
+ * (e.g. /api/auth/sign-in/google). The generic signIn.social() method POSTs
28
+ * to /api/auth/sign-in/social which doesn't exist — use this instead.
29
+ */
30
+ function signInWithProvider(provider, callbackURL) {
31
+ const params = new URLSearchParams();
32
+ if (callbackURL)
33
+ params.set('callbackURL', callbackURL);
34
+ const qs = params.toString();
35
+ window.location.href = `/api/auth/sign-in/${provider}${qs ? '?' + qs : ''}`;
36
+ }
22
37
  /**
23
38
  * NextAuth-compatible useSession wrapper.
24
39
  *
@@ -44,7 +44,7 @@ function MobileNavDrawer({ isOpen, onClose, navItems, customSections, basePath =
44
44
  onSignIn();
45
45
  }
46
46
  else {
47
- better_auth_client_1.authClient.signIn.social({ provider: 'google', callbackURL: signInCallbackUrl });
47
+ (0, better_auth_client_1.signInWithProvider)('google', signInCallbackUrl);
48
48
  }
49
49
  };
50
50
  const handleSectionItemClick = (item) => {
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * useAvailableProviders Hook
3
3
  *
4
- * Fetches the list of OAuth providers actually configured in NextAuth.
5
- * This ensures UI only shows buttons for providers that are enabled in IDP.
4
+ * Returns the list of OAuth providers configured for this client.
5
+ * Ensures UI only shows buttons for providers that are enabled in IDP.
6
6
  */
7
7
  import type { FederatedProvider } from '../types/auth';
8
8
  export interface UseAvailableProvidersResult {
@@ -12,10 +12,9 @@ export interface UseAvailableProvidersResult {
12
12
  rawProviders: Record<string, any> | null;
13
13
  }
14
14
  /**
15
- * Hook to get available OAuth providers from NextAuth.
15
+ * Hook to get available federated OAuth providers.
16
16
  *
17
- * Returns only the providers that are actually configured in auth-options,
18
- * which reflects what's enabled in IDP config.
17
+ * Returns only the providers that are enabled in IDP config.
19
18
  *
20
19
  * @example
21
20
  * ```tsx
@@ -2,21 +2,21 @@
2
2
  /**
3
3
  * useAvailableProviders Hook
4
4
  *
5
- * Fetches the list of OAuth providers actually configured in NextAuth.
6
- * This ensures UI only shows buttons for providers that are enabled in IDP.
5
+ * Returns the list of OAuth providers configured for this client.
6
+ * Ensures UI only shows buttons for providers that are enabled in IDP.
7
7
  */
8
8
  'use client';
9
9
  /**
10
10
  * useAvailableProviders Hook
11
11
  *
12
- * Fetches the list of OAuth providers actually configured in NextAuth.
13
- * This ensures UI only shows buttons for providers that are enabled in IDP.
12
+ * Returns the list of OAuth providers configured for this client.
13
+ * Ensures UI only shows buttons for providers that are enabled in IDP.
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.useAvailableProviders = useAvailableProviders;
17
17
  exports.useIsProviderAvailable = useIsProviderAvailable;
18
18
  const react_1 = require("react");
19
- // Map NextAuth provider IDs to our FederatedProvider type
19
+ // Map provider IDs to our FederatedProvider type
20
20
  const PROVIDER_MAP = {
21
21
  'google': 'google',
22
22
  'apple': 'apple',
@@ -28,10 +28,9 @@ const PROVIDER_MAP = {
28
28
  // Providers we support in UI (excludes credentials)
29
29
  const OAUTH_PROVIDERS = ['google', 'apple', 'facebook', 'github', 'azure-ad', 'microsoft-entra-id'];
30
30
  /**
31
- * Hook to get available OAuth providers from NextAuth.
31
+ * Hook to get available federated OAuth providers.
32
32
  *
33
- * Returns only the providers that are actually configured in auth-options,
34
- * which reflects what's enabled in IDP config.
33
+ * Returns only the providers that are enabled in IDP config.
35
34
  *
36
35
  * @example
37
36
  * ```tsx
@@ -8,7 +8,7 @@ import type { FederatedProvider } from '../types/auth';
8
8
  export interface PublicAuthSettings {
9
9
  enabledProviders: FederatedProvider[];
10
10
  allowPublicRegistration: boolean;
11
- allowSocialLogin: boolean;
11
+ allowFederatedLogin: boolean;
12
12
  enablePasswordReset: boolean;
13
13
  require2FA: boolean;
14
14
  allowed2FAMethods: string[];
@@ -30,7 +30,7 @@ export interface UsePublicAuthSettingsResult {
30
30
  *
31
31
  * return (
32
32
  * <>
33
- * {settings?.allowSocialLogin && (
33
+ * {settings?.allowFederatedLogin && (
34
34
  * <FederatedAuthSection providers={settings.enabledProviders} />
35
35
  * )}
36
36
  * {settings?.allowPublicRegistration && (
@@ -43,9 +43,9 @@ export interface UsePublicAuthSettingsResult {
43
43
  */
44
44
  export declare function usePublicAuthSettings(): UsePublicAuthSettingsResult;
45
45
  /**
46
- * Hook to check if social login is enabled.
46
+ * Hook to check if federated (OAuth) login is enabled.
47
47
  */
48
- export declare function useSocialLoginEnabled(): boolean;
48
+ export declare function useFederatedLoginEnabled(): boolean;
49
49
  /**
50
50
  * Hook to check if public registration is enabled.
51
51
  */
@@ -14,7 +14,7 @@
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.usePublicAuthSettings = usePublicAuthSettings;
17
- exports.useSocialLoginEnabled = useSocialLoginEnabled;
17
+ exports.useFederatedLoginEnabled = useFederatedLoginEnabled;
18
18
  exports.usePublicRegistrationEnabled = usePublicRegistrationEnabled;
19
19
  exports.usePasswordResetEnabled = usePasswordResetEnabled;
20
20
  const react_1 = require("react");
@@ -30,7 +30,7 @@ const PROVIDER_MAP = {
30
30
  const DEFAULT_SETTINGS = {
31
31
  enabledProviders: [],
32
32
  allowPublicRegistration: true,
33
- allowSocialLogin: false,
33
+ allowFederatedLogin: false,
34
34
  enablePasswordReset: true,
35
35
  require2FA: true,
36
36
  allowed2FAMethods: ['email', 'sms'],
@@ -47,7 +47,7 @@ const DEFAULT_SETTINGS = {
47
47
  *
48
48
  * return (
49
49
  * <>
50
- * {settings?.allowSocialLogin && (
50
+ * {settings?.allowFederatedLogin && (
51
51
  * <FederatedAuthSection providers={settings.enabledProviders} />
52
52
  * )}
53
53
  * {settings?.allowPublicRegistration && (
@@ -109,11 +109,11 @@ function usePublicAuthSettings() {
109
109
  return { settings, isLoading, error };
110
110
  }
111
111
  /**
112
- * Hook to check if social login is enabled.
112
+ * Hook to check if federated (OAuth) login is enabled.
113
113
  */
114
- function useSocialLoginEnabled() {
114
+ function useFederatedLoginEnabled() {
115
115
  const { settings } = usePublicAuthSettings();
116
- return settings?.allowSocialLogin ?? false;
116
+ return settings?.allowFederatedLogin ?? false;
117
117
  }
118
118
  /**
119
119
  * Hook to check if public registration is enabled.
@@ -69,6 +69,10 @@ export declare function getIDPClientConfig(forceRefresh?: boolean): Promise<IDPC
69
69
  * Clear the config cache (useful for testing or forced refresh)
70
70
  */
71
71
  export declare function clearConfigCache(): void;
72
+ /**
73
+ * Clear the Redis config cache so the next fetch always goes to IDP.
74
+ */
75
+ export declare function clearConfigRedisCache(): Promise<void>;
72
76
  /**
73
77
  * Get enabled OAuth providers from config
74
78
  */
@@ -24,6 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.getIDPClientConfig = getIDPClientConfig;
26
26
  exports.clearConfigCache = clearConfigCache;
27
+ exports.clearConfigRedisCache = clearConfigRedisCache;
27
28
  exports.getEnabledProviders = getEnabledProviders;
28
29
  require("server-only");
29
30
  const crypto_1 = require("crypto");
@@ -176,6 +177,19 @@ function clearConfigCache() {
176
177
  cachedConfig = null;
177
178
  cacheExpiry = 0;
178
179
  }
180
+ /**
181
+ * Clear the Redis config cache so the next fetch always goes to IDP.
182
+ */
183
+ async function clearConfigRedisCache() {
184
+ try {
185
+ const key = getRedisConfigKey();
186
+ await redis_1.default.del(key);
187
+ console.log('[IDP_CONFIG] Redis cache cleared:', key);
188
+ }
189
+ catch (error) {
190
+ console.warn('[IDP_CONFIG] Failed to clear Redis cache:', error);
191
+ }
192
+ }
179
193
  /**
180
194
  * Get enabled OAuth providers from config
181
195
  */
@@ -136,6 +136,8 @@ async function performInitialization() {
136
136
  try {
137
137
  // Step 1: Fetch full client config from IDP (includes secret, providers, settings)
138
138
  console.log('[STARTUP] Step 1/2: Fetching client config from IDP...');
139
+ // Clear any stale Redis cache so startup always gets fresh IDP data
140
+ await (0, idp_client_config_1.clearConfigRedisCache)();
139
141
  try {
140
142
  const config = await (0, idp_client_config_1.getIDPClientConfig)(true);
141
143
  cachedIDPConfig = config;
@@ -206,25 +208,25 @@ async function performInitialization() {
206
208
  const connectionLine = isConnectionError
207
209
  ? '║ 🔌 CONNECTION REFUSED - IDP appears to be down ║\n║ ║\n'
208
210
  : '';
209
- console.error(`
210
- ╔══════════════════════════════════════════════════════════════╗
211
- ║ ❌ FATAL: NEXTAUTH_SECRET NOT AVAILABLE ║
212
- ║ ║
213
- ║ The app cannot start without a valid NEXTAUTH_SECRET. ║
214
- ║ This should be fetched from IDP at startup. ║
215
- ║ ║
216
- ${connectionLine}║ Possible causes: ║
217
- ║ • IDP is not running or unreachable ║
218
- ║ • CLIENT_ID is not registered in IDP ║
219
- ║ • IDP_URL is incorrect ║
220
- ║ • Network connectivity issue ║
221
- ║ ║
222
- ║ Current config: ║
223
- ║ • IDP_URL: ${idpUrl}║
224
- ║ • CLIENT_ID: ${clientId}║
225
- ╚══════════════════════════════════════════════════════════════╝
226
-
227
- [STARTUP] Error: ${errorMsg}
211
+ console.error(`
212
+ ╔══════════════════════════════════════════════════════════════╗
213
+ ║ ❌ FATAL: NEXTAUTH_SECRET NOT AVAILABLE ║
214
+ ║ ║
215
+ ║ The app cannot start without a valid NEXTAUTH_SECRET. ║
216
+ ║ This should be fetched from IDP at startup. ║
217
+ ║ ║
218
+ ${connectionLine}║ Possible causes: ║
219
+ ║ • IDP is not running or unreachable ║
220
+ ║ • CLIENT_ID is not registered in IDP ║
221
+ ║ • IDP_URL is incorrect ║
222
+ ║ • Network connectivity issue ║
223
+ ║ ║
224
+ ║ Current config: ║
225
+ ║ • IDP_URL: ${idpUrl}║
226
+ ║ • CLIENT_ID: ${clientId}║
227
+ ╚══════════════════════════════════════════════════════════════╝
228
+
229
+ [STARTUP] Error: ${errorMsg}
228
230
  `);
229
231
  // Re-throw so callers know initialization failed
230
232
  throw lastInitError;
@@ -8,7 +8,7 @@ import { NextResponse } from 'next/server';
8
8
  export interface PublicAuthSettings {
9
9
  enabledProviders: string[];
10
10
  allowPublicRegistration: boolean;
11
- allowSocialLogin: boolean;
11
+ allowFederatedLogin: boolean;
12
12
  enablePasswordReset: boolean;
13
13
  require2FA: boolean;
14
14
  allowed2FAMethods: string[];
@@ -25,7 +25,7 @@ async function GET() {
25
25
  .map(p => p.provider) ?? [],
26
26
  // Registration - default to true if not specified
27
27
  allowPublicRegistration: true, // Could come from config.authSettings in future
28
- allowSocialLogin: config.oauthProviders?.some(p => p.enabled) ?? false,
28
+ allowFederatedLogin: config.oauthProviders?.some(p => p.enabled) ?? false,
29
29
  // Password reset
30
30
  enablePasswordReset: true, // Could come from config.authSettings in future
31
31
  // 2FA
@@ -45,7 +45,7 @@ async function GET() {
45
45
  data: {
46
46
  enabledProviders: [],
47
47
  allowPublicRegistration: true,
48
- allowSocialLogin: false,
48
+ allowFederatedLogin: false,
49
49
  enablePasswordReset: true,
50
50
  require2FA: true,
51
51
  allowed2FAMethods: ['email', 'sms'],
@@ -57,7 +57,7 @@ async function getAuthInstance() {
57
57
  if (authInstance)
58
58
  return authInstance;
59
59
  if (!authInitPromise) {
60
- authInitPromise = (0, idp_client_config_1.getIDPClientConfig)().then(config => {
60
+ authInitPromise = (0, idp_client_config_1.getIDPClientConfig)(true).then(config => {
61
61
  authInstance = (0, better_auth_1.createBetterAuthInstance)(config);
62
62
  return authInstance;
63
63
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payez/next-mvp",
3
- "version": "4.0.21",
3
+ "version": "4.0.23",
4
4
  "sideEffects": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",