Skip to content
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

feat(create-app): two-level prompt for framework and variants #2941

Merged
merged 3 commits into from
Apr 14, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 136 additions & 24 deletions packages/create-app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,123 @@
const fs = require('fs')
const path = require('path')
const argv = require('minimist')(process.argv.slice(2))
// eslint-disable-next-line node/no-restricted-require
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved
const { prompt } = require('enquirer')
const {
yellow,
green,
cyan,
blue,
magenta,
lightRed,
red,
stripColors
red
} = require('kolorist')

const cwd = process.cwd()

const TEMPLATES = [
yellow('vanilla'),
yellow('vanilla-ts'),
green('vue'),
green('vue-ts'),
cyan('react'),
cyan('react-ts'),
magenta('preact'),
magenta('preact-ts'),
lightRed('lit-element'),
lightRed('lit-element-ts'),
red('svelte'),
red('svelte-ts')
const FRAMEWORKS = [
{
name: 'vanilla',
color: yellow,
variants: [
{
name: 'vanilla',
display: 'JavaScript',
color: yellow
},
{
name: 'vanilla-ts',
display: 'TypeScript',
color: blue
}
]
},
{
name: 'vue',
color: green,
variants: [
{
name: 'vue',
display: 'JavaScript',
color: yellow
},
{
name: 'vue-ts',
display: 'TypeScript',
color: blue
}
]
},
{
name: 'react',
color: cyan,
variants: [
{
name: 'react',
display: 'JavaScript',
color: yellow
},
{
name: 'react-ts',
display: 'TypeScript',
color: blue
}
]
},
{
name: 'preact',
color: magenta,
variants: [
{
name: 'preact',
display: 'JavaScript',
color: yellow
},
{
name: 'preact-ts',
display: 'TypeScript',
color: blue
}
]
},
{
name: 'lit-element',
color: lightRed,
variants: [
{
name: 'lit-element',
display: 'JavaScript',
color: yellow
},
{
name: 'lit-element-ts',
display: 'TypeScript',
color: blue
}
]
},
{
name: 'svelte',
color: red,
variants: [
{
name: 'svelte',
display: 'JavaScript',
color: yellow
},
{
name: 'svelte-ts',
display: 'TypeScript',
color: blue
}
]
}
]

const TEMPLATES = FRAMEWORKS.map(
(f) => (f.variants && f.variants.map((v) => v.name)) || [f.name]
).reduce((a, b) => a.concat(b), [])

const renameFiles = {
_gitignore: '.gitignore'
}
Expand All @@ -52,7 +141,6 @@ async function init() {
}
const packageName = await getValidPackageName(targetDir)
const root = path.join(cwd, targetDir)
console.log(`\nScaffolding project in ${root}...`)

if (!fs.existsSync(root)) {
fs.mkdirSync(root, { recursive: true })
Expand Down Expand Up @@ -80,29 +168,53 @@ async function init() {

// determine template
let template = argv.t || argv.template
let message = 'Select a template:'
let message = 'Select a framework:'
let isValidTemplate = false

// --template expects a value
if (typeof template === 'string') {
const availableTemplates = TEMPLATES.map(stripColors)
isValidTemplate = availableTemplates.includes(template)
isValidTemplate = TEMPLATES.includes(template)
message = `${template} isn't a valid template. Please choose from below:`
}

if (!template || !isValidTemplate) {
/**
* @type {{ t: string }}
* @type {{ framework: string }}
*/
const { t } = await prompt({
const { framework } = await prompt({
type: 'select',
name: 't',
name: 'framework',
message,
choices: TEMPLATES
choices: FRAMEWORKS.map((f) => ({
name: f.name,
value: f.name,
message: f.color(f.display || f.name)
}))
})
template = stripColors(t)
const frameworkInfo = FRAMEWORKS.find((f) => f.name === framework)

if (frameworkInfo.variants) {
/**
* @type {{ name: string }}
*/
const { name } = await prompt({
type: 'select',
name: 'name',
message: 'Select a variant:',
choices: frameworkInfo.variants.map((v) => ({
name: v.name,
value: v.name,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should display JavaScript or TypeScript (the variant display) instead of the template name once the user selects the option. I think it would be more clear as feedback:
image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I actually noticed and tried, but haven't found a way to make enquirer work that way. Might need to hack it a bit?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it was a simple change, your call then. This was just a small DX improvement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found the way.
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

message: v.color(v.display || v.name)
}))
})
template = name
} else {
template = frameworkInfo.name
}
}

console.log(`\nScaffolding project in ${root}...`)

const templateDir = path.join(__dirname, `template-${template}`)

const write = (file, content) => {
Expand Down