Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility to add onBundle callback? #346

Open
graynk opened this issue Apr 23, 2024 · 1 comment
Open

Possibility to add onBundle callback? #346

graynk opened this issue Apr 23, 2024 · 1 comment

Comments

@graynk
Copy link

graynk commented Apr 23, 2024

Hi! This is just an issue to get your opinion on adding a new onBundle callback as part of the options object, similar to onDereference. I'm willing to contribute this, if you're open to adding this feature. Here's some context on why we need it:

We use json-schema-ref-parser to parse and bundle OpenAPI and AsyncAPI files, heavily relying on overriding the resolvers to fetch external references from GitHub.

One issue with that is: if external $ref contains $schema and $id - the bundle() function keeps them, but the resulting OpenAPI document fails validation, due to unexpected additional properties. Here's a concrete minimal example:

schema.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "someId",
  "type": "object",
  "properties": {
    "exampleProperty": {
      "description": "Lorem ipsum and so on",
      "type": "boolean"
    }
  }
}

api.yaml

openapi: "3.0.3"
info:
  title: Example API
  version: "1.0"
servers:
  - url: https://localhost:3000/v1
paths:
  /example:
    get:
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: 'schema.json'

script.ts

import fs from 'node:fs/promises';
import $RefParser from '@apidevtools/json-schema-ref-parser';
import swaggerParser from '@apidevtools/swagger-parser';
import yaml from 'yaml';

const body = await fs.readFile('api.yaml', 'utf8');
const content = yaml.parse(body);
const result = await $RefParser.bundle(content, { resolve: { external: true } });
await fs.writeFile('bundledApi.yaml', yaml.stringify(result));
await swaggerParser.validate(result);

bundledApi.yaml

openapi: 3.0.3
info:
  title: Example API
  version: "1.0"
servers:
  - url: https://localhost:3000/v1
paths:
  /example:
    get:
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $schema: http://json-schema.org/draft-07/schema#
                $id: someId
                type: object
                properties:
                  exampleProperty:
                    description: Lorem ipsum and so on
                    type: boolean

This fails validation with:

SyntaxError: Swagger schema validation failed.
  #/paths/~1example/get/responses/200/content/application~1json/schema must NOT have additional properties
  #/paths/~1example/get/responses/200/content/application~1json/schema must NOT have additional properties
  #/paths/~1example/get/responses/200/content/application~1json/schema must have required property '$ref'
  #/paths/~1example/get/responses/200/content/application~1json/schema must match exactly one schema in oneOf
  #/paths/~1example/get/responses/200 must have required property '$ref'
  #/paths/~1example/get/responses/200 must match exactly one schema in oneOf

Removing $schema and $id would make it pass the validation, however there doesn't seem to be an easy way of doing that. If we were calling dereference() instead of bundle() - the problem would be trivially solved with something like this:

const result = await $RefParser.dereference(content, {
  resolve: { external: true },
  dereference: {
    onDereference: (path: string, value: JSONSchemaObject) => {
      if ('$schema' in value) {
        delete value.$schema;
      }
    },
  },
});

Do you think adding the possibility to pass in an onBundle callback would make sense here? Or can our problem be solved in some other way? Appreciate any feedback.

@jonluca
Copy link
Collaborator

jonluca commented Apr 27, 2024

That sounds reasonable, we'd add the feature if you make a PR

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

No branches or pull requests

2 participants