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

feat(openapi): support OpenAPI version 3.1 #882

Closed
wants to merge 21 commits into from

Conversation

SF97
Copy link
Contributor

@SF97 SF97 commented Jan 1, 2024

This PR circumvents AJV issue by replacing all $dynamicAnchor keywords in OpenAPI schema with a direct reference, using $ref. This has been suggested by @Jackman3005 in #573 (comment), which originally came from @seriousme, which already made this workaround in his own OpenAPI schema validation library, https://github.com/seriousme/openapi-schema-validator. From what I understand this shouldn't be an issue. Using $dynamicAnchor would allow this lib to replace OpenAPI specification definitions, which it does not do.

Changes

  • openapi.schema.validator.ts now creates a different AJV instance that supports JSON schema 2020-12 when it detects version 3.1. This AJV instance accepts the format media-range but does not validate its content. This validation can be made in another PR
  • Adds OpenAPI specification 3.1 with $dynamicAnchor references changed to $ref
  • Change test scripts to use Mocha's --extension flag. With the previous setup, the new tests weren't being picked up by the runner

OpenAPI 3.1 support

  • Support webhook property without any defined paths
  • Support an API with only components
  • Fully complete Open API 3.1 schema in type.ts
  • Support "summary" in Info Object
  • Support "identifier" field for SPDX licenses in License Object
  • Ensure "nullable" property does not work anymore. Null type works instead
  • Ensure Request Body validation works in GET HTTP methods
  • Ensure "default" must exist in server variable "enum" values
  • Ensure it is possible to create an Operation Object without responses
  • Support "pathItems" in Components Object

There are some more changes introduced by Open API 3.1, but they're schema changes that are validated by AJV, so tests, although important, aren't as critical as the ones above. They are:

  • Ensure mutual TLS works correctly
  • Ensure extension prefixed with "x-oas-" is not allowed
  • Ensure "exclusiveMaximum" and "exclusiveMinimum" do not accept boolean values
  • Ensure server variable "enum" can not be empty
  • Ensure "jsonSchemaDialect" is supported
  • Ensure "style", "explode" and "allowReserved" for multipart/form-data are allowed as media types

Closes #573 #755

@SF97 SF97 mentioned this pull request Jan 1, 2024
@cdimascio
Copy link
Owner

Thank you! can you help build the scaffolding and establish a pattern for 3.1 tests, enabling myself and the community to contribute and expand on them

@SF97
Copy link
Contributor Author

SF97 commented Jan 31, 2024

Thank you! can you help build the scaffolding and establish a pattern for 3.1 tests, enabling myself and the community to contribute and expand on them

Yes, I can do that! I've been really busy lately so I haven't got around to that yet

I think I'll have to time to pick it up this weekend

@SF97 SF97 force-pushed the feat/openapi-3.1-support branch from 432dd0e to bb53f78 Compare February 5, 2024 00:32
…ck up subdirectories

Mocha was not picking up the tests in subdirectories with the provided glob. Adding --extension with
the tests extension and setting the root test folder in tests fixed it
@SF97
Copy link
Contributor Author

SF97 commented Feb 5, 2024

Hello!

I just pushed the first test for OpenAPI 3.1, where we test for webhook support without any API routes, in which I found some bugs immediately 🤣 but at least I was able to fix it and the tests are passing 🥳

I created the folder test/openapi_3.1 for version 3.1 related tests. I've also added the interface DocumentV3_1 for a OpenAPI 3.1 compatible type, and refactored all references to the OpenAPI document to union both 3.0 and 3.1. I found this pretty ugly, maybe we should create an abstraction around it. Anyway, what I wanted was to at least do the first tests so we can all contribute to this PR :)

I also added an (incomplete) list of things to support in OpenAPI 3.1

I'll try to contribute as much as I can in the upcoming days. Anything that I can help with, just let me know

@SF97 SF97 marked this pull request as draft February 5, 2024 00:49
Copy link
Owner

@cdimascio cdimascio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks good. one question regarding apiDocs.paths i.e. why might it be missing and what is the behavior when it is

@SF97
Copy link
Contributor Author

SF97 commented Feb 29, 2024

Hello

Just added the list of things we need to ensure that work in OpenAPI 3.1. I based it on OpenAPI's own changelog. I'm currently adding tests to ensure that everything works with the 3.1 spec just fine. Just added some and I'm happy to receive contributions :)

@SF97 SF97 force-pushed the feat/openapi-3.1-support branch from 264f83f to 0587415 Compare March 31, 2024 22:33
@SF97 SF97 marked this pull request as ready for review April 28, 2024 18:46
@SF97
Copy link
Contributor Author

SF97 commented Apr 28, 2024

Hello @cdimascio

I've added the most important tests. There are some more things to validate, but they're assured by AJV, thus I don't think they're critical to have this feature.

But I need help in one thing before shipping. I've added a test to ensure that pathItems is supported in components object, but it's failing. The YAML (test/openapi_3.1/resources/components_path_items.yaml) is fine, since it's parsed correctly in https://editor-next.swagger.io/, and it's according to the spec, but AJV is saying it's invalid, and I'm not sure why. It throws this error:
image

Can you give a little help here to ensure that we'll support this feature? After this test is passing we can proceed with a full review and add support for OpenAPI 3.1 🥳

Thank you

@medranocalvo
Copy link

Can you give a little help here to ensure that we'll support this feature? After this test is passing we can proceed with a full review and add support for OpenAPI 3.1 🥳

Had a look at this. As far as I understand the YAML is invalid, and swagger-editor is being lax about it.

Looking at the 3.1 schema https://github.com/cdimascio/express-openapi-validator/pull/882/files#diff-380b880ffe3121cfdcd466e6bc447b3607d1ddaea014b3167b3b9ee12611fd1e line 286, we see:

    "paths": {
      "$comment": "https://spec.openapis.org/oas/v3.1.0#paths-object",
      "type": "object",
      "patternProperties": {
        "^/": {
          "$ref": "#/$defs/path-item"
        }
      },
      "$ref": "#/$defs/specification-extensions",
      "unevaluatedProperties": false
    },

where in line 268:

        "pathItems": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/path-item-or-reference"
          }
        }

That is, paths' elements must be "#/$defs/path-item", while pathItems' elements might also be references. The yaml looks like this:

openapi: 3.1.0
info:
  title: Example specification
  version: "1.0"
servers:
  - url: /v1
components:
  pathItems: 
    entity:
      get: 
        [...]
paths:
  /entity:
    $ref: '#/components/pathItems/entity'

We try to use a reference from paths to components/pathItems, where they are only allowed in the other direction.


@SF97, thank you very much for working on this.

@SF97
Copy link
Contributor Author

SF97 commented May 13, 2024

@medranocalvo

Thank you very much! I took a look at the schema, and it looks like it was a bug at the schema level, which has been fixed in OAI/OpenAPI-Specification#3355, i.e. the YAML was fine, but the schema wasn't validating it correctly. I've updated the schema to the newest, and it no longer throws a schema error 😎.

The test is still failing, but I suspect what it is... I'm going to work on it

@medranocalvo
Copy link

Reviewed lightly and added a couple of comments. Hope it helps.

@cdimascio
Copy link
Owner

Thank you

@Jackman3005
Copy link

Jackman3005 commented Jul 5, 2024

Hi @cdimascio @mdmower @SF97 I'm still looking forward to testing this as I think it will help with a number of issues I'm facing around nullable.

Where are things at right now? Is there a list of outstanding tasks we could make or is it ready for a alpha release?

Thanks in advance 🙏

@SF97
Copy link
Contributor Author

SF97 commented Jul 9, 2024

Hi @cdimascio @mdmower @SF97 I'm still looking forward to testing this as I think it will help with a number of issues I'm facing around nullable.

Where are things at right now? Is there a list of outstanding tasks we could make or is it ready for a alpha release?

Thanks in advance 🙏

Hello

From my end, it's ready. I've added all the test cases and fixed the bugs that I've found along the way. If we can't do an alpha release, you can always install it from this branch to test it out locally

@huilingwei
Copy link

@cdimascio @mdmower @SF97 Hi, is there any plan when this feature will be released?

@patricktyndall
Copy link

chiming in to express interest, particularly in unevaluatedProperties. Thanks all for the work

@cdimascio
Copy link
Owner

cdimascio commented Aug 24, 2024

The content in this PR is now available on branch oas-3.1 and package [email protected]. please try it out.

# experimental OAS 3.1 in alpha (contributions welcome - see branch `oas-3.1` and pr-882)
npm install [email protected]

To contribute submit PRs against the oas-3.1 branch.

@Eileen-34
Copy link

Eileen-34 commented Dec 5, 2024

Do you know if koa openapi validator, which is provided by Express, supports 3.1 v OpenAPI Spec?

https://github.com/cdimascio/express-openapi-validator/tree/lerna-fastify/packages/koa-openapi-validator

@SF97
Copy link
Contributor Author

SF97 commented Dec 10, 2024

Hey @cdimascio

I think this is ready for a release, do you agree? We've given enough time for feedback and bug fixing

pathItems?: { [path: string]: PathItemObject | ReferenceObject }
}

export interface DocumentV3_1 extends Omit<DocumentV3, 'paths' | 'info' | 'components'> {
Copy link
Contributor

@uwinkelvos uwinkelvos Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export interface DocumentV3_1 extends Omit<DocumentV3, 'paths' | 'info' | 'components'> {
export interface DocumentV3_1 extends Omit<DocumentV3, 'paths' | 'info' | 'components', 'openapi'> {
openapi: `3.1.${p}`;

To make this also compile type safe:
could then also be applied above in 3.0 with openapi: `3.0.${p}`;

cdimascio added a commit that referenced this pull request Dec 25, 2024
* feat(openapi): support version 3.1

* test(openapi_3.1): ensure that an API with webhooks and no routes is supported

* feat(openapi_3.1): adds open api 3.1 type

* chore(test-scripts): run mocha with --extension instead of glob to pick up subdirectories

Mocha was not picking up the tests in subdirectories with the provided glob. Adding --extension with
the tests extension and setting the root test folder in tests fixed it

* test(openapi-3.1): adds test to ensure an API with only components is considered valid

* test(openapi-3.1): remove unnecessary import

* test(openapi-3.1): add support for summary in info object

* test(openapi-3.1): add support for identifier in license

* test(openapi_3.1): ensure API with type set to null works correctly

* test(open_api3.1): ensure that methods with non-explicit semantics allow request body

* test(open_api3.1): ensure 500 is returned when server variable has no default

* feat(openapi_3.1): ensure API supports an endpoint without response

* feat(openapi_3.1): add full type support for open api 3.1

* test(openapi_3.1): adds test for path item support in components

* fix(openapi_3.1_schema): update schema to fix bug

* feat(openapi_3.1): support reusable path items

* style(linting): fix linting issues

* style(openapi): improve readability of version validation

* docs(schema-validator): clearly state why media-range attribute is not defined

* version 6.0.0-alpha.1 with initial OAS-3.1 support (from PR #882)

* v6.0.0-alpha.2

* feat(openapi): support version 3.1

* test(openapi_3.1): ensure that an API with webhooks and no routes is supported

* feat(openapi_3.1): adds open api 3.1 type

* chore(test-scripts): run mocha with --extension instead of glob to pick up subdirectories

Mocha was not picking up the tests in subdirectories with the provided glob. Adding --extension with
the tests extension and setting the root test folder in tests fixed it

* test(openapi-3.1): adds test to ensure an API with only components is considered valid

* test(openapi-3.1): remove unnecessary import

* test(openapi-3.1): add support for summary in info object

* test(openapi-3.1): add support for identifier in license

* test(openapi_3.1): ensure API with type set to null works correctly

* test(open_api3.1): ensure that methods with non-explicit semantics allow request body

* test(open_api3.1): ensure 500 is returned when server variable has no default

* feat(openapi_3.1): ensure API supports an endpoint without response

* feat(openapi_3.1): add full type support for open api 3.1

* test(openapi_3.1): adds test for path item support in components

* fix(openapi_3.1_schema): update schema to fix bug

* feat(openapi_3.1): support reusable path items

* style(linting): fix linting issues

* style(openapi): improve readability of version validation

* docs(schema-validator): clearly state why media-range attribute is not defined

* version 6.0.0-alpha.1 with initial OAS-3.1 support (from PR #882)

* v6.0.0-alpha.2

* alpha.3

* feat(openapi): support version 3.1

* feat(openapi_3.1): adds open api 3.1 type

* fix(openapi_3.1_schema): update schema to fix bug

* style(linting): fix linting issues

* fix: instantiate Ajv2020 for OAS 3.1 (#1009)

* chore: create factories for ajvInstance and schema

* test: writing some tests

* chore: removing ts from editorconfig

* chore: add eslint

* update alpha 3.1 version

* fix: examples/4-eov-operations-babel/package.json & examples/4-eov-operations-babel/package-lock.json to reduce vulnerabilities (#1021)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-PATHTOREGEXP-8482416

Co-authored-by: snyk-bot <[email protected]>

* fix: package.json & package-lock.json to reduce vulnerabilities (#1017)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-PATHTOREGEXP-8482416

Co-authored-by: snyk-bot <[email protected]>

* chore(deps): bump path-to-regexp and express in /examples/1-standard (#1016)

Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `path-to-regexp` from 0.1.10 to 0.1.12
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](pillarjs/path-to-regexp@v0.1.10...v0.1.12)

Updates `express` from 4.21.0 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](expressjs/express@4.21.0...4.21.2)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: upgrade express-openapi-validator from 5.3.7 to 5.3.8 (#1011)

Snyk has created this PR to upgrade express-openapi-validator from 5.3.7 to 5.3.8.

See this package in npm:
express-openapi-validator

See this project in Snyk:
https://app.snyk.io/org/cdimascio/project/53639b22-8ff0-4bd5-97c3-ae30b20a20f4?utm_source=github&utm_medium=referral&page=upgrade-pr

Co-authored-by: snyk-bot <[email protected]>

* fix: upgrade express-openapi-validator from 5.3.6 to 5.3.7 (#1008)

Snyk has created this PR to upgrade express-openapi-validator from 5.3.6 to 5.3.7.

See this package in npm:
express-openapi-validator

See this project in Snyk:
https://app.snyk.io/org/cdimascio/project/0ac9a5bd-9a7f-4c0e-bf8b-51d0bd4c4448?utm_source=github&utm_medium=referral&page=upgrade-pr

Co-authored-by: snyk-bot <[email protected]>

* fix: upgrade @apidevtools/json-schema-ref-parser from 11.7.0 to 11.7.2 (#1006)

Snyk has created this PR to upgrade @apidevtools/json-schema-ref-parser from 11.7.0 to 11.7.2.

See this package in npm:
@apidevtools/json-schema-ref-parser

See this project in Snyk:
https://app.snyk.io/org/cdimascio/project/f63fb44e-f154-45ba-b1f0-20d49ea578ce?utm_source=github&utm_medium=referral&page=upgrade-pr

Co-authored-by: snyk-bot <[email protected]>

* adds standard example for oas-3.1

* v6.0.0.alpha.6

* update oas3.1 example

* v5.4.0 - adds initial oas3.1 support

* updates readme for oas3.1

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Sergio Ferreira <[email protected]>
Co-authored-by: carmine <[email protected]>
Co-authored-by: Luis Philipe Fidelis <[email protected]>
Co-authored-by: snyk-bot <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@cdimascio
Copy link
Owner

merged via #1027

@cdimascio cdimascio closed this Dec 25, 2024
@SF97 SF97 deleted the feat/openapi-3.1-support branch December 29, 2024 12:26
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

Successfully merging this pull request may close these issues.

OpenAPI 3.1 support
8 participants