Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ improve(minor): bud dev dx #2482

Merged
merged 2 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 18 additions & 26 deletions sources/@roots/bud-compiler/src/service/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {Error as DisplayError} from '@roots/bud-dashboard/components/error'
import {Service} from '@roots/bud-framework/service'
import {bind} from '@roots/bud-support/decorators/bind'
import {BudError} from '@roots/bud-support/errors'
import {render} from '@roots/bud-support/ink'
import isNull from '@roots/bud-support/lodash/isNull'
import isNumber from '@roots/bud-support/lodash/isNumber'
import isString from '@roots/bud-support/lodash/isString'
Expand All @@ -31,11 +30,6 @@ import stripAnsi from '@roots/bud-support/strip-ansi'
* {@link BudCompiler} implementation
*/
class Compiler extends Service implements BudCompiler {
/**
* {@link BudCompiler.compilationStats}
*/
public declare compilationStats: BudCompiler[`compilationStats`]

/**
* {@link BudCompiler.config}
*/
Expand Down Expand Up @@ -73,9 +67,11 @@ class Compiler extends Service implements BudCompiler {
})

if (`isBudError` in error) {
render(<DisplayError error={error} />)
this.app.context.render(<DisplayError error={error} />)
} else {
render(<DisplayError error={BudError.normalize(error)} />)
this.app.context.render(
<DisplayError error={BudError.normalize(error)} />,
)
}
}
/**
Expand All @@ -88,26 +84,21 @@ class Compiler extends Service implements BudCompiler {
? `${this.app.label} (${child.name})`
: child.name

this.stats = stats

this.compilationStats = stats.toJson(statsOptions)

this.app.dashboard.updateStats(this.compilationStats)
this.stats = stats.toJson(statsOptions)
this.app.context.render(this.app.dashboard.render(stats))

if (stats.hasErrors()) {
process.exitCode = 1

this.compilationStats.children = this.compilationStats.children?.map(
child => ({
...child,
errors:
child.errors && this.sourceErrors
? this.sourceErrors(child.errors)
: child.errors ?? [],
}),
)
this.stats.children = this.stats.children?.map(child => ({
...child,
errors:
child.errors && this.sourceErrors
? this.sourceErrors(child.errors)
: child.errors ?? [],
}))

this.compilationStats.children
this.stats.children
?.filter(
child => isNumber(child.errorsCount) && child.errorsCount > 0,
)
Expand All @@ -131,7 +122,7 @@ class Compiler extends Service implements BudCompiler {
})
}

this.compilationStats.children
this.stats.children
?.filter(child => child.errorsCount === 0)
.forEach(child => {
try {
Expand All @@ -146,6 +137,7 @@ class Compiler extends Service implements BudCompiler {
})

this.app.server?.publicUrl.href &&
this.app.context.browser &&
this.app.notifier.openBrowser(this.app.server?.publicUrl.href)
} catch (error) {
this.logger.error(error)
Expand Down Expand Up @@ -224,8 +216,8 @@ class Compiler extends Service implements BudCompiler {
* In a perfect world webpack plugins would use the
* `nameForCondition` property to identify the module.
*/
if (ident && this.compilationStats?.children) {
module = this.compilationStats.children
if (ident && this.stats?.children) {
module = this.stats.children
.flatMap(child => child?.modules)
.find(module => [module?.id, module?.name].includes(ident))
}
Expand Down
105 changes: 68 additions & 37 deletions sources/@roots/bud-dashboard/src/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {StatsCompilation} from '@roots/bud-framework/config'
import {exit} from 'node:process'

import {Error} from '@roots/bud-dashboard/components/error'
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'
Expand All @@ -16,11 +17,11 @@ import {
useState,
useStdout,
} from '@roots/bud-support/ink'
import escapes from '@roots/bud-support/ansi-escapes'

export interface Props {
basedir?: string
close?: (callback: (error?: Error | null) => any) => void
closed?: boolean
close?: (callback: (error?: Error | null) => any) => any
compact?: boolean
compilations?: Array<Partial<StatsCompilation>>
debug?: boolean
Expand All @@ -32,11 +33,12 @@ export interface Props {
errors?: StatsCompilation[`errors`]
isolated?: number
mode: Bud['mode']
notifier?: Bud[`notifier`]
proxy?: boolean
proxyUrl?: URL
publicDevUrl?: URL
publicProxyUrl?: URL
status?: false | string
displayHelp?: boolean
warnings?: StatsCompilation[`warnings`]
}

Expand All @@ -56,7 +58,7 @@ export const Application = ({
proxyUrl,
publicDevUrl,
publicProxyUrl,
status,
displayHelp,
}: Props) => {
const {stdout} = useStdout()

Expand Down Expand Up @@ -96,6 +98,7 @@ export const Application = ({
return (
<>
{error && <Error error={error} />}

{compilations.map((compilation, id) => (
<RenderCompilation
basedir={basedir}
Expand Down Expand Up @@ -165,73 +168,101 @@ export const RenderCompilation = ({
export const TeletypeApplication = ({
children,
close,
notifier,
...props
}: PropsWithChildren<Props>) => {
const app = useApp()
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 [debug, setDisplayDebug] = useState(props.debug)
const [displayEntrypoints, setDisplayEntrypoints] = useState(true)
const [displayAssets, setDisplayAssets] = useState(props.displayAssets)
const [closed, setClosed] = useState(false)
const [compact, setCompact] = useState(props.compact)
const [help, setHelp] = useState(false)
const [isolated, setIsolated] = useState(0)

useInput((key, input) => {
switch (key) {
case `a`:
setDisplayAssets(!displayAssets)
break
case `e`:
setDisplayEntrypoints(!displayEntrypoints)

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 `c`:
setCompact(!compact)
break

case `0`:
setIsolated(0)
break
default:
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) {
setClosed(true)
if (close)
close((error?) => {
if (error) app.exit(error)
else app.exit()

exit(error ? 1 : 0)
})
}
if (input.escape) onExit()
})

return (
<Application
{...props}
closed={closed}
compact={compact}
debug={debug}
displayAssets={displayAssets}
displayEntrypoints={displayEntrypoints}
displayServerInfo={displayServerInfo}
isolated={isolated}
/>
<>
<Application
{...props}
compact={compact}
debug={debug}
displayAssets={displayAssets}
displayEntrypoints={displayEntrypoints}
displayServerInfo={displayServerInfo}
isolated={isolated}
/>
<Footer display={help} />
</>
)
}

const useOnExit = () => {
const app = useApp()

return (error?: Error | null): any => {
if (error) app.exit(error)
else app.exit()
exit(error ? 1 : 0)
}
}
70 changes: 70 additions & 0 deletions sources/@roots/bud-dashboard/src/components/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {Box, Text} from '@roots/bud-support/ink'

export interface Props {
display?: boolean
}

const Footer = ({display}: Props) => {
if (!display) {
return (
<Box flexDirection="column">
<Text>{` `}</Text>
<Text>
<Text dimColor>{` `}Press</Text> h{' '}
<Text dimColor>to show help</Text>
</Text>
</Box>
)
}

return (
<Box flexDirection="column">
<Text>{` `}</Text>
<Text color="blue">
{` `}Shortcuts{` `}
</Text>
<Text>{` `}</Text>
<Text>
{` `}
<Text dimColor>Press</Text> b <Text dimColor>to open browser</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> c{' '}
<Text dimColor>to toggle compact display</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> d{' '}
<Text dimColor>
to toggle detailed debug information (may be system intensive)
</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> e{' '}
<Text dimColor>to toggle entrypoints display</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> h <Text dimColor>to hide help</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> q <Text dimColor>to quit</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> r{' '}
<Text dimColor>to clear/reload console</Text>
</Text>
<Text>
{` `}
<Text dimColor>Press</Text> s{' '}
<Text dimColor>to toggle server info display</Text>
</Text>
</Box>
)
}

export default Footer
Loading