diff --git a/package.json b/package.json index e7340c5..a855ee6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neynar/create-farcaster-mini-app", - "version": "1.7.10", + "version": "1.7.11", "type": "module", "private": false, "access": "public", diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 30368ab..6b3ad05 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -22,8 +22,8 @@ export default async function RootLayout({ let session = null; if (shouldUseSession) { try { - const authModule = eval('require("~/auth")'); - session = await authModule.getSession(); + const { getSession } = await import('~/auth'); + session = await getSession(); } catch (error) { console.warn('Failed to get session:', error); } diff --git a/src/app/providers.tsx b/src/app/providers.tsx index 429a147..63fb582 100644 --- a/src/app/providers.tsx +++ b/src/app/providers.tsx @@ -4,6 +4,7 @@ import dynamic from 'next/dynamic'; import { MiniAppProvider } from '@neynar/react'; import { SafeFarcasterSolanaProvider } from '~/components/providers/SafeFarcasterSolanaProvider'; import { ANALYTICS_ENABLED } from '~/lib/constants'; +import React, { useState, useEffect } from 'react'; const WagmiProvider = dynamic( () => import('~/components/providers/WagmiProvider'), @@ -12,72 +13,107 @@ const WagmiProvider = dynamic( } ); +// Helper component to conditionally render auth providers +function AuthProviders({ + children, + session, + shouldUseSession, +}: { + children: React.ReactNode; + session: any; + shouldUseSession: boolean; +}) { + const [authComponents, setAuthComponents] = useState<{ + SessionProvider: React.ComponentType | null; + AuthKitProvider: React.ComponentType | null; + loaded: boolean; + }>({ + SessionProvider: null, + AuthKitProvider: null, + loaded: false, + }); + + useEffect(() => { + if (!shouldUseSession) { + setAuthComponents({ + SessionProvider: null, + AuthKitProvider: null, + loaded: true, + }); + return; + } + + const loadAuthComponents = async () => { + try { + // Dynamic imports for auth modules + let SessionProvider = null; + let AuthKitProvider = null; + + try { + const nextAuth = await import('next-auth/react'); + SessionProvider = nextAuth.SessionProvider; + } catch (error) { + console.warn('NextAuth not available:', error); + } + + try { + const authKit = await import('@farcaster/auth-kit'); + AuthKitProvider = authKit.AuthKitProvider; + } catch (error) { + console.warn('Farcaster AuthKit not available:', error); + } + + setAuthComponents({ + SessionProvider, + AuthKitProvider, + loaded: true, + }); + } catch (error) { + console.error('Error loading auth components:', error); + setAuthComponents({ + SessionProvider: null, + AuthKitProvider: null, + loaded: true, + }); + } + }; + + loadAuthComponents(); + }, [shouldUseSession]); + + if (!authComponents.loaded) { + return
Loading...
; + } + + if (!shouldUseSession || !authComponents.SessionProvider) { + return <>{children}; + } + + const { SessionProvider, AuthKitProvider } = authComponents; + + if (AuthKitProvider) { + return ( + + {children} + + ); + } + + return {children}; +} + export function Providers({ session, children, shouldUseSession = false, }: { - session: unknown | null; + session: any | null; children: React.ReactNode; shouldUseSession?: boolean; }) { const solanaEndpoint = process.env.SOLANA_RPC_ENDPOINT || 'https://solana-rpc.publicnode.com'; - // Only wrap with SessionProvider if next auth is used - if (shouldUseSession) { - // Dynamic import for auth components - will work if modules exist, fallback if not - const AuthWrapper = dynamic( - () => { - return Promise.resolve().then(() => { - // Use eval to avoid build-time module resolution - try { - const nextAuth = eval('require("next-auth/react")'); - const authKit = eval('require("@farcaster/auth-kit")'); - - const AuthWrapper = ({ - children, - }: { - children: React.ReactNode; - }) => ( - - - {children} - - - ); - AuthWrapper.displayName = 'AuthWrapper'; - return AuthWrapper; - } catch (_error) { - // Fallback component when auth modules aren't available - const FallbackWrapper = ({ - children, - }: { - children: React.ReactNode; - }) => <>{children}; - FallbackWrapper.displayName = 'FallbackWrapper'; - return FallbackWrapper; - } - }); - }, - { ssr: false } - ); - - return ( - - - - {children} - - - - ); - } - - // Return without SessionProvider if no session return ( - {children} + + {children} + diff --git a/src/components/ui/tabs/ActionsTab.tsx b/src/components/ui/tabs/ActionsTab.tsx index c633ed9..8c418e9 100644 --- a/src/components/ui/tabs/ActionsTab.tsx +++ b/src/components/ui/tabs/ActionsTab.tsx @@ -9,19 +9,12 @@ import { SignIn } from '../wallet/SignIn'; import { type Haptics } from '@farcaster/miniapp-sdk'; import { APP_URL } from '~/lib/constants'; -// Optional import for NeynarAuthButton - may not exist in all templates +// Import NeynarAuthButton const NeynarAuthButton = dynamic( - () => { - return Promise.resolve().then(() => { - try { - const authModule = eval('require("../NeynarAuthButton/index")'); - return authModule.default || authModule.NeynarAuthButton; - } catch (_error) { - // Return null component when module doesn't exist - return () => null; - } - }); - }, + () => + import('../NeynarAuthButton').then((module) => ({ + default: module.NeynarAuthButton, + })), { ssr: false } ); @@ -156,7 +149,7 @@ export function ActionsTab() { {/* Neynar Authentication */} - {NeynarAuthButton && } + {/* Mini app actions */}