import type {Bud} from '@roots/bud-framework' import type {StatsCompilation} from '@roots/bud-framework/config' import {exit} from 'node:process' import Footer from '@roots/bud-dashboard/components/footer' import Compilation from '@roots/bud-dashboard/views/compilation' import Debug from '@roots/bud-dashboard/views/debug' import Server from '@roots/bud-dashboard/views/server' import escapes from '@roots/bud-support/ansi-escapes' import {render as renderError} from '@roots/bud-support/errors' import { Box, type PropsWithChildren, Static, useApp, useInput, useState, useStdout, } from '@roots/bud-support/ink' export interface Props { basedir?: string close?: (callback: (error?: Error | null) => any) => any compact?: boolean compilations?: Array> debug?: boolean devUrl?: URL displayAssets?: boolean displayEntrypoints?: boolean displayServerInfo?: boolean error?: Error errors?: StatsCompilation[`errors`] isolated?: number mode: Bud['mode'] notifier?: Bud[`notifier`] proxy?: boolean proxyUrl?: URL publicDevUrl?: URL publicProxyUrl?: URL warnings?: StatsCompilation[`warnings`] } export const Application = ({ basedir, compact, compilations, debug, devUrl, displayAssets, displayEntrypoints, displayServerInfo, error, isolated = 0, mode, proxy, proxyUrl, publicDevUrl, publicProxyUrl, }: Props) => { const {stdout} = useStdout() compilations = Array.isArray(compilations) ? (compilations?.filter(compilation => compilation.hash) ?? []) : [] if (error) { renderError(error) return null } if (mode === `production`) { return ( {(compilation, id) => { if (isolated > 0 && id + 1 !== isolated) return null return ( ) }} ) } return ( <> {compilations.map((compilation, id) => ( ))} ) } export const RenderCompilation = ({ basedir, compact, compilation, compilations, debug, displayAssets, displayEntrypoints, id, stdout, }: { basedir?: string compact?: boolean compilation: Partial compilations?: Array> debug?: boolean displayAssets?: boolean displayEntrypoints?: boolean id: number stdout: NodeJS.WriteStream }) => { return ( ) } export const TeletypeApplication = ({ children, close, notifier, ...props }: PropsWithChildren) => { const onExit = useOnExit() const stdout = useStdout() const [compact, setCompact] = useState(props.compact) const [debug, setDisplayDebug] = useState(props.debug) const [displayAssets, setDisplayAssets] = useState(props.displayAssets) const [displayEntrypoints, setDisplayEntrypoints] = useState(true) const [displayServerInfo, setDisplayServerInfo] = useState( props.displayServerInfo, ) const [help, setHelp] = useState(false) const [isolated, setIsolated] = useState(0) useInput((key, input) => { switch (key) { case `a`: setDisplayAssets(!displayAssets) break case `b`: if (notifier?.openBrowser && props.devUrl) { notifier.openBrowser(props.devUrl?.toString()) notifier.browserOpened = false } break case `c`: setCompact(!compact) break case `d`: setDisplayDebug(!debug) break case `e`: setDisplayEntrypoints(!displayEntrypoints) break case `h`: setHelp(!help) break case `q`: onExit() break case `r`: stdout.write(escapes.clearTerminal) break case `s`: setDisplayServerInfo(!displayServerInfo) break case `0`: setIsolated(0) break } new Array(9).fill(0).forEach((_, i) => { if (!props.compilations) return key === `${i + 1}` && isolated !== i + 1 && setIsolated(Math.min(i + 1, props.compilations.length)) }) if (input.escape) onExit() }) return ( <>