wework / speccy

Well Spectually 🤓 Enforce quality rules on your OpenAPI 3.0.x specifications.
http://speccy.io
MIT License
828 stars 78 forks source link

[question] How to copy definitions as is onto components/schema instead of inline #315

Open mariotoffia opened 5 years ago

mariotoffia commented 5 years ago

Detailed description

This is a question!

I've got several files that I wish to combine. For example I've defined Event object under event.yaml and under local-api.yaml i use those events in response objects under components/schema.

event.yml snippet:

Event:
  type: object
  additionalProperties: true
  maxProperties: 100
  description: >
    This is the base event object. Note that custom additional
    properties after the specified ones are allowed.
  properties:
    id:
      type: string
      format: uuid

and local-api.yaml snippet (under components/schema):

    LatechedEventQueueResponse:
      type: object
      description: The result of a event latched queue query
      properties:
        events:
          type: array
          items:
            oneOf:
              - $ref: 'event/event.yaml#/Event'
              - $ref: 'event/event.yaml#/ConnectionEvent'
            discriminator:
              propertyName: ot
      xml:
        name: latched-events

When running speccy resolve --json-schema spec/local-api.yaml > DIT-device-local-api.yaml it will inline the event under events property and the other responses that also referenced event/event.yaml#/Event will instead reference ```#/components/schemas/LatechedEventQueueResponse/properties/events/items/oneOf/0```` such as:

    EventQueueResponse:
      type: object
      description: The result of a event queue query
      properties:
        events:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/LatechedEventQueueResponse/properties/events/items/oneOf/0'
              - $ref: '#/components/schemas/LatechedEventQueueResponse/properties/events/items/oneOf/1'
            discriminator:
              propertyName: ot

Context

I wish, if possible, that instead of inline, copy the objects under component/schema and adjust all references to refer to those instead of the external file.

This will allow for client code auto generation to be more concise.

Possible implementation

N/A

Your environment

node, npm, windows 10

Cheers, Mario

MikeRalphson commented 5 years ago

The reason oas-kit and therefore speccy doesn't do this automatically is that "naming things is hard" and there are possible naming collisions to be aware of.

If you want resolved external $refs to always appear under components/schemas then use an internal $ref to components/schemas and put the external $ref there. For example:

schemas:
  LatechedEventQueueResponse:
      type: object
      description: The result of a event latched queue query
      properties:
        events:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/Event'
              - $ref: '#/components/schemas/ConnectionEvent'
            discriminator:
              propertyName: ot
      xml:
        name: latched-events
  Event:
    $ref: 'event/event.yaml#/Event'
  ConnectionEvent:
    $ref: 'event/event.yaml#/ConnectionEvent'
mariotoffia commented 5 years ago

@MikeRalphson Thanks! :)

I've done exactly as you're suggesting and that part works great!

However, I stumble into problems when I reference a external yaml spec that in it's turn references other yaml and I wish to have those as objects (both for reuse and code generation). So this, as I see it, workaround just works for first level references.

And when it comes to naming - I totally agree that I could get name clashes - but since it may be simple to output an error in that case e.g. Duplicate Object or some other error indicating just that.

Cheers & many thanks! Mario

cvgaviao commented 5 years ago

@MikeRalphson, Unfortunately the tool swagger-parser and some openapi-generators was complaining with the file generated by speccy. They was expecting to see local references in component/*.

So, my workaround for current project was to copy every shared component from the referenced files and paste in the main file and let my editor to show which one is not being used and removed them...

I also agree with Mario that a message error for Duplicate Object would be better than the current approach. :)

jwgcooke commented 5 years ago

I am bumping my head against this specifically when using speccy to serve (valid) definitions of items the use oneOf and a discriminator. There appears to be a disconnect between what redoc is expecting and what speccy is generating and they are totally incompatible.

apparently redoc expects references to explicitly exist as a $ref in to something in schemas (which is fine and works perfectly) but speccy will resolve the refs in ways that are incompatible with redoc