openapi-typescript generar enumeraciones
dados estos datos:
openapi: 3.0.1
info:
title: test enums
description: test enums
version: "1.00"
components:
schemas:
VideoProcessingStateDto:
type: string
enum:
- IN_PROGRESS
- FAILED
- FINISHED
Deseo generar el siguiente enum de TypeScript
export enum VideoProcessingStateDto {
IN_PROGRESS = 'IN_PROGRESS',
FAILED = 'FAILED',
FINISHED = 'FINISHED',
}
Sin embargo, openapi-typescript sigue dándome una unión de cadenas como la siguiente:
/** @enum {string} */
VideoProcessingStateDto: "IN_PROGRESS" | "FAILED" | "FINISHED";
¿Es posible configurar openapi-typescript para generar enums en este caso?
Basado en un vistazo muy superficial al código fuente, no veo ninguna opción de configuración
¿Quizás no estoy definiendo el enum correctamente en la entrada?
¡Cualquier orientación sería muy apreciada, gracias!
Respuesta #1
Ok, entonces decidí interactuar con la opción transform en la API, que permite a los usuarios reformatear la salida según sea necesario. En este caso, estoy reemplazando el valor con el nombre de un enum, generando un enum a partir de los valores en la unión y agregándolos a una caché.
Cuando llega el momento de volcar los resultados al archivo, entonces estoy agregando los enums al final del archivo para que existan cuando se hacen referencia en los componentes del esquema.
Este es un código muy básico y probablemente necesitarás modificarlo para satisfacer tus necesidades, pero aquí está todo el código.
import openapiTS, { SchemaObject } from 'openapi-typescript';
import * as fs from 'node:fs';
// Utility function to get the name of the schema from the path
function getSchemaName(str: string) {
const arr = str.split('/');
const schemaName = arr[arr.length - 1];
return schemaName;
}
/** trasform the sting union of "IN_PROGRESS" | "FAILED" | "FINISHED"
* to a typescript enum like:
* enum Status {
* IN_PROGRESS = "IN_PROGRESS",
* FAILED = "FAILED",
* FINISHED = "FINISHED"
* }
*/
function unionToEnum(enumValues: string[], enumName: string) {
const enumString = enumValues
.map((value) => `${value} = "${value}"`)
.join(',\n');
const enumType = `enum ${enumName} {
${enumString}
}`;
return enumType;
}
async function generateTypesFromSchema(): Promise<string> {
const localPath = new URL('api.yml', import.meta.url);
const output = await openapiTS(localPath, {
transform: collectAndTransformEnums,
});
if (output) {
return output;
}
return '';
}
const enumCache = new Map();
function collectAndTransformEnums(
schemaObject: SchemaObject,
metadata: any
): string {
if ('enum' in schemaObject) {
const enumName = getSchemaName(metadata.path);
const enumValues = schemaObject.enum as string[];
enumCache.set(getSchemaName(enumName), unionToEnum(enumValues, enumName));
return enumName;
}
return '';
}
/**
* 1. generate the types from the schema
* 2. iterate over the enumCache and add the enums to the types
* 3. write the types to a file
*/
generateTypesFromSchema().then((types) => {
enumCache.forEach((enumType) => {
types += enumType;
});
// write the types to a file
return fs.writeFile('defs/types.ts', types, (err) => {
if (err) {
console.error(err);
return;
}
});
});
Usando el guion de arriba, dado este ingreso:
openapi: 3.0.1
info:
title: Sample Video API
description: Sample Video API
version: '1.0'
paths:
/api/v1/video-process:
get:
tags:
- video
summary: Process a video input
operationId: VideoProcess
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/VideoProcessingStateDto'
components:
schemas:
VideoProcessingStateDto:
type: string
enum:
- IN_PROGRESS
- FAILED
- FINISHED
La salida será:
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/
export interface paths {
'/api/v1/video-process': {
/** Process a video input */
get: operations['VideoProcess'];
};
}
export type webhooks = Record<string, never>;
export interface components {
schemas: {
/** @enum {string} */
VideoProcessingStateDto: VideoProcessingStateDto;
};
responses: never;
parameters: never;
requestBodies: never;
headers: never;
pathItems: never;
}
export type external = Record<string, never>;
export interface operations {
/** Process a video input */
VideoProcess: {
responses: {
/** @description Successful operation */
200: {
content: {
'application/json': components['schemas']['VideoProcessingStateDto'];
};
};
};
};
}
enum VideoProcessingStateDto {
IN_PROGRESS = 'IN_PROGRESS',
FAILED = 'FAILED',
FINISHED = 'FINISHED',
}
Respuesta #2
Siguiendo la documentación avanzada, puedes agregar el indicador --enum al comando openapi-typescript y obtener los enums generados para ti sin esfuerzo adicional.
