126 lines
3.0 KiB
TypeScript
126 lines
3.0 KiB
TypeScript
/**
|
|
* FSD Component Generator - Flat Structure
|
|
*
|
|
* Creates components with flat structure:
|
|
* ComponentName/
|
|
* ├── index.ts
|
|
* ├── ComponentName.tsx
|
|
* ├── ComponentName.module.scss
|
|
* └── ComponentName.d.ts
|
|
*
|
|
* Usage: bun gc <layer> <ComponentName>
|
|
* Example: bun gc entity ProjectCard
|
|
*/
|
|
|
|
import { mkdir, writeFile } from "node:fs/promises"
|
|
|
|
const args = Bun.argv.slice(2)
|
|
|
|
function printUsageAndExit(): never {
|
|
console.error("Error: Please provide <layer> and <ComponentName>")
|
|
console.log("Usage: bun gc <layer> <ComponentName>")
|
|
console.log("Layers: shared, entity, feature, widget, page")
|
|
console.log("Example: bun gc entity ProjectCard")
|
|
process.exit(1)
|
|
}
|
|
|
|
function getComponentPath(layer: string, component: string): string {
|
|
const base = "./src/"
|
|
|
|
switch (layer) {
|
|
case "shared":
|
|
return `${base}shared/ui/${component}`
|
|
case "app":
|
|
return `${base}app/${component}`
|
|
case "entity":
|
|
case "entities":
|
|
return `${base}entities/${component}`
|
|
case "feature":
|
|
case "features":
|
|
return `${base}features/${component}`
|
|
case "widget":
|
|
case "widgets":
|
|
return `${base}widgets/${component}`
|
|
case "page":
|
|
case "pages":
|
|
return `${base}pages/${component}`
|
|
default:
|
|
return `${base}${layer}s/${component}`
|
|
}
|
|
}
|
|
|
|
function generateIndexTemplate(component: string): string {
|
|
return `export * from "./${component}"
|
|
`
|
|
}
|
|
|
|
function generateComponentTemplate(component: string): string {
|
|
return `import type { I${component}Props } from "./${component}.d"
|
|
import type { JSX } from "react"
|
|
|
|
import { FunctionComponent } from "react"
|
|
|
|
import styles from "./${component}.module.scss"
|
|
|
|
export const ${component}: FunctionComponent<I${component}Props> = (): JSX.Element => {
|
|
return (
|
|
<div className={styles.root} data-testid="${component}">
|
|
${component}
|
|
</div>
|
|
)
|
|
}
|
|
`
|
|
}
|
|
|
|
function generateTypesTemplate(component: string): string {
|
|
return `export interface I${component}Props {
|
|
className?: string
|
|
}
|
|
`
|
|
}
|
|
|
|
function generateStylesTemplate(): string {
|
|
return `.root {
|
|
}
|
|
`
|
|
}
|
|
|
|
if (args.length < 2) {
|
|
printUsageAndExit()
|
|
}
|
|
|
|
const layer = args[0]
|
|
const component = args[1]
|
|
const componentPath = getComponentPath(layer, component)
|
|
|
|
console.log(`Creating ${component} in ${componentPath}...`)
|
|
|
|
try {
|
|
await mkdir(componentPath, { recursive: true })
|
|
|
|
await Promise.all([
|
|
writeFile(`${componentPath}/index.ts`, generateIndexTemplate(component)),
|
|
writeFile(
|
|
`${componentPath}/${component}.tsx`,
|
|
generateComponentTemplate(component),
|
|
),
|
|
writeFile(
|
|
`${componentPath}/${component}.d.ts`,
|
|
generateTypesTemplate(component),
|
|
),
|
|
writeFile(
|
|
`${componentPath}/${component}.module.scss`,
|
|
generateStylesTemplate(),
|
|
),
|
|
])
|
|
|
|
console.log(`✅ Created ${component}:`)
|
|
console.log(` ${componentPath}/index.ts`)
|
|
console.log(` ${componentPath}/${component}.tsx`)
|
|
console.log(` ${componentPath}/${component}.d.ts`)
|
|
console.log(` ${componentPath}/${component}.module.scss`)
|
|
} catch (error) {
|
|
console.error(`Error: ${(error as Error).message}`)
|
|
process.exit(1)
|
|
}
|