Skip to content

Operation types are being mapped incorrectly (v7) #1542

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

Closed
2 tasks done
jaredLunde opened this issue Feb 15, 2024 · 3 comments · Fixed by #1545
Closed
2 tasks done

Operation types are being mapped incorrectly (v7) #1542

jaredLunde opened this issue Feb 15, 2024 · 3 comments · Fixed by #1545
Labels
bug Something isn't working openapi-ts Relevant to the openapi-typescript library

Comments

@jaredLunde
Copy link
Contributor

Description

The operation type mapping no longer uses the correct operationId keys.

Name Version
openapi-typescript 7.0.0-next.7
Node.js 21.0.0
OS + version macOS 14.2.1

Reproduction

Given an OpenAPI v3 spec

openapi: 3.0.3
info:
    title: Web API
    version: "1.0"
servers:
    - url: https://api.hgraph.com
paths:
    /v1/accounts/{id}:
        get:
            tags:
                - Accounts
            summary: Get Accounts
            description: Get an account.
            operationId: Accounts#Get
            parameters:
                - name: id
                  in: path
                  description: The ID of the account
                  required: true
                  schema:
                    type: string
                    description: The ID of the account
                    example: d9f08fe2-cc42-11ee-a737-6eaad63d76fb
                    format: uuid
                  example: d9f09118-cc42-11ee-a737-6eaad63d76fb
            responses:
                "200":
                    description: OK response.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Account'
                            example:
                                created_at: "1974-07-14T21:12:28Z"
                                id: d9da03c6-cc42-11ee-a737-6eaad63d76fb
                                personal_org_id: d9da051a-cc42-11ee-a737-6eaad63d76fb
                                primary_email_address_id: d9da0664-cc42-11ee-a737-6eaad63d76fb

The following types are generated:

export type paths = {
  "/v1/accounts/{id}": {
    parameters: {
      query?: never;
      header?: never;
      path?: never;
      cookie?: never;
    };
    /**
     * Get Accounts
     * @description Get an account.
     */
    get: operations["Get"]; // NOTE: here is the bug
    put?: never;
    post?: never;
    delete?: never;
    options?: never;
    head?: never;
    patch?: never;
    trace?: never;
  };
}

export type operations = {
  "Accounts#Get": {
    parameters: {
      query?: never;
      header?: never;
      path: {
        /**
         * @description The ID of the account
         * @example d9f09118-cc42-11ee-a737-6eaad63d76fb
         */
        id: string;
      };
      cookie?: never;
    };
    requestBody?: never;
    responses: {
      /** @description OK response. */
      200: {
        headers: {
          [name: string]: unknown;
        };
        content: {
          "application/json": components["schemas"]["Account"];
        };
     },
}

As you can see, the get method is mapped to operations["Get"]; , however the operation key is actually Accounts#Get. This only started happening today as far as I can tell. It has generated correctly to date.

Expected result

export type paths = {
  "/v1/accounts/{id}": {
    parameters: {
      query?: never;
      header?: never;
      path?: never;
      cookie?: never;
    };
    /**
     * Get Accounts
     * @description Get an account.
     */
    get: operations["Accounts#Get"]; // NOTE: here is the bug
    /**
     * Update Accounts
     * @description Update an account.
     */
    put: operations["Accounts#Update"];
    post?: never;
    delete?: never;
    options?: never;
    head?: never;
    patch?: never;
    trace?: never;
  };
}

export type operations = {
  "Accounts#Get": {
    parameters: {
      query?: never;
      header?: never;
      path: {
        /**
         * @description The ID of the account
         * @example d9f09118-cc42-11ee-a737-6eaad63d76fb
         */
        id: string;
      };
      cookie?: never;
    };
    requestBody?: never;
    responses: {
      /** @description OK response. */
      200: {
        headers: {
          [name: string]: unknown;
        };
        content: {
          "application/json": components["schemas"]["Account"];
        };
     },
  },
}

Checklist

@jaredLunde jaredLunde added bug Something isn't working openapi-ts Relevant to the openapi-typescript library labels Feb 15, 2024
@drwpow
Copy link
Contributor

drwpow commented Feb 15, 2024

Ah great catch. I don’t remember having tests for # characters specifically in an operationId, but it’d be great to ensure this works.

Not sure whether this was introduced with Redocly’s schema bundling, or just a net-new bug in 7.x. But either way seems like the # character is probably being parsed incorrectly (e.g. $ref: "#/components/schemas/foo").

Would love a PR for this if you (or anyone else) is able!

@jaredLunde
Copy link
Contributor Author

jaredLunde commented Feb 15, 2024

Digging in right now. Looks maybe related to this change: Redocly/redocly-cli@4ab6e09#diff-25c0338c90db3454ba7548187ad0db4e1e288ffca3c1d6ef65f45a442e728074

I can figure out a workaround unless you'd prefer I open an issue in Redocly.

edit:
Yeah if i move the parseRef function they were using for 2 years into your ts.ts and use that one instead, the test I wrote passes. They're effectively no longer "testing" that a given string is a ref e.g. #/components/ anymore because they removed the / from the split.

export function parseRef(ref: string): {
  uri: string | null;
  pointer: string[];
} {
  const [uri, pointer] = ref.split("#/");
  return {
    uri: uri || null,
    pointer: pointer
      ? pointer.split("/").map(unescapePointer).filter(isTruthy)
      : [],
  };
}

@drwpow
Copy link
Contributor

drwpow commented Feb 16, 2024

I can figure out a workaround unless you'd prefer I open an issue in Redocly.

No workarounds are fine. Honestly a lot of the delay of 7.x stable being released is filing down some sharp edges with Redocly. I’m glad to be using it—it offloads a ton of complexity I think it’s far better at than this library ever was—but it comes with drawbacks like this.

They're effectively no longer "testing" that a given string is a ref e.g. #/components/ anymore because they removed the / from the split.

Ah great catch! On the one hand, yeah this would be easy for them to test in some way. On the other, testing is hard 😅. Either way, I think having the fix live in this repo (and having a test for it) is smart.

drwpow pushed a commit that referenced this issue Feb 19, 2024
* fix: replace # characters in operation IDs with a slash

Fixes #1542

* add hash regex constant
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working openapi-ts Relevant to the openapi-typescript library
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants