-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
create-astro
: always create tsconfig.json
#4810
Changes from all commits
b60b7b4
d402ea5
25aeb9b
534472c
d26485f
193b01e
1aa2189
bda52db
c054cef
3b36ad5
5b27c95
fbec5e5
fd17e9a
24a06ac
305576c
ddd9723
fe6ba76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
'create-astro': minor | ||
--- | ||
|
||
Alway write chosen config to `tsconfig.json`. | ||
|
||
- Before: Only when `strict` & `strictest` was selected | ||
- After: Also when `base` is selected (via "Relaxed" or "I prefer not to use TypeScript") | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -340,7 +340,7 @@ export async function main() { | |
choices: [ | ||
{ | ||
title: 'Relaxed', | ||
value: 'default', | ||
value: 'base', | ||
}, | ||
{ | ||
title: 'Strict (recommended)', | ||
|
@@ -379,42 +379,40 @@ export async function main() { | |
console.log(` You can safely ignore these files, but don't delete them!`); | ||
console.log(dim(' (ex: tsconfig.json, src/env.d.ts)')); | ||
console.log(``); | ||
tsResponse.typescript = 'default'; | ||
tsResponse.typescript = 'base'; | ||
await wait(300); | ||
} | ||
if (args.dryRun) { | ||
ora().info(dim(`--dry-run enabled, skipping.`)); | ||
} else if (tsResponse.typescript) { | ||
if (tsResponse.typescript !== 'default') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The diff GitHub is showing here is unnecessarily complex, the only differences from here down are:
|
||
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.typescript}` }, null, 2) | ||
); | ||
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.typescript}` }, null, 2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wonder if it's helpful linking to the docs for this in a comment as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a bad idea! I didn't change those lines (just dedented them), so doesn't necessarily need to be added in this PR, but might as well toss it in, feel free to add a commit for that. |
||
); | ||
|
||
return; | ||
} | ||
return; | ||
} | ||
|
||
const templateTSConfig = parse(data.toString()); | ||
const templateTSConfig = parse(data.toString()); | ||
|
||
if (templateTSConfig && typeof templateTSConfig === 'object') { | ||
const result = assign(templateTSConfig, { | ||
extends: `astro/tsconfigs/${tsResponse.typescript}`, | ||
}); | ||
if (templateTSConfig && typeof templateTSConfig === 'object') { | ||
const result = assign(templateTSConfig, { | ||
extends: `astro/tsconfigs/${tsResponse.typescript}`, | ||
}); | ||
|
||
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" | ||
) | ||
); | ||
} | ||
}); | ||
} | ||
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!'); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { expect } from 'chai'; | ||
import { deleteSync } from 'del'; | ||
import { existsSync, mkdirSync, readdirSync, readFileSync } from 'fs'; | ||
import path from 'path'; | ||
import { | ||
PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout | ||
} from './utils.js'; | ||
|
||
const inputs = { | ||
emptyDir: './fixtures/select-typescript/empty-dir', | ||
}; | ||
|
||
function isEmpty(dirPath) { | ||
return !existsSync(dirPath) || readdirSync(dirPath).length === 0; | ||
} | ||
|
||
function ensureEmptyDir() { | ||
const dirPath = path.resolve(testDir, inputs.emptyDir); | ||
if (!existsSync(dirPath)) { | ||
mkdirSync(dirPath, { recursive: true }); | ||
} else if (!isEmpty(dirPath)) { | ||
const globPath = path.resolve(dirPath, '*'); | ||
deleteSync(globPath, { dot: true }); | ||
} | ||
} | ||
|
||
function getTsConfig(installDir) { | ||
const filePath = path.resolve(testDir, installDir, 'tsconfig.json'); | ||
return JSON.parse(readFileSync(filePath, 'utf-8')); | ||
} | ||
|
||
describe('[create-astro] select typescript', function () { | ||
this.timeout(timeout); | ||
|
||
beforeEach(ensureEmptyDir); | ||
|
||
afterEach(ensureEmptyDir); | ||
|
||
it('should prompt for typescript when none is provided', async function () { | ||
return promiseWithTimeout((resolve, onStdout) => { | ||
const { stdout } = setup([ | ||
inputs.emptyDir, | ||
'--template', 'minimal', | ||
'--install', '0', | ||
'--git', '0' | ||
]); | ||
stdout.on('data', (chunk) => { | ||
onStdout(chunk); | ||
if (chunk.includes(PROMPT_MESSAGES.typescript)) { | ||
resolve(); | ||
} | ||
}); | ||
}, () => lastStdout); | ||
}); | ||
|
||
it('should not prompt for typescript when provided', async function () { | ||
return promiseWithTimeout((resolve, onStdout) => { | ||
const { stdout } = setup([ | ||
inputs.emptyDir, | ||
'--template', 'minimal', | ||
'--install', '0', | ||
'--git', '0', | ||
'--typescript', 'base' | ||
]); | ||
stdout.on('data', (chunk) => { | ||
onStdout(chunk); | ||
if (chunk.includes(PROMPT_MESSAGES.typescriptSucceed)) { | ||
resolve(); | ||
} | ||
}); | ||
}, () => lastStdout); | ||
}); | ||
|
||
it('should use "strict" config when specified', async function () { | ||
return promiseWithTimeout((resolve, onStdout) => { | ||
let wrote = false; | ||
const { stdout, stdin } = setup([ | ||
inputs.emptyDir, | ||
'--template', 'minimal', | ||
'--install', '0', | ||
'--git', '0' | ||
]); | ||
stdout.on('data', (chunk) => { | ||
onStdout(chunk); | ||
if (!wrote && chunk.includes(PROMPT_MESSAGES.typescript)) { | ||
stdin.write('\x1B\x5B\x42\x0D'); | ||
wrote = true; | ||
} | ||
if (chunk.includes(PROMPT_MESSAGES.typescriptSucceed)) { | ||
const tsConfigJson = getTsConfig(inputs.emptyDir); | ||
expect(tsConfigJson).to.deep.equal({'extends': 'astro/tsconfigs/strict'}); | ||
resolve(); | ||
} | ||
}); | ||
}, () => lastStdout); | ||
}); | ||
|
||
it('should create tsconfig.json when missing', async function () { | ||
return promiseWithTimeout((resolve, onStdout) => { | ||
const { stdout } = setup([ | ||
inputs.emptyDir, | ||
'--template', 'cassidoo/shopify-react-astro', | ||
'--install', '0', | ||
'--git', '0', | ||
'--typescript', 'base' | ||
]); | ||
stdout.on('data', (chunk) => { | ||
onStdout(chunk); | ||
if (chunk.includes(PROMPT_MESSAGES.typescriptSucceed)) { | ||
const tsConfigJson = getTsConfig(inputs.emptyDir); | ||
expect(tsConfigJson).to.deep.equal({'extends': 'astro/tsconfigs/base'}); | ||
resolve(); | ||
} | ||
}); | ||
}, () => lastStdout); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether users would be confused as to why they have an extra file in their project when they chose "no typescript"? I suppose they can just delete it later..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're planning to update the message soon so it's more clear!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing behavior (before this PR):
When you select "I prefer not to use Typescript", it prints this:
Also, before this PR, those files would always be there when using the official templates, they would only be missing if you used a third-party template that didn't include them.