[ci] format
This commit is contained in:
parent
8d2187d8b8
commit
6a59531ff9
20 changed files with 409 additions and 298 deletions
|
@ -1,7 +1,7 @@
|
|||
import os from 'node:os';
|
||||
import arg from 'arg';
|
||||
import detectPackageManager from 'which-pm-runs';
|
||||
import { prompt } from '@astrojs/cli-kit';
|
||||
import arg from 'arg';
|
||||
import os from 'node:os';
|
||||
import detectPackageManager from 'which-pm-runs';
|
||||
|
||||
import { getName, getVersion } from '../messages.js';
|
||||
|
||||
|
@ -26,27 +26,29 @@ export interface Context {
|
|||
exit(code: number): never;
|
||||
}
|
||||
|
||||
|
||||
export async function getContext(argv: string[]): Promise<Context> {
|
||||
const flags = arg({
|
||||
'--template': String,
|
||||
'--ref': String,
|
||||
'--yes': Boolean,
|
||||
'--no': Boolean,
|
||||
'--install': Boolean,
|
||||
'--no-install': Boolean,
|
||||
'--git': Boolean,
|
||||
'--no-git': Boolean,
|
||||
'--typescript': String,
|
||||
'--skip-houston': Boolean,
|
||||
'--dry-run': Boolean,
|
||||
'--help': Boolean,
|
||||
'--fancy': Boolean,
|
||||
const flags = arg(
|
||||
{
|
||||
'--template': String,
|
||||
'--ref': String,
|
||||
'--yes': Boolean,
|
||||
'--no': Boolean,
|
||||
'--install': Boolean,
|
||||
'--no-install': Boolean,
|
||||
'--git': Boolean,
|
||||
'--no-git': Boolean,
|
||||
'--typescript': String,
|
||||
'--skip-houston': Boolean,
|
||||
'--dry-run': Boolean,
|
||||
'--help': Boolean,
|
||||
'--fancy': Boolean,
|
||||
|
||||
'-y': '--yes',
|
||||
'-n': '--no',
|
||||
'-h': '--help',
|
||||
}, { argv, permissive: true });
|
||||
'-y': '--yes',
|
||||
'-n': '--no',
|
||||
'-h': '--help',
|
||||
},
|
||||
{ argv, permissive: true }
|
||||
);
|
||||
|
||||
const pkgManager = detectPackageManager()?.name ?? 'npm';
|
||||
const [username, version] = await Promise.all([getName(), getVersion()]);
|
||||
|
@ -75,8 +77,10 @@ export async function getContext(argv: string[]): Promise<Context> {
|
|||
if (typescript == undefined) typescript = 'strict';
|
||||
}
|
||||
|
||||
skipHouston = ((os.platform() === 'win32' && !fancy) || skipHouston) ?? [yes, no, install, git, typescript].some((v) => v !== undefined);
|
||||
|
||||
skipHouston =
|
||||
((os.platform() === 'win32' && !fancy) || skipHouston) ??
|
||||
[yes, no, install, git, typescript].some((v) => v !== undefined);
|
||||
|
||||
const context: Context = {
|
||||
help,
|
||||
prompt,
|
||||
|
@ -95,7 +99,7 @@ export async function getContext(argv: string[]): Promise<Context> {
|
|||
cwd,
|
||||
exit(code) {
|
||||
process.exit(code);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
return context;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import type { Context } from "./context";
|
||||
import type { Context } from './context';
|
||||
|
||||
import { title, info, spinner } from '../messages.js';
|
||||
import { execa } from 'execa';
|
||||
import { info, spinner, title } from '../messages.js';
|
||||
|
||||
export async function dependencies(ctx: Pick<Context, 'install'|'yes'|'prompt'|'pkgManager'|'cwd'|'dryRun'>) {
|
||||
export async function dependencies(
|
||||
ctx: Pick<Context, 'install' | 'yes' | 'prompt' | 'pkgManager' | 'cwd' | 'dryRun'>
|
||||
) {
|
||||
let deps = ctx.install ?? ctx.yes;
|
||||
if (deps === undefined) {
|
||||
({ deps } = await ctx.prompt({
|
||||
|
@ -33,11 +35,10 @@ export async function dependencies(ctx: Pick<Context, 'install'|'yes'|'prompt'|'
|
|||
}
|
||||
}
|
||||
|
||||
async function install({ pkgManager, cwd }: { pkgManager: string, cwd: string }) {
|
||||
const installExec = execa(pkgManager, ['install'], { cwd });
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
installExec.on('error', (error) => reject(error));
|
||||
installExec.on('close', () => resolve());
|
||||
});
|
||||
async function install({ pkgManager, cwd }: { pkgManager: string; cwd: string }) {
|
||||
const installExec = execa(pkgManager, ['install'], { cwd });
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
installExec.on('error', (error) => reject(error));
|
||||
installExec.on('close', () => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import type { Context } from "./context";
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import type { Context } from './context';
|
||||
|
||||
import { color } from '@astrojs/cli-kit';
|
||||
import { title, info, spinner } from '../messages.js';
|
||||
import { execa } from 'execa';
|
||||
import { info, spinner, title } from '../messages.js';
|
||||
|
||||
export async function git(ctx: Pick<Context, 'cwd'|'git'|'yes'|'prompt'|'dryRun'>) {
|
||||
export async function git(ctx: Pick<Context, 'cwd' | 'git' | 'yes' | 'prompt' | 'dryRun'>) {
|
||||
if (fs.existsSync(path.join(ctx.cwd, '.git'))) {
|
||||
await info('Nice!', `Git has already been initialized`);
|
||||
return
|
||||
return;
|
||||
}
|
||||
let _git = ctx.git ?? ctx.yes;
|
||||
if (_git === undefined) {
|
||||
|
@ -43,6 +43,15 @@ async function init({ cwd }: { cwd: string }) {
|
|||
try {
|
||||
await execa('git', ['init'], { cwd, stdio: 'ignore' });
|
||||
await execa('git', ['add', '-A'], { cwd, stdio: 'ignore' });
|
||||
await execa('git', ['commit', '-m', 'Initial commit from Astro', '--author="houston[bot] <astrobot-houston@users.noreply.github.com>"'], { cwd, stdio: 'ignore' });
|
||||
await execa(
|
||||
'git',
|
||||
[
|
||||
'commit',
|
||||
'-m',
|
||||
'Initial commit from Astro',
|
||||
'--author="houston[bot] <astrobot-houston@users.noreply.github.com>"',
|
||||
],
|
||||
{ cwd, stdio: 'ignore' }
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { type Context } from './context';
|
||||
|
||||
import { banner, welcome, say } from '../messages.js';
|
||||
import { label, color } from '@astrojs/cli-kit';
|
||||
import { color, label } from '@astrojs/cli-kit';
|
||||
import { random } from '@astrojs/cli-kit/utils';
|
||||
import { banner, say, welcome } from '../messages.js';
|
||||
|
||||
export async function intro(ctx: Pick<Context, 'skipHouston'|'version'|'username'>) {
|
||||
export async function intro(ctx: Pick<Context, 'skipHouston' | 'version' | 'username'>) {
|
||||
if (!ctx.skipHouston) {
|
||||
await say([
|
||||
[
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Context } from "./context";
|
||||
import path from 'node:path';
|
||||
import { Context } from './context';
|
||||
|
||||
import { nextSteps, say } from '../messages.js';
|
||||
|
||||
export async function next(ctx: Pick<Context, 'cwd'|'pkgManager'|'skipHouston'>) {
|
||||
export async function next(ctx: Pick<Context, 'cwd' | 'pkgManager' | 'skipHouston'>) {
|
||||
let projectDir = path.relative(process.cwd(), ctx.cwd);
|
||||
const devCmd = ctx.pkgManager === 'npm' ? 'npm run dev' : `${ctx.pkgManager} dev`;
|
||||
await nextSteps({ projectDir, devCmd });
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import type { Context } from "./context";
|
||||
import type { Context } from './context';
|
||||
|
||||
import { color, generateProjectName } from '@astrojs/cli-kit';
|
||||
import { title, info, log } from '../messages.js';
|
||||
import path from 'node:path';
|
||||
import { info, log, title } from '../messages.js';
|
||||
|
||||
import { isEmpty, toValidName } from './shared.js';
|
||||
|
||||
export async function projectName(ctx: Pick<Context, 'cwd'|'prompt'|'projectName'|'exit'>) {
|
||||
export async function projectName(ctx: Pick<Context, 'cwd' | 'prompt' | 'projectName' | 'exit'>) {
|
||||
await checkCwd(ctx.cwd);
|
||||
|
||||
if (!ctx.cwd || !isEmpty(ctx.cwd)) {
|
||||
|
|
|
@ -42,20 +42,18 @@ export function isEmpty(dirPath: string) {
|
|||
}
|
||||
|
||||
export function isValidName(projectName: string) {
|
||||
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(
|
||||
projectName,
|
||||
)
|
||||
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
|
||||
}
|
||||
|
||||
export function toValidName(projectName: string) {
|
||||
if (isValidName(projectName)) return projectName;
|
||||
|
||||
return projectName
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/^[._]/, '')
|
||||
.replace(/[^a-z\d\-~]+/g, '-')
|
||||
return projectName
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/^[._]/, '')
|
||||
.replace(/[^a-z\d\-~]+/g, '-')
|
||||
.replace(/^-+/, '')
|
||||
.replace(/-+$/, '')
|
||||
.replace(/-+$/, '');
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
/* eslint no-console: 'off' */
|
||||
import type { Context } from "./context";
|
||||
import type { Context } from './context';
|
||||
|
||||
import { color } from '@astrojs/cli-kit';
|
||||
import { downloadTemplate } from 'giget';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { downloadTemplate } from 'giget';
|
||||
import { error } from '../messages.js';
|
||||
import { color } from '@astrojs/cli-kit';
|
||||
import { title, info, spinner } from '../messages.js';
|
||||
import { error, info, spinner, title } from '../messages.js';
|
||||
|
||||
export async function template(ctx: Pick<Context, 'template'|'prompt'|'dryRun'|'exit'|'exit'>) {
|
||||
export async function template(
|
||||
ctx: Pick<Context, 'template' | 'prompt' | 'dryRun' | 'exit' | 'exit'>
|
||||
) {
|
||||
if (!ctx.template) {
|
||||
const { template: tmpl } = await ctx.prompt({
|
||||
name: 'template',
|
||||
|
@ -43,18 +44,27 @@ export async function template(ctx: Pick<Context, 'template'|'prompt'|'dryRun'|'
|
|||
// some files are only needed for online editors when using astro.new. Remove for create-astro installs.
|
||||
const FILES_TO_REMOVE = ['sandbox.config.json', 'CHANGELOG.md'];
|
||||
const FILES_TO_UPDATE = {
|
||||
'package.json': (file: string, overrides: { name: string }) => fs.promises.readFile(file, 'utf-8').then(value => (
|
||||
fs.promises.writeFile(file, JSON.stringify(Object.assign(JSON.parse(value), Object.assign(overrides, { private: undefined })), null, '\t'), 'utf-8')
|
||||
))
|
||||
}
|
||||
'package.json': (file: string, overrides: { name: string }) =>
|
||||
fs.promises
|
||||
.readFile(file, 'utf-8')
|
||||
.then((value) =>
|
||||
fs.promises.writeFile(
|
||||
file,
|
||||
JSON.stringify(
|
||||
Object.assign(JSON.parse(value), Object.assign(overrides, { private: undefined })),
|
||||
null,
|
||||
'\t'
|
||||
),
|
||||
'utf-8'
|
||||
)
|
||||
),
|
||||
};
|
||||
|
||||
export default async function copyTemplate(tmpl: string, ctx: Context) {
|
||||
const ref = ctx.ref || 'latest';
|
||||
const isThirdParty = tmpl.includes('/');
|
||||
|
||||
const templateTarget = isThirdParty
|
||||
? tmpl
|
||||
: `github:withastro/astro/examples/${tmpl}#${ref}`;
|
||||
const templateTarget = isThirdParty ? tmpl : `github:withastro/astro/examples/${tmpl}#${ref}`;
|
||||
|
||||
// Copy
|
||||
if (!ctx.dryRun) {
|
||||
|
@ -64,7 +74,7 @@ export default async function copyTemplate(tmpl: string, ctx: Context) {
|
|||
provider: 'github',
|
||||
cwd: ctx.cwd,
|
||||
dir: '.',
|
||||
})
|
||||
});
|
||||
} catch (err: any) {
|
||||
fs.rmdirSync(ctx.cwd);
|
||||
if (err.message.includes('404')) {
|
||||
|
@ -85,9 +95,9 @@ export default async function copyTemplate(tmpl: string, ctx: Context) {
|
|||
const updateFiles = Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => {
|
||||
const fileLoc = path.resolve(path.join(ctx.cwd, file));
|
||||
if (fs.existsSync(fileLoc)) {
|
||||
return update(fileLoc, { name: ctx.projectName! })
|
||||
return update(fileLoc, { name: ctx.projectName! });
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
await Promise.all([...removeFiles, ...updateFiles]);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import type { Context } from "./context";
|
||||
import type { Context } from './context';
|
||||
|
||||
import fs from 'node:fs'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { color } from '@astrojs/cli-kit';
|
||||
import fs from 'node:fs';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import stripJsonComments from 'strip-json-comments';
|
||||
import { color } from '@astrojs/cli-kit';
|
||||
import { title, info, error, typescriptByDefault, spinner } from '../messages.js';
|
||||
import { error, info, spinner, title, typescriptByDefault } from '../messages.js';
|
||||
|
||||
export async function typescript(ctx: Pick<Context, 'typescript'|'yes'|'prompt'|'dryRun'|'cwd'|'exit'>) {
|
||||
export async function typescript(
|
||||
ctx: Pick<Context, 'typescript' | 'yes' | 'prompt' | 'dryRun' | 'cwd' | 'exit'>
|
||||
) {
|
||||
let ts = ctx.typescript ?? (typeof ctx.yes !== 'undefined' ? 'strict' : undefined);
|
||||
if (ts === undefined) {
|
||||
const { useTs } = await ctx.prompt({
|
||||
|
@ -68,7 +70,7 @@ export async function typescript(ctx: Pick<Context, 'typescript'|'yes'|'prompt'|
|
|||
export async function setupTypeScript(value: string, { cwd }: { cwd: string }) {
|
||||
const templateTSConfigPath = path.join(cwd, 'tsconfig.json');
|
||||
try {
|
||||
const data = await readFile(templateTSConfigPath, { encoding: 'utf-8' })
|
||||
const data = await readFile(templateTSConfigPath, { encoding: 'utf-8' });
|
||||
const templateTSConfig = JSON.parse(stripJsonComments(data));
|
||||
if (templateTSConfig && typeof templateTSConfig === 'object') {
|
||||
const result = Object.assign(templateTSConfig, {
|
||||
|
@ -77,7 +79,9 @@ export async function setupTypeScript(value: string, { cwd }: { cwd: string }) {
|
|||
|
||||
fs.writeFileSync(templateTSConfigPath, JSON.stringify(result, null, 2));
|
||||
} else {
|
||||
throw new Error("There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed")
|
||||
throw new Error(
|
||||
"There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed"
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err && (err as any).code === 'ENOENT') {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { getContext } from './actions/context.js';
|
||||
|
||||
import { setStdout } from './messages.js';
|
||||
import { help } from './actions/help.js';
|
||||
import { intro } from './actions/intro.js';
|
||||
import { projectName } from './actions/project-name.js';
|
||||
import { template } from './actions/template.js'
|
||||
import { dependencies } from './actions/dependencies.js';
|
||||
import { git } from './actions/git.js';
|
||||
import { typescript, setupTypeScript } from './actions/typescript.js';
|
||||
import { help } from './actions/help.js';
|
||||
import { intro } from './actions/intro.js';
|
||||
import { next } from './actions/next-steps.js';
|
||||
import { projectName } from './actions/project-name.js';
|
||||
import { template } from './actions/template.js';
|
||||
import { setupTypeScript, typescript } from './actions/typescript.js';
|
||||
import { setStdout } from './messages.js';
|
||||
|
||||
const exit = () => process.exit(0)
|
||||
process.on('SIGINT', exit)
|
||||
process.on('SIGTERM', exit)
|
||||
const exit = () => process.exit(0);
|
||||
process.on('SIGINT', exit);
|
||||
process.on('SIGTERM', exit);
|
||||
|
||||
// Please also update the installation instructions in the docs at
|
||||
// https://github.com/withastro/docs/blob/main/src/pages/en/install/auto.md
|
||||
|
@ -29,18 +29,10 @@ export async function main() {
|
|||
return;
|
||||
}
|
||||
|
||||
const steps = [
|
||||
intro,
|
||||
projectName,
|
||||
template,
|
||||
dependencies,
|
||||
git,
|
||||
typescript,
|
||||
next
|
||||
]
|
||||
const steps = [intro, projectName, template, dependencies, git, typescript, next];
|
||||
|
||||
for (const step of steps) {
|
||||
await step(ctx)
|
||||
await step(ctx);
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
@ -55,5 +47,5 @@ export {
|
|||
git,
|
||||
typescript,
|
||||
setupTypeScript,
|
||||
next
|
||||
}
|
||||
next,
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint no-console: 'off' */
|
||||
import { color, label, say as houston, spinner as load } from '@astrojs/cli-kit';
|
||||
import { align, sleep } from '@astrojs/cli-kit/utils';
|
||||
import { exec } from 'node:child_process';
|
||||
import { get } from 'node:https';
|
||||
import { color, label, spinner as load, say as houston } from '@astrojs/cli-kit';
|
||||
import { sleep, align } from '@astrojs/cli-kit/utils';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
|
||||
let stdout = process.stdout;
|
||||
|
@ -11,113 +11,136 @@ export function setStdout(writable: typeof process.stdout) {
|
|||
stdout = writable;
|
||||
}
|
||||
|
||||
export async function say(messages: string|string[], { clear = false, hat = '' } = {}) {
|
||||
export async function say(messages: string | string[], { clear = false, hat = '' } = {}) {
|
||||
return houston(messages, { clear, hat, stdout });
|
||||
}
|
||||
|
||||
export async function spinner(args: { start: string; end: string; while: (...args: any) => Promise<any>; }) {
|
||||
export async function spinner(args: {
|
||||
start: string;
|
||||
end: string;
|
||||
while: (...args: any) => Promise<any>;
|
||||
}) {
|
||||
await load(args, { stdout });
|
||||
}
|
||||
|
||||
export const title = (text: string) => align(label(text), 'end', 7) + ' ';
|
||||
|
||||
export const welcome = [
|
||||
`Let's claim your corner of the internet.`,
|
||||
`I'll be your assistant today.`,
|
||||
`Let's build something awesome!`,
|
||||
`Let's build something great!`,
|
||||
`Let's build something fast!`,
|
||||
`Let's build the web we want.`,
|
||||
`Let's make the web weird!`,
|
||||
`Let's make the web a better place!`,
|
||||
`Let's create a new project!`,
|
||||
`Let's create something unique!`,
|
||||
`Time to build a new website.`,
|
||||
`Time to build a faster website.`,
|
||||
`Time to build a sweet new website.`,
|
||||
`We're glad to have you on board.`,
|
||||
`Keeping the internet weird since 2021.`,
|
||||
`Initiating launch sequence...`,
|
||||
`Initiating launch sequence... right... now!`,
|
||||
`Awaiting further instructions.`,
|
||||
]
|
||||
`Let's claim your corner of the internet.`,
|
||||
`I'll be your assistant today.`,
|
||||
`Let's build something awesome!`,
|
||||
`Let's build something great!`,
|
||||
`Let's build something fast!`,
|
||||
`Let's build the web we want.`,
|
||||
`Let's make the web weird!`,
|
||||
`Let's make the web a better place!`,
|
||||
`Let's create a new project!`,
|
||||
`Let's create something unique!`,
|
||||
`Time to build a new website.`,
|
||||
`Time to build a faster website.`,
|
||||
`Time to build a sweet new website.`,
|
||||
`We're glad to have you on board.`,
|
||||
`Keeping the internet weird since 2021.`,
|
||||
`Initiating launch sequence...`,
|
||||
`Initiating launch sequence... right... now!`,
|
||||
`Awaiting further instructions.`,
|
||||
];
|
||||
|
||||
export const getName = () => new Promise<string>((resolve) => {
|
||||
exec('git config user.name', { encoding: 'utf-8' }, (_1, gitName, _2) => {
|
||||
if (gitName.trim()) {
|
||||
return resolve(gitName.split(' ')[0].trim());
|
||||
}
|
||||
exec('whoami', { encoding: 'utf-8' }, (_3, whoami, _4) => {
|
||||
if (whoami.trim()) {
|
||||
return resolve(whoami.split(' ')[0].trim());
|
||||
}
|
||||
return resolve('astronaut');
|
||||
});
|
||||
});
|
||||
});
|
||||
export const getName = () =>
|
||||
new Promise<string>((resolve) => {
|
||||
exec('git config user.name', { encoding: 'utf-8' }, (_1, gitName, _2) => {
|
||||
if (gitName.trim()) {
|
||||
return resolve(gitName.split(' ')[0].trim());
|
||||
}
|
||||
exec('whoami', { encoding: 'utf-8' }, (_3, whoami, _4) => {
|
||||
if (whoami.trim()) {
|
||||
return resolve(whoami.split(' ')[0].trim());
|
||||
}
|
||||
return resolve('astronaut');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let v: string;
|
||||
export const getVersion = () => new Promise<string>((resolve) => {
|
||||
if (v) return resolve(v);
|
||||
get('https://registry.npmjs.org/astro/latest', (res) => {
|
||||
let body = '';
|
||||
res.on('data', chunk => body += chunk)
|
||||
res.on('end', () => {
|
||||
const { version } = JSON.parse(body);
|
||||
v = version;
|
||||
resolve(version);
|
||||
})
|
||||
})
|
||||
})
|
||||
export const getVersion = () =>
|
||||
new Promise<string>((resolve) => {
|
||||
if (v) return resolve(v);
|
||||
get('https://registry.npmjs.org/astro/latest', (res) => {
|
||||
let body = '';
|
||||
res.on('data', (chunk) => (body += chunk));
|
||||
res.on('end', () => {
|
||||
const { version } = JSON.parse(body);
|
||||
v = version;
|
||||
resolve(version);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export const log = (message: string) => stdout.write(message + "\n");
|
||||
export const banner = async (version: string) => log(`\n${label('astro', color.bgGreen, color.black)} ${color.green(color.bold(`v${version}`))} ${color.bold('Launch sequence initiated.')}`);
|
||||
export const log = (message: string) => stdout.write(message + '\n');
|
||||
export const banner = async (version: string) =>
|
||||
log(
|
||||
`\n${label('astro', color.bgGreen, color.black)} ${color.green(
|
||||
color.bold(`v${version}`)
|
||||
)} ${color.bold('Launch sequence initiated.')}`
|
||||
);
|
||||
|
||||
export const info = async (prefix: string, text: string) => {
|
||||
await sleep(100)
|
||||
if (stdout.columns < 80) {
|
||||
log(`${' '.repeat(5)} ${color.cyan('◼')} ${color.cyan(prefix)}`);
|
||||
log(`${' '.repeat(9)}${color.dim(text)}`);
|
||||
} else {
|
||||
log(`${' '.repeat(5)} ${color.cyan('◼')} ${color.cyan(prefix)} ${color.dim(text)}`);
|
||||
}
|
||||
}
|
||||
await sleep(100);
|
||||
if (stdout.columns < 80) {
|
||||
log(`${' '.repeat(5)} ${color.cyan('◼')} ${color.cyan(prefix)}`);
|
||||
log(`${' '.repeat(9)}${color.dim(text)}`);
|
||||
} else {
|
||||
log(`${' '.repeat(5)} ${color.cyan('◼')} ${color.cyan(prefix)} ${color.dim(text)}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const error = async (prefix: string, text: string) => {
|
||||
if (stdout.columns < 80) {
|
||||
log(`${' '.repeat(5)} ${color.red('▲')} ${color.red(prefix)}`);
|
||||
log(`${' '.repeat(9)}${color.dim(text)}`);
|
||||
} else {
|
||||
log(`${' '.repeat(5)} ${color.red('▲')} ${color.red(prefix)} ${color.dim(text)}`);
|
||||
}
|
||||
}
|
||||
if (stdout.columns < 80) {
|
||||
log(`${' '.repeat(5)} ${color.red('▲')} ${color.red(prefix)}`);
|
||||
log(`${' '.repeat(9)}${color.dim(text)}`);
|
||||
} else {
|
||||
log(`${' '.repeat(5)} ${color.red('▲')} ${color.red(prefix)} ${color.dim(text)}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const typescriptByDefault = async () => {
|
||||
await info(`No worries!`, 'TypeScript is supported in Astro by default,');
|
||||
log(`${' '.repeat(9)}${color.dim('but you are free to continue writing JavaScript instead.')}`);
|
||||
await sleep(1000);
|
||||
}
|
||||
await info(`No worries!`, 'TypeScript is supported in Astro by default,');
|
||||
log(`${' '.repeat(9)}${color.dim('but you are free to continue writing JavaScript instead.')}`);
|
||||
await sleep(1000);
|
||||
};
|
||||
|
||||
export const nextSteps = async ({ projectDir, devCmd }: { projectDir: string, devCmd: string }) => {
|
||||
const max = stdout.columns;
|
||||
const prefix = max < 80 ? ' ' : ' '.repeat(9);
|
||||
await sleep(200);
|
||||
log(`\n ${color.bgCyan(` ${color.black('next')} `)} ${color.bold('Liftoff confirmed. Explore your project!')}`)
|
||||
|
||||
await sleep(100);
|
||||
if (projectDir !== '') {
|
||||
const enter = [`\n${prefix}Enter your project directory using`, color.cyan(`cd ./${projectDir}`, '')];
|
||||
const len = enter[0].length + stripAnsi(enter[1]).length;
|
||||
log(enter.join((len > max) ? '\n' + prefix : ' '));
|
||||
}
|
||||
log(`${prefix}Run ${color.cyan(devCmd)} to start the dev server. ${color.cyan('CTRL+C')} to stop.`)
|
||||
await sleep(100);
|
||||
log(`${prefix}Add frameworks like ${color.cyan(`react`)} or ${color.cyan('tailwind')} using ${color.cyan('astro add')}.`)
|
||||
await sleep(100);
|
||||
log(`\n${prefix}Stuck? Join us at ${color.cyan(`https://astro.build/chat`)}`)
|
||||
await sleep(200);
|
||||
}
|
||||
export const nextSteps = async ({ projectDir, devCmd }: { projectDir: string; devCmd: string }) => {
|
||||
const max = stdout.columns;
|
||||
const prefix = max < 80 ? ' ' : ' '.repeat(9);
|
||||
await sleep(200);
|
||||
log(
|
||||
`\n ${color.bgCyan(` ${color.black('next')} `)} ${color.bold(
|
||||
'Liftoff confirmed. Explore your project!'
|
||||
)}`
|
||||
);
|
||||
|
||||
await sleep(100);
|
||||
if (projectDir !== '') {
|
||||
const enter = [
|
||||
`\n${prefix}Enter your project directory using`,
|
||||
color.cyan(`cd ./${projectDir}`, ''),
|
||||
];
|
||||
const len = enter[0].length + stripAnsi(enter[1]).length;
|
||||
log(enter.join(len > max ? '\n' + prefix : ' '));
|
||||
}
|
||||
log(
|
||||
`${prefix}Run ${color.cyan(devCmd)} to start the dev server. ${color.cyan('CTRL+C')} to stop.`
|
||||
);
|
||||
await sleep(100);
|
||||
log(
|
||||
`${prefix}Add frameworks like ${color.cyan(`react`)} or ${color.cyan(
|
||||
'tailwind'
|
||||
)} using ${color.cyan('astro add')}.`
|
||||
);
|
||||
await sleep(100);
|
||||
log(`\n${prefix}Stuck? Join us at ${color.cyan(`https://astro.build/chat`)}`);
|
||||
await sleep(200);
|
||||
};
|
||||
|
||||
export function printHelp({
|
||||
commandName,
|
||||
|
@ -154,9 +177,7 @@ export function printHelp({
|
|||
if (headline) {
|
||||
message.push(
|
||||
linebreak(),
|
||||
`${title(commandName)} ${color.green(
|
||||
`v${process.env.PACKAGE_VERSION ?? ''}`
|
||||
)} ${headline}`
|
||||
`${title(commandName)} ${color.green(`v${process.env.PACKAGE_VERSION ?? ''}`)} ${headline}`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,53 +10,53 @@ describe('context', () => {
|
|||
expect(ctx.template).to.be.undefined;
|
||||
expect(ctx.skipHouston).to.eq(os.platform() === 'win32');
|
||||
expect(ctx.dryRun).to.be.undefined;
|
||||
})
|
||||
});
|
||||
it('project name', async () => {
|
||||
const ctx = await getContext(['foobar']);
|
||||
expect(ctx.projectName).to.eq('foobar');
|
||||
})
|
||||
});
|
||||
it('template', async () => {
|
||||
const ctx = await getContext(['--template', 'minimal']);
|
||||
expect(ctx.template).to.eq('minimal');
|
||||
})
|
||||
});
|
||||
it('skip houston (explicit)', async () => {
|
||||
const ctx = await getContext(['--skip-houston']);
|
||||
expect(ctx.skipHouston).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('skip houston (yes)', async () => {
|
||||
const ctx = await getContext(['-y']);
|
||||
expect(ctx.skipHouston).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('skip houston (no)', async () => {
|
||||
const ctx = await getContext(['-n']);
|
||||
expect(ctx.skipHouston).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('skip houston (install)', async () => {
|
||||
const ctx = await getContext(['--install']);
|
||||
expect(ctx.skipHouston).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('dry run', async () => {
|
||||
const ctx = await getContext(['--dry-run']);
|
||||
expect(ctx.dryRun).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('install', async () => {
|
||||
const ctx = await getContext(['--install']);
|
||||
expect(ctx.install).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('no install', async () => {
|
||||
const ctx = await getContext(['--no-install']);
|
||||
expect(ctx.install).to.eq(false);
|
||||
})
|
||||
});
|
||||
it('git', async () => {
|
||||
const ctx = await getContext(['--git']);
|
||||
expect(ctx.git).to.eq(true);
|
||||
})
|
||||
});
|
||||
it('no git', async () => {
|
||||
const ctx = await getContext(['--no-git']);
|
||||
expect(ctx.git).to.eq(false);
|
||||
})
|
||||
});
|
||||
it('typescript', async () => {
|
||||
const ctx = await getContext(['--typescript', 'strict']);
|
||||
expect(ctx.typescript).to.eq('strict');
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,36 +7,66 @@ describe('dependencies', () => {
|
|||
const fixture = setup();
|
||||
|
||||
it('--yes', async () => {
|
||||
const context = { cwd: '', yes: true, pkgManager: 'npm', dryRun: true, prompt: (() => ({ deps: true }))};
|
||||
const context = {
|
||||
cwd: '',
|
||||
yes: true,
|
||||
pkgManager: 'npm',
|
||||
dryRun: true,
|
||||
prompt: () => ({ deps: true }),
|
||||
};
|
||||
await dependencies(context);
|
||||
expect(fixture.hasMessage('Skipping dependency installation')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('prompt yes', async () => {
|
||||
const context = { cwd: '', pkgManager: 'npm', dryRun: true, prompt: (() => ({ deps: true })), install: undefined };
|
||||
const context = {
|
||||
cwd: '',
|
||||
pkgManager: 'npm',
|
||||
dryRun: true,
|
||||
prompt: () => ({ deps: true }),
|
||||
install: undefined,
|
||||
};
|
||||
await dependencies(context);
|
||||
expect(fixture.hasMessage('Skipping dependency installation')).to.be.true;
|
||||
expect(context.install).to.eq(true);
|
||||
})
|
||||
});
|
||||
|
||||
it('prompt no', async () => {
|
||||
const context = { cwd: '', pkgManager: 'npm', dryRun: true, prompt: (() => ({ deps: false })), install: undefined };
|
||||
const context = {
|
||||
cwd: '',
|
||||
pkgManager: 'npm',
|
||||
dryRun: true,
|
||||
prompt: () => ({ deps: false }),
|
||||
install: undefined,
|
||||
};
|
||||
await dependencies(context);
|
||||
expect(fixture.hasMessage('Skipping dependency installation')).to.be.true;
|
||||
expect(context.install).to.eq(false);
|
||||
})
|
||||
});
|
||||
|
||||
it('--install', async () => {
|
||||
const context = { cwd: '', install: true, pkgManager: 'npm', dryRun: true, prompt: (() => ({ deps: false })) };
|
||||
const context = {
|
||||
cwd: '',
|
||||
install: true,
|
||||
pkgManager: 'npm',
|
||||
dryRun: true,
|
||||
prompt: () => ({ deps: false }),
|
||||
};
|
||||
await dependencies(context);
|
||||
expect(fixture.hasMessage('Skipping dependency installation')).to.be.true;
|
||||
expect(context.install).to.eq(true);
|
||||
})
|
||||
});
|
||||
|
||||
it('--no-install', async () => {
|
||||
const context = { cwd: '', install: false, pkgManager: 'npm', dryRun: true, prompt: (() => ({ deps: false })) };
|
||||
const context = {
|
||||
cwd: '',
|
||||
install: false,
|
||||
pkgManager: 'npm',
|
||||
dryRun: true,
|
||||
prompt: () => ({ deps: false }),
|
||||
};
|
||||
await dependencies(context);
|
||||
expect(fixture.hasMessage('Skipping dependency installation')).to.be.true;
|
||||
expect(context.install).to.eq(false);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,14 +10,19 @@ describe('git', () => {
|
|||
const fixture = setup();
|
||||
|
||||
it('none', async () => {
|
||||
const context = { cwd: '', dryRun: true, prompt: (() => ({ git: false }))};
|
||||
const context = { cwd: '', dryRun: true, prompt: () => ({ git: false }) };
|
||||
await git(context);
|
||||
|
||||
expect(fixture.hasMessage('Skipping Git initialization')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('already initialized', async () => {
|
||||
const context = { git: true, cwd: './test/fixtures/not-empty', dryRun: true, prompt: (() => ({ git: false }))};
|
||||
const context = {
|
||||
git: true,
|
||||
cwd: './test/fixtures/not-empty',
|
||||
dryRun: true,
|
||||
prompt: () => ({ git: false }),
|
||||
};
|
||||
await execa('git', ['init'], { cwd: './test/fixtures/not-empty' });
|
||||
await git(context);
|
||||
|
||||
|
@ -25,19 +30,19 @@ describe('git', () => {
|
|||
|
||||
// Cleanup
|
||||
fs.rmSync('./test/fixtures/not-empty/.git', { recursive: true, force: true });
|
||||
})
|
||||
});
|
||||
|
||||
it('yes (--dry-run)', async () => {
|
||||
const context = { cwd: '', dryRun: true, prompt: (() => ({ git: true }))};
|
||||
const context = { cwd: '', dryRun: true, prompt: () => ({ git: true }) };
|
||||
await git(context);
|
||||
|
||||
expect(fixture.hasMessage('Skipping Git initialization')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('no (--dry-run)', async () => {
|
||||
const context = { cwd: '', dryRun: true, prompt: (() => ({ git: false }))};
|
||||
const context = { cwd: '', dryRun: true, prompt: () => ({ git: false }) };
|
||||
await git(context);
|
||||
|
||||
expect(fixture.hasMessage('Skipping Git initialization')).to.be.true;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,11 +10,11 @@ describe('intro', () => {
|
|||
await intro({ skipHouston: false, version: '0.0.0', username: 'user' });
|
||||
expect(fixture.hasMessage('Houston:')).to.be.true;
|
||||
expect(fixture.hasMessage('Welcome to astro v0.0.0')).to.be.true;
|
||||
})
|
||||
});
|
||||
it('--skip-houston', async () => {
|
||||
await intro({ skipHouston: true, version: '0.0.0', username: 'user' });
|
||||
expect(fixture.length()).to.eq(1);
|
||||
expect(fixture.hasMessage('Houston:')).to.be.false;
|
||||
expect(fixture.hasMessage('Launch sequence initiated')).to.be.true;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,10 +11,10 @@ describe('next steps', () => {
|
|||
expect(fixture.hasMessage('Liftoff confirmed.')).to.be.true;
|
||||
expect(fixture.hasMessage('npm run dev')).to.be.true;
|
||||
expect(fixture.hasMessage('Good luck out there, astronaut!')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('--skip-houston', async () => {
|
||||
await next({ skipHouston: true, cwd: './it/fixtures/not-empty', pkgManager: 'npm' });
|
||||
expect(fixture.hasMessage('Good luck out there, astronaut!')).to.be.false;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,73 +7,81 @@ describe('project name', () => {
|
|||
const fixture = setup();
|
||||
|
||||
it('pass in name', async () => {
|
||||
const context = { projectName: '', cwd: './foo/bar/baz', prompt: (() => {})};
|
||||
const context = { projectName: '', cwd: './foo/bar/baz', prompt: () => {} };
|
||||
await projectName(context);
|
||||
|
||||
expect(context.cwd).to.eq('./foo/bar/baz');
|
||||
expect(context.projectName).to.eq('baz');
|
||||
})
|
||||
});
|
||||
|
||||
it('dot', async () => {
|
||||
const context = { projectName: '', cwd: '.', prompt: (() => ({ name: 'foobar' }))};
|
||||
const context = { projectName: '', cwd: '.', prompt: () => ({ name: 'foobar' }) };
|
||||
await projectName(context);
|
||||
|
||||
expect(fixture.hasMessage('"." is not empty!')).to.be.true;
|
||||
expect(context.projectName).to.eq('foobar');
|
||||
})
|
||||
});
|
||||
|
||||
it('dot slash', async () => {
|
||||
const context = { projectName: '', cwd: './', prompt: (() => ({ name: 'foobar' }))};
|
||||
const context = { projectName: '', cwd: './', prompt: () => ({ name: 'foobar' }) };
|
||||
await projectName(context);
|
||||
|
||||
expect(fixture.hasMessage('"./" is not empty!')).to.be.true;
|
||||
expect(context.projectName).to.eq('foobar');
|
||||
})
|
||||
});
|
||||
|
||||
it('empty', async () => {
|
||||
const context = { projectName: '', cwd: './test/fixtures/empty', prompt: (() => ({ name: 'foobar' }))};
|
||||
const context = {
|
||||
projectName: '',
|
||||
cwd: './test/fixtures/empty',
|
||||
prompt: () => ({ name: 'foobar' }),
|
||||
};
|
||||
await projectName(context);
|
||||
|
||||
expect(fixture.hasMessage('"./test/fixtures/empty" is not empty!')).to.be.false;
|
||||
expect(context.projectName).to.eq('empty');
|
||||
})
|
||||
});
|
||||
|
||||
it('not empty', async () => {
|
||||
const context = { projectName: '', cwd: './test/fixtures/not-empty', prompt: (() => ({ name: 'foobar' }))};
|
||||
const context = {
|
||||
projectName: '',
|
||||
cwd: './test/fixtures/not-empty',
|
||||
prompt: () => ({ name: 'foobar' }),
|
||||
};
|
||||
await projectName(context);
|
||||
|
||||
expect(fixture.hasMessage('"./test/fixtures/not-empty" is not empty!')).to.be.true;
|
||||
expect(context.projectName).to.eq('foobar');
|
||||
})
|
||||
});
|
||||
|
||||
it('basic', async () => {
|
||||
const context = { projectName: '', cwd: '', prompt: (() => ({ name: 'foobar' }))};
|
||||
const context = { projectName: '', cwd: '', prompt: () => ({ name: 'foobar' }) };
|
||||
await projectName(context);
|
||||
|
||||
expect(context.cwd).to.eq('foobar');
|
||||
expect(context.projectName).to.eq('foobar');
|
||||
})
|
||||
});
|
||||
|
||||
it('normalize', async () => {
|
||||
const context = { projectName: '', cwd: '', prompt: (() => ({ name: 'Invalid Name' }))};
|
||||
const context = { projectName: '', cwd: '', prompt: () => ({ name: 'Invalid Name' }) };
|
||||
await projectName(context);
|
||||
|
||||
expect(context.cwd).to.eq('Invalid Name');
|
||||
expect(context.projectName).to.eq('invalid-name');
|
||||
})
|
||||
});
|
||||
|
||||
it('remove leading/trailing dashes', async () => {
|
||||
const context = { projectName: '', cwd: '', prompt: (() => ({ name: '(invalid)' }))};
|
||||
const context = { projectName: '', cwd: '', prompt: () => ({ name: '(invalid)' }) };
|
||||
await projectName(context);
|
||||
|
||||
expect(context.projectName).to.eq('invalid');
|
||||
})
|
||||
});
|
||||
|
||||
it('handles scoped packages', async () => {
|
||||
const context = { projectName: '', cwd: '', prompt: (() => ({ name: '@astro/site' }))};
|
||||
const context = { projectName: '', cwd: '', prompt: () => ({ name: '@astro/site' }) };
|
||||
await projectName(context);
|
||||
|
||||
expect(context.cwd).to.eq('@astro/site');
|
||||
expect(context.projectName).to.eq('@astro/site');
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,30 +7,30 @@ describe('template', () => {
|
|||
const fixture = setup();
|
||||
|
||||
it('none', async () => {
|
||||
const context = { template: '', cwd: '', dryRun: true, prompt: (() => ({ template: 'blog' })) };
|
||||
const context = { template: '', cwd: '', dryRun: true, prompt: () => ({ template: 'blog' }) };
|
||||
await template(context);
|
||||
|
||||
expect(fixture.hasMessage('Skipping template copying')).to.be.true;
|
||||
expect(context.template).to.eq('blog');
|
||||
})
|
||||
});
|
||||
|
||||
it('minimal (--dry-run)', async () => {
|
||||
const context = { template: 'minimal', cwd: '', dryRun: true, prompt: (() => {})};
|
||||
const context = { template: 'minimal', cwd: '', dryRun: true, prompt: () => {} };
|
||||
await template(context);
|
||||
expect(fixture.hasMessage('Using minimal as project template')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('basics (--dry-run)', async () => {
|
||||
const context = { template: 'basics', cwd: '', dryRun: true, prompt: (() => {})};
|
||||
const context = { template: 'basics', cwd: '', dryRun: true, prompt: () => {} };
|
||||
await template(context);
|
||||
|
||||
expect(fixture.hasMessage('Using basics as project template')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('blog (--dry-run)', async () => {
|
||||
const context = { template: 'blog', cwd: '', dryRun: true, prompt: (() => {})};
|
||||
const context = { template: 'blog', cwd: '', dryRun: true, prompt: () => {} };
|
||||
await template(context);
|
||||
|
||||
expect(fixture.hasMessage('Using blog as project template')).to.be.true;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect } from 'chai';
|
||||
|
||||
import fs from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { typescript, setupTypeScript } from '../dist/index.js';
|
||||
import { setup } from './utils.js';
|
||||
|
@ -10,70 +10,97 @@ describe('typescript', () => {
|
|||
const fixture = setup();
|
||||
|
||||
it('none', async () => {
|
||||
const context = { cwd: '', dryRun: true, prompt: (() => ({ ts: 'strict', useTs: true }))};
|
||||
const context = { cwd: '', dryRun: true, prompt: () => ({ ts: 'strict', useTs: true }) };
|
||||
await typescript(context);
|
||||
|
||||
|
||||
expect(fixture.hasMessage('Skipping TypeScript setup')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('use false', async () => {
|
||||
const context = { cwd: '', dryRun: true, prompt: (() => ({ ts: 'strict', useTs: false }))};
|
||||
const context = { cwd: '', dryRun: true, prompt: () => ({ ts: 'strict', useTs: false }) };
|
||||
await typescript(context);
|
||||
|
||||
expect(fixture.hasMessage('No worries')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('strict', async () => {
|
||||
const context = { typescript: 'strict', cwd: '', dryRun: true, prompt: (() => ({ ts: 'strict' }))};
|
||||
const context = {
|
||||
typescript: 'strict',
|
||||
cwd: '',
|
||||
dryRun: true,
|
||||
prompt: () => ({ ts: 'strict' }),
|
||||
};
|
||||
await typescript(context);
|
||||
|
||||
expect(fixture.hasMessage('Using strict TypeScript configuration')).to.be.true;
|
||||
expect(fixture.hasMessage('Skipping TypeScript setup')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('default', async () => {
|
||||
const context = { typescript: 'default', cwd: '', dryRun: true, prompt: (() => ({ ts: 'strict' }))};
|
||||
const context = {
|
||||
typescript: 'default',
|
||||
cwd: '',
|
||||
dryRun: true,
|
||||
prompt: () => ({ ts: 'strict' }),
|
||||
};
|
||||
await typescript(context);
|
||||
|
||||
expect(fixture.hasMessage('Using default TypeScript configuration')).to.be.true;
|
||||
expect(fixture.hasMessage('Skipping TypeScript setup')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('relaxed', async () => {
|
||||
const context = { typescript: 'relaxed', cwd: '', dryRun: true, prompt: (() => ({ ts: 'strict' }))};
|
||||
const context = {
|
||||
typescript: 'relaxed',
|
||||
cwd: '',
|
||||
dryRun: true,
|
||||
prompt: () => ({ ts: 'strict' }),
|
||||
};
|
||||
await typescript(context);
|
||||
|
||||
expect(fixture.hasMessage('Using relaxed TypeScript configuration')).to.be.true;
|
||||
expect(fixture.hasMessage('Skipping TypeScript setup')).to.be.true;
|
||||
})
|
||||
});
|
||||
|
||||
it('other', async () => {
|
||||
const context = { typescript: 'other', cwd: '', dryRun: true, prompt: (() => ({ ts: 'strict' })), exit(code) { throw code }};
|
||||
const context = {
|
||||
typescript: 'other',
|
||||
cwd: '',
|
||||
dryRun: true,
|
||||
prompt: () => ({ ts: 'strict' }),
|
||||
exit(code) {
|
||||
throw code;
|
||||
},
|
||||
};
|
||||
let err = null;
|
||||
try {
|
||||
await typescript(context);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
expect(err).to.eq(1)
|
||||
})
|
||||
})
|
||||
expect(err).to.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('typescript: setup', () => {
|
||||
it('none', async () => {
|
||||
const root = new URL('./fixtures/empty/', import.meta.url);
|
||||
const tsconfig = new URL('./tsconfig.json', root);
|
||||
|
||||
await setupTypeScript('strict', { cwd: fileURLToPath(root) })
|
||||
expect(JSON.parse(fs.readFileSync(tsconfig, { encoding: 'utf-8' }))).to.deep.eq({ "extends": "astro/tsconfigs/strict" });
|
||||
await setupTypeScript('strict', { cwd: fileURLToPath(root) });
|
||||
expect(JSON.parse(fs.readFileSync(tsconfig, { encoding: 'utf-8' }))).to.deep.eq({
|
||||
extends: 'astro/tsconfigs/strict',
|
||||
});
|
||||
fs.rmSync(tsconfig);
|
||||
})
|
||||
});
|
||||
|
||||
it('exists', async () => {
|
||||
const root = new URL('./fixtures/not-empty/', import.meta.url);
|
||||
const tsconfig = new URL('./tsconfig.json', root);
|
||||
await setupTypeScript('strict', { cwd: fileURLToPath(root) })
|
||||
expect(JSON.parse(fs.readFileSync(tsconfig, { encoding: 'utf-8' }))).to.deep.eq({ "extends": "astro/tsconfigs/strict" });
|
||||
await setupTypeScript('strict', { cwd: fileURLToPath(root) });
|
||||
expect(JSON.parse(fs.readFileSync(tsconfig, { encoding: 'utf-8' }))).to.deep.eq({
|
||||
extends: 'astro/tsconfigs/strict',
|
||||
});
|
||||
fs.writeFileSync(tsconfig, `{}`);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,26 +4,28 @@ import stripAnsi from 'strip-ansi';
|
|||
export function setup() {
|
||||
const ctx = { messages: [] };
|
||||
before(() => {
|
||||
setStdout(Object.assign({}, process.stdout, {
|
||||
write(buf) {
|
||||
ctx.messages.push(stripAnsi(String(buf)).trim())
|
||||
return true;
|
||||
}
|
||||
}))
|
||||
setStdout(
|
||||
Object.assign({}, process.stdout, {
|
||||
write(buf) {
|
||||
ctx.messages.push(stripAnsi(String(buf)).trim());
|
||||
return true;
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
beforeEach(() => {
|
||||
ctx.messages = [];
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
messages() {
|
||||
return ctx.messages
|
||||
return ctx.messages;
|
||||
},
|
||||
length() {
|
||||
return ctx.messages.length
|
||||
return ctx.messages.length;
|
||||
},
|
||||
hasMessage(content) {
|
||||
return !!ctx.messages.find(msg => msg.includes(content))
|
||||
}
|
||||
return !!ctx.messages.find((msg) => msg.includes(content));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue