mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-02 19:30:19 +03:00
Merge tag 'v2.0.0-rc.71' into sections-at-the-end
This commit is contained in:
commit
e76c0b12a1
8
.github/workflows/e2e-tests.yml
vendored
8
.github/workflows/e2e-tests.yml
vendored
|
@ -6,7 +6,7 @@ jobs:
|
||||||
build-and-e2e:
|
build-and-e2e:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run bundle
|
- run: npm run bundle
|
||||||
- run: npm run e2e
|
- run: npm run e2e
|
||||||
|
|
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
|
@ -11,7 +11,7 @@ jobs:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
|
@ -48,7 +48,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: docker_meta
|
id: docker_meta
|
||||||
|
|
34
.github/workflows/publish-cli.yml
vendored
34
.github/workflows/publish-cli.yml
vendored
|
@ -11,10 +11,10 @@ jobs:
|
||||||
if: needs.check-version-cli.outputs.changed == 'true'
|
if: needs.check-version-cli.outputs.changed == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
key: npm-${{ hashFiles('package-lock.json') }}
|
key: npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
@ -24,7 +24,7 @@ jobs:
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run bundle
|
- run: npm run bundle
|
||||||
- name: Store bundle artifact
|
- name: Store bundle artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bundles-cli
|
name: bundles-cli
|
||||||
path: bundles
|
path: bundles
|
||||||
|
@ -34,17 +34,17 @@ jobs:
|
||||||
if: needs.check-version-cli.outputs.changed == 'true'
|
if: needs.check-version-cli.outputs.changed == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v3
|
||||||
- run: npm ci && npm ci --prefix cli
|
- run: npm ci && npm ci --prefix cli
|
||||||
- run: npm test
|
- run: npm test
|
||||||
e2e-tests:
|
e2e-tests:
|
||||||
needs: [bundle]
|
needs: [bundle]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v3
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- name: Download bundled artifact
|
- name: Download bundled artifact
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bundles-cli
|
name: bundles-cli
|
||||||
path: bundles
|
path: bundles
|
||||||
|
@ -54,10 +54,10 @@ jobs:
|
||||||
if: needs.check-version-cli.outputs.changed == 'true'
|
if: needs.check-version-cli.outputs.changed == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: npm-${{ hashFiles('package-lock.json') }}
|
key: npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
@ -69,7 +69,7 @@ jobs:
|
||||||
- name: Bundle
|
- name: Bundle
|
||||||
run: npm run compile:cli
|
run: npm run compile:cli
|
||||||
- name: Store bundle artifact
|
- name: Store bundle artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cli
|
name: cli
|
||||||
path: cli
|
path: cli
|
||||||
|
@ -81,9 +81,9 @@ jobs:
|
||||||
changed: ${{ steps.check.outputs.changed }}
|
changed: ${{ steps.check.outputs.changed }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
- name: Check if version has been updated
|
- name: Check if version has been updated
|
||||||
id: check
|
id: check
|
||||||
uses: EndBug/version-check@v2.0.1
|
uses: EndBug/version-check@v2.0.1
|
||||||
|
@ -96,18 +96,18 @@ jobs:
|
||||||
if: needs.check-version-cli.outputs.changed == 'true'
|
if: needs.check-version-cli.outputs.changed == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Download cli bundled artifact
|
- name: Download cli bundled artifact
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cli
|
name: cli
|
||||||
path: cli
|
path: cli
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
key: npm-${{ hashFiles('package-lock.json') }}
|
key: npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
45
.github/workflows/publish.yml
vendored
45
.github/workflows/publish.yml
vendored
|
@ -9,10 +9,10 @@ jobs:
|
||||||
bundle:
|
bundle:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
key: npm-${{ hashFiles('package-lock.json') }}
|
key: npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
@ -22,7 +22,7 @@ jobs:
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run bundle
|
- run: npm run bundle
|
||||||
- name: Store bundle artifact
|
- name: Store bundle artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bundles
|
name: bundles
|
||||||
path: bundles
|
path: bundles
|
||||||
|
@ -30,17 +30,17 @@ jobs:
|
||||||
unit-tests:
|
unit-tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v3
|
||||||
- run: npm ci && npm ci --prefix cli
|
- run: npm ci && npm ci --prefix cli
|
||||||
- run: npm test
|
- run: npm test
|
||||||
e2e-tests:
|
e2e-tests:
|
||||||
needs: [bundle]
|
needs: [bundle]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v3
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- name: Download bundled artifact
|
- name: Download bundled artifact
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bundles
|
name: bundles
|
||||||
path: bundles
|
path: bundles
|
||||||
|
@ -50,7 +50,7 @@ jobs:
|
||||||
# needs: [bundle, unit-tests, e2e-tests]
|
# needs: [bundle, unit-tests, e2e-tests]
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
# steps:
|
# steps:
|
||||||
# - uses: actions/checkout@v1
|
# - uses: actions/checkout@v3
|
||||||
# - name: Configure AWS Credentials
|
# - name: Configure AWS Credentials
|
||||||
# uses: aws-actions/configure-aws-credentials@v1
|
# uses: aws-actions/configure-aws-credentials@v1
|
||||||
# with:
|
# with:
|
||||||
|
@ -60,7 +60,7 @@ jobs:
|
||||||
# - name: Install dependencies
|
# - name: Install dependencies
|
||||||
# run: npm ci
|
# run: npm ci
|
||||||
# - name: Download bundled artifacts
|
# - name: Download bundled artifacts
|
||||||
# uses: actions/download-artifact@v2
|
# uses: actions/download-artifact@v3
|
||||||
# with:
|
# with:
|
||||||
# name: bundles
|
# name: bundles
|
||||||
# path: bundles
|
# path: bundles
|
||||||
|
@ -71,21 +71,22 @@ jobs:
|
||||||
# - name: Invalidate
|
# - name: Invalidate
|
||||||
# run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DEMO_DISTRIBUTION_ID }} --paths "/*"
|
# run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DEMO_DISTRIBUTION_ID }} --paths "/*"
|
||||||
publish:
|
publish:
|
||||||
|
name: Publish to NPM
|
||||||
needs: [bundle, unit-tests, e2e-tests]
|
needs: [bundle, unit-tests, e2e-tests]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Download bundled artifacts
|
- name: Download bundled artifacts
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bundles
|
name: bundles
|
||||||
path: bundles
|
path: bundles
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
key: npm-${{ hashFiles('package-lock.json') }}
|
key: npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
@ -98,3 +99,21 @@ jobs:
|
||||||
run: npm publish
|
run: npm publish
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
publish-cdn:
|
||||||
|
name: Publish to CDN
|
||||||
|
needs: [bundle, unit-tests, e2e-tests]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Configure AWS
|
||||||
|
uses: aws-actions/configure-aws-credentials@v1
|
||||||
|
with:
|
||||||
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
aws-region: us-east-1
|
||||||
|
- name: Download all artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
- name: Publish to S3
|
||||||
|
run: npm run publish-cdn
|
||||||
|
|
4
.github/workflows/sync.yml
vendored
4
.github/workflows/sync.yml
vendored
|
@ -9,10 +9,10 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v3
|
||||||
- name: Run GitHub File Sync
|
- name: Run GitHub File Sync
|
||||||
uses: Redocly/repo-file-sync-action@master
|
uses: Redocly/repo-file-sync-action@master
|
||||||
with:
|
with:
|
||||||
GH_PAT: ${{ secrets.GH_PAT }}
|
GH_PAT: ${{ secrets.GH_PAT }}
|
||||||
COMMIT_PREFIX: "sync:"
|
COMMIT_PREFIX: 'sync:'
|
||||||
SKIP_PR: true
|
SKIP_PR: true
|
||||||
|
|
2
.github/workflows/unit-tests.yml
vendored
2
.github/workflows/unit-tests.yml
vendored
|
@ -6,7 +6,7 @@ jobs:
|
||||||
build-and-unit:
|
build-and-unit:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v3
|
||||||
- run: npm ci && npm ci --prefix cli
|
- run: npm ci && npm ci --prefix cli
|
||||||
- run: npm run bundle
|
- run: npm run bundle
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
|
30
CHANGELOG.md
30
CHANGELOG.md
|
@ -1,3 +1,33 @@
|
||||||
|
# [2.0.0-rc.71](https://github.com/Redocly/redoc/compare/v2.0.0-rc.70...v2.0.0-rc.71) (2022-05-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* constraints label details ([eb0917d](https://github.com/Redocly/redoc/commit/eb0917d002e57353027fee9c8f07605de8f1ff6f))
|
||||||
|
* merge allOf in correct order ([#2020](https://github.com/Redocly/redoc/issues/2020)) ([1e4ea03](https://github.com/Redocly/redoc/commit/1e4ea03d4a9b7eddf3e4cc7cbdbd4d913583e837))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add hideSecuritySection option allowing to disable the Security panel ([#2027](https://github.com/Redocly/redoc/issues/2027)) ([49cc11d](https://github.com/Redocly/redoc/commit/49cc11d91795653ca870e9276a1e0cd617964e25))
|
||||||
|
* add Redoc to Redocly CDN ([#2026](https://github.com/Redocly/redoc/issues/2026)) ([77104d6](https://github.com/Redocly/redoc/commit/77104d6c0d6f457aa08a158e93b52a45877be84e))
|
||||||
|
* add support prefix items ([27a9dba](https://github.com/Redocly/redoc/commit/27a9dbaf46aded01a6512645dab27870a85cc73b))
|
||||||
|
* remove auth section ([#2022](https://github.com/Redocly/redoc/issues/2022)) ([a863302](https://github.com/Redocly/redoc/commit/a863302cc803bdf27187c613157ba90af1040fc4))
|
||||||
|
* show minProperties maxProperties ([#2015](https://github.com/Redocly/redoc/issues/2015)) ([82712c5](https://github.com/Redocly/redoc/commit/82712c5b408dc6bc142307d45fb962de2a43ffba))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.0.0-rc.70](https://github.com/Redocly/redoc/compare/2.0.0-rc.69...2.0.0-rc.70) (2022-05-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* display patternProperties ([#2008](https://github.com/Redocly/redoc/issues/2008)) ([660cc85](https://github.com/Redocly/redoc/commit/660cc857bc86787e16237b407fe5f5d7a493bb48))
|
||||||
|
* support conditional operators ([#1939](https://github.com/Redocly/redoc/issues/1939)) ([291b62a](https://github.com/Redocly/redoc/commit/291b62a206b68f8b4d98e4b74b71c0cad20a8b9b))
|
||||||
|
* theme add links textDecoration options ([#1599](https://github.com/Redocly/redoc/issues/1599)) ([ba06485](https://github.com/Redocly/redoc/commit/ba06485ece27acbb6b846500817f4bff3e4997ba))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-rc.69](https://github.com/Redocly/redoc/compare/v2.0.0-rc.68.1...v2.0.0-rc.69) (2022-05-12)
|
# [2.0.0-rc.69](https://github.com/Redocly/redoc/compare/v2.0.0-rc.68.1...v2.0.0-rc.69) (2022-05-12)
|
||||||
|
|
||||||
|
|
||||||
|
|
13
README.md
13
README.md
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
[](https://travis-ci.com/Redocly/redoc) [](https://coveralls.io/github/Redocly/redoc?branch=master) [](https://www.npmjs.com/package/redoc) [](https://github.com/Redocly/redoc/blob/master/LICENSE)
|
[](https://travis-ci.com/Redocly/redoc) [](https://coveralls.io/github/Redocly/redoc?branch=master) [](https://www.npmjs.com/package/redoc) [](https://github.com/Redocly/redoc/blob/master/LICENSE)
|
||||||
|
|
||||||
[](https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js) [](https://www.npmjs.com/package/redoc) [](https://www.jsdelivr.com/package/npm/redoc) [](https://hub.docker.com/r/redocly/redoc/)
|
[](https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js) [](https://www.npmjs.com/package/redoc) [](https://www.jsdelivr.com/package/npm/redoc) [](https://hub.docker.com/r/redocly/redoc/)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
**This is the README for the `2.x` version of Redoc (React-based).**
|
**This is the README for the `2.x` version of Redoc (React-based).**
|
||||||
|
@ -102,9 +102,9 @@ Refer to the Redocly's documentation for more information on these products:
|
||||||

|

|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
**Important:** all the 2.x releases are deployed to npm and can be used with jsdeliver:
|
**Important:** all the 2.x releases are deployed to npm and can be used with Redocly-cdn:
|
||||||
- particular release, for example, `v2.0.0-alpha.15`: https://cdn.jsdelivr.net/npm/redoc@2.0.0-alpha.17/bundles/redoc.standalone.js
|
- particular release, for example, `v2.0.0-rc.70`: https://cdn.redoc.ly/redoc/v2.0.0-rc.70/bundles/redoc.standalone.js
|
||||||
- `next` release: https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js
|
- `latest` release: https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js
|
||||||
|
|
||||||
Additionally, all the 1.x releases are hosted on our GitHub Pages-based CDN **(deprecated)**:
|
Additionally, all the 1.x releases are hosted on our GitHub Pages-based CDN **(deprecated)**:
|
||||||
- particular release, for example `v1.2.0`: https://rebilly.github.io/ReDoc/releases/v1.2.0/redoc.min.js
|
- particular release, for example `v1.2.0`: https://rebilly.github.io/ReDoc/releases/v1.2.0/redoc.min.js
|
||||||
|
@ -166,7 +166,7 @@ replace the `spec-url` attribute with the url or local file address to your defi
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'></redoc>
|
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'></redoc>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/redoc@latest/bundles/redoc.standalone.js"> </script>
|
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@ -232,7 +232,6 @@ You can use all of the following options with the standalone version of the <red
|
||||||
* `lazyRendering` - _Not implemented yet_ ~~if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\redocly.github.io/redoc) for the example.~~
|
* `lazyRendering` - _Not implemented yet_ ~~if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\redocly.github.io/redoc) for the example.~~
|
||||||
* `menuToggle` - if true clicking second time on expanded menu item will collapse it, default `true`.
|
* `menuToggle` - if true clicking second time on expanded menu item will collapse it, default `true`.
|
||||||
* `nativeScrollbars` - use native scrollbar for sidemenu instead of perfect-scroll (scrolling performance optimization for big specs).
|
* `nativeScrollbars` - use native scrollbar for sidemenu instead of perfect-scroll (scrolling performance optimization for big specs).
|
||||||
* `noAutoAuth` - do not inject Authentication section automatically.
|
|
||||||
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
||||||
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one.
|
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one.
|
||||||
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
||||||
|
@ -289,6 +288,8 @@ You can use all of the following options with the standalone version of the <red
|
||||||
* `color`: # COMPUTED: colors.primary.main
|
* `color`: # COMPUTED: colors.primary.main
|
||||||
* `visited`: # COMPUTED: typography.links.color
|
* `visited`: # COMPUTED: typography.links.color
|
||||||
* `hover`: # COMPUTED: lighten(0.2 typography.links.color)
|
* `hover`: # COMPUTED: lighten(0.2 typography.links.color)
|
||||||
|
* `textDecoration`: 'auto'
|
||||||
|
* `hoverTextDecoration`: 'auto'
|
||||||
* `sidebar`
|
* `sidebar`
|
||||||
* `width`: '260px'
|
* `width`: '260px'
|
||||||
* `backgroundColor`: '#fafafa'
|
* `backgroundColor`: '#fafafa'
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { spawnSync } from 'child_process';
|
import { spawnSync } from 'child_process';
|
||||||
|
|
||||||
describe('build with url', () => {
|
describe('build with url', () => {
|
||||||
// FIXME: remove skip after release
|
it('should not fail on resolving url', () => {
|
||||||
it.skip('should not fail on resolving url', () => {
|
|
||||||
const r = spawnSync(
|
const r = spawnSync(
|
||||||
'ts-node',
|
'ts-node',
|
||||||
[
|
[
|
||||||
|
|
124
cli/npm-shrinkwrap.json
generated
124
cli/npm-shrinkwrap.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "redoc-cli",
|
"name": "redoc-cli",
|
||||||
"version": "0.13.12",
|
"version": "0.13.14",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "redoc-cli",
|
"name": "redoc-cli",
|
||||||
"version": "0.13.12",
|
"version": "0.13.14",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^3.5.1",
|
"chokidar": "^3.5.1",
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
"node-libs-browser": "^2.2.1",
|
"node-libs-browser": "^2.2.1",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"redoc": "2.0.0-rc.68",
|
"redoc": "2.0.0-rc.70",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"yargs": "^17.3.1"
|
"yargs": "^17.3.1"
|
||||||
},
|
},
|
||||||
|
@ -216,9 +216,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@redocly/openapi-core": {
|
"node_modules/@redocly/openapi-core": {
|
||||||
"version": "1.0.0-beta.96",
|
"version": "1.0.0-beta.97",
|
||||||
"resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.96.tgz",
|
"resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.97.tgz",
|
||||||
"integrity": "sha512-tcy0q+9PRWV4rcnVx5uHII/9Cq9qpUzWNppupAaVgutxjQRPWH45e24NLinn6lA8Q4por6HuMYkk/0QAJE8d3A==",
|
"integrity": "sha512-3WW9/6flosJuRtU3GI0Vw39OYFZqqXMDCp5TLa3EjXOb7Nm6AZTWRb3Y+I/+UdNJ/NTszVJkQczoa1t476ekiQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@redocly/ajv": "^8.6.4",
|
"@redocly/ajv": "^8.6.4",
|
||||||
"@types/node": "^14.11.8",
|
"@types/node": "^14.11.8",
|
||||||
|
@ -226,7 +226,7 @@
|
||||||
"js-levenshtein": "^1.1.6",
|
"js-levenshtein": "^1.1.6",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^5.0.1",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"yaml-ast-parser": "0.0.43"
|
"yaml-ast-parser": "0.0.43"
|
||||||
|
@ -236,9 +236,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@redocly/openapi-core/node_modules/@types/node": {
|
"node_modules/@redocly/openapi-core/node_modules/@types/node": {
|
||||||
"version": "14.18.16",
|
"version": "14.18.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.16.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.17.tgz",
|
||||||
"integrity": "sha512-X3bUMdK/VmvrWdoTkz+VCn6nwKwrKCFTHtqwBIaQJNx4RUIBBUFXM00bqPz/DsDd+Icjmzm6/tyYZzeGVqb6/Q=="
|
"integrity": "sha512-oajWz4kOajqpKJMPgnCvBajPq8QAvl2xIWoFjlAJPKGu6n7pjov5SxGE45a+0RxHDoo4ycOMoZw1SCOWtDERbw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/chokidar": {
|
"node_modules/@types/chokidar": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
|
@ -646,12 +646,11 @@
|
||||||
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
|
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0"
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/braces": {
|
"node_modules/braces": {
|
||||||
|
@ -922,11 +921,6 @@
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
|
||||||
},
|
|
||||||
"node_modules/console-browserify": {
|
"node_modules/console-browserify": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
||||||
|
@ -1253,9 +1247,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/foreach": {
|
"node_modules/foreach": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz",
|
||||||
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
|
"integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg=="
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
|
@ -1686,14 +1680,14 @@
|
||||||
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
|
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
|
@ -1932,9 +1926,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/openapi-sampler": {
|
"node_modules/openapi-sampler": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.3.tgz",
|
||||||
"integrity": "sha512-mHrYmyvcLD0qrfqPkPRBAL2z16hGT2rW0d0B7nklfoTcc3pmkJLkSZlKSeFgerUM41E5c7jlxf0Y19xrM7mWQQ==",
|
"integrity": "sha512-dH2QYXqakorV5dxkP/f1BV3Ku4yNn21YmBsqJunnyrHLw7mnCNZZldftgrEpv/66b1m5oaUAmiJoJN+FqBEkJg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"json-pointer": "0.6.2"
|
"json-pointer": "0.6.2"
|
||||||
|
@ -2207,11 +2201,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/redoc": {
|
"node_modules/redoc": {
|
||||||
"version": "2.0.0-rc.68",
|
"version": "2.0.0-rc.70",
|
||||||
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.68.tgz",
|
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.70.tgz",
|
||||||
"integrity": "sha512-sCz52OEhLDu2cIBimy4f6CaVoDxUzD16x63oZx4kpDQOTXYtk0hEOlph1s5VrgNg9pg+rJ9LCCfnwCuzx3Be8w==",
|
"integrity": "sha512-sdmZ8FX4JjF50hTSjHJ64Ccu9Ewa2O8+Fo8pCLg8GHFrbaFJ2E+KBDK9pGuAqNi61fm3Z5c91Ur7zqpITkUpNg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@redocly/openapi-core": "^1.0.0-beta.95",
|
"@redocly/openapi-core": "^1.0.0-beta.97",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"decko": "^1.2.0",
|
"decko": "^1.2.0",
|
||||||
"dompurify": "^2.2.8",
|
"dompurify": "^2.2.8",
|
||||||
|
@ -2221,7 +2215,7 @@
|
||||||
"mark.js": "^8.11.1",
|
"mark.js": "^8.11.1",
|
||||||
"marked": "^4.0.15",
|
"marked": "^4.0.15",
|
||||||
"mobx-react": "^7.2.0",
|
"mobx-react": "^7.2.0",
|
||||||
"openapi-sampler": "^1.2.1",
|
"openapi-sampler": "^1.2.3",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"perfect-scrollbar": "^1.5.1",
|
"perfect-scrollbar": "^1.5.1",
|
||||||
"polished": "^4.1.3",
|
"polished": "^4.1.3",
|
||||||
|
@ -3135,9 +3129,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@redocly/openapi-core": {
|
"@redocly/openapi-core": {
|
||||||
"version": "1.0.0-beta.96",
|
"version": "1.0.0-beta.97",
|
||||||
"resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.96.tgz",
|
"resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.97.tgz",
|
||||||
"integrity": "sha512-tcy0q+9PRWV4rcnVx5uHII/9Cq9qpUzWNppupAaVgutxjQRPWH45e24NLinn6lA8Q4por6HuMYkk/0QAJE8d3A==",
|
"integrity": "sha512-3WW9/6flosJuRtU3GI0Vw39OYFZqqXMDCp5TLa3EjXOb7Nm6AZTWRb3Y+I/+UdNJ/NTszVJkQczoa1t476ekiQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@redocly/ajv": "^8.6.4",
|
"@redocly/ajv": "^8.6.4",
|
||||||
"@types/node": "^14.11.8",
|
"@types/node": "^14.11.8",
|
||||||
|
@ -3145,16 +3139,16 @@
|
||||||
"js-levenshtein": "^1.1.6",
|
"js-levenshtein": "^1.1.6",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^5.0.1",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"yaml-ast-parser": "0.0.43"
|
"yaml-ast-parser": "0.0.43"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "14.18.16",
|
"version": "14.18.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.16.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.17.tgz",
|
||||||
"integrity": "sha512-X3bUMdK/VmvrWdoTkz+VCn6nwKwrKCFTHtqwBIaQJNx4RUIBBUFXM00bqPz/DsDd+Icjmzm6/tyYZzeGVqb6/Q=="
|
"integrity": "sha512-oajWz4kOajqpKJMPgnCvBajPq8QAvl2xIWoFjlAJPKGu6n7pjov5SxGE45a+0RxHDoo4ycOMoZw1SCOWtDERbw=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3525,12 +3519,11 @@
|
||||||
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
|
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0"
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"braces": {
|
"braces": {
|
||||||
|
@ -3771,11 +3764,6 @@
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
|
||||||
},
|
|
||||||
"console-browserify": {
|
"console-browserify": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
||||||
|
@ -4060,9 +4048,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"foreach": {
|
"foreach": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz",
|
||||||
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
|
"integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg=="
|
||||||
},
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
|
@ -4396,11 +4384,11 @@
|
||||||
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
|
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
|
@ -4563,9 +4551,9 @@
|
||||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
},
|
},
|
||||||
"openapi-sampler": {
|
"openapi-sampler": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.3.tgz",
|
||||||
"integrity": "sha512-mHrYmyvcLD0qrfqPkPRBAL2z16hGT2rW0d0B7nklfoTcc3pmkJLkSZlKSeFgerUM41E5c7jlxf0Y19xrM7mWQQ==",
|
"integrity": "sha512-dH2QYXqakorV5dxkP/f1BV3Ku4yNn21YmBsqJunnyrHLw7mnCNZZldftgrEpv/66b1m5oaUAmiJoJN+FqBEkJg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"json-pointer": "0.6.2"
|
"json-pointer": "0.6.2"
|
||||||
|
@ -4805,11 +4793,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redoc": {
|
"redoc": {
|
||||||
"version": "2.0.0-rc.68",
|
"version": "2.0.0-rc.70",
|
||||||
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.68.tgz",
|
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.70.tgz",
|
||||||
"integrity": "sha512-sCz52OEhLDu2cIBimy4f6CaVoDxUzD16x63oZx4kpDQOTXYtk0hEOlph1s5VrgNg9pg+rJ9LCCfnwCuzx3Be8w==",
|
"integrity": "sha512-sdmZ8FX4JjF50hTSjHJ64Ccu9Ewa2O8+Fo8pCLg8GHFrbaFJ2E+KBDK9pGuAqNi61fm3Z5c91Ur7zqpITkUpNg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@redocly/openapi-core": "^1.0.0-beta.95",
|
"@redocly/openapi-core": "^1.0.0-beta.97",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"decko": "^1.2.0",
|
"decko": "^1.2.0",
|
||||||
"dompurify": "^2.2.8",
|
"dompurify": "^2.2.8",
|
||||||
|
@ -4819,7 +4807,7 @@
|
||||||
"mark.js": "^8.11.1",
|
"mark.js": "^8.11.1",
|
||||||
"marked": "^4.0.15",
|
"marked": "^4.0.15",
|
||||||
"mobx-react": "^7.2.0",
|
"mobx-react": "^7.2.0",
|
||||||
"openapi-sampler": "^1.2.1",
|
"openapi-sampler": "^1.2.3",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"perfect-scrollbar": "^1.5.1",
|
"perfect-scrollbar": "^1.5.1",
|
||||||
"polished": "^4.1.3",
|
"polished": "^4.1.3",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "redoc-cli",
|
"name": "redoc-cli",
|
||||||
"version": "0.13.12",
|
"version": "0.13.14",
|
||||||
"description": "ReDoc's Command Line Interface",
|
"description": "ReDoc's Command Line Interface",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"bin": "index.js",
|
"bin": "index.js",
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
"node-libs-browser": "^2.2.1",
|
"node-libs-browser": "^2.2.1",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"redoc": "2.0.0-rc.68",
|
"redoc": "2.0.0-rc.70",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"yargs": "^17.3.1"
|
"yargs": "^17.3.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
# npm i -g http-server
|
# npm i -g http-server
|
||||||
# http-server -p 8000 --cors
|
# http-server -p 8000 --cors
|
||||||
|
|
||||||
FROM node:alpine
|
FROM node:12-alpine
|
||||||
|
|
||||||
RUN apk update && apk add --no-cache git
|
RUN apk update && apk add --no-cache git
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
COPY package.json package-lock.json /build/
|
COPY package.json package-lock.json /build/
|
||||||
RUN npm ci --no-optional --ignore-scripts --force
|
RUN npm ci --no-optional --ignore-scripts
|
||||||
|
|
||||||
# copy only required for the build files
|
# copy only required for the build files
|
||||||
COPY src /build/src
|
COPY src /build/src
|
||||||
|
|
|
@ -960,6 +960,33 @@ components:
|
||||||
schemas:
|
schemas:
|
||||||
ApiResponse:
|
ApiResponse:
|
||||||
type: object
|
type: object
|
||||||
|
patternProperties:
|
||||||
|
^S_\\w+\\.[1-9]{2,4}$:
|
||||||
|
description: The measured skill for hunting
|
||||||
|
if:
|
||||||
|
x-displayName: fieldName === 'status'
|
||||||
|
else:
|
||||||
|
minLength: 1
|
||||||
|
maxLength: 10
|
||||||
|
then:
|
||||||
|
format: url
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- success
|
||||||
|
- failed
|
||||||
|
^O_\\w+\\.[1-9]{2,4}$:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
nestedProperty:
|
||||||
|
type: [string, boolean]
|
||||||
|
description: The measured skill for hunting
|
||||||
|
default: lazy
|
||||||
|
example: adventurous
|
||||||
|
enum:
|
||||||
|
- clueless
|
||||||
|
- lazy
|
||||||
|
- adventurous
|
||||||
|
- aggressive
|
||||||
properties:
|
properties:
|
||||||
code:
|
code:
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -975,7 +1002,7 @@ components:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
huntingSkill:
|
huntingSkill:
|
||||||
type: string
|
type: [string, boolean]
|
||||||
description: The measured skill for hunting
|
description: The measured skill for hunting
|
||||||
default: lazy
|
default: lazy
|
||||||
example: adventurous
|
example: adventurous
|
||||||
|
@ -1099,15 +1126,26 @@ components:
|
||||||
example: Guru
|
example: Guru
|
||||||
photoUrls:
|
photoUrls:
|
||||||
description: The list of URL to a cute photos featuring pet
|
description: The list of URL to a cute photos featuring pet
|
||||||
type: [string, integer, 'null', array]
|
type: [string, integer, 'null']
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 20
|
maxItems: 10
|
||||||
xml:
|
xml:
|
||||||
name: photoUrl
|
name: photoUrl
|
||||||
wrapped: true
|
wrapped: true
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
format: url
|
format: url
|
||||||
|
if:
|
||||||
|
x-displayName: isString
|
||||||
|
type: string
|
||||||
|
then:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 15
|
||||||
|
else:
|
||||||
|
x-displayName: notString
|
||||||
|
type: [integer, 'null']
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 20
|
||||||
friend:
|
friend:
|
||||||
$ref: '#/components/schemas/Pet'
|
$ref: '#/components/schemas/Pet'
|
||||||
tags:
|
tags:
|
||||||
|
@ -1131,6 +1169,12 @@ components:
|
||||||
petType:
|
petType:
|
||||||
description: Type of a pet
|
description: Type of a pet
|
||||||
type: string
|
type: string
|
||||||
|
huntingSkill:
|
||||||
|
type: [integer]
|
||||||
|
enum:
|
||||||
|
- 0
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
xml:
|
xml:
|
||||||
name: Pet
|
name: Pet
|
||||||
Tag:
|
Tag:
|
||||||
|
@ -1198,6 +1242,35 @@ components:
|
||||||
type: string
|
type: string
|
||||||
contentEncoding: base64
|
contentEncoding: base64
|
||||||
contentMediaType: image/png
|
contentMediaType: image/png
|
||||||
|
addresses:
|
||||||
|
type: array
|
||||||
|
minItems: 0
|
||||||
|
maxLength: 10
|
||||||
|
prefixItems:
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
city:
|
||||||
|
type: string
|
||||||
|
minLength: 0
|
||||||
|
country:
|
||||||
|
type: string
|
||||||
|
minLength: 0
|
||||||
|
street:
|
||||||
|
description: includes build/apartment number
|
||||||
|
type: string
|
||||||
|
minLength: 0
|
||||||
|
- type: number
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
if:
|
||||||
|
title: userStatus === 10
|
||||||
|
properties:
|
||||||
|
userStatus:
|
||||||
|
enum: [10]
|
||||||
|
then:
|
||||||
|
required: ['phone']
|
||||||
|
else:
|
||||||
|
required: []
|
||||||
xml:
|
xml:
|
||||||
name: User
|
name: User
|
||||||
requestBodies:
|
requestBodies:
|
||||||
|
|
|
@ -88,7 +88,7 @@ paths:
|
||||||
parameters:
|
parameters:
|
||||||
- name: Accept-Language
|
- name: Accept-Language
|
||||||
in: header
|
in: header
|
||||||
description: "The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US"
|
description: 'The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US'
|
||||||
example: en-US
|
example: en-US
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
|
@ -254,7 +254,7 @@ paths:
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: "Bearer <TOKEN>"
|
example: 'Bearer <TOKEN>'
|
||||||
- name: petId
|
- name: petId
|
||||||
in: path
|
in: path
|
||||||
description: Pet id to delete
|
description: Pet id to delete
|
||||||
|
@ -401,6 +401,7 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
minProperties: 2
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
|
@ -429,7 +430,7 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
example:
|
example:
|
||||||
status: 400
|
status: 400
|
||||||
message: "Invalid Order"
|
message: 'Invalid Order'
|
||||||
requestBody:
|
requestBody:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
|
@ -877,11 +878,11 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
examples:
|
examples:
|
||||||
response:
|
response:
|
||||||
value: <Message> OK </Message>
|
value: <Message> OK </Message>
|
||||||
text/plain:
|
text/plain:
|
||||||
examples:
|
examples:
|
||||||
response:
|
response:
|
||||||
value: OK
|
value: OK
|
||||||
'400':
|
'400':
|
||||||
description: Invalid username/password supplied
|
description: Invalid username/password supplied
|
||||||
/user/logout:
|
/user/logout:
|
||||||
|
@ -1027,8 +1028,8 @@ components:
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
externalDocs:
|
externalDocs:
|
||||||
description: "Find more info here"
|
description: 'Find more info here'
|
||||||
url: "https://example.com"
|
url: 'https://example.com'
|
||||||
description: Pet ID
|
description: Pet ID
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/Id'
|
- $ref: '#/components/schemas/Id'
|
||||||
|
@ -1134,6 +1135,26 @@ components:
|
||||||
description: User status
|
description: User status
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
|
addresses:
|
||||||
|
type: array
|
||||||
|
minItems: 0
|
||||||
|
maxLength: 10
|
||||||
|
items:
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
city:
|
||||||
|
type: string
|
||||||
|
minLength: 0
|
||||||
|
country:
|
||||||
|
type: string
|
||||||
|
minLength: 0
|
||||||
|
street:
|
||||||
|
description: includes build/apartment number
|
||||||
|
type: string
|
||||||
|
minLength: 0
|
||||||
|
- type: number
|
||||||
|
additionalItems:
|
||||||
|
type: string
|
||||||
xml:
|
xml:
|
||||||
name: User
|
name: User
|
||||||
requestBodies:
|
requestBodies:
|
||||||
|
@ -1201,7 +1222,7 @@ x-webhooks:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Pet"
|
$ref: '#/components/schemas/Pet'
|
||||||
responses:
|
responses:
|
||||||
"200":
|
'200':
|
||||||
description: Return a 200 status to indicate that the data was received successfully
|
description: Return a 200 status to indicate that the data was received successfully
|
||||||
|
|
|
@ -51,7 +51,7 @@ or the files located in your `node modules` folder.
|
||||||
To reference the Redoc script with a CDN link:
|
To reference the Redoc script with a CDN link:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.jsdelivr.net/npm/redoc@latest/bundles/redoc.standalone.js"> </script>
|
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Node modules link
|
### Node modules link
|
||||||
|
@ -97,7 +97,7 @@ Redoc.init(specOrSpecUrl, options, element, callback)
|
||||||
```
|
```
|
||||||
- `specOrSpecUrl`: Either a JSON object with the OpenAPI definition or a URL to the
|
- `specOrSpecUrl`: Either a JSON object with the OpenAPI definition or a URL to the
|
||||||
definition in JSON or YAML format.
|
definition in JSON or YAML format.
|
||||||
- `options`: See [options object](https://redocly.com/docs/api-reference-docs/configuration/) reference.
|
- `options`: See [features.openapi object](/docs/api-reference-docs/configuration/functionality.mdx) reference.
|
||||||
- `element`: DOM element Redoc will be inserted into.
|
- `element`: DOM element Redoc will be inserted into.
|
||||||
- `callback`(optional): Callback to be called after Redoc has been fully rendered.
|
- `callback`(optional): Callback to be called after Redoc has been fully rendered.
|
||||||
It is also called on errors with `error` as the first argument.
|
It is also called on errors with `error` as the first argument.
|
||||||
|
|
|
@ -38,7 +38,7 @@ replace the `spec-url` attribute with the URL or local file address to your defi
|
||||||
<!--
|
<!--
|
||||||
Link to Redoc JavaScript on CDN for rendering standalone element
|
Link to Redoc JavaScript on CDN for rendering standalone element
|
||||||
-->
|
-->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/redoc@latest/bundles/redoc.standalone.js"></script>
|
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "redoc",
|
"name": "redoc",
|
||||||
"version": "2.0.0-rc.69",
|
"version": "2.0.0-rc.71",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "redoc",
|
"name": "redoc",
|
||||||
"version": "2.0.0-rc.69",
|
"version": "2.0.0-rc.71",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@redocly/openapi-core": "^1.0.0-beta.97",
|
"@redocly/openapi-core": "^1.0.0-beta.97",
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
"mark.js": "^8.11.1",
|
"mark.js": "^8.11.1",
|
||||||
"marked": "^4.0.15",
|
"marked": "^4.0.15",
|
||||||
"mobx-react": "^7.2.0",
|
"mobx-react": "^7.2.0",
|
||||||
"openapi-sampler": "^1.2.3",
|
"openapi-sampler": "^1.3.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"perfect-scrollbar": "^1.5.1",
|
"perfect-scrollbar": "^1.5.1",
|
||||||
"polished": "^4.1.3",
|
"polished": "^4.1.3",
|
||||||
|
@ -14217,9 +14217,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/openapi-sampler": {
|
"node_modules/openapi-sampler": {
|
||||||
"version": "1.2.3",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.3.0.tgz",
|
||||||
"integrity": "sha512-dH2QYXqakorV5dxkP/f1BV3Ku4yNn21YmBsqJunnyrHLw7mnCNZZldftgrEpv/66b1m5oaUAmiJoJN+FqBEkJg==",
|
"integrity": "sha512-2QfjK1oM9Sv0q82Ae1RrUe3yfFmAyjF548+6eAeb+h/cL1Uj51TW4UezraBEvwEdzoBgfo4AaTLVFGTKj+yYDw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"json-pointer": "0.6.2"
|
"json-pointer": "0.6.2"
|
||||||
|
@ -29872,9 +29872,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"openapi-sampler": {
|
"openapi-sampler": {
|
||||||
"version": "1.2.3",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.3.0.tgz",
|
||||||
"integrity": "sha512-dH2QYXqakorV5dxkP/f1BV3Ku4yNn21YmBsqJunnyrHLw7mnCNZZldftgrEpv/66b1m5oaUAmiJoJN+FqBEkJg==",
|
"integrity": "sha512-2QfjK1oM9Sv0q82Ae1RrUe3yfFmAyjF548+6eAeb+h/cL1Uj51TW4UezraBEvwEdzoBgfo4AaTLVFGTKj+yYDw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"json-pointer": "0.6.2"
|
"json-pointer": "0.6.2"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "redoc",
|
"name": "redoc",
|
||||||
"version": "2.0.0-rc.69",
|
"version": "2.0.0-rc.71",
|
||||||
"description": "ReDoc",
|
"description": "ReDoc",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -34,6 +34,7 @@
|
||||||
"start:benchmark": "webpack serve --mode=production --env.bench --config demo/webpack.config.ts",
|
"start:benchmark": "webpack serve --mode=production --env.bench --config demo/webpack.config.ts",
|
||||||
"test": "npm run unit && npm run license-check",
|
"test": "npm run unit && npm run license-check",
|
||||||
"unit": "jest --coverage",
|
"unit": "jest --coverage",
|
||||||
|
"test:update-snapshot": "jest --updateSnapshot",
|
||||||
"e2e": "cypress run",
|
"e2e": "cypress run",
|
||||||
"e2e-ci": "cypress run --record",
|
"e2e-ci": "cypress run --record",
|
||||||
"bundlesize": "size-limit",
|
"bundlesize": "size-limit",
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
"start:demo": "webpack serve --hot --config demo/webpack.config.ts --mode=development",
|
"start:demo": "webpack serve --hot --config demo/webpack.config.ts --mode=development",
|
||||||
"compile:cli": "tsc custom.d.ts cli/index.ts --target es6 --module commonjs --types yargs",
|
"compile:cli": "tsc custom.d.ts cli/index.ts --target es6 --module commonjs --types yargs",
|
||||||
"build:demo": "webpack --mode=production --config demo/webpack.config.ts",
|
"build:demo": "webpack --mode=production --config demo/webpack.config.ts",
|
||||||
|
"publish-cdn": "scripts/publish-cdn.sh",
|
||||||
"deploy:demo": "aws s3 sync demo/dist s3://production-redoc-demo --acl=public-read",
|
"deploy:demo": "aws s3 sync demo/dist s3://production-redoc-demo --acl=public-read",
|
||||||
"license-check": "license-checker --production --onlyAllow 'MIT;ISC;Apache-2.0;BSD;BSD-2-Clause;BSD-3-Clause;CC-BY-4.0;Python-2.0' --summary",
|
"license-check": "license-checker --production --onlyAllow 'MIT;ISC;Apache-2.0;BSD;BSD-2-Clause;BSD-3-Clause;CC-BY-4.0;Python-2.0' --summary",
|
||||||
"docker:build": "docker build -f config/docker/Dockerfile -t redoc .",
|
"docker:build": "docker build -f config/docker/Dockerfile -t redoc .",
|
||||||
|
@ -148,7 +150,7 @@
|
||||||
"mark.js": "^8.11.1",
|
"mark.js": "^8.11.1",
|
||||||
"marked": "^4.0.15",
|
"marked": "^4.0.15",
|
||||||
"mobx-react": "^7.2.0",
|
"mobx-react": "^7.2.0",
|
||||||
"openapi-sampler": "^1.2.3",
|
"openapi-sampler": "^1.3.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"perfect-scrollbar": "^1.5.1",
|
"perfect-scrollbar": "^1.5.1",
|
||||||
"polished": "^4.1.3",
|
"polished": "^4.1.3",
|
||||||
|
|
38
scripts/publish-cdn.sh
Executable file
38
scripts/publish-cdn.sh
Executable file
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e # exit on error
|
||||||
|
|
||||||
|
# TODO: Update script!
|
||||||
|
|
||||||
|
VERSION=$(node scripts/version.js)
|
||||||
|
VERSION_TAG=v${VERSION:0:1}.x
|
||||||
|
|
||||||
|
copy_to_s3 () {
|
||||||
|
aws s3 cp bundles "s3://redocly-cdn/redoc/$1/bundles" --recursive "$2"
|
||||||
|
aws s3 cp CHANGELOG.md "s3://redocly-cdn/redoc/$1/CHANGELOG.md" "$2"
|
||||||
|
aws s3 cp LICENSE "s3://redocly-cdn/redoc/$1/LICENSE" "$2"
|
||||||
|
aws s3 cp package.json "s3://redocly-cdn/redoc/$1/package.json" "$2"
|
||||||
|
aws s3 cp README.md "s3://redocly-cdn/redoc/$1/README.md" "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
if aws s3 ls "redocly-cdn/redoc/v$VERSION/" "$@"; then
|
||||||
|
echo "Version $VERSION already exists"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo Releasing $VERSION
|
||||||
|
|
||||||
|
echo Uploading to S3 $VERSION
|
||||||
|
copy_to_s3 "v$VERSION" $@
|
||||||
|
|
||||||
|
echo Uploading to S3 $VERSION_TAG
|
||||||
|
copy_to_s3 "$VERSION_TAG" $@
|
||||||
|
|
||||||
|
if [[ "$VERSION_TAG" == "v2.x" ]]; then
|
||||||
|
echo Uploading to S3 latest
|
||||||
|
copy_to_s3 latest $@
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo Deployed successfully
|
||||||
|
exit 0
|
||||||
|
fi
|
1
scripts/version.js
Normal file
1
scripts/version.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
console.log(require('../package.json').version);
|
|
@ -1,4 +1,4 @@
|
||||||
import styled, { extensionsHook, media } from '../styled-components';
|
import styled, { extensionsHook, media, css } from '../styled-components';
|
||||||
import { deprecatedCss } from './mixins';
|
import { deprecatedCss } from './mixins';
|
||||||
|
|
||||||
export const PropertiesTableCaption = styled.caption`
|
export const PropertiesTableCaption = styled.caption`
|
||||||
|
@ -72,7 +72,26 @@ export const PropertyNameCell = styled(PropertyCell)`
|
||||||
${deprecatedCss};
|
${deprecatedCss};
|
||||||
}
|
}
|
||||||
|
|
||||||
${({ kind }) => (kind !== 'field' ? 'font-style: italic' : '')};
|
${({ kind }) =>
|
||||||
|
kind === 'patternProperties' &&
|
||||||
|
css`
|
||||||
|
> span.property-name {
|
||||||
|
display: inline-table;
|
||||||
|
white-space: break-spaces;
|
||||||
|
margin-right: 20px;
|
||||||
|
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
content: '/';
|
||||||
|
filter: opacity(0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
|
||||||
|
${({ kind = '' }) =>
|
||||||
|
['field', 'additionalProperties', 'patternProperties'].includes(kind)
|
||||||
|
? ''
|
||||||
|
: 'font-style: italic'};
|
||||||
|
|
||||||
${extensionsHook('PropertyNameCell')};
|
${extensionsHook('PropertyNameCell')};
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { transparentize } from 'polished';
|
import { transparentize } from 'polished';
|
||||||
|
|
||||||
import styled, { extensionsHook } from '../styled-components';
|
import styled, { extensionsHook, css } from '../styled-components';
|
||||||
import { PropertyNameCell } from './fields-layout';
|
import { PropertyNameCell } from './fields-layout';
|
||||||
import { ShelfIcon } from './shelfs';
|
import { ShelfIcon } from './shelfs';
|
||||||
|
|
||||||
|
@ -17,6 +17,27 @@ export const ClickablePropertyNameCell = styled(PropertyNameCell)`
|
||||||
&:focus {
|
&:focus {
|
||||||
font-weight: ${({ theme }) => theme.typography.fontWeightBold};
|
font-weight: ${({ theme }) => theme.typography.fontWeightBold};
|
||||||
}
|
}
|
||||||
|
${({ kind }) =>
|
||||||
|
kind === 'patternProperties' &&
|
||||||
|
css`
|
||||||
|
display: inline-flex;
|
||||||
|
margin-right: 20px;
|
||||||
|
|
||||||
|
> span.property-name {
|
||||||
|
white-space: break-spaces;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
content: '/';
|
||||||
|
filter: opacity(0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> svg {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
`}
|
||||||
}
|
}
|
||||||
${ShelfIcon} {
|
${ShelfIcon} {
|
||||||
height: ${({ theme }) => theme.schema.arrow.size};
|
height: ${({ theme }) => theme.schema.arrow.size};
|
||||||
|
@ -56,6 +77,10 @@ export const RequiredLabel = styled(FieldLabel.withComponent('div'))`
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const PropertyLabel = styled(RequiredLabel)`
|
||||||
|
color: ${props => props.theme.colors.primary.light};
|
||||||
|
`;
|
||||||
|
|
||||||
export const RecursiveLabel = styled(FieldLabel)`
|
export const RecursiveLabel = styled(FieldLabel)`
|
||||||
color: ${({ theme }) => theme.colors.warning.main};
|
color: ${({ theme }) => theme.colors.warning.main};
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
|
@ -37,6 +37,7 @@ class IntShelfIcon extends React.PureComponent<{
|
||||||
export const ShelfIcon = styled(IntShelfIcon)`
|
export const ShelfIcon = styled(IntShelfIcon)`
|
||||||
height: ${props => props.size || '18px'};
|
height: ${props => props.size || '18px'};
|
||||||
width: ${props => props.size || '18px'};
|
width: ${props => props.size || '18px'};
|
||||||
|
min-width: ${props => props.size || '18px'};
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
float: ${props => props.float || ''};
|
float: ${props => props.float || ''};
|
||||||
transition: transform 0.2s ease-out;
|
transition: transform 0.2s ease-out;
|
||||||
|
|
|
@ -4,9 +4,20 @@ import { ConstraintsView } from './FieldContstraints';
|
||||||
import { Pattern } from './Pattern';
|
import { Pattern } from './Pattern';
|
||||||
import { SchemaModel } from '../../services';
|
import { SchemaModel } from '../../services';
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
import { OptionsContext } from '../OptionsProvider';
|
||||||
|
|
||||||
export function ArrayItemDetails({ schema }: { schema: SchemaModel }) {
|
export function ArrayItemDetails({ schema }: { schema: SchemaModel }) {
|
||||||
if (!schema || (schema.type === 'string' && !schema.constraints.length)) return null;
|
const { hideSchemaPattern } = React.useContext(OptionsContext);
|
||||||
|
if (
|
||||||
|
!schema ||
|
||||||
|
(schema.type === 'string' && !schema.constraints.length) ||
|
||||||
|
((!schema?.pattern || hideSchemaPattern) &&
|
||||||
|
!schema.items &&
|
||||||
|
!schema.displayFormat &&
|
||||||
|
!schema.constraints.length) // return null for cases where all constraints are empty
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ClickablePropertyNameCell, RequiredLabel } from '../../common-elements/fields';
|
import {
|
||||||
|
ClickablePropertyNameCell,
|
||||||
|
PropertyLabel,
|
||||||
|
RequiredLabel,
|
||||||
|
} from '../../common-elements/fields';
|
||||||
import { FieldDetails } from './FieldDetails';
|
import { FieldDetails } from './FieldDetails';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
InnerPropertiesWrap,
|
InnerPropertiesWrap,
|
||||||
PropertyBullet,
|
PropertyBullet,
|
||||||
|
@ -11,11 +14,11 @@ import {
|
||||||
PropertyDetailsCell,
|
PropertyDetailsCell,
|
||||||
PropertyNameCell,
|
PropertyNameCell,
|
||||||
} from '../../common-elements/fields-layout';
|
} from '../../common-elements/fields-layout';
|
||||||
|
|
||||||
import { ShelfIcon } from '../../common-elements/';
|
import { ShelfIcon } from '../../common-elements/';
|
||||||
|
import { Schema } from '../Schema/Schema';
|
||||||
|
|
||||||
import { FieldModel } from '../../services/models';
|
import type { SchemaOptions } from '../Schema/Schema';
|
||||||
import { Schema, SchemaOptions } from '../Schema/Schema';
|
import type { FieldModel } from '../../services/models';
|
||||||
|
|
||||||
export interface FieldProps extends SchemaOptions {
|
export interface FieldProps extends SchemaOptions {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -46,12 +49,20 @@ export class Field extends React.Component<FieldProps> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, field, isLast, expandByDefault } = this.props;
|
const { className = '', field, isLast, expandByDefault } = this.props;
|
||||||
const { name, deprecated, required, kind } = field;
|
const { name, deprecated, required, kind } = field;
|
||||||
const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular;
|
const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular;
|
||||||
|
|
||||||
const expanded = field.expanded === undefined ? expandByDefault : field.expanded;
|
const expanded = field.expanded === undefined ? expandByDefault : field.expanded;
|
||||||
|
|
||||||
|
const labels = (
|
||||||
|
<>
|
||||||
|
{kind === 'additionalProperties' && <PropertyLabel>additional property</PropertyLabel>}
|
||||||
|
{kind === 'patternProperties' && <PropertyLabel>pattern property</PropertyLabel>}
|
||||||
|
{required && <RequiredLabel>required</RequiredLabel>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
const paramName = withSubSchema ? (
|
const paramName = withSubSchema ? (
|
||||||
<ClickablePropertyNameCell
|
<ClickablePropertyNameCell
|
||||||
className={deprecated ? 'deprecated' : ''}
|
className={deprecated ? 'deprecated' : ''}
|
||||||
|
@ -64,16 +75,16 @@ export class Field extends React.Component<FieldProps> {
|
||||||
onKeyPress={this.handleKeyPress}
|
onKeyPress={this.handleKeyPress}
|
||||||
aria-label="expand properties"
|
aria-label="expand properties"
|
||||||
>
|
>
|
||||||
<span>{name}</span>
|
<span className="property-name">{name}</span>
|
||||||
<ShelfIcon direction={expanded ? 'down' : 'right'} />
|
<ShelfIcon direction={expanded ? 'down' : 'right'} />
|
||||||
</button>
|
</button>
|
||||||
{required && <RequiredLabel> required </RequiredLabel>}
|
{labels}
|
||||||
</ClickablePropertyNameCell>
|
</ClickablePropertyNameCell>
|
||||||
) : (
|
) : (
|
||||||
<PropertyNameCell className={deprecated ? 'deprecated' : undefined} kind={kind} title={name}>
|
<PropertyNameCell className={deprecated ? 'deprecated' : undefined} kind={kind} title={name}>
|
||||||
<PropertyBullet />
|
<PropertyBullet />
|
||||||
<span>{name}</span>
|
<span className="property-name">{name}</span>
|
||||||
{required && <RequiredLabel> required </RequiredLabel>}
|
{labels}
|
||||||
</PropertyNameCell>
|
</PropertyNameCell>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RecursiveLabel,
|
RecursiveLabel,
|
||||||
|
@ -24,7 +25,7 @@ import { OptionsContext } from '../OptionsProvider';
|
||||||
import { Pattern } from './Pattern';
|
import { Pattern } from './Pattern';
|
||||||
import { ArrayItemDetails } from './ArrayItemDetails';
|
import { ArrayItemDetails } from './ArrayItemDetails';
|
||||||
|
|
||||||
function FieldDetailsComponent(props: FieldProps) {
|
export const FieldDetailsComponent = observer((props: FieldProps) => {
|
||||||
const { enumSkipQuotes, hideSchemaTitles } = React.useContext(OptionsContext);
|
const { enumSkipQuotes, hideSchemaTitles } = React.useContext(OptionsContext);
|
||||||
|
|
||||||
const { showExamples, field, renderDiscriminatorSwitch } = props;
|
const { showExamples, field, renderDiscriminatorSwitch } = props;
|
||||||
|
@ -107,6 +108,6 @@ function FieldDetailsComponent(props: FieldProps) {
|
||||||
{(_const && <FieldDetail label={l('const') + ':'} value={_const} />) || null}
|
{(_const && <FieldDetail label={l('const') + ':'} value={_const} />) || null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export const FieldDetails = React.memo<FieldProps>(FieldDetailsComponent);
|
export const FieldDetails = React.memo<FieldProps>(FieldDetailsComponent);
|
||||||
|
|
|
@ -27,20 +27,20 @@ class Json extends React.PureComponent<JsonProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInner = ({ renderCopyButton }) => {
|
renderInner = ({ renderCopyButton }) => {
|
||||||
const showFoldingButtons = this.props.data && Object.values(this.props.data).some(
|
const showFoldingButtons =
|
||||||
(value) => typeof value === 'object' && value !== null,
|
this.props.data &&
|
||||||
);
|
Object.values(this.props.data).some(value => typeof value === 'object' && value !== null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<JsonViewerWrap>
|
<JsonViewerWrap>
|
||||||
<SampleControls>
|
<SampleControls>
|
||||||
{renderCopyButton()}
|
{renderCopyButton()}
|
||||||
{showFoldingButtons &&
|
{showFoldingButtons && (
|
||||||
<>
|
<>
|
||||||
<button onClick={this.expandAll}> Expand all </button>
|
<button onClick={this.expandAll}> Expand all </button>
|
||||||
<button onClick={this.collapseAll}> Collapse all </button>
|
<button onClick={this.collapseAll}> Collapse all </button>
|
||||||
</>
|
</>
|
||||||
}
|
)}
|
||||||
</SampleControls>
|
</SampleControls>
|
||||||
<OptionsContext.Consumer>
|
<OptionsContext.Consumer>
|
||||||
{options => (
|
{options => (
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { StyledComponent } from 'styled-components';
|
||||||
|
|
||||||
export const linksCss = css`
|
export const linksCss = css`
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: ${props => props.theme.typography.links.textDecoration};
|
||||||
color: ${props => props.theme.typography.links.color};
|
color: ${props => props.theme.typography.links.color};
|
||||||
|
|
||||||
&:visited {
|
&:visited {
|
||||||
|
@ -15,6 +15,7 @@ export const linksCss = css`
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${props => props.theme.typography.links.hover};
|
color: ${props => props.theme.typography.links.hover};
|
||||||
|
text-decoration: ${props => props.theme.typography.links.hoverTextDecoration};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
||||||
import { Schema } from '../Schema';
|
import { Schema } from '../Schema';
|
||||||
|
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
import { ConstraintsView } from '../Fields/FieldContstraints';
|
||||||
|
|
||||||
function safePush(obj, prop, item) {
|
function safePush(obj, prop, item) {
|
||||||
if (!obj[prop]) {
|
if (!obj[prop]) {
|
||||||
|
@ -79,6 +80,9 @@ export function BodyContent(props: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{description !== undefined && <Markdown source={description} />}
|
{description !== undefined && <Markdown source={description} />}
|
||||||
|
{schema?.type === 'object' && (
|
||||||
|
<ConstraintsView constraints={schema?.constraints || []} />
|
||||||
|
)}
|
||||||
<Schema
|
<Schema
|
||||||
skipReadOnly={isRequestType}
|
skipReadOnly={isRequestType}
|
||||||
skipWriteOnly={!isRequestType}
|
skipWriteOnly={!isRequestType}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { Schema } from '../Schema';
|
||||||
import { Extensions } from '../Fields/Extensions';
|
import { Extensions } from '../Fields/Extensions';
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
import { ResponseHeaders } from './ResponseHeaders';
|
import { ResponseHeaders } from './ResponseHeaders';
|
||||||
|
import { ConstraintsView } from '../Fields/FieldContstraints';
|
||||||
|
|
||||||
export class ResponseDetails extends React.PureComponent<{ response: ResponseModel }> {
|
export class ResponseDetails extends React.PureComponent<{ response: ResponseModel }> {
|
||||||
render() {
|
render() {
|
||||||
|
@ -21,7 +22,14 @@ export class ResponseDetails extends React.PureComponent<{ response: ResponseMod
|
||||||
<ResponseHeaders headers={headers} />
|
<ResponseHeaders headers={headers} />
|
||||||
<MediaTypesSwitch content={content} renderDropdown={this.renderDropdown}>
|
<MediaTypesSwitch content={content} renderDropdown={this.renderDropdown}>
|
||||||
{({ schema }) => {
|
{({ schema }) => {
|
||||||
return <Schema skipWriteOnly={true} key="schema" schema={schema} />;
|
return (
|
||||||
|
<>
|
||||||
|
{schema?.type === 'object' && (
|
||||||
|
<ConstraintsView constraints={schema?.constraints || []} />
|
||||||
|
)}
|
||||||
|
<Schema skipWriteOnly={true} key="schema" schema={schema} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
</MediaTypesSwitch>
|
</MediaTypesSwitch>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { ArrayClosingLabel, ArrayOpenningLabel } from '../../common-elements';
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
import { humanizeConstraints } from '../../utils';
|
import { humanizeConstraints } from '../../utils';
|
||||||
import { TypeName } from '../../common-elements/fields';
|
import { TypeName } from '../../common-elements/fields';
|
||||||
|
import { ObjectSchema } from './ObjectSchema';
|
||||||
|
|
||||||
const PaddedSchema = styled.div`
|
const PaddedSchema = styled.div`
|
||||||
padding-left: ${({ theme }) => theme.spacing.unit * 2}px;
|
padding-left: ${({ theme }) => theme.spacing.unit * 2}px;
|
||||||
|
@ -21,6 +22,9 @@ export class ArraySchema extends React.PureComponent<SchemaProps> {
|
||||||
? ''
|
? ''
|
||||||
: `(${humanizeConstraints(schema)})`;
|
: `(${humanizeConstraints(schema)})`;
|
||||||
|
|
||||||
|
if (schema.fields) {
|
||||||
|
return <ObjectSchema {...(this.props as any)} level={this.props.level} />;
|
||||||
|
}
|
||||||
if (schema.displayType && !itemsSchema && !minMaxItems.length) {
|
if (schema.displayType && !itemsSchema && !minMaxItems.length) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from '../../common-elements/schema';
|
} from '../../common-elements/schema';
|
||||||
import { Badge } from '../../common-elements/shelfs';
|
import { Badge } from '../../common-elements/shelfs';
|
||||||
import { SchemaModel } from '../../services/models';
|
import { SchemaModel } from '../../services/models';
|
||||||
|
import { ConstraintsView } from '../Fields/FieldContstraints';
|
||||||
import { Schema, SchemaProps } from './Schema';
|
import { Schema, SchemaProps } from './Schema';
|
||||||
|
|
||||||
export interface OneOfButtonProps {
|
export interface OneOfButtonProps {
|
||||||
|
@ -47,6 +48,8 @@ export class OneOfSchema extends React.Component<SchemaProps> {
|
||||||
if (oneOf === undefined) {
|
if (oneOf === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const activeSchema = oneOf[schema.activeOneOf];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<OneOfLabel> {schema.oneOfType} </OneOfLabel>
|
<OneOfLabel> {schema.oneOfType} </OneOfLabel>
|
||||||
|
@ -58,7 +61,8 @@ export class OneOfSchema extends React.Component<SchemaProps> {
|
||||||
<div>
|
<div>
|
||||||
{oneOf[schema.activeOneOf].deprecated && <Badge type="warning">Deprecated</Badge>}
|
{oneOf[schema.activeOneOf].deprecated && <Badge type="warning">Deprecated</Badge>}
|
||||||
</div>
|
</div>
|
||||||
<Schema {...this.props} schema={oneOf[schema.activeOneOf]} />
|
<ConstraintsView constraints={activeSchema.constraints} />
|
||||||
|
<Schema {...this.props} schema={activeSchema} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
71
src/components/SecurityRequirement/OAuthFlow.tsx
Normal file
71
src/components/SecurityRequirement/OAuthFlow.tsx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { OpenAPISecurityScheme } from '../../types';
|
||||||
|
import { SecurityRow } from './styled.elements';
|
||||||
|
import { SeeMore } from '../SeeMore/SeeMore';
|
||||||
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
|
||||||
|
export interface OAuthFlowProps {
|
||||||
|
type: string;
|
||||||
|
flow: OpenAPISecurityScheme['flows'][keyof OpenAPISecurityScheme['flows']];
|
||||||
|
RequiredScopes?: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OAuthFlowComponent(props: OAuthFlowProps) {
|
||||||
|
const { type, flow, RequiredScopes } = props;
|
||||||
|
const scopesNames = Object.keys(flow?.scopes || {});
|
||||||
|
console.log('rended');
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>Flow type: </b>
|
||||||
|
<code>{type} </code>
|
||||||
|
</SecurityRow>
|
||||||
|
{(type === 'implicit' || type === 'authorizationCode') && (
|
||||||
|
<SecurityRow>
|
||||||
|
<strong> Authorization URL: </strong>
|
||||||
|
<code>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={(flow as any).authorizationUrl}>
|
||||||
|
{(flow as any).authorizationUrl}
|
||||||
|
</a>
|
||||||
|
</code>
|
||||||
|
</SecurityRow>
|
||||||
|
)}
|
||||||
|
{(type === 'password' || type === 'clientCredentials' || type === 'authorizationCode') && (
|
||||||
|
<SecurityRow>
|
||||||
|
<b> Token URL: </b>
|
||||||
|
<code>{(flow as any).tokenUrl}</code>
|
||||||
|
</SecurityRow>
|
||||||
|
)}
|
||||||
|
{flow!.refreshUrl && (
|
||||||
|
<SecurityRow>
|
||||||
|
<strong> Refresh URL: </strong>
|
||||||
|
{flow!.refreshUrl}
|
||||||
|
</SecurityRow>
|
||||||
|
)}
|
||||||
|
{!!scopesNames.length && (
|
||||||
|
<>
|
||||||
|
{RequiredScopes || null}
|
||||||
|
<SecurityRow>
|
||||||
|
<b> Scopes: </b>
|
||||||
|
</SecurityRow>
|
||||||
|
<SeeMore height="4em">
|
||||||
|
<ul>
|
||||||
|
{scopesNames.map(scope => (
|
||||||
|
<li key={scope}>
|
||||||
|
<code>{scope}</code> -{' '}
|
||||||
|
<Markdown
|
||||||
|
className={'redoc-markdown'}
|
||||||
|
inline={true}
|
||||||
|
source={flow!.scopes[scope] || ''}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</SeeMore>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OAuthFlow = React.memo<OAuthFlowProps>(OAuthFlowComponent);
|
18
src/components/SecurityRequirement/RequiredScopesRow.tsx
Normal file
18
src/components/SecurityRequirement/RequiredScopesRow.tsx
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export const RequiredScopesRow = ({ scopes }: { scopes: string[] }): JSX.Element | null => {
|
||||||
|
if (!scopes.length) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<b>Required scopes: </b>
|
||||||
|
{scopes.map((scope, idx) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={idx}>
|
||||||
|
<code>{scope}</code>{' '}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
65
src/components/SecurityRequirement/SecurityDetails.tsx
Normal file
65
src/components/SecurityRequirement/SecurityDetails.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { SecuritySchemeModel } from '../../services';
|
||||||
|
import { titleize } from '../../utils';
|
||||||
|
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
||||||
|
import { SecurityRow } from './styled.elements';
|
||||||
|
import { OAuthFlow } from './OAuthFlow';
|
||||||
|
|
||||||
|
interface SecuritySchemaProps {
|
||||||
|
RequiredScopes?: JSX.Element;
|
||||||
|
scheme: SecuritySchemeModel;
|
||||||
|
}
|
||||||
|
export function SecurityDetails(props: SecuritySchemaProps) {
|
||||||
|
const { RequiredScopes, scheme } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledMarkdownBlock>
|
||||||
|
{scheme.apiKey ? (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>{titleize(scheme.apiKey.in || '')} parameter name: </b>
|
||||||
|
<code>{scheme.apiKey.name}</code>
|
||||||
|
</SecurityRow>
|
||||||
|
{RequiredScopes}
|
||||||
|
</>
|
||||||
|
) : scheme.http ? (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>HTTP Authorization Scheme: </b>
|
||||||
|
<code>{scheme.http.scheme}</code>
|
||||||
|
</SecurityRow>
|
||||||
|
<SecurityRow>
|
||||||
|
{scheme.http.scheme === 'bearer' && scheme.http.bearerFormat && (
|
||||||
|
<>
|
||||||
|
<b>Bearer format: </b>
|
||||||
|
<code>{scheme.http.bearerFormat}</code>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</SecurityRow>
|
||||||
|
{RequiredScopes}
|
||||||
|
</>
|
||||||
|
) : scheme.openId ? (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>Connect URL: </b>
|
||||||
|
<code>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={scheme.openId.connectUrl}>
|
||||||
|
{scheme.openId.connectUrl}
|
||||||
|
</a>
|
||||||
|
</code>
|
||||||
|
</SecurityRow>
|
||||||
|
{RequiredScopes}
|
||||||
|
</>
|
||||||
|
) : scheme.flows ? (
|
||||||
|
Object.keys(scheme.flows).map(type => (
|
||||||
|
<OAuthFlow
|
||||||
|
key={type}
|
||||||
|
type={type}
|
||||||
|
RequiredScopes={RequiredScopes}
|
||||||
|
flow={scheme.flows[type]}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : null}
|
||||||
|
</StyledMarkdownBlock>
|
||||||
|
);
|
||||||
|
}
|
43
src/components/SecurityRequirement/SecurityHeader.tsx
Normal file
43
src/components/SecurityRequirement/SecurityHeader.tsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
||||||
|
import {
|
||||||
|
ScopeName,
|
||||||
|
SecurityRequirementAndWrap,
|
||||||
|
SecurityRequirementOrWrap,
|
||||||
|
} from './styled.elements';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { AUTH_TYPES } from '../SecuritySchemes/SecuritySchemes';
|
||||||
|
|
||||||
|
export interface SecurityRequirementProps {
|
||||||
|
security: SecurityRequirementModel;
|
||||||
|
showSecuritySchemeType?: boolean;
|
||||||
|
expanded: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SecurityHeader(props: SecurityRequirementProps) {
|
||||||
|
const { security, showSecuritySchemeType, expanded } = props;
|
||||||
|
|
||||||
|
const grouping = security.schemes.length > 1;
|
||||||
|
return (
|
||||||
|
<SecurityRequirementOrWrap expanded={expanded}>
|
||||||
|
{grouping && '('}
|
||||||
|
{security.schemes.map(scheme => {
|
||||||
|
return (
|
||||||
|
<SecurityRequirementAndWrap key={scheme.id}>
|
||||||
|
{showSecuritySchemeType && `${AUTH_TYPES[scheme.type] || scheme.type}: `}
|
||||||
|
<i>{scheme.displayName}</i>
|
||||||
|
{expanded && scheme.scopes.length
|
||||||
|
? [
|
||||||
|
' (',
|
||||||
|
scheme.scopes.map<React.ReactNode>(scope => (
|
||||||
|
<ScopeName key={scope}>{scope}</ScopeName>
|
||||||
|
)),
|
||||||
|
') ',
|
||||||
|
]
|
||||||
|
: null}
|
||||||
|
</SecurityRequirementAndWrap>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{grouping && ') '}
|
||||||
|
</SecurityRequirementOrWrap>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,153 +1,102 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
import styled, { media } from '../../styled-components';
|
|
||||||
|
|
||||||
import { Link, UnderlinedHeader } from '../../common-elements/';
|
|
||||||
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
||||||
import { linksCss } from '../Markdown/styled.elements';
|
import {
|
||||||
|
AuthHeader,
|
||||||
const ScopeNameList = styled.ul`
|
AuthHeaderColumn,
|
||||||
display: inline;
|
SecuritiesColumn,
|
||||||
list-style: none;
|
SecurityDetailsStyle,
|
||||||
padding: 0;
|
Wrap,
|
||||||
|
} from './styled.elements';
|
||||||
li {
|
import { useStore } from '../StoreBuilder';
|
||||||
display: inherit;
|
import { SecurityHeader } from './SecurityHeader';
|
||||||
|
import { RequiredScopesRow } from './RequiredScopesRow';
|
||||||
&:after {
|
import { AUTH_TYPES } from '../SecuritySchemes/SecuritySchemes';
|
||||||
content: ',';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
}
|
import { SecurityDetails } from './SecurityDetails';
|
||||||
&:last-child:after {
|
import { ShelfIcon } from '../../common-elements';
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ScopeName = styled.code`
|
|
||||||
font-size: ${props => props.theme.typography.code.fontSize};
|
|
||||||
font-family: ${props => props.theme.typography.code.fontFamily};
|
|
||||||
border: 1px solid ${({ theme }) => theme.colors.border.dark};
|
|
||||||
margin: 0 3px;
|
|
||||||
padding: 0.2em;
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SecurityRequirementAndWrap = styled.span`
|
|
||||||
&:after {
|
|
||||||
content: ' AND ';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child:after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
${linksCss};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SecurityRequirementOrWrap = styled.span`
|
|
||||||
&:before {
|
|
||||||
content: '( ';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
&:after {
|
|
||||||
content: ' ) OR ';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
&:last-child:after {
|
|
||||||
content: ' )';
|
|
||||||
}
|
|
||||||
|
|
||||||
&:only-child:before,
|
|
||||||
&:only-child:after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
${linksCss};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface SecurityRequirementProps {
|
|
||||||
security: SecurityRequirementModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SecurityRequirement extends React.PureComponent<SecurityRequirementProps> {
|
|
||||||
render() {
|
|
||||||
const security = this.props.security;
|
|
||||||
return (
|
|
||||||
<SecurityRequirementOrWrap>
|
|
||||||
{security.schemes.length ? (
|
|
||||||
security.schemes.map(scheme => {
|
|
||||||
return (
|
|
||||||
<SecurityRequirementAndWrap key={scheme.id}>
|
|
||||||
<Link to={scheme.sectionId}>{scheme.displayName}</Link>
|
|
||||||
{scheme.scopes.length > 0 && ' ('}
|
|
||||||
<ScopeNameList>
|
|
||||||
{scheme.scopes.map(scope => (
|
|
||||||
<li key={scope}>
|
|
||||||
<ScopeName>{scope}</ScopeName>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ScopeNameList>
|
|
||||||
{scheme.scopes.length > 0 && ') '}
|
|
||||||
</SecurityRequirementAndWrap>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<SecurityRequirementAndWrap>None</SecurityRequirementAndWrap>
|
|
||||||
)}
|
|
||||||
</SecurityRequirementOrWrap>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuthHeaderColumn = styled.div`
|
|
||||||
flex: 1 1 auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SecuritiesColumn = styled.div`
|
|
||||||
width: ${props => props.theme.schema.defaultDetailsWidth};
|
|
||||||
${media.lessThan('small')`
|
|
||||||
margin-top: 10px;
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const AuthHeader = styled(UnderlinedHeader)`
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Wrap = styled.div`
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
margin: 1em 0;
|
|
||||||
|
|
||||||
${media.lessThan('small')`
|
|
||||||
flex-direction: column;
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface SecurityRequirementsProps {
|
export interface SecurityRequirementsProps {
|
||||||
securities: SecurityRequirementModel[];
|
securities: SecurityRequirementModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SecurityRequirements extends React.PureComponent<SecurityRequirementsProps> {
|
export function SecurityRequirements(props: SecurityRequirementsProps) {
|
||||||
render() {
|
const store = useStore();
|
||||||
const securities = this.props.securities;
|
const showSecuritySchemeType = store?.options.showSecuritySchemeType;
|
||||||
if (!securities.length) {
|
const [expanded, setExpanded] = useState(false);
|
||||||
return null;
|
|
||||||
}
|
const { securities } = props;
|
||||||
return (
|
|
||||||
<Wrap>
|
if (!securities?.length || store?.options.hideSecuritySection) {
|
||||||
<AuthHeaderColumn>
|
return null;
|
||||||
<AuthHeader>Authorizations: </AuthHeader>
|
}
|
||||||
|
|
||||||
|
const operationSecuritySchemes = store?.spec.securitySchemes.schemes.filter(({ id }) => {
|
||||||
|
return securities.find(security => security.schemes.find(scheme => scheme.id === id));
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Wrap expanded={expanded}>
|
||||||
|
<AuthHeaderColumn onClick={() => setExpanded(!expanded)}>
|
||||||
|
<AuthHeader>Authorizations:</AuthHeader>
|
||||||
|
<ShelfIcon size={'1.3em'} direction={expanded ? 'down' : 'right'} />
|
||||||
</AuthHeaderColumn>
|
</AuthHeaderColumn>
|
||||||
<SecuritiesColumn>
|
<SecuritiesColumn expanded={expanded}>
|
||||||
{securities.map((security, idx) => (
|
{securities.map((security, idx) => (
|
||||||
<SecurityRequirement key={idx} security={security} />
|
<SecurityHeader
|
||||||
|
key={idx}
|
||||||
|
expanded={expanded}
|
||||||
|
showSecuritySchemeType={showSecuritySchemeType}
|
||||||
|
security={security}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</SecuritiesColumn>
|
</SecuritiesColumn>
|
||||||
</Wrap>
|
</Wrap>
|
||||||
);
|
{expanded &&
|
||||||
}
|
operationSecuritySchemes?.length &&
|
||||||
|
operationSecuritySchemes.map((scheme, idx) => (
|
||||||
|
<SecurityDetailsStyle key={idx}>
|
||||||
|
<h5>
|
||||||
|
<LockIcon /> {AUTH_TYPES[scheme.type] || scheme.type}: {scheme.id}
|
||||||
|
</h5>
|
||||||
|
<Markdown source={scheme.description || ''} />
|
||||||
|
<SecurityDetails
|
||||||
|
key={scheme.id}
|
||||||
|
scheme={scheme}
|
||||||
|
RequiredScopes={
|
||||||
|
<RequiredScopesRow scopes={getRequiredScopes(scheme.id, securities)} />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SecurityDetailsStyle>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LockIcon = () => (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
function getRequiredScopes(id: string, securities: SecurityRequirementModel[]): string[] {
|
||||||
|
const allScopes: string[] = [];
|
||||||
|
let securitiesLength = securities.length;
|
||||||
|
|
||||||
|
while (securitiesLength--) {
|
||||||
|
const security = securities[securitiesLength];
|
||||||
|
let schemesLength = security.schemes.length;
|
||||||
|
while (schemesLength--) {
|
||||||
|
const scheme = security.schemes[schemesLength];
|
||||||
|
if (scheme.id === id) {
|
||||||
|
allScopes.push(...scheme.scopes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(new Set(allScopes));
|
||||||
}
|
}
|
||||||
|
|
129
src/components/SecurityRequirement/styled.elements.ts
Normal file
129
src/components/SecurityRequirement/styled.elements.ts
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { linksCss } from '../Markdown/styled.elements';
|
||||||
|
import { media } from '../../styled-components';
|
||||||
|
import { UnderlinedHeader } from '../../common-elements';
|
||||||
|
|
||||||
|
export const Header = styled.div`
|
||||||
|
background-color: #e4e7eb;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ScopeNameList = styled.ul`
|
||||||
|
display: inline;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: inherit;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ',';
|
||||||
|
}
|
||||||
|
&:last-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ScopeName = styled.code`
|
||||||
|
font-size: ${props => props.theme.typography.code.fontSize};
|
||||||
|
font-family: ${props => props.theme.typography.code.fontFamily};
|
||||||
|
margin: 0 3px;
|
||||||
|
padding: 0.2em;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ',';
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityRequirementAndWrap = styled.span`
|
||||||
|
&:after {
|
||||||
|
content: ' and ';
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
${linksCss};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityRequirementOrWrap = styled.span<{ expanded?: boolean }>`
|
||||||
|
${p => !p.expanded && `white-space: nowrap;`}
|
||||||
|
&:after {
|
||||||
|
content: ' or ';
|
||||||
|
${p => p.expanded && `content: ' or \\a';`}
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:after,
|
||||||
|
&:only-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
${linksCss};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthHeaderColumn = styled.div`
|
||||||
|
flex: 1 1 auto;
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecuritiesColumn = styled.div<{ expanded?: boolean }>`
|
||||||
|
width: ${props => props.theme.schema.defaultDetailsWidth};
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
${p =>
|
||||||
|
p.expanded &&
|
||||||
|
`background: ${p.theme.colors.gray['100']};
|
||||||
|
padding: 8px 9.6px;
|
||||||
|
margin: 20px 0;
|
||||||
|
width: 100%;
|
||||||
|
`};
|
||||||
|
${media.lessThan('small')`
|
||||||
|
margin-top: 10px;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthHeader = styled(UnderlinedHeader)`
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Wrap = styled.div<{ expanded?: boolean }>`
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
margin: 1em 0;
|
||||||
|
flex-direction: ${p => (p.expanded ? 'column' : 'row')};
|
||||||
|
${media.lessThan('small')`
|
||||||
|
flex-direction: column;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityRow = styled.div`
|
||||||
|
margin: 0.5em 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityDetailsStyle = styled.div`
|
||||||
|
border-bottom: 1px solid ${({ theme }) => theme.colors.border.dark};
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
padding-bottom: 0.7em;
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
line-height: 1em;
|
||||||
|
margin: 0 0 0.6em;
|
||||||
|
font-size: ${({ theme }) => theme.typography.fontSize};
|
||||||
|
}
|
||||||
|
|
||||||
|
.redoc-markdown p:first-child {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
`;
|
|
@ -1,72 +1,18 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { SecuritySchemesModel } from '../../services/models';
|
import { SecuritySchemesModel } from '../../services';
|
||||||
|
import { H2, Row, ShareLink, MiddlePanel, Section } from '../../common-elements';
|
||||||
import { H2, MiddlePanel, Row, Section, ShareLink } from '../../common-elements';
|
|
||||||
import { OpenAPISecurityScheme } from '../../types';
|
|
||||||
import { titleize } from '../../utils/helpers';
|
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
import { SecurityDetails } from '../SecurityRequirement/SecurityDetails';
|
||||||
|
import { SecurityDetailsStyle, SecurityRow } from '../SecurityRequirement/styled.elements';
|
||||||
|
|
||||||
const AUTH_TYPES = {
|
export const AUTH_TYPES = {
|
||||||
oauth2: 'OAuth2',
|
oauth2: 'OAuth2',
|
||||||
apiKey: 'API Key',
|
apiKey: 'API Key',
|
||||||
http: 'HTTP',
|
http: 'HTTP',
|
||||||
openIdConnect: 'OpenID Connect',
|
openIdConnect: 'OpenID Connect',
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface OAuthFlowProps {
|
|
||||||
type: string;
|
|
||||||
flow: OpenAPISecurityScheme['flows'][keyof OpenAPISecurityScheme['flows']];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OAuthFlow extends React.PureComponent<OAuthFlowProps> {
|
|
||||||
render() {
|
|
||||||
const { type, flow } = this.props;
|
|
||||||
const scopesNames = Object.keys(flow?.scopes || {});
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<th> {type} OAuth Flow </th>
|
|
||||||
<td>
|
|
||||||
{type === 'implicit' || type === 'authorizationCode' ? (
|
|
||||||
<div>
|
|
||||||
<strong> Authorization URL: </strong>
|
|
||||||
{(flow as any).authorizationUrl}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{type === 'password' || type === 'clientCredentials' || type === 'authorizationCode' ? (
|
|
||||||
<div>
|
|
||||||
<strong> Token URL: </strong>
|
|
||||||
{(flow as any).tokenUrl}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{flow!.refreshUrl && (
|
|
||||||
<div>
|
|
||||||
<strong> Refresh URL: </strong>
|
|
||||||
{flow!.refreshUrl}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!!scopesNames.length && (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<strong> Scopes: </strong>
|
|
||||||
</div>
|
|
||||||
<ul>
|
|
||||||
{scopesNames.map(scope => (
|
|
||||||
<li key={scope}>
|
|
||||||
<code>{scope}</code> -{' '}
|
|
||||||
<Markdown inline={true} source={flow!.scopes[scope] || ''} />
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SecurityDefsProps {
|
export interface SecurityDefsProps {
|
||||||
securitySchemes: SecuritySchemesModel;
|
securitySchemes: SecuritySchemesModel;
|
||||||
}
|
}
|
||||||
|
@ -82,52 +28,13 @@ export class SecurityDefs extends React.PureComponent<SecurityDefsProps> {
|
||||||
{scheme.displayName}
|
{scheme.displayName}
|
||||||
</H2>
|
</H2>
|
||||||
<Markdown source={scheme.description || ''} />
|
<Markdown source={scheme.description || ''} />
|
||||||
<StyledMarkdownBlock>
|
<SecurityDetailsStyle>
|
||||||
<table className="security-details">
|
<SecurityRow>
|
||||||
<tbody>
|
<b>Security Scheme Type: </b>
|
||||||
<tr>
|
<span>{AUTH_TYPES[scheme.type] || scheme.type}</span>
|
||||||
<th> Security Scheme Type </th>
|
</SecurityRow>
|
||||||
<td> {AUTH_TYPES[scheme.type] || scheme.type} </td>
|
<SecurityDetails scheme={scheme} />
|
||||||
</tr>
|
</SecurityDetailsStyle>
|
||||||
{scheme.apiKey ? (
|
|
||||||
<tr>
|
|
||||||
<th> {titleize(scheme.apiKey.in || '')} parameter name:</th>
|
|
||||||
<td> {scheme.apiKey.name} </td>
|
|
||||||
</tr>
|
|
||||||
) : scheme.http ? (
|
|
||||||
[
|
|
||||||
<tr key="scheme">
|
|
||||||
<th> HTTP Authorization Scheme </th>
|
|
||||||
<td> {scheme.http.scheme} </td>
|
|
||||||
</tr>,
|
|
||||||
scheme.http.scheme === 'bearer' && scheme.http.bearerFormat && (
|
|
||||||
<tr key="bearer">
|
|
||||||
<th> Bearer format </th>
|
|
||||||
<td> "{scheme.http.bearerFormat}" </td>
|
|
||||||
</tr>
|
|
||||||
),
|
|
||||||
]
|
|
||||||
) : scheme.openId ? (
|
|
||||||
<tr>
|
|
||||||
<th> Connect URL </th>
|
|
||||||
<td>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
href={scheme.openId.connectUrl}
|
|
||||||
>
|
|
||||||
{scheme.openId.connectUrl}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : scheme.flows ? (
|
|
||||||
Object.keys(scheme.flows).map(type => (
|
|
||||||
<OAuthFlow key={type} type={type} flow={scheme.flows[type]} />
|
|
||||||
))
|
|
||||||
) : null}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</StyledMarkdownBlock>
|
|
||||||
</MiddlePanel>
|
</MiddlePanel>
|
||||||
</Row>
|
</Row>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
65
src/components/SeeMore/SeeMore.tsx
Normal file
65
src/components/SeeMore/SeeMore.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const TOLERANCE_PX = 20;
|
||||||
|
|
||||||
|
interface SeeMoreProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
height: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SeeMore({ children, height }: SeeMoreProps): JSX.Element {
|
||||||
|
const ref = React.createRef() as React.RefObject<HTMLDivElement>;
|
||||||
|
const [showMore, setShowMore] = React.useState(false);
|
||||||
|
const [showLink, setShowLink] = React.useState(false);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (ref.current && ref.current.clientHeight + TOLERANCE_PX < ref.current.scrollHeight) {
|
||||||
|
setShowLink(true);
|
||||||
|
}
|
||||||
|
}, [ref]);
|
||||||
|
|
||||||
|
const onClickMore = () => {
|
||||||
|
setShowMore(!showMore);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Container
|
||||||
|
ref={ref}
|
||||||
|
className={showMore ? '' : 'container'}
|
||||||
|
style={{ height: showMore ? 'auto' : height }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Container>
|
||||||
|
<ButtonContainer dimmed={!showMore}>
|
||||||
|
{showLink && (
|
||||||
|
<ButtonLinkStyled onClick={onClickMore}>
|
||||||
|
{showMore ? 'See less' : 'See more'}
|
||||||
|
</ButtonLinkStyled>
|
||||||
|
)}
|
||||||
|
</ButtonContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
overflow-y: hidden;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonContainer = styled.div<{ dimmed?: boolean }>`
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5em;
|
||||||
|
${({ dimmed }) =>
|
||||||
|
dimmed &&
|
||||||
|
`background-image: linear-gradient(to bottom, transparent,rgb(255 255 255));
|
||||||
|
position: relative;
|
||||||
|
top: -0.5em;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
background-position-y: -1em;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonLinkStyled = styled.a`
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { createContext } from 'react';
|
import { createContext, useContext } from 'react';
|
||||||
|
|
||||||
import { AppStore } from '../services/';
|
import { AppStore } from '../services/';
|
||||||
import { RedocRawOptions } from '../services/RedocNormalizedOptions';
|
import { RedocRawOptions } from '../services/RedocNormalizedOptions';
|
||||||
|
@ -79,3 +79,7 @@ export function StoreBuilder(props: StoreBuilderProps) {
|
||||||
store,
|
store,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useStore(): AppStore | undefined {
|
||||||
|
return useContext(StoreContext);
|
||||||
|
}
|
||||||
|
|
|
@ -53,5 +53,30 @@ describe('Components', () => {
|
||||||
expect(component.render()).toMatchSnapshot();
|
expect(component.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Show minProperties/maxProperties constraints oneOf', () => {
|
||||||
|
const schema = new SchemaModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
description: 'Test description',
|
||||||
|
minProperties: 1,
|
||||||
|
maxProperties: 1,
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'The name and value o',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'',
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
const component = shallow(withTheme(<Schema schema={schema} />));
|
||||||
|
expect(component.html().includes('= 1 properties')).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
67
src/components/__tests__/Schema.test.tsx
Normal file
67
src/components/__tests__/Schema.test.tsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* tslint:disable:no-implicit-dependencies */
|
||||||
|
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Schema } from '../';
|
||||||
|
import { OpenAPIParser, SchemaModel } from '../../services';
|
||||||
|
import { RedocNormalizedOptions } from '../../services/RedocNormalizedOptions';
|
||||||
|
import { withTheme } from '../testProviders';
|
||||||
|
|
||||||
|
const options = new RedocNormalizedOptions({});
|
||||||
|
describe('Components', () => {
|
||||||
|
describe('SchemaView', () => {
|
||||||
|
const parser = new OpenAPIParser(
|
||||||
|
{ openapi: '3.0', info: { title: 'test', version: '0' }, paths: {} },
|
||||||
|
undefined,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('Show minProperties/maxProperties constraints', () => {
|
||||||
|
const schema = new SchemaModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: 'object',
|
||||||
|
minProperties: 1,
|
||||||
|
properties: {
|
||||||
|
address: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'',
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
const component = shallow(withTheme(<Schema schema={schema} />));
|
||||||
|
expect(component.html().includes('non-empty')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Show range minProperties/maxProperties constraints', () => {
|
||||||
|
const schema = new SchemaModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: 'object',
|
||||||
|
minProperties: 2,
|
||||||
|
maxProperties: 10,
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'',
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
it('should includes [ 2 .. 10 ] properties', () => {
|
||||||
|
const component = shallow(withTheme(<Schema schema={schema} />));
|
||||||
|
expect(component.html().includes('[ 2 .. 10 ] properties')).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,28 +1,72 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
|
|
||||||
import { OpenAPIParser } from '../../services';
|
import {
|
||||||
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
createStore,
|
||||||
import { SecurityRequirement } from '../SecurityRequirement/SecurityRequirement';
|
OpenAPIParser,
|
||||||
import { RedocNormalizedOptions } from '../../services/RedocNormalizedOptions';
|
OperationModel,
|
||||||
|
RedocNormalizedOptions,
|
||||||
|
SecuritySchemesModel,
|
||||||
|
} from '../../services';
|
||||||
|
import { StoreProvider } from '../StoreBuilder';
|
||||||
|
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
||||||
|
import { withTheme } from '../testProviders';
|
||||||
|
import { SecurityDefs } from '../SecuritySchemes/SecuritySchemes';
|
||||||
|
import * as simpleSecurityFixture from './fixtures/simple-security-fixture.json';
|
||||||
|
|
||||||
const options = new RedocNormalizedOptions({});
|
describe('SecurityRequirement', () => {
|
||||||
describe('Components', () => {
|
it('should render authDefinition', async () => {
|
||||||
describe('SecurityRequirement', () => {
|
const store = await createStore(simpleSecurityFixture, undefined, {
|
||||||
describe('SecurityRequirement', () => {
|
showSecuritySchemeType: true,
|
||||||
it("should render 'None' when empty object in security open api", () => {
|
});
|
||||||
const parser = new OpenAPIParser(
|
|
||||||
{ openapi: '3.0', info: { title: 'test', version: '0' }, paths: {} },
|
store.spec.contentItems.forEach((item: OperationModel) => {
|
||||||
undefined,
|
if (item.security) {
|
||||||
options,
|
const component = mount(
|
||||||
|
withTheme(
|
||||||
|
<StoreProvider value={store}>
|
||||||
|
<SecurityRequirements securities={item.security} />,
|
||||||
|
</StoreProvider>,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const securityRequirement = new SecurityRequirementModel({}, parser);
|
expect(component.html()).toMatchSnapshot();
|
||||||
const securityElement = shallow(
|
component.find('svg').simulate('click');
|
||||||
<SecurityRequirement key={1} security={securityRequirement} />,
|
//Security expanded
|
||||||
).getElement();
|
expect(component.html()).toMatchSnapshot();
|
||||||
expect(securityElement.props.children.type.target).toEqual('span');
|
}
|
||||||
expect(securityElement.props.children.props.children).toEqual('None');
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render SecurityDefs', async () => {
|
||||||
|
const parser = new OpenAPIParser(
|
||||||
|
simpleSecurityFixture,
|
||||||
|
undefined,
|
||||||
|
new RedocNormalizedOptions({}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const component = mount(
|
||||||
|
withTheme(<SecurityDefs securitySchemes={new SecuritySchemesModel(parser)} />),
|
||||||
|
);
|
||||||
|
expect(component.html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide authDefinition', async () => {
|
||||||
|
const store = await createStore(simpleSecurityFixture, undefined, {
|
||||||
|
hideSecuritySection: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
store.spec.contentItems.forEach((item: OperationModel) => {
|
||||||
|
if (item.security) {
|
||||||
|
const component = mount(
|
||||||
|
withTheme(
|
||||||
|
<StoreProvider value={store}>
|
||||||
|
<SecurityRequirements securities={item.security} />,
|
||||||
|
</StoreProvider>,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(component.html().includes('Authorizations')).toBe(false);
|
||||||
|
expect(component.html().includes('svg')).toBe(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,6 +89,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -96,7 +97,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -107,6 +107,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -273,6 +274,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -345,6 +348,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -352,7 +356,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -363,6 +366,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -529,6 +533,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -576,6 +582,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -583,7 +590,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -594,6 +600,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -760,6 +767,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -874,6 +883,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -881,7 +891,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -892,6 +901,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1058,6 +1068,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -1130,6 +1142,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -1137,7 +1150,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1148,6 +1160,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1314,6 +1327,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -1361,6 +1376,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -1368,7 +1384,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1379,6 +1394,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1545,6 +1561,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -1615,6 +1633,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -1622,7 +1641,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1633,6 +1651,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1799,6 +1818,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -1910,6 +1931,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -1917,7 +1939,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1928,6 +1949,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -2094,6 +2116,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -2166,6 +2190,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -2173,7 +2198,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -2184,6 +2208,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -2350,6 +2375,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
@ -2397,6 +2424,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"hideHostname": false,
|
"hideHostname": false,
|
||||||
"hideSchemaPattern": false,
|
"hideSchemaPattern": false,
|
||||||
"hideSchemaTitles": false,
|
"hideSchemaTitles": false,
|
||||||
|
"hideSecuritySection": false,
|
||||||
"hideSingleRequestSampleTab": false,
|
"hideSingleRequestSampleTab": false,
|
||||||
"ignoreNamedSchemas": Set {},
|
"ignoreNamedSchemas": Set {},
|
||||||
"jsonSampleExpandLevel": 2,
|
"jsonSampleExpandLevel": 2,
|
||||||
|
@ -2404,7 +2432,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -2415,6 +2442,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"sectionsAtTheEnd": Array [],
|
"sectionsAtTheEnd": Array [],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -2581,6 +2609,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"links": Object {
|
"links": Object {
|
||||||
"color": "#32329f",
|
"color": "#32329f",
|
||||||
"hover": "#6868cf",
|
"hover": "#6868cf",
|
||||||
|
"hoverTextDecoration": "auto",
|
||||||
|
"textDecoration": "auto",
|
||||||
"visited": "#32329f",
|
"visited": "#32329f",
|
||||||
},
|
},
|
||||||
"optimizeSpeed": true,
|
"optimizeSpeed": true,
|
||||||
|
|
|
@ -44,7 +44,7 @@ exports[`Components SchemaView OneOf deprecated should match snapshot 1`] = `
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="sc-iJCRrE sc-ciSkZP jCdxGr emlfPd"
|
class="sc-iJCRrE sc-ciSkZP jCdxGr lhENGb"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`SecurityRequirement should render SecurityDefs 1`] = `
|
||||||
|
"<div id=\\"section/Authentication/petstore_auth\\" data-section-id=\\"section/Authentication/petstore_auth\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">petstore_auth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>Get access to data while protecting your account credentials.
|
||||||
|
OAuth2 is also a safer and more secure way to give you access.</p>
|
||||||
|
</div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>OAuth2</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-fXgAZx gZCyoW\\"><strong> Authorization URL: </strong><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"http://petstore.swagger.io/api/oauth/dialog\\">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div class=\\"sc-fXgAZx gZCyoW\\"><b> Scopes: </b></div><div class=\\"sc-jXcxbT blWOKY container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p>
|
||||||
|
</span></li><li><code>read:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>read your pets</p>
|
||||||
|
</span></li></ul></div><div class=\\"sc-eEVmNe gbLbHj\\"></div></div></div></div></div></div><div id=\\"section/Authentication/GitLab_PersonalAccessToken\\" data-section-id=\\"section/Authentication/GitLab_PersonalAccessToken\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_PersonalAccessToken</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p>
|
||||||
|
</div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>API Key</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div></div></div></div><div id=\\"section/Authentication/GitLab_OpenIdConnect\\" data-section-id=\\"section/Authentication/GitLab_OpenIdConnect\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_OpenIdConnect</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p>
|
||||||
|
</div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>OpenID Connect</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Connect URL: </b><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://gitlab.com/.well-known/openid-configuration\\">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div></div></div></div><div id=\\"section/Authentication/basicAuth\\" data-section-id=\\"section/Authentication/basicAuth\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">basicAuth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>HTTP</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-fXgAZx gZCyoW\\"></div></div></div></div></div></div>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`SecurityRequirement should render authDefinition 1`] = `"<div class=\\"sc-bQCEYZ eDdCgW\\"><div class=\\"sc-xGAEC femyTb\\"><h5 class=\\"sc-iqAclL sc-jHcXXw eONCmm keQLTh\\">Authorizations:</h5><svg class=\\"sc-dIsUp iPqByX\\" version=\\"1.1\\" viewBox=\\"0 0 24 24\\" x=\\"0\\" xmlns=\\"http://www.w3.org/2000/svg\\" y=\\"0\\" aria-hidden=\\"true\\"><polygon points=\\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \\"></polygon></svg></div><div class=\\"sc-dWBRfb kJFNCL\\"><span class=\\"sc-kYPZxB irJeRy\\">(<span class=\\"sc-hzUIXc gcouO\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-hzUIXc gcouO\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-hzUIXc gcouO\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-kYPZxB irJeRy\\"><span class=\\"sc-hzUIXc gcouO\\">OAuth2: <i>petstore_auth</i></span></span></div></div>,"`;
|
||||||
|
|
||||||
|
exports[`SecurityRequirement should render authDefinition 2`] = `
|
||||||
|
"<div class=\\"sc-bQCEYZ dSwEDq\\"><div class=\\"sc-xGAEC femyTb\\"><h5 class=\\"sc-iqAclL sc-jHcXXw eONCmm keQLTh\\">Authorizations:</h5><svg class=\\"sc-dIsUp fVWtGJ\\" version=\\"1.1\\" viewBox=\\"0 0 24 24\\" x=\\"0\\" xmlns=\\"http://www.w3.org/2000/svg\\" y=\\"0\\" aria-hidden=\\"true\\"><polygon points=\\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \\"></polygon></svg></div><div class=\\"sc-dWBRfb ekRdav\\"><span class=\\"sc-kYPZxB fhGdrc\\">(<span class=\\"sc-hzUIXc gcouO\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-hzUIXc gcouO\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-hzUIXc gcouO\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-kYPZxB fhGdrc\\"><span class=\\"sc-hzUIXc gcouO\\">OAuth2: <i>petstore_auth</i> (<code class=\\"sc-eHEENL fwFTyL\\">write:pets</code><code class=\\"sc-eHEENL fwFTyL\\">read:pets</code>) </span></span></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> OAuth2: petstore_auth</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>Get access to data while protecting your account credentials.
|
||||||
|
OAuth2 is also a safer and more secure way to give you access.</p>
|
||||||
|
</div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-fXgAZx gZCyoW\\"><strong> Authorization URL: </strong><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"http://petstore.swagger.io/api/oauth/dialog\\">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div><b>Required scopes: </b><code>write:pets</code> <code>read:pets</code> </div><div class=\\"sc-fXgAZx gZCyoW\\"><b> Scopes: </b></div><div class=\\"sc-jXcxbT blWOKY container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p>
|
||||||
|
</span></li><li><code>read:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>read your pets</p>
|
||||||
|
</span></li></ul></div><div class=\\"sc-eEVmNe gbLbHj\\"></div></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> API Key: GitLab_PersonalAccessToken</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p>
|
||||||
|
</div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> OpenID Connect: GitLab_OpenIdConnect</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p>
|
||||||
|
</div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Connect URL: </b><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://gitlab.com/.well-known/openid-configuration\\">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> HTTP: basicAuth</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-fXgAZx gZCyoW\\"></div></div></div>,"
|
||||||
|
`;
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0",
|
||||||
|
"info": {
|
||||||
|
"title": "test",
|
||||||
|
"version": "0"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/pet": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Add a new pet to the store",
|
||||||
|
"description": "Add new pet to the store inventory.",
|
||||||
|
"operationId": "updatePet",
|
||||||
|
"responses": {
|
||||||
|
"405": {
|
||||||
|
"description": "Invalid input"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"GitLab_PersonalAccessToken": [],
|
||||||
|
"GitLab_OpenIdConnect": [],
|
||||||
|
"basicAuth": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"petstore_auth": ["write:pets", "read:pets"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"securitySchemes": {
|
||||||
|
"petstore_auth": {
|
||||||
|
"description": "Get access to data while protecting your account credentials.\nOAuth2 is also a safer and more secure way to give you access.\n",
|
||||||
|
"type": "oauth2",
|
||||||
|
"bearerFormat": "",
|
||||||
|
"flows": {
|
||||||
|
"implicit": {
|
||||||
|
"authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog",
|
||||||
|
"scopes": {
|
||||||
|
"write:pets": "modify pets in your account",
|
||||||
|
"read:pets": "read your pets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GitLab_PersonalAccessToken": {
|
||||||
|
"description": "GitLab Personal Access Token description",
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "PRIVATE-TOKEN",
|
||||||
|
"in": "header",
|
||||||
|
"bearerFormat": "",
|
||||||
|
"flows": {}
|
||||||
|
},
|
||||||
|
"GitLab_OpenIdConnect": {
|
||||||
|
"description": "GitLab OpenIdConnect description",
|
||||||
|
"bearerFormat": "",
|
||||||
|
"type": "openIdConnect",
|
||||||
|
"openIdConnectUrl": "https://gitlab.com/.well-known/openid-configuration"
|
||||||
|
},
|
||||||
|
"basicAuth": {
|
||||||
|
"type": "http",
|
||||||
|
"scheme": "basic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,11 +12,7 @@ import { SearchStore } from './SearchStore';
|
||||||
|
|
||||||
import { SchemaDefinition } from '../components/SchemaDefinition/SchemaDefinition';
|
import { SchemaDefinition } from '../components/SchemaDefinition/SchemaDefinition';
|
||||||
import { SecurityDefs } from '../components/SecuritySchemes/SecuritySchemes';
|
import { SecurityDefs } from '../components/SecuritySchemes/SecuritySchemes';
|
||||||
import {
|
import { SCHEMA_DEFINITION_JSX_NAME, SECURITY_DEFINITIONS_JSX_NAME } from '../utils/openapi';
|
||||||
SCHEMA_DEFINITION_JSX_NAME,
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
SECURITY_DEFINITIONS_JSX_NAME,
|
|
||||||
} from '../utils/openapi';
|
|
||||||
|
|
||||||
import { IS_BROWSER } from '../utils';
|
import { IS_BROWSER } from '../utils';
|
||||||
|
|
||||||
|
@ -158,12 +154,6 @@ export class AppStore {
|
||||||
|
|
||||||
const DEFAULT_OPTIONS: RedocRawOptions = {
|
const DEFAULT_OPTIONS: RedocRawOptions = {
|
||||||
allowedMdComponents: {
|
allowedMdComponents: {
|
||||||
[SECURITY_DEFINITIONS_COMPONENT_NAME]: {
|
|
||||||
component: SecurityDefs,
|
|
||||||
propsSelector: (store: AppStore) => ({
|
|
||||||
securitySchemes: store.spec.securitySchemes,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
[SECURITY_DEFINITIONS_JSX_NAME]: {
|
[SECURITY_DEFINITIONS_JSX_NAME]: {
|
||||||
component: SecurityDefs,
|
component: SecurityDefs,
|
||||||
propsSelector: (store: AppStore) => ({
|
propsSelector: (store: AppStore) => ({
|
||||||
|
|
|
@ -7,13 +7,7 @@ import {
|
||||||
OpenAPIServer,
|
OpenAPIServer,
|
||||||
OpenAPIPaths,
|
OpenAPIPaths,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import { isOperationName, JsonPointer, alphabeticallyByProp } from '../utils';
|
||||||
isOperationName,
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
setSecuritySchemePrefix,
|
|
||||||
JsonPointer,
|
|
||||||
alphabeticallyByProp,
|
|
||||||
} from '../utils';
|
|
||||||
import { MarkdownRenderer } from './MarkdownRenderer';
|
import { MarkdownRenderer } from './MarkdownRenderer';
|
||||||
import { GroupModel, OperationModel } from './models';
|
import { GroupModel, OperationModel } from './models';
|
||||||
import { OpenAPIParser } from './OpenAPIParser';
|
import { OpenAPIParser } from './OpenAPIParser';
|
||||||
|
@ -110,14 +104,7 @@ export class MenuBuilder {
|
||||||
if (heading.items) {
|
if (heading.items) {
|
||||||
group.items = mapHeadingsDeep(group, heading.items, depth + 1);
|
group.items = mapHeadingsDeep(group, heading.items, depth + 1);
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
MarkdownRenderer.containsComponent(
|
|
||||||
group.description || '',
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
setSecuritySchemePrefix(group.id + '/');
|
|
||||||
}
|
|
||||||
return group;
|
return group;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ export class MenuStore {
|
||||||
let item: IMenuItem | undefined;
|
let item: IMenuItem | undefined;
|
||||||
|
|
||||||
item = this.flatItems.find(i => i.id === id);
|
item = this.flatItems.find(i => i.id === id);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
this.activateAndScroll(item, false);
|
this.activateAndScroll(item, false);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
|
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
|
||||||
|
|
||||||
import { appendToMdHeading, isArray, IS_BROWSER } from '../utils/';
|
import { isArray, isBoolean, IS_BROWSER } from '../utils/';
|
||||||
import { JsonPointer } from '../utils/JsonPointer';
|
import { JsonPointer } from '../utils/JsonPointer';
|
||||||
import {
|
import { getDefinitionName, isNamedDefinition } from '../utils/openapi';
|
||||||
getDefinitionName,
|
|
||||||
isNamedDefinition,
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
SECURITY_DEFINITIONS_JSX_NAME,
|
|
||||||
} from '../utils/openapi';
|
|
||||||
import { buildComponentComment, MarkdownRenderer } from './MarkdownRenderer';
|
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
|
|
||||||
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
||||||
|
@ -53,7 +47,6 @@ export class OpenAPIParser {
|
||||||
private options: RedocNormalizedOptions = new RedocNormalizedOptions({}),
|
private options: RedocNormalizedOptions = new RedocNormalizedOptions({}),
|
||||||
) {
|
) {
|
||||||
this.validate(spec);
|
this.validate(spec);
|
||||||
this.preprocess(spec);
|
|
||||||
|
|
||||||
this.spec = spec;
|
this.spec = spec;
|
||||||
this.allowMergeRefs = spec.openapi.startsWith('3.1');
|
this.allowMergeRefs = spec.openapi.startsWith('3.1');
|
||||||
|
@ -70,25 +63,6 @@ export class OpenAPIParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preprocess(spec: OpenAPISpec) {
|
|
||||||
if (
|
|
||||||
!this.options.noAutoAuth &&
|
|
||||||
spec.info &&
|
|
||||||
spec.components &&
|
|
||||||
spec.components.securitySchemes
|
|
||||||
) {
|
|
||||||
// Automatically inject Authentication section with SecurityDefinitions component
|
|
||||||
const description = spec.info.description || '';
|
|
||||||
if (
|
|
||||||
!MarkdownRenderer.containsComponent(description, SECURITY_DEFINITIONS_COMPONENT_NAME) &&
|
|
||||||
!MarkdownRenderer.containsComponent(description, SECURITY_DEFINITIONS_JSX_NAME)
|
|
||||||
) {
|
|
||||||
const comment = buildComponentComment(SECURITY_DEFINITIONS_COMPONENT_NAME);
|
|
||||||
spec.info.description = appendToMdHeading(description, 'Authentication', comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get spec part by JsonPointer ($ref)
|
* get spec part by JsonPointer ($ref)
|
||||||
*/
|
*/
|
||||||
|
@ -268,29 +242,47 @@ export class OpenAPIParser {
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
for (const { $ref: subSchemaRef, schema: subSchema } of allOfSchemas) {
|
for (const { $ref: subSchemaRef, schema: subSchema } of allOfSchemas) {
|
||||||
if (
|
const {
|
||||||
receiver.type !== subSchema.type &&
|
type,
|
||||||
receiver.type !== undefined &&
|
enum: enumProperty,
|
||||||
subSchema.type !== undefined
|
properties,
|
||||||
) {
|
items,
|
||||||
console.warn(
|
required,
|
||||||
`Incompatible types in allOf at "${$ref}": "${receiver.type}" and "${subSchema.type}"`,
|
oneOf,
|
||||||
);
|
anyOf,
|
||||||
|
title,
|
||||||
|
...otherConstraints
|
||||||
|
} = subSchema;
|
||||||
|
|
||||||
|
if (receiver.type !== type && receiver.type !== undefined && type !== undefined) {
|
||||||
|
console.warn(`Incompatible types in allOf at "${$ref}": "${receiver.type}" and "${type}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subSchema.type !== undefined) {
|
if (type !== undefined) {
|
||||||
receiver.type = subSchema.type;
|
if (Array.isArray(type) && Array.isArray(receiver.type)) {
|
||||||
|
receiver.type = [...type, ...receiver.type];
|
||||||
|
} else {
|
||||||
|
receiver.type = type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subSchema.properties !== undefined) {
|
if (enumProperty !== undefined) {
|
||||||
|
if (Array.isArray(enumProperty) && Array.isArray(receiver.enum)) {
|
||||||
|
receiver.enum = [...enumProperty, ...receiver.enum];
|
||||||
|
} else {
|
||||||
|
receiver.enum = enumProperty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties !== undefined) {
|
||||||
receiver.properties = receiver.properties || {};
|
receiver.properties = receiver.properties || {};
|
||||||
for (const prop in subSchema.properties) {
|
for (const prop in properties) {
|
||||||
if (!receiver.properties[prop]) {
|
if (!receiver.properties[prop]) {
|
||||||
receiver.properties[prop] = subSchema.properties[prop];
|
receiver.properties[prop] = properties[prop];
|
||||||
} else {
|
} else {
|
||||||
// merge inner properties
|
// merge inner properties
|
||||||
const mergedProp = this.mergeAllOf(
|
const mergedProp = this.mergeAllOf(
|
||||||
{ allOf: [receiver.properties[prop], subSchema.properties[prop]] },
|
{ allOf: [receiver.properties[prop], properties[prop]] },
|
||||||
$ref + '/properties/' + prop,
|
$ref + '/properties/' + prop,
|
||||||
);
|
);
|
||||||
receiver.properties[prop] = mergedProp;
|
receiver.properties[prop] = mergedProp;
|
||||||
|
@ -299,22 +291,37 @@ export class OpenAPIParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subSchema.items !== undefined) {
|
if (items !== undefined) {
|
||||||
receiver.items = receiver.items || {};
|
const receiverItems = isBoolean(receiver.items)
|
||||||
|
? { items: receiver.items }
|
||||||
|
: receiver.items
|
||||||
|
? (Object.assign({}, receiver.items) as OpenAPISchema)
|
||||||
|
: {};
|
||||||
|
const subSchemaItems = isBoolean(items)
|
||||||
|
? { items }
|
||||||
|
: (Object.assign({}, items) as OpenAPISchema);
|
||||||
// merge inner properties
|
// merge inner properties
|
||||||
receiver.items = this.mergeAllOf(
|
receiver.items = this.mergeAllOf(
|
||||||
{ allOf: [receiver.items, subSchema.items] },
|
{ allOf: [receiverItems, subSchemaItems] },
|
||||||
$ref + '/items',
|
$ref + '/items',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subSchema.required !== undefined) {
|
if (required !== undefined) {
|
||||||
receiver.required = (receiver.required || []).concat(subSchema.required);
|
receiver.required = (receiver.required || []).concat(required);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oneOf !== undefined) {
|
||||||
|
receiver.oneOf = oneOf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyOf !== undefined) {
|
||||||
|
receiver.anyOf = anyOf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge rest of constraints
|
// merge rest of constraints
|
||||||
// TODO: do more intelligent merge
|
// TODO: do more intelligent merge
|
||||||
receiver = { ...subSchema, ...receiver };
|
receiver = { ...receiver, title: receiver.title || title, ...otherConstraints };
|
||||||
|
|
||||||
if (subSchemaRef) {
|
if (subSchemaRef) {
|
||||||
receiver.parentRefs!.push(subSchemaRef);
|
receiver.parentRefs!.push(subSchemaRef);
|
||||||
|
|
|
@ -21,7 +21,6 @@ export interface RedocRawOptions {
|
||||||
sortEnumValuesAlphabetically?: boolean | string;
|
sortEnumValuesAlphabetically?: boolean | string;
|
||||||
sortOperationsAlphabetically?: boolean | string;
|
sortOperationsAlphabetically?: boolean | string;
|
||||||
sortTagsAlphabetically?: boolean | string;
|
sortTagsAlphabetically?: boolean | string;
|
||||||
noAutoAuth?: boolean | string;
|
|
||||||
nativeScrollbars?: boolean | string;
|
nativeScrollbars?: boolean | string;
|
||||||
pathInMiddlePanel?: boolean | string;
|
pathInMiddlePanel?: boolean | string;
|
||||||
untrustedSpec?: boolean | string;
|
untrustedSpec?: boolean | string;
|
||||||
|
@ -42,6 +41,8 @@ export interface RedocRawOptions {
|
||||||
expandSingleSchemaField?: boolean | string;
|
expandSingleSchemaField?: boolean | string;
|
||||||
schemaExpansionLevel?: number | string | 'all';
|
schemaExpansionLevel?: number | string | 'all';
|
||||||
showObjectSchemaExamples?: boolean | string;
|
showObjectSchemaExamples?: boolean | string;
|
||||||
|
showSecuritySchemeType?: boolean;
|
||||||
|
hideSecuritySection?: boolean;
|
||||||
sectionsAtTheEnd?: string | string[];
|
sectionsAtTheEnd?: string | string[];
|
||||||
|
|
||||||
unstable_ignoreMimeParameters?: boolean;
|
unstable_ignoreMimeParameters?: boolean;
|
||||||
|
@ -233,7 +234,6 @@ export class RedocNormalizedOptions {
|
||||||
sortEnumValuesAlphabetically: boolean;
|
sortEnumValuesAlphabetically: boolean;
|
||||||
sortOperationsAlphabetically: boolean;
|
sortOperationsAlphabetically: boolean;
|
||||||
sortTagsAlphabetically: boolean;
|
sortTagsAlphabetically: boolean;
|
||||||
noAutoAuth: boolean;
|
|
||||||
nativeScrollbars: boolean;
|
nativeScrollbars: boolean;
|
||||||
pathInMiddlePanel: boolean;
|
pathInMiddlePanel: boolean;
|
||||||
untrustedSpec: boolean;
|
untrustedSpec: boolean;
|
||||||
|
@ -254,6 +254,8 @@ export class RedocNormalizedOptions {
|
||||||
expandSingleSchemaField: boolean;
|
expandSingleSchemaField: boolean;
|
||||||
schemaExpansionLevel: number;
|
schemaExpansionLevel: number;
|
||||||
showObjectSchemaExamples: boolean;
|
showObjectSchemaExamples: boolean;
|
||||||
|
showSecuritySchemeType?: boolean;
|
||||||
|
hideSecuritySection?: boolean;
|
||||||
sectionsAtTheEnd: string[];
|
sectionsAtTheEnd: string[];
|
||||||
|
|
||||||
/* tslint:disable-next-line */
|
/* tslint:disable-next-line */
|
||||||
|
@ -304,7 +306,6 @@ export class RedocNormalizedOptions {
|
||||||
this.sortEnumValuesAlphabetically = argValueToBoolean(raw.sortEnumValuesAlphabetically);
|
this.sortEnumValuesAlphabetically = argValueToBoolean(raw.sortEnumValuesAlphabetically);
|
||||||
this.sortOperationsAlphabetically = argValueToBoolean(raw.sortOperationsAlphabetically);
|
this.sortOperationsAlphabetically = argValueToBoolean(raw.sortOperationsAlphabetically);
|
||||||
this.sortTagsAlphabetically = argValueToBoolean(raw.sortTagsAlphabetically);
|
this.sortTagsAlphabetically = argValueToBoolean(raw.sortTagsAlphabetically);
|
||||||
this.noAutoAuth = argValueToBoolean(raw.noAutoAuth);
|
|
||||||
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
|
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
|
||||||
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
|
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
|
||||||
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
|
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
|
||||||
|
@ -327,6 +328,8 @@ export class RedocNormalizedOptions {
|
||||||
this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField);
|
this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField);
|
||||||
this.schemaExpansionLevel = argValueToExpandLevel(raw.schemaExpansionLevel);
|
this.schemaExpansionLevel = argValueToExpandLevel(raw.schemaExpansionLevel);
|
||||||
this.showObjectSchemaExamples = argValueToBoolean(raw.showObjectSchemaExamples);
|
this.showObjectSchemaExamples = argValueToBoolean(raw.showObjectSchemaExamples);
|
||||||
|
this.showSecuritySchemeType = argValueToBoolean(raw.showSecuritySchemeType);
|
||||||
|
this.hideSecuritySection = argValueToBoolean(raw.hideSecuritySection);
|
||||||
this.sectionsAtTheEnd = RedocNormalizedOptions.normalizeSectionsAtTheEnd(raw.sectionsAtTheEnd);
|
this.sectionsAtTheEnd = RedocNormalizedOptions.normalizeSectionsAtTheEnd(raw.sectionsAtTheEnd);
|
||||||
|
|
||||||
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
|
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
|
||||||
|
|
|
@ -9,14 +9,50 @@ describe('Models', () => {
|
||||||
let parser;
|
let parser;
|
||||||
|
|
||||||
test('should hoist oneOfs when mergin allOf', () => {
|
test('should hoist oneOfs when mergin allOf', () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const spec = require('./fixtures/oneOfHoist.json');
|
const spec = require('./fixtures/oneOfHoist.json');
|
||||||
parser = new OpenAPIParser(spec, undefined, opts);
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
expect(parser.mergeAllOf(spec.components.schemas.test)).toMatchSnapshot();
|
expect(parser.mergeAllOf(spec.components.schemas.test)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should get schema name from named schema', () => {
|
||||||
|
const spec = require('./fixtures/mergeAllOf.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = parser.mergeAllOf(spec.components.schemas.Case1, '#/components/schemas/Case1');
|
||||||
|
expect(schema.title).toEqual('Case1');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get schema name from first allOf', () => {
|
||||||
|
const spec = require('./fixtures/mergeAllOf.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = parser.mergeAllOf(
|
||||||
|
spec.components.schemas.Case2.properties.a,
|
||||||
|
'#components/schemas/Case2/properties/a',
|
||||||
|
);
|
||||||
|
expect(schema.title).toEqual('Bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get schema name from named schema', () => {
|
||||||
|
const spec = require('./fixtures/mergeAllOf.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = parser.mergeAllOf(
|
||||||
|
spec.components.schemas.Case3.schemas.Foo,
|
||||||
|
'#components/schemas/Case3/schemas/Foo',
|
||||||
|
);
|
||||||
|
expect(schema.title).toEqual('Foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should merge oneOff to inside allOff', () => {
|
||||||
|
// TODO: should hoist
|
||||||
|
const spec = require('./fixtures/mergeAllOf.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = parser.mergeAllOf(spec.components.schemas.Case4);
|
||||||
|
expect(schema.title).toEqual('Foo');
|
||||||
|
expect(schema.parentRefs).toHaveLength(1);
|
||||||
|
expect(schema.parentRefs[0]).toEqual('#/components/schemas/Ref');
|
||||||
|
expect(schema.oneOf).toEqual([{ title: 'Bar' }, { title: 'Baz' }]);
|
||||||
|
});
|
||||||
|
|
||||||
test('should override description from $ref of the referenced component, when sibling description exists ', () => {
|
test('should override description from $ref of the referenced component, when sibling description exists ', () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const spec = require('./fixtures/siblingRefDescription.json');
|
const spec = require('./fixtures/siblingRefDescription.json');
|
||||||
parser = new OpenAPIParser(spec, undefined, opts);
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
const schemaOrRef: Referenced<OpenAPIParameter> = {
|
const schemaOrRef: Referenced<OpenAPIParameter> = {
|
||||||
|
@ -28,7 +64,6 @@ describe('Models', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should correct resolve double $ref if no need sibling', () => {
|
test('should correct resolve double $ref if no need sibling', () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const spec = require('./fixtures/3.1/schemaDefinition.json');
|
const spec = require('./fixtures/3.1/schemaDefinition.json');
|
||||||
parser = new OpenAPIParser(spec, undefined, opts);
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
const schemaOrRef: Referenced<OpenAPIParameter> = {
|
const schemaOrRef: Referenced<OpenAPIParameter> = {
|
||||||
|
|
40
src/services/__tests__/fixtures/3.1/conditionalField.json
Normal file
40
src/services/__tests__/fixtures/3.1/conditionalField.json
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Schema definition field with conditional operators",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Test": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"test": {
|
||||||
|
"type": ["string", "integer", "null"],
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 20,
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "url"
|
||||||
|
},
|
||||||
|
"if": {
|
||||||
|
"x-displayName": "isString",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"type": "string",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 20
|
||||||
|
},
|
||||||
|
"else": {
|
||||||
|
"x-displayName": "notString",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"pattern": "\\d+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/services/__tests__/fixtures/3.1/conditionalSchema.json
Normal file
40
src/services/__tests__/fixtures/3.1/conditionalSchema.json
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Schema definition with conditional operators",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Test": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"test": {
|
||||||
|
"description": "The list of URL to a cute photos featuring pet",
|
||||||
|
"type": ["string", "integer", "null"],
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 20,
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "url"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"if": {
|
||||||
|
"title": "=== 10",
|
||||||
|
"properties": {
|
||||||
|
"test": {
|
||||||
|
"enum": [10]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"maxItems": 2
|
||||||
|
},
|
||||||
|
"else": {
|
||||||
|
"maxItems": 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
src/services/__tests__/fixtures/3.1/patternProperties.json
Normal file
32
src/services/__tests__/fixtures/3.1/patternProperties.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Schema definition with unevaluatedProperties",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Patterns": {
|
||||||
|
"type": "object",
|
||||||
|
"patternProperties": {
|
||||||
|
"^S_\\w+\\.[1-9]{2,4}$": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"^O_\\w+\\.[1-9]{2,4}$": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"x-nestedProperty": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
154
src/services/__tests__/fixtures/3.1/prefixItems.json
Normal file
154
src/services/__tests__/fixtures/3.1/prefixItems.json
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Schema definition with prefixItems",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Case1": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": false
|
||||||
|
},
|
||||||
|
"Case2": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": true
|
||||||
|
},
|
||||||
|
"Case3": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Dog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Case4": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"firstItem": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Case5": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Cat": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"color": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dog": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"size": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
154
src/services/__tests__/fixtures/arrayItems.json
Normal file
154
src/services/__tests__/fixtures/arrayItems.json
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Schema definition with array items",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Case1": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalItems": false
|
||||||
|
},
|
||||||
|
"Case2": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalItems": true
|
||||||
|
},
|
||||||
|
"Case3": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalItems": {
|
||||||
|
"$ref": "#/components/schemas/Dog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Case4": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalItems": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"firstItem": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Case5": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Cat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalItems": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Cat": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"color": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dog": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"size": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
src/services/__tests__/fixtures/mergeAllOf.json
Normal file
70
src/services/__tests__/fixtures/mergeAllOf.json
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"version": "1.0",
|
||||||
|
"title": "Foo"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Case1": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"title": "Bar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Baz"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Case2": {
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"title": "Bar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Baz"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Case3": {
|
||||||
|
"schemas": {
|
||||||
|
"Foo": {
|
||||||
|
"title": "Foo",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"title": "Bar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Baz"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Case4": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"title": "Foo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Ref"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Ref": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"title": "Bar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Baz"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,32 @@ describe('Models', () => {
|
||||||
expect(schema.pointer).toBe('#/components/schemas/Child');
|
expect(schema.pointer).toBe('#/components/schemas/Child');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('schemaDefinition should resolve schema with conditional operators', () => {
|
||||||
|
const spec = require('../fixtures/3.1/conditionalSchema.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Test, '', opts);
|
||||||
|
expect(schema.oneOf).toHaveLength(2);
|
||||||
|
|
||||||
|
expect(schema.oneOf![0].schema.title).toBe('=== 10');
|
||||||
|
expect(schema.oneOf![1].schema.title).toBe('case 2');
|
||||||
|
|
||||||
|
expect(schema.oneOf![0].schema).toMatchSnapshot();
|
||||||
|
expect(schema.oneOf![1].schema).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('schemaDefinition should resolve field with conditional operators', () => {
|
||||||
|
const spec = require('../fixtures/3.1/conditionalField.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Test, '', opts);
|
||||||
|
expect(schema.fields).toHaveLength(1);
|
||||||
|
expect(schema.fields && schema.fields[0].schema.oneOf).toHaveLength(2);
|
||||||
|
expect(schema.fields && schema.fields[0].schema.oneOf![0].schema.title).toBe('isString');
|
||||||
|
expect(schema.fields && schema.fields[0].schema.oneOf![1].schema.title).toBe('notString');
|
||||||
|
|
||||||
|
expect(schema.fields && schema.fields[0].schema.oneOf![0].schema).toMatchSnapshot();
|
||||||
|
expect(schema.fields && schema.fields[0].schema.oneOf![1].schema).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
test('schemaDefinition should resolve unevaluatedProperties in properties', () => {
|
test('schemaDefinition should resolve unevaluatedProperties in properties', () => {
|
||||||
const spec = require('../fixtures/3.1/unevaluatedProperties.json');
|
const spec = require('../fixtures/3.1/unevaluatedProperties.json');
|
||||||
parser = new OpenAPIParser(spec, undefined, opts);
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
@ -76,5 +102,116 @@ describe('Models', () => {
|
||||||
expect(schema.fields![1].kind).toEqual('additionalProperties');
|
expect(schema.fields![1].kind).toEqual('additionalProperties');
|
||||||
expect(schema.fields![1].schema.type).toEqual('boolean');
|
expect(schema.fields![1].schema.type).toEqual('boolean');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('schemaDefinition should resolve patternProperties', () => {
|
||||||
|
const spec = require('../fixtures/3.1/patternProperties.json');
|
||||||
|
parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Patterns, '', opts);
|
||||||
|
expect(schema.fields).toHaveLength(2);
|
||||||
|
expect(schema.fields![0].kind).toEqual('patternProperties');
|
||||||
|
expect(schema.fields![0].schema.type).toEqual('string');
|
||||||
|
expect(schema.fields![1].kind).toEqual('patternProperties');
|
||||||
|
expect(schema.fields![1].schema.type).toEqual('object');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('type array', () => {
|
||||||
|
function testImmutablePart(schema: SchemaModel) {
|
||||||
|
expect(schema.minItems).toEqual(1);
|
||||||
|
expect(schema.maxItems).toEqual(10);
|
||||||
|
expect(schema.fields![0].schema.type).toEqual('string');
|
||||||
|
expect(schema.fields![1].schema.type).toEqual('number');
|
||||||
|
}
|
||||||
|
const eachArray = ['../fixtures/3.1/prefixItems.json', '../fixtures/arrayItems.json'];
|
||||||
|
|
||||||
|
test.each(eachArray)(
|
||||||
|
'schemaDefinition should resolve prefixItems without additional items',
|
||||||
|
specFixture => {
|
||||||
|
const spec = require(specFixture);
|
||||||
|
const parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Case1, '', opts);
|
||||||
|
|
||||||
|
testImmutablePart(schema);
|
||||||
|
|
||||||
|
expect(schema.fields).toHaveLength(3);
|
||||||
|
expect(schema.fields![2].name).toEqual('[2]');
|
||||||
|
expect(schema.fields![2].schema.pointer).toEqual('#/components/schemas/Cat');
|
||||||
|
expect(schema.fields![2].schema.type).toEqual('object');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.each(eachArray)(
|
||||||
|
'schemaDefinition should resolve prefixItems with additional items',
|
||||||
|
specFixture => {
|
||||||
|
const spec = require(specFixture);
|
||||||
|
const parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Case2, '', opts);
|
||||||
|
|
||||||
|
testImmutablePart(schema);
|
||||||
|
|
||||||
|
expect(schema.fields).toHaveLength(4);
|
||||||
|
expect(schema.fields![3].name).toEqual('[3...]');
|
||||||
|
expect(schema.fields![2].schema.type).toEqual('object');
|
||||||
|
expect(schema.fields![2].schema.pointer).toEqual('#/components/schemas/Cat');
|
||||||
|
expect(schema.fields![3].schema.type).toEqual('any');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.each(eachArray)(
|
||||||
|
'schemaDefinition should resolve prefixItems with additional items with $ref',
|
||||||
|
specFixture => {
|
||||||
|
const spec = require(specFixture);
|
||||||
|
const parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Case3, '', opts);
|
||||||
|
|
||||||
|
testImmutablePart(schema);
|
||||||
|
|
||||||
|
expect(schema.fields).toHaveLength(4);
|
||||||
|
expect(schema.fields![3].name).toEqual('[3...]');
|
||||||
|
expect(schema.fields![2].schema.type).toEqual('object');
|
||||||
|
expect(schema.fields![2].schema.pointer).toEqual('#/components/schemas/Cat');
|
||||||
|
expect(schema.fields![3].schema.type).toEqual('object');
|
||||||
|
expect(schema.fields![3].schema.pointer).toEqual('#/components/schemas/Dog');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.each(eachArray)(
|
||||||
|
'schemaDefinition should resolve prefixItems with additional schema items',
|
||||||
|
specFixture => {
|
||||||
|
const spec = require(specFixture);
|
||||||
|
const parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Case4, '', opts);
|
||||||
|
|
||||||
|
testImmutablePart(schema);
|
||||||
|
|
||||||
|
expect(schema.fields).toHaveLength(4);
|
||||||
|
expect(schema.fields![3].name).toEqual('[3...]');
|
||||||
|
expect(schema.fields![2].schema.type).toEqual('object');
|
||||||
|
expect(schema.fields![2].schema.pointer).toEqual('#/components/schemas/Cat');
|
||||||
|
expect(schema.fields![3].schema.type).toEqual('object');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.each(eachArray)(
|
||||||
|
'schemaDefinition should resolve prefixItems with additional array items',
|
||||||
|
specFixture => {
|
||||||
|
const spec = require(specFixture);
|
||||||
|
const parser = new OpenAPIParser(spec, undefined, opts);
|
||||||
|
const schema = new SchemaModel(parser, spec.components.schemas.Case5, '', opts);
|
||||||
|
|
||||||
|
testImmutablePart(schema);
|
||||||
|
|
||||||
|
expect(schema.fields).toHaveLength(4);
|
||||||
|
expect(schema.fields![3].name).toEqual('[3...]');
|
||||||
|
expect(schema.fields![2].schema.type).toEqual('object');
|
||||||
|
expect(schema.fields![2].schema.pointer).toEqual('#/components/schemas/Cat');
|
||||||
|
expect(schema.fields![3].schema.type).toEqual('array');
|
||||||
|
expect(schema.fields![3].schema.fields).toHaveLength(1);
|
||||||
|
expect(schema.fields![3].schema.fields![0].schema.type).toEqual('string');
|
||||||
|
expect(schema.fields![3].schema.fields![0].schema.constraints).toEqual([
|
||||||
|
'>= 0 characters',
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
107
src/services/__tests__/models/__snapshots__/Schema.test.ts.snap
Normal file
107
src/services/__tests__/models/__snapshots__/Schema.test.ts.snap
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Models Schema schemaDefinition should resolve field with conditional operators 1`] = `
|
||||||
|
Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"default": undefined,
|
||||||
|
"items": Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"format": "url",
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"title": undefined,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"maxItems": 20,
|
||||||
|
"minItems": 1,
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"title": "isString",
|
||||||
|
"type": "string",
|
||||||
|
"x-displayName": "isString",
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Models Schema schemaDefinition should resolve field with conditional operators 2`] = `
|
||||||
|
Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"default": undefined,
|
||||||
|
"items": Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"format": "url",
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"title": undefined,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"maxItems": 10,
|
||||||
|
"minItems": 1,
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"pattern": "\\\\d+",
|
||||||
|
"title": "notString",
|
||||||
|
"type": Array [
|
||||||
|
"string",
|
||||||
|
"integer",
|
||||||
|
"null",
|
||||||
|
],
|
||||||
|
"x-displayName": "notString",
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Models Schema schemaDefinition should resolve schema with conditional operators 1`] = `
|
||||||
|
Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"maxItems": 2,
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"properties": Object {
|
||||||
|
"test": Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"description": "The list of URL to a cute photos featuring pet",
|
||||||
|
"enum": Array [
|
||||||
|
10,
|
||||||
|
],
|
||||||
|
"items": Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"format": "url",
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"title": undefined,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"maxItems": 20,
|
||||||
|
"minItems": 1,
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"title": undefined,
|
||||||
|
"type": Array [
|
||||||
|
"string",
|
||||||
|
"integer",
|
||||||
|
"null",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"title": "=== 10",
|
||||||
|
"type": "object",
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Models Schema schemaDefinition should resolve schema with conditional operators 2`] = `
|
||||||
|
Object {
|
||||||
|
"allOf": undefined,
|
||||||
|
"maxItems": 20,
|
||||||
|
"parentRefs": Array [],
|
||||||
|
"properties": Object {
|
||||||
|
"test": Object {
|
||||||
|
"description": "The list of URL to a cute photos featuring pet",
|
||||||
|
"items": Object {
|
||||||
|
"format": "url",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"maxItems": 20,
|
||||||
|
"minItems": 1,
|
||||||
|
"type": Array [
|
||||||
|
"string",
|
||||||
|
"integer",
|
||||||
|
"null",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"title": "case 2",
|
||||||
|
"type": "object",
|
||||||
|
}
|
||||||
|
`;
|
|
@ -12,7 +12,9 @@ import {
|
||||||
extractExtensions,
|
extractExtensions,
|
||||||
humanizeConstraints,
|
humanizeConstraints,
|
||||||
isArray,
|
isArray,
|
||||||
|
isBoolean,
|
||||||
isNamedDefinition,
|
isNamedDefinition,
|
||||||
|
isObject,
|
||||||
isPrimitiveType,
|
isPrimitiveType,
|
||||||
JsonPointer,
|
JsonPointer,
|
||||||
pluralizeType,
|
pluralizeType,
|
||||||
|
@ -152,6 +154,11 @@ export class SchemaModel {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((schema.if && schema.then) || (schema.if && schema.else)) {
|
||||||
|
this.initConditionalOperators(schema, parser);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isChild && getDiscriminator(schema) !== undefined) {
|
if (!isChild && getDiscriminator(schema) !== undefined) {
|
||||||
this.initDiscriminator(schema, parser);
|
this.initDiscriminator(schema, parser);
|
||||||
return;
|
return;
|
||||||
|
@ -183,17 +190,31 @@ export class SchemaModel {
|
||||||
|
|
||||||
if (this.hasType('object')) {
|
if (this.hasType('object')) {
|
||||||
this.fields = buildFields(parser, schema, this.pointer, this.options);
|
this.fields = buildFields(parser, schema, this.pointer, this.options);
|
||||||
} else if (this.hasType('array') && schema.items) {
|
} else if (this.hasType('array')) {
|
||||||
this.items = new SchemaModel(parser, schema.items, this.pointer + '/items', this.options);
|
if (isArray(schema.items) || isArray(schema.prefixItems)) {
|
||||||
this.displayType = pluralizeType(this.items.displayType);
|
this.fields = buildFields(parser, schema, this.pointer, this.options);
|
||||||
this.displayFormat = this.items.format;
|
} else if (isObject(schema.items)) {
|
||||||
this.typePrefix = this.items.typePrefix + l('arrayOf');
|
this.items = new SchemaModel(
|
||||||
this.title = this.title || this.items.title;
|
parser,
|
||||||
this.isPrimitive = this.items.isPrimitive;
|
schema.items as OpenAPISchema,
|
||||||
if (this.example === undefined && this.items.example !== undefined) {
|
this.pointer + '/items',
|
||||||
|
this.options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.displayType =
|
||||||
|
schema.prefixItems || isArray(schema.items)
|
||||||
|
? 'items'
|
||||||
|
: pluralizeType(this.items?.displayType || this.displayType);
|
||||||
|
this.displayFormat = this.items?.format || '';
|
||||||
|
this.typePrefix = this.items?.typePrefix || '' + l('arrayOf');
|
||||||
|
this.title = this.title || this.items?.title || '';
|
||||||
|
this.isPrimitive = this.items?.isPrimitive || this.isPrimitive;
|
||||||
|
|
||||||
|
if (this.example === undefined && this.items?.example !== undefined) {
|
||||||
this.example = [this.items.example];
|
this.example = [this.items.example];
|
||||||
}
|
}
|
||||||
if (this.items.isPrimitive) {
|
if (this.items?.isPrimitive) {
|
||||||
this.enum = this.items.enum;
|
this.enum = this.items.enum;
|
||||||
}
|
}
|
||||||
if (isArray(this.type)) {
|
if (isArray(this.type)) {
|
||||||
|
@ -355,6 +376,38 @@ export class SchemaModel {
|
||||||
return innerSchema;
|
return innerSchema;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initConditionalOperators(schema: OpenAPISchema, parser: OpenAPIParser) {
|
||||||
|
const {
|
||||||
|
if: ifOperator,
|
||||||
|
else: elseOperator = {},
|
||||||
|
then: thenOperator = {},
|
||||||
|
...restSchema
|
||||||
|
} = schema;
|
||||||
|
const groupedOperators = [
|
||||||
|
{
|
||||||
|
allOf: [restSchema, thenOperator, ifOperator],
|
||||||
|
title: (ifOperator && ifOperator['x-displayName']) || ifOperator?.title || 'case 1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
allOf: [restSchema, elseOperator],
|
||||||
|
title: (elseOperator && elseOperator['x-displayName']) || elseOperator?.title || 'case 2',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
this.oneOf = groupedOperators.map(
|
||||||
|
(variant, idx) =>
|
||||||
|
new SchemaModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
...variant,
|
||||||
|
} as OpenAPISchema,
|
||||||
|
this.pointer + '/oneOf/' + idx,
|
||||||
|
this.options,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
this.oneOfType = 'One of';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildFields(
|
function buildFields(
|
||||||
|
@ -363,8 +416,10 @@ function buildFields(
|
||||||
$ref: string,
|
$ref: string,
|
||||||
options: RedocNormalizedOptions,
|
options: RedocNormalizedOptions,
|
||||||
): FieldModel[] {
|
): FieldModel[] {
|
||||||
const props = schema.properties || {};
|
const props = schema.properties || schema.prefixItems || schema.items || {};
|
||||||
|
const patternProps = schema.patternProperties || {};
|
||||||
const additionalProps = schema.additionalProperties || schema.unevaluatedProperties;
|
const additionalProps = schema.additionalProperties || schema.unevaluatedProperties;
|
||||||
|
const itemsProps = schema.prefixItems ? schema.items : schema.additionalItems;
|
||||||
const defaults = schema.default;
|
const defaults = schema.default;
|
||||||
let fields = Object.keys(props || []).map(fieldName => {
|
let fields = Object.keys(props || []).map(fieldName => {
|
||||||
let field = props[fieldName];
|
let field = props[fieldName];
|
||||||
|
@ -382,7 +437,7 @@ function buildFields(
|
||||||
return new FieldModel(
|
return new FieldModel(
|
||||||
parser,
|
parser,
|
||||||
{
|
{
|
||||||
name: fieldName,
|
name: schema.properties ? fieldName : `[${fieldName}]`,
|
||||||
required,
|
required,
|
||||||
schema: {
|
schema: {
|
||||||
...field,
|
...field,
|
||||||
|
@ -402,6 +457,31 @@ function buildFields(
|
||||||
fields = sortByRequired(fields, !options.sortPropsAlphabetically ? schema.required : undefined);
|
fields = sortByRequired(fields, !options.sortPropsAlphabetically ? schema.required : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fields.push(
|
||||||
|
...Object.keys(patternProps).map(fieldName => {
|
||||||
|
let field = patternProps[fieldName];
|
||||||
|
|
||||||
|
if (!field) {
|
||||||
|
console.warn(
|
||||||
|
`Field "${fieldName}" is invalid, skipping.\n Field must be an object but got ${typeof field} at "${$ref}"`,
|
||||||
|
);
|
||||||
|
field = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FieldModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
name: fieldName,
|
||||||
|
required: false,
|
||||||
|
schema: field,
|
||||||
|
kind: 'patternProperties',
|
||||||
|
},
|
||||||
|
`${$ref}/patternProperties/${fieldName}`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
if (typeof additionalProps === 'object' || additionalProps === true) {
|
if (typeof additionalProps === 'object' || additionalProps === true) {
|
||||||
fields.push(
|
fields.push(
|
||||||
new FieldModel(
|
new FieldModel(
|
||||||
|
@ -421,9 +501,82 @@ function buildFields(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fields.push(
|
||||||
|
...buildAdditionalItems({
|
||||||
|
parser,
|
||||||
|
schema: itemsProps,
|
||||||
|
fieldsCount: fields.length,
|
||||||
|
$ref,
|
||||||
|
options,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildAdditionalItems({
|
||||||
|
parser,
|
||||||
|
schema = false,
|
||||||
|
fieldsCount,
|
||||||
|
$ref,
|
||||||
|
options,
|
||||||
|
}: {
|
||||||
|
parser: OpenAPIParser;
|
||||||
|
schema?: OpenAPISchema | OpenAPISchema[] | boolean;
|
||||||
|
fieldsCount: number;
|
||||||
|
$ref: string;
|
||||||
|
options: RedocNormalizedOptions;
|
||||||
|
}) {
|
||||||
|
if (isBoolean(schema)) {
|
||||||
|
return schema
|
||||||
|
? [
|
||||||
|
new FieldModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
name: `[${fieldsCount}...]`,
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
`${$ref}/additionalItems`,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArray(schema)) {
|
||||||
|
return [
|
||||||
|
...schema.map(
|
||||||
|
(field, idx) =>
|
||||||
|
new FieldModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
name: `[${fieldsCount + idx}]`,
|
||||||
|
schema: field,
|
||||||
|
},
|
||||||
|
`${$ref}/additionalItems`,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isObject(schema)) {
|
||||||
|
return [
|
||||||
|
new FieldModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
name: `[${fieldsCount}...]`,
|
||||||
|
schema: schema,
|
||||||
|
},
|
||||||
|
`${$ref}/additionalItems`,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
function getDiscriminator(schema: OpenAPISchema): OpenAPISchema['discriminator'] {
|
function getDiscriminator(schema: OpenAPISchema): OpenAPISchema['discriminator'] {
|
||||||
return schema.discriminator || schema['x-discriminator'];
|
return schema.discriminator || schema['x-discriminator'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { OpenAPISecurityRequirement, OpenAPISecurityScheme } from '../../types';
|
import { OpenAPISecurityRequirement, OpenAPISecurityScheme } from '../../types';
|
||||||
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export interface SecurityScheme extends OpenAPISecurityScheme {
|
export interface SecurityScheme extends OpenAPISecurityScheme {
|
||||||
|
@ -29,7 +28,7 @@ export class SecurityRequirementModel {
|
||||||
return {
|
return {
|
||||||
...scheme,
|
...scheme,
|
||||||
id,
|
id,
|
||||||
sectionId: SECURITY_SCHEMES_SECTION_PREFIX + id,
|
sectionId: id,
|
||||||
displayName,
|
displayName,
|
||||||
scopes,
|
scopes,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { OpenAPISecurityScheme, Referenced } from '../../types';
|
import { OpenAPISecurityScheme, Referenced } from '../../types';
|
||||||
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi';
|
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export class SecuritySchemeModel {
|
export class SecuritySchemeModel {
|
||||||
|
|
|
@ -128,6 +128,8 @@ const defaultTheme: ThemeInterface = {
|
||||||
color: ({ colors }) => colors.primary.main,
|
color: ({ colors }) => colors.primary.main,
|
||||||
visited: ({ typography }) => typography.links.color,
|
visited: ({ typography }) => typography.links.color,
|
||||||
hover: ({ typography }) => lighten(0.2, typography.links.color),
|
hover: ({ typography }) => lighten(0.2, typography.links.color),
|
||||||
|
textDecoration: 'auto',
|
||||||
|
hoverTextDecoration: 'auto',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sidebar: {
|
sidebar: {
|
||||||
|
@ -315,6 +317,8 @@ export interface ResolvedThemeInterface {
|
||||||
color: string;
|
color: string;
|
||||||
visited: string;
|
visited: string;
|
||||||
hover: string;
|
hover: string;
|
||||||
|
textDecoration: string;
|
||||||
|
hoverTextDecoration: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
sidebar: {
|
sidebar: {
|
||||||
|
|
|
@ -113,11 +113,12 @@ export interface OpenAPISchema {
|
||||||
$ref?: string;
|
$ref?: string;
|
||||||
type?: string | string[];
|
type?: string | string[];
|
||||||
properties?: { [name: string]: OpenAPISchema };
|
properties?: { [name: string]: OpenAPISchema };
|
||||||
|
patternProperties?: { [name: string]: OpenAPISchema };
|
||||||
additionalProperties?: boolean | OpenAPISchema;
|
additionalProperties?: boolean | OpenAPISchema;
|
||||||
unevaluatedProperties?: boolean | OpenAPISchema;
|
unevaluatedProperties?: boolean | OpenAPISchema;
|
||||||
description?: string;
|
description?: string;
|
||||||
default?: any;
|
default?: any;
|
||||||
items?: OpenAPISchema;
|
items?: OpenAPISchema | OpenAPISchema[] | boolean;
|
||||||
required?: string[];
|
required?: string[];
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
writeOnly?: boolean;
|
writeOnly?: boolean;
|
||||||
|
@ -147,10 +148,16 @@ export interface OpenAPISchema {
|
||||||
minProperties?: number;
|
minProperties?: number;
|
||||||
enum?: any[];
|
enum?: any[];
|
||||||
example?: any;
|
example?: any;
|
||||||
|
|
||||||
|
if?: OpenAPISchema;
|
||||||
|
else?: OpenAPISchema;
|
||||||
|
then?: OpenAPISchema;
|
||||||
examples?: any[];
|
examples?: any[];
|
||||||
const?: string;
|
const?: string;
|
||||||
contentEncoding?: string;
|
contentEncoding?: string;
|
||||||
contentMediaType?: string;
|
contentMediaType?: string;
|
||||||
|
prefixItems?: OpenAPISchema[];
|
||||||
|
additionalItems?: OpenAPISchema | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenAPIDiscriminator {
|
export interface OpenAPIDiscriminator {
|
||||||
|
|
|
@ -352,6 +352,37 @@ Object {
|
||||||
},
|
},
|
||||||
"User": Object {
|
"User": Object {
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
|
"addresses": Object {
|
||||||
|
"additionalItems": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"items": Array [
|
||||||
|
Object {
|
||||||
|
"properties": Object {
|
||||||
|
"city": Object {
|
||||||
|
"minLength": 0,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"country": Object {
|
||||||
|
"minLength": 0,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"street": Object {
|
||||||
|
"description": "includes build/apartment number",
|
||||||
|
"minLength": 0,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"type": "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"maxLength": 10,
|
||||||
|
"minItems": 0,
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
"email": Object {
|
"email": Object {
|
||||||
"description": "User email address",
|
"description": "User email address",
|
||||||
"example": "john.smith@example.com",
|
"example": "john.smith@example.com",
|
||||||
|
@ -966,6 +997,7 @@ try {
|
||||||
"format": "int32",
|
"format": "int32",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
},
|
},
|
||||||
|
"minProperties": 2,
|
||||||
"type": "object",
|
"type": "object",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1903,6 +1935,46 @@ Object {
|
||||||
},
|
},
|
||||||
"schemas": Object {
|
"schemas": Object {
|
||||||
"ApiResponse": Object {
|
"ApiResponse": Object {
|
||||||
|
"patternProperties": Object {
|
||||||
|
"^O_\\\\\\\\w+\\\\\\\\.[1-9]{2,4}$": Object {
|
||||||
|
"properties": Object {
|
||||||
|
"nestedProperty": Object {
|
||||||
|
"default": "lazy",
|
||||||
|
"description": "The measured skill for hunting",
|
||||||
|
"enum": Array [
|
||||||
|
"clueless",
|
||||||
|
"lazy",
|
||||||
|
"adventurous",
|
||||||
|
"aggressive",
|
||||||
|
],
|
||||||
|
"example": "adventurous",
|
||||||
|
"type": Array [
|
||||||
|
"string",
|
||||||
|
"boolean",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
|
"^S_\\\\\\\\w+\\\\\\\\.[1-9]{2,4}$": Object {
|
||||||
|
"description": "The measured skill for hunting",
|
||||||
|
"else": Object {
|
||||||
|
"maxLength": 10,
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"if": Object {
|
||||||
|
"x-displayName": "fieldName === 'status'",
|
||||||
|
},
|
||||||
|
"then": Object {
|
||||||
|
"enum": Array [
|
||||||
|
"success",
|
||||||
|
"failed",
|
||||||
|
],
|
||||||
|
"format": "url",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"format": "int32",
|
"format": "int32",
|
||||||
|
@ -1934,7 +2006,10 @@ Object {
|
||||||
"aggressive",
|
"aggressive",
|
||||||
],
|
],
|
||||||
"example": "adventurous",
|
"example": "adventurous",
|
||||||
"type": "string",
|
"type": Array [
|
||||||
|
"string",
|
||||||
|
"boolean",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"required": Array [
|
"required": Array [
|
||||||
|
@ -2086,6 +2161,16 @@ Object {
|
||||||
"friend": Object {
|
"friend": Object {
|
||||||
"$ref": "#/components/schemas/Pet",
|
"$ref": "#/components/schemas/Pet",
|
||||||
},
|
},
|
||||||
|
"huntingSkill": Object {
|
||||||
|
"enum": Array [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
"type": Array [
|
||||||
|
"integer",
|
||||||
|
],
|
||||||
|
},
|
||||||
"id": Object {
|
"id": Object {
|
||||||
"$ref": "#/components/schemas/Id",
|
"$ref": "#/components/schemas/Id",
|
||||||
"description": "Pet ID",
|
"description": "Pet ID",
|
||||||
|
@ -2105,17 +2190,33 @@ Object {
|
||||||
},
|
},
|
||||||
"photoUrls": Object {
|
"photoUrls": Object {
|
||||||
"description": "The list of URL to a cute photos featuring pet",
|
"description": "The list of URL to a cute photos featuring pet",
|
||||||
|
"else": Object {
|
||||||
|
"maxItems": 20,
|
||||||
|
"minItems": 1,
|
||||||
|
"type": Array [
|
||||||
|
"integer",
|
||||||
|
"null",
|
||||||
|
],
|
||||||
|
"x-displayName": "notString",
|
||||||
|
},
|
||||||
|
"if": Object {
|
||||||
|
"type": "string",
|
||||||
|
"x-displayName": "isString",
|
||||||
|
},
|
||||||
"items": Object {
|
"items": Object {
|
||||||
"format": "url",
|
"format": "url",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
},
|
},
|
||||||
"maxItems": 20,
|
"maxItems": 10,
|
||||||
"minItems": 1,
|
"minItems": 1,
|
||||||
|
"then": Object {
|
||||||
|
"maxItems": 15,
|
||||||
|
"minItems": 1,
|
||||||
|
},
|
||||||
"type": Array [
|
"type": Array [
|
||||||
"string",
|
"string",
|
||||||
"integer",
|
"integer",
|
||||||
"null",
|
"null",
|
||||||
"array",
|
|
||||||
],
|
],
|
||||||
"xml": Object {
|
"xml": Object {
|
||||||
"name": "photoUrl",
|
"name": "photoUrl",
|
||||||
|
@ -2173,7 +2274,51 @@ Object {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"User": Object {
|
"User": Object {
|
||||||
|
"else": Object {
|
||||||
|
"required": Array [],
|
||||||
|
},
|
||||||
|
"if": Object {
|
||||||
|
"properties": Object {
|
||||||
|
"userStatus": Object {
|
||||||
|
"enum": Array [
|
||||||
|
10,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"title": "userStatus === 10",
|
||||||
|
},
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
|
"addresses": Object {
|
||||||
|
"items": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"maxLength": 10,
|
||||||
|
"minItems": 0,
|
||||||
|
"prefixItems": Array [
|
||||||
|
Object {
|
||||||
|
"properties": Object {
|
||||||
|
"city": Object {
|
||||||
|
"minLength": 0,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"country": Object {
|
||||||
|
"minLength": 0,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"street": Object {
|
||||||
|
"description": "includes build/apartment number",
|
||||||
|
"minLength": 0,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"type": "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
"email": Object {
|
"email": Object {
|
||||||
"description": "User email address",
|
"description": "User email address",
|
||||||
"example": "john.smith@example.com",
|
"example": "john.smith@example.com",
|
||||||
|
@ -2238,6 +2383,11 @@ Object {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"then": Object {
|
||||||
|
"required": Array [
|
||||||
|
"phone",
|
||||||
|
],
|
||||||
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"xml": Object {
|
"xml": Object {
|
||||||
"name": "User",
|
"name": "User",
|
||||||
|
|
|
@ -277,7 +277,7 @@ describe('Utils', () => {
|
||||||
expect(isPrimitiveType(schema)).toEqual(true);
|
expect(isPrimitiveType(schema)).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should return false for array of string which include the null value', () => {
|
it('Should return true for array of string which include the null value', () => {
|
||||||
const schema = {
|
const schema = {
|
||||||
type: ['object', 'string', 'null'],
|
type: ['object', 'string', 'null'],
|
||||||
};
|
};
|
||||||
|
@ -553,7 +553,7 @@ describe('Utils', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a humanized constraint when minItems and maxItems are the same', () => {
|
it('should have a humanized constraint when minItems and maxItems are the same', () => {
|
||||||
expect(humanizeConstraints(itemConstraintSchema(7, 7))).toContain('7 items');
|
expect(humanizeConstraints(itemConstraintSchema(7, 7))).toContain('= 7 items');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a humanized constraint when justMinItems is set, and it is equal to 1', () => {
|
it('should have a humanized constraint when justMinItems is set, and it is equal to 1', () => {
|
||||||
|
|
|
@ -107,7 +107,7 @@ export const mergeObjects = (target: any, ...sources: any[]): any => {
|
||||||
return mergeObjects(target, ...sources);
|
return mergeObjects(target, ...sources);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isObject = (item: any): boolean => {
|
export const isObject = (item: unknown): item is Record<string, unknown> => {
|
||||||
return item !== null && typeof item === 'object';
|
return item !== null && typeof item === 'object';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,6 +210,10 @@ export function unescapeHTMLChars(str: string): string {
|
||||||
.replace(/"/g, '"');
|
.replace(/"/g, '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isArray(value: unknown): value is Array<any> {
|
export function isArray(value: unknown): value is any[] {
|
||||||
return Array.isArray(value);
|
return Array.isArray(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isBoolean(value: unknown): value is boolean {
|
||||||
|
return typeof value === 'boolean';
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
Referenced,
|
Referenced,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { IS_BROWSER } from './dom';
|
import { IS_BROWSER } from './dom';
|
||||||
import { isNumeric, removeQueryString, resolveUrl, isArray } from './helpers';
|
import { isNumeric, removeQueryString, resolveUrl, isArray, isBoolean } from './helpers';
|
||||||
|
|
||||||
function isWildcardStatusCode(statusCode: string | number): statusCode is string {
|
function isWildcardStatusCode(statusCode: string | number): statusCode is string {
|
||||||
return typeof statusCode === 'string' && /\dxx/i.test(statusCode);
|
return typeof statusCode === 'string' && /\dxx/i.test(statusCode);
|
||||||
|
@ -99,6 +99,7 @@ const schemaKeywordTypes = {
|
||||||
additionalProperties: 'object',
|
additionalProperties: 'object',
|
||||||
unevaluatedProperties: 'object',
|
unevaluatedProperties: 'object',
|
||||||
properties: 'object',
|
properties: 'object',
|
||||||
|
patternProperties: 'object',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function detectType(schema: OpenAPISchema): string {
|
export function detectType(schema: OpenAPISchema): string {
|
||||||
|
@ -124,6 +125,10 @@ export function isPrimitiveType(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((schema.if && schema.then) || (schema.if && schema.else)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let isPrimitive = true;
|
let isPrimitive = true;
|
||||||
const isArrayType = isArray(type);
|
const isArrayType = isArray(type);
|
||||||
|
|
||||||
|
@ -134,8 +139,13 @@ export function isPrimitiveType(
|
||||||
: schema.additionalProperties === undefined && schema.unevaluatedProperties === undefined;
|
: schema.additionalProperties === undefined && schema.unevaluatedProperties === undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isArray(schema.items) || isArray(schema.prefixItems)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
schema.items !== undefined &&
|
schema.items !== undefined &&
|
||||||
|
!isBoolean(schema.items) &&
|
||||||
(type === 'array' || (isArrayType && type?.includes('array')))
|
(type === 'array' || (isArrayType && type?.includes('array')))
|
||||||
) {
|
) {
|
||||||
isPrimitive = isPrimitiveType(schema.items, schema.items.type);
|
isPrimitive = isPrimitiveType(schema.items, schema.items.type);
|
||||||
|
@ -418,7 +428,7 @@ function humanizeRangeConstraint(
|
||||||
let stringRange;
|
let stringRange;
|
||||||
if (min !== undefined && max !== undefined) {
|
if (min !== undefined && max !== undefined) {
|
||||||
if (min === max) {
|
if (min === max) {
|
||||||
stringRange = `${min} ${description}`;
|
stringRange = `= ${min} ${description}`;
|
||||||
} else {
|
} else {
|
||||||
stringRange = `[ ${min} .. ${max} ] ${description}`;
|
stringRange = `[ ${min} .. ${max} ] ${description}`;
|
||||||
}
|
}
|
||||||
|
@ -471,6 +481,15 @@ export function humanizeConstraints(schema: OpenAPISchema): string[] {
|
||||||
res.push(arrayRange);
|
res.push(arrayRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const propertiesRange = humanizeRangeConstraint(
|
||||||
|
'properties',
|
||||||
|
schema.minProperties,
|
||||||
|
schema.maxProperties,
|
||||||
|
);
|
||||||
|
if (propertiesRange !== undefined) {
|
||||||
|
res.push(propertiesRange);
|
||||||
|
}
|
||||||
|
|
||||||
const multipleOfConstraint = humanizeMultipleOfConstraint(schema.multipleOf);
|
const multipleOfConstraint = humanizeMultipleOfConstraint(schema.multipleOf);
|
||||||
if (multipleOfConstraint !== undefined) {
|
if (multipleOfConstraint !== undefined) {
|
||||||
res.push(multipleOfConstraint);
|
res.push(multipleOfConstraint);
|
||||||
|
@ -596,7 +615,6 @@ export function normalizeServers(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SECURITY_DEFINITIONS_COMPONENT_NAME = 'security-definitions';
|
|
||||||
export const SECURITY_DEFINITIONS_JSX_NAME = 'SecurityDefinitions';
|
export const SECURITY_DEFINITIONS_JSX_NAME = 'SecurityDefinitions';
|
||||||
export const SCHEMA_DEFINITION_JSX_NAME = 'SchemaDefinition';
|
export const SCHEMA_DEFINITION_JSX_NAME = 'SchemaDefinition';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user