summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/large-rivers-enjoy.md5
-rw-r--r--packages/create-astro/src/index.ts156
2 files changed, 116 insertions, 45 deletions
diff --git a/.changeset/large-rivers-enjoy.md b/.changeset/large-rivers-enjoy.md
new file mode 100644
index 000000000..b4c51c594
--- /dev/null
+++ b/.changeset/large-rivers-enjoy.md
@@ -0,0 +1,5 @@
+---
+'create-astro': patch
+---
+
+Added better error handling when cancelling operations, providing bad templates and when there's a degit cache issue
diff --git a/packages/create-astro/src/index.ts b/packages/create-astro/src/index.ts
index be6c6a6b9..43bbdaa63 100644
--- a/packages/create-astro/src/index.ts
+++ b/packages/create-astro/src/index.ts
@@ -2,6 +2,7 @@
import degit from 'degit';
import { execa, execaCommand } from 'execa';
import fs from 'fs';
+import os from 'os';
import { bgCyan, black, bold, cyan, dim, gray, green, red, reset, yellow } from 'kleur/colors';
import ora from 'ora';
import path from 'path';
@@ -72,18 +73,21 @@ export async function main() {
let rejectProjectDir = ora({ color: 'red', text: notEmptyMsg(cwd) });
rejectProjectDir.fail();
}
- const dirResponse = await prompts({
- type: 'text',
- name: 'directory',
- message: 'Where would you like to create your new project?',
- initial: './my-astro-site',
- validate(value) {
- if (!isEmpty(value)) {
- return notEmptyMsg(value);
- }
- return true;
+ const dirResponse = await prompts(
+ {
+ type: 'text',
+ name: 'directory',
+ message: 'Where would you like to create your new project?',
+ initial: './my-astro-site',
+ validate(value) {
+ if (!isEmpty(value)) {
+ return notEmptyMsg(value);
+ }
+ return true;
+ },
},
- });
+ { onCancel: () => ora().info(dim('Operation cancelled. See you later, astronaut!')) }
+ );
cwd = dirResponse.directory;
}
@@ -91,20 +95,23 @@ export async function main() {
process.exit(1);
}
- const options = await prompts([
- {
- type: 'select',
- name: 'template',
- message: 'Which template would you like to use?',
- choices: TEMPLATES,
- },
- ]);
+ const options = await prompts(
+ [
+ {
+ type: 'select',
+ name: 'template',
+ message: 'Which template would you like to use?',
+ choices: TEMPLATES,
+ },
+ ],
+ { onCancel: () => ora().info(dim('Operation cancelled. See you later, astronaut!')) }
+ );
if (!options.template) {
process.exit(1);
}
- const templateSpinner = await loadWithRocketGradient('Copying project files...');
+ let templateSpinner = await loadWithRocketGradient('Copying project files...');
const hash = args.commit ? `#${args.commit}` : '';
@@ -132,23 +139,55 @@ export async function main() {
logger.debug(info.message);
});
await emitter.clone(cwd);
+
+ // degit does not return an error when an invalid template is provided, as such we need to handle this manually
+ // It's not very pretty, but to the user eye, we just return a nice message and nothing weird happened
+ if (isEmpty(cwd)) {
+ fs.rmdirSync(cwd);
+ throw new Error(`Error: The provided template (${cyan(options.template)}) does not exist`);
+ }
} catch (err: any) {
+ templateSpinner.fail();
+
// degit is compiled, so the stacktrace is pretty noisy. Only report the stacktrace when using verbose mode.
logger.debug(err);
console.error(red(err.message));
- // Warning for issue #655
- if (err.message === 'zlib: unexpected end of file') {
- console.log(
- yellow(
- "This seems to be a cache related problem. Remove the folder '~/.degit/github/withastro' to fix this error."
- )
- );
+ // Warning for issue #655 and other corrupted cache issue
+ if (
+ err.message === 'zlib: unexpected end of file' ||
+ err.message === 'TAR_BAD_ARCHIVE: Unrecognized archive format'
+ ) {
console.log(
yellow(
- 'For more information check out this issue: https://github.com/withastro/astro/issues/655'
+ 'Local degit cache seems to be corrupted. For more information check out this issue: https://github.com/withastro/astro/issues/655. '
)
);
+ const cacheIssueResponse = await prompts({
+ type: 'confirm',
+ name: 'cache',
+ message: 'Would you like us to clear the cache and try again?',
+ initial: true,
+ });
+
+ if (cacheIssueResponse.cache) {
+ const homeDirectory = os.homedir();
+ const cacheDir = path.join(homeDirectory, '.degit', 'github', 'withastro');
+
+ fs.rmSync(cacheDir, { recursive: true, force: true, maxRetries: 3 });
+
+ templateSpinner = await loadWithRocketGradient('Copying project files...');
+ try {
+ await emitter.clone(cwd);
+ } catch (e: any) {
+ logger.debug(e);
+ console.error(red(e.message));
+ }
+ } else {
+ console.log(
+ "Okay, no worries! To fix this manually, remove the folder '~/.degit/github/withastro' and rerun the command."
+ );
+ }
}
// Helpful message when encountering the "could not find commit hash for ..." error
@@ -164,7 +203,7 @@ export async function main() {
)
);
}
- templateSpinner.fail();
+
process.exit(1);
}
@@ -182,12 +221,26 @@ export async function main() {
templateSpinner.text = green('Template copied!');
templateSpinner.succeed();
- const installResponse = await prompts({
- type: 'confirm',
- name: 'install',
- message: `Would you like to install ${pkgManager} dependencies? ${reset(dim('(recommended)'))}`,
- initial: true,
- });
+ const installResponse = await prompts(
+ {
+ type: 'confirm',
+ name: 'install',
+ message: `Would you like to install ${pkgManager} dependencies? ${reset(
+ dim('(recommended)')
+ )}`,
+ initial: true,
+ },
+ {
+ onCancel: () => {
+ ora().info(
+ dim(
+ 'Operation cancelled. Your project folder has already been created, however no dependencies have been installed'
+ )
+ );
+ process.exit(1);
+ },
+ }
+ );
if (args.dryRun) {
ora().info(dim(`--dry-run enabled, skipping.`));
@@ -210,12 +263,22 @@ export async function main() {
ora().info(dim(`No problem! Remember to install dependencies after setup.`));
}
- const gitResponse = await prompts({
- type: 'confirm',
- name: 'git',
- message: `Would you like to initialize a new git repository? ${reset(dim('(optional)'))}`,
- initial: true,
- });
+ const gitResponse = await prompts(
+ {
+ type: 'confirm',
+ name: 'git',
+ message: `Would you like to initialize a new git repository? ${reset(dim('(optional)'))}`,
+ initial: true,
+ },
+ {
+ onCancel: () => {
+ ora().info(
+ dim('Operation cancelled. No worries, your project folder has already been created')
+ );
+ process.exit(1);
+ },
+ }
+ );
if (args.dryRun) {
ora().info(dim(`--dry-run enabled, skipping.`));
@@ -234,9 +297,12 @@ export async function main() {
let projectDir = path.relative(process.cwd(), cwd);
const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`;
- await logAndWait(
- `You can now ${bold(cyan('cd'))} into the ${bold(cyan(projectDir))} project directory.`
- );
+ // If the project dir is the current dir, no need to tell users to cd in the folder
+ if (projectDir !== '/') {
+ await logAndWait(
+ `You can now ${bold(cyan('cd'))} into the ${bold(cyan(projectDir))} project directory.`
+ );
+ }
await logAndWait(
`Run ${bold(cyan(devCmd))} to start the Astro dev server. ${bold(cyan('CTRL-C'))} to close.`
);
@@ -246,7 +312,7 @@ export async function main() {
)} to your project using ${bold(cyan('astro add'))}`
);
await logAndWait('');
- await logAndWait(`Stuck? Come join us at ${bold(cyan('https://astro.build/chat'))}`, 1000);
+ await logAndWait(`Stuck? Come join us at ${bold(cyan('https://astro.build/chat'))}`, 750);
await logAndWait(dim('Good luck out there, astronaut.'));
await logAndWait('', 300);
}