Merge pull request #4773 from mslourens/openapi3-import
Support Openapi 3 import
This commit is contained in:
commit
2830698629
|
@ -2,6 +2,7 @@ import { queryValidation } from "../validation"
|
||||||
import { generateQueryID } from "../../../../db/utils"
|
import { generateQueryID } from "../../../../db/utils"
|
||||||
import { ImportInfo, ImportSource } from "./sources/base"
|
import { ImportInfo, ImportSource } from "./sources/base"
|
||||||
import { OpenAPI2 } from "./sources/openapi2"
|
import { OpenAPI2 } from "./sources/openapi2"
|
||||||
|
import { OpenAPI3 } from "./sources/openapi3"
|
||||||
import { Query } from "./../../../../definitions/common"
|
import { Query } from "./../../../../definitions/common"
|
||||||
import { Curl } from "./sources/curl"
|
import { Curl } from "./sources/curl"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -18,7 +19,7 @@ export class RestImporter {
|
||||||
|
|
||||||
constructor(data: string) {
|
constructor(data: string) {
|
||||||
this.data = data
|
this.data = data
|
||||||
this.sources = [new OpenAPI2(), new Curl()]
|
this.sources = [new OpenAPI2(), new OpenAPI3(), new Curl()]
|
||||||
}
|
}
|
||||||
|
|
||||||
init = async () => {
|
init = async () => {
|
||||||
|
|
|
@ -23,7 +23,7 @@ export abstract class ImportSource {
|
||||||
name: string,
|
name: string,
|
||||||
method: string,
|
method: string,
|
||||||
path: string,
|
path: string,
|
||||||
url: URL,
|
url: URL | string | undefined,
|
||||||
queryString: string,
|
queryString: string,
|
||||||
headers: object = {},
|
headers: object = {},
|
||||||
parameters: QueryParameter[] = [],
|
parameters: QueryParameter[] = [],
|
||||||
|
@ -34,7 +34,13 @@ export abstract class ImportSource {
|
||||||
const transformer = "return data"
|
const transformer = "return data"
|
||||||
const schema = {}
|
const schema = {}
|
||||||
path = this.processPath(path)
|
path = this.processPath(path)
|
||||||
path = `${url.origin}/${path}`
|
if (url) {
|
||||||
|
if (typeof url === "string") {
|
||||||
|
path = `${url}/${path}`
|
||||||
|
} else {
|
||||||
|
path = `${url.origin}/${path}`
|
||||||
|
}
|
||||||
|
}
|
||||||
queryString = this.processQuery(queryString)
|
queryString = this.processQuery(queryString)
|
||||||
const requestBody = JSON.stringify(body, null, 2)
|
const requestBody = JSON.stringify(body, null, 2)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
import { ImportInfo } from "./base"
|
||||||
|
import { Query, QueryParameter } from "../../../../../definitions/datasource"
|
||||||
|
import { OpenAPIV3 } from "openapi-types"
|
||||||
|
import { OpenAPISource } from "./base/openapi"
|
||||||
|
import { URL } from "url"
|
||||||
|
|
||||||
|
const parameterNotRef = (
|
||||||
|
param: OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject
|
||||||
|
): param is OpenAPIV3.ParameterObject => {
|
||||||
|
// all refs are deferenced by parser library
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestBodyNotRef = (
|
||||||
|
param: OpenAPIV3.RequestBodyObject | OpenAPIV3.ReferenceObject | undefined
|
||||||
|
): param is OpenAPIV3.RequestBodyObject => {
|
||||||
|
// all refs are deferenced by parser library
|
||||||
|
return param !== undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const schemaNotRef = (
|
||||||
|
param: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined
|
||||||
|
): param is OpenAPIV3.SchemaObject => {
|
||||||
|
// all refs are deferenced by parser library
|
||||||
|
return param !== undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const isOpenAPI3 = (document: any): document is OpenAPIV3.Document => {
|
||||||
|
return document.openapi.includes("3.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
const methods: string[] = Object.values(OpenAPIV3.HttpMethods)
|
||||||
|
|
||||||
|
const isOperation = (
|
||||||
|
key: string,
|
||||||
|
pathItem: any
|
||||||
|
): pathItem is OpenAPIV3.OperationObject => {
|
||||||
|
return methods.includes(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const isParameter = (
|
||||||
|
key: string,
|
||||||
|
pathItem: any
|
||||||
|
): pathItem is OpenAPIV3.ParameterObject => {
|
||||||
|
return !isOperation(key, pathItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getRequestBody = (operation: OpenAPIV3.OperationObject) => {
|
||||||
|
if (requestBodyNotRef(operation.requestBody)) {
|
||||||
|
const request: OpenAPIV3.RequestBodyObject = operation.requestBody
|
||||||
|
const supportedMimeTypes = getMimeTypes(operation)
|
||||||
|
if (supportedMimeTypes.length > 0) {
|
||||||
|
const mimeType = supportedMimeTypes[0]
|
||||||
|
|
||||||
|
// try get example from request
|
||||||
|
const content = request.content[mimeType]
|
||||||
|
if (content.example) {
|
||||||
|
return content.example
|
||||||
|
}
|
||||||
|
|
||||||
|
// try get example from schema
|
||||||
|
if (schemaNotRef(content.schema)) {
|
||||||
|
const schema = content.schema
|
||||||
|
if (schema.example) {
|
||||||
|
return schema.example
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMimeTypes = (operation: OpenAPIV3.OperationObject): string[] => {
|
||||||
|
if (requestBodyNotRef(operation.requestBody)) {
|
||||||
|
const request: OpenAPIV3.RequestBodyObject = operation.requestBody
|
||||||
|
return Object.keys(request.content)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI Version 3.0
|
||||||
|
* https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md
|
||||||
|
*/
|
||||||
|
export class OpenAPI3 extends OpenAPISource {
|
||||||
|
document!: OpenAPIV3.Document
|
||||||
|
|
||||||
|
isSupported = async (data: string): Promise<boolean> => {
|
||||||
|
try {
|
||||||
|
const document: any = await this.parseData(data)
|
||||||
|
if (isOpenAPI3(document)) {
|
||||||
|
this.document = document
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getInfo = async (): Promise<ImportInfo> => {
|
||||||
|
const name = this.document.info.title || "OpenAPI Import"
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getQueries = async (datasourceId: string): Promise<Query[]> => {
|
||||||
|
let url: string | URL | undefined
|
||||||
|
if (this.document.servers?.length) {
|
||||||
|
url = this.document.servers[0].url
|
||||||
|
try {
|
||||||
|
url = new URL(url)
|
||||||
|
} catch (err) {
|
||||||
|
// unable to construct url, e.g. with variables
|
||||||
|
// proceed with string form of url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queries: Query[] = []
|
||||||
|
|
||||||
|
for (let [path, pathItemObject] of Object.entries(this.document.paths)) {
|
||||||
|
// parameters that apply to every operation in the path
|
||||||
|
let pathParams: OpenAPIV3.ParameterObject[] = []
|
||||||
|
|
||||||
|
// pathItemObject can be undefined
|
||||||
|
if (!pathItemObject) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let [key, opOrParams] of Object.entries(pathItemObject)) {
|
||||||
|
if (isParameter(key, opOrParams)) {
|
||||||
|
const pathParameters = opOrParams as OpenAPIV3.ParameterObject[]
|
||||||
|
pathParams.push(...pathParameters)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// can not be a parameter, must be an operation
|
||||||
|
const operation = opOrParams as OpenAPIV3.OperationObject
|
||||||
|
|
||||||
|
const methodName = key
|
||||||
|
const name = operation.operationId || path
|
||||||
|
let queryString = ""
|
||||||
|
const headers: any = {}
|
||||||
|
let requestBody = getRequestBody(operation)
|
||||||
|
const parameters: QueryParameter[] = []
|
||||||
|
const mimeTypes = getMimeTypes(operation)
|
||||||
|
|
||||||
|
if (mimeTypes.length > 0) {
|
||||||
|
headers["Content-Type"] = mimeTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// combine the path parameters with the operation parameters
|
||||||
|
const operationParams = operation.parameters || []
|
||||||
|
const allParams = [...pathParams, ...operationParams]
|
||||||
|
|
||||||
|
for (let param of allParams) {
|
||||||
|
if (parameterNotRef(param)) {
|
||||||
|
switch (param.in) {
|
||||||
|
case "query":
|
||||||
|
let prefix = ""
|
||||||
|
if (queryString) {
|
||||||
|
prefix = "&"
|
||||||
|
}
|
||||||
|
queryString = `${queryString}${prefix}${param.name}={{${param.name}}}`
|
||||||
|
break
|
||||||
|
case "header":
|
||||||
|
headers[param.name] = `{{${param.name}}}`
|
||||||
|
break
|
||||||
|
case "path":
|
||||||
|
// do nothing: param is already in the path
|
||||||
|
break
|
||||||
|
case "formData":
|
||||||
|
// future enhancement
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the parameter if it can be bound in our config
|
||||||
|
if (["query", "header", "path"].includes(param.in)) {
|
||||||
|
parameters.push({
|
||||||
|
name: param.name,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = this.constructQuery(
|
||||||
|
datasourceId,
|
||||||
|
name,
|
||||||
|
methodName,
|
||||||
|
path,
|
||||||
|
url,
|
||||||
|
queryString,
|
||||||
|
headers,
|
||||||
|
parameters,
|
||||||
|
requestBody
|
||||||
|
)
|
||||||
|
queries.push(query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return queries
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.2",
|
||||||
|
"info": {
|
||||||
|
"description": "A basic swagger file",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"title": "CRUD"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"name": "entity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/entities": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"entity"
|
||||||
|
],
|
||||||
|
"operationId": "createEntity",
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/CreateEntity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "successful operation",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"entity"
|
||||||
|
],
|
||||||
|
"operationId": "getEntities",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/PageParameter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/SizeParameter"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "successful operation",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entities"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/entities/{entityId}": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/EntityIdParameter"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"entity"
|
||||||
|
],
|
||||||
|
"operationId": "getEntity",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "successful operation",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"tags": [
|
||||||
|
"entity"
|
||||||
|
],
|
||||||
|
"operationId": "updateEntity",
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "successful operation",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patch": {
|
||||||
|
"tags": [
|
||||||
|
"entity"
|
||||||
|
],
|
||||||
|
"operationId": "patchEntity",
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "successful operation",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"tags": [
|
||||||
|
"entity"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/APIKeyParameter"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operationId": "deleteEntity",
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "successful operation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"parameters": {
|
||||||
|
"EntityIdParameter": {
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"name": "entityId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"PageParameter": {
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"name": "page",
|
||||||
|
"in": "query",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
"SizeParameter": {
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"name": "size",
|
||||||
|
"in": "query",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
"APIKeyParameter": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": "x-api-key",
|
||||||
|
"in": "header",
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schemas": {
|
||||||
|
"CreateEntity": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "type"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Entity": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/CreateEntity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"example": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type": "type"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Entities" : {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
---
|
||||||
|
openapi: 3.0.2
|
||||||
|
info:
|
||||||
|
description: A basic swagger file
|
||||||
|
version: 1.0.0
|
||||||
|
title: CRUD
|
||||||
|
servers:
|
||||||
|
- url: http://example.com
|
||||||
|
tags:
|
||||||
|
- name: entity
|
||||||
|
paths:
|
||||||
|
"/entities":
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- entity
|
||||||
|
operationId: createEntity
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/CreateEntity"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- entity
|
||||||
|
operationId: getEntities
|
||||||
|
parameters:
|
||||||
|
- "$ref": "#/components/parameters/PageParameter"
|
||||||
|
- "$ref": "#/components/parameters/SizeParameter"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entities"
|
||||||
|
"/entities/{entityId}":
|
||||||
|
parameters:
|
||||||
|
- "$ref": "#/components/parameters/EntityIdParameter"
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- entity
|
||||||
|
operationId: getEntity
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- entity
|
||||||
|
operationId: updateEntity
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
patch:
|
||||||
|
tags:
|
||||||
|
- entity
|
||||||
|
operationId: patchEntity
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- entity
|
||||||
|
parameters:
|
||||||
|
- "$ref": "#/components/parameters/APIKeyParameter"
|
||||||
|
operationId: deleteEntity
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: successful operation
|
||||||
|
components:
|
||||||
|
parameters:
|
||||||
|
EntityIdParameter:
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name: entityId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
PageParameter:
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
name: page
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
SizeParameter:
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
name: size
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
APIKeyParameter:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
name: x-api-key
|
||||||
|
in: header
|
||||||
|
required: false
|
||||||
|
schemas:
|
||||||
|
CreateEntity:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
name: name
|
||||||
|
type: type
|
||||||
|
Entity:
|
||||||
|
allOf:
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
- "$ref": "#/components/schemas/CreateEntity"
|
||||||
|
example:
|
||||||
|
id: 1
|
||||||
|
name: name
|
||||||
|
type: type
|
||||||
|
Entities:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
"$ref": "#/components/schemas/Entity"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,804 @@
|
||||||
|
---
|
||||||
|
openapi: 3.0.2
|
||||||
|
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 [http://swagger.io](http://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: "/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/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 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/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,240 @@
|
||||||
|
const fs = require("fs")
|
||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const { OpenAPI3 } = require("../../openapi3")
|
||||||
|
|
||||||
|
const getData = (file, extension) => {
|
||||||
|
return fs.readFileSync(
|
||||||
|
path.join(__dirname, `./data/${file}/${file}.${extension}`),
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("OpenAPI3 Import", () => {
|
||||||
|
let openapi3
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
openapi3 = new OpenAPI3()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("validates unsupported data", async () => {
|
||||||
|
let data
|
||||||
|
let supported
|
||||||
|
|
||||||
|
// non json / yaml
|
||||||
|
data = "curl http://example.com"
|
||||||
|
supported = await openapi3.isSupported(data)
|
||||||
|
expect(supported).toBe(false)
|
||||||
|
|
||||||
|
// Empty
|
||||||
|
data = ""
|
||||||
|
supported = await openapi3.isSupported(data)
|
||||||
|
expect(supported).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
const runTests = async (filename, test, assertions) => {
|
||||||
|
for (let extension of ["json", "yaml"]) {
|
||||||
|
await test(filename, extension, assertions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testImportInfo = async (file, extension) => {
|
||||||
|
await openapi3.isSupported(getData(file, extension))
|
||||||
|
const info = await openapi3.getInfo()
|
||||||
|
expect(info.name).toBe("Swagger Petstore - OpenAPI 3.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
it("returns import info", async () => {
|
||||||
|
await runTests("petstore", testImportInfo)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Returns queries", () => {
|
||||||
|
const indexQueries = queries => {
|
||||||
|
return queries.reduce((acc, query) => {
|
||||||
|
acc[query.name] = query
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getQueries = async (file, extension) => {
|
||||||
|
await openapi3.isSupported(getData(file, extension))
|
||||||
|
const queries = await openapi3.getQueries()
|
||||||
|
expect(queries.length).toBe(6)
|
||||||
|
return indexQueries(queries)
|
||||||
|
}
|
||||||
|
|
||||||
|
const testVerb = async (file, extension, assertions) => {
|
||||||
|
const queries = await getQueries(file, extension)
|
||||||
|
for (let [operationId, method] of Object.entries(assertions)) {
|
||||||
|
expect(queries[operationId].queryVerb).toBe(method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it("populates verb", async () => {
|
||||||
|
const assertions = {
|
||||||
|
createEntity: "create",
|
||||||
|
getEntities: "read",
|
||||||
|
getEntity: "read",
|
||||||
|
updateEntity: "update",
|
||||||
|
patchEntity: "patch",
|
||||||
|
deleteEntity: "delete",
|
||||||
|
}
|
||||||
|
await runTests("crud", testVerb, assertions)
|
||||||
|
})
|
||||||
|
|
||||||
|
const testPath = async (file, extension, assertions) => {
|
||||||
|
const queries = await getQueries(file, extension)
|
||||||
|
for (let [operationId, urlPath] of Object.entries(assertions)) {
|
||||||
|
expect(queries[operationId].fields.path).toBe(urlPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it("populates path", async () => {
|
||||||
|
const assertions = {
|
||||||
|
createEntity: "http://example.com/entities",
|
||||||
|
getEntities: "http://example.com/entities",
|
||||||
|
getEntity: "http://example.com/entities/{{entityId}}",
|
||||||
|
updateEntity: "http://example.com/entities/{{entityId}}",
|
||||||
|
patchEntity: "http://example.com/entities/{{entityId}}",
|
||||||
|
deleteEntity: "http://example.com/entities/{{entityId}}",
|
||||||
|
}
|
||||||
|
await runTests("crud", testPath, assertions)
|
||||||
|
})
|
||||||
|
|
||||||
|
const testHeaders = async (file, extension, assertions) => {
|
||||||
|
const queries = await getQueries(file, extension)
|
||||||
|
for (let [operationId, headers] of Object.entries(assertions)) {
|
||||||
|
expect(queries[operationId].fields.headers).toStrictEqual(headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentTypeHeader = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
it("populates headers", async () => {
|
||||||
|
const assertions = {
|
||||||
|
createEntity: {
|
||||||
|
...contentTypeHeader,
|
||||||
|
},
|
||||||
|
getEntities: {},
|
||||||
|
getEntity: {},
|
||||||
|
updateEntity: {
|
||||||
|
...contentTypeHeader,
|
||||||
|
},
|
||||||
|
patchEntity: {
|
||||||
|
...contentTypeHeader,
|
||||||
|
},
|
||||||
|
deleteEntity: {
|
||||||
|
"x-api-key": "{{x-api-key}}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
await runTests("crud", testHeaders, assertions)
|
||||||
|
})
|
||||||
|
|
||||||
|
const testQuery = async (file, extension, assertions) => {
|
||||||
|
const queries = await getQueries(file, extension)
|
||||||
|
for (let [operationId, queryString] of Object.entries(assertions)) {
|
||||||
|
expect(queries[operationId].fields.queryString).toStrictEqual(
|
||||||
|
queryString
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it("populates query", async () => {
|
||||||
|
const assertions = {
|
||||||
|
createEntity: "",
|
||||||
|
getEntities: "page={{page}}&size={{size}}",
|
||||||
|
getEntity: "",
|
||||||
|
updateEntity: "",
|
||||||
|
patchEntity: "",
|
||||||
|
deleteEntity: "",
|
||||||
|
}
|
||||||
|
await runTests("crud", testQuery, assertions)
|
||||||
|
})
|
||||||
|
|
||||||
|
const testParameters = async (file, extension, assertions) => {
|
||||||
|
const queries = await getQueries(file, extension)
|
||||||
|
for (let [operationId, parameters] of Object.entries(assertions)) {
|
||||||
|
expect(queries[operationId].parameters).toStrictEqual(parameters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it("populates parameters", async () => {
|
||||||
|
const assertions = {
|
||||||
|
createEntity: [],
|
||||||
|
getEntities: [
|
||||||
|
{
|
||||||
|
name: "page",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "size",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
getEntity: [
|
||||||
|
{
|
||||||
|
name: "entityId",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
updateEntity: [
|
||||||
|
{
|
||||||
|
name: "entityId",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
patchEntity: [
|
||||||
|
{
|
||||||
|
name: "entityId",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
deleteEntity: [
|
||||||
|
{
|
||||||
|
name: "entityId",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "x-api-key",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
await runTests("crud", testParameters, assertions)
|
||||||
|
})
|
||||||
|
|
||||||
|
const testBody = async (file, extension, assertions) => {
|
||||||
|
const queries = await getQueries(file, extension)
|
||||||
|
for (let [operationId, body] of Object.entries(assertions)) {
|
||||||
|
expect(queries[operationId].fields.requestBody).toStrictEqual(
|
||||||
|
JSON.stringify(body, null, 2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it("populates body", async () => {
|
||||||
|
const assertions = {
|
||||||
|
createEntity: {
|
||||||
|
name: "name",
|
||||||
|
type: "type",
|
||||||
|
},
|
||||||
|
getEntities: undefined,
|
||||||
|
getEntity: undefined,
|
||||||
|
updateEntity: {
|
||||||
|
id: 1,
|
||||||
|
name: "name",
|
||||||
|
type: "type",
|
||||||
|
},
|
||||||
|
patchEntity: {
|
||||||
|
id: 1,
|
||||||
|
name: "name",
|
||||||
|
type: "type",
|
||||||
|
},
|
||||||
|
deleteEntity: undefined,
|
||||||
|
}
|
||||||
|
await runTests("crud", testBody, assertions)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -23,14 +23,27 @@ const oapi2CrudYaml = getData("openapi2/data/crud/crud.json")
|
||||||
const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json")
|
const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json")
|
||||||
const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json")
|
const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json")
|
||||||
|
|
||||||
|
// openapi3
|
||||||
|
const oapi3CrudJson = getData("openapi3/data/crud/crud.json")
|
||||||
|
const oapi3CrudYaml = getData("openapi3/data/crud/crud.json")
|
||||||
|
const oapi3PetstoreJson = getData("openapi3/data/petstore/petstore.json")
|
||||||
|
const oapi3PetstoreYaml = getData("openapi3/data/petstore/petstore.json")
|
||||||
|
|
||||||
// curl
|
// curl
|
||||||
const curl = getData("curl/data/post.txt")
|
const curl = getData("curl/data/post.txt")
|
||||||
|
|
||||||
const datasets = {
|
const datasets = {
|
||||||
|
// openapi2 (swagger)
|
||||||
oapi2CrudJson,
|
oapi2CrudJson,
|
||||||
oapi2CrudYaml,
|
oapi2CrudYaml,
|
||||||
oapi2PetstoreJson,
|
oapi2PetstoreJson,
|
||||||
oapi2PetstoreYaml,
|
oapi2PetstoreYaml,
|
||||||
|
// openapi3
|
||||||
|
oapi3CrudJson,
|
||||||
|
oapi3CrudYaml,
|
||||||
|
oapi3PetstoreJson,
|
||||||
|
oapi3PetstoreYaml,
|
||||||
|
// curl
|
||||||
curl
|
curl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +69,7 @@ describe("Rest Importer", () => {
|
||||||
|
|
||||||
it("gets info", async () => {
|
it("gets info", async () => {
|
||||||
const assertions = {
|
const assertions = {
|
||||||
|
// openapi2 (swagger)
|
||||||
"oapi2CrudJson" : {
|
"oapi2CrudJson" : {
|
||||||
name: "CRUD",
|
name: "CRUD",
|
||||||
},
|
},
|
||||||
|
@ -68,6 +82,20 @@ describe("Rest Importer", () => {
|
||||||
"oapi2PetstoreYaml" :{
|
"oapi2PetstoreYaml" :{
|
||||||
name: "Swagger Petstore",
|
name: "Swagger Petstore",
|
||||||
},
|
},
|
||||||
|
// openapi3
|
||||||
|
"oapi3CrudJson" : {
|
||||||
|
name: "CRUD",
|
||||||
|
},
|
||||||
|
"oapi3CrudYaml" : {
|
||||||
|
name: "CRUD",
|
||||||
|
},
|
||||||
|
"oapi3PetstoreJson" : {
|
||||||
|
name: "Swagger Petstore - OpenAPI 3.0",
|
||||||
|
},
|
||||||
|
"oapi3PetstoreYaml" :{
|
||||||
|
name: "Swagger Petstore - OpenAPI 3.0",
|
||||||
|
},
|
||||||
|
// curl
|
||||||
"curl": {
|
"curl": {
|
||||||
name: "example.com",
|
name: "example.com",
|
||||||
}
|
}
|
||||||
|
@ -89,6 +117,7 @@ describe("Rest Importer", () => {
|
||||||
// simple sanity assertions that the whole dataset
|
// simple sanity assertions that the whole dataset
|
||||||
// makes it through the importer
|
// makes it through the importer
|
||||||
const assertions = {
|
const assertions = {
|
||||||
|
// openapi2 (swagger)
|
||||||
"oapi2CrudJson" : {
|
"oapi2CrudJson" : {
|
||||||
count: 6,
|
count: 6,
|
||||||
},
|
},
|
||||||
|
@ -101,6 +130,20 @@ describe("Rest Importer", () => {
|
||||||
"oapi2PetstoreYaml" :{
|
"oapi2PetstoreYaml" :{
|
||||||
count: 20,
|
count: 20,
|
||||||
},
|
},
|
||||||
|
// openapi3
|
||||||
|
"oapi3CrudJson" : {
|
||||||
|
count: 6,
|
||||||
|
},
|
||||||
|
"oapi3CrudYaml" :{
|
||||||
|
count: 6,
|
||||||
|
},
|
||||||
|
"oapi3PetstoreJson" : {
|
||||||
|
count: 19,
|
||||||
|
},
|
||||||
|
"oapi3PetstoreYaml" :{
|
||||||
|
count: 19,
|
||||||
|
},
|
||||||
|
// curl
|
||||||
"curl": {
|
"curl": {
|
||||||
count: 1
|
count: 1
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue