json-schema-ref-parser icon indicating copy to clipboard operation
json-schema-ref-parser copied to clipboard

Ability to skip dereferencing inline/internal $ref values

Open denver-HJS opened this issue 4 years ago • 6 comments

Hi all,

@stoplight/json-ref-resolver offers options to skip dereferencing either internal or remote references. I've found this feature to be very useful, but now that project is now deprecated and points to this one.

I was wondering if there's already a way to accomplish the same thing using this library?

Essentially I'm hoping to preserve this behavior of taking an example schema:

{
   "paths": {
     "/awesome/endpoint": {
       "post": {
          "responses": {
            "400": {
              "$ref": "#/components/responses/400"
            }
          }
       }
     }
   },
   "components": {
     "responses": {
       "400": {
         "$ref": "https://example.com/path/to/my/oas/file.oas3.json#/components/responses/400"
     }
  }
}

and only dereference the remote HTTP reference:

{
   "paths": {
     "/awesome/endpoint": {
       "post": {
          "responses": {
            "400": {
              "$ref": "#/components/responses/400"
            }
          }
       }
     }
   },
   "components": {
     "responses": {
       "400": {
         "description": "The request syntax was malformed and could not be processed.",
          "content": {
             "application/json": {
                "type": "object",
                "properties": {
                  "statusCode": {
                    "type": "integer"
                  },
                  "message": {
                    "type": "string"
                  }
                }
             }
          }
       }
   }
}

@P0lip sorry to ping you directly, but I noticed that you've been active in both projects. If you have any pointers it would be much appreciated.

Hopefully this summary makes sense. Thanks!

denver-HJS avatar Feb 04 '21 05:02 denver-HJS

@philsturgeon sorry to mention you directly too, but I see in one of the issues in the now deprecated Stoplight project referenced above that you commented that you've been able to meet your requirements with this library. I'm wondering if you have any suggestions for using it to only dereference the remote references and leave the inline ones in place?

denver-HJS avatar Feb 10 '21 21:02 denver-HJS

Why not use bundle if you're ok with references but want them to exist as local refs instead? That's exactly what it's for. :)

philsturgeon avatar Feb 12 '21 11:02 philsturgeon

Hmmm, I thought I tried this but I might have been dereferencing & bundling in some incorrect combination. I'll give that another look. Thanks!

denver-HJS avatar Feb 15 '21 19:02 denver-HJS

I have the same issue, but I'm not able to solve it with bundle. Here my example: oas-root.yaml

paths:
  /example1:
    get:
      $ref: "./oas-example1.yaml"
  /example2:
    get:
      $ref: "#/components/schemas/Error"
components:
  schemas:
    Error: "...."

oas-example1.yaml

ErrorResponse:
  $ref: "#/components/schemas/Error"

Which returns this error: MissingPointerError: Token "components" does not exist.

The only solution I found is to skip JSON Pointer references checks with some extra option like options.resolve.internal at https://github.com/APIDevTools/json-schema-ref-parser/blob/master/lib/ref.js#L179 or as @denver-HJS mention to have options.resolve.skipInternal

agavazov avatar May 21 '21 22:05 agavazov

This is not a bug, it's saying that #/components/schemas/Error does not exist in oas-example1.yaml because, it doesnt! :D

Each ref needs to point to the filepath then # is the start of the pointer. Perhaps you could make a shared model for ErrorResponse.yml then all locations point to that?

https://blog.stoplight.io/keeping-openapi-dry-and-portable

philsturgeon avatar Aug 15 '21 10:08 philsturgeon

The only method I currently found to ignore the parsing error of local references is to do something like this:

const $RefParser = require("@apidevtools/json-schema-ref-parser")

async function bundle(root) {
    let bundle = {}
    try {
        bundle = await $RefParser.bundle(root, {
            continueOnError: true,
        })
    } catch (e) {
        bundle = e.files.schema
    }
    return bundle
}

const root = './index.yaml'
bundle(root).then(bundle =>{
    console.log(bundle)
})

Apparently even if the bundle function fails the schema is generated ignoring the local references

marc0l92 avatar Dec 08 '21 18:12 marc0l92