packages/cli/src/commands/create-files/index.ts
import chalk from 'chalk'
import { resolve } from 'node:path'
import { Command } from 'commander'
import { exit } from 'node:process'
import { multiselect, text, confirm, spinner, cancel, isCancel } from '@clack/prompts'
import { createDocumentFile } from './create-documentation-file'
import { createLibraryTestFile } from './create-library-test-file'
import { createLibraryComponentFile } from './create-library-component-file'
import { buildEntry } from '../../../../lib/build/entry-builder'
import { pascalCaseToKebabCase } from './../../utils/pascal-case-to-kebab-case'
import { fileURLToPath } from 'node:url'
const _dirname = fileURLToPath(new URL('.', import.meta.url))
export function createFilesCommand(): Command {
const createFiles = new Command('create-files')
createFiles
.description('Create Vue, Tests et Documentations files for a new component')
.option(
'-f, --filename <filename>',
'Optional: Provide the name of the component you want create - Ex: "MazBtn"',
)
.action(async (option: { filename?: string }) => {
try {
let filename = option.filename
if (filename) {
const isGoodFilename = await confirm({
message: `Are you sure the name of your component is "${filename}"`,
})
checkIsCancel(isGoodFilename)
if (!isGoodFilename) {
filename = await getComponentName(filename)
}
}
if (!filename) {
filename = await getComponentName()
}
const fileTypes = await multiselect({
message: 'Select the file types you want to create',
options: [
{ value: 'all', label: 'All files' },
{ value: 'docs', label: 'Documentation File' },
{ value: 'vue', label: 'Library Vue Component File' },
{ value: 'test', label: 'Library Test Unit File' },
],
})
checkIsCancel(fileTypes)
if (Array.isArray(fileTypes)) {
await runCreateFiles({
filename,
fileTypes: fileTypes as string[],
})
}
} catch {
exit(1)
}
})
return createFiles
}
async function getComponentName(initialValue?: string): Promise<string> {
const componentName = await text({
message: 'What is your component name?',
placeholder: 'Not sure',
initialValue,
validate(value) {
if (value.length === 0) return 'Value is required!'
},
})
checkIsCancel(componentName)
return componentName as string
}
function checkIsCancel(value: unknown): void {
if (isCancel(value)) {
cancel('Operation cancelled.')
exit(0)
}
}
async function runCreateFiles({
filename,
fileTypes,
}: {
filename: string
fileTypes: string[]
}): Promise<void> {
const filenameKebab = pascalCaseToKebabCase(filename)
const spinnerLoader = spinner()
spinnerLoader.start('File(s) creating')
const shouldCreateAllFiles = fileTypes.includes('all')
if (shouldCreateAllFiles || fileTypes.includes('test')) {
await createLibraryTestFile({
filename,
filenameKebab,
})
}
if (shouldCreateAllFiles || fileTypes.includes('vue')) {
await createLibraryComponentFile({
filename,
filenameKebab,
})
await buildEntry({
output: resolve(_dirname, './../../../../lib/components/index.ts'),
componentName: 'fullName',
scriptName: 'component-entry-generated',
})
}
const shouldCreateDocumentationFile = shouldCreateAllFiles || fileTypes.includes('docs')
if (shouldCreateDocumentationFile) {
await createDocumentFile({
filename,
filenameKebab,
})
}
spinnerLoader.stop('File(s) created')
if (shouldCreateDocumentationFile) {
const componentConfigurationFilePath = resolve(
_dirname,
'./../../../docs/docs/.vitepress/configs/components.mts',
)
console.log('')
console.log(
chalk.bold.hex('#ffa500')(
`⚠ Now you should add your component reference in the right part in ${chalk.bold.hex(
'#1e90ff',
)(componentConfigurationFilePath)}`,
),
)
console.log('')
}
}