ng-openapi-gen icon indicating copy to clipboard operation
ng-openapi-gen copied to clipboard

Multimple Content type generate wrong service

Open exejutable opened this issue 4 years ago • 2 comments

Based on this open api spec on line 13100 i have two content types

Extra

  • Angular : 11
  • ng-openapi-gen: 0.19.2

{
   "requestBody":{
      "content":{
         "application/basic-authentication+json":{
            "schema":{
               "$ref":"#/components/schemas/AuthenticationBasicRequest"
            }
         },
         "application/social-authentication+json":{
            "schema":{
               "$ref":"#/components/schemas/AuthenticationSocialRequest"
            }
         }
      }
   }
}


And generates this service ignoring application/basic-authentication+json, also i noticed that only the 200 responses are handled in the response.

/* tslint:disable */
/* eslint-disable */
import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { BaseService } from '../base-service';
import { ApiConfiguration } from '../api-configuration';
import { StrictHttpResponse } from '../strict-http-response';
import { RequestBuilder } from '../request-builder';
import { Observable } from 'rxjs';
import { map, filter } from 'rxjs/operators';

import { AccountCreatePublicRequest } from '../models/account-create-public-request';
import { AccountSocialNetworksResponse } from '../models/account-social-networks-response';
import { AuthenticationBasicRequest } from '../models/authentication-basic-request';
import { AuthenticationResponse } from '../models/authentication-response';
import { AuthenticationSocialRequest } from '../models/authentication-social-request';
import { AuthorizationRequest } from '../models/authorization-request';
import { AuthorizationResponse } from '../models/authorization-response';
import { ChangeAccountEmailRequest } from '../models/change-account-email-request';
import { ChangeAccountPasswordRequest } from '../models/change-account-password-request';
import { RegistrationResponse } from '../models/registration-response';
import { RestoreAccountPasswordRequest } from '../models/restore-account-password-request';
import { SocialNetworkAddedResponse } from '../models/social-network-added-response';
import { SocialNetworkLogin } from '../models/social-network-login';
import { UnknownDeviceLoginResponse } from '../models/unknown-device-login-response';
import { UpdateAccountLegacyRequest } from '../models/update-account-legacy-request';
import { UpdateChangesAppliedResponse } from '../models/update-changes-applied-response';
import { UpdateSendCodeResponse } from '../models/update-send-code-response';

@Injectable({
  providedIn: 'root',
})
export class PublicService extends BaseService {
  constructor(
    config: ApiConfiguration,
    http: HttpClient
  ) {
    super(config, http);
  }

  /**
   * Path part for operation createOneAccountPublic
   */
  static readonly CreateOneAccountPublicPath = '/public/register';

  /**
   * Create account.
   *
   * Create one Account
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `createOneAccountPublic()` instead.
   *
   * This method sends `application/json` and handles request body of type `application/json`.
   */
  createOneAccountPublic$Response(params?: {
    tenant?: string;

    /**
     * AccountCreatePublicRequest
     */
    body?: AccountCreatePublicRequest
  }): Observable<StrictHttpResponse<RegistrationResponse>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.CreateOneAccountPublicPath, 'post');
    if (params) {
      rb.header('tenant', params.tenant, {});
      rb.body(params.body, 'application/json');
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<RegistrationResponse>;
      })
    );
  }

  /**
   * Create account.
   *
   * Create one Account
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `createOneAccountPublic$Response()` instead.
   *
   * This method sends `application/json` and handles request body of type `application/json`.
   */
  createOneAccountPublic(params?: {
    tenant?: string;

    /**
     * AccountCreatePublicRequest
     */
    body?: AccountCreatePublicRequest
  }): Observable<RegistrationResponse> {

    return this.createOneAccountPublic$Response(params).pipe(
      map((r: StrictHttpResponse<RegistrationResponse>) => r.body as RegistrationResponse)
    );
  }

  /**
   * Path part for operation authorizeAccount
   */
  static readonly AuthorizeAccountPath = '/public/authorize';

  /**
   * Authorize.
   *
   * Authorize Account
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `authorizeAccount()` instead.
   *
   * This method sends `application/json` and handles request body of type `application/json`.
   */
  authorizeAccount$Response(params?: {

    /**
     * AuthorizationRequest
     */
    body?: AuthorizationRequest
  }): Observable<StrictHttpResponse<AuthorizationResponse>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.AuthorizeAccountPath, 'post');
    if (params) {
      rb.body(params.body, 'application/json');
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<AuthorizationResponse>;
      })
    );
  }

  /**
   * Authorize.
   *
   * Authorize Account
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `authorizeAccount$Response()` instead.
   *
   * This method sends `application/json` and handles request body of type `application/json`.
   */
  authorizeAccount(params?: {

    /**
     * AuthorizationRequest
     */
    body?: AuthorizationRequest
  }): Observable<AuthorizationResponse> {

    return this.authorizeAccount$Response(params).pipe(
      map((r: StrictHttpResponse<AuthorizationResponse>) => r.body as AuthorizationResponse)
    );
  }

  /**
   * Path part for operation authenticateAccountPublic
   */
  static readonly AuthenticateAccountPublicPath = '/public/authentication/login';

  /**
   * Authenticate account.
   *
   * Authenticate Account
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `authenticateAccountPublic()` instead.
   *
   * This method sends `application/social-authentication+json` and handles request body of type `application/social-authentication+json`.
   */
  authenticateAccountPublic$Response(params?: {
    tenant?: string;
    body?: AuthenticationSocialRequest
  }): Observable<StrictHttpResponse<(AuthenticationResponse | UnknownDeviceLoginResponse)>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.AuthenticateAccountPublicPath, 'post');
    if (params) {
      rb.header('tenant', params.tenant, {});
      rb.body(params.body, 'application/social-authentication+json');
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<(AuthenticationResponse | UnknownDeviceLoginResponse)>;
      })
    );
  }

  /**
   * Authenticate account.
   *
   * Authenticate Account
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `authenticateAccountPublic$Response()` instead.
   *
   * This method sends `application/social-authentication+json` and handles request body of type `application/social-authentication+json`.
   */
  authenticateAccountPublic(params?: {
    tenant?: string;
    body?: AuthenticationSocialRequest
  }): Observable<(AuthenticationResponse | UnknownDeviceLoginResponse)> {

    return this.authenticateAccountPublic$Response(params).pipe(
      map((r: StrictHttpResponse<(AuthenticationResponse | UnknownDeviceLoginResponse)>) => r.body as (AuthenticationResponse | UnknownDeviceLoginResponse))
    );
  }

  /**
   * Path part for operation updateOnePublicAccount
   */
  static readonly UpdateOnePublicAccountPath = '/public/accounts';

  /**
   * Account Update.
   *
   * Update a DG account
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `updateOnePublicAccount()` instead.
   *
   * This method sends `application/change-account-legacy-jwt+json` and handles request body of type `application/change-account-legacy-jwt+json`.
   */
  updateOnePublicAccount$Response(params?: {

    /**
     * Only is required in the content types with **jwt** in the name
     */
    authorization?: string;
    body?: UpdateAccountLegacyRequest
  }): Observable<StrictHttpResponse<(UpdateChangesAppliedResponse | UpdateSendCodeResponse)>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.UpdateOnePublicAccountPath, 'put');
    if (params) {
      rb.header('authorization', params.authorization, {});
      rb.body(params.body, 'application/change-account-legacy-jwt+json');
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<(UpdateChangesAppliedResponse | UpdateSendCodeResponse)>;
      })
    );
  }

  /**
   * Account Update.
   *
   * Update a DG account
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `updateOnePublicAccount$Response()` instead.
   *
   * This method sends `application/change-account-legacy-jwt+json` and handles request body of type `application/change-account-legacy-jwt+json`.
   */
  updateOnePublicAccount(params?: {

    /**
     * Only is required in the content types with **jwt** in the name
     */
    authorization?: string;
    body?: UpdateAccountLegacyRequest
  }): Observable<(UpdateChangesAppliedResponse | UpdateSendCodeResponse)> {

    return this.updateOnePublicAccount$Response(params).pipe(
      map((r: StrictHttpResponse<(UpdateChangesAppliedResponse | UpdateSendCodeResponse)>) => r.body as (UpdateChangesAppliedResponse | UpdateSendCodeResponse))
    );
  }

  /**
   * Path part for operation confirmAccountUpdateByCode
   */
  static readonly ConfirmAccountUpdateByCodePath = '/public/accounts/{code}/update';

  /**
   * Account Update Confirmation.
   *
   * Update a DG account Confirmation
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `confirmAccountUpdateByCode()` instead.
   *
   * This method doesn't expect any request body.
   */
  confirmAccountUpdateByCode$Response(params: {
    code: string;
  }): Observable<StrictHttpResponse<UpdateChangesAppliedResponse>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.ConfirmAccountUpdateByCodePath, 'get');
    if (params) {
      rb.path('code', params.code, {});
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<UpdateChangesAppliedResponse>;
      })
    );
  }

  /**
   * Account Update Confirmation.
   *
   * Update a DG account Confirmation
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `confirmAccountUpdateByCode$Response()` instead.
   *
   * This method doesn't expect any request body.
   */
  confirmAccountUpdateByCode(params: {
    code: string;
  }): Observable<UpdateChangesAppliedResponse> {

    return this.confirmAccountUpdateByCode$Response(params).pipe(
      map((r: StrictHttpResponse<UpdateChangesAppliedResponse>) => r.body as UpdateChangesAppliedResponse)
    );
  }

  /**
   * Path part for operation confirmNewDeviceByCode
   */
  static readonly ConfirmNewDeviceByCodePath = '/public/accounts/device/{code}/confirm';

  /**
   * Confirm new Device.
   *
   * Confirm new Device
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `confirmNewDeviceByCode()` instead.
   *
   * This method doesn't expect any request body.
   */
  confirmNewDeviceByCode$Response(params: {
    code: string;
  }): Observable<StrictHttpResponse<UpdateChangesAppliedResponse>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.ConfirmNewDeviceByCodePath, 'get');
    if (params) {
      rb.path('code', params.code, {});
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<UpdateChangesAppliedResponse>;
      })
    );
  }

  /**
   * Confirm new Device.
   *
   * Confirm new Device
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `confirmNewDeviceByCode$Response()` instead.
   *
   * This method doesn't expect any request body.
   */
  confirmNewDeviceByCode(params: {
    code: string;
  }): Observable<UpdateChangesAppliedResponse> {

    return this.confirmNewDeviceByCode$Response(params).pipe(
      map((r: StrictHttpResponse<UpdateChangesAppliedResponse>) => r.body as UpdateChangesAppliedResponse)
    );
  }

  /**
   * Path part for operation publicControllerAssociateSocialNetwork
   */
  static readonly PublicControllerAssociateSocialNetworkPath = '/public/social-networks/associate';

  /**
   * Associate social network.
   *
   * Associate Social Network
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `publicControllerAssociateSocialNetwork()` instead.
   *
   * This method sends `application/json` and handles request body of type `application/json`.
   */
  publicControllerAssociateSocialNetwork$Response(params?: {

    /**
     * SocialNetworkLogin
     */
    body?: SocialNetworkLogin
  }): Observable<StrictHttpResponse<SocialNetworkAddedResponse>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.PublicControllerAssociateSocialNetworkPath, 'post');
    if (params) {
      rb.body(params.body, 'application/json');
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<SocialNetworkAddedResponse>;
      })
    );
  }

  /**
   * Associate social network.
   *
   * Associate Social Network
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `publicControllerAssociateSocialNetwork$Response()` instead.
   *
   * This method sends `application/json` and handles request body of type `application/json`.
   */
  publicControllerAssociateSocialNetwork(params?: {

    /**
     * SocialNetworkLogin
     */
    body?: SocialNetworkLogin
  }): Observable<SocialNetworkAddedResponse> {

    return this.publicControllerAssociateSocialNetwork$Response(params).pipe(
      map((r: StrictHttpResponse<SocialNetworkAddedResponse>) => r.body as SocialNetworkAddedResponse)
    );
  }

  /**
   * Path part for operation publicControllerGetSocialNetworks
   */
  static readonly PublicControllerGetSocialNetworksPath = '/public/social-networks';

  /**
   * Get social networks.
   *
   * Get associated social platforms
   *
   * This method provides access to the full `HttpResponse`, allowing access to response headers.
   * To access only the response body, use `publicControllerGetSocialNetworks()` instead.
   *
   * This method doesn't expect any request body.
   */
  publicControllerGetSocialNetworks$Response(params?: {
  }): Observable<StrictHttpResponse<AccountSocialNetworksResponse>> {

    const rb = new RequestBuilder(this.rootUrl, PublicService.PublicControllerGetSocialNetworksPath, 'get');
    if (params) {
    }

    return this.http.request(rb.build({
      responseType: 'json',
      accept: 'application/json'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<AccountSocialNetworksResponse>;
      })
    );
  }

  /**
   * Get social networks.
   *
   * Get associated social platforms
   *
   * This method provides access to only to the response body.
   * To access the full response (for headers, for example), `publicControllerGetSocialNetworks$Response()` instead.
   *
   * This method doesn't expect any request body.
   */
  publicControllerGetSocialNetworks(params?: {
  }): Observable<AccountSocialNetworksResponse> {

    return this.publicControllerGetSocialNetworks$Response(params).pipe(
      map((r: StrictHttpResponse<AccountSocialNetworksResponse>) => r.body as AccountSocialNetworksResponse)
    );
  }

}

exejutable avatar Nov 23 '21 14:11 exejutable

The problem is that the generator handles "general" content types - Text vs Json vs Image vs Binary, etc. In this example, both are JSON, which confuses the generator. A workaround would be to have a single content type, but differentiating objects in the data itself. Even IMHO, that would be a cleaner approach. I'm sorry, but I'm not having much time to work on the generator. Feel free to submit a PR if you think this is important, but I don't see issue as a priority.

luisfpg avatar Jan 03 '22 11:01 luisfpg

The problem is that the generator handles "general" content types - Text vs Json vs Image vs Binary, etc. In this example, both are JSON, which confuses the generator. A workaround would be to have a single content type, but differentiating objects in the data itself. Even IMHO, that would be a cleaner approach. I'm sorry, but I'm not having much time to work on the generator. Feel free to submit a PR if you think this is important, but I don't see issue as a priority.

If you can indicate me where are the classes involved i can make the change.

exejutable avatar Jan 04 '22 15:01 exejutable