Openapi-generator: [BUG][typescript-angular] oneOf file not getting created

Created on 13 Feb 2019  路  11Comments  路  Source: OpenAPITools/openapi-generator

Description

I have an api spec that uses the "oneOf" attribute and while it's showing the file and interface in the default.service.ts file, it's not actually creating the file.

In the below yaml file, i have a response body returning oneOf: Beneficiary, IndividualBeneficiary, TrustBeneficiary, and CharityBeneficiary.
When generated, the default.service.ts file has the following line in the imports section:

import { OneOfBeneficiaryIndividualBeneficiaryTrustBeneficiaryCharityBeneficiaryModel } from '../model/one-of-beneficiary-individual-beneficiary-trust-beneficiary-charity-beneficiary';

but the "one-of-beneficiary-individual-beneficiary-trust-beneficiary-charity-beneficiary" file isn't actually generated.

openapi-generator version

4.0.0-SNAPSHOT

OpenAPI declaration file content or url

member.yaml

openapi: '3.0.1'
info:
  version: '0.1'
  title: Member API
security:
  - session: []
paths:
  '/members/{memberId}/beneficiaries':
    parameters:
      - name: MP-Group
        in: header
        description: the identifier of the group in which the operation should be performed
        required: true
        schema:
          type: integer
      - name: memberId
        in: path
        required: true
        schema:
          type: integer
    get:
      operationId: getMemberBeneficiaries
      parameters:
        - name: maskSsn
          in: query
          schema:
            type: boolean
            default: true
      responses:
        '200':
          description: found
          content:
            application/json:
              schema:
                type: array
                items:
                  oneOf:
                    - $ref: '#/components/schemas/Beneficiary'
                    - $ref: '#/components/schemas/IndividualBeneficiary'
                    - $ref: '#/components/schemas/TrustBeneficiary'
                    - $ref: '#/components/schemas/CharityBeneficiary'
        '403':
          description: |
            - forbidden: cannot unmask
components:
  schemas:
    Beneficiary:
      required:
        - type
      properties:
        id:
          type: integer
          readOnly: true
        type:
          description: |
            cannot change once created (i.e. an update will fail if different from previous type)
            a beneficiary of type ESTATE cannot be created, updated, or deleted
          type: string
          enum: [INDIVIDUAL,ESTATE,TRUST,CHARITY]
        details:
          type: string
        contact:
          $ref: 'shared.yaml#/components/schemas/Contact'
        allocations:
          type: array
          items:
            $ref: '#/components/schemas/BeneficiaryAllocation'
          readOnly: true
      discriminator:
        propertyName: type
        mapping:
          'INDIVIDUAL': '#/components/schemas/IndividualBeneficiary'
          'ESTATE': '#/components/schemas/Beneficiary'
          'TRUST': '#/components/schemas/TrustBeneficiary'
          'CHARITY': '#/components/schemas/CharityBeneficiary'
    IndividualBeneficiary:
      allOf:
        - $ref: '#/components/schemas/Beneficiary'
        - required:
            - relationshipToMember
          properties:
            dependentId:
              description: note that when saving, if this is set, the other fields will be ignored
              type: integer
            name:
              $ref: 'shared.yaml#/components/schemas/Name'
            relationshipToMember:
              type: string
            birthDate:
              type: string
              format: date
            ssn:
              type: string
    TrustBeneficiary:
      allOf:
        - $ref: '#/components/schemas/Beneficiary'
        - required:
            - name
            - trustAgreementDate
          properties:
            name:
              type: string
            trustee:
              $ref: 'shared.yaml#/components/schemas/Name'
            trustAgreementDate:
              type: string
              format: date
    CharityBeneficiary:
      allOf:
        - $ref: '#/components/schemas/Beneficiary'
        - required:
            - name
          properties:
            name:
              type: string
            taxId:
              type: string
    BeneficiaryAllocation:
      properties:
        product:
          type: string
        percent:
          type: number
          format: float
        type:
          $ref: '#/components/schemas/BeneficiaryAllocationType'
    BeneficiaryAllocationType:
      type: string
      enum: [PRIMARY,SECONDARY,CONTINGENT]
    IdentifierType:
      properties:
        id:
          type: integer
        type:
          type: string
          enum: [SSN,MEMBER,CUSTOM,EMPLOYEE_ID,CIF_NUMBER]
        name:
          description: this is the display name
          type: string
        validationRegex:
          type: string
        memberEligible:
          type: boolean
        dependentEligible:
          type: boolean
  securitySchemes:
    session:
      type: apiKey
      in: cookie
      name: SESSIONID

shared.yaml

openapi: '3.0.1'
info:
  version: '0.1'
  title: Shared Components
  description: |
    Due to the restrictions of current programs, instead of this being a standard YAML file, this must be a valid OAS
    file. As such, an empty paths object is included. This normally means that there are paths that exist here and are
    not available to be used, but in this case, no paths exist.
paths: {}
components:
  parameters:
    groupHeader:
      name: MP-Group
      in: header
      description: the identifier of the group in which the operation should be performed
      required: true
      schema:
        type: integer
    optionalGroupHeader:
      name: MP-Group
      in: header
      description: the identifier of the group in which the operation should be performed
      required: false
      schema:
        type: integer
    referenceDate:
      name: date
      in: query
      description: |
        the date at which the operation should be considered
        if no value is provided, assume the date to be TODAY
      required: false
      schema:
        type: string
        format: date
    searchProperty:
      name: property
      in: query
      description: the property on which to perform a search
      required: true
      schema:
        type: string
    searchValue:
      name: value
      in: query
      description: |
        the value of the property on which to perform a search
        note that this should be able to include a comma-separated list of values
      required: true
      schema:
        type: string
    optionalSearchProperty:
      name: property
      in: query
      description: the optional property on which to perform a search
      required: false
      schema:
        type: string
    optionalSearchValue:
      name: value
      in: query
      description: |
        the value of the optional property on which to perform a search
        note that this should be able to include a comma-separated list of values
      required: false
      schema:
        type: string
    sort:
      name: sort
      in: query
      description: the property and direction on which to sort
      schema:
        type: string
      example: name,desc
    page:
      name: page
      in: query
      description: the page of results to receive
      schema:
        type: string
    size:
      name: size
      in: query
      description: the size of the result set
      schema:
        type: string
  responses:
    Duplicate:
      description: |
        - duplicate: duplicate found
      headers:
        Location:
          description: the location of the duplicate
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Name:
      required:
        - firstName
        - lastName
      properties:
        firstName:
          type: string
        middleName:
          type: string
        lastName:
          type: string
        suffix:
          type: string
        maidenName:
          type: string
        nickname:
          type: string
    Contact:
      required:
        - address
      properties:
        address:
          $ref: '#/components/schemas/Address'
        phoneNumbers:
          type: array
          items:
            $ref: '#/components/schemas/PhoneContact'
        emailAddresses:
          type: array
          items:
            $ref: '#/components/schemas/EmailContact'
        phoneNumber:
          type: string
          pattern: '^\d{3}-?\d{3}-?\d{4}$'
          deprecated: true
        cellPhoneNumber:
          type: string
          pattern: '^\d{3}-?\d{3}-?\d{4}$'
          deprecated: true
        email:
          type: string
          deprecated: true
    UserContact:
      required:
        - address
      properties:
        address:
          $ref: '#/components/schemas/Address'
        phoneNumbers:
          type: array
          items:
            allOf:
              - $ref: '#/components/schemas/PhoneContact'
              - $ref: '#/components/schemas/UserContactParameters'
        emailAddresses:
          type: array
          items:
            allOf:
              - $ref: '#/components/schemas/EmailContact'
              - $ref: '#/components/schemas/UserContactParameters'
        phoneNumber:
          type: string
          pattern: '^\d{3}-?\d{3}-?\d{4}$'
          deprecated: true
        cellPhoneNumber:
          type: string
          pattern: '^\d{3}-?\d{3}-?\d{4}$'
          deprecated: true
        email:
          type: string
          deprecated: true
    PhoneContact:
      properties:
        phoneNumber:
          type: string
          pattern: '^\d{3}-?\d{3}-?\d{4}$'
        extension:
          type: string
        type:
          description: one of /static/phoneNumberTypes
          type: string
    EmailContact:
      properties:
        email:
          type: string
        type:
          description: one of /static/emailTypes
          type: string
    UserContactParameters:
      properties:
        verified:
          type: boolean
          readOnly: true
        primary:
          type: boolean
          default: false
    Address:
      required:
        - state
        - zip
      properties:
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        state:
          type: string
          maxLength: 2
        zip:
          type: string
          pattern: '^\d{5}?(-\d{4})?$'
        countyId:
          type: integer
        country:
          description: one of /static/countries
          type: string
    Validity:
      required:
        - effectiveStarting
      properties:
        effectiveStarting:
          type: string
          format: date
        expiresAfter:
          description: must be after effectiveStarting
          type: string
          format: date
    Error:
      properties:
        status:
          type: integer
        code:
          type: string
        message:
          type: string
          description: not included in QA or higher environments
        details:
          type: array
          items:
            $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      properties:
        objectId:
          description: Included in case the error refers to a list of objects. Otherwise null.
          type: integer
        field:
          type: string
        message:
          type: string
          description: not included in QA or higher environments

config.json

{
    "npmName":"Not important",
    "npmVersion":"0.0.1",
    "ngVersion":"7.2.1",
    "taggedUnions": true,
    "supportsES6": true,
    "ensureUniqueParams": false,
    "modelSuffix": "Model",
    "fileNaming": "kebab-case"
}
Command line used for generation

openapi-generator generate -c config.json -g typescript-angular -i ./member.yaml -o ./member

Other comments

I thought it might be due to the length of the names but I shortened them all to one letter names and got the same result.

TypeScript Bug

Most helpful comment

I am observing the same problem with typescript-axios. Here's a minimal reproducer:

---
openapi: 3.0.0

info:
  title: Generator bug reproducer
  version: 0.1.0

paths:
  /foo:
    get:
      operationId: foo
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  oneOf:
                    - type: number
                    - type: boolean

Causes:

api.ts:119:105 - error TS2304: Cannot find name 'OneOfnumberboolean'.

119         foo(options?: any): (axios?: AxiosInstance, basePath?: string) => AxiosPromise<{ [key: string]: OneOfnumberboolean; }> {
                                                                                                            ~~~~~~~~~~~~~~~~~~

All 11 comments

馃憤 Thanks for opening this issue!
馃彿 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

I am observing the same problem with typescript-axios. Here's a minimal reproducer:

---
openapi: 3.0.0

info:
  title: Generator bug reproducer
  version: 0.1.0

paths:
  /foo:
    get:
      operationId: foo
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  oneOf:
                    - type: number
                    - type: boolean

Causes:

api.ts:119:105 - error TS2304: Cannot find name 'OneOfnumberboolean'.

119         foo(options?: any): (axios?: AxiosInstance, basePath?: string) => AxiosPromise<{ [key: string]: OneOfnumberboolean; }> {
                                                                                                            ~~~~~~~~~~~~~~~~~~

Same here. Any hot fix so far?

Hello! I ran into this with Go today. :(

I ran into this issue with Python as well. Any resolution in sight?

Thanks!

I have the same issue with the angular variant :(

Same issue here.

Did anyone find a workaround for this to at least be able to 'spec' the same kind of models?

From my perspective (thing that worked for us), workaround was to rollback installed version of @openapitools/openapi-generator-cli to "0.0.11-3.3.4" ... This is a temporary solution for us until this bug is fixed

In my case, my issue was with OneOfstringinteger. I added the following file to my output path, and the codegen overwrites everything else:

// <output_dir>/model/oneOfstringinteger.ts
export type OneOfstringinteger = string | integer;

In my case, I was using the typescript-angular generator. For your respective case, you could create similar matching files, and if you set the --model-name-prefix flag, be sure to implement that with the naming of your class as well i.e.:

// <output_dir>/model/oneOfstringinteger.ts
// with --module-name-prefix Ab
export type AbOneOfstringinteger = string | integer;

Hope this is helpful in the short term.

Same here with typescript-fetch

Anyone found a way to generate the OneOf- type with an adapted mustache script? I also have this issue...

Was this page helpful?
0 / 5 - 0 ratings