Búsqueda de sitios web

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.

Artículos relacionados