-
Notifications
You must be signed in to change notification settings - Fork 204
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf(spec-parser): add browser api, truncate string (#10196)
* perf(spec-parser): add browser api, truncate string * fix: commit missing class file * fix: commit missing file * fix: add test cases to make codecov happy --------- Co-authored-by: turenlong <[email protected]>
- Loading branch information
Showing
12 changed files
with
1,155 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
"use strict"; | ||
|
||
export { SpecParser } from "./specParser.browser"; | ||
export { SpecParserError } from "./specParserError"; | ||
export { ValidationStatus, WarningType, ErrorType, WarningResult } from "./interfaces"; | ||
export { ConstantString } from "./constants"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
184 changes: 184 additions & 0 deletions
184
packages/fx-core/src/common/spec-parser/specParser.browser.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
"use strict"; | ||
|
||
import SwaggerParser from "@apidevtools/swagger-parser"; | ||
import { OpenAPIV3 } from "openapi-types"; | ||
import { | ||
APIInfo, | ||
ErrorType, | ||
GenerateResult, | ||
ParseOptions, | ||
ValidateResult, | ||
ValidationStatus, | ||
Parameter, | ||
} from "./interfaces"; | ||
import { SpecParserError } from "./specParserError"; | ||
import { listSupportedAPIs, parseApiInfo, validateSpec } from "./utils"; | ||
import { ConstantString } from "./constants"; | ||
|
||
/** | ||
* A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts. | ||
*/ | ||
export class SpecParser { | ||
public readonly pathOrSpec: string | OpenAPIV3.Document; | ||
public readonly parser: SwaggerParser; | ||
public readonly options: ParseOptions; | ||
|
||
private apiMap: { [key: string]: OpenAPIV3.PathItemObject } | undefined; | ||
private spec: OpenAPIV3.Document | undefined; | ||
private unResolveSpec: OpenAPIV3.Document | undefined; | ||
private isSwaggerFile: boolean | undefined; | ||
|
||
private defaultOptions: ParseOptions = { | ||
allowMissingId: false, | ||
allowSwagger: false, | ||
}; | ||
|
||
/** | ||
* Creates a new instance of the SpecParser class. | ||
* @param pathOrDoc The path to the OpenAPI specification file or the OpenAPI specification object. | ||
* @param options The options for parsing the OpenAPI specification file. | ||
*/ | ||
constructor(pathOrDoc: string | OpenAPIV3.Document, options?: ParseOptions) { | ||
this.pathOrSpec = pathOrDoc; | ||
this.parser = new SwaggerParser(); | ||
this.options = { | ||
...this.defaultOptions, | ||
...(options ?? {}), | ||
}; | ||
} | ||
|
||
/** | ||
* Validates the OpenAPI specification file and returns a validation result. | ||
* | ||
* @returns A validation result object that contains information about any errors or warnings in the specification file. | ||
*/ | ||
async validate(): Promise<ValidateResult> { | ||
try { | ||
try { | ||
await this.loadSpec(); | ||
await this.parser.validate(this.spec!); | ||
} catch (e) { | ||
return { | ||
status: ValidationStatus.Error, | ||
warnings: [], | ||
errors: [{ type: ErrorType.SpecNotValid, content: (e as Error).toString() }], | ||
}; | ||
} | ||
|
||
if (!this.options.allowSwagger && this.isSwaggerFile) { | ||
return { | ||
status: ValidationStatus.Error, | ||
warnings: [], | ||
errors: [ | ||
{ type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported }, | ||
], | ||
}; | ||
} | ||
|
||
return validateSpec(this.spec!, this.parser, !!this.isSwaggerFile); | ||
} catch (err) { | ||
throw new SpecParserError((err as Error).toString(), ErrorType.ValidateFailed); | ||
} | ||
} | ||
|
||
async listSupportedAPIInfo(): Promise<APIInfo[]> { | ||
try { | ||
await this.loadSpec(); | ||
const apiMap = this.getAllSupportedAPIs(this.spec!); | ||
const apiInfos: APIInfo[] = []; | ||
for (const key in apiMap) { | ||
const pathObjectItem = apiMap[key]; | ||
const [method, path] = key.split(" "); | ||
const operationId = pathObjectItem.operationId; | ||
|
||
// In Browser environment, this api is by default not support api without operationId | ||
if (!operationId) { | ||
continue; | ||
} | ||
|
||
const [command, warning] = parseApiInfo(pathObjectItem); | ||
|
||
const apiInfo: APIInfo = { | ||
method: method, | ||
path: path, | ||
title: command.title, | ||
id: operationId, | ||
parameters: command.parameters! as Parameter[], | ||
description: command.description!, | ||
}; | ||
|
||
if (warning) { | ||
apiInfo.warning = warning; | ||
} | ||
|
||
apiInfos.push(apiInfo); | ||
} | ||
|
||
return apiInfos; | ||
} catch (err) { | ||
throw new SpecParserError((err as Error).toString(), ErrorType.listSupportedAPIInfoFailed); | ||
} | ||
} | ||
|
||
/** | ||
* Lists all the OpenAPI operations in the specification file. | ||
* @returns A string array that represents the HTTP method and path of each operation, such as ['GET /pets/{petId}', 'GET /user/{userId}'] | ||
* according to copilot plugin spec, only list get and post method without auth | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/require-await | ||
async list(): Promise<string[]> { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
/** | ||
* List all the OpenAPI operations in the specification file and return a map of operationId and operation path. | ||
* @returns A map of operationId and operation path, such as [{'getPetById': 'GET /pets/{petId}'}, {'getUser': 'GET /user/{userId}'}] | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/require-await | ||
async listOperationMap(): Promise<Map<string, string>> { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
/** | ||
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file. | ||
* @param manifestPath A file path of the Teams app manifest file to update. | ||
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing. | ||
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated. | ||
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/require-await | ||
async generate( | ||
manifestPath: string, | ||
filter: string[], | ||
outputSpecPath: string, | ||
adaptiveCardFolder: string, | ||
signal?: AbortSignal | ||
): Promise<GenerateResult> { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
private async loadSpec(): Promise<void> { | ||
if (!this.spec) { | ||
this.unResolveSpec = (await this.parser.parse(this.pathOrSpec)) as OpenAPIV3.Document; | ||
if (!this.unResolveSpec.openapi && (this.unResolveSpec as any).swagger === "2.0") { | ||
this.isSwaggerFile = true; | ||
} | ||
|
||
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec)); | ||
this.spec = (await this.parser.dereference(clonedUnResolveSpec)) as OpenAPIV3.Document; | ||
} | ||
} | ||
|
||
private getAllSupportedAPIs(spec: OpenAPIV3.Document): { | ||
[key: string]: OpenAPIV3.OperationObject; | ||
} { | ||
if (this.apiMap !== undefined) { | ||
return this.apiMap; | ||
} | ||
const result = listSupportedAPIs(spec, this.options.allowMissingId!); | ||
this.apiMap = result; | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.