diff --git a/.vscode/launch.json b/.vscode/launch.json index 512bc08..f2c4dad 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -65,8 +65,7 @@ "MOCHA_enableTimeouts": "0", // Disable time-outs "DEBUGTELEMETRY": "1", "NODE_DEBUG": "", - "ENABLE_LONG_RUNNING_TESTS": "", - "FUNC_PATH": "func" + "ENABLE_LONG_RUNNING_TESTS": "" } }, { @@ -89,8 +88,7 @@ "MOCHA_enableTimeouts": "0", // Disable time-outs "DEBUGTELEMETRY": "1", "NODE_DEBUG": "", - "ENABLE_LONG_RUNNING_TESTS": "", - "FUNC_PATH": "func" + "ENABLE_LONG_RUNNING_TESTS": "" } } ] diff --git a/extension.bundle.ts b/extension.bundle.ts index 31894b6..f5e0f58 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -18,3 +18,13 @@ export { activateInternal, deactivateInternal } from './src/extension'; // The tests should import '../extension.bundle.ts'. At design-time they live in tests/ and so will pick up this file (extension.bundle.ts). // At runtime the tests live in dist/tests and will therefore pick up the main webpack bundle at dist/extension.bundle.js. export { ext } from './src/extensionVariables'; +export * from './src/constants'; +export * from "vscode-azureextensionui"; +export * from './src/utils/fsUtil'; +export * from './src/explorer/ApiManagementProvider'; +export * from './src/vsCodeConfig/settings'; +export * from './src/openApi/OpenApiParser'; +export * from './src/openApi/OpenApiImportObject'; +export { treeUtils } from './src/utils/treeUtils'; +export * from './src/utils/azure'; +export * from './src/utils/nameUtil'; diff --git a/gulp/gulp_installRestClient.ts b/gulp/gulp_installRestClient.ts new file mode 100644 index 0000000..1c0fa63 --- /dev/null +++ b/gulp/gulp_installRestClient.ts @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { File } from 'decompress'; +import * as glob from 'glob'; +import * as gulp from 'gulp'; +// tslint:disable-next-line: no-require-imports +import decompress = require('gulp-decompress'); +// tslint:disable-next-line: no-require-imports +import download = require('gulp-download'); +import * as os from 'os'; +import * as path from 'path'; +import { Stream } from 'stream'; + +// Tests expect the extension to be installed. +// tslint:disable-next-line: promise-function-async +// tslint:disable:no-console +// tslint:disable: no-unsafe-any +export function gulp_installRestClient(): Promise | Stream { + const version: string = '0.21.3'; + const extensionPath: string = path.join(os.homedir(), `.vscode/extensions/humao.rest-client-${version}`); + const existingExtensions: string[] = glob.sync(extensionPath.replace(version, '*')); + if (existingExtensions.length === 0) { + console.log("installing rest-client extension."); + // tslint:disable-next-line:no-http-string + return download(`http://humao.gallery.vsassets.io/_apis/public/gallery/publisher/humao/extension/rest-client/${version}/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage`) + .pipe(decompress({ + filter: (file: File): boolean => file.path.startsWith('extension/'), + map: (file: File): File => { + file.path = file.path.slice(10); + return file; + } + })) + .pipe(gulp.dest(extensionPath)); + } else { + console.log("rest-client extension already installed."); + // We need to signal to gulp that we've completed this async task + return Promise.resolve(); + } +} diff --git a/gulpfile.ts b/gulpfile.ts index 43acf45..0951ee6 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -9,6 +9,7 @@ import * as cp from 'child_process'; import * as gulp from 'gulp'; import * as path from 'path'; import { gulp_installAzureAccount, gulp_webpack } from 'vscode-azureextensiondev'; +import { gulp_installRestClient } from './gulp/gulp_installRestClient'; const env = process.env; @@ -20,4 +21,4 @@ function test(): cp.ChildProcess { exports['webpack-dev'] = () => gulp_webpack('development'); exports['webpack-prod'] = () => gulp_webpack('production'); -exports.test = gulp.series(gulp_installAzureAccount, test); +exports.test = gulp.series(gulp_installAzureAccount, gulp_installRestClient, test); diff --git a/package-lock.json b/package-lock.json index 2031f7c..723ee5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-apimanagement", - "version": "0.0.1-alpha", + "version": "0.1.0-alpha", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/utils/fsUtil.ts b/src/utils/fsUtil.ts index 7188ea2..e6a3db2 100644 --- a/src/utils/fsUtil.ts +++ b/src/utils/fsUtil.ts @@ -25,12 +25,15 @@ export async function createTemporaryFile(fileName: string): Promise { export function getSessionWorkingFolderName() : string { let sessionFolderName = ext.context.globalState.get(sessionFolderKey); if (!sessionFolderName) { - const randomFolderNameLength: number = 12; - const buffer: Buffer = crypto.randomBytes(Math.ceil(randomFolderNameLength / 2)); - sessionFolderName = buffer.toString('hex').slice(0, randomFolderNameLength); + sessionFolderName = getRandomHexString(); ext.outputChannel.appendLine(`Session working folder:${sessionFolderName}`); ext.context.globalState.update(sessionFolderKey, sessionFolderName); } return sessionFolderName; } + +export function getRandomHexString(length: number = 10): string { + const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); + return buffer.toString('hex').slice(0, length); +} diff --git a/src/utils/treeUtils.ts b/src/utils/treeUtils.ts index 0d78746..b002ec4 100644 --- a/src/utils/treeUtils.ts +++ b/src/utils/treeUtils.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as path from 'path'; -import { AzureParentTreeItem, AzureTreeDataProvider, AzureTreeItem } from 'vscode-azureextensionui'; +import { AzureParentTreeItem, AzureTreeDataProvider, AzureTreeItem, RootTreeItem } from 'vscode-azureextensionui'; import { ext } from '../extensionVariables'; import { localize } from '../localize'; @@ -37,4 +37,9 @@ export namespace treeUtils { throw new Error(localize('noMatchingSubscription', 'Failed to find a subscription matching id "{0}".', subscriptionId)); } } + + export async function getRootNode(tree: AzureTreeDataProvider): Promise { + // is there a better way than querying children? + return (await tree.getChildren()).find((n: AzureParentTreeItem) => n instanceof RootTreeItem); + } } diff --git a/src/vsCodeConfig/settings.ts b/src/vsCodeConfig/settings.ts index 44b128e..7ffe6c6 100644 --- a/src/vsCodeConfig/settings.ts +++ b/src/vsCodeConfig/settings.ts @@ -6,6 +6,12 @@ import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; import { extensionPrefix } from "../constants"; +export function getGlobalSetting(key: string, prefix: string = extensionPrefix): T | undefined { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); + const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); + return result && result.globalValue; +} + export async function updateGlobalSetting(section: string, value: T, prefix: string = extensionPrefix): Promise { const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); await projectConfiguration.update(section, value, ConfigurationTarget.Global); @@ -15,3 +21,8 @@ export function getWorkspaceSetting(key: string, fsPath?: string, prefix: str const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); return projectConfiguration.get(key); } + +export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = extensionPrefix): Promise { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); + await projectConfiguration.update(section, value); +} diff --git a/test/assertThrowsAsync.ts b/test/assertThrowsAsync.ts new file mode 100644 index 0000000..a9e9879 --- /dev/null +++ b/test/assertThrowsAsync.ts @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; + +/** + * Same as assert.throws except for async functions + */ +export async function assertThrowsAsync(block: () => Promise, error: RegExp | Function, message?: string): Promise { + // tslint:disable-next-line:typedef + let blockSync = (): void => { /* ignore */ }; + try { + await block(); + } catch (e) { + blockSync = (): void => { throw e; }; + } finally { + assert.throws(blockSync, error, message); + } +} diff --git a/test/azure.test.ts b/test/azure.test.ts new file mode 100644 index 0000000..feb7142 --- /dev/null +++ b/test/azure.test.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { getNameFromId, getResourceGroupFromId, getSubscriptionFromId } from '../extension.bundle'; + +// tslint:disable: no-unsafe-any +suite("Azure Resource Util", () => { + const resourceId: string = "/subscriptions/a59d7183-f4a0-4b15-8ecc-9542203d3c54/resourceGroups/apim-rg/providers/Microsoft.ApiManagement/service/apim-service"; + + test("Parse name from azure resource id", async () => { + const name: string = getNameFromId(resourceId); + assert.equal(name, "apim-service"); + }); + + test("Parse resource group name from azure resource id", async () => { + const rg: string = getResourceGroupFromId(resourceId); + assert.equal(rg, "apim-rg"); + }); + + test("Parse subscription from azure resource id", async () => { + const sub: string = getSubscriptionFromId(resourceId); + assert.equal(sub, "a59d7183-f4a0-4b15-8ecc-9542203d3c54"); + }); +}); diff --git a/test/createService.test.ts b/test/createService.test.ts new file mode 100644 index 0000000..208163f --- /dev/null +++ b/test/createService.test.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { ApiManagementClient, ApiManagementModels } from 'azure-arm-apimanagement'; +import { ResourceManagementClient } from 'azure-arm-resource'; +import { IHookCallbackContext, ISuiteCallbackContext } from 'mocha'; +import * as vscode from 'vscode'; +import { AzureParentTreeItem } from 'vscode-azureextensionui'; +import { ApiManagementProvider, AzureTreeDataProvider, ext, getRandomHexString, TestAzureAccount, TestUserInput, treeUtils } from '../extension.bundle'; +import { longRunningTestsEnabled } from './global.test'; +import { runWithApimSetting } from './runWithSetting'; + +// tslint:disable-next-line:max-func-body-length +suite('Create Azure Resources', async function (this: ISuiteCallbackContext): Promise { + this.timeout(1200 * 1000); + const resourceGroupsToDelete: string[] = []; + const testAccount: TestAzureAccount = new TestAzureAccount(); + let apiManagementClient: ApiManagementClient; + const resourceName1: string = getRandomHexString().toLowerCase(); + + suiteSetup(async function (this: IHookCallbackContext): Promise { + if (!longRunningTestsEnabled) { + this.skip(); + } + + this.timeout(120 * 1000); + await testAccount.signIn(); + ext.tree = new AzureTreeDataProvider(ApiManagementProvider, 'azureApiManagement.startTesting', undefined, testAccount); + const rootNode : AzureParentTreeItem = await treeUtils.getRootNode(ext.tree); + rootNode.root.userId = "vscodeapimtest@microsoft.com"; // userId doesnt exist for service principal. + apiManagementClient = getApiManagementClient(testAccount); + }); + + suiteTeardown(async function (this: IHookCallbackContext): Promise { + if (!longRunningTestsEnabled) { + this.skip(); + } + this.timeout(1200 * 1000); + + const client: ResourceManagementClient = getResourceManagementClient(testAccount); + for (const resourceGroup of resourceGroupsToDelete) { + if (await client.resourceGroups.checkExistence(resourceGroup)) { + console.log(`Deleting resource group "${resourceGroup}"...`); + await client.resourceGroups.deleteMethod(resourceGroup); + console.log(`Resource group "${resourceGroup}" deleted.`); + } else { + // If the test failed, the resource group might not actually exist + console.log(`Ignoring resource group "${resourceGroup}" because it does not exist.`); + } + } + ext.tree.dispose(); + }); + + test('createApiManagementService (Default)', async () => { + resourceGroupsToDelete.push(resourceName1); + await runWithApimSetting('advancedCreation', undefined, async () => { + ext.ui = new TestUserInput([resourceName1]); + await vscode.commands.executeCommand('azureApiManagement.createService'); + const createdService: ApiManagementModels.ApiManagementServiceResource = await apiManagementClient.apiManagementService.get(resourceName1, resourceName1); + assert.ok(createdService); + }); + }); +}); + +function getApiManagementClient(testAccount: TestAzureAccount): ApiManagementClient { + return new ApiManagementClient(testAccount.getSubscriptionCredentials(), testAccount.getSubscriptionId()); +} + +function getResourceManagementClient(testAccount: TestAzureAccount): ResourceManagementClient { + return new ResourceManagementClient(testAccount.getSubscriptionCredentials(), testAccount.getSubscriptionId()); +} diff --git a/test/extension.test.ts b/test/extension.test.ts deleted file mode 100644 index 13c8cc0..0000000 --- a/test/extension.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -// -// Note: This example test is leveraging the Mocha test framework. -// Please refer to their documentation on https://mochajs.org/ for help. -// - -// The module 'assert' provides assertion methods from node -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -// import * as vscode from 'vscode'; -// import * as myExtension from '../extension'; - -// Defines a Mocha test suite to group tests of similar kind together -suite("Extension Tests", () => { - - // Defines a Mocha unit test - test("Something 1", () => { - assert.equal(-1, [1, 2, 3].indexOf(5)); - assert.equal(-1, [1, 2, 3].indexOf(0)); - }); -}); diff --git a/test/global.test.ts b/test/global.test.ts new file mode 100644 index 0000000..120d98c --- /dev/null +++ b/test/global.test.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fse from 'fs-extra'; +import { IHookCallbackContext } from 'mocha'; +import * as os from 'os'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import { TestOutputChannel } from 'vscode-azureextensiondev'; +import { ext, getRandomHexString, parseError, TestUserInput } from '../extension.bundle'; + +export let longRunningTestsEnabled: boolean; +export const testFolderPath: string = path.join(os.tmpdir(), `azureApiManagementTest${getRandomHexString()}`); + +// Runs before all tests +suiteSetup(async function (this: IHookCallbackContext): Promise { + this.timeout(120 * 1000); + + await fse.ensureDir(testFolderPath); + + await vscode.commands.executeCommand('azureApiManagement.Refresh'); // activate the extension before tests begin + ext.outputChannel = new TestOutputChannel(); + ext.ui = new TestUserInput([]); + + // tslint:disable-next-line:strict-boolean-expressions + longRunningTestsEnabled = !/^(false|0)?$/i.test(process.env.ENABLE_LONG_RUNNING_TESTS || ''); +}); + +suiteTeardown(async function (this: IHookCallbackContext): Promise { + this.timeout(90 * 1000); + try { + await fse.remove(testFolderPath); + } catch (error) { + // Build machines fail pretty often with an EPERM error on Windows, but removing the temp test folder isn't worth failing the build + console.warn(`Failed to delete test folder path: ${parseError(error).message}`); + } +}); diff --git a/test/nameUtil.test.ts b/test/nameUtil.test.ts new file mode 100644 index 0000000..8738ee9 --- /dev/null +++ b/test/nameUtil.test.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { nameUtil } from '../extension.bundle'; +import { IApiTreeRoot } from '../src/explorer/IApiTreeRoot'; +import { IOperationTreeRoot } from '../src/explorer/IOperationTreeRoot'; +import { IServiceTreeRoot } from '../src/explorer/IServiceTreeRoot'; + +// tslint:disable: no-unsafe-any +suite("Name Util", () => { + test("ServiceRoot", async () => { + const name : string = nameUtil({ serviceName : "apim-service" }); + assert.equal(name, "apim-service"); + }); + + test("OperationRoot", async () => { + const name : string = nameUtil({ serviceName : "apim-service", apiName: "apim-api", opName: "apim-op" }); + assert.equal(name, "apim-service-apim-api-apim-op"); + }); + + test("ApiRoot", async () => { + const name : string = nameUtil({ serviceName : "apim-service", apiName: "apim-api"}); + assert.equal(name, "apim-service-apim-api"); + }); +}); diff --git a/test/openApiParser.test.ts b/test/openApiParser.test.ts new file mode 100644 index 0000000..571007d --- /dev/null +++ b/test/openApiParser.test.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { IOpenApiImportObject, OpenApiParser } from '../extension.bundle'; +import { assertThrowsAsync } from './assertThrowsAsync'; +import {openApi2_0, openApi3_0} from './testData'; + +// tslint:disable: no-unsafe-any +suite("Open API Parser", () => { + test("Parse OpenAPI Json 2.0", async () => { + const parsedOpenAPI: IOpenApiImportObject = await new OpenApiParser().parse(openApi2_0); + assert.deepEqual(parsedOpenAPI.sourceDocument, openApi2_0); + assert.equal(parsedOpenAPI.importFormat, "swagger-json"); + assert.equal(parsedOpenAPI.version, "2.0"); + }); + + test("Parse OpenAPI Json > 3.0", async () => { + const parsedOpenAPI: IOpenApiImportObject = await new OpenApiParser().parse(openApi3_0); + assert.deepEqual(parsedOpenAPI.sourceDocument, openApi3_0); + assert.equal(parsedOpenAPI.importFormat, "openapi+json"); + assert.equal(parsedOpenAPI.version, "3.0.0"); + }); + + test("Invalid OpenAPI input", async () => { + // tslint:disable-next-line:no-any + const invalidSwagger : any = {}; + await assertThrowsAsync(async () => new OpenApiParser().parse(invalidSwagger), /Could not parse the OpenAPI document./); + }); +}); diff --git a/test/runWithSetting.ts b/test/runWithSetting.ts new file mode 100644 index 0000000..0d75c41 --- /dev/null +++ b/test/runWithSetting.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { extensionPrefix, getGlobalSetting, updateGlobalSetting } from "../extension.bundle"; + +export async function runWithApimSetting(key: string, value: string | undefined, callback: () => Promise): Promise { + await runWithSettingInternal(key, value, extensionPrefix, callback); +} + +export async function runWithSetting(key: string, value: string | undefined, callback: () => Promise): Promise { + await runWithSettingInternal(key, value, '', callback); +} + +async function runWithSettingInternal(key: string, value: string | undefined, prefix: string, callback: () => Promise): Promise { + const oldValue: string | undefined = getGlobalSetting(key, prefix); + try { + await updateGlobalSetting(key, value, prefix); + await callback(); + } finally { + await updateGlobalSetting(key, oldValue, prefix); + } +} diff --git a/test/testData.ts b/test/testData.ts new file mode 100644 index 0000000..0ef57a2 --- /dev/null +++ b/test/testData.ts @@ -0,0 +1,2097 @@ +// https://petstore.swagger.io/v2/swagger.json +// tslint:disable:object-literal-key-quotes +// tslint:disable:no-http-string +// tslint:disable:no-any +export const openApi2_0: any = { + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version": "1.0.0", + "title": "Swagger Petstore", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders" + }, + { + "name": "user", + "description": "Operations about user", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "schemes": [ + "https", + "http" + ], + "paths": { + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "", + "operationId": "updatePet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": true, + "type": "array", + "items": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "default": "available" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "deprecated": true + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "name", + "in": "formData", + "description": "Updated name of the pet", + "required": false, + "type": "string" + }, + { + "name": "status", + "in": "formData", + "description": "Updated status of the pet", + "required": false, + "type": "string" + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "api_key", + "in": "header", + "required": false, + "type": "string" + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "additionalMetadata", + "in": "formData", + "description": "Additional data to pass to server", + "required": false, + "type": "string" + }, + { + "name": "file", + "in": "formData", + "description": "file to upload", + "required": false, + "type": "file" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/ApiResponse" + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "", + "operationId": "placeOrder", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "order placed for purchasing the pet", + "required": true, + "schema": { + "$ref": "#/definitions/Order" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid Order" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", + "operationId": "getOrderById", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "maximum": 10.0, + "minimum": 1.0, + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", + "operationId": "deleteOrder", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "type": "integer", + "minimum": 1.0, + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Created user object", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/createWithArray": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithArrayInput", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithListInput", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": true, + "type": "string" + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "string" + }, + "headers": { + "X-Rate-Limit": { + "type": "integer", + "format": "int32", + "description": "calls per hour allowed by the user" + }, + "X-Expires-After": { + "type": "string", + "format": "date-time", + "description": "date in UTC when token expires" + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/User" + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Updated user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be updated", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "Updated user object", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "400": { + "description": "Invalid user supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "type": "string" + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "securityDefinitions": { + "petstore_auth": { + "type": "oauth2", + "authorizationUrl": "https://petstore.swagger.io/oauth/authorize", + "flow": "implicit", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + }, + "definitions": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean", + "default": false + } + }, + "xml": { + "name": "Order" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + }, + "xml": { + "name": "User" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "Pet": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/definitions/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "xml": { + "name": "photoUrl", + "wrapped": true + }, + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "xml": { + "name": "tag", + "wrapped": true + }, + "items": { + "$ref": "#/definitions/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "Pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + } +}; + +// Converted to json https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore.yaml +export const openApi3_0: any = { + "openapi": "3.0.0", + "servers": [ + { + "url": "https://petstore.swagger.io/v2" + }, + { + "url": "http://petstore.swagger.io/v2" + } + ], + "info": { + "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version": "1.0.0", + "title": "Swagger Petstore", + "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" + } + }, + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders" + }, + { + "name": "user", + "description": "Operations about user", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "paths": { + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "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" + ] + } + ], + "requestBody": { + "$ref": "#/components/requestBodies/Pet" + } + } + }, + "/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, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "default": "available" + } + } + } + ], + "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": "Muliple 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": true, + "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" + ] + } + ], + "deprecated": true + } + }, + "/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": [] + } + ] + }, + "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" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "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" + } + } + } + } + } + }, + "/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/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "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 >= 1 and <= 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": 10 + } + } + ], + "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 positive integer value. Negative or non-integer values 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", + "minimum": 1 + } + } + ], + "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", + "responses": { + "default": { + "description": "successful operation" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + }, + "description": "Created user object", + "required": true + } + } + }, + "/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/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", + "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": "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 updated", + "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" + } + } + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean", + "default": false + } + }, + "xml": { + "name": "Order" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + }, + "xml": { + "name": "User" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "Pet": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "xml": { + "name": "photoUrl", + "wrapped": true + }, + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "xml": { + "name": "tag", + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "Pet" + } + } + }, + "requestBodies": { + "Pet": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "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": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore.swagger.io/oauth/dialog", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } +}; diff --git a/tslint.json b/tslint.json index 5446869..4c521cb 100644 --- a/tslint.json +++ b/tslint.json @@ -66,7 +66,8 @@ false, "single" ], - "radix": false + "radix": false, + "no-use-before-declare": false }, "linterOptions": { "exclude": [