diff --git a/.changeset/new-hats-deliver.md b/.changeset/new-hats-deliver.md new file mode 100644 index 000000000..061ab79ba --- /dev/null +++ b/.changeset/new-hats-deliver.md @@ -0,0 +1,5 @@ +--- +"create-astro": patch +--- + +Rename the `--run` option to `--skip-install` for clarity. diff --git a/packages/create-astro/package.json b/packages/create-astro/package.json index 25b3c4899..659bd66a5 100644 --- a/packages/create-astro/package.json +++ b/packages/create-astro/package.json @@ -18,6 +18,7 @@ "create-astro.js" ], "dependencies": { + "decamelize": "^5.0.0", "decompress": "^4.2.1", "ink": "^3.0.8", "ink-select-input": "^4.2.0", diff --git a/packages/create-astro/src/components/App.tsx b/packages/create-astro/src/components/App.tsx index deb9b252a..4cf9f3852 100644 --- a/packages/create-astro/src/components/App.tsx +++ b/packages/create-astro/src/components/App.tsx @@ -9,7 +9,7 @@ import Finalize from './Finalize'; interface Context { use: 'npm' | 'yarn'; - run: boolean; + skipInstall?: boolean; projectExists?: boolean; force?: boolean; projectName?: string; @@ -18,7 +18,7 @@ interface Context { ready?: boolean; } -const getStep = ({ projectName, projectExists: exists, template, force, ready }: Context) => { +const getStep = ({ projectName, projectExists: exists, template, force, ready, skipInstall }: Context) => { switch (true) { case !projectName: return { @@ -35,16 +35,21 @@ const getStep = ({ projectName, projectExists: exists, template, force, ready }: key: 'template', Component: Template, }; - case !ready: + case !ready && !skipInstall: return { key: 'install', Component: Install, }; - default: + case ready: return { key: 'final', Component: Finalize, }; + default: + return { + key: 'empty', + Component: () => <>, + }; } }; @@ -70,7 +75,12 @@ const App: FC<{ context: Context }> = ({ context }) => { if (state.projectName && (state.projectExists === false || state.force) && state.template) { if (state.force) emptyDir(state.projectName); - prepareTemplate(context.use, state.template, state.projectName).then(() => { + prepareTemplate({ + use: context.use, + templateName: state.template, + projectName: state.projectName, + skipInstall: state.skipInstall, + }).then(() => { if (isSubscribed) { setState((v) => { const newState = { ...v, ready: true }; diff --git a/packages/create-astro/src/components/Confirm.tsx b/packages/create-astro/src/components/Confirm.tsx index 84d83ed8f..6f755ee61 100644 --- a/packages/create-astro/src/components/Confirm.tsx +++ b/packages/create-astro/src/components/Confirm.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react'; -import { Box, Text, useInput, useApp } from 'ink'; +import { Box, Text, useApp } from 'ink'; +import { relative } from 'path'; import Spacer from './Spacer'; import Select from './Select'; @@ -18,7 +19,7 @@ const Confirm: FC<{ message?: any; context: any; onSubmit: (value: boolean) => v {'[uh-oh]'} {' '} - It appears ./{projectName} is not empty. Overwrite? + It appears ./{relative(process.cwd(), projectName)} is not empty. Overwrite? ) : ( diff --git a/packages/create-astro/src/components/Finalize.tsx b/packages/create-astro/src/components/Finalize.tsx index 933a8844e..c7aeaad36 100644 --- a/packages/create-astro/src/components/Finalize.tsx +++ b/packages/create-astro/src/components/Finalize.tsx @@ -1,5 +1,6 @@ import React, { FC, useEffect } from 'react'; import { Box, Text } from 'ink'; +import { relative } from 'path'; import { cancelProcessListeners } from '../utils'; const Finalize: FC<{ context: any }> = ({ context: { use, projectName } }) => { @@ -8,20 +9,22 @@ const Finalize: FC<{ context: any }> = ({ context: { use, projectName } }) => { process.exit(0); }, []); + const projectPath = `./${relative(process.cwd(), projectName)}`; + return ( <> {'[ yes ]'} {' '} - Project initialized at ./{projectName} + Project initialized at {projectPath} {'[ tip ]'} Get started by running - cd ./{projectName} + cd {projectPath} {use} start diff --git a/packages/create-astro/src/components/Help.tsx b/packages/create-astro/src/components/Help.tsx index 5991664f1..ebbc0aa3c 100644 --- a/packages/create-astro/src/components/Help.tsx +++ b/packages/create-astro/src/components/Help.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react'; import { Box, Text } from 'ink'; +import decamelize from 'decamelize'; import { ARGS, ARG } from '../config'; const Type: FC<{ type: any; enum?: string[] }> = ({ type, enum: e }) => { @@ -71,7 +72,7 @@ const Help: FC<{ context: any }> = ({ context: { templates } }) => { {Object.entries(ARGS).map(([name, info]) => ( - value) } : info} /> + value) } : info} /> ))} diff --git a/packages/create-astro/src/config.ts b/packages/create-astro/src/config.ts index 8216fd1ab..8da0720e6 100644 --- a/packages/create-astro/src/config.ts +++ b/packages/create-astro/src/config.ts @@ -1,4 +1,5 @@ import type * as arg from 'arg'; +import decamelize from 'decamelize'; export interface ARG { type: any; @@ -17,9 +18,9 @@ export const ARGS: Record = { enum: ['npm', 'yarn'], description: 'specifies package manager to use', }, - run: { + skipInstall: { type: Boolean, - description: 'should dependencies be installed automatically?', + description: 'should installing dependencies be skipped?', }, force: { type: Boolean, @@ -39,7 +40,7 @@ export const ARGS: Record = { }; export const args = Object.entries(ARGS).reduce((acc, [name, info]) => { - const key = `--${name}`; + const key = `--${decamelize(name, { separator: '-' })}`; const spec = { ...acc, [key]: info.type }; if (info.alias) { diff --git a/packages/create-astro/src/index.tsx b/packages/create-astro/src/index.tsx index 9a510d7b7..631079083 100644 --- a/packages/create-astro/src/index.tsx +++ b/packages/create-astro/src/index.tsx @@ -25,9 +25,9 @@ export default async function createAstro() { const use = (args['--use'] ?? pkgManager) as 'npm' | 'yarn'; const template = args['--template']; const force = args['--force']; - const run = args['--run'] ?? true; + const skipInstall = args['--skip-install']; - const app = render(); + const app = render(); const onError = () => { if (app) app.clear(); diff --git a/packages/create-astro/src/utils.ts b/packages/create-astro/src/utils.ts index 52e56f5f0..892e01076 100644 --- a/packages/create-astro/src/utils.ts +++ b/packages/create-astro/src/utils.ts @@ -61,16 +61,14 @@ export async function rewriteFiles(projectName: string) { 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)); +export async function prepareTemplate(options: { use: 'npm' | 'yarn'; templateName: string; projectName: string; skipInstall?: boolean }) { + const { use, templateName, projectName, skipInstall } = options; + const dest = resolve(projectName); + const template = fileURLToPath(new URL(`./templates/${templateName}.tgz`, import.meta.url)); await decompress(template, dest); await rewriteFiles(projectName); - try { - await run(use, use === 'npm' ? 'i' : null, dest); - } catch (e) { - cleanup(true); + if (!skipInstall) { + await run(use, use === 'npm' ? 'i' : null, dest).catch(() => cleanup(true)); } isDone = true; return; diff --git a/packages/create-astro/test/create-astro.test.js b/packages/create-astro/test/create-astro.test.js index 5fb556ef3..d7abb7e64 100644 --- a/packages/create-astro/test/create-astro.test.js +++ b/packages/create-astro/test/create-astro.test.js @@ -19,10 +19,13 @@ CreateAstro.before(async () => { for (const template of templates) { CreateAstro(template, async () => { - await execa('../../create-astro.js', [template, '--template', template], { cwd }); + const { stdout } = await execa('../../create-astro.js', [`./${template}`, '--template', template, '--skip-install'], { cwd }); + + // test: path should formatted as './{dirName}' + assert.not.match(stdout, '././'); const DOES_HAVE = ['.gitignore', 'package.json', 'public', 'src']; - const DOES_NOT_HAVE = ['_gitignore', 'meta.json']; + const DOES_NOT_HAVE = ['_gitignore', 'meta.json', 'node_modules']; // test: template contains essential files & folders for (const file of DOES_HAVE) { @@ -31,7 +34,7 @@ for (const template of templates) { // test: template DOES NOT contain files supposed to be stripped away for (const file of DOES_NOT_HAVE) { - assert.not.ok(fs.existsSync(path.join(cwd, template, `does not have ${file}`))); + assert.not.ok(fs.existsSync(path.join(cwd, template, file)), `does not have ${file}`); } }); } diff --git a/yarn.lock b/yarn.lock index 8ff5db51e..3efbfc2bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3306,6 +3306,11 @@ decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decamelize@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-5.0.0.tgz#88358157b010ef133febfd27c18994bd80c6215b" + integrity sha512-U75DcT5hrio3KNtvdULAWnLiAPbFUC4191ldxMmj4FA/mRuBnmDwU0boNfPyFRhnan+Jm+haLeSn3P0afcBn4w== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz"