зеркало из https://github.com/Azure/autorest.git
Move OpenAPI2 types into @azure-tools/openapi library (#4465)
This commit is contained in:
Родитель
82887f1ed0
Коммит
bdf3f0ca4a
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/core",
|
||||
"comment": "Uptake change in typing in openapi library",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/core",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/modelerfour",
|
||||
"comment": "Uptake change in typing in openapi library",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/modelerfour",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@azure-tools/oai2-to-oai3",
|
||||
"comment": "Extract OpenAPI2 types into @azure-tools/openapi package",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@azure-tools/oai2-to-oai3",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@azure-tools/openapi",
|
||||
"comment": "Add `/v2` scope to load OpenAPI2 schema types.",
|
||||
"type": "minor"
|
||||
},
|
||||
{
|
||||
"packageName": "@azure-tools/openapi",
|
||||
"comment": "Update OpenAPI 3.0 types to be more accurate.",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@azure-tools/openapi",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -21,4 +21,7 @@ const config = {
|
|||
testEnvironment: "node",
|
||||
};
|
||||
|
||||
// Disable ts-jest warning because we are using alpha version of jest 28.x to resolve this issue https://github.com/facebook/jest/issues/9771
|
||||
process.env.TS_JEST_DISABLE_VER_CHECKER = "1";
|
||||
|
||||
module.exports = config;
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"jsonpath": "1.0.0",
|
||||
"mkdirp": "~0.5.1",
|
||||
"prettier": "~2.3.1",
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"lodash": "~4.17.20",
|
||||
"prettier": "~2.3.1",
|
||||
"rimraf": "^3.0.2",
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"jsonpath": "1.0.0",
|
||||
"lodash": "~4.17.20",
|
||||
"mkdirp": "~0.5.1",
|
||||
|
|
|
@ -30,7 +30,7 @@ function cleanAllOfForSchema(schema: Schema) {
|
|||
}
|
||||
// otherwise, copy this schema stuff into the schema
|
||||
for (const [key, value] of Object.entries(aSchema)) {
|
||||
schema[key] = value;
|
||||
schema[key as any] = value;
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
|
|
|
@ -31,7 +31,7 @@ export class ComponentKeyRenamer extends Transformer<any, oai.Model> {
|
|||
|
||||
// copy these over without worrying about moving things down to components.
|
||||
default:
|
||||
this.clone(targetParent, key, pointer, value);
|
||||
this.clone(targetParent, key as any, pointer, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,14 +55,13 @@ export class ComponentsCleaner extends Transformer<any, oai.Model> {
|
|||
switch (key) {
|
||||
case "components":
|
||||
{
|
||||
const components =
|
||||
<oai.Components>targetParent.components || this.newObject(targetParent, "components", pointer);
|
||||
const components = targetParent.components || this.newObject(targetParent, "components", pointer);
|
||||
this.visitComponents(components, children);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this.clone(targetParent, key, pointer, value);
|
||||
this.clone(targetParent, key as any, pointer, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -228,12 +227,12 @@ class UnsuedComponentFinder {
|
|||
}
|
||||
|
||||
for (const item of arrayify(items)) {
|
||||
if (item.$ref) {
|
||||
if ("$ref" in item) {
|
||||
const refParts = item.$ref.split("/");
|
||||
const componentRefUid = refParts.pop();
|
||||
const refType = refParts.pop() as keyof ComponentTracker;
|
||||
if (
|
||||
this.componentsToKeep[refType].has(componentRefUid) &&
|
||||
this.componentsToKeep[refType].has(componentRefUid as string) &&
|
||||
!this.componentsToKeep[containerType].has(currentComponentUid)
|
||||
) {
|
||||
this.componentsToKeep[containerType].add(currentComponentUid);
|
||||
|
|
|
@ -98,14 +98,14 @@ export class MultiAPIMerger extends Transformer<any, oai.Model> {
|
|||
case "x-ms-paths":
|
||||
// Merge paths and x-ms-paths together under paths.
|
||||
if (!this.isSecondaryFile) {
|
||||
const paths = <oai.PathItem>target.paths || this.newObject(target, "paths", pointer);
|
||||
this.visitPaths(paths, children);
|
||||
const paths = target.paths || this.newObject(target, "paths", pointer);
|
||||
this.visitPaths(paths as any, children);
|
||||
}
|
||||
break;
|
||||
|
||||
case "components":
|
||||
{
|
||||
const components = <oai.Components>target.components || this.newObject(target, "components", pointer);
|
||||
const components = target.components || this.newObject(target, "components", pointer);
|
||||
this.visitComponents(components, children);
|
||||
}
|
||||
break;
|
||||
|
@ -150,7 +150,7 @@ export class MultiAPIMerger extends Transformer<any, oai.Model> {
|
|||
}
|
||||
const docsMetadata =
|
||||
(<oai.ExternalDocumentation>target.externalDocs)["x-ms-metadata"] ||
|
||||
this.newArray(<oai.ExternalDocumentation>target.externalDocs, "x-ms-metadata", pointer);
|
||||
this.newArray(<oai.ExternalDocumentation>target.externalDocs, "x-ms-metadata" as any, pointer);
|
||||
docsMetadata.__push__({
|
||||
value: cloneDeep(value),
|
||||
pointer,
|
||||
|
@ -169,8 +169,8 @@ export class MultiAPIMerger extends Transformer<any, oai.Model> {
|
|||
|
||||
default:
|
||||
if (!this.isSecondaryFile) {
|
||||
if (!target[key]) {
|
||||
this.copy(target, key, pointer, value);
|
||||
if (!target[key as any]) {
|
||||
this.copy(target, key as any, pointer, value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -457,7 +457,7 @@ export class MultiAPIMerger extends Transformer<any, oai.Model> {
|
|||
this.newObject(components, key, pointer);
|
||||
}
|
||||
|
||||
this.visitComponent(key, components[key], children);
|
||||
this.visitComponent(key, components[key] as any, children);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ export class ProfileFilter extends Transformer<any, oai.Model> {
|
|||
break;
|
||||
|
||||
default:
|
||||
this.clone(targetParent, key, pointer, value);
|
||||
this.clone(targetParent, key as any, pointer, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ const baseModel: oai3.Model = {
|
|||
title: "Semantic Validation Unit Tests",
|
||||
version: "1.0",
|
||||
},
|
||||
openApi: "3.0.0",
|
||||
openapi: "3.0.0",
|
||||
paths: {},
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const baseModel: oai3.Model = {
|
|||
title: "Semantic Validation Unit Tests",
|
||||
version: "1.0",
|
||||
},
|
||||
openApi: "3.0.0",
|
||||
openapi: "3.0.0",
|
||||
paths: {},
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const baseModel: oai3.Model = {
|
|||
title: "Semantic Validation Unit Tests",
|
||||
version: "1.0",
|
||||
},
|
||||
openApi: "3.0.0",
|
||||
openapi: "3.0.0",
|
||||
paths: {},
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ export class SubsetSchemaDeduplicator extends Transformer<any, oai.Model> {
|
|||
|
||||
// copy these over without worrying about moving things down to components.
|
||||
default:
|
||||
this.clone(targetParent, key, pointer, value);
|
||||
this.clone(targetParent, key as any, pointer, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { OAI3Shaker } from "./tree-shaker";
|
|||
|
||||
const createTestModel = (model: Partial<Model>): Model => {
|
||||
return {
|
||||
openApi: "3.0.0",
|
||||
openapi: "3.0.0",
|
||||
paths: {},
|
||||
info: {
|
||||
title: "Test spec",
|
||||
|
|
|
@ -43,13 +43,13 @@ export class ApiVersionParameterHandler extends Transformer<any, oai.Model> {
|
|||
|
||||
case "paths":
|
||||
{
|
||||
const paths = <oai.PathItem>targetParent.paths || this.newObject(targetParent, "paths", pointer);
|
||||
this.visitPaths(paths, children);
|
||||
const paths = targetParent.paths || this.newObject(targetParent, "paths", pointer);
|
||||
this.visitPaths(paths as any, children);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this.clone(targetParent, key, pointer, value);
|
||||
this.clone(targetParent, key as any, pointer, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"lodash": "~4.17.20",
|
||||
"prettier": "~2.3.1",
|
||||
"recursive-diff": "~1.0.6",
|
||||
|
|
|
@ -857,7 +857,7 @@ export class ModelerFour {
|
|||
maxProperties: schema.maxProperties ? Number(schema.maxProperties) : undefined,
|
||||
language: {
|
||||
default: {
|
||||
summary: schema.summary || schema.title,
|
||||
summary: schema.title,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
@ -866,14 +866,13 @@ export class ModelerFour {
|
|||
// cache this now before we accidentally recurse on this type.
|
||||
this.schemaCache.set(schema, objectSchema);
|
||||
for (const [propertyName, propertyDeclaration] of Object.entries(schema.properties ?? {})) {
|
||||
const property = this.resolve(propertyDeclaration);
|
||||
this.use(<OpenAPI.Refable<OpenAPI.Schema>>propertyDeclaration, (pSchemaName, pSchema) => {
|
||||
const pType = this.processSchema(pSchemaName || `type·for·${propertyName}`, pSchema);
|
||||
const prop = objectSchema.addProperty(
|
||||
new Property(
|
||||
this.interpret.getPreferredName(propertyDeclaration, propertyName),
|
||||
propertyDeclaration.description ||
|
||||
this.interpret.getDescription(pType.language.default.description, property),
|
||||
this.interpret.getDescription(pType.language.default.description, pSchema),
|
||||
pType,
|
||||
{
|
||||
readOnly: propertyDeclaration.readOnly || pSchema.readOnly,
|
||||
|
@ -881,8 +880,8 @@ export class ModelerFour {
|
|||
required: schema.required ? schema.required.indexOf(propertyName) > -1 : undefined,
|
||||
serializedName: propertyName,
|
||||
isDiscriminator: discriminatorProperty === propertyName ? true : undefined,
|
||||
extensions: this.interpret.getExtensionProperties(property, propertyDeclaration),
|
||||
clientDefaultValue: this.interpret.getClientDefault(property.instance, propertyDeclaration),
|
||||
extensions: this.interpret.getExtensionProperties(pSchema, propertyDeclaration),
|
||||
clientDefaultValue: this.interpret.getClientDefault(pSchema, propertyDeclaration),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -1487,7 +1486,7 @@ export class ModelerFour {
|
|||
const pSchema =
|
||||
requestBodyGroup.type === KnownMediaType.Text
|
||||
? this.stringSchema
|
||||
: this.processBinarySchema(requestSchema?.name || "upload", requestSchema || <OpenAPI.Schema>{});
|
||||
: this.processBinarySchema((requestSchema as any)?.name || "upload", requestSchema || <OpenAPI.Schema>{});
|
||||
// add a stream parameter for the body
|
||||
httpRequest.addParameter(
|
||||
new Parameter(bodyName, this.interpret.getDescription("", body?.instance || {}), pSchema, {
|
||||
|
@ -1568,14 +1567,13 @@ export class ModelerFour {
|
|||
// but we must turn them back into operation parameters so that code
|
||||
// generators will generate them as method parameters.
|
||||
for (const [propertyName, propertyDeclaration] of Object.entries(requestSchema.properties ?? {})) {
|
||||
const property = this.resolve(propertyDeclaration);
|
||||
this.use(<OpenAPI.Refable<OpenAPI.Schema>>propertyDeclaration, (pSchemaName, pSchema) => {
|
||||
const pType = this.processSchema(pSchemaName || `type·for·${propertyName}`, pSchema);
|
||||
httpRequest.addParameter(
|
||||
new Parameter(
|
||||
propertyName,
|
||||
propertyDeclaration.description ||
|
||||
this.interpret.getDescription(pType.language.default.description, property),
|
||||
this.interpret.getDescription(pType.language.default.description, pSchema),
|
||||
pType,
|
||||
{
|
||||
schema: pType,
|
||||
|
@ -1605,7 +1603,7 @@ export class ModelerFour {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
const pSchema = this.processSchema(requestSchema?.name || "requestBody", requestSchema ?? {});
|
||||
const pSchema = this.processSchema((requestSchema as any)?.name || "requestBody", requestSchema ?? {});
|
||||
|
||||
// Track the usage of this schema as an input with media type
|
||||
this.trackSchemaUsage(pSchema, { usage: [SchemaContext.Input], serializationFormats: [kmt] });
|
||||
|
@ -1618,7 +1616,7 @@ export class ModelerFour {
|
|||
{
|
||||
extensions: this.interpret.getExtensionProperties(body.instance),
|
||||
required: !!body.instance.required,
|
||||
nullable: requestSchema?.instance?.nullable,
|
||||
nullable: requestSchema?.nullable,
|
||||
protocol: {
|
||||
http: new HttpParameter(ParameterLocation.Body, {
|
||||
style: <SerializationStyle>(<any>kmt),
|
||||
|
@ -2045,7 +2043,7 @@ export class ModelerFour {
|
|||
implementation,
|
||||
extensions: this.interpret.getExtensionProperties(parameter),
|
||||
deprecated: this.interpret.getDeprecation(parameter),
|
||||
nullable: parameter.nullable || schema.nullable,
|
||||
nullable: (parameter as any).nullable || schema.nullable,
|
||||
protocol: {
|
||||
http: new HttpParameter(
|
||||
parameter.in,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Interpretations } from "./interpretations";
|
|||
import { SecurityProcessor } from "./security-processor";
|
||||
|
||||
const baseOpenapiSpec = {
|
||||
openApi: "3.0.0",
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Base spec",
|
||||
version: "1.0",
|
||||
|
|
|
@ -187,10 +187,10 @@ export class DuplicateSchemaMerger {
|
|||
* @returns Schema to keep and list of schema to remove.
|
||||
*/
|
||||
private findSchemaToRemove(
|
||||
spec: oai3.Model,
|
||||
spec: oai3.OpenAPI3Document,
|
||||
schemas: DereferencedSchema[],
|
||||
): { keep: DereferencedSchema; remove: DereferencedSchema[] } {
|
||||
const nonRefSchema = schemas.find((x) => spec.components?.schemas?.[x.key].$ref === undefined);
|
||||
const nonRefSchema = schemas.find((x) => (spec.components?.schemas?.[x.key] as any).$ref === undefined);
|
||||
if (nonRefSchema) {
|
||||
return { keep: nonRefSchema, remove: schemas.filter((x) => x.key !== nonRefSchema.key) };
|
||||
} else {
|
||||
|
|
|
@ -206,7 +206,7 @@ export class QualityPreChecker {
|
|||
continue;
|
||||
}
|
||||
|
||||
const $ref = schema?.allOf?.[0]?.$ref;
|
||||
const $ref = (schema?.allOf?.[0] as any)?.$ref;
|
||||
|
||||
const text = JSON.stringify(this.input);
|
||||
this.input = JSON.parse(text.replace(new RegExp(`"\\#\\/components\\/schemas\\/${key}"`, "g"), `"${$ref}"`));
|
||||
|
|
|
@ -79,7 +79,7 @@ describe("Prechecker", () => {
|
|||
expect(schemas["SiblingSchema"]).toBeUndefined();
|
||||
expect(schemas["MainSchema"]).not.toBeUndefined();
|
||||
const mainSchema: Schema = schemas["MainSchema"] as any;
|
||||
expect(mainSchema.properties?.name.type).toEqual("string");
|
||||
expect((mainSchema.properties?.name as any).type).toEqual("string");
|
||||
});
|
||||
|
||||
describe("Remove child types with no additional properties", () => {
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"source-map-support": "^0.5.19",
|
||||
"ts-jest": "^27.0.3",
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
},
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.0.3",
|
||||
"typescript": "~4.4.2"
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.0.3",
|
||||
"typescript": "~4.4.2"
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
},
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"mkdirp": "~0.5.1",
|
||||
"source-map-support": "^0.5.19",
|
||||
"typescript": "~4.4.2"
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
},
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
},
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"source-map-support": "^0.5.19",
|
||||
"ts-jest": "^27.0.3",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { OpenAPI2Operation } from "./oai2";
|
||||
import { OpenAPI2Operation } from "@azure-tools/openapi/v2";
|
||||
|
||||
/**
|
||||
* Resolve the list of content types produced by an operation.
|
||||
|
|
|
@ -11,15 +11,7 @@ import {
|
|||
createMappingTree,
|
||||
} from "@azure-tools/datastore";
|
||||
import { JsonPointer, getFromJsonPointer, appendJsonPointer } from "@azure-tools/json";
|
||||
import oai3, {
|
||||
EncodingStyle,
|
||||
HttpOperation,
|
||||
includeXDashKeys,
|
||||
JsonType,
|
||||
PathItem,
|
||||
SecurityType,
|
||||
} from "@azure-tools/openapi";
|
||||
import { resolveOperationConsumes, resolveOperationProduces } from "./content-type-utils";
|
||||
import { includeXDashKeys, isExtensionKey, PathReference, Refable } from "@azure-tools/openapi";
|
||||
import {
|
||||
OpenAPI2Document,
|
||||
OpenAPI2ResponseHeader,
|
||||
|
@ -29,7 +21,17 @@ import {
|
|||
OpenAPI2FormDataParameter,
|
||||
HttpMethod,
|
||||
OpenAPI2Parameter,
|
||||
} from "./oai2";
|
||||
} from "@azure-tools/openapi/v2";
|
||||
import oai3, {
|
||||
OpenAPI3Document,
|
||||
EncodingStyle,
|
||||
HttpOperation,
|
||||
JsonType,
|
||||
PathItem,
|
||||
SecurityType,
|
||||
OAuth2SecurityScheme,
|
||||
} from "@azure-tools/openapi/v3";
|
||||
import { resolveOperationConsumes, resolveOperationProduces } from "./content-type-utils";
|
||||
import { cleanElementName, convertOai2RefToOai3, parseOai2Ref } from "./refs-utils";
|
||||
import { ResolveReferenceFn } from "./runner";
|
||||
import { statusCodes } from "./status-codes";
|
||||
|
@ -70,7 +72,7 @@ export interface ConverterLogger {
|
|||
}
|
||||
|
||||
export class Oai2ToOai3 {
|
||||
public generated: MappingTreeObject<oai3.Model>;
|
||||
public generated: MappingTreeObject<OpenAPI3Document>;
|
||||
public mappings: PathMapping[] = [];
|
||||
|
||||
constructor(
|
||||
|
@ -291,127 +293,146 @@ export class Oai2ToOai3 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async visitParameter(
|
||||
parameterTarget: MappingTreeObject<Refable<oai3.Parameter>>,
|
||||
parameterValue: any,
|
||||
sourcePointer: string,
|
||||
parameterItemMembers: () => Iterable<Node>,
|
||||
) {
|
||||
if (this.isTargetReference(parameterTarget, parameterValue)) {
|
||||
return this.copyRef(parameterTarget, parameterValue, sourcePointer);
|
||||
} else {
|
||||
await this.visitParameterDefinition(parameterTarget, parameterValue, sourcePointer, parameterItemMembers);
|
||||
}
|
||||
}
|
||||
|
||||
private isTargetReference<I, T>(
|
||||
target: MappingTreeObject<Refable<T>>,
|
||||
value: Refable<I>,
|
||||
): target is MappingTreeObject<PathReference> {
|
||||
return "$ref" in value;
|
||||
}
|
||||
|
||||
private async copyRef(target: MappingTreeObject<PathReference>, value: PathReference, sourcePointer: string) {
|
||||
target.__set__("$ref", { value: await this.convertReferenceToOai3(value.$ref), sourcePointer });
|
||||
}
|
||||
|
||||
private async visitParameterDefinition(
|
||||
parameterTarget: MappingTreeObject<oai3.Parameter>,
|
||||
parameterValue: any,
|
||||
sourcePointer: string,
|
||||
parameterItemMembers: () => Iterable<Node>,
|
||||
) {
|
||||
if ("$ref" in parameterValue) {
|
||||
parameterTarget.__set__("$ref", { value: await this.convertReferenceToOai3(parameterValue.$ref), sourcePointer });
|
||||
} else {
|
||||
const parameterUnchangedProperties = ["name", "in", "description", "allowEmptyValue", "required"];
|
||||
const parameterUnchangedProperties = ["name", "in", "description", "allowEmptyValue", "required"];
|
||||
|
||||
for (const key of parameterUnchangedProperties) {
|
||||
if (parameterValue[key] !== undefined) {
|
||||
parameterTarget.__set__(key, { value: parameterValue[key], sourcePointer });
|
||||
}
|
||||
for (const key of parameterUnchangedProperties) {
|
||||
if (parameterValue[key] !== undefined) {
|
||||
parameterTarget.__set__(key as any, { value: parameterValue[key], sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterValue["x-ms-skip-url-encoding"] !== undefined) {
|
||||
if (parameterValue["x-ms-skip-url-encoding"] !== undefined) {
|
||||
if (parameterValue.in === "query") {
|
||||
parameterTarget.__set__("allowReserved", { value: true, sourcePointer });
|
||||
} else {
|
||||
parameterTarget.__set__("x-ms-skip-url-encoding", {
|
||||
value: parameterValue["x-ms-skip-url-encoding"],
|
||||
sourcePointer,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of extension properties that shouldn't just be passed through.
|
||||
*/
|
||||
const extensionPropertiesCustom = new Set(["x-ms-skip-url-encoding", "x-ms-original", "x-ms-enum"]);
|
||||
|
||||
for (const key of includeXDashKeys(parameterValue)) {
|
||||
if (parameterValue[key] !== undefined && !extensionPropertiesCustom.has(key)) {
|
||||
parameterTarget.__set__(key, { value: parameterValue[key], sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
// Collection Format
|
||||
if (parameterValue.type === "array") {
|
||||
parameterValue.collectionFormat = parameterValue.collectionFormat || "csv";
|
||||
if (
|
||||
parameterValue.collectionFormat === "csv" &&
|
||||
(parameterValue.in === "query" || parameterValue.in === "cookie")
|
||||
) {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.Form, sourcePointer });
|
||||
}
|
||||
if (
|
||||
parameterValue.collectionFormat === "csv" &&
|
||||
(parameterValue.in === "path" || parameterValue.in === "header")
|
||||
) {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.Simple, sourcePointer });
|
||||
}
|
||||
if (parameterValue.collectionFormat === "ssv") {
|
||||
if (parameterValue.in === "query") {
|
||||
parameterTarget.__set__("allowReserved", { value: true, sourcePointer });
|
||||
} else {
|
||||
parameterTarget.__set__("x-ms-skip-url-encoding", {
|
||||
value: parameterValue["x-ms-skip-url-encoding"],
|
||||
sourcePointer,
|
||||
});
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.SpaceDelimited, sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of extension properties that shouldn't just be passed through.
|
||||
*/
|
||||
const extensionPropertiesCustom = new Set(["x-ms-skip-url-encoding", "x-ms-original", "x-ms-enum"]);
|
||||
|
||||
for (const key of includeXDashKeys(parameterValue)) {
|
||||
if (parameterValue[key] !== undefined && !extensionPropertiesCustom.has(key)) {
|
||||
parameterTarget.__set__(key, { value: parameterValue[key], sourcePointer });
|
||||
if (parameterValue.collectionFormat === "pipes") {
|
||||
if (parameterValue.in === "query") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.PipeDelimited, sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
// Collection Format
|
||||
if (parameterValue.type === "array") {
|
||||
parameterValue.collectionFormat = parameterValue.collectionFormat || "csv";
|
||||
if (
|
||||
parameterValue.collectionFormat === "csv" &&
|
||||
(parameterValue.in === "query" || parameterValue.in === "cookie")
|
||||
) {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.Form, sourcePointer });
|
||||
}
|
||||
if (
|
||||
parameterValue.collectionFormat === "csv" &&
|
||||
(parameterValue.in === "path" || parameterValue.in === "header")
|
||||
) {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.Simple, sourcePointer });
|
||||
}
|
||||
if (parameterValue.collectionFormat === "ssv") {
|
||||
if (parameterValue.in === "query") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.SpaceDelimited, sourcePointer });
|
||||
}
|
||||
}
|
||||
if (parameterValue.collectionFormat === "pipes") {
|
||||
if (parameterValue.in === "query") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.PipeDelimited, sourcePointer });
|
||||
}
|
||||
}
|
||||
if (parameterValue.collectionFormat === "multi") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.Form, sourcePointer });
|
||||
parameterTarget.__set__("explode", { value: true, sourcePointer });
|
||||
}
|
||||
|
||||
// tsv is no longer supported in OAI3, but we still need to support this.
|
||||
if (parameterValue.collectionFormat === "tsv") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.TabDelimited, sourcePointer });
|
||||
}
|
||||
if (parameterValue.collectionFormat === "multi") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.Form, sourcePointer });
|
||||
parameterTarget.__set__("explode", { value: true, sourcePointer });
|
||||
}
|
||||
|
||||
if (parameterTarget.schema === undefined) {
|
||||
parameterTarget.__set__("schema", this.newObject(sourcePointer));
|
||||
// tsv is no longer supported in OAI3, but we still need to support this.
|
||||
if (parameterValue.collectionFormat === "tsv") {
|
||||
parameterTarget.__set__("style", { value: EncodingStyle.TabDelimited, sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
const schema: MappingTreeObject<oai3.Schema> = parameterTarget.schema as any;
|
||||
if (parameterTarget.schema === undefined) {
|
||||
parameterTarget.__set__("schema", this.newObject(sourcePointer));
|
||||
}
|
||||
|
||||
const schemaKeys = [
|
||||
"maximum",
|
||||
"exclusiveMaximum",
|
||||
"minimum",
|
||||
"exclusiveMinimum",
|
||||
"maxLength",
|
||||
"minLength",
|
||||
"pattern",
|
||||
"maxItems",
|
||||
"minItems",
|
||||
"uniqueItems",
|
||||
"enum",
|
||||
"x-ms-enum",
|
||||
"multipleOf",
|
||||
"default",
|
||||
"format",
|
||||
];
|
||||
const schema: MappingTreeObject<oai3.Schema> = parameterTarget.schema as any;
|
||||
|
||||
for (const { key, childIterator, pointer: jsonPointer } of parameterItemMembers()) {
|
||||
if (key === "schema") {
|
||||
if (schema.items === undefined) {
|
||||
schema.__set__("items", this.newObject(jsonPointer));
|
||||
}
|
||||
const schemaKeys = [
|
||||
"maximum",
|
||||
"exclusiveMaximum",
|
||||
"minimum",
|
||||
"exclusiveMinimum",
|
||||
"maxLength",
|
||||
"minLength",
|
||||
"pattern",
|
||||
"maxItems",
|
||||
"minItems",
|
||||
"uniqueItems",
|
||||
"enum",
|
||||
"x-ms-enum",
|
||||
"multipleOf",
|
||||
"default",
|
||||
"format",
|
||||
];
|
||||
|
||||
for (const { key, childIterator, pointer: jsonPointer } of parameterItemMembers()) {
|
||||
if (key === "schema") {
|
||||
if (schema.items === undefined) {
|
||||
schema.__set__("items", this.newObject(jsonPointer));
|
||||
}
|
||||
await this.visitSchema(schema.items as any, parameterValue.items, childIterator);
|
||||
} else if (schemaKeys.indexOf(key) !== -1) {
|
||||
schema.__set__(key as any, { value: parameterValue[key], sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterValue.type !== undefined) {
|
||||
schema.__set__("type", { value: parameterValue.type, sourcePointer });
|
||||
}
|
||||
|
||||
if (parameterValue.items !== undefined) {
|
||||
schema?.__set__("items", this.newObject(sourcePointer));
|
||||
for (const { key, childIterator } of parameterItemMembers()) {
|
||||
if (key === "items") {
|
||||
await this.visitSchema(schema.items as any, parameterValue.items, childIterator);
|
||||
} else if (schemaKeys.indexOf(key) !== -1) {
|
||||
schema.__set__(key, { value: parameterValue[key], sourcePointer });
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterValue.type !== undefined) {
|
||||
schema.__set__("type", { value: parameterValue.type, sourcePointer });
|
||||
}
|
||||
|
||||
if (parameterValue.items !== undefined) {
|
||||
schema?.__set__("items", this.newObject(sourcePointer));
|
||||
for (const { key, childIterator } of parameterItemMembers()) {
|
||||
if (key === "items") {
|
||||
await this.visitSchema(schema.items as any, parameterValue.items, childIterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +475,7 @@ export class Oai2ToOai3 {
|
|||
case "description":
|
||||
case "name":
|
||||
case "in":
|
||||
securityScheme.__set__(key, { value, sourcePointer: pointer });
|
||||
securityScheme.__set__(key as any, { value, sourcePointer: pointer });
|
||||
break;
|
||||
default:
|
||||
await this.visitExtensions(securityScheme, key, value, pointer);
|
||||
|
@ -470,7 +491,7 @@ export class Oai2ToOai3 {
|
|||
break;
|
||||
case "type":
|
||||
securityScheme.__set__("type", { value: SecurityType.Http, sourcePointer: pointer });
|
||||
securityScheme.__set__("scheme", { value: "basic", sourcePointer: pointer });
|
||||
securityScheme.__set__("scheme" as any, { value: "basic", sourcePointer: pointer });
|
||||
break;
|
||||
default:
|
||||
await this.visitExtensions(securityScheme, key, value, pointer);
|
||||
|
@ -480,12 +501,13 @@ export class Oai2ToOai3 {
|
|||
break;
|
||||
case "oauth2":
|
||||
{
|
||||
const oauth2Scheme: MappingTreeObject<OAuth2SecurityScheme> = securityScheme as any;
|
||||
if (v.description !== undefined) {
|
||||
securityScheme.__set__("description", { value: v.description, sourcePointer });
|
||||
oauth2Scheme.__set__("description", { value: v.description, sourcePointer });
|
||||
}
|
||||
|
||||
securityScheme.__set__("type", { value: v.type, sourcePointer });
|
||||
securityScheme.__set__("flows", this.newObject(sourcePointer));
|
||||
oauth2Scheme.__set__("type", { value: v.type, sourcePointer });
|
||||
oauth2Scheme.__set__("flows", this.newObject(sourcePointer));
|
||||
let flowName = v.flow;
|
||||
|
||||
// convert flow names to OpenAPI 3 flow names
|
||||
|
@ -497,22 +519,22 @@ export class Oai2ToOai3 {
|
|||
flowName = "authorizationCode";
|
||||
}
|
||||
|
||||
securityScheme.flows.__set__(flowName, this.newObject(sourcePointer));
|
||||
oauth2Scheme.flows.__set__(flowName, this.newObject(sourcePointer));
|
||||
let authorizationUrl;
|
||||
let tokenUrl;
|
||||
|
||||
if (v.authorizationUrl) {
|
||||
authorizationUrl = v.authorizationUrl.split("?")[0].trim() || "/";
|
||||
securityScheme.flows[flowName].__set__("authorizationUrl", { value: authorizationUrl, sourcePointer });
|
||||
oauth2Scheme.flows[flowName].__set__("authorizationUrl", { value: authorizationUrl, sourcePointer });
|
||||
}
|
||||
|
||||
if (v.tokenUrl) {
|
||||
tokenUrl = v.tokenUrl.split("?")[0].trim() || "/";
|
||||
securityScheme.flows[flowName].__set__("tokenUrl", { value: tokenUrl, sourcePointer });
|
||||
oauth2Scheme.flows[flowName].__set__("tokenUrl", { value: tokenUrl, sourcePointer });
|
||||
}
|
||||
|
||||
const scopes = v.scopes || {};
|
||||
securityScheme.flows[flowName].__set__("scopes", { value: scopes, sourcePointer });
|
||||
oauth2Scheme.flows[flowName].__set__("scopes", { value: scopes, sourcePointer });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -570,7 +592,7 @@ export class Oai2ToOai3 {
|
|||
for (const { key, value, pointer, childIterator } of schemaItemMemebers()) {
|
||||
switch (key) {
|
||||
case "$ref":
|
||||
target.__set__("$ref", { value: await this.convertReferenceToOai3(value), sourcePointer: pointer });
|
||||
await this.copyRef(target as any, { $ref: value }, pointer);
|
||||
break;
|
||||
case "additionalProperties":
|
||||
if (typeof value === "boolean") {
|
||||
|
@ -579,7 +601,7 @@ export class Oai2ToOai3 {
|
|||
} // false is assumed anyway in autorest.
|
||||
} else {
|
||||
target.__set__(key, this.newObject(pointer));
|
||||
await this.visitSchema(target[key]!, value, childIterator);
|
||||
await this.visitSchema(target[key]! as any, value, childIterator);
|
||||
}
|
||||
break;
|
||||
case "required":
|
||||
|
@ -612,7 +634,7 @@ export class Oai2ToOai3 {
|
|||
break;
|
||||
case "items":
|
||||
target.__set__(key, this.newObject(pointer));
|
||||
await this.visitSchema(target[key]!, value, childIterator);
|
||||
await this.visitSchema(target[key]! as any, value, childIterator);
|
||||
break;
|
||||
case "properties":
|
||||
target.__set__(key, this.newObject(pointer));
|
||||
|
@ -665,7 +687,7 @@ export class Oai2ToOai3 {
|
|||
}
|
||||
}
|
||||
|
||||
private async visitAllOf(target: MappingTreeArray<oai3.Refable<oai3.Schema>>, allOfMembers: () => Iterable<Node>) {
|
||||
private async visitAllOf(target: MappingTreeArray<Refable<oai3.Schema>>, allOfMembers: () => Iterable<Node>) {
|
||||
for (const { key: index, value, pointer, childIterator } of allOfMembers()) {
|
||||
target.__push__(this.newObject(pointer));
|
||||
await this.visitSchema(target[index], value, childIterator);
|
||||
|
@ -1009,7 +1031,7 @@ export class Oai2ToOai3 {
|
|||
if (parameterValue.schema !== undefined) {
|
||||
for (const { key, value, childIterator } of parameterItemMembers()) {
|
||||
if (key === "schema") {
|
||||
await this.visitSchema(requestBody.content[mimetype].schema!, value, childIterator);
|
||||
await this.visitSchema(requestBody.content[mimetype].schema! as any, value, childIterator);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1019,7 +1041,7 @@ export class Oai2ToOai3 {
|
|||
|
||||
// copy extensions in requestBody
|
||||
for (const { key, pointer: fieldPointer, value } of parameterItemMembers()) {
|
||||
if (key.startsWith("x-")) {
|
||||
if (isExtensionKey(key)) {
|
||||
if (!requestBody[key]) {
|
||||
requestBody.__set__(key, { value: value, sourcePointer: fieldPointer });
|
||||
}
|
||||
|
@ -1096,7 +1118,7 @@ export class Oai2ToOai3 {
|
|||
|
||||
// copy extensions in target property
|
||||
for (const { key, pointer: fieldPointer, value } of parameterItemMembers()) {
|
||||
if (key.startsWith("x-")) {
|
||||
if (isExtensionKey(key)) {
|
||||
targetProperty.__set__(key, { value: value, sourcePointer: fieldPointer });
|
||||
}
|
||||
}
|
||||
|
@ -1109,9 +1131,9 @@ export class Oai2ToOai3 {
|
|||
) {
|
||||
for (const { key, value, pointer, childIterator } of responsesItemMembers) {
|
||||
target.__set__(key, this.newObject(pointer));
|
||||
if (value.$ref) {
|
||||
target[key].__set__("$ref", { value: await this.convertReferenceToOai3(value.$ref), sourcePointer: pointer });
|
||||
} else if (key.startsWith("x-")) {
|
||||
if (this.isTargetReference(target, value)) {
|
||||
return this.copyRef(target, value, pointer);
|
||||
} else if (isExtensionKey(key)) {
|
||||
await this.visitExtensions(target[key], key, value, pointer);
|
||||
} else {
|
||||
await this.visitResponse(target[key], value, key, childIterator, pointer, produces);
|
||||
|
@ -1181,13 +1203,13 @@ export class Oai2ToOai3 {
|
|||
responseTarget.__set__("headers", this.newObject(sourcePointer));
|
||||
for (const h in responseValue.headers) {
|
||||
responseTarget.headers!.__set__(h, this.newObject(sourcePointer));
|
||||
await this.visitHeader(responseTarget.headers![h]!, responseValue.headers[h], sourcePointer);
|
||||
await this.visitHeader(responseTarget.headers![h]! as any, responseValue.headers[h], sourcePointer);
|
||||
}
|
||||
}
|
||||
|
||||
// copy extensions
|
||||
for (const { key, pointer: fieldPointer, value } of responsesFieldMembers()) {
|
||||
if (key.startsWith("x-") && responseTarget[key] === undefined) {
|
||||
if (isExtensionKey(key) && responseTarget[key] === undefined) {
|
||||
responseTarget.__set__(key, { value: value, sourcePointer: fieldPointer });
|
||||
}
|
||||
}
|
||||
|
@ -1221,11 +1243,8 @@ export class Oai2ToOai3 {
|
|||
headerValue: OpenAPI2ResponseHeader,
|
||||
sourcePointer: string,
|
||||
) {
|
||||
if (headerValue.$ref) {
|
||||
targetHeader.__set__("$ref", {
|
||||
value: this.convertReferenceToOai3(headerValue.schema.$ref),
|
||||
sourcePointer,
|
||||
});
|
||||
if (this.isTargetReference(targetHeader, headerValue)) {
|
||||
return this.copyRef(targetHeader, headerValue.schema, sourcePointer);
|
||||
} else {
|
||||
if (headerValue.type && headerValue.schema === undefined) {
|
||||
targetHeader.__set__("schema", this.newObject(sourcePointer));
|
||||
|
@ -1238,10 +1257,10 @@ export class Oai2ToOai3 {
|
|||
const schema: MappingTreeObject<oai3.Schema> = targetHeader.schema as any;
|
||||
for (const { key, childIterator } of visit(headerValue)) {
|
||||
if (key === "schema") {
|
||||
await this.visitSchema(schema.items!, headerValue.items, childIterator);
|
||||
await this.visitSchema(schema.items! as any, headerValue.items, childIterator);
|
||||
} else if (this.parameterTypeProperties.includes(key) || this.arrayProperties.includes(key)) {
|
||||
schema.__set__(key, { value: headerValue[key], sourcePointer });
|
||||
} else if (key.startsWith("x-") && targetHeader[key] === undefined) {
|
||||
schema.__set__(key as any, { value: headerValue[key], sourcePointer });
|
||||
} else if (isExtensionKey(key) && targetHeader[key] === undefined) {
|
||||
targetHeader.__set__(key, { value: headerValue[key], sourcePointer });
|
||||
}
|
||||
}
|
||||
|
@ -1251,7 +1270,7 @@ export class Oai2ToOai3 {
|
|||
}
|
||||
if (headerValue.items && headerValue.items.collectionFormat) {
|
||||
if (headerValue.collectionFormat === "csv") {
|
||||
targetHeader.__set__("style", { value: "simple", sourcePointer });
|
||||
targetHeader.__set__("style" as any, { value: "simple", sourcePointer });
|
||||
}
|
||||
|
||||
if (headerValue.collectionFormat === "multi") {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DataHandle, PathMapping } from "@azure-tools/datastore";
|
||||
import { getFromJsonPointer } from "@azure-tools/json";
|
||||
import { ConverterDiagnostic, ConverterLogger, Oai2ToOai3 } from "../converter";
|
||||
import { OpenAPI2Document } from "../oai2";
|
||||
import { OpenAPI2Document } from "@azure-tools/openapi/v2";
|
||||
import { loadInputFiles } from "./utils";
|
||||
|
||||
export interface OaiToOai3FileInput {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { DataHandle } from "@azure-tools/datastore";
|
||||
import { OpenAPI2Document } from "../oai2";
|
||||
import { OpenAPI2Document } from "@azure-tools/openapi/v2";
|
||||
import { OaiToOai3FileInput } from "./oai2-to-oai3-runner";
|
||||
|
||||
export async function loadInputFiles(inputFiles: DataHandle[]): Promise<OaiToOai3FileInput[]> {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import fs from "fs";
|
||||
import { join } from "path";
|
||||
import * as datastore from "@azure-tools/datastore";
|
||||
import { OpenAPI2Document } from "@azure-tools/openapi/v2";
|
||||
import { ConverterLogger, Oai2ToOai3 } from "../src/converter";
|
||||
import { OpenAPI2Document } from "../src/oai2";
|
||||
|
||||
const logger: ConverterLogger = {
|
||||
trackError: jest.fn(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { serializeJsonPointer } from "@azure-tools/json";
|
||||
import { OpenAPI2Document } from "@azure-tools/openapi/v2";
|
||||
import { ConverterLogger, Oai2ToOai3 } from "../src";
|
||||
import { OpenAPI2Document } from "../src/oai2";
|
||||
|
||||
const defaultOpenApi2 = {
|
||||
swagger: "2.0",
|
||||
|
|
|
@ -4,6 +4,24 @@
|
|||
"description": "OpenAPI common code for Azure Tools.",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./v2": "./dist/v2/index.js",
|
||||
"./v3": "./dist/v3/index.js"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
"./dist/index.d.ts"
|
||||
],
|
||||
"v2": [
|
||||
"./dist/v2/index.d.ts"
|
||||
],
|
||||
"v3": [
|
||||
"./dist/v3/index.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
|
@ -46,7 +64,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
},
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# Project: @azure-tools/openapi
|
||||
# @azure-tools/openapi
|
||||
|
||||
Contains types reprensting OpenAPI 3.0 documents
|
||||
Library providing types for OpenAPI 2.0 and OpenAPI 3.0 as well as some utilities to manipulate those documents.
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export interface PathReference {
|
||||
$ref: string;
|
||||
}
|
||||
|
||||
export type Refable<T> = T | PathReference;
|
||||
|
||||
export interface Dereferenced<T> {
|
||||
instance: T;
|
||||
name: string;
|
||||
fromRef?: boolean;
|
||||
}
|
||||
|
||||
export type Reference<T> = T;
|
||||
|
||||
export type Refable<T> = T | PathReference;
|
||||
|
||||
export type ExtensionKey = `x-${string}`;
|
||||
|
||||
export type EnumStr<T extends string> = `${T}`;
|
||||
export type Extensions = {
|
||||
[key in ExtensionKey]: any;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export * from "./oai3";
|
||||
export * from "./formats";
|
||||
export * from "./common";
|
||||
export * from "./utils";
|
||||
export * from "./v3";
|
||||
|
|
|
@ -1,25 +1,21 @@
|
|||
import { PathReference } from "../common";
|
||||
|
||||
export interface OpenAPI2Definition {
|
||||
[key: string]: unknown;
|
||||
|
||||
additionalProperties?: OpenAPI2Definition | OpenAPI2Reference | boolean;
|
||||
additionalProperties?: OpenAPI2Definition | PathReference | boolean;
|
||||
allOf?: OpenAPI2Definition[];
|
||||
description?: string;
|
||||
enum?: string[];
|
||||
format?: string;
|
||||
items?: OpenAPI2Definition | OpenAPI2Reference;
|
||||
oneOf?: (OpenAPI2Definition | OpenAPI2Reference)[];
|
||||
properties?: { [index: string]: OpenAPI2Definition | OpenAPI2Reference };
|
||||
items?: OpenAPI2Definition | PathReference;
|
||||
oneOf?: (OpenAPI2Definition | PathReference)[];
|
||||
properties?: { [index: string]: OpenAPI2Definition | PathReference };
|
||||
required?: string[];
|
||||
title?: string;
|
||||
type?: OpenAPI2Type; // allow this to be optional to cover cases when this is missing
|
||||
}
|
||||
|
||||
export interface OpenAPI2Reference<T = any> {
|
||||
$ref: string;
|
||||
}
|
||||
|
||||
export type Refable<T> = OpenAPI2Reference<T> | T;
|
||||
|
||||
export type OpenAPI2Type =
|
||||
| "array"
|
||||
| "boolean"
|
|
@ -1,8 +1,9 @@
|
|||
import { OpenAPI2Definition, OpenAPI2Reference } from "./definition";
|
||||
import { PathReference } from "../common";
|
||||
import { OpenAPI2Definition } from "./definition";
|
||||
|
||||
export interface OpenAPI2HeaderDefinition {
|
||||
type: "string" | "number" | "integer" | "boolean" | "array";
|
||||
schema: OpenAPI2Reference & OpenAPI2Definition;
|
||||
schema: PathReference & OpenAPI2Definition;
|
||||
items: any;
|
||||
collectionFormat: "csv" | "ssv" | "tsv" | "pipes" | "multi";
|
||||
description?: string;
|
|
@ -1,4 +1,5 @@
|
|||
import { OpenAPI2Definition, OpenAPI2Reference, Refable } from "./definition";
|
||||
import { PathReference, Refable } from "../common";
|
||||
import { OpenAPI2Definition } from "./definition";
|
||||
import { OpenAPI2HeaderDefinition } from "./header";
|
||||
import { OpenAPI2Parameter } from "./parameter";
|
||||
|
||||
|
@ -33,4 +34,4 @@ export interface OpenAPI2OperationResponse {
|
|||
headers?: { [headerName: string]: OpenAPI2ResponseHeader };
|
||||
}
|
||||
|
||||
export type OpenAPI2ResponseHeader = OpenAPI2Reference & OpenAPI2HeaderDefinition;
|
||||
export type OpenAPI2ResponseHeader = PathReference & OpenAPI2HeaderDefinition;
|
|
@ -0,0 +1 @@
|
|||
export type EnumStr<T extends string> = `${T}`;
|
|
@ -0,0 +1,6 @@
|
|||
import { OpenAPI3Document } from "./oai3";
|
||||
|
||||
/**
|
||||
* @deprecated use OpenAPI3Document
|
||||
*/
|
||||
export type Model = OpenAPI3Document;
|
|
@ -0,0 +1,4 @@
|
|||
export * from "./oai3";
|
||||
export * from "./formats";
|
||||
export * from "./common";
|
||||
export * from "./deprecated";
|
|
@ -3,25 +3,25 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EnumStr, Refable as Reference } from "./common";
|
||||
import { Extensions, Refable } from "../common";
|
||||
import { EnumStr } from "./common";
|
||||
|
||||
export type Dictionary<T> = { [key: string]: T };
|
||||
|
||||
// OAI3 variants for the basic model definitions.
|
||||
|
||||
/** Nearly all classes can support additional key-value pairs where the key starts with 'x-' */
|
||||
export interface Extensions {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/** Properties, Parameters, Operations and Schemas require additional support */
|
||||
export interface Implementation<T> {}
|
||||
|
||||
export interface Details {}
|
||||
|
||||
/** Property References may have additional data that's not in the target reference */
|
||||
/**
|
||||
* Property References may have additional data that's not in the target reference
|
||||
*/
|
||||
export interface PropertyDetails extends Details, Extensions {
|
||||
description?: string;
|
||||
readOnly?: boolean;
|
||||
nullable?: boolean;
|
||||
}
|
||||
|
||||
/** Parameter References may have additional data that's not in the target reference */
|
||||
|
@ -73,12 +73,12 @@ export function isQueryParameter(parameter: Parameter): parameter is InQuery & P
|
|||
/**
|
||||
* Properties have additional data when referencing them
|
||||
*/
|
||||
export type PropertyReference<T> = PropertyDetails & Reference<T>;
|
||||
export type PropertyReference<T> = PropertyDetails & Refable<T>;
|
||||
|
||||
/**
|
||||
* Parameter references could have additional data to override the shared parameter value.
|
||||
*/
|
||||
export type ParameterReference<T> = ParameterDetails & Reference<T>;
|
||||
export type ParameterReference<T> = ParameterDetails & Refable<T>;
|
||||
|
||||
/**
|
||||
* @description common ways of serializing simple parameters
|
||||
|
@ -130,9 +130,9 @@ export type QueryEncodingStyle =
|
|||
| EncodingStyle.DeepObject;
|
||||
export type PathEncodingStyle = EncodingStyle.Matrix | EncodingStyle.Label | EncodingStyle.Simple;
|
||||
|
||||
export interface Model extends Extensions {
|
||||
export interface OpenAPI3Document extends Extensions {
|
||||
paths: Dictionary<PathItem>;
|
||||
openApi: string;
|
||||
openapi: string;
|
||||
info: Info;
|
||||
externalDocs?: ExternalDocumentation;
|
||||
servers?: Array<Server>;
|
||||
|
@ -142,15 +142,15 @@ export interface Model extends Extensions {
|
|||
}
|
||||
|
||||
export interface Components extends Extensions {
|
||||
schemas?: Dictionary<Reference<Schema>>;
|
||||
responses?: Dictionary<Reference<Response>>;
|
||||
parameters?: Dictionary<Reference<Parameter>>;
|
||||
examples?: Dictionary<Reference<Example>>;
|
||||
requestBodies?: Dictionary<Reference<RequestBody>>;
|
||||
headers?: Dictionary<Reference<Header>>;
|
||||
securitySchemes?: Dictionary<Reference<SecurityScheme>>;
|
||||
links?: Dictionary<Reference<Link>>;
|
||||
callbacks?: Dictionary<Reference<Callback>>;
|
||||
schemas?: Dictionary<Schema>;
|
||||
responses?: Dictionary<Response>;
|
||||
parameters?: Dictionary<Parameter>;
|
||||
examples?: Dictionary<Example>;
|
||||
requestBodies?: Dictionary<RequestBody>;
|
||||
headers?: Dictionary<Header>;
|
||||
securitySchemes?: Dictionary<SecurityScheme>;
|
||||
links?: Dictionary<Link>;
|
||||
callbacks?: Dictionary<Callback>;
|
||||
}
|
||||
|
||||
export interface APIKeySecurityScheme extends Extensions {
|
||||
|
@ -188,7 +188,7 @@ export interface Discriminator extends Extensions {
|
|||
}
|
||||
export interface Encoding extends Extensions {
|
||||
contentType?: string;
|
||||
headers?: Dictionary<Reference<Header>>;
|
||||
headers?: Dictionary<Refable<Header>>;
|
||||
style?: QueryEncodingStyle;
|
||||
explode?: boolean;
|
||||
allowReserved?: boolean;
|
||||
|
@ -248,7 +248,7 @@ export interface MediaType extends Extensions, Partial<HasExample>, Partial<HasE
|
|||
/** A map between a property name and its encoding information. The key, being the property name, MUST exist in the schema as a property. The encoding object SHALL only apply to requestBody objects when the media type is multipart or application/x-www-form-urlencoded. */
|
||||
encoding?: Dictionary<Encoding>;
|
||||
/** The schema defining the type used for the request body. */
|
||||
schema?: Reference<Schema>;
|
||||
schema?: Refable<Schema>;
|
||||
}
|
||||
|
||||
export interface NonBearerHTTPSecurityScheme extends Extensions {
|
||||
|
@ -280,9 +280,9 @@ export interface HttpOperation extends Deprecatable, Extensions, Implementation<
|
|||
externalDocs?: ExternalDocumentation;
|
||||
operationId?: string;
|
||||
parameters?: ParameterReference<Parameter>[];
|
||||
requestBody?: Reference<RequestBody>;
|
||||
responses: Dictionary<Reference<Response>>;
|
||||
callbacks?: Dictionary<Reference<Callback>>;
|
||||
requestBody?: Refable<RequestBody>;
|
||||
responses: Dictionary<Refable<Response>>;
|
||||
callbacks?: Dictionary<Refable<Callback>>;
|
||||
|
||||
security?: Array<SecurityRequirement>;
|
||||
servers?: Array<Server>;
|
||||
|
@ -293,7 +293,7 @@ export interface Deprecatable {
|
|||
}
|
||||
|
||||
export interface HasSchema {
|
||||
schema: Reference<Schema>;
|
||||
schema: Refable<Schema>;
|
||||
explode?: boolean;
|
||||
}
|
||||
export interface HasContent {
|
||||
|
@ -303,7 +303,7 @@ export interface HasExample {
|
|||
example: any;
|
||||
}
|
||||
export interface HasExamples {
|
||||
examples: Dictionary<Reference<HasExample>>;
|
||||
examples: Dictionary<Refable<HasExample>>;
|
||||
}
|
||||
export interface InCookie extends HasSchema, Partial<HasExample>, Partial<HasExamples> {
|
||||
in: ParameterLocation.Cookie;
|
||||
|
@ -368,9 +368,9 @@ export interface RequestBody extends Extensions {
|
|||
|
||||
export interface Response extends Extensions {
|
||||
description: string;
|
||||
headers?: Dictionary<Reference<Header>>;
|
||||
headers?: Dictionary<Refable<Header>>;
|
||||
content?: Dictionary<MediaType>;
|
||||
links?: Dictionary<Reference<Link>>;
|
||||
links?: Dictionary<Refable<Link>>;
|
||||
}
|
||||
|
||||
export interface Schema extends Deprecatable, Extensions, Implementation<SchemaDetails> {
|
||||
|
@ -418,13 +418,13 @@ export interface Schema extends Deprecatable, Extensions, Implementation<SchemaD
|
|||
enum?: Array<any>;
|
||||
|
||||
/* properties with potential references */
|
||||
not?: Reference<Schema>;
|
||||
allOf?: Array<Reference<Schema>>;
|
||||
oneOf?: Array<Reference<Schema>>;
|
||||
anyOf?: Array<Reference<Schema>>;
|
||||
items?: Reference<Schema>;
|
||||
not?: Refable<Schema>;
|
||||
allOf?: Array<Refable<Schema>>;
|
||||
oneOf?: Array<Refable<Schema>>;
|
||||
anyOf?: Array<Refable<Schema>>;
|
||||
items?: Refable<Schema>;
|
||||
properties?: Dictionary<PropertyReference<Schema>>;
|
||||
additionalProperties?: boolean | Reference<Schema>;
|
||||
additionalProperties?: boolean | Refable<Schema>;
|
||||
}
|
||||
|
||||
export interface Server extends Extensions {
|
|
@ -40,7 +40,7 @@
|
|||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint-plugin-import": "~2.24.2",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
},
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"@azure-tools/tasks": "~3.0.0",
|
||||
"expect": "~26.6.2",
|
||||
"jest-snapshot": "~26.6.2",
|
||||
"jest": "^27.0.4"
|
||||
"jest": "^28.0.0-alpha.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.20",
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
"eslint-plugin-prettier": "~3.4.0",
|
||||
"eslint-plugin-unicorn": "~33.0.1",
|
||||
"eslint": "^7.17.0",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"prettier": "~2.3.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.4.2"
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
"commonmark": "^0.27.0",
|
||||
"deep-equal": "^2.0.5",
|
||||
"express": "~4.17.1",
|
||||
"jest": "^27.0.4",
|
||||
"jest": "^28.0.0-alpha.7",
|
||||
"js-yaml": "~4.0.0",
|
||||
"morgan": "^1.10.0",
|
||||
"mustache": "^4.1.0",
|
||||
|
|
Загрузка…
Ссылка в новой задаче