Giter Site home page Giter Site logo

Comments (13)

mrlubos avatar mrlubos commented on September 27, 2024 2

@IgorKha ah, i know what's going on. Will fix, thanks for catching

from openapi-ts.

julianklumpers avatar julianklumpers commented on September 27, 2024 1

@julianklumpers Are you creating those before/after yourself? If so, how and why?

I thought about passing it as the last argument but think I had an issue with it not being typed correctly when using optional values. I can revisit, want to open an issue for it?

created a issue: 888

from openapi-ts.

mrlubos avatar mrlubos commented on September 27, 2024

Hey @IgorKha can you check whether you really have the latest Axios client installed?

from openapi-ts.

mrlubos avatar mrlubos commented on September 27, 2024

This will be fixed in the next release, thanks for catching!

from openapi-ts.

IgorKha avatar IgorKha commented on September 27, 2024

The problem partly still remains. This problem did not exist before and intellisense(for error) does not work.

"@hey-api/openapi-ts": "^0.52.3",
"@hey-api/client-axios": "^0.2.1",
"axios": "^1.7.3",
// Example
import { createClient } from '@hey-api/client-axios'

const client = createClient({
  baseURL: import.meta.env.VITE_BASE_URL
})

const login = async (username: string, password: string, remember: boolean) => {
    try {
      const { data, error, request } = await AuthService.loginV1AuthLoginPost({
        client: client,
        body: {
          grant_type: 'password',
          username,
          password
        },
        query: {
          remember
        }
      })
      if (error) {
        errorStatusCode.value = error.status_code
        throw new Error(error)
      }
    } catch (err) {
      console.error(err.message)
    }
  }
src/stores/userStore.ts:54:39 - error TS2339: Property 'status_code' does not exist on type 'LoginV1AuthLoginPostError'.
  Property 'status_code' does not exist on type 'HTTPValidationError'.

54         errorStatusCode.value = error.status_code
                                         ~~~~~~~~~~~

Thank you so much )

from openapi-ts.

mrlubos avatar mrlubos commented on September 27, 2024

@IgorKha Would you be able to do either:

  • create a StackBlitz example
  • locally, go to the error type for this endpoint. You will see it's a union type of all possible errors (|). Try changing it to intersection (&) and see if the error disappears for this statement you showed me?

I'd prefer a StackBlitz example but either one would help. Thanks!

from openapi-ts.

IgorKha avatar IgorKha commented on September 27, 2024

@mrlubos yes, if I change to (types.gen.ts)export type LoginV1AuthLoginPostError = HttpResponse & HTTPValidationError, this error disappears :)
I'll try to create an example on StackBlitz a little later.

from openapi-ts.

mrlubos avatar mrlubos commented on September 27, 2024

@IgorKha are you able to drop here schemas for HTTPValidationError and HttpResponse? Will be faster than creating an example

from openapi-ts.

IgorKha avatar IgorKha commented on September 27, 2024
types.gen.ts
// types.gen.ts
// This file is auto-generated by @hey-api/openapi-ts

export type Body_login_v1_auth_login_post = {
  grant_type?: string | null
  username: string
  password: string
  scope?: string
  client_id?: string | null
  client_secret?: string | null
}

export type HTTPValidationError = {
  detail?: Array<ValidationError>
}

/**
 * Data model for HTTP response.
 */
export type HttpResponse = {
  status_code: number
  message: string
}

/**
 * Data model for tokens.
 */
export type TokenResponse = {
  access_token: string
}

export type ValidationError = {
  loc: Array<string | number>
  msg: string
  type: string
}

export type LoginV1AuthLoginPostData = {
  body: Body_login_v1_auth_login_post
  query?: {
    remember?: boolean
  }
}

export type LoginV1AuthLoginPostResponse = TokenResponse

export type LoginV1AuthLoginPostError = HttpResponse & HTTPValidationError

export type RefreshTokenV1AuthRefreshTokenPostResponse = TokenResponse

export type RefreshTokenV1AuthRefreshTokenPostError = HttpResponse

export type TestJwtV1AuthTestJwtGetResponse = {
  [key: string]: string
}

export type TestJwtV1AuthTestJwtGetError = HttpResponse

export type TestApiKeyV1AuthTestApiKeyGetResponse = {
  [key: string]: string
}

export type TestApiKeyV1AuthTestApiKeyGetError = HttpResponse

export type TestBothAuthV1AuthBothAuthRouteGetResponse = {
  [key: string]: string
}

export type TestBothAuthV1AuthBothAuthRouteGetError = HttpResponse

export type MsgV1ExpMsgPostData = {
  query: {
    msg: string
  }
}

export type MsgV1ExpMsgPostResponse = string

export type MsgV1ExpMsgPostError = HTTPValidationError

export type PrivateV1ExpPrivatePostData = {
  query: {
    msg: string
  }
}

export type PrivateV1ExpPrivatePostResponse = string

export type PrivateV1ExpPrivatePostError = HTTPValidationError

export type $OpenApiTs = {
  '/v1/auth/login': {
    post: {
      req: LoginV1AuthLoginPostData
      res: {
        /**
         * Successful Response
         */
        '200': TokenResponse
        /**
         * Unauthorized
         */
        '401': HttpResponse
        /**
         * Forbidden
         */
        '403': HttpResponse
        /**
         * Validation Error
         */
        '422': HTTPValidationError
      }
    }
  }
  '/v1/auth/refresh-token': {
    post: {
      res: {
        /**
         * Successful Response
         */
        '200': TokenResponse
        /**
         * Unauthorized
         */
        '401': HttpResponse
        /**
         * Forbidden
         */
        '403': HttpResponse
      }
    }
  }
  '/v1/auth/test-jwt': {
    get: {
      res: {
        /**
         * Successful Response
         */
        '200': {
          [key: string]: string
        }
        /**
         * Unauthorized
         */
        '401': HttpResponse
        /**
         * Forbidden
         */
        '403': HttpResponse
      }
    }
  }
  '/v1/auth/test-api-key': {
    get: {
      res: {
        /**
         * Successful Response
         */
        '200': {
          [key: string]: string
        }
        /**
         * Unauthorized
         */
        '401': HttpResponse
        /**
         * Forbidden
         */
        '403': HttpResponse
      }
    }
  }
  '/v1/auth/both-auth-route': {
    get: {
      res: {
        /**
         * Successful Response
         */
        '200': {
          [key: string]: string
        }
        /**
         * Unauthorized
         */
        '401': HttpResponse
        /**
         * Forbidden
         */
        '403': HttpResponse
      }
    }
  }
  '/v1/exp/msg': {
    post: {
      req: MsgV1ExpMsgPostData
      res: {
        /**
         * Successful Response
         */
        '200': string
        /**
         * Validation Error
         */
        '422': HTTPValidationError
      }
    }
  }
  '/v1/exp/private': {
    post: {
      req: PrivateV1ExpPrivatePostData
      res: {
        /**
         * Successful Response
         */
        '200': string
        /**
         * Validation Error
         */
        '422': HTTPValidationError
      }
    }
  }
}
schemas.gen.ts
// schemas.gen.ts
// This file is auto-generated by @hey-api/openapi-ts

export const $Body_login_v1_auth_login_post = {
  properties: {
    grant_type: {
      anyOf: [
        {
          type: 'string',
          pattern: 'password'
        },
        {
          type: 'null'
        }
      ],
      title: 'Grant Type'
    },
    username: {
      type: 'string',
      title: 'Username'
    },
    password: {
      type: 'string',
      title: 'Password'
    },
    scope: {
      type: 'string',
      title: 'Scope',
      default: ''
    },
    client_id: {
      anyOf: [
        {
          type: 'string'
        },
        {
          type: 'null'
        }
      ],
      title: 'Client Id'
    },
    client_secret: {
      anyOf: [
        {
          type: 'string'
        },
        {
          type: 'null'
        }
      ],
      title: 'Client Secret'
    }
  },
  type: 'object',
  required: ['username', 'password'],
  title: 'Body_login_v1_auth_login_post'
} as const

export const $HTTPValidationError = {
  properties: {
    detail: {
      items: {
        $ref: '#/components/schemas/ValidationError'
      },
      type: 'array',
      title: 'Detail'
    }
  },
  type: 'object',
  title: 'HTTPValidationError'
} as const

export const $HttpResponse = {
  properties: {
    status_code: {
      type: 'integer',
      title: 'Status Code'
    },
    message: {
      type: 'string',
      title: 'Message'
    }
  },
  type: 'object',
  required: ['status_code', 'message'],
  title: 'HttpResponse',
  description: 'Data model for HTTP response.'
} as const

export const $TokenResponse = {
  properties: {
    access_token: {
      type: 'string',
      title: 'Access Token'
    }
  },
  type: 'object',
  required: ['access_token'],
  title: 'TokenResponse',
  description: 'Data model for tokens.'
} as const

export const $ValidationError = {
  properties: {
    loc: {
      items: {
        anyOf: [
          {
            type: 'string'
          },
          {
            type: 'integer'
          }
        ]
      },
      type: 'array',
      title: 'Location'
    },
    msg: {
      type: 'string',
      title: 'Message'
    },
    type: {
      type: 'string',
      title: 'Error Type'
    }
  },
  type: 'object',
  required: ['loc', 'msg', 'type'],
  title: 'ValidationError'
} as const

OpenAPI:

{
  "openapi": "3.1.0",
  "servers": [
    {
      "url": "/api"
    }
  ],
  "paths": {
    "/v1/auth/login": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Login",
        "description": "Authenticates",
        "operationId": "login_v1_auth_login_post",
        "parameters": [
          {
            "name": "remember",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Remember"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/Body_login_v1_auth_login_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            },
            "description": "Forbidden"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/refresh-token": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Refresh Token",
        "description": "Refresh",
        "operationId": "refresh_token_v1_auth_refresh_token_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/test-jwt": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Test Jwt",
        "description": "Protected route that requires authentication.\n\nArgs:\n----\n    current_user (User): The authenticated user.\n\nReturns:\n-------\n    dict[str, str]: A dictionary with a message indicating access granted.",
        "operationId": "test_jwt_v1_auth_test_jwt_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object",
                  "title": "Response Test Jwt V1 Auth Test Jwt Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2PasswordBearer": []
          }
        ]
      }
    },
    "/v1/auth/test-api-key": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Test Api Key",
        "description": "APIKey Route.\n\nArgs:\n----\n    api_key (str, optional): The API key.\n\nReturns:\n-------\n    dict[str, str]: A dictionary with a message indicating access granted.",
        "operationId": "test_api_key_v1_auth_test_api_key_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object",
                  "title": "Response Test Api Key V1 Auth Test Api Key Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ]
      }
    },
    "/v1/auth/both-auth-route": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Test Both Auth",
        "description": "Test route to check auth for api key and oauth2",
        "operationId": "test_both_auth_v1_auth_both_auth_route_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object",
                  "title": "Response Test Both Auth V1 Auth Both Auth Route Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          },
          {
            "OAuth2PasswordBearer": []
          }
        ]
      }
    },
    "/v1/exp/msg": {
      "post": {
        "tags": [
          "exp"
        ],
        "summary": "Msg",
        "operationId": "msg_v1_exp_msg_post",
        "parameters": [
          {
            "name": "msg",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Msg"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string",
                  "title": "Response Msg V1 Exp Msg Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/exp/private": {
      "post": {
        "tags": [
          "exp"
        ],
        "summary": "Private",
        "operationId": "private_v1_exp_private_post",
        "parameters": [
          {
            "name": "msg",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Msg"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string",
                  "title": "Response Private V1 Exp Private Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Body_login_v1_auth_login_post": {
        "properties": {
          "grant_type": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "password"
              },
              {
                "type": "null"
              }
            ],
            "title": "Grant Type"
          },
          "username": {
            "type": "string",
            "title": "Username"
          },
          "password": {
            "type": "string",
            "title": "Password"
          },
          "scope": {
            "type": "string",
            "title": "Scope",
            "default": ""
          },
          "client_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Client Id"
          },
          "client_secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Client Secret"
          }
        },
        "type": "object",
        "required": [
          "username",
          "password"
        ],
        "title": "Body_login_v1_auth_login_post"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "HttpResponse": {
        "properties": {
          "status_code": {
            "type": "integer",
            "title": "Status Code"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "status_code",
          "message"
        ],
        "title": "HttpResponse",
        "description": "Data model for HTTP response."
      },
      "TokenResponse": {
        "properties": {
          "access_token": {
            "type": "string",
            "title": "Access Token"
          }
        },
        "type": "object",
        "required": [
          "access_token"
        ],
        "title": "TokenResponse",
        "description": "Data model for tokens."
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    },
    "securitySchemes": {
      "OAuth2PasswordBearer": {
        "type": "oauth2",
        "flows": {
          "password": {
            "scopes": {},
            "tokenUrl": "login"
          }
        }
      },
      "APIKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    }
  }
}

from openapi-ts.

mrlubos avatar mrlubos commented on September 27, 2024

Yeah I don't think this is a bug anymore @IgorKha, the previous implementation was incorrect. When you assign error.status_code to your value, this field can be undefined because it does not exist on one of the possible returned error types. The previous code worked for you because you got lucky and your errors are objects. But imagine if one of the possible errors was a string, then accessing status_code on it would throw a runtime error.

You will want to explicitly check if that field exists to narrow the type. There's a related issue #495 where people asked for a different approach by status code, but the problem is the same.

from openapi-ts.

IgorKha avatar IgorKha commented on September 27, 2024

I see, thanks for your time. i will read the neighboring thread more closely to understand :)

from openapi-ts.

julianklumpers avatar julianklumpers commented on September 27, 2024

With the latest version where this was problem was fixed, the typescript implementation has changed for the fetch-client. I now have to explicitly specify a boolean type as a generic.

I see that the type has changed, if this is intentional, I would suggest placing the ThrowOnError as the last argument. As we now have to specify a boolean type in all our services now.

type MethodFn = <ThrowOnError extends boolean, Data = unknown, TError = unknown>(options: Omit<RequestOptionsBase<ThrowOnError>, 'method'>) => RequestResult<ThrowOnError, Data, TError>;

Before

export const UpdateProfile = (options: Options<{ path: { userId: string } }>) => {
  return (options?.client ?? client).patch<ProfileUser, ApiError>({
    ...options,
    url: '/api/nl/users/{userId}',
  });
};

After

export const UpdateProfile = (options: Options<{ path: { userId: string } }>) => {
  return (options?.client ?? client).patch<boolean, ProfileUser, ApiError>({ // all good now
    ...options,
    url: '/api/nl/users/{userId}',
  });
};

from openapi-ts.

mrlubos avatar mrlubos commented on September 27, 2024

@julianklumpers Are you creating those before/after yourself? If so, how and why?

I thought about passing it as the last argument but think I had an issue with it not being typed correctly when using optional values. I can revisit, want to open an issue for it?

from openapi-ts.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.