Giter Site home page Giter Site logo

Comments (8)

jordanshatford avatar jordanshatford commented on May 23, 2024 1

Can you provide a reasoning for why these types aren't in your OpenAPI spec?

from openapi-ts.

dymovalex avatar dymovalex commented on May 23, 2024

Thank you for your response!

There is a module A that provides general UI logic, components etc, including generated abstract entities types based on the OpenAPI schema of this module.

And also there are several modules B, C, etc., which pull up module A as a dependency, and these modules describe types that inherit from the abstract entities types of module A.

Moreover, module A will also be used by third party developers who will add their own logic on top, and I would like them to directly import the types of module A instead of describing copies, otherwise there will be duplication of types descriptions and potential data inconsistency.

I don't know if I could properly explain the need, but import mappings are used in some other generators, for example, in https://github.com/OpenAPITools/openapi-generator (for multiple languages, including TS), because this adds more flexibility to the generation configuration.

from openapi-ts.

mrlubos avatar mrlubos commented on May 23, 2024

@dymovalex are you able to share a sample OpenAPI spec with current and expected results?

Are you currently using the library linked in your comment? I assume you're not using this package since it doesn't support the feature you're asking for. Why are you looking to switch?

from openapi-ts.

dymovalex avatar dymovalex commented on May 23, 2024

@mrlubos

We've been using openapi-typescript-codegen in the project for a couple of years, but now the need for import mappings support has come to light.

Therefore, I am looking now for a suitable solution. The simplest solution for me, of course, if mappings support appears in this maintainable fork of openapi-typescript-codegen. Or I'll have to look for a completely different generator.

In the package I linked to in the comments above, two generators were considered:

typescript-fetch - does not support mappings

typescript - supports mappings, but in a version that differs from one we are using to generate Java code on the backend. Due to the fact that the project is large with custom mustache templates, transferring the backend to a new version seems to be a difficult task, and pulling two different versions of generators into the project seems inconvenient and potentially unreliable. Plus, to be honest, I don't really like the resulting generated code, it's very verbose and confusing (classes instead of types, for example).

And as for the samples, is not a real case, but describes the main idea:

Module A

We have schema:

components:
  schemas:
    AbstractComponent:
      description: Abstract component
      properties:
        id:
          type: string
      required:
          - id
   
    AbstractButton:
      description: Abstract button
      properties:
        width:
          type: number

and result type:

/**
 * Abstract component
 */
export type AbstractComponent = {
    id: string
};

/**
 * Abstract button
 */
export type AbstractButton = {
    width?: number
};

Module B:

Current:

We have schema below. And we are forced to describe copies of AbstractComponent and AbstractButton in this module if we want to refer to these types:

components:
  schemas:
    AbstractComponent:
      description: Abstract component
      properties:
        id:
          type: string
      required:
          - id
   
    AbstractButton:
      description: Abstract button
      properties:
        width:
          type: number

    Button:
      description: Button
      allOf:
        - $ref: "#/components/schemas/AbstractComponent"
        - $ref: "#/components/schemas/AbstractButton"
        - type: object
          properties:
            some:
              type: string

And result models.ts will look like this:

/**
 * Abstract component
 */
export type AbstractComponent = {
    id: string
};

/**
 * Abstract button
 */
export type AbstractButton = {
    width?: number
};

/**
 * Button
 */
export type Button = AbstractComponent & AbstractButton & {
    some?: string
};

Expected:

We describe config openapi-ts.importMappings.mjs in root directory:

export default {
  AbstractComponent: 'moduleA/AbstractComponent',
  AbstractButton: 'moduleA/AbstractButton',
}

We have schema:

components:
  schemas:
    Button:
      description: Button
      allOf:
        - $ref: "#/components/schemas/AbstractComponent"
        - $ref: "#/components/schemas/AbstractButton"
        - type: object
          properties:
            some:
              type: string

And result models.ts will look like this:

import { AbstractComponent } from 'moduleA/AbstractComponent';
import { AbstractButton } from 'moduleB/AbstractButton';

/**
 * Button
 */
export type Button = AbstractComponent & AbstractButton & {
    some?: string
};

from openapi-ts.

jordanshatford avatar jordanshatford commented on May 23, 2024

@dymovalex would what I propose here solve your problem?

Specifically:

    TypeA:
      $ref: './some/path/type_a.yaml#/components/schemas/TypeA'

or

    TypeA:
      $ref: 'http://some-url.com/openapi.yamll#/components/schemas/TypeA'

See relevant openapi docs: here. When using a reference from an external file or url we do handle generating the models/etc. So rather than providing third partys with module A, could you:

  1. Provide module A's openapi spec for them to use and they can extend there openapi spec off it. This could be a url or file provided.
  2. Generate module A to provide to third partys, but internally reference module A in your module B/C?

from openapi-ts.

dymovalex avatar dymovalex commented on May 23, 2024

@jordanshatford

Sounds like it might help, I'll try it. Thank you!

UPD
So far I've faced a problem that all the entities that I refer to through the local ref are typed as any.

Maybe the problem is that the schema in the project consists of many schemas, which merge into one during the build.

from openapi-ts.

jordanshatford avatar jordanshatford commented on May 23, 2024

@dymovalex are you able provide an example of what module A and B specs look like? I could try it out myself and see what is happening.

from openapi-ts.

dymovalex avatar dymovalex commented on May 23, 2024

@jordanshatford

I solved problem with any, it was due to type was not specified like 'object'.

But there's another problem:

moduleA.yaml

There are types Action and DataType

components:
  schemas:
    Action:
      type: object
      properties:
        actionId:
          type: string
        parameterType:
          $ref: "#/components/schemas/DataType"
        returnType:
          $ref: "#/components/schemas/DataType"
      additionalProperties: false
      required:
        - actionId
        - parameterType
        - returnType
    
    DataType:
      type: object
      properties:
        a:
          type: string
        b:
          type: integer
        properties:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/DataType"
      additionalProperties: false
      required:
        - a
        - b

moduleB.yaml

Here DataType is used both separately and as part of the Action type

components:
  schemas:
    SomeAction:
      type: object
      properties:
        actionProps:
          $ref: '../../../moduleA.yaml#/components/schemas/Action'

    Component:
      type: object
      properties:
        name:
          type: string
        type:
          $ref: '../../../moduleA.yaml#/components/schemas/DataType'
      additionalProperties: false
      required:
        - name
        - type

As a result I get in module B:

  1. Not a reference to the type, but a copy of it (it seems that you can live with this, but it's not very convenient)
  2. I get a strange import of the Component_properties_type, which actually does not exist and which causes a build error
import type { Component_properties_type } from './Component_properties_type';

export type SomeAction = {
    actionProps?: {
        actionId: string;
        parameterType: Component_properties_type;
        returnType: Component_properties_type;
    };
}
import type { Component_properties_type } from './Component_properties_type';

export type Component = {
    name: string;
    type: {
        a: string;
        b: number;
        properties?: Record<string, Component_properties_type>;
    };
};

I suppose that adding a relative reference to the DataType in Action in Module A itself can help fix it (not sure) but:

  1. Using relative references to types definitions that are in the same module and in the same schema is confusing
  2. There can be a lot of nesting in types and this problem will lead to 'relative path hell'
  3. Itโ€™s not entirely clear what to do with types that have recursion, as DataType. If we also take into account the problem with copying a type rather than referring to it, Iโ€™m not sure that this is basically possible to do.

Based on the above, it seems that in my case itโ€™s simply impossible to do what I'm looking for without import mappings.

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.