diff options
Diffstat (limited to 'packages/create-astro/src')
-rw-r--r-- | packages/create-astro/src/actions/typescript.ts | 105 |
1 files changed, 76 insertions, 29 deletions
diff --git a/packages/create-astro/src/actions/typescript.ts b/packages/create-astro/src/actions/typescript.ts index 97ae24303..1b6f5cc80 100644 --- a/packages/create-astro/src/actions/typescript.ts +++ b/packages/create-astro/src/actions/typescript.ts @@ -1,15 +1,18 @@ import type { Context } from './context.js'; import { color } from '@astrojs/cli-kit'; -import fs from 'node:fs'; -import { readFile } from 'node:fs/promises'; +import { readFile, writeFile, rm } from 'node:fs/promises'; import path from 'node:path'; import stripJsonComments from 'strip-json-comments'; import { error, info, spinner, title, typescriptByDefault } from '../messages.js'; +import { shell } from '../shell.js'; -export async function typescript( - ctx: Pick<Context, 'typescript' | 'yes' | 'prompt' | 'dryRun' | 'cwd' | 'exit'> -) { +type PickedTypeScriptContext = Pick< + Context, + 'typescript' | 'yes' | 'prompt' | 'dryRun' | 'cwd' | 'exit' | 'packageManager' | 'install' +>; + +export async function typescript(ctx: PickedTypeScriptContext) { let ts = ctx.typescript ?? (typeof ctx.yes !== 'undefined' ? 'strict' : undefined); if (ts === undefined) { const { useTs } = await ctx.prompt({ @@ -39,7 +42,7 @@ export async function typescript( } else { if (!['strict', 'strictest', 'relaxed', 'default', 'base'].includes(ts)) { if (!ctx.dryRun) { - fs.rmSync(ctx.cwd, { recursive: true, force: true }); + await rm(ctx.cwd, { recursive: true, force: true }); } error( 'Error', @@ -62,7 +65,7 @@ export async function typescript( start: 'TypeScript customizing...', end: 'TypeScript customized', while: () => - setupTypeScript(ts!, { cwd: ctx.cwd }).catch((e) => { + setupTypeScript(ts!, ctx).catch((e) => { error('error', e); process.exit(1); }), @@ -71,29 +74,73 @@ export async function typescript( } } -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 templateTSConfig = JSON.parse(stripJsonComments(data)); - if (templateTSConfig && typeof templateTSConfig === 'object') { - const result = Object.assign(templateTSConfig, { - extends: `astro/tsconfigs/${value}`, - }); +const FILES_TO_UPDATE = { + 'package.json': async ( + file: string, + options: { value: string; ctx: PickedTypeScriptContext } + ) => { + try { + // add required dependencies for astro check + if (options.ctx.install) + await shell(options.ctx.packageManager, ['install', '@astrojs/check', 'typescript'], { + cwd: path.dirname(file), + stdio: 'ignore', + }); - 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" - ); + // inject addtional command to build script + const data = await readFile(file, { encoding: 'utf-8' }); + const indent = /(^\s+)/m.exec(data)?.[1] ?? '\t'; + const parsedPackageJson = JSON.parse(data); + + const buildScript = parsedPackageJson.scripts?.build; + + // in case of any other template already have astro checks defined, we don't want to override it + if (typeof buildScript === 'string' && !buildScript.includes('astro check')) { + const newPackageJson = Object.assign(parsedPackageJson, { + scripts: { + build: 'astro check && ' + buildScript, + }, + }); + + await writeFile(file, JSON.stringify(newPackageJson, null, indent), 'utf-8'); + } + } catch (err) { + // if there's no package.json (which is very unlikely), then do nothing + if (err && (err as any).code === 'ENOENT') return; + if (err instanceof Error) throw new Error(err.message); } - } catch (err) { - if (err && (err as any).code === 'ENOENT') { - // If the template doesn't have a tsconfig.json, let's add one instead - fs.writeFileSync( - templateTSConfigPath, - JSON.stringify({ extends: `astro/tsconfigs/${value}` }, null, 2) - ); + }, + 'tsconfig.json': async (file: string, options: { value: string }) => { + try { + const data = await readFile(file, { encoding: 'utf-8' }); + const templateTSConfig = JSON.parse(stripJsonComments(data)); + if (templateTSConfig && typeof templateTSConfig === 'object') { + const result = Object.assign(templateTSConfig, { + extends: `astro/tsconfigs/${options.value}`, + }); + + await writeFile(file, 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" + ); + } + } catch (err) { + if (err && (err as any).code === 'ENOENT') { + // If the template doesn't have a tsconfig.json, let's add one instead + await writeFile( + file, + JSON.stringify({ extends: `astro/tsconfigs/${options.value}` }, null, 2) + ); + } } - } + }, +}; + +export async function setupTypeScript(value: string, ctx: PickedTypeScriptContext) { + await Promise.all( + Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => + update(path.resolve(path.join(ctx.cwd, file)), { value, ctx }) + ) + ); } |