Skip to content

Commit

Permalink
chore: update ink to v3 (#26190)
Browse files Browse the repository at this point in the history
* Fix most stuff

* Whitespace

* Upgrade spinners

* Format

* Wrap error in text

* Fix devDeps

* Remove ink-box

* Eslint fix

* Eslint

* Eslint

* Eslint

* Fix return type missing

* fix: update bundled ink

* fix: update caniuse-lite so tests pass

* since we started bundling ink resolution check was almost never true ... because `ink` module wasn't installed - it was bundled in `gatsby-cli` (yikes)

* workaround rollup problem when trying to import cjs with default

* some tests should be fixed

* ink auto wraps output, so current ln splitting won't work well - just accumulate output as is and instead of checking exact output, replace spaces with any whitespace in matcher

* fix "default" import thingies

* add comment about nullable stdout

Co-authored-by: Kyle Mathews <mathews.kyle@gmail.com>
Co-authored-by: Adam Schay <adamschay@gmail.com>
Co-authored-by: Michal Piechowiak <misiek.piechowiak@gmail.com>
  • Loading branch information
4 people committed Dec 15, 2020
1 parent 52027db commit 1e702ae
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 184 deletions.
13 changes: 7 additions & 6 deletions integration-tests/gatsby-cli/test-helpers/invoke-cli.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import execa, { sync } from "execa"
import { join } from "path"
import strip from "strip-ansi"
import { createLogsMatcher } from "./matcher"

const gatsbyBinLocation = join(
Expand All @@ -23,12 +24,12 @@ export const GatsbyCLI = {

return [
results.exitCode,
createLogsMatcher(results.stdout.toString().split("\n")),
createLogsMatcher(strip(results.stdout.toString())),
]
} catch (err) {
return [
err.exitCode,
createLogsMatcher(err.stdout?.toString().split("\n") || ``),
createLogsMatcher(strip(err.stdout?.toString() || ``)),
]
}
},
Expand All @@ -40,13 +41,13 @@ export const GatsbyCLI = {
env: { NODE_ENV, CI: 1, GATSBY_LOGGER: `ink` },
})

const logs = []
let logs = ``
res.stdout.on("data", data => {
if (!res.killed) {
logs.push(data.toString())
logs += data.toString()
}

if (onExit && onExit(data.toString())) {
if (onExit && onExit(strip(logs))) {
res.cancel()
}
})
Expand All @@ -59,7 +60,7 @@ export const GatsbyCLI = {

throw err
}),
() => createLogsMatcher(logs),
() => createLogsMatcher(strip(logs)),
]
},
}
Expand Down
24 changes: 5 additions & 19 deletions integration-tests/gatsby-cli/test-helpers/matcher.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
import strip from "strip-ansi"

export const createLogsMatcher = output => {
const logs = output.map(strip)

return {
// Useful for debuggging
// Useful for debugging
logOutput() {
console.log(logs.join("\n"))
console.log(output)
},

should: {
contain: match => {
const foundMatch = logs.reduce(
(matches, log) => matches || new RegExp(match).test(log),
false
)

if (!foundMatch) {
// This will never pass, but lets user see the issues
expect(logs).toBe(match)
return
}

// track an assertion that passes!
expect(match).toBe(match)
// ink will auto wrap things, so we need to get rid of any whitespace specific checks
// and let it just make sure there is whitespace
expect(output).toMatch(new RegExp(match.replace(/\s+/g, `\\s+`)))
},
},
}
Expand Down
8 changes: 4 additions & 4 deletions packages/gatsby-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,20 @@
"@babel/cli": "^7.12.1",
"@babel/core": "^7.12.3",
"@rollup/plugin-babel": "^5.1.0",
"@rollup/plugin-commonjs": "^14.0.0",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-replace": "^2.3.3",
"@types/hosted-git-info": "^3.0.1",
"@types/yargs": "^15.0.8",
"babel-preset-gatsby-package": "^0.10.0-next.0",
"cross-env": "^7.0.3",
"ink": "^2.7.1",
"ink-spinner": "^3.1.0",
"ink": "^3.0.8",
"ink-spinner": "^4.0.1",
"npm-run-all": "4.1.5",
"react": "^16.8.0",
"rimraf": "^3.0.2",
"rollup": "^2.23.0",
"rollup": "^2.34.2",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-internal": "^1.0.0",
"typescript": "^3.9.7"
Expand Down
40 changes: 15 additions & 25 deletions packages/gatsby-cli/src/reporter/loggers/ink/cli.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,30 +64,6 @@ class CLI extends React.Component<ICLIProps, ICLIState> {
)
}

/*
Only operation on messages array is to push new message into it. Once
message is there it can't change. Because of that we can do single
transform from message object to react element and store it.
This will avoid calling React.createElement completely for every message
that can't change.
*/
if (messages.length > this.memoizedReactElementsForMessages.length) {
for (
let index = this.memoizedReactElementsForMessages.length;
index < messages.length;
index++
) {
const msg = messages[index]
this.memoizedReactElementsForMessages.push(
msg.level === `ERROR` ? (
<ErrorComponent details={msg as IStructuredError} key={index} />
) : (
<Message key={index} {...(msg as IMessageProps)} />
)
)
}
}

const spinners: Array<IActivity> = []
const progressBars: Array<IActivity> = []
if (showProgress) {
Expand All @@ -108,7 +84,21 @@ class CLI extends React.Component<ICLIProps, ICLIState> {
return (
<Box flexDirection="column">
<Box flexDirection="column">
<Static>{this.memoizedReactElementsForMessages}</Static>
<Static items={messages}>
{(message): React.ReactElement =>
message.level === `ERROR` ? (
<ErrorComponent
details={message as IStructuredError}
key={messages.indexOf(message)}
/>
) : (
<Message
key={messages.indexOf(message)}
{...(message as IMessageProps)}
/>
)
}
</Static>

{spinners.map(activity => (
<Spinner key={activity.id} {...activity} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext, useState, useEffect } from "react"
import { Box, Color, StdoutContext } from "ink"
import { Box, Text, useStdout } from "ink"
import StoreStateContext from "../context"
import { ActivityStatuses } from "../../../constants"
import { createLabel } from "./utils"
Expand All @@ -24,7 +24,19 @@ const getLabel = (

// Track the width and height of the terminal. Responsive app design baby!
const useTerminalResize = (): Array<number> => {
const { stdout } = useContext(StdoutContext)
const { stdout } = useStdout()

// stdout type is nullable, so we need to handle case where it is undefined for type checking.
// In practice this shouldn't happen ever, because AFAIK type is only nullable
// because Ink's StdoutContext is initiated with `undefined`:
// https://github.com/vadimdemedes/ink/blob/83894963727cf40ccac2256ec346e5ff3381c918/src/components/StdoutContext.ts#L20-L23
// but ContextProvider requires stdout to be set:
// https://github.com/vadimdemedes/ink/blob/83894963727cf40ccac2256ec346e5ff3381c918/src/components/App.tsx#L18
// https://github.com/vadimdemedes/ink/blob/83894963727cf40ccac2256ec346e5ff3381c918/src/components/App.tsx#L79-L84
if (!stdout) {
return [0]
}

const [sizes, setSizes] = useState([stdout.columns, stdout.rows])
useEffect(() => {
const resizeListener = (): void => {
Expand Down Expand Up @@ -52,13 +64,15 @@ const Develop: React.FC<IDevelopProps> = ({ pagesCount, appName, status }) => {

return (
<Box flexDirection="column" marginTop={2}>
<Box textWrap={`truncate`}>{`—`.repeat(width)}</Box>
<Box>
<Text wrap="truncate">{`—`.repeat(width)}</Text>
</Box>
<Box height={1} flexDirection="row">
<StatusLabel />
<Box flexGrow={1} />
<Color>{appName}</Color>
<Text>{appName}</Text>
<Box flexGrow={1} />
<Color>{pagesCount} pages</Color>
<Text>{pagesCount} pages</Text>
</Box>
</Box>
)
Expand Down
20 changes: 11 additions & 9 deletions packages/gatsby-cli/src/reporter/loggers/ink/components/error.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FunctionComponent } from "react"
import path from "path"
import { Color, Box } from "ink"
import { Box, Text } from "ink"
import { IStructuredError } from "../../../../structured-errors/types"

interface IFileProps {
Expand All @@ -21,10 +21,10 @@ const File: FunctionComponent<IFileProps> = ({ filePath, location }) => {
}

return (
<Color blue>
<Text color="blue">
{path.relative(process.cwd(), filePath)}
{locString}
</Color>
</Text>
)
}

Expand All @@ -38,7 +38,7 @@ const DocsLink: FunctionComponent<IDocsLinkProps> = ({ docsUrl }) => {
if (docsUrl === `https://gatsby.dev/issue-how-to`) return null
return (
<Box marginTop={1}>
See our docs page for more info on this error: {docsUrl}
<Text>See our docs page for more info on this error: {docsUrl}</Text>
</Box>
)
}
Expand All @@ -56,17 +56,19 @@ export const Error: FunctionComponent<IErrorProps> = React.memo(
<Box flexDirection="column">
<Box>
<Box marginRight={1}>
<Color black bgRed>
<Text color="black" backgroundColor="red">
{` ${details.level} `}
{details.code ? `#${details.code} ` : ``}
</Color>
<Color red>{details.type ? ` ` + details.type : ``}</Color>
</Text>
<Text color="red">{details.type ? ` ` + details.type : ``}</Text>
</Box>
</Box>
<Box marginTop={1}>{details.text}</Box>
<Box marginTop={1}>
<Text>{details.text}</Text>
</Box>
{details.filePath && (
<Box marginTop={1}>
File:{` `}
<Text>File:{` `}</Text>
<File filePath={details.filePath} location={details.location} />
</Box>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react"
import { Box } from "ink"
import { Box, Text } from "ink"
import { createLabel } from "./utils"

import { ActivityLogLevels, LogLevels } from "../../../constants"
Expand Down Expand Up @@ -44,16 +44,18 @@ export const Message = React.memo<IMessageProps>(
message += ` - ${statusText}`
}
if (!level || level === `LOG`) {
return <>{message}</>
return <Text>{message}</Text>
}

const TextLabel = getLabel(level)

return (
<Box textWrap="wrap" flexDirection="row">
<TextLabel />
{` `}
{message}
<Box flexDirection="row">
<Text wrap="wrap">
<TextLabel />
{` `}
{message}
</Text>
</Box>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react"
import { Box } from "ink"
import { Box, Text } from "ink"
import { calcElapsedTime } from "../../../../util/calc-elapsed-time"

const maxWidth = 30
Expand Down Expand Up @@ -38,18 +38,26 @@ export function ProgressBar({
return (
<Box flexDirection="row">
<Box marginRight={3} width={progressBarWidth}>
[
<Text>[</Text>
<Box width={progressBarWidth - 2}>
{`=`.repeat(((progressBarWidth - 2) * percentage) / 100)}
<Text>{`=`.repeat(((progressBarWidth - 2) * percentage) / 100)}</Text>
</Box>
]
<Text>]</Text>
</Box>
<Box marginRight={1}>{calcElapsedTime(startTime)} s</Box>
<Box marginRight={1}>
{current}/{total}
<Text>{calcElapsedTime(startTime)} s</Text>
</Box>
<Box marginRight={1}>
<Text>
{current}/{total}
</Text>
</Box>
<Box marginRight={1}>
<Text>{`` + percentage}%</Text>
</Box>
<Box>
<Text wrap="truncate">{message}</Text>
</Box>
<Box marginRight={1}>{`` + percentage}%</Box>
<Box textWrap="truncate">{message}</Box>
</Box>
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react"
import { Box } from "ink"
import { Box, Text } from "ink"
import InkSpinner from "ink-spinner"

interface ISpinnerProps {
Expand All @@ -14,7 +14,9 @@ export function Spinner({ text, statusText }: ISpinnerProps): JSX.Element {

return (
<Box>
<InkSpinner type="dots" /> {label}
<Text>
<InkSpinner type="dots" /> {label}
</Text>
</Box>
)
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import React, { FunctionComponent } from "react"
import { Color, ColorProps } from "ink"

export const ColorSwitcher: FunctionComponent<ColorProps> = ({
children,
...props
}) => <Color {...props}>{children}</Color>
import { Text, TextProps } from "ink"

export const createLabel = (
text: string,
color: string
): FunctionComponent<ColorProps> => (...props): JSX.Element => (
<ColorSwitcher {...{ [color]: true, ...props }}>{text}</ColorSwitcher>
): FunctionComponent<TextProps> => (...props): JSX.Element => (
<Text color={color} {...props}>
{text}
</Text>
)
4 changes: 2 additions & 2 deletions packages/gatsby-cli/src/reporter/loggers/ink/context.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, createContext } from "react"
import React, { useState, useLayoutEffect, createContext } from "react"
import { getStore, onLogAction } from "../../redux"
import { IGatsbyState } from "gatsby/src/redux/types"

Expand All @@ -17,7 +17,7 @@ export const StoreStateProvider: React.FC = ({
(getStore().getState() as any) as IGatsbyState
)

useEffect(
useLayoutEffect(
() =>
onLogAction(() => {
setState((getStore().getState() as any) as IGatsbyState)
Expand Down

0 comments on commit 1e702ae

Please sign in to comment.