Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Bundle: option to keep all refs but turn them into internal refs #29

Open
joffrey-bion opened this issue May 13, 2019 · 13 comments
Open

Comments

@joffrey-bion
Copy link

joffrey-bion commented May 13, 2019

The bundle command's current behaviour breaks the code generation in my current project.

Currently, with no special option, the bundle command inlines all $refs it finds on the first encounter, and then makes a reference to that local inline upon any subsequent encounter of the same reference.

For this example input:

main.yaml

swagger: '2.0'
info:
  version: 0.0.0
paths:
  /test1:
    get:
      parameters:
        - $ref: "./parameters.yaml#/parameters/param"
  /test2:
    get:
      parameters:
        - $ref: "./parameters.yaml#/parameters/param"

parameters.yaml

parameters:
  param:
    in: query
    name: myParam
    description: some demo parameter
    type: string
    pattern: '^[a-zA-Z]+$'
    required: true

The output I get from npx swagger-cli bundle main.yaml is the following:

swagger: '2.0'
info:
  version: 0.0.0
paths:
  /test1:
    get:
      parameters:
        - in: query
          name: myParam
          description: some demo parameter
          type: string
          pattern: '^[a-zA-Z]+$'
          required: true
  /test2:
    get:
      parameters:
        - $ref: '#/paths/~1test1/get/parameters/0'

When things get complicated, it can yield references like this:

$ref: '#/paths/~1analytics-ui/post/parameters/3/schema/items/properties/data/properties/page/properties/attributes'

And during code generation, this may turn into class names as long as this path, which is far from ideal.

It would be nice to have an option (e.g. --no-dereference) to preserve any reference, and simply bring the referenced declarations to the bundled file, but in a separate place within the file. This means that every reference will simply become a local declaration, but point to the same path.

Here is the output I would expect using this option on the same sample input that I provided:

bundle.yaml

swagger: '2.0'
info:
  version: 0.0.0
paths:
  /test1:
    get:
      parameters:
        - $ref: "#/parameters/param"
  /test2:
    get:
      parameters:
        - $ref: "#/parameters/param"

parameters:
  param:
    in: query
    name: myParam
    description: some demo parameter
    type: string
    pattern: '^[a-zA-Z]+$'
    required: true

Is there a way to achieve this currently?

@mgrzechocinski
Copy link

Would love to have this feature too!

@aaldredge
Copy link

aaldredge commented Aug 6, 2019

I would also like to have this feature. Specifically for OpenAPI 3, It would be great to have an option where bundle takes the referenced components and combines them in a components section in a bundled file, updating the original $ref that pointed to <file>#<componentPath> to point to #<componentPath> in the combined file.

@lorthirk
Copy link

A +1 on this, since I have a circular reference on my project and the code generation breaks if I don't use --dereference, which I have to because of the circular ref.

@stephanebachelier
Copy link

Thanks @lorthirk. Using --dereference fix my issues with circular ref. Having this feature would be really awesome !

@stephanebachelier
Copy link

@lorthirk @aaldredge @mgrzechocinski @joffrey-bion it seems that it already exists as long as you manage to avoid circular references. I add forgotten to add some schemas before the paths sections. Adding them before the path sections remove the circular references are they are already defined in the bundled schema.

Now mystery of references are rewritten using schema references :
From $ref: ../../components/responses/index.yaml#/Unauthenticated, the reference is changed to $ref: '#/components/responses/Unauthenticated' in the bundled file.

And the Unauthenticated is existing only in the #/components/responses section.

@aaldredge
Copy link

aaldredge commented Nov 11, 2019

@stephanebachelier thanks for the tag.

I tried with the latest version (2.3.4) using the command
swagger-cli bundle schemas/specs/all.yaml -t yaml -o schemas/resolved/all.yaml and I am still seeing the reference inlined and then referenced later with a $ref to the inlined occurrence. This results in refs such as:

- $ref: '#/paths/~1v1~1my~1path/get/parameters/0'

and this beauty

- $ref: '#/paths/~1v1~1my~1other-path/get/responses/200/content/application~1json/schema/allOf/1/properties/data/items/oneOf/0/properties/dataPoint/allOf/0'

@Bogdaan
Copy link

Bogdaan commented Jan 27, 2020

+1, very important feature. With --dereference we unable to generate valid client specification.

There is no semantic names for schemas:

  /random:
    get:
      summary: todo.
      description: todo.
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Successful result.
          content:
            application/json:
              schema:
                type: object
                required:
                  - categories
                properties:
                  categories:
                    type: object
                    required:
                      - name
                    properties:
                      name:
                        type: string

@theaxel
Copy link

theaxel commented Mar 2, 2020

Would be great to have a solution for this!
Running into the same issue.

@AlbinoDrought
Copy link

In our projects we only have a few shared schemas. A workaround we've been using because of this problem is to avoid code like this:

swagger: '2.0'
info:
  version: 0.0.0
paths:
  /test1:
    get:
      parameters:
        - $ref: "./parameters.yaml#/parameters/param"
  /test2:
    get:
      parameters:
        - $ref: "./parameters.yaml#/parameters/param"

and use code like this instead:

swagger: '2.0'
info:
  version: 0.0.0
paths:
  /test1:
    get:
      parameters:
        - $ref: "#/parameters/param"
  /test2:
    get:
      parameters:
        - $ref: "#/parameters/param"
parameters:
  param:
    $ref: "./parameters.yaml#/parameters/param"

This gets bundled into:

swagger: '2.0'
info:
  version: 0.0.0
paths:
  /test1:
    get:
      parameters:
        - $ref: "#/parameters/param"
  /test2:
    get:
      parameters:
        - $ref: "#/parameters/param"

parameters:
  param:
    in: query
    name: myParam
    description: some demo parameter
    type: string
    pattern: '^[a-zA-Z]+$'
    required: true

which works with our code generators but takes some extra lines.

@MaxDesplanches
Copy link

MaxDesplanches commented Nov 18, 2020

Hello there,

I am waiting to have ref internal or to ignore hasardous generation:
#/paths/~1users~1address~1%7Bid%7D/get/responses/200/content/application~1json/schema/properties/data

During this time, I am coding some split string things to get what I want in my original file to get internal components to bundle a valid file.

Thank in advance

@bu4ak
Copy link

bu4ak commented Mar 1, 2021

+

@aleskovets
Copy link

Looks related to APIDevTools/swagger-parser#127

@pauldraper
Copy link

pauldraper commented Sep 20, 2021

Copying from APIDevTools/swagger-parser#127 (comment)


The obvious -- if annoying -- workaround is to put components first, and reference everything there.

Example input

example.yml

openapi: "3.0.3"
components: # reference everything here
  schemas:
    a: { $ref: "./schema/a.yml" }
    b: { $ref: "./schema/b.yml" }
info:
  title: Example
  version: 0.0.0
paths:
  /a:
    get:
      responses:
        "200":
           content:
             application/json:
               schema: { $ref: "./schema/a.yml" }
           description: Success
  /b:
    get:
      responses:
        "200":
          content:
            application/json:
              schema: { $ref: "./schema/b.yml" }
          description: Success

schema/a.yml

properties:
  aName: { type: string }
  b: { $ref: "./b.yml" }

schema/b.yml

properties:
  bName: { type: string }
Example output
swagger-cli bundle example.yml

yields

openapi: 3.0.3
components:
  schemas:
    a:
      properties:
        aName:
          type: string
        b:
          $ref: '#/components/schemas/b'
    b:
      properties:
        bName:
          type: string
info:
  title: Example
  version: 0.0.0
paths:
  /a:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/a'
          description: Success
  /b:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/b'
          description: Success

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

No branches or pull requests