Skip to content

PluginScaffold ​

Одноразово создает набор файлов по marker-файлу, не обновляя и не проверяя содержимое созданных файлов.

Если хотя бы один целевой файл уже существует, плагин оставляет marker и сообщает об ошибке. Когда все файлы успешно записаны, marker удаляется.

Общий headerTemplate к файлам не добавляется.

ts
entries: Array<string>

Массив с glob-паттернами поиска файлов внутри rootDir, например ['features/*/.feature']

ts
createFiles: (params: {
  folderName: string;
  folderPath: string;
}) => Array<{
  filePath: string;
  content: string;
}>

Возвращает набор файлов для папки marker.

folderPath и filePath должны быть абсолютными путями, иначе плагин сообщит об ошибке

Пример: новая feature

Marker создает UI и публичный API feature-slice. После удаления marker компонент можно менять вручную: плагин больше его не переписывает

ts
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
USER: features/addToCart/.feature создан с содержимым:
text
ARFA Generator выводит логи:
txt
[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
ARFA Generator сгенерировал файлы:
tsx
export function AddToCart() {
  return <button type="button">AddToCart</button>;
}

Пример: маршрут Next.js App Router

Marker в папке маршрута создает page.tsx и loading.tsx. Если повторно добавить marker при существующем page.tsx, плагин сохранит оба файла и сообщит о конфликте

ts
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
USER: app/orders/.page создан с содержимым:
text
ARFA Generator выводит логи:
txt
[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
ARFA Generator сгенерировал файлы:
tsx
export default function Page() {
  return <main><h1>orders</h1></main>;
}

Пример: компонент с CSS и Storybook

Один marker создает React-компонент, CSS module и Storybook story рядом с ним

ts
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
USER: shared/ui/Button/.component создан с содержимым:
text
ARFA Generator выводит логи:
txt
[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
ARFA Generator сгенерировал файлы:
tsx
import styles from './Button.module.css';

type PropsButton = { label: string };

export function Button({ label }: PropsButton) {
  return <button className={styles.root} type="button">{label}</button>;
}

MIT License