astro/packages/create-astro/src/index.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

399 lines
11 KiB
TypeScript
Raw Normal View History

/* eslint no-console: 'off' */
2022-10-26 15:16:54 +00:00
import { color, generateProjectName, label, say } from '@astrojs/cli-kit';
2022-10-28 17:26:22 +00:00
import { forceUnicode, random } from '@astrojs/cli-kit/utils';
import { assign, parse, stringify } from 'comment-json';
2022-06-06 16:49:53 +00:00
import { execa, execaCommand } from 'execa';
import fs from 'fs';
2022-10-26 15:16:54 +00:00
import { downloadTemplate } from 'giget';
import { bold, dim, green, reset, yellow } from 'kleur/colors';
2022-06-06 16:49:53 +00:00
import ora from 'ora';
import { platform } from 'os';
2022-06-06 16:49:53 +00:00
import path from 'path';
import prompts from 'prompts';
2022-07-07 18:14:25 +00:00
import detectPackageManager from 'which-pm-runs';
import yargs from 'yargs-parser';
import { loadWithRocketGradient, rocketAscii } from './gradient.js';
2022-10-26 15:16:54 +00:00
import { logger } from './logger.js';
import {
banner,
getName,
getVersion,
info,
nextSteps,
typescriptByDefault,
welcome,
} from './messages.js';
2022-06-06 16:49:53 +00:00
import { TEMPLATES } from './templates.js';
// NOTE: In the v7.x version of npm, the default behavior of `npm init` was changed
2021-11-17 18:32:36 +00:00
// to no longer require `--` to pass args and instead pass `--` directly to us. This
// broke our arg parser, since `--` is a special kind of flag. Filtering for `--` here
// fixes the issue so that create-astro now works on all npm version.
2021-11-17 18:32:36 +00:00
const cleanArgv = process.argv.filter((arg) => arg !== '--');
const args = yargs(cleanArgv, { boolean: ['fancy', 'y'], alias: { y: 'yes' } });
// Always skip Houston on Windows (for now)
if (platform() === 'win32') args.skipHouston = true;
prompts.override(args);
// Enable full unicode support if the `--fancy` flag is passed
if (args.fancy) {
forceUnicode();
}
export function mkdirp(dir: string) {
2021-06-08 15:12:07 +00:00
try {
fs.mkdirSync(dir, { recursive: true });
} catch (e: any) {
2021-06-08 15:12:07 +00:00
if (e.code === 'EEXIST') return;
throw e;
}
}
// Some existing files and directories can be safely ignored when checking if a directory is a valid project directory.
// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/create-react-app/createReactApp.js#L907-L934
const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
'.DS_Store',
'.git',
'.gitattributes',
'.gitignore',
'.gitlab-ci.yml',
'.hg',
'.hgcheck',
'.hgignore',
'.idea',
'.npmignore',
'.travis.yml',
'.yarn',
'.yarnrc.yml',
'docs',
'LICENSE',
'mkdocs.yml',
'Thumbs.db',
/\.iml$/,
/^npm-debug\.log/,
/^yarn-debug\.log/,
/^yarn-error\.log/,
];
function isValidProjectDirectory(dirPath: string) {
if (!fs.existsSync(dirPath)) {
2023-01-20 14:54:53 +00:00
return true;
}
const conflicts = fs.readdirSync(dirPath).filter((content) => {
return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
return typeof safeContent === 'string' ? content === safeContent : safeContent.test(content);
});
});
return conflicts.length === 0;
}
const FILES_TO_REMOVE = ['.stackblitzrc', 'sandbox.config.json', 'CHANGELOG.md']; // some files are only needed for online editors when using astro.new. Remove for create-astro installs.
// Please also update the installation instructions in the docs at https://github.com/withastro/docs/blob/main/src/pages/en/install/auto.md if you make any changes to the flow or wording here.
export async function main() {
2023-01-20 14:54:53 +00:00
const pkgManager = detectPackageManager()?.name || 'npm';
const [username, version] = await Promise.all([getName(), getVersion()]);
logger.debug('Verbose logging turned on');
if (!args.skipHouston) {
2023-01-20 14:54:53 +00:00
await say(
[
[
2022-10-28 17:26:22 +00:00
'Welcome',
'to',
label('astro', color.bgGreen, color.black),
color.green(`v${version}`) + ',',
`${username}!`,
],
random(welcome),
2022-10-26 15:16:54 +00:00
],
2022-10-28 17:26:22 +00:00
{ hat: args.fancy ? '🎩' : undefined }
);
await banner(version);
}
2021-12-22 16:11:05 -05:00
let cwd = args['_'][2] as string;
if (cwd && isValidProjectDirectory(cwd)) {
let acknowledgeProjectDir = ora({
color: 'green',
text: `Using ${bold(cwd)} as project directory.`,
});
acknowledgeProjectDir.succeed();
}
if (!cwd || !isValidProjectDirectory(cwd)) {
const notEmptyMsg = (dirPath: string) => `"${bold(dirPath)}" is not empty!`;
if (!isValidProjectDirectory(cwd)) {
let rejectProjectDir = ora({ color: 'red', text: notEmptyMsg(cwd) });
rejectProjectDir.fail();
2021-06-08 15:12:07 +00:00
}
const dirResponse = await prompts(
{
type: 'text',
name: 'directory',
message: 'Where would you like to create your new project?',
initial: generateProjectName(),
validate(value) {
if (!isValidProjectDirectory(value)) {
return notEmptyMsg(value);
}
return true;
},
},
{ onCancel: () => ora().info(dim('Operation cancelled. See you later, astronaut!')) }
);
cwd = dirResponse.directory;
}
if (!cwd) {
2022-10-28 19:07:40 +00:00
ora().info(dim('No directory provided. See you later, astronaut!'));
process.exit(1);
2021-06-08 15:12:07 +00:00
}
2021-12-22 16:11:05 -05:00
const options = await prompts(
[
{
type: 'select',
name: 'template',
message: 'How would you like to setup your new project?',
choices: TEMPLATES,
},
],
{ onCancel: () => ora().info(dim('Operation cancelled. See you later, astronaut!')) }
);
2021-12-22 16:11:05 -05:00
2022-11-15 07:29:00 +00:00
if (!options.template || options.template === true) {
2022-10-28 19:07:40 +00:00
ora().info(dim('No template provided. See you later, astronaut!'));
process.exit(1);
}
2021-12-22 16:11:05 -05:00
let templateSpinner = await loadWithRocketGradient('Copying project files...');
const hash = args.commit ? `#${args.commit}` : '';
2021-12-22 16:11:05 -05:00
const isThirdParty = options.template.includes('/');
const templateTarget = isThirdParty
? options.template
: `withastro/astro/examples/${options.template}#latest`;
2021-12-22 16:11:05 -05:00
// Copy
if (!args.dryRun) {
try {
await downloadTemplate(`${templateTarget}${hash}`, {
force: true,
provider: 'github',
cwd,
dir: '.',
});
} catch (err: any) {
fs.rmdirSync(cwd);
if (err.message.includes('404')) {
console.error(`Could not find template ${color.underline(options.template)}!`);
if (isThirdParty) {
const hasBranch = options.template.includes('#');
if (hasBranch) {
console.error('Are you sure this GitHub repo and branch exist?');
} else {
console.error(
`Are you sure this GitHub repo exists?` +
`This command uses the ${color.bold('main')} branch by default.\n` +
`If the repo doesn't have a main branch, specify a custom branch name:\n` +
color.underline(options.template + color.bold('#branch-name'))
);
}
}
} else {
console.error(err.message);
}
process.exit(1);
}
2021-12-22 16:11:05 -05:00
// Post-process in parallel
await Promise.all(
FILES_TO_REMOVE.map(async (file) => {
const fileLoc = path.resolve(path.join(cwd, file));
if (fs.existsSync(fileLoc)) {
return fs.promises.rm(fileLoc, {});
}
})
);
}
2021-12-22 16:11:05 -05:00
templateSpinner.text = green('Template copied!');
templateSpinner.succeed();
2021-12-22 16:11:05 -05:00
2023-01-20 14:54:53 +00:00
const install = args.y
? true
: (
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);
},
}
)
).install;
if (args.dryRun) {
ora().info(dim(`--dry-run enabled, skipping.`));
} else if (install) {
const installExec = execa(pkgManager, ['install'], { cwd });
const installingPackagesMsg = `Installing packages${emojiWithFallback(' 📦', '...')}`;
const installSpinner = await loadWithRocketGradient(installingPackagesMsg);
await new Promise<void>((resolve, reject) => {
installExec.stdout?.on('data', function (data) {
installSpinner.text = `${rocketAscii} ${installingPackagesMsg}\n${bold(
`[${pkgManager}]`
)} ${data}`;
});
installExec.on('error', (error) => reject(error));
installExec.on('close', () => resolve());
});
installSpinner.text = green('Packages installed!');
installSpinner.succeed();
} else {
2022-10-26 15:16:54 +00:00
await info('No problem!', 'Remember to install dependencies after setup.');
}
2023-01-20 14:54:53 +00:00
const gitResponse = args.y
? true
: (
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);
},
}
)
).git;
if (args.dryRun) {
ora().info(dim(`--dry-run enabled, skipping.`));
} else if (gitResponse) {
// Add a check to see if there is already a .git directory and skip 'git init' if yes (with msg to output)
const gitDir = './.git';
if (fs.existsSync(gitDir)) {
2023-01-26 20:36:29 +00:00
ora().info(dim('A .git directory already exists. Skipping creating a new Git repository.'));
} else {
await execaCommand('git init', { cwd });
ora().succeed('Git repository created!');
}
} else {
2022-10-26 15:16:54 +00:00
await info(
'Sounds good!',
`You can come back and run ${color.reset(`git init`)}${color.dim(' later.')}`
);
}
2023-01-20 14:54:53 +00:00
if (args.y && !args.typescript) {
ora().warn(dim('--typescript <choice> missing. Defaulting to "strict"'));
args.typescript = 'strict';
}
let tsResponse =
2023-01-20 14:54:53 +00:00
args.typescript ||
(
await prompts(
{
type: 'select',
name: 'typescript',
message: 'How would you like to setup TypeScript?',
choices: [
{ value: 'strict', title: 'Strict', description: '(recommended)' },
{ value: 'strictest', title: 'Strictest' },
{ value: 'base', title: 'Relaxed' },
{ value: 'unsure', title: 'Help me choose' },
],
},
{
onCancel: () => {
ora().info(
dim(
'Operation cancelled. Your project folder has been created but no TypeScript configuration file was created.'
)
);
process.exit(1);
},
}
)
).typescript;
if (tsResponse === 'unsure') {
await typescriptByDefault();
tsResponse = 'base';
}
if (args.dryRun) {
ora().info(dim(`--dry-run enabled, skipping.`));
} else if (tsResponse) {
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
const templateTSConfigPath = path.join(cwd, 'tsconfig.json');
fs.readFile(templateTSConfigPath, (err, data) => {
if (err && err.code === 'ENOENT') {
// If the template doesn't have a tsconfig.json, let's add one instead
fs.writeFileSync(
templateTSConfigPath,
stringify({ extends: `astro/tsconfigs/${tsResponse ?? 'base'}` }, null, 2)
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
);
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
return;
}
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
const templateTSConfig = parse(data.toString());
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
if (templateTSConfig && typeof templateTSConfig === 'object') {
const result = assign(templateTSConfig, {
extends: `astro/tsconfigs/${tsResponse ?? 'base'}`,
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
});
`create-astro`: always create `tsconfig.json` (#4810) * `create-astro`: always create `tsconfig.json` Currently, we only make sure `tsconfig.json` exists when `strict` or `strictest` is selected. Both `default` & `optout` are intended to correspond to `base` -- and will do so for all [23 official templates](https://github.com/withastro/astro/tree/main/examples), but not necessarily for third-party templates. The [example command for installing a third-party template](https://github.com/withastro/astro/blob/a800bf7/packages/create-astro/README.md?plain=1#L31-L35) is (rather conveniently for the sake of this PR!) an example of a template without a `tsconfig.json` file, and installing it with the `default` ("Relaxed") Typescript option results in no `tsconfig.json` file, rather than a `tsconfig.json` file containing `{ "extends": "astro/tsconfigs/base" }` as would be expected. This PR addresses this scenario. It also explicitly sets the `tsconfig.json` file to `{ "extends": "astro/tsconfigs/base" }` when `default` (which I renamed to `base`, still presented to the user as "Relaxed") or `optout` is selected (`optout` has always printed a warning about the importance of `tsconfig.json` & `src/env.d.ts` but otherwise behaved identically to `default`). This is necessary in two scenarios: 1. When the `tsconfig.json` file was created by this script. 2. When it either didn't already include `"extends"`, or it extended a different config by default. For example, some third-party templates might default to `strict`, in which case I'm guessing we'd want to respect the user's choice and change that to `base`. * update `del` 6.1.1 --> 7.0.0 * test: prevent excess writes (without this it triggers many times) * test: create-astro typescript prompt * changeset * fix: recursive `mkdirSync` * test: longer timeout for `windows-latest` OS (see if this fixes failing tests) * better glob path creation, don't hardcode `/` * test: longer timeout for windows-latest OS (since I'm about to trigger another CI run by pushing a commit, might as well try this too) * create-astro test: show last CLI output on timeout * drop variable timeout Typescript tests are slower than directory tests, but they are all usually less than 5000 ms. Less complexity, easier to maintain. * DRY new error output * Update lockfile * Sync lockfile with main * Update lockfile Co-authored-by: Princesseuh <princssdev@gmail.com>
2022-09-22 11:37:01 -07:00
fs.writeFileSync(templateTSConfigPath, stringify(result, null, 2));
} else {
console.log(
yellow(
"There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed"
)
);
}
});
ora().succeed('TypeScript settings applied!');
}
2022-10-26 15:16:54 +00:00
let projectDir = path.relative(process.cwd(), cwd);
const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`;
await nextSteps({ projectDir, devCmd });
if (!args.skipHouston) {
await say(['Good luck out there, astronaut!']);
}
2021-06-08 15:12:07 +00:00
}
function emojiWithFallback(char: string, fallback: string) {
return process.platform !== 'win32' ? char : fallback;
}