import { useIsLoggedIn, useParams } from 'common' import { Terminal } from 'lucide-react' import Head from 'next/head' import Link from 'next/link' import { useRouter } from 'next/router' import { useEffect, useRef, useState, type ReactNode } from 'react' import { Button, Card, CardContent } from 'ui' import { Admonition, ShimmeringLoader } from 'ui-patterns' import { InterstitialAccountRow, InterstitialLayout, LogoBox, LogoPair, BrivenLogo, } from '@/components/layouts/InterstitialLayout' import CopyButton from '@/components/ui/CopyButton' import { InlineLink } from '@/components/ui/InlineLink' import { createCliLoginSession } from '@/data/cli/login' import { withAuth } from '@/hooks/misc/withAuth' import { useStaticEffectEvent } from '@/hooks/useStaticEffectEvent' import { buildStudioPageTitle } from '@/lib/page-title' import { useProfile } from '@/lib/profile' import type { NextPageWithLayout } from '@/types' const PAGE_TITLE = buildStudioPageTitle({ section: 'Authorize CLI', brand: 'Briven' }) const CliLogo = () => ( ) const CliLoginInterstitial = ({ title, description, children, }: { title: ReactNode description?: ReactNode children: ReactNode }) => ( } right={} />} title={title} description={description} >
{children}
) function getErrorMessage(error: unknown): string { if (error instanceof Error) return error.message if ( typeof error === 'object' && error !== null && 'message' in error && typeof (error as { message: unknown }).message === 'string' ) { return (error as { message: string }).message } return 'Unknown error' } const CliLoginPage: NextPageWithLayout = () => { const router = useRouter() const { session_id, public_key, token_name, device_code } = useParams() const isLoggedIn = useIsLoggedIn() if (!router.isReady) return null return ( <> {PAGE_TITLE} router.push(destination)} /> ) } type CliLoginStatus = | { _tag: 'loading' } | { _tag: 'ready'; deviceCode: string } | { _tag: 'missing-params'; missingParameters: string[] } | { _tag: 'error'; message?: string } export const CliLoginScreen = ({ isLoggedIn, routerReady, sessionId, publicKey, tokenName, deviceCode, navigate: navigateProp, }: { isLoggedIn: boolean routerReady: boolean sessionId?: string publicKey?: string tokenName?: string deviceCode?: string navigate: (destination: string) => void }) => { const { profile } = useProfile() const [status, setStatus] = useState({ _tag: 'loading' }) const startedForSessionIdRef = useRef(undefined) // Keep navigate in a ref so changing the prop never re-triggers the effect // or cancels an in-flight POST via the isActive cleanup. const navigate = useStaticEffectEvent(navigateProp) const displayName = profile?.primary_email ?? profile?.username useEffect(() => { if (!isLoggedIn || !routerReady) return if (deviceCode) { setStatus({ _tag: 'ready', deviceCode }) return } const missingParameters = [ !sessionId ? 'session_id' : undefined, !publicKey ? 'public_key' : undefined, ].filter(Boolean) as string[] if (missingParameters.length > 0) { setStatus({ _tag: 'missing-params', missingParameters }) return } // Guard against re-render loops triggered by unstable deps (e.g. a new // `navigate` reference on each parent render) firing the POST more than // once per session_id. Without this, the dashboard creates several // identical access tokens before navigating to the device_code view. if (startedForSessionIdRef.current === sessionId) return startedForSessionIdRef.current = sessionId let isActive = true setStatus({ _tag: 'loading' }) async function createSession() { try { const { nonce } = await createCliLoginSession(sessionId!, publicKey!, tokenName) if (!isActive) return if (nonce) { navigate(`/cli/login?device_code=${nonce.substring(0, 8)}`) } else { setStatus({ _tag: 'error', message: 'The CLI sign-in session did not return a code.' }) } } catch (error: unknown) { if (!isActive) return setStatus({ _tag: 'error', message: getErrorMessage(error) }) } } createSession() return () => { isActive = false } }, [deviceCode, isLoggedIn, publicKey, routerReady, sessionId, tokenName, navigate]) if (status._tag === 'loading') { return ( } description={} >
) } if (status._tag === 'missing-params') { const isPlural = status.missingParameters.length > 1 return (
) } if (status._tag === 'error') { return (
Briven could not create the CLI sign-in session. {status.message && ( Error: {status.message} )} } />
) } return (
{ event.preventDefault() event.clipboardData.setData('text/plain', status.deviceCode) }} > {Array.from(status.deviceCode.padEnd(8, ' ')).map((character, index) => ( {character} ))}

After authorizing, you can close this tab or manage tokens like this one in{' '} Access Tokens.

) } export default withAuth(CliLoginPage)