Files
main_frontend/.scripts/create-fsd-component.ts
2026-02-17 23:36:55 +03:00

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)
}