diff --git a/demo/index.tsx b/demo/index.tsx index b6f1fe0571..e5e48c00e2 100644 --- a/demo/index.tsx +++ b/demo/index.tsx @@ -5,7 +5,11 @@ import { resolve as urlResolve } from 'url'; import { RedocStandalone } from '../src'; import ComboBox from './ComboBox'; +const DEFAULT_SPEC = 'openapi.yaml'; +const NEW_VERSION_SPEC = 'openapi-3-1.yaml'; + const demos = [ + { value: NEW_VERSION_SPEC, label: 'OpenApi 3.1' }, { value: 'https://api.apis.guru/v2/specs/instagram.com/1.0.0/swagger.yaml', label: 'Instagram' }, { value: 'https://api.apis.guru/v2/specs/googleapis.com/calendar/v3/openapi.yaml', @@ -16,8 +20,6 @@ const demos = [ { value: 'https://docs.graphhopper.com/openapi.json', label: 'GraphHopper' }, ]; -const DEFAULT_SPEC = 'openapi.yaml'; - class DemoApp extends React.Component< {}, { specUrl: string; dropdownOpen: boolean; cors: boolean } @@ -45,6 +47,9 @@ class DemoApp extends React.Component< } handleChange = (url: string) => { + if (url === NEW_VERSION_SPEC) { + this.setState({ cors: false }) + } this.setState({ specUrl: url, }); diff --git a/demo/openapi-3-1.yaml b/demo/openapi-3-1.yaml new file mode 100644 index 0000000000..026ff0aed6 --- /dev/null +++ b/demo/openapi-3-1.yaml @@ -0,0 +1,1249 @@ +openapi: 3.1.0 +servers: + - url: //petstore.swagger.io/v2 + description: Default server + - url: //petstore.swagger.io/sandbox + description: Sandbox server +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. + + # Introduction + This API is documented in **OpenAPI format** and is based on + [Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team. + It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo) + tool and [ReDoc](https://github.com/Redocly/redoc) documentation. In addition to standard + OpenAPI syntax we use a few [vendor extensions](https://github.com/Redocly/redoc/blob/master/docs/redoc-vendor-extensions.md). + + # OpenAPI Specification + This API is documented in **OpenAPI format** and is based on + [Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team. + It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo) + tool and [ReDoc](https://github.com/Redocly/redoc) documentation. In addition to standard + OpenAPI syntax we use a few [vendor extensions](https://github.com/Redocly/redoc/blob/master/docs/redoc-vendor-extensions.md). + + # Cross-Origin Resource Sharing + This API features Cross-Origin Resource Sharing (CORS) implemented in compliance with [W3C spec](https://www.w3.org/TR/cors/). + And that allows cross-domain communication from the browser. + All responses have a wildcard same-origin which makes them completely public and accessible to everyone, including any code on any site. + + # Authentication + + Petstore offers two forms of authentication: + - API Key + - OAuth2 + OAuth2 - an open protocol to allow secure authorization in a simple + and standard method from web, mobile and desktop applications. + + + + version: 1.0.0 + title: Swagger Petstore + summary: My lovely API + termsOfService: 'http://swagger.io/terms/' + contact: + name: API Support + email: apiteam@swagger.io + url: https://github.com/Redocly/redoc + x-logo: + url: 'https://redocly.github.io/redoc/petstore-logo.png' + altText: Petstore logo + license: + name: Apache 2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' + identifier: Apache 2.0 +externalDocs: + description: Find out how to create Github repo for your OpenAPI spec. + url: 'https://github.com/Rebilly/generator-openapi-repo' +tags: + - name: pet + description: Everything about your Pets + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user + - name: webhooks + description: Everything about your Webhooks + - name: pet_model + x-displayName: The Pet Model + description: | + + - name: store_model + x-displayName: The Order Model + description: | + +x-tagGroups: + - name: General + tags: + - pet + - store + - webhooks + - name: User Management + tags: + - user + - name: Models + tags: + - pet_model + - store_model +paths: + /pet: + parameters: + - name: Accept-Language + in: header + description: "The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US" + example: en-US + required: false + schema: + type: string + default: en-AU + - name: cookieParam + in: cookie + description: Some cookie + required: true + schema: + type: integer + format: int64 + post: + tags: + - pet + summary: Add a new pet to the store + description: Add new pet to the store inventory. + operationId: addPet + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + x-codeSamples: + - lang: 'C#' + source: | + PetStore.v1.Pet pet = new PetStore.v1.Pet(); + pet.setApiKey("your api key"); + pet.petType = PetStore.v1.Pet.TYPE_DOG; + pet.name = "Rex"; + // set other fields + PetStoreResponse response = pet.create(); + if (response.statusCode == HttpStatusCode.Created) + { + // Successfully created + } + else + { + // Something wrong -- check response for errors + Console.WriteLine(response.getRawResponse()); + } + - lang: PHP + source: | + $form = new \PetStore\Entities\Pet(); + $form->setPetType("Dog"); + $form->setName("Rex"); + // set other fields + try { + $pet = $client->pets()->create($form); + } catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); + } + requestBody: + $ref: '#/components/requestBodies/Pet' + put: + tags: + - pet + summary: Update an existing pet + description: '' + operationId: updatePet + responses: + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + x-codeSamples: + - lang: PHP + source: | + $form = new \PetStore\Entities\Pet(); + $form->setPetId(1); + $form->setPetType("Dog"); + $form->setName("Rex"); + // set other fields + try { + $pet = $client->pets()->update($form); + } catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); + } + requestBody: + $ref: '#/components/requestBodies/Pet' + '/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 + deprecated: 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: [] + 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 + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + delete: + tags: + - pet + summary: Deletes a pet + description: '' + operationId: deletePet + parameters: + - name: api_key + in: header + required: false + schema: + type: string + example: "Bearer " + - 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 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + /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: true + style: form + schema: + type: array + minItems: 1 + maxItems: 3 + items: + type: string + enum: + - available + - pending + - sold + default: available + 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 + deprecated: true + parameters: + - name: tags + in: query + description: Tags to filter by + required: true + style: form + 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' + /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: '' + operationId: placeOrder + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid Order + content: + application/json: + example: + status: 400 + message: "Invalid Order" + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + '/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 pet that needs to be fetched + required: true + schema: + type: integer + format: int64 + minimum: 1 + maximum: 5 + 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: string + minimum: 1 + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /store/subscribe: + post: + tags: + - store + summary: Subscribe to the Store events + description: Add subscription for a store events + requestBody: + content: + application/json: + schema: + type: object + properties: + callbackUrl: + type: string + format: uri + description: This URL will be called by the server when the desired event will occur + example: https://myserver.com/send/callback/here + eventName: + type: string + description: Event name for the subscription + enum: + - orderInProgress + - orderShipped + - orderDelivered + example: orderInProgress + required: + - callbackUrl + - eventName + responses: + '201': + description: Subscription added + content: + application/json: + schema: + type: object + properties: + subscriptionId: + type: string + example: AAA-123-BBB-456 + callbacks: + orderInProgress: + '{$request.body#/callbackUrl}?event={$request.body#/eventName}': + servers: + - url: //callback-url.path-level/v1 + description: Path level server 1 + - url: //callback-url.path-level/v2 + description: Path level server 2 + post: + summary: Order in Progress (Summary) + description: A callback triggered every time an Order is updated status to "inProgress" (Description) + externalDocs: + description: Find out more + url: 'https://more-details.com/demo' + requestBody: + content: + application/json: + schema: + type: object + properties: + orderId: + type: string + example: '123' + timestamp: + type: string + format: date-time + example: '2018-10-19T16:46:45Z' + status: + type: string + example: 'inProgress' + application/xml: + schema: + type: object + properties: + orderId: + type: string + example: '123' + example: | + + + 123 + inProgress + 2018-10-19T16:46:45Z + + responses: + '200': + description: Callback successfully processed and no retries will be performed + content: + application/json: + schema: + type: object + properties: + someProp: + type: string + example: '123' + '299': + description: Response for cancelling subscription + '500': + description: Callback processing failed and retries will be performed + x-codeSamples: + - lang: 'C#' + source: | + PetStore.v1.Pet pet = new PetStore.v1.Pet(); + pet.setApiKey("your api key"); + pet.petType = PetStore.v1.Pet.TYPE_DOG; + pet.name = "Rex"; + // set other fields + PetStoreResponse response = pet.create(); + if (response.statusCode == HttpStatusCode.Created) + { + // Successfully created + } + else + { + // Something wrong -- check response for errors + Console.WriteLine(response.getRawResponse()); + } + - lang: PHP + source: | + $form = new \PetStore\Entities\Pet(); + $form->setPetType("Dog"); + $form->setName("Rex"); + // set other fields + try { + $pet = $client->pets()->create($form); + } catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); + } + put: + description: Order in Progress (Only Description) + servers: + - url: //callback-url.operation-level/v1 + description: Operation level server 1 (Operation override) + - url: //callback-url.operation-level/v2 + description: Operation level server 2 (Operation override) + requestBody: + content: + application/json: + schema: + type: object + properties: + orderId: + type: string + example: '123' + timestamp: + type: string + format: date-time + example: '2018-10-19T16:46:45Z' + status: + type: string + example: 'inProgress' + application/xml: + schema: + type: object + properties: + orderId: + type: string + example: '123' + example: | + + + 123 + inProgress + 2018-10-19T16:46:45Z + + responses: + '200': + description: Callback successfully processed and no retries will be performed + content: + application/json: + schema: + type: object + properties: + someProp: + type: string + example: '123' + orderShipped: + '{$request.body#/callbackUrl}?event={$request.body#/eventName}': + post: + description: | + Very long description + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis + nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu + fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + requestBody: + content: + application/json: + schema: + type: object + properties: + orderId: + type: string + example: '123' + timestamp: + type: string + format: date-time + example: '2018-10-19T16:46:45Z' + estimatedDeliveryDate: + type: string + format: date-time + example: '2018-11-11T16:00:00Z' + responses: + '200': + description: Callback successfully processed and no retries will be performed + orderDelivered: + 'http://notificationServer.com?url={$request.body#/callbackUrl}&event={$request.body#/eventName}': + post: + deprecated: true + summary: Order delivered + description: A callback triggered every time an Order is delivered to the recipient + requestBody: + content: + application/json: + schema: + type: object + properties: + orderId: + type: string + example: '123' + timestamp: + type: string + format: date-time + example: '2018-10-19T16:46:45Z' + responses: + '200': + description: Callback successfully processed and no retries will be performed + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + responses: + default: + description: successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + '/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: Updated 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 + responses: + '400': + description: Invalid user supplied + '404': + description: User not found + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + 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 + /user/createWithArray: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithArrayInput + responses: + default: + description: successful operation + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithListInput + responses: + default: + description: successful operation + requestBody: + $ref: '#/components/requestBodies/UserArray' + /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: true + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: true + 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/json: + schema: + type: string + examples: + response: + value: OK + application/xml: + schema: + type: string + examples: + response: + value: OK + text/plain: + examples: + response: + value: OK + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + responses: + default: + description: successful operation +components: + pathItems: + webhooks: + put: + summary: Get a cat details after update + description: Get a cat details after update + operationId: updatedCat + tags: + - webhooks + requestBody: + description: Information about cat in the system + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/Cat" + responses: + '200': + description: update Cat details + post: + summary: Create new cat + description: Info about new cat + operationId: createdCat + tags: + - webhooks + requestBody: + description: Information about cat in the system + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/Cat" + responses: + '200': + description: create Cat details + schemas: + ApiResponse: + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string + Cat: + description: A representation of a cat + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + properties: + huntingSkill: + type: string + description: The measured skill for hunting + default: lazy + example: adventurous + enum: + - clueless + - lazy + - adventurous + - aggressive + required: + - huntingSkill + Category: + type: object + properties: + id: + description: Category ID + allOf: + - $ref: '#/components/schemas/Id' + name: + description: Category name + type: string + minLength: 1 + sub: + description: Test Sub Category + type: object + properties: + prop1: + type: string + description: Dumb Property + xml: + name: Category + Dog: + description: A representation of a dog + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + properties: + packSize: + type: integer + format: int32 + description: The size of the pack the dog is from + default: 1 + minimum: 1 + required: + - packSize + HoneyBee: + description: A representation of a honey bee + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + properties: + honeyPerDay: + type: number + description: Average amount of honey produced per day in ounces + example: 3.14 + multipleOf: .01 + required: + - honeyPerDay + Id: + type: integer + format: int64 + readOnly: true + Order: + type: object + properties: + id: + description: Order ID + allOf: + - $ref: '#/components/schemas/Id' + petId: + description: Pet ID + allOf: + - $ref: '#/components/schemas/Id' + quantity: + type: integer + format: int32 + minimum: 1 + default: 1 + shipDate: + description: Estimated ship date + type: string + format: date-time + status: + type: string + description: Order Status + enum: + - placed + - approved + - delivered + complete: + description: Indicates whenever order was completed or not + type: boolean + default: false + readOnly: true + requestId: + description: Unique Request Id + type: string + writeOnly: true + xml: + name: Order + Pet: + type: object + required: + - name + - photoUrls + discriminator: + propertyName: petType + mapping: + cat: '#/components/schemas/Cat' + dog: '#/components/schemas/Dog' + bee: '#/components/schemas/HoneyBee' + properties: + id: + externalDocs: + description: "Find more info here" + url: "https://example.com" + description: Pet ID + allOf: + - $ref: '#/components/schemas/Id' + category: + description: Categories this pet belongs to + allOf: + - $ref: '#/components/schemas/Category' + name: + description: The name given to a pet + type: string + example: Guru + photoUrls: + description: The list of URL to a cute photos featuring pet + type: [string, integer, 'null', array] + minItems: 1 + maxItems: 20 + xml: + name: photoUrl + wrapped: true + items: + type: string + format: url + friend: + allOf: + - $ref: '#/components/schemas/Pet' + tags: + description: Tags attached to the pet + type: array + exclusiveMaximum: 100 + exclusiveMinimum: 0 + xml: + name: tag + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: Pet status in the store + enum: + - available + - pending + - sold + default: pending + petType: + description: Type of a pet + type: string + xml: + name: Pet + Tag: + type: object + properties: + id: + description: Tag ID + allOf: + - $ref: '#/components/schemas/Id' + name: + description: Tag name + type: string + minLength: 1 + xml: + name: Tag + User: + type: object + properties: + id: + $ref: '#/components/schemas/Id' + pet: + oneOf: + - $ref: '#/components/schemas/Pet' + - $ref: '#/components/schemas/Tag' + username: + description: User supplied username + type: string + minLength: 4 + example: John78 + firstName: + description: User first name + type: string + minLength: 1 + example: John + lastName: + description: User last name + type: string + minLength: 1 + example: Smith + email: + description: User email address + type: string + format: email + example: john.smith@example.com + password: + type: string + description: >- + User password, MUST contain a mix of upper and lower case letters, + as well as digits + format: password + minLength: 8 + pattern: '/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/' + example: drowssaP123 + phone: + description: User phone number in international format + type: string + pattern: '/^\+(?:[0-9]-?){6,14}[0-9]$/' + example: +1-202-555-0192 + userStatus: + description: User status + type: integer + format: int32 + xml: + name: User + requestBodies: + Pet: + content: + application/json: + schema: + allOf: + - description: My Pet + title: Pettie + - $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: 'object' + properties: + name: + type: string + description: hooray + description: Pet object that needs to be added to the store + required: true + UserArray: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + description: List of user object + required: true + securitySchemes: + petstore_auth: + description: | + Get access to data while protecting your account credentials. + OAuth2 is also a safer and more secure way to give you access. + type: oauth2 + flows: + implicit: + authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + description: > + For this sample, you can use the api key `special-key` to test the + authorization filters. + type: apiKey + name: api_key + in: header + examples: + Order: + value: + quantity: 1 + shipDate: '2018-10-19T16:46:45Z' + status: placed + complete: false +webhooks: + newPet: + post: + summary: New pet + description: Information about a new pet in the systems + operationId: newPet + tags: + - webhooks + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + "200": + description: Return a 200 status to indicate that the data was received successfully + myWebhook: + $ref: '#/components/pathItems/webhooks' + description: Overriding description + summary: Overriding summary \ No newline at end of file diff --git a/demo/openapi.yaml b/demo/openapi.yaml index 1b363c5566..74c16b70f2 100644 --- a/demo/openapi.yaml +++ b/demo/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.0 servers: - url: //petstore.swagger.io/v2 description: Default server @@ -42,7 +42,6 @@ info: version: 1.0.0 title: Swagger Petstore - summary: My lovely API termsOfService: 'http://swagger.io/terms/' contact: name: API Support @@ -54,15 +53,12 @@ info: license: name: Apache 2.0 url: 'http://www.apache.org/licenses/LICENSE-2.0.html' - identifier: Apache 2.0 externalDocs: description: Find out how to create Github repo for your OpenAPI spec. url: 'https://github.com/Rebilly/generator-openapi-repo' tags: - name: pet description: Everything about your Pets - - name: webhooks - description: Everything about your Webhooks - name: store description: Access to Petstore orders - name: user @@ -80,7 +76,6 @@ x-tagGroups: tags: - pet - store - - webhooks - name: User Management tags: - user @@ -898,38 +893,6 @@ paths: default: description: successful operation components: - pathItems: - webhooks: - put: - summary: Get a cat details after update - description: Get a cat details after update - operationId: updatedCat - tags: - - webhooks - requestBody: - description: Information about cat in the system - content: - multipart/form-data: - schema: - $ref: "#/components/schemas/Cat" - responses: - '200': - description: update Cat details - post: - summary: Create new cat - description: Info about new cat - operationId: createdCat - tags: - - webhooks - requestBody: - description: Information about cat in the system - content: - multipart/form-data: - schema: - $ref: "#/components/schemas/Cat" - responses: - '200': - description: create Cat details schemas: ApiResponse: type: object @@ -1077,8 +1040,7 @@ components: example: Guru photoUrls: description: The list of URL to a cute photos featuring pet - type: [string, integer, 'null', array] - minItems: 1 + type: array maxItems: 20 xml: name: photoUrl @@ -1092,8 +1054,7 @@ components: tags: description: Tags attached to the pet type: array - exclusiveMaximum: 100 - exclusiveMinimum: 0 + minItems: 1 xml: name: tag wrapped: true @@ -1106,7 +1067,6 @@ components: - available - pending - sold - default: pending petType: description: Type of a pet type: string @@ -1227,14 +1187,14 @@ components: shipDate: '2018-10-19T16:46:45Z' status: placed complete: false -webhooks: +x-webhooks: newPet: post: summary: New pet description: Information about a new pet in the systems operationId: newPet - tags: - - webhooks + tags: + - pet requestBody: content: application/json: @@ -1242,8 +1202,4 @@ webhooks: $ref: "#/components/schemas/Pet" responses: "200": - description: Return a 200 status to indicate that the data was received successfully - myWebhook: - $ref: '#/components/pathItems/webhooks' - description: Overriding description - summary: Overriding summary \ No newline at end of file + description: Return a 200 status to indicate that the data was received successfully \ No newline at end of file diff --git a/e2e/integration/menu.e2e.ts b/e2e/integration/menu.e2e.ts index 89ac53d9ce..e1b053d125 100644 --- a/e2e/integration/menu.e2e.ts +++ b/e2e/integration/menu.e2e.ts @@ -6,7 +6,7 @@ describe('Menu', () => { it('should have valid items count', () => { cy.get('.menu-content') .find('li') - .should('have.length', 37); + .should('have.length', 34); }); it('should sync active menu items while scroll', () => { diff --git a/e2e/integration/standalone.e2e.ts b/e2e/integration/standalone.e2e.ts index 587c73b4a1..918ef51f8c 100644 --- a/e2e/integration/standalone.e2e.ts +++ b/e2e/integration/standalone.e2e.ts @@ -16,5 +16,6 @@ describe('Standalone bundle test', () => { } baseCheck('OAS3 mode', 'e2e/standalone.html'); + baseCheck('OAS3.1 mode', 'e2e/standalone-3-1.html'); baseCheck('OAS2 compatibility mode', 'e2e/standalone-compatibility.html'); }); diff --git a/e2e/standalone-3-1.html b/e2e/standalone-3-1.html new file mode 100644 index 0000000000..a9d459a595 --- /dev/null +++ b/e2e/standalone-3-1.html @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap b/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap index ecd32e05cb..c878803796 100644 --- a/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap +++ b/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap @@ -1,6 +1,1802 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`#loadAndBundleSpec should load And Bundle Spec demo/openapi.yaml 1`] = ` +Object { + "components": Object { + "examples": Object { + "Order": Object { + "value": Object { + "complete": false, + "quantity": 1, + "shipDate": "2018-10-19T16:46:45Z", + "status": "placed", + }, + }, + }, + "requestBodies": Object { + "Pet": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "allOf": Array [ + Object { + "description": "My Pet", + "title": "Pettie", + }, + Object { + "$ref": "#/components/schemas/Pet", + }, + ], + }, + }, + "application/xml": Object { + "schema": Object { + "properties": Object { + "name": Object { + "description": "hooray", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Pet object that needs to be added to the store", + "required": true, + }, + "UserArray": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "items": Object { + "$ref": "#/components/schemas/User", + }, + "type": "array", + }, + }, + }, + "description": "List of user object", + "required": true, + }, + }, + "schemas": Object { + "ApiResponse": Object { + "properties": Object { + "code": Object { + "format": "int32", + "type": "integer", + }, + "message": Object { + "type": "string", + }, + "type": Object { + "type": "string", + }, + }, + "type": "object", + }, + "Cat": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Pet", + }, + Object { + "properties": Object { + "huntingSkill": Object { + "default": "lazy", + "description": "The measured skill for hunting", + "enum": Array [ + "clueless", + "lazy", + "adventurous", + "aggressive", + ], + "example": "adventurous", + "type": "string", + }, + }, + "required": Array [ + "huntingSkill", + ], + "type": "object", + }, + ], + "description": "A representation of a cat", + }, + "Category": Object { + "properties": Object { + "id": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Id", + }, + ], + "description": "Category ID", + }, + "name": Object { + "description": "Category name", + "minLength": 1, + "type": "string", + }, + "sub": Object { + "description": "Test Sub Category", + "properties": Object { + "prop1": Object { + "description": "Dumb Property", + "type": "string", + }, + }, + "type": "object", + }, + }, + "type": "object", + "xml": Object { + "name": "Category", + }, + }, + "Dog": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Pet", + }, + Object { + "properties": Object { + "packSize": Object { + "default": 1, + "description": "The size of the pack the dog is from", + "format": "int32", + "minimum": 1, + "type": "integer", + }, + }, + "required": Array [ + "packSize", + ], + "type": "object", + }, + ], + "description": "A representation of a dog", + }, + "HoneyBee": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Pet", + }, + Object { + "properties": Object { + "honeyPerDay": Object { + "description": "Average amount of honey produced per day in ounces", + "example": 3.14, + "multipleOf": 0.01, + "type": "number", + }, + }, + "required": Array [ + "honeyPerDay", + ], + "type": "object", + }, + ], + "description": "A representation of a honey bee", + }, + "Id": Object { + "format": "int64", + "readOnly": true, + "type": "integer", + }, + "Order": Object { + "properties": Object { + "complete": Object { + "default": false, + "description": "Indicates whenever order was completed or not", + "readOnly": true, + "type": "boolean", + }, + "id": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Id", + }, + ], + "description": "Order ID", + }, + "petId": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Id", + }, + ], + "description": "Pet ID", + }, + "quantity": Object { + "default": 1, + "format": "int32", + "minimum": 1, + "type": "integer", + }, + "requestId": Object { + "description": "Unique Request Id", + "type": "string", + "writeOnly": true, + }, + "shipDate": Object { + "description": "Estimated ship date", + "format": "date-time", + "type": "string", + }, + "status": Object { + "description": "Order Status", + "enum": Array [ + "placed", + "approved", + "delivered", + ], + "type": "string", + }, + }, + "type": "object", + "xml": Object { + "name": "Order", + }, + }, + "Pet": Object { + "discriminator": Object { + "mapping": Object { + "bee": "#/components/schemas/HoneyBee", + "cat": "#/components/schemas/Cat", + "dog": "#/components/schemas/Dog", + }, + "propertyName": "petType", + }, + "properties": Object { + "category": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Category", + }, + ], + "description": "Categories this pet belongs to", + }, + "friend": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Pet", + }, + ], + }, + "id": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Id", + }, + ], + "description": "Pet ID", + "externalDocs": Object { + "description": "Find more info here", + "url": "https://example.com", + }, + }, + "name": Object { + "description": "The name given to a pet", + "example": "Guru", + "type": "string", + }, + "petType": Object { + "description": "Type of a pet", + "type": "string", + }, + "photoUrls": Object { + "description": "The list of URL to a cute photos featuring pet", + "items": Object { + "format": "url", + "type": "string", + }, + "maxItems": 20, + "type": "array", + "xml": Object { + "name": "photoUrl", + "wrapped": true, + }, + }, + "status": Object { + "description": "Pet status in the store", + "enum": Array [ + "available", + "pending", + "sold", + ], + "type": "string", + }, + "tags": Object { + "description": "Tags attached to the pet", + "items": Object { + "$ref": "#/components/schemas/Tag", + }, + "minItems": 1, + "type": "array", + "xml": Object { + "name": "tag", + "wrapped": true, + }, + }, + }, + "required": Array [ + "name", + "photoUrls", + ], + "type": "object", + "xml": Object { + "name": "Pet", + }, + }, + "Tag": Object { + "properties": Object { + "id": Object { + "allOf": Array [ + Object { + "$ref": "#/components/schemas/Id", + }, + ], + "description": "Tag ID", + }, + "name": Object { + "description": "Tag name", + "minLength": 1, + "type": "string", + }, + }, + "type": "object", + "xml": Object { + "name": "Tag", + }, + }, + "User": Object { + "properties": Object { + "email": Object { + "description": "User email address", + "example": "john.smith@example.com", + "format": "email", + "type": "string", + }, + "firstName": Object { + "description": "User first name", + "example": "John", + "minLength": 1, + "type": "string", + }, + "id": Object { + "$ref": "#/components/schemas/Id", + }, + "lastName": Object { + "description": "User last name", + "example": "Smith", + "minLength": 1, + "type": "string", + }, + "password": Object { + "description": "User password, MUST contain a mix of upper and lower case letters, as well as digits", + "example": "drowssaP123", + "format": "password", + "minLength": 8, + "pattern": "/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/", + "type": "string", + }, + "pet": Object { + "oneOf": Array [ + Object { + "$ref": "#/components/schemas/Pet", + }, + Object { + "$ref": "#/components/schemas/Tag", + }, + ], + }, + "phone": Object { + "description": "User phone number in international format", + "example": "+1-202-555-0192", + "pattern": "/^\\\\+(?:[0-9]-?){6,14}[0-9]$/", + "type": "string", + }, + "userStatus": Object { + "description": "User status", + "format": "int32", + "type": "integer", + }, + "username": Object { + "description": "User supplied username", + "example": "John78", + "minLength": 4, + "type": "string", + }, + }, + "type": "object", + "xml": Object { + "name": "User", + }, + }, + }, + "securitySchemes": Object { + "api_key": Object { + "description": "For this sample, you can use the api key \`special-key\` to test the authorization filters. +", + "in": "header", + "name": "api_key", + "type": "apiKey", + }, + "petstore_auth": Object { + "description": "Get access to data while protecting your account credentials. +OAuth2 is also a safer and more secure way to give you access. +", + "flows": Object { + "implicit": Object { + "authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog", + "scopes": Object { + "read:pets": "read your pets", + "write:pets": "modify pets in your account", + }, + }, + }, + "type": "oauth2", + }, + }, + }, + "externalDocs": Object { + "description": "Find out how to create Github repo for your OpenAPI spec.", + "url": "https://github.com/Rebilly/generator-openapi-repo", + }, + "info": Object { + "contact": Object { + "email": "apiteam@swagger.io", + "name": "API Support", + "url": "https://github.com/Redocly/redoc", + }, + "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. + +# Introduction +This API is documented in **OpenAPI format** and is based on +[Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team. +It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo) +tool and [ReDoc](https://github.com/Redocly/redoc) documentation. In addition to standard +OpenAPI syntax we use a few [vendor extensions](https://github.com/Redocly/redoc/blob/master/docs/redoc-vendor-extensions.md). + +# OpenAPI Specification +This API is documented in **OpenAPI format** and is based on +[Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team. +It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo) +tool and [ReDoc](https://github.com/Redocly/redoc) documentation. In addition to standard +OpenAPI syntax we use a few [vendor extensions](https://github.com/Redocly/redoc/blob/master/docs/redoc-vendor-extensions.md). + +# Cross-Origin Resource Sharing +This API features Cross-Origin Resource Sharing (CORS) implemented in compliance with [W3C spec](https://www.w3.org/TR/cors/). +And that allows cross-domain communication from the browser. +All responses have a wildcard same-origin which makes them completely public and accessible to everyone, including any code on any site. + +# Authentication + +Petstore offers two forms of authentication: + - API Key + - OAuth2 +OAuth2 - an open protocol to allow secure authorization in a simple +and standard method from web, mobile and desktop applications. + + +", + "license": Object { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html", + }, + "termsOfService": "http://swagger.io/terms/", + "title": "Swagger Petstore", + "version": "1.0.0", + "x-logo": Object { + "altText": "Petstore logo", + "url": "https://redocly.github.io/redoc/petstore-logo.png", + }, + }, + "openapi": "3.0.0", + "paths": Object { + "/pet": Object { + "parameters": Array [ + Object { + "description": "The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US", + "example": "en-US", + "in": "header", + "name": "Accept-Language", + "required": false, + "schema": Object { + "default": "en-AU", + "type": "string", + }, + }, + Object { + "description": "Some cookie", + "in": "cookie", + "name": "cookieParam", + "required": true, + "schema": Object { + "format": "int64", + "type": "integer", + }, + }, + ], + "post": Object { + "description": "Add new pet to the store inventory.", + "operationId": "addPet", + "requestBody": Object { + "$ref": "#/components/requestBodies/Pet", + }, + "responses": Object { + "405": Object { + "description": "Invalid input", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Add a new pet to the store", + "tags": Array [ + "pet", + ], + "x-codeSamples": Array [ + Object { + "lang": "C#", + "source": "PetStore.v1.Pet pet = new PetStore.v1.Pet(); +pet.setApiKey(\\"your api key\\"); +pet.petType = PetStore.v1.Pet.TYPE_DOG; +pet.name = \\"Rex\\"; +// set other fields +PetStoreResponse response = pet.create(); +if (response.statusCode == HttpStatusCode.Created) +{ + // Successfully created +} +else +{ + // Something wrong -- check response for errors + Console.WriteLine(response.getRawResponse()); +} +", + }, + Object { + "lang": "PHP", + "source": "$form = new \\\\PetStore\\\\Entities\\\\Pet(); +$form->setPetType(\\"Dog\\"); +$form->setName(\\"Rex\\"); +// set other fields +try { + $pet = $client->pets()->create($form); +} catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); +} +", + }, + ], + }, + "put": Object { + "description": "", + "operationId": "updatePet", + "requestBody": Object { + "$ref": "#/components/requestBodies/Pet", + }, + "responses": Object { + "400": Object { + "description": "Invalid ID supplied", + }, + "404": Object { + "description": "Pet not found", + }, + "405": Object { + "description": "Validation exception", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Update an existing pet", + "tags": Array [ + "pet", + ], + "x-codeSamples": Array [ + Object { + "lang": "PHP", + "source": "$form = new \\\\PetStore\\\\Entities\\\\Pet(); +$form->setPetId(1); +$form->setPetType(\\"Dog\\"); +$form->setName(\\"Rex\\"); +// set other fields +try { + $pet = $client->pets()->update($form); +} catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); +} +", + }, + ], + }, + }, + "/pet/findByStatus": Object { + "get": Object { + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": Array [ + Object { + "description": "Status values that need to be considered for filter", + "in": "query", + "name": "status", + "required": true, + "schema": Object { + "items": Object { + "default": "available", + "enum": Array [ + "available", + "pending", + "sold", + ], + "type": "string", + }, + "maxItems": 3, + "minItems": 1, + "type": "array", + }, + "style": "form", + }, + ], + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "items": Object { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + "application/xml": Object { + "schema": Object { + "items": Object { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + }, + "description": "successful operation", + }, + "400": Object { + "description": "Invalid status value", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Finds Pets by status", + "tags": Array [ + "pet", + ], + }, + }, + "/pet/findByTags": Object { + "get": Object { + "deprecated": true, + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": Array [ + Object { + "description": "Tags to filter by", + "in": "query", + "name": "tags", + "required": true, + "schema": Object { + "items": Object { + "type": "string", + }, + "type": "array", + }, + "style": "form", + }, + ], + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "items": Object { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + "application/xml": Object { + "schema": Object { + "items": Object { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + }, + "description": "successful operation", + }, + "400": Object { + "description": "Invalid tag value", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Finds Pets by tags", + "tags": Array [ + "pet", + ], + }, + }, + "/pet/{petId}": Object { + "delete": Object { + "description": "", + "operationId": "deletePet", + "parameters": Array [ + Object { + "example": "Bearer ", + "in": "header", + "name": "api_key", + "required": false, + "schema": Object { + "type": "string", + }, + }, + Object { + "description": "Pet id to delete", + "in": "path", + "name": "petId", + "required": true, + "schema": Object { + "format": "int64", + "type": "integer", + }, + }, + ], + "responses": Object { + "400": Object { + "description": "Invalid pet value", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Deletes a pet", + "tags": Array [ + "pet", + ], + }, + "get": Object { + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": Array [ + Object { + "deprecated": true, + "description": "ID of pet to return", + "in": "path", + "name": "petId", + "required": true, + "schema": Object { + "format": "int64", + "type": "integer", + }, + }, + ], + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/Pet", + }, + }, + "application/xml": Object { + "schema": Object { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + "description": "successful operation", + }, + "400": Object { + "description": "Invalid ID supplied", + }, + "404": Object { + "description": "Pet not found", + }, + }, + "security": Array [ + Object { + "api_key": Array [], + }, + ], + "summary": "Find pet by ID", + "tags": Array [ + "pet", + ], + }, + "post": Object { + "description": "", + "operationId": "updatePetWithForm", + "parameters": Array [ + Object { + "description": "ID of pet that needs to be updated", + "in": "path", + "name": "petId", + "required": true, + "schema": Object { + "format": "int64", + "type": "integer", + }, + }, + ], + "requestBody": Object { + "content": Object { + "application/x-www-form-urlencoded": Object { + "schema": Object { + "properties": Object { + "name": Object { + "description": "Updated name of the pet", + "type": "string", + }, + "status": Object { + "description": "Updated status of the pet", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + }, + "responses": Object { + "405": Object { + "description": "Invalid input", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Updates a pet in the store with form data", + "tags": Array [ + "pet", + ], + }, + }, + "/pet/{petId}/uploadImage": Object { + "post": Object { + "description": "", + "operationId": "uploadFile", + "parameters": Array [ + Object { + "description": "ID of pet to update", + "in": "path", + "name": "petId", + "required": true, + "schema": Object { + "format": "int64", + "type": "integer", + }, + }, + ], + "requestBody": Object { + "content": Object { + "application/octet-stream": Object { + "schema": Object { + "format": "binary", + "type": "string", + }, + }, + }, + }, + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/ApiResponse", + }, + }, + }, + "description": "successful operation", + }, + }, + "security": Array [ + Object { + "petstore_auth": Array [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "uploads an image", + "tags": Array [ + "pet", + ], + }, + }, + "/store/inventory": Object { + "get": Object { + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "additionalProperties": Object { + "format": "int32", + "type": "integer", + }, + "type": "object", + }, + }, + }, + "description": "successful operation", + }, + }, + "security": Array [ + Object { + "api_key": Array [], + }, + ], + "summary": "Returns pet inventories by status", + "tags": Array [ + "store", + ], + }, + }, + "/store/order": Object { + "post": Object { + "description": "", + "operationId": "placeOrder", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/Order", + }, + }, + }, + "description": "order placed for purchasing the pet", + "required": true, + }, + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/Order", + }, + }, + "application/xml": Object { + "schema": Object { + "$ref": "#/components/schemas/Order", + }, + }, + }, + "description": "successful operation", + }, + "400": Object { + "content": Object { + "application/json": Object { + "example": Object { + "message": "Invalid Order", + "status": 400, + }, + }, + }, + "description": "Invalid Order", + }, + }, + "summary": "Place an order for a pet", + "tags": Array [ + "store", + ], + }, + }, + "/store/order/{orderId}": Object { + "delete": Object { + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": Array [ + Object { + "description": "ID of the order that needs to be deleted", + "in": "path", + "name": "orderId", + "required": true, + "schema": Object { + "minimum": 1, + "type": "string", + }, + }, + ], + "responses": Object { + "400": Object { + "description": "Invalid ID supplied", + }, + "404": Object { + "description": "Order not found", + }, + }, + "summary": "Delete purchase order by ID", + "tags": Array [ + "store", + ], + }, + "get": Object { + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "operationId": "getOrderById", + "parameters": Array [ + Object { + "description": "ID of pet that needs to be fetched", + "in": "path", + "name": "orderId", + "required": true, + "schema": Object { + "format": "int64", + "maximum": 5, + "minimum": 1, + "type": "integer", + }, + }, + ], + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/Order", + }, + }, + "application/xml": Object { + "schema": Object { + "$ref": "#/components/schemas/Order", + }, + }, + }, + "description": "successful operation", + }, + "400": Object { + "description": "Invalid ID supplied", + }, + "404": Object { + "description": "Order not found", + }, + }, + "summary": "Find purchase order by ID", + "tags": Array [ + "store", + ], + }, + }, + "/store/subscribe": Object { + "post": Object { + "callbacks": Object { + "orderDelivered": Object { + "http://notificationServer.com?url={$request.body#/callbackUrl}&event={$request.body#/eventName}": Object { + "post": Object { + "deprecated": true, + "description": "A callback triggered every time an Order is delivered to the recipient", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "orderId": Object { + "example": "123", + "type": "string", + }, + "timestamp": Object { + "example": "2018-10-19T16:46:45Z", + "format": "date-time", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + }, + "responses": Object { + "200": Object { + "description": "Callback successfully processed and no retries will be performed", + }, + }, + "summary": "Order delivered", + }, + }, + }, + "orderInProgress": Object { + "{$request.body#/callbackUrl}?event={$request.body#/eventName}": Object { + "post": Object { + "description": "A callback triggered every time an Order is updated status to \\"inProgress\\" (Description)", + "externalDocs": Object { + "description": "Find out more", + "url": "https://more-details.com/demo", + }, + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "orderId": Object { + "example": "123", + "type": "string", + }, + "status": Object { + "example": "inProgress", + "type": "string", + }, + "timestamp": Object { + "example": "2018-10-19T16:46:45Z", + "format": "date-time", + "type": "string", + }, + }, + "type": "object", + }, + }, + "application/xml": Object { + "example": " + + 123 + inProgress + 2018-10-19T16:46:45Z + +", + "schema": Object { + "properties": Object { + "orderId": Object { + "example": "123", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + }, + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "someProp": Object { + "example": "123", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Callback successfully processed and no retries will be performed", + }, + "299": Object { + "description": "Response for cancelling subscription", + }, + "500": Object { + "description": "Callback processing failed and retries will be performed", + }, + }, + "summary": "Order in Progress (Summary)", + "x-codeSamples": Array [ + Object { + "lang": "C#", + "source": "PetStore.v1.Pet pet = new PetStore.v1.Pet(); +pet.setApiKey(\\"your api key\\"); +pet.petType = PetStore.v1.Pet.TYPE_DOG; +pet.name = \\"Rex\\"; +// set other fields +PetStoreResponse response = pet.create(); +if (response.statusCode == HttpStatusCode.Created) +{ + // Successfully created +} +else +{ + // Something wrong -- check response for errors + Console.WriteLine(response.getRawResponse()); +} +", + }, + Object { + "lang": "PHP", + "source": "$form = new \\\\PetStore\\\\Entities\\\\Pet(); +$form->setPetType(\\"Dog\\"); +$form->setName(\\"Rex\\"); +// set other fields +try { + $pet = $client->pets()->create($form); +} catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); +} +", + }, + ], + }, + "put": Object { + "description": "Order in Progress (Only Description)", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "orderId": Object { + "example": "123", + "type": "string", + }, + "status": Object { + "example": "inProgress", + "type": "string", + }, + "timestamp": Object { + "example": "2018-10-19T16:46:45Z", + "format": "date-time", + "type": "string", + }, + }, + "type": "object", + }, + }, + "application/xml": Object { + "example": " + + 123 + inProgress + 2018-10-19T16:46:45Z + +", + "schema": Object { + "properties": Object { + "orderId": Object { + "example": "123", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + }, + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "someProp": Object { + "example": "123", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Callback successfully processed and no retries will be performed", + }, + }, + "servers": Array [ + Object { + "description": "Operation level server 1 (Operation override)", + "url": "//callback-url.operation-level/v1", + }, + Object { + "description": "Operation level server 2 (Operation override)", + "url": "//callback-url.operation-level/v2", + }, + ], + }, + "servers": Array [ + Object { + "description": "Path level server 1", + "url": "//callback-url.path-level/v1", + }, + Object { + "description": "Path level server 2", + "url": "//callback-url.path-level/v2", + }, + ], + }, + }, + "orderShipped": Object { + "{$request.body#/callbackUrl}?event={$request.body#/eventName}": Object { + "post": Object { + "description": "Very long description +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor +incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis +nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu +fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in +culpa qui officia deserunt mollit anim id est laborum. +", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "estimatedDeliveryDate": Object { + "example": "2018-11-11T16:00:00Z", + "format": "date-time", + "type": "string", + }, + "orderId": Object { + "example": "123", + "type": "string", + }, + "timestamp": Object { + "example": "2018-10-19T16:46:45Z", + "format": "date-time", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + }, + "responses": Object { + "200": Object { + "description": "Callback successfully processed and no retries will be performed", + }, + }, + }, + }, + }, + }, + "description": "Add subscription for a store events", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "callbackUrl": Object { + "description": "This URL will be called by the server when the desired event will occur", + "example": "https://myserver.com/send/callback/here", + "format": "uri", + "type": "string", + }, + "eventName": Object { + "description": "Event name for the subscription", + "enum": Array [ + "orderInProgress", + "orderShipped", + "orderDelivered", + ], + "example": "orderInProgress", + "type": "string", + }, + }, + "required": Array [ + "callbackUrl", + "eventName", + ], + "type": "object", + }, + }, + }, + }, + "responses": Object { + "201": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "properties": Object { + "subscriptionId": Object { + "example": "AAA-123-BBB-456", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Subscription added", + }, + }, + "summary": "Subscribe to the Store events", + "tags": Array [ + "store", + ], + }, + }, + "/user": Object { + "post": Object { + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/User", + }, + }, + }, + "description": "Created user object", + "required": true, + }, + "responses": Object { + "default": Object { + "description": "successful operation", + }, + }, + "summary": "Create user", + "tags": Array [ + "user", + ], + }, + }, + "/user/createWithArray": Object { + "post": Object { + "description": "", + "operationId": "createUsersWithArrayInput", + "requestBody": Object { + "$ref": "#/components/requestBodies/UserArray", + }, + "responses": Object { + "default": Object { + "description": "successful operation", + }, + }, + "summary": "Creates list of users with given input array", + "tags": Array [ + "user", + ], + }, + }, + "/user/createWithList": Object { + "post": Object { + "description": "", + "operationId": "createUsersWithListInput", + "requestBody": Object { + "$ref": "#/components/requestBodies/UserArray", + }, + "responses": Object { + "default": Object { + "description": "successful operation", + }, + }, + "summary": "Creates list of users with given input array", + "tags": Array [ + "user", + ], + }, + }, + "/user/login": Object { + "get": Object { + "description": "", + "operationId": "loginUser", + "parameters": Array [ + Object { + "description": "The user name for login", + "in": "query", + "name": "username", + "required": true, + "schema": Object { + "type": "string", + }, + }, + Object { + "description": "The password for login in clear text", + "in": "query", + "name": "password", + "required": true, + "schema": Object { + "type": "string", + }, + }, + ], + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "examples": Object { + "response": Object { + "value": "OK", + }, + }, + "schema": Object { + "type": "string", + }, + }, + "application/xml": Object { + "examples": Object { + "response": Object { + "value": " OK ", + }, + }, + "schema": Object { + "type": "string", + }, + }, + "text/plain": Object { + "examples": Object { + "response": Object { + "value": "OK", + }, + }, + }, + }, + "description": "successful operation", + "headers": Object { + "X-Expires-After": Object { + "description": "date in UTC when token expires", + "schema": Object { + "format": "date-time", + "type": "string", + }, + }, + "X-Rate-Limit": Object { + "description": "calls per hour allowed by the user", + "schema": Object { + "format": "int32", + "type": "integer", + }, + }, + }, + }, + "400": Object { + "description": "Invalid username/password supplied", + }, + }, + "summary": "Logs user into the system", + "tags": Array [ + "user", + ], + }, + }, + "/user/logout": Object { + "get": Object { + "description": "", + "operationId": "logoutUser", + "responses": Object { + "default": Object { + "description": "successful operation", + }, + }, + "summary": "Logs out current logged in user session", + "tags": Array [ + "user", + ], + }, + }, + "/user/{username}": Object { + "delete": Object { + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "parameters": Array [ + Object { + "description": "The name that needs to be deleted", + "in": "path", + "name": "username", + "required": true, + "schema": Object { + "type": "string", + }, + }, + ], + "responses": Object { + "400": Object { + "description": "Invalid username supplied", + }, + "404": Object { + "description": "User not found", + }, + }, + "summary": "Delete user", + "tags": Array [ + "user", + ], + }, + "get": Object { + "description": "", + "operationId": "getUserByName", + "parameters": Array [ + Object { + "description": "The name that needs to be fetched. Use user1 for testing. ", + "in": "path", + "name": "username", + "required": true, + "schema": Object { + "type": "string", + }, + }, + ], + "responses": Object { + "200": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/User", + }, + }, + "application/xml": Object { + "schema": Object { + "$ref": "#/components/schemas/User", + }, + }, + }, + "description": "successful operation", + }, + "400": Object { + "description": "Invalid username supplied", + }, + "404": Object { + "description": "User not found", + }, + }, + "summary": "Get user by user name", + "tags": Array [ + "user", + ], + }, + "put": Object { + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "parameters": Array [ + Object { + "description": "name that need to be deleted", + "in": "path", + "name": "username", + "required": true, + "schema": Object { + "type": "string", + }, + }, + ], + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/User", + }, + }, + }, + "description": "Updated user object", + "required": true, + }, + "responses": Object { + "400": Object { + "description": "Invalid user supplied", + }, + "404": Object { + "description": "User not found", + }, + }, + "summary": "Updated user", + "tags": Array [ + "user", + ], + }, + }, + }, + "servers": Array [ + Object { + "description": "Default server", + "url": "//petstore.swagger.io/v2", + }, + Object { + "description": "Sandbox server", + "url": "//petstore.swagger.io/sandbox", + }, + ], + "tags": Array [ + Object { + "description": "Everything about your Pets", + "name": "pet", + }, + Object { + "description": "Access to Petstore orders", + "name": "store", + }, + Object { + "description": "Operations about user", + "name": "user", + }, + Object { + "description": " +", + "name": "pet_model", + "x-displayName": "The Pet Model", + }, + Object { + "description": " +", + "name": "store_model", + "x-displayName": "The Order Model", + }, + ], + "x-tagGroups": Array [ + Object { + "name": "General", + "tags": Array [ + "pet", + "store", + ], + }, + Object { + "name": "User Management", + "tags": Array [ + "user", + ], + }, + Object { + "name": "Models", + "tags": Array [ + "pet_model", + "store_model", + ], + }, + ], + "x-webhooks": Object { + "newPet": Object { + "post": Object { + "description": "Information about a new pet in the systems", + "operationId": "newPet", + "requestBody": Object { + "content": Object { + "application/json": Object { + "schema": Object { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + }, + "responses": Object { + "200": Object { + "description": "Return a 200 status to indicate that the data was received successfully", + }, + }, + "summary": "New pet", + "tags": Array [ + "pet", + ], + }, + }, + }, +} +`; + +exports[`#loadAndBundleSpec should load And Bundle Spec demo/openapi-3-1.yaml 1`] = ` Object { "components": Object { "examples": Object { @@ -1784,10 +3580,6 @@ culpa qui officia deserunt mollit anim id est laborum. "description": "Everything about your Pets", "name": "pet", }, - Object { - "description": "Everything about your Webhooks", - "name": "webhooks", - }, Object { "description": "Access to Petstore orders", "name": "store", @@ -1796,6 +3588,10 @@ culpa qui officia deserunt mollit anim id est laborum. "description": "Operations about user", "name": "user", }, + Object { + "description": "Everything about your Webhooks", + "name": "webhooks", + }, Object { "description": " ", diff --git a/src/utils/__tests__/loadAndBundleSpec.test.ts b/src/utils/__tests__/loadAndBundleSpec.test.ts index 74dd2c881d..62f4c6fee8 100644 --- a/src/utils/__tests__/loadAndBundleSpec.test.ts +++ b/src/utils/__tests__/loadAndBundleSpec.test.ts @@ -10,6 +10,12 @@ describe('#loadAndBundleSpec', () => { expect(bundledSpec).toMatchSnapshot(); }); + it('should load And Bundle Spec demo/openapi-3-1.yaml', async () => { + const spec = yaml.load(readFileSync(resolve(__dirname, '../../../demo/openapi-3-1.yaml'))); + const bundledSpec = await loadAndBundleSpec(spec); + expect(bundledSpec).toMatchSnapshot(); + }); + it('should load And Bundle Spec demo/swagger.yaml', async () => { const spec = yaml.load(readFileSync(resolve(__dirname, '../../../demo/swagger.yaml'))); const bundledSpec = await loadAndBundleSpec(spec);