This commit is contained in:
2023-01-03 00:04:38 +00:00
commit 3f002872e3
925 changed files with 181049 additions and 0 deletions
@@ -0,0 +1,11 @@
[production]
last 3 chrome versions
last 3 edge version
last 3 firefox versions
last 3 safari versions
opera >= 90
[development]
last 1 chrome version
last 1 firefox version
last 1 safari version
@@ -0,0 +1,21 @@
{
"extends": [
"@commitlint/config-conventional"
],
"rules": {
"header-max-length": [2, "always", 69],
"scope-case": [
2,
"always",
[
"camel-case",
"kebab-case",
"upper-case"
]
],
"subject-case": [
0,
"always"
]
}
}
+16
View File
@@ -0,0 +1,16 @@
/.git
/.github
# submodule
/apidom
/cypress
/docs
/config
/node_modules
/src
/scripts
/test
*.md
.git
.gitignore
+36
View File
@@ -0,0 +1,36 @@
# http://editorconfig.org
# A special property that should be specified at the top of the file outside of
# any sections. Set to true to stop .editor config file search on current file
root = true
[*]
# Indentation style
# Possible values - tab, space
indent_style = space
# Indentation size in single-spaced characters
# Possible values - an integer, tab
indent_size = 2
# Line ending file format
# Possible values - lf, crlf, cr
end_of_line = lf
# File character encoding
# Possible values - latin1, utf-8, utf-16be, utf-16le
charset = utf-8
# Denotes whether to trim whitespace at the end of lines
# Possible values - true, false
trim_trailing_whitespace = true
# Denotes whether file should end with a newline
# Possible values - true, false
insert_final_newline = true
[packages/apidom-ls/test/fixtures/**/*.json]
trim_trailing_whitespace = false
[packages/apidom-ls/test/fixtures/**/*.yaml]
trim_trailing_whitespace = false
+20
View File
@@ -0,0 +1,20 @@
REACT_APP_EXTEND_ESLINT=true
REACT_APP_COMPACT_BUNDLE=true
# The following are sample settings of REACT_APP_DEFINITION_FILE and REACT_APP_DEFINITION_URL
# Note that applying changes to REACT_APP_DEFINITION_FILE or REACT_APP_DEFINITION_URL flags requires restart of applicaton
# Tip: Should not set both REACT_APP_DEFINITION_FILE and REACT_APP_DEFINITION_URL flags
# Create-React-App expects static directory within /public to contain FILE
# REACT_APP_DEFINITION_FILE=/static/petstore-oas3.yml
# OAS3.0 remote absolute URI
# REACT_APP_DEFINITION_URL=https://petstore3.swagger.io/api/v3/openapi.json
# OAS2.x remote absolute URI
# REACT_APP_DEFINITION_URL=https://petstore.swagger.io/v2/swagger.json
# AsyncAPI 2.x.x remote absolute URI
REACT_APP_DEFINITION_URL=https://raw.githubusercontent.com/asyncapi/spec/v2.5.0/examples/streetlights-kafka.yml
REACT_APP_VERSION=$npm_package_version
@@ -0,0 +1,6 @@
/.husky
/build
/dist
/create-react-app
/node_modules
/public
+49
View File
@@ -0,0 +1,49 @@
{
"extends": [
"react-app",
"react-app/jest",
"airbnb",
"plugin:cypress/recommended",
"plugin:jsx-a11y/recommended",
"prettier",
"plugin:prettier/recommended"
],
"globals": {
"File": true,
"Blob": true,
"globalThis": true
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
}
},
"plugins": [
"jsx-a11y",
"prettier",
"@typescript-eslint"
],
"rules": {
"import/order": ["error", {
"groups": [
["builtin", "external", "internal"],
["parent", "sibling", "index"]
],
"newlines-between": "always"
}],
"prettier/prettier": "error",
"react/react-in-jsx-scope": 0,
"react/function-component-definition": [1, {
"namedComponents": ["arrow-function"]
}],
"import/extensions": ["error", "always", {
"ignorePackages": true
}],
"import/no-unresolved": [2, {
"ignore": [
// https://github.com/import-js/eslint-plugin-import/issues/1810
"^monaco-languageclient\/monaco-converter$"
]
}]
}
}
@@ -0,0 +1 @@
* text=auto eol=lf
+71
View File
@@ -0,0 +1,71 @@
# Do not modify this file.
# Dependabot configuration can only be changed in the default branch
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
commit-message:
prefix: "chore"
include: "scope"
open-pull-requests-limit: 3
ignore:
# node-fetch must be synced manually
- dependency-name: "node-fetch"
- dependency-name: "release-it"
- dependency-name: "@release-it/conventional-changelog"
- package-ecosystem: "docker"
# Look for a `Dockerfile` in the `root` directory
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
######################
# SwaggerEditor@next #
######################
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
target-branch: "next"
labels:
- "swagger-editor@next"
- "cat: dependencies"
- "javascript"
commit-message:
prefix: "chore"
include: "scope"
open-pull-requests-limit: 3
- package-ecosystem: "docker"
# Look for a `Dockerfile` in the `root` directory
target-branch: "next"
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"
labels:
- "swagger-editor@next"
- "cat: dependencies"
- "cat: docker"
- "docker"
- package-ecosystem: "github-actions"
target-branch: "next"
directory: "/"
schedule:
interval: "weekly"
labels:
- "swagger-editor@next"
- "cat: dependencies"
- "github_actions"
+69
View File
@@ -0,0 +1,69 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: SwaggerEditor@next build
on:
push:
branches: [ next ]
pull_request:
branches: [ next ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Use Node.js 16
uses: actions/setup-node@v3
with:
node-version: 16.16
registry-url: https://npm.pkg.github.com/
scope: "@swagger-api"
- name: Cache npm cache files
id: cache-npm-cache-files
uses: actions/cache@v3
with:
path: ~/.npm
key: npm-cache-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Cache Cypress binary
id: cache-cypress-binary
uses: actions/cache@v3
with:
path: cypress/cache
key: cypress-binary-${{ hashFiles('package-lock.json') }}
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Lint commit message
if: github.ref != 'refs/heads/next' && github.actor != 'dependabot[bot]'
run: git log -1 --pretty=format:"%s" | npx commitlint
- name: Lint code
run: npm run lint
- name: Unit tests
run: npm test
env:
CI: true
- name: Build App artifacts
run: npm run build:app
- name: E2E Tests
run: npm run cy:ci
- name: Upload build artifacts
if: github.ref == 'refs/heads/next'
uses: actions/upload-artifact@v3
with:
name: build
path: ./build
@@ -0,0 +1,37 @@
name: Dependabot Merge Me!
on:
pull_request_target:
branches: [ master, next ]
jobs:
merge-me:
name: Merge me!
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
# This first step will fail if there's no metadata and so the approval
# will not occur.
- name: Dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v1.3.5
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
# Here the PR gets approved.
- name: Approve a PR
if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
# Finally, tell dependabot to merge the PR if all checks are successful
- name: Instruct dependabot to squash & merge
if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}
uses: mshick/add-pr-comment@v2
with:
repo-token: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
allow-repeats: true
message: |
@dependabot squash and merge
env:
GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
@@ -0,0 +1,53 @@
# inspired by https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
name: Deploy SwaggerEditor@next to GitHub Pages
on:
workflow_run:
workflows: ["SwaggerEditor@next build", "SwaggerEditor@next nightly build"]
types:
- completed
branches: [next]
jobs:
deploy:
if: >
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.conclusion == 'success'
name: Deploy SwaggerEditor@next to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: next
- name: 'Download build artifact'
uses: actions/github-script@v6
with:
script: |
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "build"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
const fs = require('fs');
fs.writeFileSync('${{github.workspace}}/build.zip', Buffer.from(download.data));
- run: |
mkdir deploy-dir
unzip build.zip -d deploy-dir
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages # The branch the action should deploy to.
folder: deploy-dir # The folder the action should deploy.
clean: true # Automatically remove deleted files from the deploy branch
@@ -0,0 +1,32 @@
# inspired by https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
name: Deploy SwaggerEditor@next to Rancher🚢
on:
workflow_run:
workflows: ["Build & Push SwaggerEditor@next Docker image"]
types:
- completed
jobs:
deploy:
if: github.event.workflow_run.conclusion == 'success'
name: Deploy SwaggerEditor@next to Rancher
runs-on: ubuntu-latest
steps:
- name: Deploy Rancher🚢
run: |
ts="$(date +'%Y-%m-%dT%H:%M:%SZ' --utc)"
curl -s -D /dev/stderr -X PATCH \
-H "Authorization: Bearer ${RANCHER_BEARER_TOKEN}" \
-H 'Content-Type: application/strategic-merge-patch+json' \
"${RANCHER_URL}/k8s/clusters/${RANCHER_CLUSTER_ID}/apis/apps/v1/namespaces/${RANCHER_NAMESPACE}/${RANCHER_K8S_OBJECT_TYPE}/${RANCHER_K8S_OBJECT_NAME}" \
-d "{\"spec\": {\"template\": {\"metadata\": {\"annotations\": {\"cattle.io/timestamp\": \"${ts}\"}}}}}"
env:
RANCHER_BEARER_TOKEN: ${{ secrets.RANCHER_BEARER_TOKEN }}
RANCHER_CLUSTER_ID: 'c-n8zp2'
RANCHER_NAMESPACE: 'swagger-oss'
RANCHER_K8S_OBJECT_TYPE: 'daemonsets'
RANCHER_URL: ${{ secrets.RANCHER_URL }}
RANCHER_K8S_OBJECT_NAME: 'swagger-editor-next'
@@ -0,0 +1,74 @@
# inspired by https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
name: Build & Push SwaggerEditor@next Docker image
on:
workflow_run:
workflows: ["Release SwaggerEditor@next"]
types:
- completed
branches: [next]
jobs:
build-push:
if: github.event.workflow_run.conclusion == 'success'
name: Build & Push SwaggerEditor@next Docker image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: next
- name: Download build artifact
uses: actions/github-script@v6
with:
script: |
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "build"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
const fs = require('fs');
fs.writeFileSync('${{github.workspace}}/build.zip', Buffer.from(download.data));
- run: |
mkdir build
unzip build.zip -d build
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_SB_USERNAME }}
password: ${{ secrets.DOCKERHUB_SB_PASSWORD }}
- name: Build docker image and push
uses: docker/build-push-action@v3
with:
context: .
push: true
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386,linux/ppc64le,linux/s390x
tags: swaggerapi/swagger-editor:next-v5
- name: Build unprivileged docker image and push
uses: docker/build-push-action@v3
with:
context: .
file: Dockerfile.unprivileged
push: true
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386,linux/ppc64le,linux/s390x
tags: swaggerapi/swagger-editor:next-v5-unprivileged
@@ -0,0 +1,74 @@
# Do not modify this file.
# Github Actions only recognizes `workflow_run` and `workflow_dispatch`
# events that are located in the default branch
name: SwaggerEditor@next nightly build
on:
workflow_dispatch:
schedule:
- cron: '30 22 * * *'
jobs:
nightly-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
ref: next
- name: Use Node.js 16
uses: actions/setup-node@v3
with:
node-version: 16.16
registry-url: https://npm.pkg.github.com/
scope: "@swagger-api"
- name: Cache npm cache files
id: cache-npm-cache-files
uses: actions/cache@v3
with:
path: ~/.npm
key: npm-cache-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Cache Cypress binary
id: cache-cypress-binary
uses: actions/cache@v3
with:
path: cypress/cache
key: cypress-binary-${{ hashFiles('package-lock.json') }}
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
- name: Lint code
run: npm run lint
- name: unit tests
run: npm test
env:
CI: true
- name: Produce build artifacts
run: npm run build
- name: Produce npm artifact
run: npm pack
- name: E2E Tests
run: npm run cy:ci
- name: Upload build artifact
uses: actions/upload-artifact@v3
with:
name: build
path: ./build
- name: Upload npm artifact
uses: actions/upload-artifact@v3
with:
name: "swagger-api-swagger-editor-next.tgz"
path: ./swagger-api-swagger-editor-next-*.tgz
@@ -0,0 +1,92 @@
name: Release SwaggerEditor@next
on:
workflow_dispatch:
branches:
- next
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false
submodules: true
ref: next
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
registry-url: https://npm.pkg.github.com/
scope: "@swagger-api"
- name: Determine the next release version
uses: cycjimmy/semantic-release-action@v3
with:
dry_run: true
extra_plugins: |
@semantic-release/git
@semantic-release/exec
env:
GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
- name: Nothing to release
if: ${{ env.NEXT_RELEASE_VERSION == '' }}
uses: actions/github-script@v6
with:
script: |
core.setFailed('Nothing to release')
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
- name: Prepare for the Release
env:
REACT_APP_VERSION: ${{ env.NEXT_RELEASE_VERSION }}
run: |
npm run lint
npm run test
npm run build:app
npm run cy:ci
npm run build:bundle:esm
npm run build:bundle:umd
- name: Semantic Release
id: semantic
uses: cycjimmy/semantic-release-action@v3
with:
dry_run: false
extra_plugins: |
@semantic-release/git
env:
GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }}
- name: Release failed
if: steps.semantic.outputs.new_release_published == 'false'
uses: actions/github-script@v6
with:
script: |
core.setFailed('Release failed')
- name: Release published
run: |
echo ${{ steps.semantic.outputs.new_release_version }}
echo ${{ steps.semantic.outputs.new_release_major_version }}
echo ${{ steps.semantic.outputs.new_release_minor_version }}
echo ${{ steps.semantic.outputs.new_release_patch_version }}
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build
path: ./build
+35
View File
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
/dist
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Cypress
test/cypress/screenshots
test/cypress/videos
test/cypress/downloads
# idea
*.iml
.idea
/swagger-api-swagger-editor*.tgz
+3
View File
@@ -0,0 +1,3 @@
[submodule "create-react-app"]
path = create-react-app
url = https://github.com/swagger-api/swagger-editor-cra.git
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit $1
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install lint-staged
@@ -0,0 +1,4 @@
{
"*.js": "eslint",
"*.jsx": "eslint"
}
+27
View File
@@ -0,0 +1,27 @@
/.idea/
/.github/
/.husky/
/build/
/public/
/docs/
/node_modules/
/test/
/src/
/create-react-app/
/.nvmrc
/.lintstagedrc
/.eslintignore
/.env
/.prettierrc
/.releaserc
/.whitesource
/.gitmodules
/.dockerignore
/.browserslistrc
/.commitlintrc.json
/cypress.config.js
/Dockerfile
/.eslintrc
/.editorconfig
/swagger-api-swagger-editor-*.tgz
/whitesource.config
+1
View File
@@ -0,0 +1 @@
@swagger-api:registry=https://npm.pkg.github.com
+1
View File
@@ -0,0 +1 @@
16.13.2
+8
View File
@@ -0,0 +1,8 @@
{
"printWidth": 100,
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"endOfLine": "lf"
}
+26
View File
@@ -0,0 +1,26 @@
{
"branches": [
{"name": "master"},
{"name": "next", "channel": "alpha", "prerelease": "alpha"}
],
"tagFormat": "v${version}",
"plugins": [
"@semantic-release/commit-analyzer",
[
"@semantic-release/exec",
{
"verifyReleaseCmd": "echo \"NEXT_RELEASE_VERSION=${nextRelease.version}\" >> $GITHUB_ENV"
}
],
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github",
["@semantic-release/git", {
"assets": [
"package.json",
"package-lock.json"
],
"message": "chore(release): cut the ${nextRelease.version} release\n\n${nextRelease.notes}"
}]
]
}
+15
View File
@@ -0,0 +1,15 @@
{
"scanSettings": {
"configMode": "LOCAL",
"configExternalURL": "",
"projectToken": "",
"baseBranches": ["main"]
},
"checkRunSettings": {
"vulnerableCheckRunConclusionLevel": "success",
"displayMode": "diff"
},
"issueSettings": {
"minSeverityLevel": "LOW"
}
}
+3
View File
@@ -0,0 +1,3 @@
# Changelog
Release notes can be found in [Releases](https://github.com/swagger-api/swagger-editor/releases)
+5
View File
@@ -0,0 +1,5 @@
FROM nginx:1.23.3-alpine
COPY ./build /usr/share/nginx/html
EXPOSE 8080
# start nginx
CMD ["nginx", "-g", "daemon off;"]
@@ -0,0 +1,5 @@
FROM nginxinc/nginx-unprivileged:1.23.2-alpine
COPY ./build /usr/share/nginx/html
EXPOSE 8080
# start nginx
CMD ["nginx", "-g", "daemon off;"]
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,9 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+19
View File
@@ -0,0 +1,19 @@
SwaggerEditor
Copyright 2020 SmartBear Software Inc.
SwaggerEditor is licensed under Apache 2.0 license.
Copy of the Apache 2.0 license can be found in `LICENSES/Apache-2.0.txt` file.
react-dd-menu
Copyright (c) 2015 Mikkel Laursen
Specific Sass Cascading Style Sheet in `_dropdown-menu.scss` (the file) were originally created under MIT license in https://github.com/mlaursen/react-dd-menu repository.
Specific Sass Cascading Style Sheet have been copied into this project and modified. All modifications are licensed under Apache 2.0 License.
Copy of the MIT license can be found in `LICENSES/MIT.txt` file.
---
If the SPDX-FileCopyrightText and SPDX-License-Identifier tags are not present in the file,
it is assumed that these tags have following implicit value:
SPDX-FileCopyrightText: Copyright 2020 SmartBear Software Inc.
SPDX-License-Identifier: Apache-2.0
+559
View File
@@ -0,0 +1,559 @@
# SwaggerEditor
SwaggerEditor is using **forked** Create React App as it's building infrastructure.
## Table of Contents
- [Getting started](#getting-started)
- [Installation](#installation)
- [Usage](#usage)
- [Development](#development)
- [Prerequisites](#prerequisites)
- [Setting up](#setting-up)
- [Setting up on MacOS](#setting-up-on-macos)
- [npm scripts](#npm-scripts)
- [Build artifacts](#build-artifacts)
- [Package mapping](#package-mapping)
- [Documentation](#documentation)
- [Docker](#docker)
- [License](#license)
## Getting started
### Installation
SwaggerEditor is currently hosted on [GitHub packages registry](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages).
For installing SwaggerEditor npm package from GitHub packages registry, create `.npmrc` file in your current directory and add
the following line to it:
```
@swagger-api:registry=https://npm.pkg.github.com
```
#### Prerequisites
Using [Node.js](https://nodejs.org/) [active LTS version](https://nodejs.org/en/about/releases/) is recommended.
[node-gyp](https://www.npmjs.com/package/node-gyp) is used to build some fragments that require [Python 3.x](https://www.python.org/downloads/).
[emscripten](https://emscripten.org/docs/getting_started/downloads.html) or [docker](https://www.docker.com/) needs to be installed
on your operating system as well. We strongly recommend going with a docker option.
You can now install SwaggerEditor package using `npm`:
```sh
$ npm install @swagger-api/swagger-editor
````
For more information about installing npm packages from GitHub packages registry please visit [Installing a package](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#installing-a-package)
section in their documentation.
### Usage
Install the package:
```sh
$ npm install @swagger-api/swagger-editor
````
Use the package in you application:
**index.js**:
```js
import React from 'react';
import ReactDOM from 'react-dom';
import SwaggerEditor from '@swagger-api/swagger-editor';
import '@swagger-api/swagger-editor/swagger-editor.css';
const url = "https://raw.githubusercontent.com/asyncapi/spec/v2.2.0/examples/streetlights-kafka.yml";
const MyApp = () => (
<div>
<h1>SwaggerEditor Integration</h1>
<SwaggerEditor url={url} />
</div>
);
self.MonacoEnvironment = {
/**
* We're building into the dist/ folder. When application starts on
* URL=https://example.com then SwaggerEditor will look for
* `apidom.worker.js` on https://example.com/dist/apidom.worker.js and
* `editor.worker` on https://example.com/dist/editor.worker.js.
*/
baseUrl: `${document.baseURI || location.href}/dist/`,
}
ReactDOM.render(<MyApp />, document.getElementById('swagger-editor'));
```
**webpack.config.js** (webpack@5)
Install dependencies needed for webpack@5 to properly build SwaggerEditor.
```sh
$ npm i stream-browserify --save-dev
$ npm i process --save-dev
$ npm i https-browserify --save-dev
$ npm i stream-http --save-dev
$ npm i util --save-dev
```
```js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'production',
entry: {
app: './index.js',
'apidom.worker': '@swagger-api/swagger-editor/apidom.worker',
'editor.worker': '@swagger-api/swagger-editor/editor.worker',
},
output: {
globalObject: 'self',
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
fallback: {
path: false,
fs: false,
http: require.resolve('stream-http'), // required for asyncapi parser
https: require.resolve('https-browserify'), // required for asyncapi parser
stream: require.resolve('stream-browserify'),
util: require.resolve('util'),
zlib: false,
},
alias: {
// This alias doesn't pull any languages into bundles and works as monaco-editor-core was installed
'monaco-editor$': 'monaco-editor/esm/vs/editor/edcore.main.js',
// This alias make sure we don't pull two different versions of monaco-editor
'monaco-editor': '/node_modules/monaco-editor',
},
},
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser.js',
Buffer: ['buffer', 'Buffer'],
}),
],
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
/**
* The default way in which webpack loads wasm files wont work in a worker,
* so we will have to disable webpacks default handling of wasm files and
* then fetch the wasm file by using the file path that we get using file-loader.
*
* Resource: https://pspdfkit.com/blog/2020/webassembly-in-a-web-worker/
*
* Alternatively, WASM file can be bundled directly into JavaScript bundle as data URLs.
* This configuration reduces the complexity of WASM file loading
* but increases the overal bundle size:
*
* {
* test: /\.wasm$/,
* type: 'asset/inline',
* }
*/
{
test: /\.wasm$/,
loader: 'file-loader',
type: 'javascript/auto', // this disables webpacks default handling of wasm
},
]
}
};
```
Alternative **webpack.config.js** (webpack@5)
We've already built Web Workers fragments for you, and they're located inside our npm distribution
package in `dist/umd/` directory. In order to avoid complexity of building the Web Worker fragments you can
use those fragments directly. This setup will work both for **production** and **development** (webpack-dev-server)
and will significantly shorten your build process.
Install `copy-webpack-plugin` and other needed dependencies.
```sh
$ npm i copy-webpack-plugin --save-dev
$ npm i stream-browserify --save-dev
$ npm i process --save-dev
$ npm i https-browserify --save-dev
$ npm i stream-http --save-dev
$ npm i util --save-dev
```
```js
const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
mode: 'production',
entry: {
app: './index.js',
},
output: {
globalObject: 'self',
filename: 'static/js/[name].js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
fallback: {
path: false,
fs: false,
http: require.resolve('stream-http'), // required for asyncapi parser
https: require.resolve('https-browserify'), // required for asyncapi parser
stream: require.resolve('stream-browserify'),
util: require.resolve('util'),
zlib: false,
},
alias: {
// This alias doesn't pull any languages into bundles and works as monaco-editor-core was installed
'monaco-editor$': 'monaco-editor/esm/vs/editor/edcore.main.js',
// This alias make sure we don't pull two different versions of monaco-editor
'monaco-editor': '/node_modules/monaco-editor',
}
},
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser.js',
Buffer: ['buffer', 'Buffer'],
}),
new CopyWebpackPlugin({
patterns: [
{
from: 'node_modules/@swagger-api/swagger-editor/dist/umd/apidom.worker.js',
to: 'static/js',
},
{
from: 'node_modules/@swagger-api/swagger-editor/dist/umd/editor.worker.js',
to: 'static/js',
}
]
}),
],
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
```
## Development
### Prerequisites
[Node.js](https://nodejs.org/) >= 16.13.0 and `npm >= 8.1.0` are the minimum required versions that this repo runs on.
We recommend using the latest version of Node.js@16 though. We're using [node-gyp](https://www.npmjs.com/package/node-gyp) to build some fragments that require [Python 3.x](https://www.python.org/downloads/).
[emscripten](https://emscripten.org/docs/getting_started/downloads.html) or [docker](https://www.docker.com/) needs to be installed
on your operating system. We strongly recommend going with a docker option.
### Setting up
If you use [nvm](https://github.com/nvm-sh/nvm), running following command inside this repository
will automatically pick the right Node.js version for you:
```sh
$ nvm use
```
This repository is using npm packages from [https://www.npmjs.com/](npmjs.com) and [GitHub packages registry](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages).
To successfully install npm packages that SwaggerEditor requires, you need to [Authenticate to GitHub Packages](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-to-github-packages).
We recommend that you [authenticate using GitHub PAT (Personal Access Token)](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-with-a-personal-access-token).
**Create a new ~/.npmrc file if one doesn't exist.**
```sh
//npm.pkg.github.com/:_authToken=TOKEN
```
Alternatively, to authenticate by logging in to npm, use the `npm login` command,
replacing USERNAME with your GitHub username, TOKEN with your personal access token (classic),
and PUBLIC-EMAIL-ADDRESS with your email address.
```sh
$ npm login --scope=@swagger-api --registry=https://npm.pkg.github.com
> Username: USERNAME
> Password: TOKEN
> Email: PUBLIC-EMAIL-ADDRESS
```
Run the following commands to set up the repository for local development:
```sh
$ git submodule init
$ git submodule update
$ npm i
$ npm start
```
#### Setting up on MacOS
With the combination of MacOS and Node.js 16, there is a known compatibility issue of installing and building the `tree-sitter` dependency. The workaround is to globally install `>=npm@8.1.x` (for lerna/apidom monorepo) but use Node.js 14 to install/build tree-sitter.
Although the prerequisite is to use Node@16.13, at this point we don't rely on any specific feature from Node.js 16.13 (except for `>=npm@8.1.x`).
```sh
$ npm install -g npm
$ npm --version
```
Assuming we are using [nvm](https://github.com/nvm-sh/nvm) to manage Node versions:
```sh
$ nvm use v14
```
Then follow the installation steps above.
### npm scripts
**Lint**
```sh
$ npm run lint
```
**Runs unit and integration tests**
```sh
$ npm test
```
**Runs E2E Cypress tests**
Usage in **development** environment:
```sh
$ npm run cy:dev
```
Usage in **Continuos Integration (CI)** environment:
```sh
$ npm run cy:ci
```
**Build**
```sh
$ npm run build
````
This script will build all the SwaggerEditor build artifacts - `app`, `esm` and `umd`.
### Build artifacts
After building artifacts, every two new directories will be created: `build/` and `dist/`.
**build/**
```sh
$ npm run build:app
$ npm run build:app:serve
```
Builds and serves standalone SwaggerEditor application and all it's assets on `http://localhost:3050/`.
**dist/esm/**
```sh
$ npm run build:bundle:esm
```
This bundle is suited for consumption by 3rd parties,
which want to use SwaggerEditor as a library in their own applications and have their own build process.
**dist/umd/**
```sh
$ npm run build:bundle:umd
```
SwaggerEditor UMD bundle exports SwaggerEditor symbol on global object.
It's bundled with React defined as external. This allows consumer to use his own version of React + ReactDOM and mount SwaggerEditor lazily.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="SwaggerEditor"
/>
<title>SwaggerEditor</title>
<link rel="stylesheet" href="./swagger-editor.css" />
</head>
<body>
<div id="swagger-editor"></div>
<script src="https://unpkg.com/react@17/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js" crossorigin></script>
<script src="./dist/umd/swagger-editor.js"></script>
<script>
const props = {
url: 'https://raw.githubusercontent.com/asyncapi/spec/v2.2.0/examples/streetlights-kafka.yml',
};
const element = React.createElement(SwaggerEditor, props);
const domContainer = document.querySelector('#swagger-editor');
ReactDOM.render(element, domContainer);
</script>
</body>
</html>
```
**npm**
SwaggerEditor is released as `@swagger-api/swagger-editor` npm package on [GitHub packages registry](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages).
Package can also be produced manually by running following commands (assuming you're already followed [setting up](#setting-up) steps):
```sh
$ npm run build:bundle:esm
$ npm run build:bundle:umd
$ npm pack
```
### Package mapping
SwaggerEditor maps its [build artifacts](#build-artifacts) in `package.json` file in following way:
```json
"unpkg": "./dist/umd/swagger-editor.js",
"module": "./dist/esm/swagger-editor.js",
"browser": "./dist/esm/swagger-editor.js",
"jsnext:main": "./dist/esm/swagger-editor.js",
"exports": {
"./package.json": "./package.json",
"./swagger-editor.css": "./dist/esm/swagger-editor.css",
".": {
"browser": "./dist/esm/swagger-editor.js"
},
"./apidom.worker": {
"browser": "./dist/esm/apidom.worker.js"
},
"./editor.worker": {
"browser": "./dist/esm/editor.worker.js"
}
}
```
To learn more about these fields please refer to [webpack mainFields documentation](https://webpack.js.org/configuration/resolve/#resolvemainfields)
or to [Node.js Modules: Packages documentation](https://nodejs.org/docs/latest-v16.x/api/packages.html).
## Documentation
### Customization
- [Plug points](./docs/customization/plug-points/README.md)
### Environment Variables
It is possible to use an environment variable to specify a local JSON/YAML file or a remote URL for SwaggerEditor to load on startup.
These environment variables will get baked in during build time into build artifacts.
Environment variables currently available:
| Variable name | Description |
|-----------------------------|:----------------------------------------------------------------------------------------------------------:|
| `REACT_APP_DEFINITION_FILE` | Specifies a local file path, and the specified file must also be present in the `/public/static` directory |
| `REACT_APP_DEFINITION_URL` | Specifies a remote URL. This environment variable currently takes precedence over `REACT_APP_SWAGGER_FILE` |
| `REACT_APP_VERSION` | Specifies the version of this app. The version is read from `package.json` file. |
Sample environment variable values can be found in `.env` file. For more information about using
environment variables, please refer to [adding Custom Environment Variables](https://create-react-app.dev/docs/adding-custom-environment-variables/)
section of Create React App documentation.
### Using preview plugins in SwaggerUI
SwaggerEditor comes with number of `preview` plugins that are responsible for rendering
the definition that's being created in the editor. These plugins include:
- **EditorPreviewAsyncAPIPlugin** - AsyncAPI specification rendering support
- **EditorPreviewAPIDesignSystemsPlugin** - API Design Systems rendering support
With a bit of adapting, we can use these plugins with SwaggerUI to provide ability
to render AsyncAPI or API Design Systems definitions with SwaggerUI.
```js
import React from 'react';
import ReactDOM from 'react-dom';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
import SwaggerEditor from '@swagger-api/swagger-editor';
const plugins = [
SwaggerEditor.plugins.EditorContentType,
SwaggerEditor.plugins.EditorPreviewAsyncAPI,
SwaggerEditor.plugins.EditorPreviewAPIDesignSystems,
SwaggerEditor.plugins.SwaggerUIAdapter,
];
ReactDOM.render(
<SwaggerUI
plugins={plugins}
url="https://raw.githubusercontent.com/asyncapi/spec/v2.4.0/examples/streetlights-kafka.yml"
/>,
document.getElementById('swagger-ui')
);
```
The key here is `SwaggerUIAdapter` plugin which adapts SwaggerEditor plugins to use
directly with SwaggerUI.
## Docker
### Pre-built DockerHub image
SwaggerEditor is available as a pre-built docker image hosted on [DockerHub](https://hub.docker.com/r/swaggerapi/swagger-editor/tags?page=1&name=next-v5).
```sh
$ docker pull swaggerapi/swagger-editor:next-v5
$ docker run -d -p 8080:80 swaggerapi/swagger-editor:next-v5
```
### Building locally
**Privileged image**:
```sh
$ npm run build:app
$ docker build . -t swaggerapi/swagger-editor:next-v5
$ docker run -d -p 8080:80 swaggerapi/swagger-editor:next-v5
```
Now open your browser at `http://localhost:8080/`.
**Unprivileged image**:
```sh
$ npm run build:app
$ docker build . -f Dockerfile.unprivileged -t swaggerapi/swagger-editor:next-v5-unprivileged
$ docker run -d -p 8080:8080 swaggerapi/swagger-editor:next-v5-unprivileged
```
Now open your browser at `http://localhost:8080/`.
> **No** custom environment variables are currently supported by SwaggerEditor.
## License
SwaggerEditor is licensed under [Apache 2.0 license](https://github.com/swagger-api/swagger-editor/blob/next/LICENSES/Apache-2.0.txt).
SwaggerEditor comes with an explicit [NOTICE](https://github.com/swagger-api/apidom/blob/next/NOTICE) file
containing additional legal notifications and information.
This project uses [REUSE specification](https://reuse.software/spec/) that defines a standardized method
for declaring copyright and licensing for software projects.
@@ -0,0 +1,18 @@
/* eslint-disable import/no-extraneous-dependencies */
import { defineConfig } from 'cypress';
import setupNodeEvents from './test/cypress/plugins/index.js';
export default defineConfig({
fileServerFolder: 'test/cypress/static',
fixturesFolder: 'test/cypress/fixtures',
screenshotsFolder: 'test/cypress/screenshots',
videosFolder: 'test/cypress/videos',
video: false,
e2e: {
baseUrl: 'http://localhost:3050/',
supportFile: 'test/cypress/support/e2e.js',
specPattern: 'test/cypress/integration/**/*spec.js',
setupNodeEvents,
},
});
@@ -0,0 +1,55 @@
# High level architecture of SwaggerEditor@5
This document briefly describes high level architecture of SwaggerEditor@5.
## Plugin architecture
SwaggerEditor@5 is composed of number of plugins. These plugins are divided into four
distinct categories
1. Plugins providing editor implementations
2. Plugins providing preview of editor content
3. Editor implementation support plugins
4. Generic features plugins
### Plugins providing editor implementations
These plugins include `editor-textarea` and `editor-moanco`.
`editor-textarea` is a base plugin that other editor implementations build on.
This plugin provides basic editing experience using `<textarea />` HTML tag.
`editor-monaco` builds on top of `editor-textarea` and provide advanced editing
experience using [Monaco Editor](https://microsoft.github.io/monaco-editor/).
### Plugins providing preview of editor content
These plugins include `editor-preview-swagger-ui`, `editor-preview-asyncapi` and others.
The single responsibility of editor preview plugin is to render the editor content (text)
to a set of UI components.
### Editor implementation support plugins
These plugins include `editor-persistence`, `editor-read-only` and others.
Plugins in this category are responsible to support plugins providing editor implementation
with additional enhanced capabilities in generic way.
### Generic features plugins
These plugins include `dialogs`, `modals`, `layout` and others. Each plugin in this
category provide features or enhancements to plugins in previous three categories.
## Future architectural changes
This section describes opportunities to make the architecture of SwaggerEditor@5 better.
### State management
Currently, editor content (text) is stored in SwaggerUI `spec` plugin. This causes various issues
which manifests in decreased user experience of editing text. Every time the editor content
changes the `spec` plugin will try to parse it as JSON or YAML, resolve it and store it in
redux state. This is absolutely not necessary. We can store editor content in editor implementation plugin
and have preview plugins work as finite state machines and detect if they should process the editor content in any way.
When this architectural change is implemented, the typing lag on big amount of editor content (text)
will significantly decrease.
@@ -0,0 +1,3 @@
# Plug points
- [editor-monaco](./editor-monaco.md)
@@ -0,0 +1,169 @@
# editor-monaco plug points
## Extending web worker capabilities
`editor-monaco` plugin is using monaco editor, which is using web workers to provide
editor capabilities. `editor-monaco` comes with a web worker called `apidom.worker`.
This worker contains all the language service utilizing ApiDOM capabilities.
`apidom.worker` can be extended in two ways: dynamic and static.
### Dynamic extension
Dynamic extension happens during runtime, and we recommend to use it only for simple use-cases.
First thing we need to do is to pass a `customApiDOMWorkerPath` option to the `EditorMonaco` plugin.
```js
EditorMonaco({
createData: {
customApiDOMWorkerPath: 'https://example.com/index.js',
},
})
```
`customApiDOMWorkerPath` is a URL (absolute or relative) of extending script. When the `apidom.worker`
is bootstrapping it, it imports this URL using [importScripts](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts).
The `apidom.worker` then expects the script to have the following signature:
**https://example.com/index.js**
```js
globalThis.customApiDOMWorkerFactory = (ApiDOMWorkerClass, toolbelt) => {
return ApiDOMWorkerClass;
};
```
The script must expose `customApiDOMWorkerFactory` function on global object. This function will
receive two arguments:
- ApiDOMWorkerClass - the class that implements the editor capabilities
- toolbelt - an object containing various library exports
Here is a simple **example** demonstrating changing the log level of language service:
```js
globalThis.customApiDOMWorkerFactory = (ApiDOMWorkerClass, toolbelt) => {
const { apidomLS } = toolbelt;
class ApiDOMWorkerLogLevelErrorClass extends ApiDOMWorkerClass {
static apiDOMContext = {
...ApiDOMWorkerClass.apiDOMContext,
logLevel: apidomLS.LogLevel.ERROR,
};
}
return ApiDOMWorkerLogLevelErrorClass;
};
```
### Static extension
Static extension involves need to use a build system like webpack.
**my-custom-apidom.worker.js**
```js
import { initialize, makeCreate, ApiDOMWorker } from '@swagger-api/swagger-editor/apidom.worker';
class ApiDOMWorkerExtended extends ApiDOMWorker {
// implementation of extensions
}
const create = makeCreate(ApiDOMWorkerExtended);
globalThis.onmessage = () => {
initialize((ctx, createData) => {
return create(ctx, createData);
});
};
export { initialize, create, makeCreate, ApiDOMWorkerExtended as ApiDOMWorker };
```
Next please have a look at the [usage section](../../../README.md#usage) of the documentation
specifically the **webpack.config.js** part. Given that we now extended the default worker,
we need to reconfigure the webpack and provide it with the path to the extended worker.
This is the part of the configuration that will change.
```js
entry: {
app: './index.js',
'apidom.worker': './my-custom-apidom.worker.js',
'editor.worker': '@swagger-api/swagger-editor/editor.worker',
}
```
## Passing data to web workers
Often when extending web worker capabilities it is the case that we need to pass additional
data to web worker. These data may include any arbitrary data compatible with
[the structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm).
Let's consider the following use-case. We need to extend the `apidom.worker` in a way that
it will be fetching data on demand from authorized REST endpoint.
### Dynamic extension
`EditorMonaco` plugin configuration.
```js
EditorMonaco({
createData: {
authToken: 'c32d8b45-92fe-44f6-8b61-42c2107dfe87',
customApiDOMWorkerPath: 'https://example.com/index.js',
},
})
```
**https://example.com/index.js**
```js
globalThis.customApiDOMWorkerFactory = (ApiDOMWorkerClass, toolbelt) => {
const { apidomLS } = toolbelt;
class ApiDOMWorkerLogLevelErrorClass extends ApiDOMWorkerClass {
static apiDOMContext = {
...ApiDOMWorkerClass.apiDOMContext,
logLevel: apidomLS.LogLevel.ERROR,
};
async loadData() {
// createData passed as plugin option is available in worker as this._createData
const { authToken } = this._createData;
return await fetch(`https://example.com/data?authToken=${authToken}`)
}
}
return ApiDOMWorkerLogLevelErrorClass;
};
```
### Static extension
Whenever you extend the `ApiDOMWorker` class you will have `_createData` public property available.
**my-custom-apidom.worker.js**
```js
import { initialize, makeCreate, ApiDOMWorker } from '@swagger-api/swagger-editor/apidom.worker';
class ApiDOMWorkerExtended extends ApiDOMWorker {
async loadData() {
// createData passed as plugin option is available in worker as this._createData
const { authToken } = this._createData;
return await fetch(`https://example.com/data?authToken=${authToken}`)
}
}
const create = makeCreate(ApiDOMWorkerExtended);
globalThis.onmessage = () => {
initialize((ctx, createData) => {
return create(ctx, createData);
});
};
export { initialize, create, makeCreate, ApiDOMWorkerExtended as ApiDOMWorker };
```
@@ -0,0 +1,133 @@
## Swagger Editor Legacy (v3/v4) Migration Summary
### Topbar Features
[x] Import from URL
[x] Import from File
[x] Save As Json
[x] Save As Yaml
[x] Convert from Json to Yaml, then download
[x] Convert from Yaml to Json, then download
[x] Convert from Json to Yaml, in editor only
[x] Clear Editor (moved from File Menu to Edit Menu)
[x] Convert from OAS2 to OAS3
[x] Generate Servers list - OAS2
[x] Generate Servers list - OAS3.0
[x] Generate Clients list - OAS2
[x] Generate Clients list - OAS3.0
[x] Display/Hide menu items based on combination of json/yaml, oas2/oas3
[x] NEW: consistent use of styled Modal components throughout (react-modal)
[x] NEW: Load default OAS2/OAS3/OAS3.1/AsyncApi2 definition; w/keyboard shortcuts
[x] Removed: topbar-insert (plugin); no replacement planned
### Editor Features
[x] NEW: Monaco Editor
[x] NEW: validation from apidom-ls library
[x] Removed: Ace Editor
[x] Removed: internal validation from swagger-editor v3/v4
[x] Drag-n-drop local file to editor (react-dropzone)
[x] Persist definition on browser refresh/reload (localStorage)
[x] Display validation pane results
### Visual UI Features
[x] SwaggerUI v4; React 17
### Implementation Changes
[x] React Hooks support, e.g. menu item display toggle, modal system
[x] Behavioral testing of components, e.g. not the implementation details
[x] Simplify and reorganize `presets`, `layouts`, and `plugins`
[x] Extract menu action methods from Components to Actions
[x] Extract menu logic helpers to Actions
[x] Extract shared menu logic helpers to `utils/editor-converter`
[x] Replace `fetch` with `axios` http helpers to `utils/topbar-http`
[x] deprecate plugins with direct implementation: Convert to OAS3, Import File
[x] Removed: unnecessary state where possible
[x] Removed: window.alert and window.confirm popups
[x] Removed: swagger-client library dependency
[x] Tests: testing-library + jest (unit), cypress (e2e)
### Possible additional/expanded docs/contributing topics
[x] Separation of actions from components. tldr: easier to test, possibly more re-usable
[x] React Hooks. tldr: modern practices
[x] testing-library. tldr: focus on user behaviors, more durable/maintainable tests
[x] reorganizing the presets. e.g. what happened to `standalone` and other plugins? The new recommended structure. tldr: multi-spec, multi-layouts
### List of migrated legacy methods
Note: likely to remove this section from final doc
Extract menu action methods from React to Actions
[x] importFromURL
[x] saveAsYaml
[x] saveAsJson
[x] convertToYaml
[x] downloadGeneratedFile
[x] importFile
[x] onDocumentLoad prop - removed. handled now in actions. Theoretically, we could expose as a user-overwritable function. Maybe SH needed it?
[x] updateEditorContent prop - will be removed, and handled in actions.
[x] clearEditor
Deprecate methods from React
[x] saveAsText
[x] handleResponse
Extract menu logic helpers to Actions
[x] getGeneratorUrl
[x] instantiateGeneratorClient
[x] shouldReInstantiateGeneratorClient (new)
Extract menu logic helpers to utils-converter
[x] hasParserErrors
[x] getFileName
[x] getDefinitionLanguage
[x] getDefinitionVersion
Create (axios) http method to utils-http
[x] getDefinitionFromUrl
[x] getGenerator2Definition
[x] postPerformOasConversion
Remove unnecessary state:
[x] swaggerClient
[x] definitionVersion
Remove use of alert and confirm via new modal system
[x] alert
[x] confirm
### Additional notes (remove from final doc)
[x] swagger-ui redux state
[x] connect monaco state to swagger-ui redux state
[x] connect actions with monaco state, e.g. updateEditorContent
[x] init oas spec via swagger-ui
[x] connect & sync generic-editor updates to swagger-ui
[x] init oas spec via import File (finish action) - Json
[x] init oas spec via import File (finish action) - Yaml
[x] init oas spec via import Url (finish action)
[x] CSS/Less/Saas styling
[x] remove use of mock data in topbarActions. (mock fixtures not removed yet)
[x] try react-modal lib instead of creating internal version
[x] modify generic-editor plugin to have a default editor placeholder (instead of calling GenericEditorContainer directly)
[x] add disposables array, and ability to dispose()
[x] make generator servers/clients toggleable; enable oas3.1/others when supported
[x] File Menu dropdown - add json/yaml detection to display appropriate link
[x] Edit menu dropdown - render convert to OAS3 only if currently 'isSwagger2`
[x] Edit menu dropdown - render convert to Yaml only if currently 'json'
[x] onboard - default definition should be in YAML format
### Resolved Issues (remove from final doc)
[x] ~~fix exploding styling/rendering when using in-browser (ctrl+f) find text within monaco; monaco's find+replace feature~~ USING P2M/M2P FIXES THIS ISSUE
[x] ~~warning: overlapping semantic tokens~~ THIS IS APIDOM-LS ISSUE
[x] fix editor configuration/onChange to always word-wrap.
[x] remove "dev mode" case when editor content is undefined
[x] remove mock data/fixtures/configuration from `actions.js`
[x] in codeActionUi, sometimes recieve an Uncaught promise TypeError: d.dispose is not a funtion
[x] asyncapi support: anywhere we should be detecting async api (or any other supported spec); e.g. clearEditor
[x] handle apidom parser throw, when unable to detect langugage. e.g. empty string, or oas2
[x] load default (oas3). note the topbar generate server/client exists. -> clear all. user may type random string. note that the topbar generate server/client did NOT disappear
[x] load default -> import OAS2. note the topbar generate server/client exists. -> clear all. user may type random string. note that the topbar generate server/client did NOT disappear
@@ -0,0 +1,30 @@
# Migration Status
* [Swagger Editor Legacy (v3/v4) Migration Summary](./migration-legacy-summary.md)
### Known Issues
[ ] handle case(s) when specSelectors.method returns undefined
### Integration Tasks
[ ] match and extend configurability options for editor & monaco
### Backlog
[ ] update "minimal" specs/fixtures for `clearEditor`; oas2, oas3, oas3_1, asycapi2
[ ] memory performance benchmarks
[ ] if refresh empty monaco, ~~should~~ MAY load a default definition
[ ] jump-to-path (plugin)
### Ideas
[ ] topbar: topbar-insert (plugin); this should be integrated into the `Topbar` plugin
[ ] topbar: update generator (plugin?) for oas3.1, asyncapi, etc. support when available
[ ] monaco: update syntax highlighting as needed
[ ] monaco - additional initial style and configuration of monaco editor, as needed
### Test Coverage Ideas
[ ] should add unit tests with bad/invalid urls; generator, import Url
[ ] should add unit tests when both swagger2 and oas3 flags set to same value (both true, both false)
[ ] should add unit tests allowing exclusion of both swagger2 and oas3, e.g. future asynapi, graphql, etc.
[ ] e2e: monaco-editor features
@@ -0,0 +1,134 @@
# Migrate from SwaggerEditor@4 to SwaggerEditor@next
## Table of Contents
- [Introduction](#introduction)
- [Development](#development)
- [Start script with hot-reloading](#start-script-with-hot-reloading)
- [Static build script](#static-build-script)
- [Local & remote definitions](#local--remote-definitions)
- [Linting](#linting)
- [Dependencies](#dependencies)
- [Testing](#testing)
- [Design](#design)
- [Plugins](#plugins)
- [plugins available at release](#plugins-available-at-release)
- [plugins not yet migrated](#plugins-not-yet-migrated)
- [Layout](#layout)
### Introduction
SwaggerEditor@next is a ground-up rewrite of SwaggerEditor@4. However, SwaggerEditor@4 is still fundamentally based on the SwaggerUI plugin system, and continues to be developed within the React ecosystem. For users without custom plugins or other forked customizations, SwaggerEditor@next is intended to be mostly drop-in compatible with the existing SwaggerEditor@4.
SwaggerEditor@4 introduces integration with ApiDOM and Microsoft's Monaco Editor. ApiDOM replaces the parser from SwaggerClient, as well as existing custom validation from SwaggerEditor@4. Monaco Editor replaces Ace Editor. Additional documentation on features and usage of [ApiDOM](https://github.com/swagger-api/apidom) and [Monaco Editor](https://github.com/microsoft/monaco-editor) can be found within their respective documention. Also available are the [ApiDOM Playground](https://swagger-api.github.io/apidom/) and [Monaco Editor Playground](https://microsoft.github.io/monaco-editor/playground.html)
This migration guide is intended to highlight setup changes and key customization features for SwaggerEditor@next.
### Development
SwaggerEditor@next is using **forked** Create React App as it's building infrastructure. Therefore there are a few minor differences to develop SwaggerEditor@next
#### Start script with hot-reloading
new:
```
$ npm start
```
old:
```
$ npm run dev
```
#### Static build script
new:
```
$ npm run build:app
$ npm run build:app:serve
```
old:
```
$ npm start
```
#### Local & remote definitions
Only files inside `public` can be used from `public/index.html`. JS files must be put inside `src`.
new:
```
<SwaggerEditor url={url} />
```
old:
In `dev-helpers/index.html`, add a `url` key like this:
```
const editor = SwaggerEditorBundle({
dom_id: '#swagger-editor',
url: "some-local-or-remote-path-to-definition.yaml" # define path here
layout: 'StandaloneLayout',
presets: [
SwaggerEditorStandalonePreset
]
})
```
#### Linting
Automatic linting checks remain part of the commit process. SwaggerEditor@4 now generally follows the eslint recommendations from the AirBnb and React teams.
There is currently a known issue between compatibility of `eslint-config-airbnb` and `eslint-config-react-app`. The workaround is to set `DISABLE_ESLINT_PLUGIN=false` in the npm script.
#### Dependencies
SwaggerEditor@next is now based on `swagger-ui-react` instead of `swagger-ui`. In addition, unlike SwaggerEditor@4, SwaggerEditor@next does not have a dependency on `SwaggerClient`.
#### Testing
Unit tests are now covered by `jest` and `@testing-library`. Unit tests are now co-located next to their component. Component tests follow the `@testing-library` philosophy to avoid including implementation details, so that changes to implementation but not functionality doesn't break existing tests.
E2E Cypress tests remain in the `test/cypress` directory.
### Design
#### Plugins
SwaggerEditor@next maintains its core as an extension of SwaggerUI's plugin system. SwaggerEditor@next exports itself as a fully realized set of plugins, each of which can be extended and wrapped as needed. This even includes the new Monaco Editor feature as a plugin!
Compared to SwaggerEditor@4, there is also no change to precedence with regards to the order of loading plugins.
SwaggerEditor@next provides a `modals` plugin for a unified modal system. The `modals` plugin is further extended via the `dialogs` plugin which provides a set of `alert` and `confirm` modal dialogs.
Any existing custom plugins for SwaggerEditor@4 that modified the behavior of, or directly interfaced with, the Ace Editor will likely need to be heavily refactored. Custom validation rules should be migrated to ApiDOM as needed.
##### plugins available at release
- `dialogs`
- `dropzone`
- `editor-monaco`
- `editor-persistence`
- `editor-preview-asyncapi`
- `editor-preview-swagger-ui`
- `editor-read-only`
- `editor-spec-origin`
- `editor-textarea`
- `layout`
- `modals`
- `topbar`
##### plugins not yet migrated
At the time of this writing there are two plugins from SwaggerEditor@4 that have not been migrated:
1. `jump-to-path`. Note: expect to leverage ApiDOM and `editor-monaco` plugin to replace AST and Ace Editor.
2. `topbar-insert`. Note: expect to leverage and wrap components of various existing plugins: `topbar`, `editor-monaco`, `modals`, and `dialogs`.
#### Layout
SwaggerEditor@next comes with a plugin for a "core" layout. The "core" layout provides plug points that are analogous to "panes" and/or "bars" in other IDEs. These plug points make it easier for developers to create plugins that customize their UX with as minimal changes to the "core" layout as possible.
The "core" layout includes contains `EditorPane`, `EditorPreviewPane`, and `Topbar`. These three components represent the basic UX wireframe for SwaggerEditor@next. In addition, the `EditorPane` is provided with four surrounding `bars` (top, bottom, left, right) that can each be customized with their own wrapped implementations.
Using itself as a reference design, SwaggerEditor@next provides implementation of two different `EditorPane` (`editor-monaco` and `editor-textarea`), and two different `EditorPreviewPane` (`editor-preview-swagger-ui` and `editor-preview-asyncapi). The `editor-monaco` plugin also further extends the base `EditorPaneBarTop` and `EditorPaneBarBottom` with its own wrapped version of each.
@@ -0,0 +1,24 @@
Monaco Client (React)
- setup a Monaco instance
- setup monaco environment use of language worker(s) to use
- instantiate web workers
- register providers via Adapters
- create a Monaco instance
Adapter
- an adapter for each service or provider
- generally expect a `provide[Description]` method that matches monaco interface
- offloads language service functions to language web worker
- run and/or return a monaco editor "effect". e.g. hover, completion, based on web worker result
- not required to use Typescript
WebWorker
- called via an adapter
- call a language service method in separate thread
- recommended use by Monaco
LanguageService
- called via a web worker
- any lib, in our case, apidom
- examples include typescript/javascript, json, css
notes:
- some minor naming differences across libs
@@ -0,0 +1,31 @@
Swagger-client is used as middleware to transform `generator` responses,
which also includes function methods alongside data objects.
fetch GET call to `SwaggerClient(url, [options])` will return `response.apis` methods.
- reminder to attach `.catch()` to any `response.apis.[method]` call
```
response.apis.clients:
- clientOptions: ƒ(parameters)
- downloadFile: ƒ(parameters)
- generateClient: ƒ(parameters)
- getClientOptions: ƒ(parameters)
response.apis.servers:
- downloadFile: ƒ(parameters)
- generateServerForLanguage: ƒ(parameters)
- getServerOptions: ƒ(parameters)
- serverOptions: ƒ(parameters)
```
### Summary
In order to download a generated definition, `legacy swagger-editor` made two calls to swagger-client.
1. Given OAS3 or Swagger2/OAS2 definition, swagger-editor makes a request to Generator3 or Generator2 respectively.
Generator3/Generator2 returns a response that includes it's own definition, which `swagger-client`, as middleware, translates the defintion included in Generator's response into a more usable `response.apis.clients` format. This format also includes new `execute` methods for `swagger-editor` to call.
2. `swagger-editor` calls the appropriate `execute` method that was created by `swagger-client` to download the generated definition. Note, Generator3 returns the Blob directly, while Generator2 returns a json object containing an URI link to the Blob.
Additionally, `legacy swagger-editor` saved these methods to React state for general purpose use, e.g. downloadFile vs clientOptions.
In this new version of swagger-editor, use of `swagger-client` has been deprecated, so these methods are no longer available or saved. Equivalent functionality to directly interface with Generator3/Generator2 now exists in `topbarActions`. This change also should now always yield a deterministic final result.
File diff suppressed because it is too large Load Diff
+131
View File
@@ -0,0 +1,131 @@
{
"name": "@swagger-api/swagger-editor",
"version": "5.0.0-alpha.42",
"private": false,
"publishConfig": {
"registry": "https://npm.pkg.github.com"
},
"contributors": [
"(in alphabetical order)",
"Francesco Tumanischvili",
"Timothy Lai",
"Vladimir Gorej <vladimir.gorej@gmail.com>"
],
"license": "Apache-2.0",
"type": "module",
"sideEffects": false,
"unpkg": "./dist/umd/swagger-editor.js",
"module": "./dist/esm/swagger-editor.js",
"browser": "./dist/esm/swagger-editor.js",
"jsnext:main": "./dist/esm/swagger-editor.js",
"exports": {
"./package.json": "./package.json",
"./swagger-editor.css": "./dist/swagger-editor.css",
".": {
"browser": "./dist/esm/swagger-editor.js"
},
"./apidom.worker": {
"browser": "./dist/esm/apidom.worker.js"
},
"./editor.worker": {
"browser": "./dist/esm/editor.worker.js"
}
},
"scripts": {
"start": "cross-env DISABLE_ESLINT_PLUGIN=false ENABLE_PROGRESS_PLUGIN=true react-scripts start",
"build": "npm run build:app && npm run build:bundle:esm && npm run build:bundle:umd",
"build:app": "cross-env ENABLE_PROGRESS_PLUGIN=false DISABLE_ESLINT_PLUGIN=false react-scripts build",
"build:app:serve": "serve -s build -l 3050",
"build:bundle:esm": "rimraf ./dist/esm && cross-env DISABLE_ESLINT_PLUGIN=false ENABLE_PROGRESS_PLUGIN=false GENERATE_SOURCEMAP=true BUILD_ESM_BUNDLE=true DIST_PATH=dist/esm react-scripts build-bundle && rimraf ./dist/esm/swagger-editor.css*",
"build:bundle:umd": "rimraf ./dist/umd ./dist/swagger-editor.css && cross-env DISABLE_ESLINT_PLUGIN=false ENABLE_PROGRESS_PLUGIN=false GENERATE_SOURCEMAP=false BUILD_UMD_BUNDLE=true DIST_PATH=dist/umd react-scripts build-bundle && copyfiles -u 2 ./dist/umd/swagger-editor.css ./dist && rimraf ./dist/umd/swagger-editor.css",
"analyze": "source-map-explorer 'build/static/js/main.js'",
"test": "react-scripts test",
"cy:dev": "start-server-and-test cy:dev:server http://localhost:3003 cy:dev:open",
"cy:dev:open": "cross-env CYPRESS_BASE_URL=http://localhost:3003 cypress open --e2e",
"cy:dev:server": "cross-env PORT=3003 BROWSER=none ENABLE_PROGRESS_PLUGIN=false react-scripts start",
"cy:ci": "start-server-and-test build:app:serve http://localhost:3050 cy:run:chrome",
"cy:run:chrome": "cypress run --browser chrome",
"cy:run:firefox": "cypress run --browser firefox",
"lint": "eslint . --ext .jsx,.js",
"lint:fix": "eslint . --ext .jsx,.js --fix",
"clean": "rimraf ./build ./dist",
"link:apidom": "npm link @swagger-api/apidom-ast @swagger-api/apidom-core @swagger-api/apidom-json-path @swagger-api/apidom-json-pointer @swagger-api/apidom-ls @swagger-api/apidom-ns-api-design-systems @swagger-api/apidom-ns-asyncapi-2 @swagger-api/apidom-ns-openapi-3-1 @swagger-api/apidom-parser-adapter-api-design-systems-json @swagger-api/apidom-parser-adapter-api-design-systems-yaml @swagger-api/apidom-parser-adapter-asyncapi-json-2 @swagger-api/apidom-parser-adapter-asyncapi-yaml-2 @swagger-api/apidom-parser-adapter-json @swagger-api/apidom-parser-adapter-openapi-json-3-0 @swagger-api/apidom-parser-adapter-openapi-json-3-1 @swagger-api/apidom-parser-adapter-openapi-yaml-3-0 @swagger-api/apidom-parser-adapter-openapi-yaml-3-1 @swagger-api/apidom-parser-adapter-yaml-1-2 @swagger-api/apidom-parser @swagger-api/apidom-reference",
"link:apidom-ls": "npm link @swagger-api/apidom-ls"
},
"dependencies": {
"@asyncapi/avro-schema-parser": "^1.1.0",
"@asyncapi/openapi-schema-parser": "^2.0.1",
"@asyncapi/parser": "^1.17.2",
"@asyncapi/react-component": "^1.0.0-next.44",
"@babel/runtime": "^7.20.6",
"@braintree/sanitize-url": "^6.0.2",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@mui/material": "^5.11.0",
"@primer/octicons-react": "^17.10.0",
"@swagger-api/apidom-core": "^0.58.0",
"@swagger-api/apidom-ls": "^0.58.0",
"@swagger-api/apidom-ns-api-design-systems": "^0.58.0",
"@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.58.0",
"@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.58.0",
"@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.58.0",
"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.58.0",
"@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.58.0",
"@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.58.0",
"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.58.0",
"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.58.0",
"axios": "^1.2.1",
"classnames": "^2.3.2",
"deepmerge": "^4.2.2",
"file-dialog": "^0.0.8",
"immutable": "^3.8.2",
"js-file-download": "^0.4.12",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"monaco-editor": "^0.34.1",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-collapse-pane": "^3.0.1",
"react-dom": "^17.0.2",
"react-dropzone": "^14.2.3",
"react-immutable-proptypes": "^2.2.0",
"react-modal": "^3.16.1",
"react-resize-detector": "^7.1.2",
"react-table": "^7.8.0",
"reselect": "^4.1.7",
"short-unique-id": "^4.4.4",
"styled-components": "^5.3.6",
"swagger-ui-react": "^4.15.5",
"vscode": "npm:@codingame/monaco-vscode-api@~1.69.13",
"vscode-languageclient": "^8.0.2",
"vscode-languageserver-textdocument": "^1.0.8"
},
"devDependencies": {
"@commitlint/cli": "^17.3.0",
"@commitlint/config-conventional": "^17.3.0",
"@testing-library/cypress": "^9.0.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^14.4.3",
"copyfiles": "^2.4.1",
"cross-env": "^7.0.3",
"cypress": "^12.1.0",
"cypress-file-upload": "^5.0.8",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-prettier": "^4.2.1",
"https-browserify": "^1.0.0",
"husky": "^8.0.2",
"jest-canvas-mock": "^2.4.0",
"lint-staged": "^13.1.0",
"prettier": "^2.8.1",
"react-scripts": "file:./create-react-app/packages/react-scripts",
"rimraf": "^3.0.2",
"sass": "^1.57.1",
"serve": "^14.1.2",
"source-map-explorer": "^2.5.3",
"start-server-and-test": "^1.15.2",
"web-vitals": "^3.1.0"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="preload" href="%PUBLIC_URL%/static/media/splash-screen/loader.gif" as="image" type="image/gif" />
<link rel="preload" href="%PUBLIC_URL%/static/media/splash-screen/logo.svg" as="image" type="image/svg+xml" />
<link rel="preload" href="%PUBLIC_URL%/static/media/splash-screen/styles.css" as="style" type="text/css" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="SwaggerEditor"
/>
<link rel="icon" href="%PUBLIC_URL%/favicon-32x32.png" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/favicon-32x32.png" />
<link rel="stylesheet" href="%PUBLIC_URL%/static/media/splash-screen/styles.css" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>SwaggerEditor</title>
<script>
window.MonacoEnvironment = {
baseUrl: new URL('/static/js/', document.baseURI || location.href).toString(),
};
</script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="swagger-editor">
<div class="swagger-editor">
<div class="swagger-editor__splash-screen">
<figure class="swagger-editor__splash-screen-figure">
<img width="100%" src="%PUBLIC_URL%/static/media/splash-screen/logo.svg" alt="Swagger Editor" />
<figcaption>%REACT_APP_VERSION%</figcaption>
<img
width="25"
height="25"
class="swagger-editor__splash-screen-spinner"
src="%PUBLIC_URL%/static/media/splash-screen/loader.gif"
alt="Loading..."
/>
</figure>
</div>
</div>
</div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
@@ -0,0 +1,15 @@
{
"short_name": "SwaggerEditor",
"name": "SwaggerEditor",
"icons": [
{
"src": "favicon-32x32.ico",
"sizes": "32x32",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

@@ -0,0 +1,66 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 536 116">
<defs>
<style>
.cls-1 {
clip-path: url(#clip-SWE_TM-logo-on-dark);
}
.cls-2 {
fill: #fff;
}
.cls-3 {
fill: #85ea2d;
}
.cls-4 {
fill: #173647;
}
</style>
<clipPath id="clip-SWE_TM-logo-on-dark">
<rect width="536" height="116"/>
</clipPath>
</defs>
<g id="SWE_TM-logo-on-dark" class="cls-1">
<g id="SWE_In-Product">
<path id="Path_3002" data-name="Path 3002" class="cls-2" d="M528.911,70.857h-.7V67.176h-1.26v-.6h3.219v.6h-1.26Z"/>
<path id="Path_3003" data-name="Path 3003" class="cls-2" d="M532.979,70.857l-1.242-3.576h-.023q.049.8.05,1.494v2.082h-.636V66.574h.987l1.19,3.408h.017l1.225-3.408h.99v4.283h-.674V68.74q0-.319.016-.832t.028-.621h-.023l-1.286,3.57Z"/>
<path id="Path_3004" data-name="Path 3004" class="cls-3" d="M50.027,97.669A47.642,47.642,0,1,1,97.67,50.027,47.642,47.642,0,0,1,50.027,97.669Z"/>
<path id="Path_3005" data-name="Path 3005" class="cls-3" d="M50.027,4.769A45.258,45.258,0,1,1,4.769,50.027,45.258,45.258,0,0,1,50.027,4.769m0-4.769a50.027,50.027,0,1,0,50.027,50.027A50.027,50.027,0,0,0,50.027,0Z"/>
<path id="Path_3006" data-name="Path 3006" class="cls-4" d="M31.5,33.854c-.154,1.712.058,3.482-.057,5.213a42.665,42.665,0,0,1-.693,5.156,9.532,9.532,0,0,1-4.1,5.829c4.078,2.654,4.539,6.771,4.809,10.946.135,2.25.077,4.52.308,6.752.173,1.731.846,2.174,2.636,2.231.731.02,1.48,0,2.327,0V75.33c-5.29.9-9.657-.6-10.734-5.079a30.76,30.76,0,0,1-.654-5c-.116-1.789.076-3.578-.058-5.367-.385-4.906-1.02-6.56-5.713-6.791v-6.1a9.189,9.189,0,0,1,1.019-.173c2.577-.135,3.674-.924,4.232-3.463a29.573,29.573,0,0,0,.481-4.329,81.809,81.809,0,0,1,.6-8.406c.674-3.982,3.136-5.906,7.234-6.137,1.154-.057,2.327,0,3.655,0v5.464c-.558.038-1.039.115-1.539.115C31.925,29.949,31.751,31.084,31.5,33.854Zm6.407,12.658H37.83a3.515,3.515,0,1,0-.347,7.021h.231a3.461,3.461,0,0,0,3.655-3.251V50.09a3.523,3.523,0,0,0-3.461-3.578Zm12.061,0a3.373,3.373,0,0,0-3.482,3.251,1.79,1.79,0,0,0,.02.327,3.3,3.3,0,0,0,3.578,3.443,3.264,3.264,0,0,0,3.444-3.558,3.309,3.309,0,0,0-3.559-3.463Zm12.351,0a3.592,3.592,0,0,0-3.655,3.482A3.529,3.529,0,0,0,62.2,53.533h.039c1.769.309,3.559-1.4,3.674-3.462a3.571,3.571,0,0,0-3.593-3.559Zm16.948.288c-2.232-.1-3.348-.846-3.9-2.962a21.523,21.523,0,0,1-.635-4.136c-.154-2.578-.135-5.175-.308-7.753-.4-6.117-4.828-8.252-11.254-7.195v5.31c1.019,0,1.808,0,2.6.019,1.366.019,2.4.539,2.539,2.059.136,1.385.136,2.789.27,4.193.269,2.79.423,5.618.9,8.369A8.715,8.715,0,0,0,73.4,50.052c-3.4,2.289-4.4,5.559-4.578,9.234-.1,2.52-.154,5.059-.289,7.6-.115,2.308-.923,3.058-3.251,3.116-.653.019-1.288.077-2.019.115v5.445c1.366,0,2.616.077,3.866,0,3.886-.231,6.233-2.117,7-5.887A48.9,48.9,0,0,0,74.7,63.4c.135-1.923.116-3.866.309-5.771.288-2.982,1.654-4.213,4.635-4.4a4.037,4.037,0,0,0,.828-.192v-6.1c-.5-.058-.844-.115-1.209-.135Z"/>
<path id="Path_3007" data-name="Path 3007" class="cls-2" d="M151.972,58.122a11.231,11.231,0,0,1-4.383,9.425q-4.385,3.381-11.9,3.381-8.14,0-12.523-2.1V63.7a32.95,32.95,0,0,0,6.137,1.879,32.279,32.279,0,0,0,6.574.689q5.323,0,8.015-2.02a6.629,6.629,0,0,0,2.693-5.62,7.216,7.216,0,0,0-.955-3.9,8.868,8.868,0,0,0-3.194-2.8,44.614,44.614,0,0,0-6.809-2.911q-6.388-2.286-9.127-5.417a11.959,11.959,0,0,1-2.739-8.171A10.164,10.164,0,0,1,127.739,27q3.976-3.131,10.52-3.131a31,31,0,0,1,12.555,2.5L149.154,31a28.377,28.377,0,0,0-11.02-2.38,10.665,10.665,0,0,0-6.607,1.816,5.985,5.985,0,0,0-2.379,5.041,7.733,7.733,0,0,0,.876,3.9,8.259,8.259,0,0,0,2.959,2.786,36.732,36.732,0,0,0,6.371,2.8q7.2,2.568,9.91,5.509a10.843,10.843,0,0,1,2.708,7.647Z"/>
<path id="Path_3008" data-name="Path 3008" class="cls-2" d="M184.988,70.3,178.7,50.17q-.6-1.848-2.223-8.391h-.25q-1.254,5.479-2.192,8.453L167.549,70.3h-6.012l-9.361-34.316h5.448q3.318,12.932,5.056,19.694a79.655,79.655,0,0,1,1.988,9.111h.251q.343-1.784,1.111-4.618t1.331-4.493l6.293-19.694h5.635l6.137,19.694a66.551,66.551,0,0,1,2.38,9.049h.25a33.338,33.338,0,0,1,.673-3.476q.547-2.347,6.528-25.267h5.385L191.156,70.3Z"/>
<path id="Path_3009" data-name="Path 3009" class="cls-2" d="M224.815,70.3l-1.033-4.885h-.251a14.446,14.446,0,0,1-5.119,4.368,15.6,15.6,0,0,1-6.372,1.143q-5.1,0-8-2.63t-2.9-7.484q0-10.394,16.625-10.894l5.824-.189V47.6q0-4.04-1.738-5.964T216.3,39.713a22.644,22.644,0,0,0-9.706,2.63L205,38.366a24.492,24.492,0,0,1,5.558-2.16,24.094,24.094,0,0,1,6.058-.782q6.137,0,9.1,2.723t2.959,8.736V70.3Zm-11.741-3.663a10.548,10.548,0,0,0,7.624-2.662,9.846,9.846,0,0,0,2.771-7.452v-3.1l-5.2.219q-6.2.219-8.939,1.925a5.81,5.81,0,0,0-2.739,5.307,5.357,5.357,0,0,0,1.706,4.29,7.082,7.082,0,0,0,4.777,1.475Z"/>
<path id="Path_3010" data-name="Path 3010" class="cls-2" d="M264.3,35.986v3.288l-6.356.751a11.175,11.175,0,0,1,2.254,6.858,10.144,10.144,0,0,1-3.444,8.046q-3.444,3.006-9.455,3.006a15.655,15.655,0,0,1-2.881-.251Q241.1,59.439,241.1,62.1a2.243,2.243,0,0,0,1.158,2.082,8.459,8.459,0,0,0,3.976.673h6.074q5.572,0,8.563,2.348a8.159,8.159,0,0,1,2.99,6.825,9.742,9.742,0,0,1-4.571,8.688q-4.57,2.991-13.337,2.99-6.732,0-10.379-2.5a8.088,8.088,0,0,1-3.648-7.076,7.943,7.943,0,0,1,2-5.416,10.209,10.209,0,0,1,5.635-3.1,5.435,5.435,0,0,1-2.207-1.847,4.887,4.887,0,0,1-.892-2.912,5.524,5.524,0,0,1,1-3.287,10.517,10.517,0,0,1,3.162-2.724,9.266,9.266,0,0,1-4.336-3.726,10.949,10.949,0,0,1-1.675-6.011q0-5.635,3.381-8.689t9.581-3.053a17.449,17.449,0,0,1,4.853.626ZM236.932,76.063a4.658,4.658,0,0,0,2.349,4.226,12.969,12.969,0,0,0,6.731,1.44q6.543,0,9.691-1.956a5.992,5.992,0,0,0,3.146-5.307q0-2.788-1.722-3.867t-6.481-1.08h-6.231a8.207,8.207,0,0,0-5.51,1.69,6.044,6.044,0,0,0-1.973,4.854Zm2.818-29.086a6.985,6.985,0,0,0,2.036,5.447,8.121,8.121,0,0,0,5.667,1.847q7.607,0,7.607-7.388,0-7.734-7.7-7.735a7.628,7.628,0,0,0-5.635,1.973q-1.974,1.979-1.975,5.856Z"/>
<path id="Path_3011" data-name="Path 3011" class="cls-2" d="M298.835,35.986v3.288l-6.356.751a11.166,11.166,0,0,1,2.255,6.858,10.147,10.147,0,0,1-3.444,8.046q-3.444,3.006-9.456,3.006a15.644,15.644,0,0,1-2.88-.251q-3.32,1.755-3.319,4.415a2.242,2.242,0,0,0,1.159,2.082,8.456,8.456,0,0,0,3.976.673h6.074q5.573,0,8.563,2.348a8.159,8.159,0,0,1,2.99,6.825,9.742,9.742,0,0,1-4.571,8.688q-4.572,2.991-13.338,2.99-6.732,0-10.379-2.5a8.087,8.087,0,0,1-3.647-7.076,7.942,7.942,0,0,1,2-5.416,10.212,10.212,0,0,1,5.636-3.1,5.429,5.429,0,0,1-2.207-1.847A4.887,4.887,0,0,1,271,62.85a5.524,5.524,0,0,1,1-3.287,10.517,10.517,0,0,1,3.162-2.724,9.275,9.275,0,0,1-4.336-3.726,10.949,10.949,0,0,1-1.675-6.011q0-5.635,3.382-8.689t9.58-3.053a17.439,17.439,0,0,1,4.853.626ZM271.471,76.063a4.659,4.659,0,0,0,2.348,4.226,12.973,12.973,0,0,0,6.732,1.44q6.543,0,9.69-1.956a5.991,5.991,0,0,0,3.147-5.307q0-2.788-1.723-3.867t-6.481-1.08h-6.23a8.2,8.2,0,0,0-5.51,1.69A6.044,6.044,0,0,0,271.471,76.063Zm2.818-29.086a6.985,6.985,0,0,0,2.035,5.447,8.123,8.123,0,0,0,5.667,1.847q7.608,0,7.608-7.388,0-7.734-7.7-7.735a7.628,7.628,0,0,0-5.635,1.973q-1.976,1.979-1.975,5.856Z"/>
<path id="Path_3012" data-name="Path 3012" class="cls-2" d="M316.477,70.928q-7.606,0-12.006-4.634t-4.4-12.868q0-8.3,4.086-13.181A13.567,13.567,0,0,1,315.13,35.36a12.94,12.94,0,0,1,10.208,4.24q3.762,4.246,3.762,11.2v3.288H305.457q.156,6.042,3.052,9.173t8.156,3.131a27.629,27.629,0,0,0,10.958-2.317v4.634a27.541,27.541,0,0,1-5.212,1.706,29.262,29.262,0,0,1-5.934.513Zm-1.408-31.215a8.488,8.488,0,0,0-6.591,2.692,12.41,12.41,0,0,0-2.9,7.451h17.94q0-4.914-2.192-7.529a7.712,7.712,0,0,0-6.257-2.614Z"/>
<path id="Path_3013" data-name="Path 3013" class="cls-2" d="M350.6,35.36a20.372,20.372,0,0,1,4.1.376l-.72,4.822a17.72,17.72,0,0,0-3.757-.47A9.144,9.144,0,0,0,343.1,43.47a12.326,12.326,0,0,0-2.959,8.422V70.3h-5.2V35.986h4.289l.6,6.357h.251a15.069,15.069,0,0,1,4.6-5.166A10.366,10.366,0,0,1,350.6,35.36Z"/>
<path id="Path_3014" data-name="Path 3014" class="cls-2" d="M394.454,70.3H368.937V24.527h25.517v4.729H374.26V44h18.973v4.7H374.26V65.543h20.194Z"/>
<path id="Path_3015" data-name="Path 3015" class="cls-2" d="M423.683,65.7H423.4q-3.6,5.231-10.77,5.229-6.734,0-10.473-4.6t-3.742-13.087q0-8.484,3.757-13.181t10.458-4.7q6.981,0,10.707,5.073h.407l-.219-2.474-.125-2.41V21.585h5.2V70.3h-4.227Zm-10.394.877q5.322,0,7.718-2.9t2.395-9.346v-1.1q0-7.294-2.427-10.41t-7.749-3.115a7.953,7.953,0,0,0-7,3.553Q403.8,46.821,403.8,53.3q0,6.574,2.41,9.925a8.166,8.166,0,0,0,7.079,3.351Z"/>
<path id="Path_3016" data-name="Path 3016" class="cls-2" d="M435.918,26.688a3.449,3.449,0,0,1,.877-2.614,3.243,3.243,0,0,1,4.351.016,3.385,3.385,0,0,1,.909,2.6,3.442,3.442,0,0,1-.909,2.615,3.182,3.182,0,0,1-4.351,0,3.515,3.515,0,0,1-.877-2.617ZM441.554,70.3h-5.2V35.986h5.2Z"/>
<path id="Path_3017" data-name="Path 3017" class="cls-2" d="M461.26,66.639a17.07,17.07,0,0,0,2.661-.2,17.339,17.339,0,0,0,2.035-.423v3.976a9.508,9.508,0,0,1-2.489.674,18.741,18.741,0,0,1-2.959.266q-9.955,0-9.956-10.489V40.025h-4.915v-2.5l4.915-2.161,2.191-7.326h3.006V35.99h9.956v4.039h-9.956v20.2a6.943,6.943,0,0,0,1.472,4.759,5.117,5.117,0,0,0,4.039,1.651Z"/>
<path id="Path_3018" data-name="Path 3018" class="cls-2" d="M499.014,53.113q0,8.391-4.227,13.1t-11.68,4.712a15.478,15.478,0,0,1-8.171-2.16,14.264,14.264,0,0,1-5.51-6.2,21.6,21.6,0,0,1-1.941-9.455q0-8.389,4.2-13.072t11.647-4.681q7.2,0,11.443,4.79T499.014,53.113Zm-26.144,0q0,6.575,2.63,10.019t7.732,3.444q5.1,0,7.75-3.429t2.645-10.034q0-6.543-2.645-9.941t-7.812-3.4q-5.1,0-7.7,3.35T472.87,53.113Z"/>
<path id="Path_3019" data-name="Path 3019" class="cls-2" d="M520.726,35.36a20.376,20.376,0,0,1,4.1.376l-.721,4.822a17.712,17.712,0,0,0-3.757-.47,9.145,9.145,0,0,0-7.123,3.382,12.335,12.335,0,0,0-2.958,8.422V70.3h-5.2V35.986h4.289l.6,6.357h.251a15.078,15.078,0,0,1,4.6-5.166A10.368,10.368,0,0,1,520.726,35.36Z"/>
<path id="Path_3020" data-name="Path 3020" class="cls-2" d="M255.556,96.638s-3.43-.391-4.85-.391c-2.058,0-3.111.735-3.111,2.18,0,1.568.882,1.935,3.748,2.719,3.527.98,4.8,1.911,4.8,4.777,0,3.675-2.3,5.267-5.61,5.267a35.667,35.667,0,0,1-5.486-.662l.269-2.18s3.307.441,5.046.441c2.082,0,3.037-.931,3.037-2.7,0-1.421-.759-1.91-3.331-2.523-3.626-.93-5.193-2.033-5.193-4.948,0-3.381,2.229-4.776,5.585-4.776a37.222,37.222,0,0,1,5.316.587Z"/>
<path id="Path_3021" data-name="Path 3021" class="cls-2" d="M262.666,94.14h4.728l3.748,13.106L274.89,94.14h4.752v16.78H276.9V96.42h-.144l-4.192,13.816h-2.841L265.53,96.418h-.145v14.5h-2.719Z"/>
<path id="Path_3022" data-name="Path 3022" class="cls-2" d="M321.756,94.14H334v2.425h-4.728V110.92h-2.743V96.565h-4.777Z"/>
<path id="Path_3023" data-name="Path 3023" class="cls-2" d="M345.837,94.14c3.331,0,5.119,1.249,5.119,4.361,0,2.033-.636,3.037-1.984,3.772,1.445.563,2.4,1.592,2.4,3.9,0,3.43-2.082,4.752-5.34,4.752h-6.566V94.14Zm-3.651,2.352v4.8h3.6c1.667,0,2.4-.832,2.4-2.474,0-1.617-.833-2.327-2.5-2.327Zm0,7.1v4.973h3.7c1.689,0,2.694-.539,2.694-2.548,0-1.911-1.421-2.425-2.743-2.425Z"/>
<path id="Path_3024" data-name="Path 3024" class="cls-2" d="M358.113,94.14H368.7v2.377h-7.864v4.751h6.394V103.6h-6.394v4.924H368.7v2.4H358.113Z"/>
<path id="Path_3025" data-name="Path 3025" class="cls-2" d="M378.446,94.14h5.414l4.164,16.78h-2.743l-1.24-4.92h-5.777l-1.239,4.923h-2.719Zm.362,9.456h4.707l-1.737-7.178h-1.225Z"/>
<path id="Path_3026" data-name="Path 3026" class="cls-2" d="M396.8,105.947v4.973h-2.72V94.14h6.37c3.7,0,5.683,2.12,5.683,5.843,0,2.376-.956,4.519-2.744,5.352l2.769,5.585h-2.989l-2.425-4.973Zm3.65-9.455H396.8v7.1h3.7c2.058,0,2.841-1.85,2.841-3.589-.005-1.9-.935-3.511-2.895-3.511Z"/>
<path id="Path_3027" data-name="Path 3027" class="cls-2" d="M289.712,94.14h5.413l4.165,16.78h-2.744L295.307,106H289.53l-1.239,4.923h-2.719Zm.361,9.456h4.707l-1.737-7.178h-1.224Z"/>
<path id="Path_3028" data-name="Path 3028" class="cls-2" d="M308.061,105.947v4.973h-2.719V94.14h6.369c3.7,0,5.683,2.12,5.683,5.843,0,2.376-.955,4.519-2.743,5.352l2.768,5.585h-2.988l-2.426-4.973Zm3.65-9.455h-3.65v7.1h3.7c2.057,0,2.841-1.85,2.841-3.589C314.6,98.1,313.671,96.492,311.711,96.492Z"/>
<path id="Path_3029" data-name="Path 3029" class="cls-2" d="M130.306,107.644a3.021,3.021,0,0,1-1.18,2.536,5.115,5.115,0,0,1-3.2.91,8.009,8.009,0,0,1-3.371-.565v-1.381a8.932,8.932,0,0,0,1.651.5,8.672,8.672,0,0,0,1.77.186,3.57,3.57,0,0,0,2.158-.544,1.782,1.782,0,0,0,.724-1.512,1.943,1.943,0,0,0-.257-1.049,2.382,2.382,0,0,0-.859-.755,12.173,12.173,0,0,0-1.833-.784,5.853,5.853,0,0,1-2.457-1.458,3.218,3.218,0,0,1-.737-2.2,2.734,2.734,0,0,1,1.07-2.266,4.44,4.44,0,0,1,2.832-.844,8.337,8.337,0,0,1,3.379.675l-.447,1.247a7.635,7.635,0,0,0-2.966-.641,2.877,2.877,0,0,0-1.778.489,1.613,1.613,0,0,0-.641,1.357,2.078,2.078,0,0,0,.236,1.049,2.218,2.218,0,0,0,.8.75,9.873,9.873,0,0,0,1.715.755,6.77,6.77,0,0,1,2.667,1.483,2.914,2.914,0,0,1,.724,2.062Z"/>
<path id="Path_3030" data-name="Path 3030" class="cls-2" d="M134.147,101.686v5.992a2.41,2.41,0,0,0,.514,1.685,2.091,2.091,0,0,0,1.609.556,2.627,2.627,0,0,0,2.12-.792,4,4,0,0,0,.67-2.587v-4.854h1.4v9.236H139.3l-.2-1.238h-.076a2.8,2.8,0,0,1-1.192,1.045,4.019,4.019,0,0,1-1.74.361,3.527,3.527,0,0,1-2.524-.8,3.408,3.408,0,0,1-.839-2.561v-6.043Z"/>
<path id="Path_3031" data-name="Path 3031" class="cls-2" d="M147.906,111.09a4,4,0,0,1-1.648-.332,3.113,3.113,0,0,1-1.251-1.024h-.1a12.458,12.458,0,0,1,.1,1.534v3.8h-1.4V101.686h1.137l.194,1.263h.068a3.244,3.244,0,0,1,1.256-1.094,3.81,3.81,0,0,1,1.643-.337,3.414,3.414,0,0,1,2.836,1.255,6.686,6.686,0,0,1-.018,7.057,3.417,3.417,0,0,1-2.817,1.26Zm-.2-8.385a2.48,2.48,0,0,0-2.047.784,4.03,4.03,0,0,0-.649,2.494v.312a4.616,4.616,0,0,0,.649,2.785,2.464,2.464,0,0,0,2.081.839,2.162,2.162,0,0,0,1.875-.97,4.588,4.588,0,0,0,.679-2.67,4.423,4.423,0,0,0-.679-2.65,2.232,2.232,0,0,0-1.915-.924Z"/>
<path id="Path_3032" data-name="Path 3032" class="cls-2" d="M158.739,111.09a4,4,0,0,1-1.648-.332,3.113,3.113,0,0,1-1.251-1.024h-.1a12.461,12.461,0,0,1,.1,1.534v3.8h-1.4V101.686h1.137l.194,1.263h.068a3.244,3.244,0,0,1,1.256-1.094,3.81,3.81,0,0,1,1.643-.337,3.414,3.414,0,0,1,2.836,1.255,6.686,6.686,0,0,1-.018,7.057,3.417,3.417,0,0,1-2.817,1.26Zm-.2-8.385a2.48,2.48,0,0,0-2.048.784,4.03,4.03,0,0,0-.649,2.494v.312a4.616,4.616,0,0,0,.649,2.785,2.464,2.464,0,0,0,2.081.839,2.162,2.162,0,0,0,1.875-.97,4.588,4.588,0,0,0,.679-2.67,4.423,4.423,0,0,0-.679-2.65,2.231,2.231,0,0,0-1.91-.924Z"/>
<path id="Path_3033" data-name="Path 3033" class="cls-2" d="M173.312,106.3a5.092,5.092,0,0,1-1.138,3.527,4,4,0,0,1-3.143,1.268,4.172,4.172,0,0,1-2.2-.581,3.843,3.843,0,0,1-1.482-1.669,5.8,5.8,0,0,1-.523-2.545,5.087,5.087,0,0,1,1.129-3.518,4,4,0,0,1,3.135-1.259,3.9,3.9,0,0,1,3.08,1.289A5.067,5.067,0,0,1,173.312,106.3Zm-7.037,0a4.384,4.384,0,0,0,.708,2.7,2.809,2.809,0,0,0,4.167,0,4.36,4.36,0,0,0,.713-2.7,4.294,4.294,0,0,0-.713-2.676,2.5,2.5,0,0,0-2.1-.914,2.462,2.462,0,0,0-2.073.9A4.344,4.344,0,0,0,166.275,106.3Z"/>
<path id="Path_3034" data-name="Path 3034" class="cls-2" d="M180.224,101.518a5.5,5.5,0,0,1,1.1.1l-.193,1.3a4.8,4.8,0,0,0-1.012-.127,2.467,2.467,0,0,0-1.917.91,3.324,3.324,0,0,0-.8,2.268v4.955H176v-9.236h1.154l.161,1.71h.067a4.056,4.056,0,0,1,1.239-1.39,2.786,2.786,0,0,1,1.6-.49Z"/>
<path id="Path_3035" data-name="Path 3035" class="cls-2" d="M187.062,109.936a4.53,4.53,0,0,0,.717-.055,4.647,4.647,0,0,0,.548-.113v1.07a2.613,2.613,0,0,1-.67.181,5.124,5.124,0,0,1-.8.071q-2.679,0-2.679-2.822v-5.5h-1.324V102.1l1.324-.581.589-1.973h.809v2.141h2.68v1.087h-2.68v5.436a1.868,1.868,0,0,0,.4,1.28,1.378,1.378,0,0,0,1.086.446Z"/>
<path id="Path_3036" data-name="Path 3036" class="cls-2" d="M194.238,111.09a4.243,4.243,0,0,1-3.232-1.246,4.833,4.833,0,0,1-1.184-3.464,5.352,5.352,0,0,1,1.1-3.548,3.651,3.651,0,0,1,2.953-1.314,3.48,3.48,0,0,1,2.747,1.141,4.374,4.374,0,0,1,1.012,3.013v.885h-6.363a3.665,3.665,0,0,0,.822,2.468,2.839,2.839,0,0,0,2.2.844,7.453,7.453,0,0,0,2.95-.624v1.247a7.377,7.377,0,0,1-1.4.459,7.875,7.875,0,0,1-1.6.139Zm-.379-8.4a2.282,2.282,0,0,0-1.774.726,3.329,3.329,0,0,0-.78,2h4.829a3.073,3.073,0,0,0-.59-2.026,2.077,2.077,0,0,0-1.685-.7Z"/>
<path id="Path_3037" data-name="Path 3037" class="cls-2" d="M206.65,109.684h-.075a3.289,3.289,0,0,1-2.9,1.406,3.428,3.428,0,0,1-2.819-1.238,5.452,5.452,0,0,1-1.007-3.523,5.548,5.548,0,0,1,1.011-3.548,3.4,3.4,0,0,1,2.815-1.263,3.359,3.359,0,0,1,2.882,1.365h.109l-.059-.666-.033-.649V97.81h1.4v13.112h-1.138Zm-2.8.235a2.55,2.55,0,0,0,2.077-.779,3.94,3.94,0,0,0,.645-2.516v-.3a4.638,4.638,0,0,0-.653-2.8,2.485,2.485,0,0,0-2.086-.839,2.142,2.142,0,0,0-1.883.957,4.754,4.754,0,0,0-.654,2.7,4.57,4.57,0,0,0,.649,2.672,2.2,2.2,0,0,0,1.908.905Z"/>
<path id="Path_3038" data-name="Path 3038" class="cls-2" d="M220.411,101.534a3.437,3.437,0,0,1,2.828,1.243,6.659,6.659,0,0,1-.009,7.053,3.42,3.42,0,0,1-2.819,1.26,3.993,3.993,0,0,1-1.647-.332,3.109,3.109,0,0,1-1.252-1.024h-.1l-.295,1.188h-1V97.81h1.4v3.184q0,1.073-.067,1.922h.067a3.32,3.32,0,0,1,2.894-1.382Zm-.2,1.171a2.446,2.446,0,0,0-2.065.822,6.338,6.338,0,0,0,.017,5.553,2.466,2.466,0,0,0,2.082.839,2.16,2.16,0,0,0,1.921-.939,4.832,4.832,0,0,0,.632-2.7,4.645,4.645,0,0,0-.632-2.689,2.239,2.239,0,0,0-1.957-.886Z"/>
<path id="Path_3039" data-name="Path 3039" class="cls-2" d="M225.458,101.686h1.5l2.022,5.267a20.027,20.027,0,0,1,.826,2.6h.067q.11-.431.46-1.471t2.287-6.4h1.5L230.152,112.2a5.256,5.256,0,0,1-1.378,2.212,2.933,2.933,0,0,1-1.934.653,5.645,5.645,0,0,1-1.264-.143V113.8a4.9,4.9,0,0,0,1.036.1,2.137,2.137,0,0,0,2.056-1.618l.514-1.314Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

@@ -0,0 +1,30 @@
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
}
.swagger-editor .swagger-editor__splash-screen {
position: absolute;
z-index: 10000;
background-color: #173647;
width: 100vw;
height: 100vh;
text-align: center;
}
.swagger-editor .swagger-editor__splash-screen-figure {
position: relative;
top: calc(50% - 126px);
width: 15vw;
display: inline-block;
color: lightslategrey;
font-size: 0.8rem;
font-weight: bold;
}
.swagger-editor .swagger-editor__splash-screen-spinner {
padding-top: 20px;
}
@@ -0,0 +1,802 @@
openapi: 3.0.2
info:
title: CI Example - Swagger Petstore - OpenAPI 3.0
description: "This is a sample Pet Store Server based on the OpenAPI 3.0 specification.\
\ You can find out more about\nSwagger at [http://swagger.io](http://swagger.io).\
\ In the third iteration of the pet store, we've switched to the design first\
\ approach!\nYou can now help us improve the API whether it's by making changes\
\ to the definition itself or to the code.\nThat way, with time, we can improve\
\ the API in general, and expose some of the new features in OAS3.\n\nSome useful\
\ links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n\
- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)"
termsOfService: http://swagger.io/terms/
contact:
email: apiteam@swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.6
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: /api/v3
tags:
- name: pet
description: Everything about your Pets
externalDocs:
description: Find out more
url: http://swagger.io
- name: store
description: Operations about user
- name: user
description: Access to Petstore orders
externalDocs:
description: Find out more about our store
url: http://swagger.io
paths:
/pet:
put:
tags:
- pet
summary: Update an existing pet
description: Update an existing pet by Id
operationId: updatePet
requestBody:
description: Update an existent pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
"200":
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid ID supplied
"404":
description: Pet not found
"405":
description: Validation exception
security:
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
requestBody:
description: Create a new pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
"200":
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
"405":
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: false
explode: true
schema:
type: string
default: available
enum:
- available
- pending
- sold
responses:
"200":
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid status value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: "Multiple tags can be provided with comma separated strings. Use\
\ tag1, tag2, tag3 for testing."
operationId: findPetsByTags
parameters:
- name: tags
in: query
description: Tags to filter by
required: false
explode: true
schema:
type: array
items:
type: string
responses:
"200":
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid tag value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}:
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
"200":
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid ID supplied
"404":
description: Pet not found
security:
- api_key: []
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ""
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: integer
format: int64
- name: name
in: query
description: Name of pet that needs to be updated
schema:
type: string
- name: status
in: query
description: Status of pet that needs to be updated
schema:
type: string
responses:
"405":
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
delete:
tags:
- pet
summary: Deletes a pet
description: ""
operationId: deletePet
parameters:
- name: api_key
in: header
description: ""
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
"400":
description: Invalid pet value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}/uploadImage:
post:
tags:
- pet
summary: uploads an image
description: ""
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
- name: additionalMetadata
in: query
description: Additional Metadata
required: false
schema:
type: string
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
security:
- petstore_auth:
- write:pets
- read:pets
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
responses:
"200":
description: successful operation
content:
application/json:
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: Place a new order in the store
operationId: placeOrder
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Order'
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
"405":
description: Invalid input
/store/order/{orderId}:
get:
tags:
- store
summary: Find purchase order by ID
description: For valid response try integer IDs with value <= 5 or > 10. Other
values will generated exceptions
operationId: getOrderById
parameters:
- name: orderId
in: path
description: ID of order that needs to be fetched
required: true
schema:
type: integer
format: int64
responses:
"200":
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/json:
schema:
$ref: '#/components/schemas/Order'
"400":
description: Invalid ID supplied
"404":
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: For valid response try integer IDs with value < 1000. Anything
above 1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
schema:
type: integer
format: int64
responses:
"400":
description: Invalid ID supplied
"404":
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
requestBody:
description: Created user object
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: Creates list of users with given input array
operationId: createUsersWithListInput
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
responses:
"200":
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/User'
application/json:
schema:
$ref: '#/components/schemas/User'
default:
description: successful operation
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ""
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: false
schema:
type: string
- name: password
in: query
description: The password for login in clear text
required: false
schema:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
description: date in UTC when token expires
schema:
type: string
format: date-time
content:
application/xml:
schema:
type: string
application/json:
schema:
type: string
"400":
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ""
operationId: logoutUser
parameters: []
responses:
default:
description: successful operation
/user/{username}:
get:
tags:
- user
summary: Get user by user name
description: ""
operationId: getUserByName
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing. '
required: true
schema:
type: string
responses:
"200":
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/User'
application/json:
schema:
$ref: '#/components/schemas/User'
"400":
description: Invalid username supplied
"404":
description: User not found
put:
tags:
- user
summary: Update user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
schema:
type: string
requestBody:
description: Update an existent user in the store
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
"400":
description: Invalid username supplied
"404":
description: User not found
components:
schemas:
Order:
type: object
properties:
id:
type: integer
format: int64
example: 10
petId:
type: integer
format: int64
example: 198772
quantity:
type: integer
format: int32
example: 7
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
example: approved
enum:
- placed
- approved
- delivered
complete:
type: boolean
xml:
name: order
Customer:
type: object
properties:
id:
type: integer
format: int64
example: 100000
username:
type: string
example: fehguy
address:
type: array
xml:
name: addresses
wrapped: true
items:
$ref: '#/components/schemas/Address'
xml:
name: customer
Address:
type: object
properties:
street:
type: string
example: 437 Lytton
city:
type: string
example: Palo Alto
state:
type: string
example: CA
zip:
type: string
example: "94301"
xml:
name: address
Category:
type: object
properties:
id:
type: integer
format: int64
example: 1
name:
type: string
example: Dogs
xml:
name: category
User:
type: object
properties:
id:
type: integer
format: int64
example: 10
username:
type: string
example: theUser
firstName:
type: string
example: John
lastName:
type: string
example: James
email:
type: string
example: john@email.com
password:
type: string
example: "12345"
phone:
type: string
example: "12345"
userStatus:
type: integer
description: User Status
format: int32
example: 1
xml:
name: user
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: tag
Pet:
required:
- name
- photoUrls
type: object
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
$ref: '#/components/schemas/Category'
photoUrls:
type: array
xml:
wrapped: true
items:
type: string
xml:
name: photoUrl
tags:
type: array
xml:
wrapped: true
items:
$ref: '#/components/schemas/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: pet
ApiResponse:
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
xml:
name: '##default'
requestBodies:
Pet:
description: Pet object that needs to be added to the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
UserArray:
description: List of user object
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
securitySchemes:
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
scopes:
write:pets: modify pets in your account
read:pets: read your pets
api_key:
type: apiKey
name: api_key
in: header
File diff suppressed because it is too large Load Diff
+138
View File
@@ -0,0 +1,138 @@
import React from 'react';
import deepmerge from 'deepmerge';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
import './styles/main.scss';
import LayoutPlugin from './plugins/layout/index.js';
import SplashScreenPlugin from './plugins/splash-screen/index.js';
import TopBarPlugin from './plugins/top-bar/index.js';
import ModalsPlugin from './plugins/modals/index.js';
import DialogsPlugin from './plugins/dialogs/index.js';
import DropdownMenuPlugin from './plugins/dropdown-menu/index.js';
import DropzonePlugin from './plugins/dropzone/index.js';
import VersionsPlugin from './plugins/versions/index.js';
import EditorTextareaPlugin from './plugins/editor-textarea/index.js';
import EditorMonacoPlugin from './plugins/editor-monaco/index.js';
import EditorPreviewPlugin from './plugins/editor-preview/index.js';
import EditorPreviewSwaggerUIPlugin from './plugins/editor-preview-swagger-ui/index.js';
import EditorPreviewAsyncAPIPlugin from './plugins/editor-preview-asyncapi/index.js';
import EditorPreviewApiDesignSystemsPlugin from './plugins/editor-preview-api-design-systems/index.js';
import EditorContentReadOnlyPlugin from './plugins/editor-content-read-only/index.js';
import EditorContentOriginPlugin from './plugins/editor-content-origin/index.js';
import EditorContentTypePlugin from './plugins/editor-content-type/index.js';
import EditorContentPersistencePlugin from './plugins/editor-content-persistence/index.js';
import EditorContentFixturesPlugin from './plugins/editor-content-fixtures/index.js';
import EditorContentJumpFromPathToLinePlugin from './plugins/editor-content-jump-from-path-to-line/index.js';
import SwaggerUIAdapterPlugin from './plugins/swagger-ui-adapter/index.js';
const SafeRenderPlugin = (system) =>
SwaggerUI.plugins.SafeRender({
componentList: [
'TopBar',
'SwaggerEditorLayout',
'Editor',
'EditorTextarea',
'EditorMonaco',
'EditorPane',
'EditorPaneBarTop',
'EditorPreviewPane',
'ValidationPane',
'AlertDialog',
'ConfirmDialog',
'Dropzone',
],
})(system);
const SwaggerEditor = React.memo((props) => {
const mergedProps = deepmerge(SwaggerEditor.defaultProps, props);
return (
<div className="swagger-editor">
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<SwaggerUI {...mergedProps} />
</div>
);
});
SwaggerEditor.plugins = {
Modals: ModalsPlugin,
Dialogs: DialogsPlugin,
DropdownMenu: DropdownMenuPlugin,
Dropzone: DropzonePlugin,
Versions: VersionsPlugin,
EditorTextarea: EditorTextareaPlugin,
EditorMonaco: EditorMonacoPlugin,
EditorContentReadOnly: EditorContentReadOnlyPlugin,
EditorContentOrigin: EditorContentOriginPlugin,
EditorContentType: EditorContentTypePlugin,
EditorContentPersistence: EditorContentPersistencePlugin,
EditorContentFixtures: EditorContentFixturesPlugin,
EditorContentJumpFromPathToLine: EditorContentJumpFromPathToLinePlugin,
EditorPreview: EditorPreviewPlugin,
EditorPreviewSwaggerUI: EditorPreviewSwaggerUIPlugin,
EditorPreviewAsyncAPI: EditorPreviewAsyncAPIPlugin,
EditorPreviewApiDesignSystems: EditorPreviewApiDesignSystemsPlugin,
TopBar: TopBarPlugin,
SplashScreenPlugin,
Layout: LayoutPlugin,
SwaggerUIAdapter: SwaggerUIAdapterPlugin,
};
SwaggerEditor.presets = {
textarea: () => [
ModalsPlugin,
DialogsPlugin,
DropdownMenuPlugin,
DropzonePlugin,
VersionsPlugin,
EditorTextareaPlugin,
EditorContentReadOnlyPlugin,
EditorContentOriginPlugin,
EditorContentTypePlugin,
EditorContentPersistencePlugin,
EditorContentFixturesPlugin,
EditorContentJumpFromPathToLinePlugin,
EditorPreviewPlugin,
EditorPreviewSwaggerUIPlugin,
EditorPreviewAsyncAPIPlugin,
EditorPreviewApiDesignSystemsPlugin,
TopBarPlugin,
SplashScreenPlugin,
LayoutPlugin,
SafeRenderPlugin,
],
monaco: () => [
ModalsPlugin,
DialogsPlugin,
DropdownMenuPlugin,
DropzonePlugin,
VersionsPlugin,
EditorTextareaPlugin,
EditorMonacoPlugin,
EditorContentReadOnlyPlugin,
EditorContentOriginPlugin,
EditorContentTypePlugin,
EditorContentPersistencePlugin,
EditorContentFixturesPlugin,
EditorContentJumpFromPathToLinePlugin,
EditorPreviewPlugin,
EditorPreviewSwaggerUIPlugin,
EditorPreviewAsyncAPIPlugin,
EditorPreviewApiDesignSystemsPlugin,
TopBarPlugin,
SplashScreenPlugin,
LayoutPlugin,
SafeRenderPlugin,
],
default: (...args) => SwaggerEditor.presets.monaco(...args),
};
SwaggerEditor.propTypes = SwaggerUI.propTypes;
SwaggerEditor.defaultProps = {
...SwaggerUI.defaultProps,
layout: 'SwaggerEditorLayout',
presets: [SwaggerEditor.presets.default],
};
export default SwaggerEditor;
+11
View File
@@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import 'swagger-ui-react/swagger-ui.css';
import SwaggerEditor from './App.jsx';
const url = process.env.REACT_APP_DEFINITION_FILE
? `${process.env.PUBLIC_URL}${process.env.REACT_APP_DEFINITION_FILE}`
: process.env.REACT_APP_DEFINITION_URL;
ReactDOM.render(<SwaggerEditor url={url} />, document.getElementById('swagger-editor'));
@@ -0,0 +1,44 @@
import PropTypes from 'prop-types';
import React from 'react';
const AlertDialog = ({ isOpen, title, getComponent, children, onClose }) => {
const Modal = getComponent('Modal');
const ModalHeader = getComponent('ModalHeader');
const ModalTitle = getComponent('ModalTitle');
const ModalBody = getComponent('ModalBody');
const ModalFooter = getComponent('ModalFooter');
return (
<Modal isOpen={isOpen} contentLabel={title}>
<ModalHeader>
<button type="button" className="close" onClick={onClose}>
<span aria-hidden="true">x</span>
</button>
<ModalTitle>{title}</ModalTitle>
</ModalHeader>
<ModalBody>{children}</ModalBody>
<ModalFooter>
<button type="button" className="btn btn-primary" onClick={onClose}>
OK
</button>
</ModalFooter>
</Modal>
);
};
AlertDialog.propTypes = {
isOpen: PropTypes.bool,
title: PropTypes.string,
getComponent: PropTypes.func.isRequired,
children: PropTypes.node,
onClose: PropTypes.func,
};
AlertDialog.defaultProps = {
isOpen: false,
title: '',
children: null,
onClose: () => {},
};
export default AlertDialog;
@@ -0,0 +1,57 @@
import PropTypes from 'prop-types';
import React from 'react';
const ConfirmDialog = ({ isOpen, title, getComponent, children, onClose }) => {
const Modal = getComponent('Modal');
const ModalHeader = getComponent('ModalHeader');
const ModalTitle = getComponent('ModalTitle');
const ModalBody = getComponent('ModalBody');
const ModalFooter = getComponent('ModalFooter');
const handleOKClick = () => {
onClose(true);
};
const handleCancelClick = () => {
onClose(false);
};
const handleCloseClick = () => {
onClose(false);
};
return (
<Modal isOpen={isOpen} contentLabel={title}>
<ModalHeader>
<button type="button" className="close" onClick={handleCloseClick}>
<span aria-hidden="true">x</span>
</button>
<ModalTitle>{title}</ModalTitle>
</ModalHeader>
<ModalBody>{children}</ModalBody>
<ModalFooter>
<button type="button" className="btn btn-secondary" onClick={handleCancelClick}>
Cancel
</button>
<button type="button" className="btn btn-primary" onClick={handleOKClick}>
OK
</button>
</ModalFooter>
</Modal>
);
};
ConfirmDialog.propTypes = {
isOpen: PropTypes.bool,
title: PropTypes.string,
getComponent: PropTypes.func.isRequired,
children: PropTypes.node,
onClose: PropTypes.func,
};
ConfirmDialog.defaultProps = {
isOpen: false,
title: '',
children: null,
onClose: () => {},
};
export default ConfirmDialog;
@@ -0,0 +1,20 @@
/**
* Dialogs inform users about a task and can contain critical information,
* require decisions, or involve multiple tasks.
*
* A Dialog is a type of modal window that appears in front of app content to provide
* critical information or ask for a decision. Dialogs disable all app functionality when they appear,
* and remain on screen until confirmed, dismissed, or a required action has been taken. *
*/
import AlertDialog from './components/AlertDialog.jsx';
import ConfirmDialog from './components/ConfirmDialog.jsx';
const DialogsPlugin = () => ({
components: {
AlertDialog,
ConfirmDialog,
},
});
export default DialogsPlugin;
@@ -0,0 +1,67 @@
import React, { useState, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
/* eslint-disable jsx-a11y/click-events-have-key-events */
const DropdownMenu = ({ children, label, isLong }) => {
const ref = useRef(null);
const [isOpen, setIsOpen] = useState(false);
const handleClickOutside = (event) => {
if (ref.current !== null && !ref.current.contains(event.target)) {
setIsOpen(false);
}
};
const handleToggleClick = () => {
setIsOpen(!isOpen);
};
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
return (
<div className={classNames('dd-menu dd-menu-left', { long: isLong })} ref={ref}>
<span
className="menu-item"
role="button"
tabIndex={0}
aria-haspopup="true"
aria-expanded={isOpen}
onClick={handleToggleClick}
>
{label}
</span>
{isOpen && (
<div
className="dd-menu-items"
aria-labelledby="Dropdown"
onClick={handleToggleClick}
role="menu"
tabIndex={0}
>
<ul className="dd-items-left">{children}</ul>
</div>
)}
</div>
);
};
DropdownMenu.propTypes = {
label: PropTypes.string.isRequired,
children: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
isLong: PropTypes.bool,
};
DropdownMenu.defaultProps = {
children: [],
isLong: false,
};
export default DropdownMenu;
@@ -0,0 +1,415 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 Mikkel Laursen
* SPDX-License-Identifier: MIT
*/
/* Not really sure why, but the inverse version has a bigger gap */
/* line 42, ../src/scss/_mixins.scss */
.grow-from-left-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
transition: -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8), -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
}
/* line 47, ../src/scss/_mixins.scss */
.grow-from-left-enter.grow-from-left-enter-active {
-webkit-transform: scale(1);
transform: scale(1);
}
/* line 52, ../src/scss/_mixins.scss */
.grow-from-left-leave {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out;
}
/* line 57, ../src/scss/_mixins.scss */
.grow-from-left-leave.grow-from-left-leave-active {
-webkit-transform: scale(0);
transform: scale(0);
}
/* line 42, ../src/scss/_mixins.scss */
.grow-from-right-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 100% 0;
transform-origin: 100% 0;
transition: -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8), -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
}
/* line 47, ../src/scss/_mixins.scss */
.grow-from-right-enter.grow-from-right-enter-active {
-webkit-transform: scale(1);
transform: scale(1);
}
/* line 52, ../src/scss/_mixins.scss */
.grow-from-right-leave {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 100% 0;
transform-origin: 100% 0;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out;
}
/* line 57, ../src/scss/_mixins.scss */
.grow-from-right-leave.grow-from-right-leave-active {
-webkit-transform: scale(0);
transform: scale(0);
}
/* line 42, ../src/scss/_mixins.scss */
.grow-from-center-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 50% 0;
transform-origin: 50% 0;
transition: -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8), -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
}
/* line 47, ../src/scss/_mixins.scss */
.grow-from-center-enter.grow-from-center-enter-active {
-webkit-transform: scale(1);
transform: scale(1);
}
/* line 52, ../src/scss/_mixins.scss */
.grow-from-center-leave {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 50% 0;
transform-origin: 50% 0;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out;
}
/* line 57, ../src/scss/_mixins.scss */
.grow-from-center-leave.grow-from-center-leave-active {
-webkit-transform: scale(0);
transform: scale(0);
}
/* line 42, ../src/scss/_mixins.scss */
.grow-from-up-left-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
transition: -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8), -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
}
/* line 47, ../src/scss/_mixins.scss */
.grow-from-up-left-enter.grow-from-up-left-enter-active {
-webkit-transform: scale(1);
transform: scale(1);
}
/* line 52, ../src/scss/_mixins.scss */
.grow-from-up-left-leave {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out;
}
/* line 57, ../src/scss/_mixins.scss */
.grow-from-up-left-leave.grow-from-up-left-leave-active {
-webkit-transform: scale(0);
transform: scale(0);
}
/* line 42, ../src/scss/_mixins.scss */
.grow-from-up-center-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 50% 100%;
transform-origin: 50% 100%;
transition: -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8), -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
}
/* line 47, ../src/scss/_mixins.scss */
.grow-from-up-center-enter.grow-from-up-center-enter-active {
-webkit-transform: scale(1);
transform: scale(1);
}
/* line 52, ../src/scss/_mixins.scss */
.grow-from-up-center-leave {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 50% 100%;
transform-origin: 50% 100%;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out;
}
/* line 57, ../src/scss/_mixins.scss */
.grow-from-up-center-leave.grow-from-up-center-leave-active {
-webkit-transform: scale(0);
transform: scale(0);
}
/* line 42, ../src/scss/_mixins.scss */
.grow-from-up-right-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 100% 100%;
transform-origin: 100% 100%;
transition: -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
transition: transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8), -webkit-transform 0.15s cubic-bezier(0.5, 1.8, 0.9, 0.8);
}
/* line 47, ../src/scss/_mixins.scss */
.grow-from-up-right-enter.grow-from-up-right-enter-active {
-webkit-transform: scale(1);
transform: scale(1);
}
/* line 52, ../src/scss/_mixins.scss */
.grow-from-up-right-leave {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 100% 100%;
transform-origin: 100% 100%;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out;
}
/* line 57, ../src/scss/_mixins.scss */
.grow-from-up-right-leave.grow-from-up-right-leave-active {
-webkit-transform: scale(0);
transform: scale(0);
}
/* line 2, ../src/scss/_dd-menu.scss */
.dd-menu {
display: inline-block;
position: relative;
}
/* line 6, ../src/scss/_dd-menu.scss */
.dd-menu.dd-menu-center .dd-menu-items {
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
/* line 18, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-left .dd-menu-items {
left: 0;
}
/* line 5, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-left .dd-menu-items [class^='nested-']:not(.nested-reverse) > span {
right: 100%;
padding-right: 0.5em;
}
/* line 10, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-left .dd-menu-items .nested-reverse > span {
left: 100%;
padding-left: 0.5em;
}
/* line 5, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-left.dd-menu-inverse .dd-menu-items [class^='nested-']:not(.nested-reverse) > span {
right: 100%;
padding-right: 0.3em;
}
/* line 10, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-left.dd-menu-inverse .dd-menu-items .nested-reverse > span {
left: 100%;
padding-left: 0.3em;
}
/* line 18, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-right .dd-menu-items {
right: 0;
}
/* line 5, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-right .dd-menu-items [class^='nested-']:not(.nested-reverse) > span {
left: 100%;
padding-left: 0.5em;
}
/* line 10, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-right .dd-menu-items .nested-reverse > span {
right: 100%;
padding-right: 0.5em;
}
/* line 5, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-right.dd-menu-inverse .dd-menu-items [class^='nested-']:not(.nested-reverse) > span {
left: 100%;
padding-left: 0.3em;
}
/* line 10, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-right.dd-menu-inverse .dd-menu-items .nested-reverse > span {
right: 100%;
padding-right: 0.3em;
}
/* line 30, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-sm .dd-menu-items {
width: 150px;
}
/* line 30, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-md .dd-menu-items {
width: 300px;
}
/* line 30, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-lg .dd-menu-items {
width: 450px;
}
/* line 30, ../src/scss/_mixins.scss */
.dd-menu.dd-menu-xl .dd-menu-items {
width: 600px;
}
/* line 15, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items {
position: absolute;
z-index: 12;
margin: 0.5em 0 0 0;
}
/* line 20, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items.dd-items-upwards {
bottom: 100%;
margin: 0 0 0.5em;
}
/* line 25, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul, .dd-menu .dd-menu-items ol {
list-style: none;
padding: 0;
margin: 0;
color: #000;
background-color: #fefefe;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.29);
}
/* line 34, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul.dd-items-right li > *, .dd-menu .dd-menu-items ol.dd-items-right li > * {
text-align: right;
}
/* line 38, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul.dd-items-left li > *, .dd-menu .dd-menu-items ol.dd-items-left li > * {
text-align: left;
}
/* line 42, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul.dd-items-center li > *, .dd-menu .dd-menu-items ol.dd-items-center li > * {
text-align: center;
}
/* line 48, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul li:hover:not([role="separator"]):not(.separator),
.dd-menu .dd-menu-items ul li > *:focus, .dd-menu .dd-menu-items ol li:hover:not([role="separator"]):not(.separator),
.dd-menu .dd-menu-items ol li > *:focus {
color: #000;
background-color: #bdc3c7;
outline: none;
}
/* line 55, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul li > *:not(.dd-item-ignore), .dd-menu .dd-menu-items ol li > *:not(.dd-item-ignore) {
display: block;
width: auto;
min-width: 100%;
padding: 1em 1.5em;
font-family: Roboto, sans-serif;
white-space: pre;
color: inherit;
text-decoration: none;
font-size: inherit;
}
/* line 68, ../src/scss/_dd-menu.scss */
.dd-menu .dd-menu-items ul li > button, .dd-menu .dd-menu-items ol li > button {
border: none;
background: transparent;
}
/* line 78, ../src/scss/_dd-menu.scss */
.dd-menu.dd-menu-inverse .dd-menu-items ul, .dd-menu.dd-menu-inverse .dd-menu-items ol {
color: #fff;
background-color: #2c3e50;
}
/* line 84, ../src/scss/_dd-menu.scss */
.dd-menu.dd-menu-inverse .dd-menu-items ul li:hover:not([role="separator"]):not(.separator),
.dd-menu.dd-menu-inverse .dd-menu-items ul li > *:focus, .dd-menu.dd-menu-inverse .dd-menu-items ol li:hover:not([role="separator"]):not(.separator),
.dd-menu.dd-menu-inverse .dd-menu-items ol li > *:focus {
color: #fff;
background-color: #34495e;
}
/* line 93, ../src/scss/_dd-menu.scss */
.dd-menu.dd-menu-inverse [role="separator"], .dd-menu.dd-menu-inverse .separator {
background-color: #45595e;
}
/* line 98, ../src/scss/_dd-menu.scss */
.dd-menu [role="separator"], .dd-menu .separator {
content: '';
display: block;
height: 2px;
background-color: rgba(0, 0, 0, 0.15);
margin: 0.5em 0 0.5em 0;
}
/* line 107, ../src/scss/_dd-menu.scss */
.dd-menu .dd-items-upwards li.nested-dd-menu > span {
bottom: 0;
top: initial;
}
/* line 113, ../src/scss/_dd-menu.scss */
.dd-menu li.nested-dd-menu {
position: relative;
}
/* line 116, ../src/scss/_dd-menu.scss */
.dd-menu li.nested-dd-menu > span {
position: absolute;
top: 0;
}
.dd-menu {
&.long {
display: flex;
flex-wrap: wrap;
max-width: 800px;
.dd-menu-items {
width: 700px;
.dd-items-left {
display: flex;
flex-direction: column;
max-height: 500px;
flex-wrap: wrap;
margin: 1.7rem 0 0!important;
li {
flex:22%;
}
}
}
.long-menu-message {
padding: 1.5rem;
color: #ccc;
cursor: pointer;
}
.dropdown-item button {
font-size: 0.8rem !important;
}
}
.dd-menu-items {
margin: 1.1rem 0 0 0 !important;
ol,ul {
border-radius:0 0 4px 4px;
li {
&:last-of-type {
&:hover {
border-radius:0 0 4px 4px;
}
}
font-size: 0.9rem;
}
}
}
}
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
const DropdownMenuItem = ({ children, onClick }) => {
return (
<div>
<li className="dropdown-item">
<button type="button" onClick={onClick}>
{children}
</button>
</li>
</div>
);
};
DropdownMenuItem.propTypes = {
children: PropTypes.node.isRequired,
onClick: PropTypes.func.isRequired,
};
export default DropdownMenuItem;
@@ -0,0 +1,13 @@
.swagger-editor {
& .menu-item {
cursor: pointer;
font-size: 0.95rem;
&::after {
content: '';
margin-left: 6px;
font-size: 0.5rem;
}
}
}
@@ -0,0 +1,3 @@
const DropdownMenuItemDivider = () => <li role="separator" />;
export default DropdownMenuItemDivider;
@@ -0,0 +1,40 @@
import { useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
const DropdownMenuNested = ({ children, label, isLong }) => {
const [isOpen, setIsOpen] = useState(false);
const handleOpen = () => {
setIsOpen(true);
};
const handleClose = () => {
setIsOpen(false);
};
return (
<li
className={classNames('nested-dd-menu nested-reverse', { long: isLong })}
onMouseEnter={handleOpen}
onMouseLeave={handleClose}
>
<button type="button">
{label}&nbsp;&nbsp;<b>&gt;</b>
</button>
<span className="dd-item-ignore">{isOpen && <ul>{children}</ul>}</span>
</li>
);
};
DropdownMenuNested.propTypes = {
label: PropTypes.string.isRequired,
children: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
isLong: PropTypes.bool,
};
DropdownMenuNested.defaultProps = {
children: [],
isLong: false,
};
export default DropdownMenuNested;
@@ -0,0 +1,7 @@
.dd-menu {
.dd-item-ignore {
ol, ul {
border-radius:4px 4px 4px 4px;
}
}
}
@@ -0,0 +1,3 @@
@import './DropdownMenu/dropdown-menu';
@import './DropdownMenuItem/dropdown-menu-item';
@import './DropdownMenuNested/dropdown-menu-nested';
@@ -0,0 +1,15 @@
import DropdownMenu from './components/DropdownMenu/DropdownMenu.jsx';
import DropdownMenuNested from './components/DropdownMenuNested/DropdownMenuNested.jsx';
import DropdownMenuItem from './components/DropdownMenuItem/DropdownMenuItem.jsx';
import DropdownMenuItemDivider from './components/DropdownMenuItemDivider.jsx';
const DropdownMenuPlugin = () => ({
components: {
DropdownMenu,
DropdownMenuNested,
DropdownMenuItem,
DropdownMenuItemDivider,
},
});
export default DropdownMenuPlugin;
@@ -0,0 +1,47 @@
/* eslint-disable react/jsx-props-no-spreading */
import React from 'react';
import PropTypes from 'prop-types';
const Dropzone = ({ getComponent, useDropzone, children }) => {
const AlertDialog = getComponent('AlertDialog', true);
const [
isDragActive,
isAlertDialogOpen,
setIsAlertDialogOpen,
errorMessage,
getRootProps,
getInputProps,
] = useDropzone();
const handleAlertDialogClose = () => {
setIsAlertDialogOpen(false);
};
return (
<div className="dropzone" {...getRootProps()}>
<AlertDialog
isOpen={isAlertDialogOpen}
title="Uh oh, an error has occurred"
onClose={handleAlertDialogClose}
>
{errorMessage}
</AlertDialog>
<input data-cy="dropzone" {...getInputProps()} />
{isDragActive ? (
<div className="dropzone__overlay">
Please drop an OpenAPI 2.0/3.0/3.1 or AsyncApi 2.x definition in .yaml or .json format.
</div>
) : (
children
)}
</div>
);
};
Dropzone.propTypes = {
getComponent: PropTypes.func.isRequired,
useDropzone: PropTypes.func.isRequired,
children: PropTypes.node.isRequired,
};
export default Dropzone;
@@ -0,0 +1,48 @@
import { useCallback, useState } from 'react';
import { useDropzone as useVendorDropzone } from 'react-dropzone';
// eslint-disable-next-line import/prefer-default-export
export const makeUseDropzone = (getSystem) => () => {
const { editorActions } = getSystem();
const [isAlertDialogOpen, setIsAlertDialogOpen] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const handleFileDrop = useCallback(
async (acceptedFiles, rejectedFiles) => {
const someFilesWereRejected = rejectedFiles && rejectedFiles.length > 0;
const thereIsExactlyOneAcceptedFile = acceptedFiles && acceptedFiles.length === 1;
try {
if (someFilesWereRejected || !thereIsExactlyOneAcceptedFile) {
const dropFileErrMessage = `Sorry, there was an error processing your file.\nPlease drag and drop exactly one file.`;
setErrorMessage(dropFileErrMessage);
setIsAlertDialogOpen(true);
} else {
const file = acceptedFiles[0];
const content = await file.text();
editorActions.setContent(content, 'file-drop');
}
} catch (error) {
const importedFileErrMessage = `Sorry, there was an error processing your file. Unable to process as valid YAML or JSON `;
setErrorMessage(importedFileErrMessage);
setIsAlertDialogOpen(true);
}
},
[editorActions, setErrorMessage, setIsAlertDialogOpen]
);
const { getRootProps, getInputProps, isDragActive } = useVendorDropzone({
onDrop: handleFileDrop,
multiple: false,
noClick: true,
});
return [
isDragActive,
isAlertDialogOpen,
setIsAlertDialogOpen,
errorMessage,
getRootProps,
getInputProps,
];
};
@@ -0,0 +1,13 @@
import Dropzone from './components/Dropzone.jsx';
import { makeUseDropzone } from './hooks.js';
const DropzonePlugin = ({ getSystem }) => ({
rootInjects: {
useDropzone: makeUseDropzone(getSystem),
},
components: {
Dropzone,
},
});
export default DropzonePlugin;
@@ -0,0 +1,802 @@
openapi: 3.0.2
info:
title: CI Example - Swagger Petstore - OpenAPI 3.0
description: "This is a sample Pet Store Server based on the OpenAPI 3.0 specification.\
\ You can find out more about\nSwagger at [http://swagger.io](http://swagger.io).\
\ In the third iteration of the pet store, we've switched to the design first\
\ approach!\nYou can now help us improve the API whether it's by making changes\
\ to the definition itself or to the code.\nThat way, with time, we can improve\
\ the API in general, and expose some of the new features in OAS3.\n\nSome useful\
\ links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n\
- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)"
termsOfService: http://swagger.io/terms/
contact:
email: apiteam@swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.6
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: /api/v3
tags:
- name: pet
description: Everything about your Pets
externalDocs:
description: Find out more
url: http://swagger.io
- name: store
description: Operations about user
- name: user
description: Access to Petstore orders
externalDocs:
description: Find out more about our store
url: http://swagger.io
paths:
/pet:
put:
tags:
- pet
summary: Update an existing pet
description: Update an existing pet by Id
operationId: updatePet
requestBody:
description: Update an existent pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
"200":
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid ID supplied
"404":
description: Pet not found
"405":
description: Validation exception
security:
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
requestBody:
description: Create a new pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
"200":
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
"405":
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: false
explode: true
schema:
type: string
default: available
enum:
- available
- pending
- sold
responses:
"200":
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid status value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: "Multiple tags can be provided with comma separated strings. Use\
\ tag1, tag2, tag3 for testing."
operationId: findPetsByTags
parameters:
- name: tags
in: query
description: Tags to filter by
required: false
explode: true
schema:
type: array
items:
type: string
responses:
"200":
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid tag value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}:
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
"200":
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
"400":
description: Invalid ID supplied
"404":
description: Pet not found
security:
- api_key: []
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ""
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: integer
format: int64
- name: name
in: query
description: Name of pet that needs to be updated
schema:
type: string
- name: status
in: query
description: Status of pet that needs to be updated
schema:
type: string
responses:
"405":
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
delete:
tags:
- pet
summary: Deletes a pet
description: ""
operationId: deletePet
parameters:
- name: api_key
in: header
description: ""
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
"400":
description: Invalid pet value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}/uploadImage:
post:
tags:
- pet
summary: uploads an image
description: ""
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
- name: additionalMetadata
in: query
description: Additional Metadata
required: false
schema:
type: string
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
security:
- petstore_auth:
- write:pets
- read:pets
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
responses:
"200":
description: successful operation
content:
application/json:
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: Place a new order in the store
operationId: placeOrder
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Order'
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
"405":
description: Invalid input
/store/order/{orderId}:
get:
tags:
- store
summary: Find purchase order by ID
description: For valid response try integer IDs with value <= 5 or > 10. Other
values will generated exceptions
operationId: getOrderById
parameters:
- name: orderId
in: path
description: ID of order that needs to be fetched
required: true
schema:
type: integer
format: int64
responses:
"200":
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/json:
schema:
$ref: '#/components/schemas/Order'
"400":
description: Invalid ID supplied
"404":
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: For valid response try integer IDs with value < 1000. Anything
above 1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
schema:
type: integer
format: int64
responses:
"400":
description: Invalid ID supplied
"404":
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
requestBody:
description: Created user object
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: Creates list of users with given input array
operationId: createUsersWithListInput
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
responses:
"200":
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/User'
application/json:
schema:
$ref: '#/components/schemas/User'
default:
description: successful operation
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ""
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: false
schema:
type: string
- name: password
in: query
description: The password for login in clear text
required: false
schema:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
description: date in UTC when token expires
schema:
type: string
format: date-time
content:
application/xml:
schema:
type: string
application/json:
schema:
type: string
"400":
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ""
operationId: logoutUser
parameters: []
responses:
default:
description: successful operation
/user/{username}:
get:
tags:
- user
summary: Get user by user name
description: ""
operationId: getUserByName
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing. '
required: true
schema:
type: string
responses:
"200":
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/User'
application/json:
schema:
$ref: '#/components/schemas/User'
"400":
description: Invalid username supplied
"404":
description: User not found
put:
tags:
- user
summary: Update user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
schema:
type: string
requestBody:
description: Update an existent user in the store
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
"400":
description: Invalid username supplied
"404":
description: User not found
components:
schemas:
Order:
type: object
properties:
id:
type: integer
format: int64
example: 10
petId:
type: integer
format: int64
example: 198772
quantity:
type: integer
format: int32
example: 7
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
example: approved
enum:
- placed
- approved
- delivered
complete:
type: boolean
xml:
name: order
Customer:
type: object
properties:
id:
type: integer
format: int64
example: 100000
username:
type: string
example: fehguy
address:
type: array
xml:
name: addresses
wrapped: true
items:
$ref: '#/components/schemas/Address'
xml:
name: customer
Address:
type: object
properties:
street:
type: string
example: 437 Lytton
city:
type: string
example: Palo Alto
state:
type: string
example: CA
zip:
type: string
example: "94301"
xml:
name: address
Category:
type: object
properties:
id:
type: integer
format: int64
example: 1
name:
type: string
example: Dogs
xml:
name: category
User:
type: object
properties:
id:
type: integer
format: int64
example: 10
username:
type: string
example: theUser
firstName:
type: string
example: John
lastName:
type: string
example: James
email:
type: string
example: john@email.com
password:
type: string
example: "12345"
phone:
type: string
example: "12345"
userStatus:
type: integer
description: User Status
format: int32
example: 1
xml:
name: user
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: tag
Pet:
required:
- name
- photoUrls
type: object
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
$ref: '#/components/schemas/Category'
photoUrls:
type: array
xml:
wrapped: true
items:
type: string
xml:
name: photoUrl
tags:
type: array
xml:
wrapped: true
items:
$ref: '#/components/schemas/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: pet
ApiResponse:
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
xml:
name: '##default'
requestBodies:
Pet:
description: Pet object that needs to be added to the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
UserArray:
description: List of user object
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
securitySchemes:
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
scopes:
write:pets: modify pets in your account
read:pets: read your pets
api_key:
type: apiKey
name: api_key
in: header
@@ -0,0 +1,24 @@
import selectOpenAPI310PetstoreYAML from './selectors/selectOpenAPI310PetstoreYAML.js';
import selectOpenAPI303PetstoreYAML from './selectors/selectOpenAPI303PetstoreYAML.js';
import selectOpenAPI20PetstoreYAML from './selectors/selectOpenAPI20PetstoreYAML.js';
import selectAsyncAPI250PetstoreYAML from './selectors/selectAsyncAPI250PetstoreYAML.js';
import selectAsyncAPI250StreetlightsYAML from './selectors/selectAsyncAPI250StreetlightsYAML.js';
import selectAPIDesignSystemsYAML from './selectors/selectAPIDesignSystemsYAML.js';
// test
const EditorContentFixturesPlugin = () => ({
statePlugins: {
editorContentFixtures: {
selectors: {
selectOpenAPI310PetstoreYAML,
selectOpenAPI303PetstoreYAML,
selectOpenAPI20PetstoreYAML,
selectAsyncAPI250PetstoreYAML,
selectAsyncAPI250StreetlightsYAML,
selectAPIDesignSystemsYAML,
},
},
},
});
export default EditorContentFixturesPlugin;
@@ -0,0 +1,257 @@
const selectAPIDesignSystemsYAML = () => `version: '2021-05-07'
info:
title: SmartBear API Guidelines
description: |
A machine and human readable version of the SmartBear API Style Guide aimed at promoting living API Style Governance across various tools and teams, leading to improved API quality.
See the [SmartBear Standards and Guidelines](https://github.com/SmartBear/api-standards-and-guidelines) repo for a traditional view of the static guidelines.
principles:
- iri: urn:apidesign.systems:principle:robustness
level: must
- iri: urn:apidesign.systems:principle:rmm:level2
level: must
- iri: urn:apidesign.systems:principle:rmm:level3
level: should
standards:
- iri: urn:ietf:rfc:6648
level: must
- iri: urn:ietf:rfc:7807
level: must
- iri: urn:ietf:rfc:7231
level: should
- iri: urn:ietf:rfc:6585
level: may
- iri: urn:ietf:rfc:5788
level: may
- iri: urn:ietf:draft:http-semantics
level: may
scenarios:
- description: SB-API-010 - Only apply standard HTTP methods
when:
- http
- transaction
then:
- subject:
- http
- request
- method
level: may
values:
- get
- post
- put
- patch
- delete
- subject:
- http
- request
- header
level: may
values:
- Accept
- Accept-Charset
- Authorization
- Content-Language
- Content-Type
- Link
- Prefer
- subject:
- http
- request
- header
- Content-Type
level: may
values:
- application/json
- application/hal+json
- subject:
- http
- response
- header
- Content-Type
level: should
values:
- application/hal+json
- subject:
- http
- response
- header
- Content-Type
level: may
values:
- application/json
- application/hal+json
- application/problem+json
- description: GET Methods - Allowed status codes
when:
- http
- request
- method
- get
then:
- subject:
- http
- response
- status_code
level: may
values:
- '200'
- '304'
- '400'
- '401'
- '403'
- '404'
- '405'
- '422'
- '429'
- '500'
- '501'
- '503'
- description: POST Method - Allowed status codes
when:
- http
- request
- method
- post
then:
- subject:
- http
- response
- status_code
level: may
values:
- '200'
- '201'
- '202'
- '400'
- '401'
- '403'
- '404'
- '405'
- '409'
- '415'
- '422'
- '429'
- '500'
- '501'
- '503'
- description: PUT Method - Allowed status codes
when:
- http
- request
- method
- put
then:
- subject:
- http
- response
- status_code
level: may
values:
- '200'
- '201'
- '202'
- '204'
- '400'
- '401'
- '403'
- '404'
- '405'
- '409'
- '412'
- '415'
- '422'
- '429'
- '500'
- '501'
- '503'
- description: PATCH Method - Allowed status codes
when:
- http
- request
- method
- patch
then:
- subject:
- http
- response
- status_code
level: may
values:
- '200'
- '202'
- '204'
- '400'
- '401'
- '403'
- '404'
- '405'
- '409'
- '412'
- '415'
- '422'
- '429'
- '500'
- '501'
- '503'
- description: DELETE Method - Allowed status codes
when:
- http
- request
- method
- delete
then:
- subject:
- http
- response
- status_code
level: may
values:
- '200'
- '202'
- '204'
- '400'
- '401'
- '403'
- '404'
- '405'
- '409'
- '412'
- '415'
- '422'
- '429'
- '500'
- '501'
- '503'
- description: Client Errors must return \`application/problem+json\`
when:
- http
- response
- status_code
- client_error
then:
- subject:
- http
- response
- header
- Content-Type
level: must
values:
- application/problem+json
- description: Server Errors must return \`application/problem+json\`
when:
- http
- response
- status_code
- server_error
then:
- subject:
- http
- response
- header
- Content-Type
level: must
values:
- application/problem+json
`;
export default selectAPIDesignSystemsYAML;
@@ -0,0 +1,225 @@
const selectAsyncAPI250PetstoreYAML = () => `asyncapi: 2.5.0
info:
title: Petstore
version: 1.0.0
description: The PetStore running in Kafka
channels:
petstore.order.added:
publish:
message:
title: New order for pet
summary: A new order for a pet was added.
name: Order
contentType: application/json
payload:
"$ref": "#/components/schemas/Order"
petstore.order.deleted:
publish:
message:
name: OrderId
contentType: application/json
payload:
type: integer
format: int64
petstore.pet.added:
publish:
message:
name: Pet
contentType: application/json
payload:
"$ref": "#/components/schemas/Pet"
petstore.pet.changed:
publish:
message:
name: Pet
contentType: application/json
payload:
"$ref": "#/components/schemas/Pet"
petstore.pet.deleted:
publish:
message:
name: PetId
contentType: application/json
payload:
type: integer
format: int64
components:
schemas:
Inventory:
type: object
additionalProperties:
type: integer
format: int64
Order:
type: object
properties:
id:
type: integer
format: int64
example: 10
petId:
type: integer
format: int64
example: 198772
quantity:
type: integer
format: int32
example: 7
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
example: approved
enum:
- placed
- approved
- delivered
complete:
type: boolean
xml:
name: order
Customer:
type: object
properties:
id:
type: integer
format: int64
example: 100000
username:
type: string
example: fehguy
address:
type: array
xml:
name: addresses
wrapped: true
items:
"$ref": "#/components/schemas/Address"
xml:
name: customer
Address:
type: object
properties:
street:
type: string
example: 437 Lytton
city:
type: string
example: Palo Alto
state:
type: string
example: CA
zip:
type: string
example: '94301'
xml:
name: address
Category:
type: object
properties:
id:
type: integer
format: int64
example: 1
name:
type: string
example: Dogs
xml:
name: category
User:
type: object
properties:
id:
type: integer
format: int64
example: 10
username:
type: string
example: theUser
firstName:
type: string
example: John
lastName:
type: string
example: James
email:
type: string
example: john@email.com
password:
type: string
example: '12345'
phone:
type: string
example: '12345'
userStatus:
type: integer
description: User Status
format: int32
example: 1
xml:
name: user
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: tag
Pet:
required:
- name
- photoUrls
type: object
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
"$ref": "#/components/schemas/Category"
photoUrls:
type: array
xml:
wrapped: true
items:
type: string
xml:
name: photoUrl
tags:
type: array
xml:
wrapped: true
items:
"$ref": "#/components/schemas/Tag"
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: pet
ApiResponse:
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
xml:
name: "##default"
`;
export default selectAsyncAPI250PetstoreYAML;
@@ -0,0 +1,191 @@
const selectAsyncAPI250StreetlightsYAML = () => `asyncapi: '2.5.0'
info:
title: Streetlights Kafka API
version: '1.0.0'
description: |
The Smartylighting Streetlights API allows you to remotely manage the city lights.
### Check out its awesome features:
* Turn a specific streetlight on/off 🌃
* Dim a specific streetlight 😎
* Receive real-time information about environmental lighting conditions 📈
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
servers:
scram-connections:
url: test.mykafkacluster.org:18092
protocol: kafka-secure
description: Test broker secured with scramSha256
security:
- saslScram: []
tags:
- name: "env:test-scram"
description: "This environment is meant for running internal tests through scramSha256"
- name: "kind:remote"
description: "This server is a remote server. Not exposed by the application"
- name: "visibility:private"
description: "This resource is private and only available to certain users"
mtls-connections:
url: test.mykafkacluster.org:28092
protocol: kafka-secure
description: Test broker secured with X509
security:
- certs: []
tags:
- name: "env:test-mtls"
description: "This environment is meant for running internal tests through mtls"
- name: "kind:remote"
description: "This server is a remote server. Not exposed by the application"
- name: "visibility:private"
description: "This resource is private and only available to certain users"
defaultContentType: application/json
channels:
smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured:
description: The topic on which measured values may be produced and consumed.
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
publish:
summary: Inform about environmental lighting conditions of a particular streetlight.
operationId: receiveLightMeasurement
traits:
- $ref: '#/components/operationTraits/kafka'
message:
$ref: '#/components/messages/lightMeasured'
smartylighting.streetlights.1.0.action.{streetlightId}.turn.on:
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
subscribe:
operationId: turnOn
traits:
- $ref: '#/components/operationTraits/kafka'
message:
$ref: '#/components/messages/turnOnOff'
smartylighting.streetlights.1.0.action.{streetlightId}.turn.off:
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
subscribe:
operationId: turnOff
traits:
- $ref: '#/components/operationTraits/kafka'
message:
$ref: '#/components/messages/turnOnOff'
smartylighting.streetlights.1.0.action.{streetlightId}.dim:
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
subscribe:
operationId: dimLight
traits:
- $ref: '#/components/operationTraits/kafka'
message:
$ref: '#/components/messages/dimLight'
components:
messages:
lightMeasured:
name: lightMeasured
title: Light measured
summary: Inform about environmental lighting conditions of a particular streetlight.
contentType: application/json
traits:
- $ref: '#/components/messageTraits/commonHeaders'
payload:
$ref: "#/components/schemas/lightMeasuredPayload"
turnOnOff:
name: turnOnOff
title: Turn on/off
summary: Command a particular streetlight to turn the lights on or off.
traits:
- $ref: '#/components/messageTraits/commonHeaders'
payload:
$ref: "#/components/schemas/turnOnOffPayload"
dimLight:
name: dimLight
title: Dim light
summary: Command a particular streetlight to dim the lights.
traits:
- $ref: '#/components/messageTraits/commonHeaders'
payload:
$ref: "#/components/schemas/dimLightPayload"
schemas:
lightMeasuredPayload:
type: object
properties:
lumens:
type: integer
minimum: 0
description: Light intensity measured in lumens.
sentAt:
$ref: "#/components/schemas/sentAt"
turnOnOffPayload:
type: object
properties:
command:
type: string
enum:
- on
- off
description: Whether to turn on or off the light.
sentAt:
$ref: "#/components/schemas/sentAt"
dimLightPayload:
type: object
properties:
percentage:
type: integer
description: Percentage to which the light should be dimmed to.
minimum: 0
maximum: 100
sentAt:
$ref: "#/components/schemas/sentAt"
sentAt:
type: string
format: date-time
description: Date and time when the message was sent.
securitySchemes:
saslScram:
type: scramSha256
description: Provide your username and password for SASL/SCRAM authentication
certs:
type: X509
description: Download the certificate files from service provider
parameters:
streetlightId:
description: The ID of the streetlight.
schema:
type: string
messageTraits:
commonHeaders:
headers:
type: object
properties:
my-app-header:
type: integer
minimum: 0
maximum: 100
operationTraits:
kafka:
bindings:
kafka:
clientId:
type: string
enum: ['my-app-id']
`;
export default selectAsyncAPI250StreetlightsYAML;
@@ -0,0 +1,708 @@
const selectOpenAPI20PetstoreYAML = () => `swagger: "2.0"
info:
description: "This is a sample server Petstore server. You can find out more about\
\\ Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).\
\\ For this sample, you can use the api key \`special-key\` to test the authorization\
\\ filters."
version: "1.0.0"
title: "Swagger Petstore 2.0"
termsOfService: "http://swagger.io/terms/"
contact:
email: "apiteam@swagger.io"
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
host: "petstore.swagger.io"
basePath: "/v2"
tags:
- name: "pet"
description: "Everything about your Pets"
externalDocs:
description: "Find out more"
url: "http://swagger.io"
- name: "store"
description: "Access to Petstore orders"
- name: "user"
description: "Operations about user"
externalDocs:
description: "Find out more about our store"
url: "http://swagger.io"
schemes:
- "https"
- "http"
paths:
/pet:
post:
tags:
- "pet"
summary: "Add a new pet to the store"
description: ""
operationId: "addPet"
consumes:
- "application/json"
- "application/xml"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Pet object that needs to be added to the store"
required: true
schema:
$ref: "#/definitions/Pet"
responses:
"405":
description: "Invalid input"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
put:
tags:
- "pet"
summary: "Update an existing pet"
description: ""
operationId: "updatePet"
consumes:
- "application/json"
- "application/xml"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Pet object that needs to be added to the store"
required: true
schema:
$ref: "#/definitions/Pet"
responses:
"400":
description: "Invalid ID supplied"
"404":
description: "Pet not found"
"405":
description: "Validation exception"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/pet/findByStatus:
get:
tags:
- "pet"
summary: "Finds Pets by status"
description: "Multiple status values can be provided with comma separated strings"
operationId: "findPetsByStatus"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "status"
in: "query"
description: "Status values that need to be considered for filter"
required: true
type: "array"
items:
type: "string"
enum:
- "available"
- "pending"
- "sold"
default: "available"
collectionFormat: "multi"
responses:
"200":
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Pet"
"400":
description: "Invalid status value"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/pet/findByTags:
get:
tags:
- "pet"
summary: "Finds Pets by tags"
description: "Muliple tags can be provided with comma separated strings. Use\
\\ tag1, tag2, tag3 for testing."
operationId: "findPetsByTags"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "tags"
in: "query"
description: "Tags to filter by"
required: true
type: "array"
items:
type: "string"
collectionFormat: "multi"
responses:
"200":
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Pet"
"400":
description: "Invalid tag value"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
deprecated: true
/pet/{petId}:
get:
tags:
- "pet"
summary: "Find pet by ID"
description: "Returns a single pet"
operationId: "getPetById"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "petId"
in: "path"
description: "ID of pet to return"
required: true
type: "integer"
format: "int64"
responses:
"200":
description: "successful operation"
schema:
$ref: "#/definitions/Pet"
"400":
description: "Invalid ID supplied"
"404":
description: "Pet not found"
security:
- api_key: []
post:
tags:
- "pet"
summary: "Updates a pet in the store with form data"
description: ""
operationId: "updatePetWithForm"
consumes:
- "application/x-www-form-urlencoded"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "petId"
in: "path"
description: "ID of pet that needs to be updated"
required: true
type: "integer"
format: "int64"
- name: "name"
in: "formData"
description: "Updated name of the pet"
required: false
type: "string"
- name: "status"
in: "formData"
description: "Updated status of the pet"
required: false
type: "string"
responses:
"405":
description: "Invalid input"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
delete:
tags:
- "pet"
summary: "Deletes a pet"
description: ""
operationId: "deletePet"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "api_key"
in: "header"
required: false
type: "string"
- name: "petId"
in: "path"
description: "Pet id to delete"
required: true
type: "integer"
format: "int64"
responses:
"400":
description: "Invalid ID supplied"
"404":
description: "Pet not found"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/pet/{petId}/uploadImage:
post:
tags:
- "pet"
summary: "uploads an image"
description: ""
operationId: "uploadFile"
consumes:
- "multipart/form-data"
produces:
- "application/json"
parameters:
- name: "petId"
in: "path"
description: "ID of pet to update"
required: true
type: "integer"
format: "int64"
- name: "additionalMetadata"
in: "formData"
description: "Additional data to pass to server"
required: false
type: "string"
- name: "file"
in: "formData"
description: "file to upload"
required: false
type: "file"
responses:
"200":
description: "successful operation"
schema:
$ref: "#/definitions/ApiResponse"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/store/inventory:
get:
tags:
- "store"
summary: "Returns pet inventories by status"
description: "Returns a map of status codes to quantities"
operationId: "getInventory"
produces:
- "application/json"
parameters: []
responses:
"200":
description: "successful operation"
schema:
type: "object"
additionalProperties:
type: "integer"
format: "int32"
security:
- api_key: []
/store/order:
post:
tags:
- "store"
summary: "Place an order for a pet"
description: ""
operationId: "placeOrder"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "order placed for purchasing the pet"
required: true
schema:
$ref: "#/definitions/Order"
responses:
"200":
description: "successful operation"
schema:
$ref: "#/definitions/Order"
"400":
description: "Invalid Order"
/store/order/{orderId}:
get:
tags:
- "store"
summary: "Find purchase order by ID"
description: "For valid response try integer IDs with value >= 1 and <= 10.\
\\ Other values will generated exceptions"
operationId: "getOrderById"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "orderId"
in: "path"
description: "ID of pet that needs to be fetched"
required: true
type: "integer"
maximum: 10.0
minimum: 1.0
format: "int64"
responses:
"200":
description: "successful operation"
schema:
$ref: "#/definitions/Order"
"400":
description: "Invalid ID supplied"
"404":
description: "Order not found"
delete:
tags:
- "store"
summary: "Delete purchase order by ID"
description: "For valid response try integer IDs with positive integer value.\
\\ Negative or non-integer values will generate API errors"
operationId: "deleteOrder"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "orderId"
in: "path"
description: "ID of the order that needs to be deleted"
required: true
type: "integer"
minimum: 1.0
format: "int64"
responses:
"400":
description: "Invalid ID supplied"
"404":
description: "Order not found"
/user:
post:
tags:
- "user"
summary: "Create user"
description: "This can only be done by the logged in user."
operationId: "createUser"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Created user object"
required: true
schema:
$ref: "#/definitions/User"
responses:
default:
description: "successful operation"
/user/createWithArray:
post:
tags:
- "user"
summary: "Creates list of users with given input array"
description: ""
operationId: "createUsersWithArrayInput"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "List of user object"
required: true
schema:
type: "array"
items:
$ref: "#/definitions/User"
responses:
default:
description: "successful operation"
/user/createWithList:
post:
tags:
- "user"
summary: "Creates list of users with given input array"
description: ""
operationId: "createUsersWithListInput"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "List of user object"
required: true
schema:
type: "array"
items:
$ref: "#/definitions/User"
responses:
default:
description: "successful operation"
/user/login:
get:
tags:
- "user"
summary: "Logs user into the system"
description: ""
operationId: "loginUser"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "username"
in: "query"
description: "The user name for login"
required: true
type: "string"
- name: "password"
in: "query"
description: "The password for login in clear text"
required: true
type: "string"
responses:
"200":
description: "successful operation"
schema:
type: "string"
headers:
X-Rate-Limit:
type: "integer"
format: "int32"
description: "calls per hour allowed by the user"
X-Expires-After:
type: "string"
format: "date-time"
description: "date in UTC when token expires"
"400":
description: "Invalid username/password supplied"
/user/logout:
get:
tags:
- "user"
summary: "Logs out current logged in user session"
description: ""
operationId: "logoutUser"
produces:
- "application/xml"
- "application/json"
parameters: []
responses:
default:
description: "successful operation"
/user/{username}:
get:
tags:
- "user"
summary: "Get user by user name"
description: ""
operationId: "getUserByName"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "username"
in: "path"
description: "The name that needs to be fetched. Use user1 for testing. "
required: true
type: "string"
responses:
"200":
description: "successful operation"
schema:
$ref: "#/definitions/User"
"400":
description: "Invalid username supplied"
"404":
description: "User not found"
put:
tags:
- "user"
summary: "Updated user"
description: "This can only be done by the logged in user."
operationId: "updateUser"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "username"
in: "path"
description: "name that need to be updated"
required: true
type: "string"
- in: "body"
name: "body"
description: "Updated user object"
required: true
schema:
$ref: "#/definitions/User"
responses:
"400":
description: "Invalid user supplied"
"404":
description: "User not found"
delete:
tags:
- "user"
summary: "Delete user"
description: "This can only be done by the logged in user."
operationId: "deleteUser"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "username"
in: "path"
description: "The name that needs to be deleted"
required: true
type: "string"
responses:
"400":
description: "Invalid username supplied"
"404":
description: "User not found"
securityDefinitions:
petstore_auth:
type: "oauth2"
authorizationUrl: "http://petstore.swagger.io/oauth/dialog"
flow: "implicit"
scopes:
write:pets: "modify pets in your account"
read:pets: "read your pets"
api_key:
type: "apiKey"
name: "api_key"
in: "header"
definitions:
Order:
type: "object"
properties:
id:
type: "integer"
format: "int64"
petId:
type: "integer"
format: "int64"
quantity:
type: "integer"
format: "int32"
shipDate:
type: "string"
format: "date-time"
status:
type: "string"
description: "Order Status"
enum:
- "placed"
- "approved"
- "delivered"
complete:
type: "boolean"
default: false
xml:
name: "Order"
Category:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
xml:
name: "Category"
User:
type: "object"
properties:
id:
type: "integer"
format: "int64"
username:
type: "string"
firstName:
type: "string"
lastName:
type: "string"
email:
type: "string"
password:
type: "string"
phone:
type: "string"
userStatus:
type: "integer"
format: "int32"
description: "User Status"
xml:
name: "User"
Tag:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
xml:
name: "Tag"
Pet:
type: "object"
required:
- "name"
- "photoUrls"
properties:
id:
type: "integer"
format: "int64"
category:
$ref: "#/definitions/Category"
name:
type: "string"
example: "doggie"
photoUrls:
type: "array"
xml:
name: "photoUrl"
wrapped: true
items:
type: "string"
tags:
type: "array"
xml:
name: "tag"
wrapped: true
items:
$ref: "#/definitions/Tag"
status:
type: "string"
description: "pet status in the store"
enum:
- "available"
- "pending"
- "sold"
xml:
name: "Pet"
ApiResponse:
type: "object"
properties:
code:
type: "integer"
format: "int32"
type:
type: "string"
message:
type: "string"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"`;
export default selectOpenAPI20PetstoreYAML;
@@ -0,0 +1,804 @@
const selectOpenAPI310PetstoreYAML = () => `openapi: 3.0.3
info:
title: Swagger Petstore - OpenAPI 3.0
description: |-
This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about
Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
You can now help us improve the API whether it's by making changes to the definition itself or to the code.
That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
Some useful links:
- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
termsOfService: http://swagger.io/terms/
contact:
email: apiteam@swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.11
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: https://petstore3.swagger.io/api/v3
tags:
- name: pet
description: Everything about your Pets
externalDocs:
description: Find out more
url: http://swagger.io
- name: store
description: Access to Petstore orders
externalDocs:
description: Find out more about our store
url: http://swagger.io
- name: user
description: Operations about user
paths:
/pet:
put:
tags:
- pet
summary: Update an existing pet
description: Update an existing pet by Id
operationId: updatePet
requestBody:
description: Update an existent pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
requestBody:
description: Create a new pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: false
explode: true
schema:
type: string
default: available
enum:
- available
- pending
- sold
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid status value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
operationId: findPetsByTags
parameters:
- name: tags
in: query
description: Tags to filter by
required: false
explode: true
schema:
type: array
items:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid tag value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}:
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ''
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: integer
format: int64
- name: name
in: query
description: Name of pet that needs to be updated
schema:
type: string
- name: status
in: query
description: Status of pet that needs to be updated
schema:
type: string
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
delete:
tags:
- pet
summary: Deletes a pet
description: delete a pet
operationId: deletePet
parameters:
- name: api_key
in: header
description: ''
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid pet value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}/uploadImage:
post:
tags:
- pet
summary: uploads an image
description: ''
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
- name: additionalMetadata
in: query
description: Additional Metadata
required: false
schema:
type: string
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
security:
- petstore_auth:
- write:pets
- read:pets
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: Place a new order in the store
operationId: placeOrder
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Order'
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'405':
description: Invalid input
/store/order/{orderId}:
get:
tags:
- store
summary: Find purchase order by ID
description: For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.
operationId: getOrderById
parameters:
- name: orderId
in: path
description: ID of order that needs to be fetched
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid ID supplied
'404':
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid ID supplied
'404':
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
requestBody:
description: Created user object
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: Creates list of users with given input array
operationId: createUsersWithListInput
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
default:
description: successful operation
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ''
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: false
schema:
type: string
- name: password
in: query
description: The password for login in clear text
required: false
schema:
type: string
responses:
'200':
description: successful operation
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
description: date in UTC when token expires
schema:
type: string
format: date-time
content:
application/xml:
schema:
type: string
application/json:
schema:
type: string
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ''
operationId: logoutUser
parameters: []
responses:
default:
description: successful operation
/user/{username}:
get:
tags:
- user
summary: Get user by user name
description: ''
operationId: getUserByName
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing. '
required: true
schema:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid username supplied
'404':
description: User not found
put:
tags:
- user
summary: Update user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
schema:
type: string
requestBody:
description: Update an existent user in the store
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid username supplied
'404':
description: User not found
components:
schemas:
Order:
type: object
properties:
id:
type: integer
format: int64
example: 10
petId:
type: integer
format: int64
example: 198772
quantity:
type: integer
format: int32
example: 7
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
example: approved
enum:
- placed
- approved
- delivered
complete:
type: boolean
xml:
name: order
Customer:
type: object
properties:
id:
type: integer
format: int64
example: 100000
username:
type: string
example: fehguy
address:
type: array
xml:
name: addresses
wrapped: true
items:
$ref: '#/components/schemas/Address'
xml:
name: customer
Address:
type: object
properties:
street:
type: string
example: 437 Lytton
city:
type: string
example: Palo Alto
state:
type: string
example: CA
zip:
type: string
example: '94301'
xml:
name: address
Category:
type: object
properties:
id:
type: integer
format: int64
example: 1
name:
type: string
example: Dogs
xml:
name: category
User:
type: object
properties:
id:
type: integer
format: int64
example: 10
username:
type: string
example: theUser
firstName:
type: string
example: John
lastName:
type: string
example: James
email:
type: string
example: john@email.com
password:
type: string
example: '12345'
phone:
type: string
example: '12345'
userStatus:
type: integer
description: User Status
format: int32
example: 1
xml:
name: user
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: tag
Pet:
required:
- name
- photoUrls
type: object
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
$ref: '#/components/schemas/Category'
photoUrls:
type: array
xml:
wrapped: true
items:
type: string
xml:
name: photoUrl
tags:
type: array
xml:
wrapped: true
items:
$ref: '#/components/schemas/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: pet
ApiResponse:
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
xml:
name: '##default'
requestBodies:
Pet:
description: Pet object that needs to be added to the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
UserArray:
description: List of user object
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
securitySchemes:
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
scopes:
write:pets: modify pets in your account
read:pets: read your pets
api_key:
type: apiKey
name: api_key
in: header
`;
export default selectOpenAPI310PetstoreYAML;
@@ -0,0 +1,804 @@
const selectOpenAPI310PetstoreYAML = () => `openapi: 3.1.0
info:
title: Swagger Petstore - OpenAPI 3.1
description: |-
This is a sample Pet Store Server based on the OpenAPI 3.1 specification. You can find out more about
Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
You can now help us improve the API whether it's by making changes to the definition itself or to the code.
That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
Some useful links:
- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
termsOfService: http://swagger.io/terms/
contact:
email: apiteam@swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.11
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: https://petstore3.swagger.io/api/v3
tags:
- name: pet
description: Everything about your Pets
externalDocs:
description: Find out more
url: http://swagger.io
- name: store
description: Access to Petstore orders
externalDocs:
description: Find out more about our store
url: http://swagger.io
- name: user
description: Operations about user
paths:
/pet:
put:
tags:
- pet
summary: Update an existing pet
description: Update an existing pet by Id
operationId: updatePet
requestBody:
description: Update an existent pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
requestBody:
description: Create a new pet in the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: false
explode: true
schema:
type: string
default: available
enum:
- available
- pending
- sold
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid status value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
operationId: findPetsByTags
parameters:
- name: tags
in: query
description: Tags to filter by
required: false
explode: true
schema:
type: array
items:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid tag value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}:
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
- petstore_auth:
- write:pets
- read:pets
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ''
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: integer
format: int64
- name: name
in: query
description: Name of pet that needs to be updated
schema:
type: string
- name: status
in: query
description: Status of pet that needs to be updated
schema:
type: string
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
delete:
tags:
- pet
summary: Deletes a pet
description: delete a pet
operationId: deletePet
parameters:
- name: api_key
in: header
description: ''
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid pet value
security:
- petstore_auth:
- write:pets
- read:pets
/pet/{petId}/uploadImage:
post:
tags:
- pet
summary: uploads an image
description: ''
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
- name: additionalMetadata
in: query
description: Additional Metadata
required: false
schema:
type: string
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
security:
- petstore_auth:
- write:pets
- read:pets
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: Place a new order in the store
operationId: placeOrder
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Order'
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'405':
description: Invalid input
/store/order/{orderId}:
get:
tags:
- store
summary: Find purchase order by ID
description: For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.
operationId: getOrderById
parameters:
- name: orderId
in: path
description: ID of order that needs to be fetched
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid ID supplied
'404':
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid ID supplied
'404':
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
requestBody:
description: Created user object
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: Creates list of users with given input array
operationId: createUsersWithListInput
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
default:
description: successful operation
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ''
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: false
schema:
type: string
- name: password
in: query
description: The password for login in clear text
required: false
schema:
type: string
responses:
'200':
description: successful operation
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
description: date in UTC when token expires
schema:
type: string
format: date-time
content:
application/xml:
schema:
type: string
application/json:
schema:
type: string
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ''
operationId: logoutUser
parameters: []
responses:
default:
description: successful operation
/user/{username}:
get:
tags:
- user
summary: Get user by user name
description: ''
operationId: getUserByName
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing. '
required: true
schema:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid username supplied
'404':
description: User not found
put:
tags:
- user
summary: Update user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
schema:
type: string
requestBody:
description: Update an existent user in the store
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/User'
responses:
default:
description: successful operation
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid username supplied
'404':
description: User not found
components:
schemas:
Order:
type: object
properties:
id:
type: integer
format: int64
example: 10
petId:
type: integer
format: int64
example: 198772
quantity:
type: integer
format: int32
example: 7
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
example: approved
enum:
- placed
- approved
- delivered
complete:
type: boolean
xml:
name: order
Customer:
type: object
properties:
id:
type: integer
format: int64
example: 100000
username:
type: string
example: fehguy
address:
type: array
xml:
name: addresses
wrapped: true
items:
$ref: '#/components/schemas/Address'
xml:
name: customer
Address:
type: object
properties:
street:
type: string
example: 437 Lytton
city:
type: string
example: Palo Alto
state:
type: string
example: CA
zip:
type: string
example: '94301'
xml:
name: address
Category:
type: object
properties:
id:
type: integer
format: int64
example: 1
name:
type: string
example: Dogs
xml:
name: category
User:
type: object
properties:
id:
type: integer
format: int64
example: 10
username:
type: string
example: theUser
firstName:
type: string
example: John
lastName:
type: string
example: James
email:
type: string
example: john@email.com
password:
type: string
example: '12345'
phone:
type: string
example: '12345'
userStatus:
type: integer
description: User Status
format: int32
example: 1
xml:
name: user
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: tag
Pet:
required:
- name
- photoUrls
type: object
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
$ref: '#/components/schemas/Category'
photoUrls:
type: array
xml:
wrapped: true
items:
type: string
xml:
name: photoUrl
tags:
type: array
xml:
wrapped: true
items:
$ref: '#/components/schemas/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: pet
ApiResponse:
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
xml:
name: '##default'
requestBodies:
Pet:
description: Pet object that needs to be added to the store
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
UserArray:
description: List of user object
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
securitySchemes:
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
scopes:
write:pets: modify pets in your account
read:pets: read your pets
api_key:
type: apiKey
name: api_key
in: header
`;
export default selectOpenAPI310PetstoreYAML;
@@ -0,0 +1,73 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import JumpIcon from './jump-icon.svg';
/**
* JumpToPath is a legacy name that is already built into SwaggerUI
* 1. onHover of SwaggerUI operation or model, render svg icon
* 2. onClick of svg icon => jump to line in editorContent
*/
const JumpFromPathToLine = ({
editorActions,
editorSelectors,
path,
specPath,
content,
showButton,
}) => {
const handleJumpToEditorLine = (e) => {
e.stopPropagation();
const jumpPath = editorSelectors.bestJumpPath({ path, specPath });
// `apidom-ls` will expect `jumpPath` to be a String instead of legacy Array, e.g. '/components/schemas/Category/properties/id'
// `Editor` will handle the rest of workflow
editorActions.setRequestJumpToEditorMarker({ jsonPointer: jumpPath });
};
const defaultJumpButton = (
<div
role="button"
tabIndex={0}
onClick={handleJumpToEditorLine}
onKeyPress={handleJumpToEditorLine}
>
<img src={JumpIcon} className="view-line-link" title="Jump to definition" alt="" />
</div>
);
if (content) {
// if we were given content to render, wrap it
return (
<span
role="button"
tabIndex={0}
onClick={handleJumpToEditorLine}
onKeyPress={handleJumpToEditorLine}
>
{showButton ? { defaultJumpButton } : null}
{content}
</span>
);
}
return <div>{defaultJumpButton}</div>;
};
JumpFromPathToLine.propTypes = {
editorActions: PropTypes.oneOfType([PropTypes.object]).isRequired,
editorSelectors: PropTypes.oneOfType([PropTypes.object]).isRequired, // TODO: make this a shape
path: PropTypes.oneOfType([PropTypes.array, PropTypes.string, ImmutablePropTypes.list]),
specPath: PropTypes.oneOfType([PropTypes.array, ImmutablePropTypes.list]), // the location within the spec. used as a fallback if `path` doesn't exist
content: PropTypes.element,
showButton: PropTypes.bool,
};
JumpFromPathToLine.defaultProps = {
path: [],
specPath: [],
content: null,
showButton: false,
};
export default JumpFromPathToLine;
@@ -0,0 +1,3 @@
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
</svg>

After

Width:  |  Height:  |  Size: 281 B

@@ -0,0 +1,17 @@
import JumpFromPathToLine from './components/JumpFromPathToLine.jsx';
import { bestJumpPath } from './selectors.js';
const EditorContentJumpFromPathToLinePlugin = () => ({
components: {
JumpToPath: JumpFromPathToLine, // SwaggerUI component
},
statePlugins: {
editor: {
selectors: {
bestJumpPath,
},
},
},
});
export default EditorContentJumpFromPathToLinePlugin;
@@ -0,0 +1,61 @@
/* eslint-disable import/prefer-default-export */
import { createSelector } from 'reselect';
import { List } from 'immutable';
const transformArrayToStringPath = (arr) => {
if (arr.at(0) !== '/') {
return `/${arr.join('')}`;
}
return arr.join('/');
};
const transformImListToStringPath = (list) => {
const arr = list.toJS();
if (arr.at(0) !== '/') {
return `/${arr.join('')}`;
}
return arr.join('');
};
// compared to `path`, each element inside `specPath` does not contain leading `/`
const transformArrayToStringSpecPath = (arr) => {
if (arr.at(0) !== '/') {
return `/${arr.join('/')}`;
}
return arr.join('/');
};
// compared to `path`, each element inside `specPath` does not contain leading `/`
const transformImListToStringSpecPath = (list) => {
const arr = list.toJS();
if (arr.at(0) !== '/') {
return `/${arr.join('/')}`;
}
return arr.join('/');
};
// apidom-ls expects a String as arg
export const bestJumpPath = createSelector(
(state, pathObj) => pathObj, // input from arg to forward to output
({ path, specPath }) => {
if (path && typeof path === 'string') {
return path;
}
if (path && Array.isArray(path) && path.length > 0) {
return transformArrayToStringPath(path);
}
if (path && List.isList(path) && path.size > 0) {
return transformImListToStringPath(path);
}
if (specPath && typeof specPath === 'string') {
return specPath;
}
if (specPath && Array.isArray(specPath) && specPath.length > 0) {
return transformArrayToStringSpecPath(specPath);
}
if (specPath && List.isList(specPath) && specPath.size > 0) {
return transformImListToStringSpecPath(specPath);
}
return '';
}
);
@@ -0,0 +1,6 @@
export const EDITOR_CONTENT_SET_ORIGIN = 'editor_content_set_origin';
export const setContentOrigin = (contentOrigin = 'not-editor') => ({
type: EDITOR_CONTENT_SET_ORIGIN,
payload: String(contentOrigin),
});
@@ -0,0 +1,30 @@
import reducers from './reducers.js';
import { selectContentOrigin } from './selectors.js';
import { setContentOrigin } from './actions.js';
import { setContent } from './wrap-actions.js';
/**
* Wraps setContent to include the "contentOrigin" parameter, defaulting to "not-editor".
* Includes a selector to get the origin: `editorSelectors.selectContentOrigin()`.
*/
const EditorContentOriginPlugin = () => {
return {
statePlugins: {
editor: {
wrapActions: {
setContent,
},
reducers,
selectors: {
selectContentOrigin,
},
actions: {
setContentOrigin,
},
},
},
};
};
export default EditorContentOriginPlugin;
@@ -0,0 +1,9 @@
import { EDITOR_CONTENT_SET_ORIGIN } from './actions.js';
const reducers = {
[EDITOR_CONTENT_SET_ORIGIN]: (state, action) => {
return state.set('contentOrigin', action.payload);
},
};
export default reducers;
@@ -0,0 +1,2 @@
// eslint-disable-next-line import/prefer-default-export
export const selectContentOrigin = (state) => state.get('contentOrigin') || 'not-editor';
@@ -0,0 +1,10 @@
import createSafeActionWrapper from '../../utils/create-safe-action-wrapper.js';
// eslint-disable-next-line import/prefer-default-export
export const setContent = createSafeActionWrapper(
(oriAction, system) => (content, contentOrigin) => {
const { editorActions } = system;
editorActions.setContentOrigin(contentOrigin);
}
);
@@ -0,0 +1,13 @@
const afterLoad = (system) => {
const { editorContentPersistence, editorActions, editorSelectors } = system;
const contentPersisted = editorContentPersistence.get();
const isPersisted = contentPersisted !== null;
if (!isPersisted) return; // nothing persisted
if (editorSelectors.selectContent() === contentPersisted) return; // content already persisted
editorActions.setContent(contentPersisted, 'local-storage');
};
export default afterLoad;
@@ -0,0 +1,26 @@
import { setContent as setContentWrap, download as downloadWrap } from './wrap-actions.js';
import { editorContentPersistence } from './root-injects.js';
import afterLoad from './after-load.js';
const EditorContentPersistencePlugin = () => {
return {
afterLoad,
rootInjects: {
editorContentPersistence,
},
statePlugins: {
spec: {
wrapActions: {
download: downloadWrap,
},
},
editor: {
wrapActions: {
setContent: setContentWrap,
},
},
},
};
};
export default EditorContentPersistencePlugin;
@@ -0,0 +1,13 @@
const STORAGE_KEY = 'swagger-editor-next-content';
export const saveToLocalStorage = (value) => {
return localStorage.setItem(STORAGE_KEY, value);
};
export const loadFromLocalStorage = () => {
return localStorage.getItem(STORAGE_KEY);
};
export const hasLocalStorage = () => {
return loadFromLocalStorage() !== null;
};
@@ -0,0 +1,18 @@
import {
hasLocalStorage,
saveToLocalStorage,
loadFromLocalStorage,
} from './layers/local-storage.js';
// eslint-disable-next-line import/prefer-default-export
export const editorContentPersistence = {
has() {
return hasLocalStorage();
},
set(value) {
return saveToLocalStorage(value);
},
get() {
return loadFromLocalStorage();
},
};
@@ -0,0 +1,21 @@
import createSafeActionWrapper from '../../utils/create-safe-action-wrapper.js';
export const setContent = createSafeActionWrapper((oriAction, system) => (content) => {
const { editorContentPersistence } = system;
editorContentPersistence.set(content);
});
/**
* When given a SwaggerUI config prop `url`,
* before `download` of new content as specified by `url`,
* check if active content already exists in localStorage.
*/
export const download = (oriAction, system) => (content) => {
const { editorContentPersistence } = system;
if (!editorContentPersistence.has()) {
oriAction(content);
}
};
@@ -0,0 +1,16 @@
/**
* Action types.
*/
export const EDITOR_CONTENT_SET_READ_ONLY = 'editor_update_read_only';
export const EDITOR_CONTENT_SET_READ_WRITE = 'editor_update_read_write';
/**
* Action creators.
*/
export const setContentReadOnly = () => ({
type: EDITOR_CONTENT_SET_READ_ONLY,
});
export const setContentReadWrite = () => ({
type: EDITOR_CONTENT_SET_READ_WRITE,
});
@@ -0,0 +1,48 @@
import React from 'react';
import PropTypes from 'prop-types';
import { LockIcon, UnlockIcon } from '@primer/octicons-react';
const ReadOnlySelectionIcon = ({ editorSelectors, editorActions }) => {
const isReadWrite = editorSelectors.selectContentIsReadWrite();
const handleReadonly = (isReadOnlyNew) => () => {
if (isReadOnlyNew) {
editorActions.setContentReadOnly();
} else {
editorActions.setContentReadWrite();
}
};
return isReadWrite ? (
<div className="swagger-editor__generic-padding-thin-top-bottom">
<button
type="button"
className="swagger-editor__editor-pane-bar-control"
onClick={handleReadonly(true)}
>
<UnlockIcon size="small" aria-label="Unlock" />
</button>
</div>
) : (
<div className="swagger-editor__generic-padding-thin-top-bottom">
<button
type="button"
className="swagger-editor__editor-pane-bar-control"
onClick={handleReadonly(false)}
>
<LockIcon size="small" aria-label="Lock" />
</button>
</div>
);
};
ReadOnlySelectionIcon.propTypes = {
editorActions: PropTypes.shape({
setContentReadOnly: PropTypes.func.isRequired,
setContentReadWrite: PropTypes.func.isRequired,
}).isRequired,
editorSelectors: PropTypes.shape({
selectContentIsReadWrite: PropTypes.func.isRequired,
}).isRequired,
};
export default ReadOnlySelectionIcon;
@@ -0,0 +1,33 @@
import reducers from './reducers.js';
import { setContentReadOnly, setContentReadWrite } from './actions.js';
import { selectContentIsReadOnly, selectContentIsReadWrite } from './selectors.js';
import ReadOnlySelectionIcon from './components/ReadOnlySelectionIcon.jsx';
import EditorPaneBarTopWrapper from './wrap-components/EditorPaneBarTopWrapper.jsx';
import EditorWrapper from './wrap-components/EditorWrapper.jsx';
const EditorContentReadOnlyPlugin = () => {
return {
components: {
ReadOnlySelection: ReadOnlySelectionIcon,
},
wrapComponents: {
Editor: EditorWrapper,
EditorPaneBarTop: EditorPaneBarTopWrapper,
},
statePlugins: {
editor: {
reducers,
selectors: {
selectContentIsReadOnly,
selectContentIsReadWrite,
},
actions: {
setContentReadOnly,
setContentReadWrite,
},
},
},
};
};
export default EditorContentReadOnlyPlugin;
@@ -0,0 +1,12 @@
import { EDITOR_CONTENT_SET_READ_ONLY, EDITOR_CONTENT_SET_READ_WRITE } from './actions.js';
const reducers = {
[EDITOR_CONTENT_SET_READ_ONLY]: (state) => {
return state.set('contentIsReadOnly', true);
},
[EDITOR_CONTENT_SET_READ_WRITE]: (state) => {
return state.set('contentIsReadOnly', false);
},
};
export default reducers;
@@ -0,0 +1,3 @@
export const selectContentIsReadOnly = (state) => state.get('contentIsReadOnly') || false;
export const selectContentIsReadWrite = (state) => !selectContentIsReadOnly(state);
@@ -0,0 +1,31 @@
import PropTypes from 'prop-types';
/* eslint-disable react/jsx-props-no-spreading */
const EditorPaneBarTopWrapper = (Original, system) => {
const ReadOnlySelection = system.getComponent('ReadOnlySelection', true);
const EditorPaneBarTop = ({ renderControls, ...rest }) => {
return (
<Original
{...rest}
renderControls={(controls) =>
renderControls(
<>
<ReadOnlySelection />
{controls}
</>
)
}
/>
);
};
EditorPaneBarTop.propTypes = {
renderControls: PropTypes.func,
};
EditorPaneBarTop.defaultProps = {
renderControls: (controls) => controls,
};
return EditorPaneBarTop;
};
export default EditorPaneBarTopWrapper;
@@ -0,0 +1,12 @@
const EditorWrapper = (Original, system) => {
const Editor = (props) => {
const isReadOnly = system.editorSelectors.selectContentIsReadOnly();
// eslint-disable-next-line react/jsx-props-no-spreading
return <Original {...props} isReadOnly={isReadOnly} />;
};
return Editor;
};
export default EditorWrapper;

Some files were not shown because too many files have changed in this diff Show More