PluginScaffold
Одноразово создает набор файлов по marker-файлу, не обновляя и не проверяя содержимое созданных файлов.
Если хотя бы один целевой файл уже существует, плагин оставляет marker и сообщает об ошибке. Когда все файлы успешно записаны, marker удаляется.
Общий headerTemplate к файлам не добавляется.
ts | Массив с glob-паттернами поиска файлов внутри |
ts | Возвращает набор файлов для папки marker.
|
Пример: новая feature
Marker создает UI и публичный API feature-slice. После удаления marker компонент можно менять вручную: плагин больше его не переписывает
new PluginScaffold([
{
entries: ['features/*/.feature'],
createFiles({ folderName, folderPath }) {
function upperFirst(value: string) {
return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
}
const componentName = upperFirst(folderName);
return [
{
filePath: path.resolve(folderPath, `ui/${componentName}.tsx`),
content: `export function ${componentName}() {
return <button type="button">${componentName}</button>;
}`,
},
{
filePath: path.resolve(folderPath, 'index.ts'),
content: `export { ${componentName} } from './ui/${componentName}';`,
},
];
},
},
]),
Запустить Sandbox
[ARFA-GEN] [write] features/addToCart/ui/AddToCart.tsx
[ARFA-GEN] [write] features/addToCart/index.ts
[ARFA-GEN] [remove] features/addToCart/.feature
[ARFA-GEN] finished in 0ms
export function AddToCart() {
return <button type="button">AddToCart</button>;
}
Пример: маршрут Next.js App Router
Marker в папке маршрута создает page.tsx и loading.tsx. Если повторно добавить marker при существующем page.tsx, плагин сохранит оба файла и сообщит о конфликте
new PluginScaffold([
{
entries: ['app/**/.page'],
createFiles({ folderName, folderPath }) {
return [
{
filePath: path.resolve(folderPath, 'page.tsx'),
content: `export default function Page() {
return <main><h1>${folderName}</h1></main>;
}`,
},
{
filePath: path.resolve(folderPath, 'loading.tsx'),
content: `export default function Loading() {
return <p>Loading...</p>;
}`,
},
];
},
},
]),
Запустить Sandbox
[ARFA-GEN] [write] app/orders/page.tsx
[ARFA-GEN] [write] app/orders/loading.tsx
[ARFA-GEN] [remove] app/orders/.page
[ARFA-GEN] finished in 0ms
export default function Page() {
return <main><h1>orders</h1></main>;
}
Пример: компонент с CSS и Storybook
Один marker создает React-компонент, CSS module и Storybook story рядом с ним
new PluginScaffold([
{
entries: ['shared/ui/*/.component'],
createFiles({ folderName, folderPath }) {
return [
{
filePath: path.resolve(folderPath, `${folderName}.tsx`),
content: `import styles from './${folderName}.module.css';
type Props${folderName} = { label: string };
export function ${folderName}({ label }: Props${folderName}) {
return <button className={styles.root} type="button">{label}</button>;
}`,
},
{
filePath: path.resolve(folderPath, `${folderName}.module.css`),
content: `.root {
padding: 0.5rem 1rem;
}`,
},
{
filePath: path.resolve(folderPath, `${folderName}.stories.tsx`),
content: `import type { Meta, StoryObj } from '@storybook/react';
import { ${folderName} } from './${folderName}';
const meta = { component: ${folderName} } satisfies Meta<typeof ${folderName}>;
export default meta;
type TypeStory = StoryObj<typeof meta>;
export const Primary: TypeStory = { args: { label: '${folderName}' } };`,
},
];
},
},
]),
Запустить Sandbox
[ARFA-GEN] [write] shared/ui/Button/Button.tsx
[ARFA-GEN] [write] shared/ui/Button/Button.module.css
[ARFA-GEN] [write] shared/ui/Button/Button.stories.tsx
[ARFA-GEN] [remove] shared/ui/Button/.component
[ARFA-GEN] finished in 0ms
import styles from './Button.module.css';
type PropsButton = { label: string };
export function Button({ label }: PropsButton) {
return <button className={styles.root} type="button">{label}</button>;
}