diff options
Diffstat (limited to 'packages/create-astro/src')
19 files changed, 430 insertions, 384 deletions
diff --git a/packages/create-astro/src/components/App.tsx b/packages/create-astro/src/components/App.tsx index fd9192bb6..deb9b252a 100644 --- a/packages/create-astro/src/components/App.tsx +++ b/packages/create-astro/src/components/App.tsx @@ -1,4 +1,4 @@ -import React, {FC, useEffect} from 'react'; +import React, { FC, useEffect } from 'react'; import { prepareTemplate, isEmpty, emptyDir } from '../utils'; import Header from './Header'; import Install from './Install'; @@ -8,86 +8,91 @@ import Confirm from './Confirm'; import Finalize from './Finalize'; interface Context { - use: 'npm'|'yarn'; - run: boolean; - projectExists?: boolean; - force?: boolean; - projectName?: string; - template?: string; - templates: string[]; - ready?: boolean; + use: 'npm' | 'yarn'; + run: boolean; + projectExists?: boolean; + force?: boolean; + projectName?: string; + template?: string; + templates: string[]; + ready?: boolean; } const getStep = ({ projectName, projectExists: exists, template, force, ready }: Context) => { - switch (true) { - case !projectName: return { - key: 'projectName', - Component: ProjectName - }; - case projectName && exists === true && typeof force === 'undefined': return { - key: 'force', - Component: Confirm - } - case (exists === false || force) && !template: return { - key: 'template', - Component: Template - }; - case !ready: return { - key: 'install', - Component: Install - }; - default: return { - key: 'final', - Component: Finalize - } - } -} + switch (true) { + case !projectName: + return { + key: 'projectName', + Component: ProjectName, + }; + case projectName && exists === true && typeof force === 'undefined': + return { + key: 'force', + Component: Confirm, + }; + case (exists === false || force) && !template: + return { + key: 'template', + Component: Template, + }; + case !ready: + return { + key: 'install', + Component: Install, + }; + default: + return { + key: 'final', + Component: Finalize, + }; + } +}; const App: FC<{ context: Context }> = ({ context }) => { - const [state, setState] = React.useState(context); - const step = React.useRef(getStep(context)); - const onSubmit = (value: string|boolean) => { - const { key } = step.current; - const newState = { ...state, [key]: value }; - step.current = getStep(newState) - setState(newState) - } + const [state, setState] = React.useState(context); + const step = React.useRef(getStep(context)); + const onSubmit = (value: string | boolean) => { + const { key } = step.current; + const newState = { ...state, [key]: value }; + step.current = getStep(newState); + setState(newState); + }; - useEffect(() => { - let isSubscribed = true - if (state.projectName && typeof state.projectExists === 'undefined') { - const newState = { ...state, projectExists: !isEmpty(state.projectName) }; - step.current = getStep(newState) - if (isSubscribed) { - setState(newState); - } - } + useEffect(() => { + let isSubscribed = true; + if (state.projectName && typeof state.projectExists === 'undefined') { + const newState = { ...state, projectExists: !isEmpty(state.projectName) }; + step.current = getStep(newState); + if (isSubscribed) { + setState(newState); + } + } - if (state.projectName && (state.projectExists === false || state.force) && state.template) { - if (state.force) emptyDir(state.projectName); - prepareTemplate(context.use, state.template, state.projectName).then(() => { - if (isSubscribed) { - setState(v => { - const newState = {...v, ready: true }; - step.current = getStep(newState); - return newState; - }); - } - }); - } + if (state.projectName && (state.projectExists === false || state.force) && state.template) { + if (state.force) emptyDir(state.projectName); + prepareTemplate(context.use, state.template, state.projectName).then(() => { + if (isSubscribed) { + setState((v) => { + const newState = { ...v, ready: true }; + step.current = getStep(newState); + return newState; + }); + } + }); + } - return () => { - isSubscribed = false; - } - }, [state]); - const { Component } = step.current; + return () => { + isSubscribed = false; + }; + }, [state]); + const { Component } = step.current; - return ( - <> - <Header context={state}/> - <Component context={state} onSubmit={onSubmit} /> - </> - ) + return ( + <> + <Header context={state} /> + <Component context={state} onSubmit={onSubmit} /> + </> + ); }; export default App; diff --git a/packages/create-astro/src/components/Confirm.tsx b/packages/create-astro/src/components/Confirm.tsx index 1fd1aa862..84d83ed8f 100644 --- a/packages/create-astro/src/components/Confirm.tsx +++ b/packages/create-astro/src/components/Confirm.tsx @@ -31,7 +31,7 @@ const Confirm: FC<{ message?: any; context: any; onSubmit: (value: boolean) => v items={[ { value: false, - label: 'no' + label: 'no', }, { value: true, diff --git a/packages/create-astro/src/components/Emoji.tsx b/packages/create-astro/src/components/Emoji.tsx index 3af9ae508..4a294f5db 100644 --- a/packages/create-astro/src/components/Emoji.tsx +++ b/packages/create-astro/src/components/Emoji.tsx @@ -2,4 +2,4 @@ import React from 'react'; import { Text } from 'ink'; import { isWin } from '../utils'; -export default ({ children }) => isWin() ? null : <Text>{children}</Text> +export default ({ children }) => (isWin() ? null : <Text>{children}</Text>); diff --git a/packages/create-astro/src/components/Exit.tsx b/packages/create-astro/src/components/Exit.tsx index cc3096705..b108fb36f 100644 --- a/packages/create-astro/src/components/Exit.tsx +++ b/packages/create-astro/src/components/Exit.tsx @@ -2,8 +2,11 @@ import React, { FC } from 'react'; import { Box, Text } from 'ink'; import { isDone } from '../utils'; -const Exit: FC<{ didError?: boolean }> = ({ didError }) => isDone ? null : <Box marginTop={1} display="flex"> - <Text color={didError ? "#FF1639" : "#FFBE2D"}>[abort]</Text> - <Text> astro cancelled</Text> -</Box> +const Exit: FC<{ didError?: boolean }> = ({ didError }) => + isDone ? null : ( + <Box marginTop={1} display="flex"> + <Text color={didError ? '#FF1639' : '#FFBE2D'}>[abort]</Text> + <Text> astro cancelled</Text> + </Box> + ); export default Exit; diff --git a/packages/create-astro/src/components/Finalize.tsx b/packages/create-astro/src/components/Finalize.tsx index 8d2a2103a..933a8844e 100644 --- a/packages/create-astro/src/components/Finalize.tsx +++ b/packages/create-astro/src/components/Finalize.tsx @@ -7,21 +7,26 @@ const Finalize: FC<{ context: any }> = ({ context: { use, projectName } }) => { cancelProcessListeners(); process.exit(0); }, []); - - return <> + + return ( + <> <Box display="flex"> <Text color="#17C083">{'[ yes ]'}</Text> - <Text> Project initialized at <Text color="#3894FF">./{projectName}</Text></Text> + <Text> + {' '} + Project initialized at <Text color="#3894FF">./{projectName}</Text> + </Text> </Box> <Box display="flex" marginY={1}> <Text dimColor>{'[ tip ]'}</Text> <Box display="flex" marginLeft={1} flexDirection="column"> - <Text>Get started by running</Text> - <Text color="#3894FF">cd ./{projectName}</Text> - <Text color="#3894FF">{use} start</Text> + <Text>Get started by running</Text> + <Text color="#3894FF">cd ./{projectName}</Text> + <Text color="#3894FF">{use} start</Text> </Box> </Box> - </>; + </> + ); }; export default Finalize; diff --git a/packages/create-astro/src/components/Header.tsx b/packages/create-astro/src/components/Header.tsx index 1d894a60e..0684d1b3c 100644 --- a/packages/create-astro/src/components/Header.tsx +++ b/packages/create-astro/src/components/Header.tsx @@ -2,19 +2,27 @@ import React from 'react'; import { Box, Text } from 'ink'; const getMessage = ({ projectName, template }) => { - switch (true) { - case !projectName: return <Text dimColor>Gathering mission details</Text>; - case !template: return <Text dimColor>Optimizing navigational system</Text>; - default: return <Text color="black" backgroundColor="white"> {projectName} </Text> - } -} + switch (true) { + case !projectName: + return <Text dimColor>Gathering mission details</Text>; + case !template: + return <Text dimColor>Optimizing navigational system</Text>; + default: + return ( + <Text color="black" backgroundColor="white"> + {' '} + {projectName}{' '} + </Text> + ); + } +}; const Header: React.FC<{ context: any }> = ({ context }) => ( - <Box width={48} display="flex" marginY={1}> - <Text backgroundColor="#882DE7" color="white">{' astro '}</Text> - <Box marginLeft={1}> - {getMessage(context)} - </Box> - </Box> -) + <Box width={48} display="flex" marginY={1}> + <Text backgroundColor="#882DE7" color="white"> + {' astro '} + </Text> + <Box marginLeft={1}>{getMessage(context)}</Box> + </Box> +); export default Header; diff --git a/packages/create-astro/src/components/Help.tsx b/packages/create-astro/src/components/Help.tsx index 88fcf5633..5991664f1 100644 --- a/packages/create-astro/src/components/Help.tsx +++ b/packages/create-astro/src/components/Help.tsx @@ -2,61 +2,79 @@ import React, { FC } from 'react'; import { Box, Text } from 'ink'; import { ARGS, ARG } from '../config'; -const Type: FC<{ type: any, enum?: string[] }> = ({ type, enum: e }) => { - if (type === Boolean) { - return <> - <Text color="#3894FF">true</Text> - <Text dimColor>|</Text> - <Text color="#3894FF">false</Text> - </> - } - if (e?.length > 0) { - return <> - {e.map((item, i, { length: len}) => { - if (i !== len - 1) { - return <Box key={item}> - <Text color="#17C083">{item}</Text> - <Text dimColor>|</Text> - </Box> - } - - return <Text color="#17C083" key={item}>{item}</Text> - })} - </> - } - - return <Text color="#3894FF">string</Text>; -} - -const Command: FC<{ name: string, info: ARG }> = ({ name, info: { alias, description, type, enum: e } }) => { +const Type: FC<{ type: any; enum?: string[] }> = ({ type, enum: e }) => { + if (type === Boolean) { return ( - <Box display="flex" alignItems="flex-start"> - <Box width={24} display="flex" flexGrow={0}> - <Text color="whiteBright">--{name}</Text>{alias && <Text dimColor> -{alias}</Text>} - </Box> - <Box width={24}> - <Type type={type} enum={e} /> - </Box> - <Box> - <Text>{description}</Text> - </Box> - </Box> + <> + <Text color="#3894FF">true</Text> + <Text dimColor>|</Text> + <Text color="#3894FF">false</Text> + </> ); -} - -const Help: FC<{ context: any }> = ({ context: { templates }}) => { + } + if (e?.length > 0) { return ( - <> - <Box width={48} display="flex" marginY={1}> - <Text backgroundColor="#882DE7" color="white">{' astro '}</Text> - <Box marginLeft={1}> - <Text color="black" backgroundColor="white"> help </Text> - </Box> - </Box> - <Box marginBottom={1} marginLeft={2} display="flex" flexDirection="column"> - {Object.entries(ARGS).map(([name, info]) => <Command key={name} name={name} info={name === 'template' ? { ...info, enum: templates.map(({ value }) => value) } : info} /> )} - </Box> - </> - ) + <> + {e.map((item, i, { length: len }) => { + if (i !== len - 1) { + return ( + <Box key={item}> + <Text color="#17C083">{item}</Text> + <Text dimColor>|</Text> + </Box> + ); + } + + return ( + <Text color="#17C083" key={item}> + {item} + </Text> + ); + })} + </> + ); + } + + return <Text color="#3894FF">string</Text>; +}; + +const Command: FC<{ name: string; info: ARG }> = ({ name, info: { alias, description, type, enum: e } }) => { + return ( + <Box display="flex" alignItems="flex-start"> + <Box width={24} display="flex" flexGrow={0}> + <Text color="whiteBright">--{name}</Text> + {alias && <Text dimColor> -{alias}</Text>} + </Box> + <Box width={24}> + <Type type={type} enum={e} /> + </Box> + <Box> + <Text>{description}</Text> + </Box> + </Box> + ); +}; + +const Help: FC<{ context: any }> = ({ context: { templates } }) => { + return ( + <> + <Box width={48} display="flex" marginY={1}> + <Text backgroundColor="#882DE7" color="white"> + {' astro '} + </Text> + <Box marginLeft={1}> + <Text color="black" backgroundColor="white"> + {' '} + help{' '} + </Text> + </Box> + </Box> + <Box marginBottom={1} marginLeft={2} display="flex" flexDirection="column"> + {Object.entries(ARGS).map(([name, info]) => ( + <Command key={name} name={name} info={name === 'template' ? { ...info, enum: templates.map(({ value }) => value) } : info} /> + ))} + </Box> + </> + ); }; export default Help; diff --git a/packages/create-astro/src/components/Install.tsx b/packages/create-astro/src/components/Install.tsx index d9d2bc9b6..776c0cc34 100644 --- a/packages/create-astro/src/components/Install.tsx +++ b/packages/create-astro/src/components/Install.tsx @@ -4,16 +4,20 @@ import Spacer from './Spacer'; import Spinner from './Spinner'; const Install: FC<{ context: any }> = ({ context: { use } }) => { - return <> + return ( + <> <Box display="flex"> - <Spinner/> + <Spinner /> <Text> Initiating launch sequence...</Text> </Box> <Box> <Spacer /> - <Text color="white" dimColor>(aka running <Text color="#17C083">{use === 'npm' ? 'npm install' : 'yarn'}</Text>)</Text> + <Text color="white" dimColor> + (aka running <Text color="#17C083">{use === 'npm' ? 'npm install' : 'yarn'}</Text>) + </Text> </Box> - </>; + </> + ); }; export default Install; diff --git a/packages/create-astro/src/components/ProjectName.tsx b/packages/create-astro/src/components/ProjectName.tsx index 87b976494..d09a33d82 100644 --- a/packages/create-astro/src/components/ProjectName.tsx +++ b/packages/create-astro/src/components/ProjectName.tsx @@ -8,8 +8,9 @@ const { default: Input } = TextInput; const ProjectName: FC<{ onSubmit: (value: string) => void }> = ({ onSubmit }) => { const [value, setValue] = React.useState(''); const handleSubmit = (v: string) => onSubmit(v); - - return <> + + return ( + <> <Box display="flex"> <Text color="#17C083">{'[query]'}</Text> <Text> What is your project name?</Text> @@ -18,7 +19,8 @@ const ProjectName: FC<{ onSubmit: (value: string) => void }> = ({ onSubmit }) => <Spacer /> <Input value={value} onChange={setValue} onSubmit={handleSubmit} placeholder="my-project" /> </Box> - </>; + </> + ); }; export default ProjectName; diff --git a/packages/create-astro/src/components/Select.tsx b/packages/create-astro/src/components/Select.tsx index acf8eb29f..08d588f4f 100644 --- a/packages/create-astro/src/components/Select.tsx +++ b/packages/create-astro/src/components/Select.tsx @@ -5,28 +5,28 @@ import { Text, Box } from 'ink'; const { default: Select } = SelectInput; interface Props { - isSelected?: boolean; - label: string; - description?: string; + isSelected?: boolean; + label: string; + description?: string; } -const Indicator: FC<Props> = ({ isSelected }) => isSelected ? <Text color="#3894FF">[ </Text> : <Text> </Text> -const Item: FC<Props> = ({isSelected = false, label, description }) => ( - <Box display="flex"> - <Text color={isSelected ? '#3894FF' : 'white'} dimColor={!isSelected}>{label}</Text> - {isSelected && description && typeof description === 'string' && <Text> {description}</Text>} - {isSelected && description && typeof description !== 'string' && <Box marginLeft={1}>{description}</Box>} - </Box> +const Indicator: FC<Props> = ({ isSelected }) => (isSelected ? <Text color="#3894FF">[ </Text> : <Text> </Text>); +const Item: FC<Props> = ({ isSelected = false, label, description }) => ( + <Box display="flex"> + <Text color={isSelected ? '#3894FF' : 'white'} dimColor={!isSelected}> + {label} + </Text> + {isSelected && description && typeof description === 'string' && <Text> {description}</Text>} + {isSelected && description && typeof description !== 'string' && <Box marginLeft={1}>{description}</Box>} + </Box> ); interface SelectProps { - items: { value: string|number|boolean, label: string, description?: any }[] - onSelect(value: string|number|boolean): void; + items: { value: string | number | boolean; label: string; description?: any }[]; + onSelect(value: string | number | boolean): void; } const CustomSelect: FC<SelectProps> = ({ items, onSelect }) => { - const handleSelect = ({ value }) => onSelect(value); - return ( - <Select indicatorComponent={Indicator} itemComponent={Item} items={items} onSelect={handleSelect} /> - ) -} + const handleSelect = ({ value }) => onSelect(value); + return <Select indicatorComponent={Indicator} itemComponent={Item} items={items} onSelect={handleSelect} />; +}; export default CustomSelect; diff --git a/packages/create-astro/src/components/Spacer.tsx b/packages/create-astro/src/components/Spacer.tsx index 1e4e14561..15ef71d7c 100644 --- a/packages/create-astro/src/components/Spacer.tsx +++ b/packages/create-astro/src/components/Spacer.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react'; import { Box } from 'ink'; -const Spacer: FC<{ width?: number }> = ({ width = 8 }) => <Box width={width} /> +const Spacer: FC<{ width?: number }> = ({ width = 8 }) => <Box width={width} />; export default Spacer; diff --git a/packages/create-astro/src/components/Spinner.tsx b/packages/create-astro/src/components/Spinner.tsx index 2d3335e1c..fa62b614f 100644 --- a/packages/create-astro/src/components/Spinner.tsx +++ b/packages/create-astro/src/components/Spinner.tsx @@ -6,14 +6,14 @@ const Spinner: FC<{ type?: keyof typeof spinners }> = ({ type = 'countdown' }) = const [i, setI] = useState(0); useEffect(() => { const _ = setInterval(() => { - setI(v => (v < frames.length - 1) ? v + 1 : 0) - }, interval) + setI((v) => (v < frames.length - 1 ? v + 1 : 0)); + }, interval); return () => clearInterval(_); - }, []) + }, []); - return frames[i] -} + return frames[i]; +}; const spinners = { countdown: { @@ -35,73 +35,73 @@ const spinners = { <Text backgroundColor="#882DE7">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> <Text backgroundColor="#882DE7">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#6858F1"> </Text> <Text backgroundColor="#882DE7">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#6858F1"> </Text> <Text backgroundColor="#882DE7">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#6858F1"> </Text> <Text backgroundColor="#882DE7">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#6858F1"> </Text> <Text backgroundColor="#882DE7">{' '}</Text> </Box>, - <Box display="flex"> - <Text backgroundColor="#17C083">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#882DE7">{' '}</Text> + <Box display="flex"> + <Text backgroundColor="#17C083"> </Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#882DE7"> </Text> </Box>, - <Box display="flex"> + <Box display="flex"> <Text backgroundColor="#17C083">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#6858F1"> </Text> </Box>, - <Box display="flex"> + <Box display="flex"> <Text backgroundColor="#17C083">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#5076F9"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#17C083">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#3894FF"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#17C083">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#17C083">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#17C083">{' '}</Text> @@ -122,79 +122,79 @@ const spinners = { <Text backgroundColor="#17C083">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#23B1AF"> </Text> <Text backgroundColor="#17C083">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#23B1AF"> </Text> <Text backgroundColor="#17C083">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#23B1AF"> </Text> <Text backgroundColor="#17C083">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#23B1AF"> </Text> <Text backgroundColor="#17C083">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#23B1AF"> </Text> <Text backgroundColor="#17C083">{' '}</Text> </Box>, <Box display="flex"> - <Text backgroundColor="#882DE7">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> - <Text backgroundColor="#17C083">{' '}</Text> + <Text backgroundColor="#882DE7"> </Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#23B1AF"> </Text> + <Text backgroundColor="#17C083"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#882DE7">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> - <Text backgroundColor="#23B1AF">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> + <Text backgroundColor="#23B1AF"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#882DE7">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> - <Text backgroundColor="#2CA5D2">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#3894FF"> </Text> + <Text backgroundColor="#2CA5D2"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#882DE7">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> - <Text backgroundColor="#3894FF">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#5076F9"> </Text> + <Text backgroundColor="#3894FF"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#882DE7">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> - <Text backgroundColor="#5076F9">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> + <Text backgroundColor="#5076F9"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#882DE7">{' '}</Text> - <Text backgroundColor="#6858F1">{' '}</Text> + <Text backgroundColor="#6858F1"> </Text> </Box>, <Box display="flex"> <Text backgroundColor="#882DE7">{' '}</Text> </Box>, - ] - } -} + ], + }, +}; export default Spinner; diff --git a/packages/create-astro/src/components/Template.tsx b/packages/create-astro/src/components/Template.tsx index 7fbab035d..23ff905f2 100644 --- a/packages/create-astro/src/components/Template.tsx +++ b/packages/create-astro/src/components/Template.tsx @@ -3,7 +3,7 @@ import { Box, Text } from 'ink'; import Spacer from './Spacer'; import Select from './Select'; -const Template: FC<{ context: any, onSubmit: (value: string) => void }> = ({ context: { templates }, onSubmit }) => { +const Template: FC<{ context: any; onSubmit: (value: string) => void }> = ({ context: { templates }, onSubmit }) => { const items = templates.map(({ title: label, ...rest }) => ({ ...rest, label })); return ( diff --git a/packages/create-astro/src/config.ts b/packages/create-astro/src/config.ts index 3d3c07912..8216fd1ab 100644 --- a/packages/create-astro/src/config.ts +++ b/packages/create-astro/src/config.ts @@ -1,49 +1,49 @@ import type * as arg from 'arg'; export interface ARG { - type: any; - description: string; - enum?: string[]; - alias?: string; + type: any; + description: string; + enum?: string[]; + alias?: string; } export const ARGS: Record<string, ARG> = { - 'template': { - type: String, - description: 'specifies template to use' - }, - 'use': { - type: String, - enum: ['npm', 'yarn'], - description: 'specifies package manager to use' - }, - 'run': { - type: Boolean, - description: 'should dependencies be installed automatically?' - }, - 'force': { - type: Boolean, - alias: 'f', - description: 'should existing files be overwritten?' - }, - 'version': { - type: Boolean, - alias: 'v', - description: 'prints current version' - }, - 'help': { - type: Boolean, - alias: 'h', - description: 'prints this message' - } -} + template: { + type: String, + description: 'specifies template to use', + }, + use: { + type: String, + enum: ['npm', 'yarn'], + description: 'specifies package manager to use', + }, + run: { + type: Boolean, + description: 'should dependencies be installed automatically?', + }, + force: { + type: Boolean, + alias: 'f', + description: 'should existing files be overwritten?', + }, + version: { + type: Boolean, + alias: 'v', + description: 'prints current version', + }, + help: { + type: Boolean, + alias: 'h', + description: 'prints this message', + }, +}; export const args = Object.entries(ARGS).reduce((acc, [name, info]) => { - const key = `--${name}`; - const spec = { ...acc, [key]: info.type }; + const key = `--${name}`; + const spec = { ...acc, [key]: info.type }; - if (info.alias) { - spec[`-${info.alias}`] = key; - } - return spec + if (info.alias) { + spec[`-${info.alias}`] = key; + } + return spec; }, {} as arg.Spec); diff --git a/packages/create-astro/src/index.tsx b/packages/create-astro/src/index.tsx index 0927eaae9..9a510d7b7 100644 --- a/packages/create-astro/src/index.tsx +++ b/packages/create-astro/src/index.tsx @@ -3,7 +3,7 @@ import React from 'react'; import App from './components/App'; import Version from './components/Version'; import Exit from './components/Exit'; -import {render} from 'ink'; +import { render } from 'ink'; import { getTemplates, addProcessListeners } from './utils'; import { args as argsConfig } from './config'; import arg from 'arg'; @@ -11,36 +11,36 @@ import Help from './components/Help'; /** main `create-astro` CLI */ export default async function createAstro() { - const args = arg(argsConfig); - const projectName = args._[0]; - if (args['--version']) { - return render(<Version />); - } - const templates = await getTemplates(); - if (args['--help']) { - return render(<Help context={{ templates }} />) - } + const args = arg(argsConfig); + const projectName = args._[0]; + if (args['--version']) { + return render(<Version />); + } + const templates = await getTemplates(); + if (args['--help']) { + return render(<Help context={{ templates }} />); + } - const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm'; - const use = (args['--use'] ?? pkgManager) as 'npm'|'yarn'; - const template = args['--template']; - const force = args['--force']; - const run = args['--run'] ?? true; - - const app = render(<App context={{ projectName, template, templates, force, run, use }} />); + const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm'; + const use = (args['--use'] ?? pkgManager) as 'npm' | 'yarn'; + const template = args['--template']; + const force = args['--force']; + const run = args['--run'] ?? true; - const onError = () => { - if (app) app.clear(); - render(<Exit didError />); - } - const onExit = () => { - if (app) app.clear(); - render(<Exit />); - } - addProcessListeners([ - ['uncaughtException', onError], - ['exit', onExit], - ['SIGINT', onExit], - ['SIGTERM', onExit], - ]) + const app = render(<App context={{ projectName, template, templates, force, run, use }} />); + + const onError = () => { + if (app) app.clear(); + render(<Exit didError />); + }; + const onExit = () => { + if (app) app.clear(); + render(<Exit />); + }; + addProcessListeners([ + ['uncaughtException', onError], + ['exit', onExit], + ['SIGINT', onExit], + ['SIGTERM', onExit], + ]); } diff --git a/packages/create-astro/src/templates/blank/meta.json b/packages/create-astro/src/templates/blank/meta.json index ca942e99f..41a259d53 100644 --- a/packages/create-astro/src/templates/blank/meta.json +++ b/packages/create-astro/src/templates/blank/meta.json @@ -1,4 +1,4 @@ { - "title": "Blank", - "description": "a bare-bones, ultra-minimal template" + "title": "Blank", + "description": "a bare-bones, ultra-minimal template" } diff --git a/packages/create-astro/src/templates/starter/README.md b/packages/create-astro/src/templates/starter/README.md index 59940918f..70ff237f6 100644 --- a/packages/create-astro/src/templates/starter/README.md +++ b/packages/create-astro/src/templates/starter/README.md @@ -20,10 +20,8 @@ Inside of your Astro project, you'll see the following folders and files: ``` Astro looks for `.astro` or `.md.astro` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. - There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. - Any static assets, like images, can be placed in the `public/` directory. diff --git a/packages/create-astro/src/templates/starter/meta.json b/packages/create-astro/src/templates/starter/meta.json index ba775af32..e9f3778c7 100644 --- a/packages/create-astro/src/templates/starter/meta.json +++ b/packages/create-astro/src/templates/starter/meta.json @@ -1,5 +1,5 @@ { - "title": "Getting Started", - "description": "a friendly starting point for new astronauts", - "rank": 999 + "title": "Getting Started", + "description": "a friendly starting point for new astronauts", + "rank": 999 } diff --git a/packages/create-astro/src/utils.ts b/packages/create-astro/src/utils.ts index 790a64cf9..52e56f5f0 100644 --- a/packages/create-astro/src/utils.ts +++ b/packages/create-astro/src/utils.ts @@ -6,8 +6,8 @@ import decompress from 'decompress'; const listeners = new Map(); -export async function addProcessListeners(handlers: [NodeJS.Signals|string, NodeJS.SignalsListener][]) { - for (const [event,handler] of handlers) { +export async function addProcessListeners(handlers: [NodeJS.Signals | string, NodeJS.SignalsListener][]) { + for (const [event, handler] of handlers) { listeners.set(event, handler); process.once(event as NodeJS.Signals, handler); } @@ -21,18 +21,20 @@ export async function cancelProcessListeners() { } export async function getTemplates() { - const templatesRoot = fileURLToPath(new URL('./templates', import.meta.url)); - const templateFiles = await fs.readdir(templatesRoot, 'utf8'); - const templates = templateFiles.filter(t => t.endsWith('.tgz')); - const metafile = templateFiles.find(t => t.endsWith('meta.json')); + const templatesRoot = fileURLToPath(new URL('./templates', import.meta.url)); + const templateFiles = await fs.readdir(templatesRoot, 'utf8'); + const templates = templateFiles.filter((t) => t.endsWith('.tgz')); + const metafile = templateFiles.find((t) => t.endsWith('meta.json')); - const meta = await fs.readFile(resolve(templatesRoot, metafile)).then(r => JSON.parse(r.toString())); + const meta = await fs.readFile(resolve(templatesRoot, metafile)).then((r) => JSON.parse(r.toString())); - return templates.map(template => { + return templates + .map((template) => { const value = basename(template, '.tgz'); if (meta[value]) return { ...meta[value], value }; return { value }; - }).sort((a, b) => { + }) + .sort((a, b) => { const aRank = a.rank ?? 0; const bRank = b.rank ?? 0; if (aRank > bRank) return -1; @@ -49,28 +51,29 @@ export async function rewriteFiles(projectName: string) { const tasks = []; tasks.push(fs.rename(resolve(dest, '_gitignore'), resolve(dest, '.gitignore'))); tasks.push( - fs.readFile(resolve(dest, 'package.json')) - .then(res => JSON.parse(res.toString())) - .then(json => JSON.stringify({ ...json, name: getValidPackageName(projectName) }, null, 2)) - .then(res => fs.writeFile(resolve(dest, 'package.json'), res)) + fs + .readFile(resolve(dest, 'package.json')) + .then((res) => JSON.parse(res.toString())) + .then((json) => JSON.stringify({ ...json, name: getValidPackageName(projectName) }, null, 2)) + .then((res) => fs.writeFile(resolve(dest, 'package.json'), res)) ); return Promise.all(tasks); } -export async function prepareTemplate(use: 'npm'|'yarn', name: string, dest: string) { - const projectName = dest; - dest = resolve(dest); - const template = fileURLToPath(new URL(`./templates/${name}.tgz`, import.meta.url)); - await decompress(template, dest); - await rewriteFiles(projectName); - try { - await run(use, use === 'npm' ? 'i' : null, dest); - } catch (e) { - cleanup(true); - } - isDone = true; - return; +export async function prepareTemplate(use: 'npm' | 'yarn', name: string, dest: string) { + const projectName = dest; + dest = resolve(dest); + const template = fileURLToPath(new URL(`./templates/${name}.tgz`, import.meta.url)); + await decompress(template, dest); + await rewriteFiles(projectName); + try { + await run(use, use === 'npm' ? 'i' : null, dest); + } catch (e) { + cleanup(true); + } + isDone = true; + return; } export function cleanup(didError = false) { @@ -81,10 +84,10 @@ export function cleanup(didError = false) { } export function killChildren() { - childrenProcesses.forEach(p => p.kill('SIGINT')); + childrenProcesses.forEach((p) => p.kill('SIGINT')); } -export function run(pkgManager: 'npm'|'yarn', command: string, projectPath: string, stdio: any = 'ignore'): Promise<void> { +export function run(pkgManager: 'npm' | 'yarn', command: string, projectPath: string, stdio: any = 'ignore'): Promise<void> { return new Promise((resolve, reject) => { const p = spawn(pkgManager, command ? [command] : [], { shell: true, @@ -102,40 +105,40 @@ export function isWin() { } export function isEmpty(path) { - try { - const files = readdirSync(resolve(path)); - if (files.length > 0) { - return false; - } else { - return true; - } - } catch (err) { - if (err.code !== 'ENOENT') throw err; + try { + const files = readdirSync(resolve(path)); + if (files.length > 0) { + return false; + } else { + return true; } - return true; + } catch (err) { + if (err.code !== 'ENOENT') throw err; + } + return true; } export function emptyDir(dir) { dir = resolve(dir); if (!existsSync(dir)) { - return + return; } for (const file of readdirSync(dir)) { - const abs = resolve(dir, file) + const abs = resolve(dir, file); if (lstatSync(abs).isDirectory()) { - emptyDir(abs) - rmdirSync(abs) + emptyDir(abs); + rmdirSync(abs); } else { - unlinkSync(abs) + unlinkSync(abs); } } } export function getValidPackageName(projectName: string) { - const packageNameRegExp = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/ + const packageNameRegExp = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/; if (packageNameRegExp.test(projectName)) { - return projectName + return projectName; } return projectName |