PluginModular
Собирает информацию о наборе файлов или папок и генерирует один общий файл. Он подходит для случаев, где нужен централизованный модуль на основе структуры проекта: реестр страниц, карта виджетов, список публичных entrypoint, конфигурация роутов или импортов.
В отличие от PluginReexport, этот плагин не создает файл в каждой найденной папке, а пишет один targetFile для каждой конфигурации.
В watch-режиме плагин реагирует только на добавление или удаление файлов, игнорируя изменение контента файлов.
ts | Массив с glob-паттернами поиска файлов и папок внутри |
ts | Определяет, как обрабатываются совпадения с entries |
ts | Абсолютный путь к файлу, который будет сгенерирован |
ts | Функция-шаблон, возвращающая содержимое целевого файла |
Поля modules
ts | Абсолютный путь найденного файла или папки |
ts | Полное имя найденного файла или папки, включая расширение |
ts | Имя из |
ts | Имя родительской папки найденного элемента |
ts | Путь от |
ts | Путь от |
ts | При |
Пример: центральные entrypoint feature-модулей
Плагин собирает index.ts из разных feature-модулей в один файл с namespace-экспортами. Имя экспорта берется из родительской папки
new PluginModular([
{
entries: ['features/*/index.ts'],
entryKind: 'file',
targetFile: path.resolve(rootDir, 'features.generated.ts'),
template({ modules }) {
return modules
.map(({ moduleName, relativePath }) => `export * as ${moduleName} from './${relativePath}';`)
.join('\n');
},
},
]),
Запустить Sandbox
export const featureName = 'orders';
export const featureName = 'profile';
[ARFA-GEN] [write] features.generated.ts
[ARFA-GEN] finished in 0ms
// this file is generated
export * as orders from './features/orders/index';
export * as profile from './features/profile/index';
Пример: типы страниц
Плагин создает типы либо реалтаймовые объекты, описывающие store и actions каждой страницы при их наличии
new PluginModular([
{
entries: ['pages/*'],
entryKind: 'dir',
targetFile: path.resolve(rootDir, 'modularPages.ts'),
template({ modules }) {
return modules
.map(({ entryName: pageName, files }) => ({
pageName,
storePath: files.find(({ fileName }) => fileName === 'store.ts')?.relativePath,
actionsPath: files.find(({ fileName }) => fileName === 'actions')?.relativePath,
}))
.map(
({ pageName, actionsPath, storePath }) => `export declare const ${pageName}: {
store: ${storePath ? `typeof import('./${storePath}').PageStore` : 'never'};
actions: ${actionsPath ? `typeof import('./${actionsPath}')` : 'never'};
};`
)
.join('\n\n');
},
},
]),
Запустить Sandbox
export const pageName = 'orders';
export class PageStore {}
export async function createOrder() {}
export const pageName = 'profile';
[ARFA-GEN] [write] modularPages.ts
[ARFA-GEN] finished in 0ms
// this file is generated
export declare const orders: {
store: typeof import('./pages/orders/store').PageStore;
actions: typeof import('./pages/orders/actions');
};
export declare const profile: {
store: never;
actions: never;
};
Пример: маршруты feature-модулей
Плагин находит feature-модули с файлом routes.ts и объединяет их маршруты. Добавление routes.ts подключает модуль автоматически
new PluginModular([
{
entries: ['features/*'],
entryKind: 'dir',
targetFile: path.resolve(rootDir, 'routes.generated.ts'),
template({ modules }) {
const routeModules = modules.flatMap(({ entryName, files }) =>
files
.filter(({ fileName }) => fileName === 'routes.ts')
.map(({ relativePath }) => ({ name: `${entryName}Routes`, relativePath }))
);
const imports = routeModules
.map(({ name, relativePath }) => `import { routes as ${name} } from './${relativePath}';`)
.join('\n');
const routes = routeModules.map(({ name }) => ` ...${name},`).join('\n');
return `${imports}\n\nexport const routes = [\n${routes}\n];`;
},
},
]),
Запустить Sandbox
export const orders = [];
export const routes = [{ path: '/orders' }];
export const profile = {};
[ARFA-GEN] [write] routes.generated.ts
[ARFA-GEN] finished in 0ms
// this file is generated
import { routes as ordersRoutes } from './features/orders/routes';
export const routes = [
...ordersRoutes,
];
Пример: манифест feature-модулей
По набору файлов в каждой директории генерируется типизированное описание возможностей feature-модулей
new PluginModular([
{
entries: ['features/*'],
entryKind: 'dir',
targetFile: path.resolve(rootDir, 'featureManifest.generated.ts'),
template({ modules }) {
const manifest: Record<string, { hasApi: boolean; hasRoutes: boolean; hasMessages: boolean }> = {};
for (const { entryName, files } of modules) {
const fileNames = new Set(files.map(({ fileName }) => fileName));
manifest[entryName] = {
hasApi: fileNames.has('api.ts'),
hasRoutes: fileNames.has('routes.ts'),
hasMessages: fileNames.has('messages.ts'),
};
}
return `export const featureManifest = ${JSON.stringify(manifest, null, 2)} as const;`;
},
},
]),
Запустить Sandbox
export async function getOrders() {}
export const routes = [{ path: '/orders' }];
export const messages = {};
export const routes = [{ path: '/profile' }];
[ARFA-GEN] [write] featureManifest.generated.ts
[ARFA-GEN] finished in 0ms
// this file is generated
export const featureManifest = {
"orders": {
"hasApi": true,
"hasRoutes": true,
"hasMessages": true
},
"profile": {
"hasApi": false,
"hasRoutes": true,
"hasMessages": false
}
} as const;