PluginValidators
Генерирует схемы валидации из TypeScript-контрактов через библиотеку api-contract-check. Плагин читает входные API-файлы, находит типы запроса и ответа, строит сериализуемые схемы валидации и записывает их в targetFolder. При удалении API-файла соответствующая схема валидации автоматически удаляется.
Плагин работает инкрементально в watch-режиме благодаря хранению обратной карты зависимостей.
Целевой путь строится как targetFolder + relativePathFromRootDir. Если исходник находится в src/api/orders.ts, а targetFolder — на src/validators, результат будет записан в src/validators/api/orders.ts. Для удобства можно также использовать PluginReexport в папке validators.
Не забудьте подключить realtime-валидацию, как описано в разделе Валидация данных.
ts | Массив с glob-паттернами поиска папок внутри |
ts | Регулярное выражение для исключения файлов из обработки |
ts | Имя декларации типа запроса (например, |
ts | Имя декларации типа ответа (например, |
ts | Папка, куда будут сгенерированы файлы со схемами валидации |
ts | Путь к tsconfig для поиска ts-алиасов и резолвинга путей |
ts | Функция форматирования содержимого файла со схемой валидации |
ts | Колбэк для получения списка деградировавших до |
ts | По умолчанию |
Пример: API-контракты в общей папке
Для файлов в папке api генерируются схемы валидации в validators/api. Изменение общего типа обновляет зависящие от него схемы валидации
new PluginValidators([
{
entries: ['api'],
exclude: /(^_|\.test\.ts$|package\.json$)/,
targetFolder: path.resolve(rootDir, 'validators'),
tsconfigPath: path.resolve(rootDir, 'tsconfig.json'),
requestDeclaration: 'TypeRequest',
responseDeclaration: 'TypeResponse',
formatContent({ schema, targetPath }) {
return `export const ${path.parse(targetPath).name} = ${JSON.stringify(schema, null, 2)} as const;\n`;
},
},
]),
Запустить Sandbox
{
"include": ["**/*.ts"],
"compilerOptions": {
"target": "ES2023",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true
}
}
export type TypeOrder = {
id: string;
status: 'draft' | 'confirmed';
};
import type { TypeOrder } from '../models/order';
export type TypeRequest = { status?: TypeOrder['status'] };
export type TypeResponse = { orders: Array<TypeOrder> };
[ARFA-GEN] [write] validators/api/orders.ts
[ARFA-GEN] finished in 0ms
// this file is generated
export const orders = {
"request": {
"status": [
"optional",
[
"union",
[
"literal",
"draft"
],
[
"literal",
"confirmed"
]
]
]
},
"response": {
"orders": [
"array",
{
"id": "string",
"status": [
"union",
[
"literal",
"draft"
],
[
"literal",
"confirmed"
]
]
}
]
}
} as const;
Пример: API-контракты внутри feature-модулей
Плагин находит папки features/*/api и сохраняет структуру модулей в validators/features
new PluginValidators([
{
entries: ['features/*/api'],
exclude: /(^_|\.test\.ts$|package\.json$)/,
targetFolder: path.resolve(rootDir, 'validators'),
tsconfigPath: path.resolve(rootDir, 'tsconfig.json'),
requestDeclaration: 'TypeRequest',
responseDeclaration: 'TypeResponse',
formatContent({ schema, targetPath }) {
return `export const ${path.parse(targetPath).name} = ${JSON.stringify(schema, null, 2)} as const;\n`;
},
},
]),
Запустить Sandbox
{
"include": ["**/*.ts"],
"compilerOptions": {
"target": "ES2023",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true
}
}
export type TypeRequest = { status?: 'draft' | 'confirmed' };
export type TypeResponse = { orders: Array<{ id: string; status: string }> };
export type TypeRequest = { profileId: string };
export type TypeResponse = { name: string };
[ARFA-GEN] [write] validators/features/orders/api/listOrders.ts
[ARFA-GEN] [write] validators/features/profile/api/getProfile.ts
[ARFA-GEN] finished in 0ms
// this file is generated
export const listOrders = {
"request": {
"status": [
"optional",
[
"union",
[
"literal",
"draft"
],
[
"literal",
"confirmed"
]
]
]
},
"response": {
"orders": [
"array",
{
"id": "string",
"status": "string"
}
]
}
} as const;