Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ts-to-oapi] Enums are not generated during conversion. #28

Open
0xOmarA opened this issue Sep 4, 2022 · 3 comments
Open

[ts-to-oapi] Enums are not generated during conversion. #28

0xOmarA opened this issue Sep 4, 2022 · 3 comments

Comments

@0xOmarA
Copy link

0xOmarA commented Sep 4, 2022

Hi. I have a number of TypeScript files which I am trying to generate OpenAPI documentation for using this tool. In one of the typescript files, I have an enum which looks like the following:

export enum SpeciesKind {
    Human,
    Bird,
    Fish
}

I am using the following command to generate OpenAPI documentation from my typescript files:

npx typeconv -f ts -t oapi -o spec ./src/*.ts

When running the above command, everything is generated as expected except for any enums I have in my code, no OpenAPI schema is generated for them.

@jkrauss82
Copy link

Just found out about this issue, can confirm enums are not generated. Would be great if this can be fixed!

@erkin98
Copy link

erkin98 commented Oct 17, 2022

Annoying issue

@MattHalloran
Copy link

I was having this issue as well. First, I tried replacing each enum with a string union like this:

    // Read the TypeScript file
    let tsData = fs.readFileSync(pathToTsFile, "utf8");

    // Split into blocks of types
    let blocks = tsData.split("\n\n");
    
    // Convert TypeScript enums to string unions
    tsData = tsData.replace(/export enum (\w+) \{([^}]+)\}/g, (match, enumName, enumBody) => {
        // Split the body of the enum into individual members
        const enumMembers = enumBody.split(",");

        // Map each member to its value (the part after the equals sign)
        const enumValues = enumMembers.map(member => {
            const parts = member.trim().split("=");
            return parts[1]?.trim() || parts[0]?.trim();
        });

        // Join the values into a union
        const union = enumValues.join(" | ");

        // Return the replacement
        const result = `export type ${enumName} = ${union};`;
        console.log(result);
        return result;
    });

    // Join the blocks back together
    tsData = blocks.join("\n\n");

Unfortunately, this didn't work. It seems referencing a string union isn't enough. What I had to do instead was replace each reference to an enum with its string union directly, like this:

    // Read the TypeScript file
    let tsData = fs.readFileSync(pathToTsFile, "utf8");

    // Split into blocks of types
    let blocks = tsData.split("\n\n");
    
    // Define a Map to store the enums and their corresponding string unions
    const enumMap = new Map<string, string>();

    // Convert TypeScript enums to string unions
    tsData = tsData.replace(/export enum (\w+) \{([^}]+)\}/g, (match, enumName, enumBody) => {
        // Split the body of the enum into individual members
        const enumMembers = enumBody.split(",");

        // Map each member to its value (the part after the equals sign)
        const enumValues = enumMembers.map(member => {
            const parts = member.trim().split("=");
            return parts[1]?.trim() || parts[0]?.trim();
        });

        // Join the values into a union
        const union = enumValues.join(" | ");

        // Store the enum and its corresponding union in the map
        enumMap.set(enumName, union);

        // Return an empty string to remove the enum block
        return "";
    });

    // Remove enum blocks from the array of blocks
    blocks = blocks.filter(block => !block.startsWith("export enum "));

    // Replace enum usages with their corresponding unions
    blocks = blocks.map(block => {
        let replacedBlock = block;
        for (const [enumName, union] of enumMap.entries()) {
            const enumRegex = new RegExp(`\\b${enumName}\\b`, "g");
            replacedBlock = replacedBlock.replace(enumRegex, union);
        }
        return replacedBlock;
    });
    
    // Join the blocks back together
    tsData = blocks.join("\n\n");

MattHalloran added a commit to Vrooli/Vrooli that referenced this issue Jul 23, 2023
Improved the OpenAPI schema, by:
- Removing `Resolver` types, which are only used internally by GraphQL
- [Replacing enums with string literals](grantila/typeconv#28 (comment))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants