feat: сделать split-клиент режимом по умолчанию
- добавлен operationsTree для сборки полного клиента - удален режим генерации both - обновлена документация под npm SDK workflow - поднята версия пакета до 4.0.0
This commit is contained in:
@@ -33,7 +33,7 @@ program
|
||||
.option('-i, --input <path>', 'Путь к OpenAPI спецификации (JSON/YAML файл или URL)')
|
||||
.option('-o, --output <path>', 'Директория для сохранения сгенерированных файлов')
|
||||
.option('-n, --name <name>', 'Имя монолитного клиента без расширения .ts')
|
||||
.option('--mode <mode>', 'Режим генерации: single, split, both', 'single')
|
||||
.option('--mode <mode>', 'Режим генерации: split, single', 'split')
|
||||
.option('--single-file', 'Устаревший алиас для --mode single')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type GeneratorMode = 'single' | 'split' | 'both';
|
||||
export type GeneratorMode = 'single' | 'split';
|
||||
|
||||
/**
|
||||
* Конфигурация генератора API
|
||||
@@ -8,7 +8,7 @@ export interface GeneratorConfig {
|
||||
inputPath: string;
|
||||
/** Путь для сохранения сгенерированных файлов */
|
||||
outputPath: string;
|
||||
/** Имя сгенерированного файла (без расширения), используется в single/both режиме */
|
||||
/** Имя сгенерированного файла (без расширения), используется в single режиме */
|
||||
fileName?: string;
|
||||
/** Режим генерации */
|
||||
mode?: GeneratorMode;
|
||||
@@ -28,8 +28,8 @@ export function validateConfig(config: Partial<GeneratorConfig>): config is Gene
|
||||
errors.push('Не указана директория для генерации (--output)');
|
||||
}
|
||||
|
||||
if (config.mode && !['single', 'split', 'both'].includes(config.mode)) {
|
||||
errors.push('Некорректный режим генерации (--mode). Доступные значения: single, split, both');
|
||||
if (config.mode && !['single', 'split'].includes(config.mode)) {
|
||||
errors.push('Некорректный режим генерации (--mode). Доступные значения: split, single');
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
|
||||
@@ -38,6 +38,11 @@ type OperationFileInfo = {
|
||||
fileName: string;
|
||||
};
|
||||
|
||||
type OperationTreeGroup = {
|
||||
moduleName: string;
|
||||
operations: OperationFileInfo[];
|
||||
};
|
||||
|
||||
const RESERVED_IDENTIFIERS = new Set([
|
||||
'break',
|
||||
'case',
|
||||
@@ -204,6 +209,53 @@ function createHttpClientImport(content: string): string {
|
||||
return imports.join('\n');
|
||||
}
|
||||
|
||||
function createObjectPropertyKey(name: string): string {
|
||||
return JSON.stringify(name);
|
||||
}
|
||||
|
||||
function createOperationTreePropertyName(operationFile: OperationFileInfo): string {
|
||||
return operationFile.route.routeName.usage || operationFile.operationName;
|
||||
}
|
||||
|
||||
function createOperationTreeContent(configuration: GenerateApiConfiguration, operationFiles: OperationFileInfo[]): string {
|
||||
const operationByRoute = new Map(operationFiles.map((operationFile) => [operationFile.route, operationFile]));
|
||||
const imports = operationFiles.map(
|
||||
(operationFile) => `import { ${operationFile.operationName} } from "./operations/${operationFile.fileName}";`,
|
||||
);
|
||||
const outOfModuleOperations = (configuration.routes.outOfModule || [])
|
||||
.map((route) => operationByRoute.get(route))
|
||||
.filter((operationFile): operationFile is OperationFileInfo => Boolean(operationFile));
|
||||
const operationTreeGroups: OperationTreeGroup[] = (configuration.routes.combined || []).map(({ moduleName, routes }) => ({
|
||||
moduleName,
|
||||
operations: (routes || [])
|
||||
.map((route) => operationByRoute.get(route))
|
||||
.filter((operationFile): operationFile is OperationFileInfo => Boolean(operationFile)),
|
||||
}));
|
||||
const lines = [
|
||||
...imports,
|
||||
'',
|
||||
'export const operationsTree = {',
|
||||
];
|
||||
|
||||
for (const operationFile of outOfModuleOperations) {
|
||||
lines.push(` ${createObjectPropertyKey(createOperationTreePropertyName(operationFile))}: ${operationFile.operationName},`);
|
||||
}
|
||||
|
||||
for (const { moduleName, operations } of operationTreeGroups) {
|
||||
lines.push(` ${createObjectPropertyKey(moduleName)}: {`);
|
||||
|
||||
for (const operationFile of operations) {
|
||||
lines.push(` ${createObjectPropertyKey(createOperationTreePropertyName(operationFile))}: ${operationFile.operationName},`);
|
||||
}
|
||||
|
||||
lines.push(' },');
|
||||
}
|
||||
|
||||
lines.push('} as const;', '', 'export type OperationsTree = typeof operationsTree;');
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
async function renderTemplateFile(
|
||||
generatorOutput: GenerateApiOutput,
|
||||
templatePath: string,
|
||||
@@ -229,6 +281,7 @@ async function cleanTreeOutput(outputDir: string): Promise<void> {
|
||||
rm(join(outputDir, 'http-client.ts'), { force: true }),
|
||||
rm(join(outputDir, 'data-contracts.ts'), { force: true }),
|
||||
rm(join(outputDir, 'create-api-client.ts'), { force: true }),
|
||||
rm(join(outputDir, 'operations-tree.ts'), { force: true }),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -319,9 +372,9 @@ export async function generate(config: GeneratorConfig): Promise<void> {
|
||||
|
||||
const outputDir = resolve(config.outputPath);
|
||||
const outputFileName = `${fileName}.ts`;
|
||||
const mode = config.mode || 'single';
|
||||
const shouldGenerateSingle = mode === 'single' || mode === 'both';
|
||||
const shouldGenerateSplit = mode === 'split' || mode === 'both';
|
||||
const mode = config.mode || 'split';
|
||||
const shouldGenerateSingle = mode === 'single';
|
||||
const shouldGenerateSplit = mode === 'split';
|
||||
|
||||
const baseGenerateOptions = {
|
||||
...(isUrl ? { url } : { input: inputPath }),
|
||||
@@ -477,6 +530,12 @@ export async function generate(config: GeneratorConfig): Promise<void> {
|
||||
operationExports.length ? operationExports.join('\n') : 'export {};',
|
||||
);
|
||||
|
||||
await writeFormattedFile(
|
||||
generatorOutput,
|
||||
join(outputDir, 'operations-tree.ts'),
|
||||
createOperationTreeContent(generatorOutput.configuration, operationFiles),
|
||||
);
|
||||
|
||||
await writeFormattedFile(
|
||||
generatorOutput,
|
||||
join(outputDir, 'index.ts'),
|
||||
@@ -486,6 +545,9 @@ export async function generate(config: GeneratorConfig): Promise<void> {
|
||||
'export { ContentType, HttpClient } from "./http-client";',
|
||||
'export type { ApiConfig, ApiRequestClient, FullRequestParams, HttpResponse, QueryParamsType, RequestParams, ResponseFormat } from "./http-client";',
|
||||
'export type * from "./data-contracts";',
|
||||
'export { operationsTree } from "./operations-tree";',
|
||||
'export type { OperationsTree } from "./operations-tree";',
|
||||
'export * as operations from "./operations";',
|
||||
'export * from "./operations";',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user