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

[BUG][typescript] Spaces in model names #19996

Open
4 of 6 tasks
ybelenko opened this issue Oct 29, 2024 · 0 comments
Open
4 of 6 tasks

[BUG][typescript] Spaces in model names #19996

ybelenko opened this issue Oct 29, 2024 · 0 comments

Comments

@ybelenko
Copy link
Contributor

ybelenko commented Oct 29, 2024

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Current AbstractTypeScriptClientCodegen.java doesn't strip spaces in component names. So Api Response model cause broken TS build.

openapi-generator version

7.10.0-SNAPSHOT

OpenAPI declaration file content or url
definitions:
  Api Response:
    title: An uploaded response
    description: Describes the result of uploading an image resource
    type: object
    properties:
      code:
        type: integer
        format: int32
      type:
        type: string
      message:
        type: string
Full spec file ```yaml swagger: '2.0' info: description: 'This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.' version: 1.0.0 title: OpenAPI Petstore license: name: Apache-2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0.html' host: petstore.swagger.io basePath: /v2 tags: - name: pet description: Everything about your Pets - name: store description: Access to Petstore orders - name: user description: Operations about user schemes: - http paths: /pet: post: tags: - pet summary: Add a new pet to the store description: '' operationId: addPet consumes: - application/json - application/xml produces: - application/xml - application/json parameters: - in: body name: body description: Pet object that needs to be added to the store required: true schema: $ref: '#/definitions/Pet' responses: '405': description: Invalid input security: - petstore_auth: - 'write:pets' - 'read:pets' put: tags: - pet summary: Update an existing pet description: '' operationId: updatePet consumes: - application/json - application/xml produces: - application/xml - application/json parameters: - in: body name: body description: Pet object that needs to be added to the store required: true schema: $ref: '#/definitions/Pet' responses: '400': description: Invalid ID supplied '404': description: Pet not found '405': description: Validation exception security: - petstore_auth: - 'write:pets' - 'read:pets' /pet/findByStatus: get: tags: - pet summary: Finds Pets by status description: Multiple status values can be provided with comma separated strings operationId: findPetsByStatus produces: - application/xml - application/json parameters: - name: status in: query description: Status values that need to be considered for filter required: true type: array items: type: string enum: - available - pending - sold default: available collectionFormat: csv responses: '200': description: successful operation schema: type: array items: $ref: '#/definitions/Pet' '400': description: Invalid status value security: - petstore_auth: - 'write:pets' - 'read:pets' /pet/findByTags: get: tags: - pet summary: Finds Pets by tags description: 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.' operationId: findPetsByTags produces: - application/xml - application/json parameters: - name: tags in: query description: Tags to filter by required: true type: array items: type: string collectionFormat: csv responses: '200': description: successful operation schema: type: array items: $ref: '#/definitions/Pet' '400': description: Invalid tag value security: - petstore_auth: - 'write:pets' - 'read:pets' deprecated: true '/pet/{petId}': get: tags: - pet summary: Find pet by ID description: Returns a single pet operationId: getPetById produces: - application/xml - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: '#/definitions/Pet' '400': description: Invalid ID supplied '404': description: Pet not found security: - api_key: [] post: tags: - pet summary: Updates a pet in the store with form data description: '' operationId: updatePetWithForm consumes: - application/x-www-form-urlencoded produces: - application/xml - application/json parameters: - name: petId in: path description: ID of pet that needs to be updated required: true type: integer format: int64 - name: name in: formData description: Updated name of the pet required: false type: string - name: status in: formData description: Updated status of the pet required: false type: string responses: '405': description: Invalid input security: - petstore_auth: - 'write:pets' - 'read:pets' delete: tags: - pet summary: Deletes a pet description: '' operationId: deletePet produces: - application/xml - application/json parameters: - name: api_key in: header required: false type: string - name: petId in: path description: Pet id to delete required: true type: integer format: int64 responses: '400': description: Invalid pet value security: - petstore_auth: - 'write:pets' - 'read:pets' '/pet/{petId}/uploadImage': post: tags: - pet summary: uploads an image description: '' operationId: uploadFile consumes: - multipart/form-data produces: - application/json parameters: - name: petId in: path description: ID of pet to update required: true type: integer format: int64 - name: additionalMetadata in: formData description: Additional data to pass to server required: false type: string - name: file in: formData description: file to upload required: false type: file responses: '200': description: successful operation schema: $ref: '#/definitions/Api Response' security: - petstore_auth: - 'write:pets' - 'read:pets' /store/inventory: get: tags: - store summary: Returns pet inventories by status description: Returns a map of status codes to quantities operationId: getInventory produces: - application/json parameters: [] responses: '200': description: successful operation schema: type: object additionalProperties: type: integer format: int32 security: - api_key: [] /store/order: post: tags: - store summary: Place an order for a pet description: '' operationId: placeOrder produces: - application/xml - application/json parameters: - in: body name: body description: order placed for purchasing the pet required: true schema: $ref: '#/definitions/Order' responses: '200': description: successful operation schema: $ref: '#/definitions/Order' '400': description: Invalid Order '/store/order/{orderId}': get: tags: - store summary: Find purchase order by ID description: 'For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions' operationId: getOrderById produces: - application/xml - application/json parameters: - name: orderId in: path description: ID of pet that needs to be fetched required: true type: integer maximum: 5 minimum: 1 format: int64 responses: '200': description: successful operation schema: $ref: '#/definitions/Order' '400': description: Invalid ID supplied '404': description: Order not found delete: tags: - store summary: Delete purchase order by ID description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors operationId: deleteOrder produces: - application/xml - application/json parameters: - name: orderId in: path description: ID of the order that needs to be deleted required: true type: string responses: '400': description: Invalid ID supplied '404': description: Order not found /user: post: tags: - user summary: Create user description: This can only be done by the logged in user. operationId: createUser produces: - application/xml - application/json parameters: - in: body name: body description: Created user object required: true schema: $ref: '#/definitions/User' responses: default: description: successful operation /user/createWithArray: post: tags: - user summary: Creates list of users with given input array description: '' operationId: createUsersWithArrayInput produces: - application/xml - application/json parameters: - in: body name: body description: List of user object required: true schema: type: array items: $ref: '#/definitions/User' responses: default: description: successful operation /user/createWithList: post: tags: - user summary: Creates list of users with given input array description: '' operationId: createUsersWithListInput produces: - application/xml - application/json parameters: - in: body name: body description: List of user object required: true schema: type: array items: $ref: '#/definitions/User' responses: default: description: successful operation /user/login: get: tags: - user summary: Logs user into the system description: '' operationId: loginUser produces: - application/xml - application/json parameters: - name: username in: query description: The user name for login required: true type: string - name: password in: query description: The password for login in clear text required: true type: string responses: '200': description: successful operation schema: type: string headers: X-Rate-Limit: type: integer format: int32 description: calls per hour allowed by the user X-Expires-After: type: string format: date-time description: date in UTC when token expires '400': description: Invalid username/password supplied /user/logout: get: tags: - user summary: Logs out current logged in user session description: '' operationId: logoutUser produces: - application/xml - application/json parameters: [] responses: default: description: successful operation '/user/{username}': get: tags: - user summary: Get user by user name description: '' operationId: getUserByName produces: - application/xml - application/json parameters: - name: username in: path description: 'The name that needs to be fetched. Use user1 for testing.' required: true type: string responses: '200': description: successful operation schema: $ref: '#/definitions/User' '400': description: Invalid username supplied '404': description: User not found put: tags: - user summary: Updated user description: This can only be done by the logged in user. operationId: updateUser produces: - application/xml - application/json parameters: - name: username in: path description: name that need to be deleted required: true type: string - in: body name: body description: Updated user object required: true schema: $ref: '#/definitions/User' responses: '400': description: Invalid user supplied '404': description: User not found delete: tags: - user summary: Delete user description: This can only be done by the logged in user. operationId: deleteUser produces: - application/xml - application/json parameters: - name: username in: path description: The name that needs to be deleted required: true type: string responses: '400': description: Invalid username supplied '404': description: User not found securityDefinitions: petstore_auth: type: oauth2 authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' flow: implicit scopes: 'write:pets': modify pets in your account 'read:pets': read your pets api_key: type: apiKey name: api_key in: header definitions: Order: title: Pet Order description: An order for a pets from the pet store type: object properties: id: type: integer format: int64 petId: type: integer format: int64 quantity: type: integer format: int32 shipDate: type: string format: date-time status: type: string description: Order Status enum: - placed - approved - delivered complete: type: boolean default: false xml: name: Order Category: title: Pet category description: A category for a pet type: object properties: id: type: integer format: int64 name: type: string xml: name: Category User: title: a User description: A User who is purchasing from the pet store type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer format: int32 description: User Status xml: name: User Tag: title: Pet Tag description: A tag for a pet type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: title: a Pet description: A pet for sale in the pet store type: object required: - name - photoUrls properties: id: type: integer format: int64 category: $ref: '#/definitions/Category' name: type: string example: doggie photoUrls: type: array xml: name: photoUrl wrapped: true items: type: string tags: type: array xml: name: tag wrapped: true items: $ref: '#/definitions/Tag' status: type: string description: pet status in the store enum: - available - pending - sold xml: name: Pet Api Response: title: An uploaded response description: Describes the result of uploading an image resource type: object properties: code: type: integer format: int32 type: type: string message: type: string ```
Generation Details
bin/generate-samples.sh bin/configs/typescript-fetch-with-npm*

and tsc command output:

src/apis/PetApi.ts:383:152 - error TS4055: Return type of public method from exported class has or is using private name 'Api'.

383     async uploadFileRaw(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Api Response>> {
                                                                                                                                                           ~~~

src/apis/PetApi.ts:383:156 - error TS1005: '>' expected.

383     async uploadFileRaw(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Api Response>> {
                                                                                                                                                               ~~~~~~~~

src/apis/PetApi.ts:383:164 - error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.

383     async uploadFileRaw(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Api Response>> {
                                                                                                                                                                       ~

src/apis/PetApi.ts:384:30 - error TS1005: ',' expected.

384         if (requestParameters['petId'] == null) {
                                 ~

src/apis/PetApi.ts:384:31 - error TS1181: Array element destructuring pattern expected.

384         if (requestParameters['petId'] == null) {
                                  ~~~~~~~

src/apis/PetApi.ts:384:38 - error TS1005: ')' expected.

384         if (requestParameters['petId'] == null) {
                                         ~

src/apis/PetApi.ts:384:40 - error TS1136: Property assignment expected.

384         if (requestParameters['petId'] == null) {
                                           ~~

src/apis/PetApi.ts:384:47 - error TS1005: ';' expected.

384         if (requestParameters['petId'] == null) {
                                                  ~

src/apis/PetApi.ts:432:73 - error TS1005: ',' expected.

432         return new runtime.JSONApiResponse(response, (jsonValue) => Api ResponseFromJSON(jsonValue));
                                                                            ~~~~~~~~~~~~~~~~

src/apis/PetApi.ts:433:5 - error TS1128: Declaration or statement expected.

433     }
        ~

src/apis/PetApi.ts:438:5 - error TS1434: Unexpected keyword or identifier.

438     async uploadFile(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Api Response> {
        ~~~~~

src/apis/PetApi.ts:438:39 - error TS1005: ',' expected.

438     async uploadFile(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Api Response> {
                                          ~

src/apis/PetApi.ts:438:74 - error TS1109: Expression expected.

438     async uploadFile(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Api Response> {
                                                                             ~

src/apis/PetApi.ts:438:119 - error TS1005: ';' expected.

438     async uploadFile(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Api Response> {
                                                                                                                          ~

src/apis/PetApi.ts:438:133 - error TS1005: ';' expected.

438     async uploadFile(requestParameters: UploadFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Api Response> {
                                                                                                                                        ~~~~~~~~

src/apis/PetApi.ts:439:15 - error TS1005: ':' expected.

439         const response = await this.uploadFileRaw(requestParameters, initOverrides);
                  ~~~~~~~~

src/apis/PetApi.ts:439:84 - error TS1005: ',' expected.

439         const response = await this.uploadFileRaw(requestParameters, initOverrides);
                                                                                       ~

src/apis/PetApi.ts:440:16 - error TS1005: ':' expected.

440         return await response.value();
                   ~~~~~

src/apis/PetApi.ts:440:38 - error TS1005: ',' expected.

440         return await response.value();
                                         ~

src/apis/PetApi.ts:443:1 - error TS1128: Declaration or statement expected.

443 }
    ~

src/models/Api Response.ts:21:22 - error TS1005: '{' expected.

21 export interface Api Response {
                        ~~~~~~~~

src/models/Api Response.ts:27:10 - error TS1109: Expression expected.

27     code?: number;
            ~

src/models/Api Response.ts:33:10 - error TS1109: Expression expected.

33     type?: string;
            ~

src/models/Api Response.ts:39:13 - error TS1109: Expression expected.

39     message?: string;
               ~

src/models/Api Response.ts:45:31 - error TS1005: '(' expected.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                 ~~~~~~~~

src/models/Api Response.ts:45:45 - error TS1005: ',' expected.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                               ~

src/models/Api Response.ts:45:54 - error TS1005: ';' expected.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                                        ~

src/models/Api Response.ts:45:56 - error TS1434: Unexpected keyword or identifier.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                                          ~~~~~

src/models/Api Response.ts:45:62 - error TS1228: A type predicate is only allowed in return type position for functions and methods.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                                                ~~~

src/models/Api Response.ts:45:65 - error TS1434: Unexpected keyword or identifier.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                                                   ~~~

src/models/Api Response.ts:45:69 - error TS1434: Unexpected keyword or identifier.

45 export function instanceOfApi Response(value: object): value is Api Response {
                                                                       ~~~~~~~~

src/models/Api Response.ts:49:21 - error TS1005: '(' expected.

49 export function Api ResponseFromJSON(json: any): Api Response {
                       ~~~~~~~~~~~~~~~~

src/models/Api Response.ts:49:42 - error TS1005: ',' expected.

49 export function Api ResponseFromJSON(json: any): Api Response {
                                            ~

src/models/Api Response.ts:49:48 - error TS1005: ';' expected.

49 export function Api ResponseFromJSON(json: any): Api Response {
                                                  ~

src/models/Api Response.ts:49:50 - error TS1434: Unexpected keyword or identifier.

49 export function Api ResponseFromJSON(json: any): Api Response {
                                                    ~~~

src/models/Api Response.ts:49:54 - error TS1434: Unexpected keyword or identifier.

49 export function Api ResponseFromJSON(json: any): Api Response {
                                                        ~~~~~~~~

src/models/Api Response.ts:50:16 - error TS1005: ';' expected.

50     return Api ResponseFromJSONTyped(json, false);
                  ~~~~~~~~~~~~~~~~~~~~~

src/models/Api Response.ts:53:21 - error TS1005: '(' expected.

53 export function Api ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): Api Response {
                       ~~~~~~~~~~~~~~~~~~~~~

src/models/Api Response.ts:53:47 - error TS1005: ',' expected.

53 export function Api ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): Api Response {
                                                 ~

src/models/Api Response.ts:53:73 - error TS1005: ',' expected.

53 export function Api ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): Api Response {
                                                                           ~

src/models/Api Response.ts:53:83 - error TS1005: ';' expected.

53 export function Api ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): Api Response {
                                                                                     ~

src/models/Api Response.ts:53:85 - error TS1434: Unexpected keyword or identifier.

53 export function Api ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): Api Response {
                                                                                       ~~~

src/models/Api Response.ts:53:89 - error TS1434: Unexpected keyword or identifier.

53 export function Api ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): Api Response {
                                                                                           ~~~~~~~~

src/models/Api Response.ts:65:23 - error TS1005: '(' expected.

65   export function Api ResponseToJSON(json: any): Api Response {
                         ~~~~~~~~~~~~~~

src/models/Api Response.ts:65:42 - error TS1005: ',' expected.

65   export function Api ResponseToJSON(json: any): Api Response {
                                            ~

src/models/Api Response.ts:65:48 - error TS1005: ';' expected.

65   export function Api ResponseToJSON(json: any): Api Response {
                                                  ~

src/models/Api Response.ts:65:50 - error TS1434: Unexpected keyword or identifier.

65   export function Api ResponseToJSON(json: any): Api Response {
                                                    ~~~

src/models/Api Response.ts:65:54 - error TS1434: Unexpected keyword or identifier.

65   export function Api ResponseToJSON(json: any): Api Response {
                                                        ~~~~~~~~

src/models/Api Response.ts:66:18 - error TS1005: ';' expected.

66       return Api ResponseToJSONTyped(json, false);
                    ~~~~~~~~~~~~~~~~~~~

src/models/Api Response.ts:69:23 - error TS1005: '(' expected.

69   export function Api ResponseToJSONTyped(value?: Api Response | null, ignoreDiscriminator: boolean = false): any {
                         ~~~~~~~~~~~~~~~~~~~

src/models/Api Response.ts:69:49 - error TS1109: Expression expected.

69   export function Api ResponseToJSONTyped(value?: Api Response | null, ignoreDiscriminator: boolean = false): any {
                                                   ~

src/models/Api Response.ts:69:55 - error TS1005: ',' expected.

69   export function Api ResponseToJSONTyped(value?: Api Response | null, ignoreDiscriminator: boolean = false): any {
                                                         ~~~~~~~~

src/models/Api Response.ts:69:91 - error TS1005: ',' expected.

69   export function Api ResponseToJSONTyped(value?: Api Response | null, ignoreDiscriminator: boolean = false): any {
                                                                                             ~

src/models/Api Response.ts:69:109 - error TS1005: ';' expected.

69   export function Api ResponseToJSONTyped(value?: Api Response | null, ignoreDiscriminator: boolean = false): any {
                                                                                                               ~

src/models/Api Response.ts:69:111 - error TS1434: Unexpected keyword or identifier.

69   export function Api ResponseToJSONTyped(value?: Api Response | null, ignoreDiscriminator: boolean = false): any {
                                                                                                                 ~~~


Found 55 errors in 2 files.

Errors  Files
    20  src/apis/PetApi.ts:383
    35  src/models/Api Response.ts:21
Steps to reproduce

Use model name with a space, then generate any typescript generator and check syntax via tsc command

Suggest a fix

Should be corrected somewhere in
modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java:603

ArrayList<String> exceptions = new ArrayList<String>(Arrays.asList("\\|", " "));
String sanName = sanitizeName(name, "(?![| ])\\W", exceptions);

if somebody can explain these 2 lines I can submit PR with the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant