зеркало из https://github.com/Azure/autorest.git
Tweak OpenAPI include/exclude `x-dash` utils types (#4218)
This commit is contained in:
Родитель
fbb7d48054
Коммит
59be4e234e
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/core",
|
||||
"comment": "",
|
||||
"type": "none"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/core",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/modelerfour",
|
||||
"comment": "",
|
||||
"type": "none"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/modelerfour",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@azure-tools/codegen",
|
||||
"comment": "**Remove** include/exclude x-dash properties utils. Use @azure-tools/openapi instead for this functionality",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@azure-tools/codegen",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@azure-tools/openapi",
|
||||
"comment": "**Update** include/exclude x-dash properties utils types",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@azure-tools/openapi",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import oai3 from "@azure-tools/openapi";
|
||||
import { SemanticErrorCodes } from "../types";
|
||||
import { validateDiscriminator } from "./discriminator-validator";
|
||||
import { validateRefsSiblings } from "./refs-siblings-validator";
|
||||
|
||||
const baseModel: oai3.Model = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { walk } from "@azure-tools/json";
|
||||
import oai3, { excludeXDash, omitXDashProperties } from "@azure-tools/openapi";
|
||||
import oai3 from "@azure-tools/openapi";
|
||||
import { SemanticError, SemanticErrorCodes } from "../types";
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,7 @@ import assert from "assert";
|
|||
import { AutoRest } from "../src/lib/autorest-core";
|
||||
import { RealFileSystem } from "@azure-tools/datastore";
|
||||
import { Channel, Message } from "../src/lib/message";
|
||||
import { CreateFolderUri, ResolveUri } from "@azure-tools/uri";
|
||||
import { createFolderUri, resolveUri } from "@azure-tools/uri";
|
||||
import { AppRoot } from "../src/lib/constants";
|
||||
import { AutorestConfiguration } from "@autorest/configuration";
|
||||
|
||||
|
@ -70,90 +70,11 @@ describe("EndToEnd", () => {
|
|||
it("other configuration scenario", async () => {
|
||||
const autoRest = new AutoRest(
|
||||
new RealFileSystem(),
|
||||
ResolveUri(CreateFolderUri(AppRoot), "test/resources/literate-example/readme-complicated.md"),
|
||||
resolveUri(createFolderUri(AppRoot), "test/resources/literate-example/readme-complicated.md"),
|
||||
);
|
||||
// PumpMessagesToConsole(autoRest);
|
||||
|
||||
const context = await autoRest.view;
|
||||
assert.strictEqual(context.config["shouldwork" as keyof AutorestConfiguration], true);
|
||||
});
|
||||
|
||||
// todo: skipping because testing is broken?
|
||||
it.skip("complicated configuration scenario", async () => {
|
||||
const autoRest = new AutoRest(
|
||||
new RealFileSystem(),
|
||||
ResolveUri(CreateFolderUri(AppRoot), "test/resources/literate-example/readme-complicated.md"),
|
||||
);
|
||||
// PumpMessagesToConsole(autoRest);
|
||||
autoRest.AddConfiguration({
|
||||
"cmd-line-true": true,
|
||||
"cmd-line-false": false,
|
||||
"cmd-line-complex": {
|
||||
true: true,
|
||||
false: false,
|
||||
},
|
||||
});
|
||||
|
||||
const config = await autoRest.view;
|
||||
assert.strictEqual(config.config.inputFileUris.length, 1);
|
||||
|
||||
const messages: Array<Message> = [];
|
||||
|
||||
autoRest.Message.Subscribe((_, m) => {
|
||||
if (m.Channel === Channel.Warning) {
|
||||
messages.push(m);
|
||||
}
|
||||
});
|
||||
assert.equal(await autoRest.Process().finish, true);
|
||||
assert.notEqual(messages.length, 0);
|
||||
});
|
||||
// testing end-to-end for non-arm type validation rules. Since all validation rules are currently defaulted to
|
||||
// ARM, non-ARM documents should show 0 validation messages
|
||||
// TODO: fix this test when validation rules are properly categorized
|
||||
it.skip("non-arm type spec testing", async () => {
|
||||
const autoRest = new AutoRest(
|
||||
new RealFileSystem(),
|
||||
ResolveUri(CreateFolderUri(AppRoot), "test/resources/validation-options/readme.md"),
|
||||
);
|
||||
autoRest.AddConfiguration({
|
||||
"openapi-type": "default",
|
||||
"azure-validator": true,
|
||||
});
|
||||
|
||||
const config = await autoRest.view;
|
||||
const messages: Array<Message> = [];
|
||||
|
||||
autoRest.Message.Subscribe((_, m) => {
|
||||
messages.push(m);
|
||||
});
|
||||
assert.equal(await autoRest.Process().finish, true);
|
||||
assert.notEqual(messages.length, 0);
|
||||
// flag any fatal errors
|
||||
assert.equal(messages.filter((m) => m.Channel === Channel.Fatal).length, 0);
|
||||
});
|
||||
|
||||
// todo: skipping because testing is broken?
|
||||
it.skip("arm type spec testing", async () => {
|
||||
const autoRest = new AutoRest(
|
||||
new RealFileSystem(),
|
||||
ResolveUri(CreateFolderUri(AppRoot), "test/resources/validation-options/readme.md"),
|
||||
);
|
||||
autoRest.AddConfiguration({
|
||||
"openapi-type": "arm",
|
||||
"azure-validator": true,
|
||||
});
|
||||
|
||||
const config = await autoRest.view;
|
||||
|
||||
const messages: Array<Message> = [];
|
||||
|
||||
autoRest.Message.Subscribe((_, m) => {
|
||||
messages.push(m);
|
||||
});
|
||||
// PumpMessagesToConsole(autoRest);
|
||||
assert.equal(await autoRest.Process().finish, true);
|
||||
// flag any fatal errors
|
||||
assert.equal(messages.filter((m) => m.Channel === Channel.Fatal).length, 0);
|
||||
assert.notEqual(messages.length, 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Session } from "@autorest/extension-base";
|
||||
import * as OpenAPI from "@azure-tools/openapi";
|
||||
import { values, length, items, ToDictionary, Dictionary } from "@azure-tools/linq";
|
||||
import { values, length, ToDictionary, Dictionary } from "@azure-tools/linq";
|
||||
import {
|
||||
ChoiceSchema,
|
||||
XmlSerlializationFormat,
|
||||
|
@ -10,7 +10,7 @@ import {
|
|||
ChoiceValue,
|
||||
SetType,
|
||||
} from "@autorest/codemodel";
|
||||
import { StringFormat, JsonType, ParameterLocation } from "@azure-tools/openapi";
|
||||
import { StringFormat, JsonType, ParameterLocation, includeXDashKeys } from "@azure-tools/openapi";
|
||||
import { getPascalIdentifier } from "@azure-tools/codegen";
|
||||
|
||||
export interface XMSEnum {
|
||||
|
@ -420,7 +420,7 @@ export class Interpretations {
|
|||
}
|
||||
|
||||
static getExtensionProperties(dictionary: Dictionary<any>): Dictionary<any> | undefined {
|
||||
const result = ToDictionary(OpenAPI.includeXDash(dictionary), (each) => dictionary[each]);
|
||||
const result = ToDictionary(includeXDashKeys(dictionary), (each) => dictionary[each]);
|
||||
for (const each of removeKnownParameters) {
|
||||
delete result[each];
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ import {
|
|||
StringFormat,
|
||||
NumberFormat,
|
||||
MediaType,
|
||||
filterOutXDash,
|
||||
omitXDashProperties,
|
||||
} from "@azure-tools/openapi";
|
||||
import * as OpenAPI from "@azure-tools/openapi";
|
||||
import { items, values, Dictionary, length, keys } from "@azure-tools/linq";
|
||||
import { items, values, Dictionary, length } from "@azure-tools/linq";
|
||||
import {
|
||||
HttpMethod,
|
||||
HttpModel,
|
||||
|
@ -167,7 +167,7 @@ export class ModelerFour {
|
|||
contact: i.contact,
|
||||
license: i.license,
|
||||
termsOfService: i.termsOfService,
|
||||
externalDocs: filterOutXDash<ExternalDocumentation>(this.input.externalDocs as any),
|
||||
externalDocs: omitXDashProperties<ExternalDocumentation>(this.input.externalDocs as any),
|
||||
extensions: Interpretations.getExtensionProperties(i),
|
||||
},
|
||||
extensions: Interpretations.getExtensionProperties(this.input),
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
"directories": {
|
||||
"doc": "docs"
|
||||
},
|
||||
"main": "dist/exports.js",
|
||||
"typings": "dist/exports.d.ts",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Dictionary } from "@azure-tools/linq";
|
||||
|
||||
export function includeXDash<T>(dictionary: Dictionary<T>) {
|
||||
return Object.keys(dictionary).filter((v, i, a) => v.startsWith("x-"));
|
||||
}
|
||||
export function excludeXDash<T>(dictionary: Dictionary<T>) {
|
||||
return Object.keys(dictionary).filter((v, i, a) => !v.startsWith("x-"));
|
||||
}
|
|
@ -2,7 +2,6 @@ export * from "./exec";
|
|||
export * from "./file-generator";
|
||||
export * from "./initializer";
|
||||
export * from "./intersect";
|
||||
export * from "./dictionary-filter";
|
||||
export * from "./pluralization";
|
||||
export * from "./text-manipulation";
|
||||
export * from "./utility";
|
|
@ -0,0 +1,65 @@
|
|||
import { omitXDashKeys, includeXDashKeys, includeXDashProperties, omitXDashProperties } from "./utils";
|
||||
|
||||
describe("OpenAPI utils", () => {
|
||||
it("includeXDashKeys returns x- properties keys", () => {
|
||||
// Type validation
|
||||
const result: ("x-foo" | "x-other")[] = includeXDashKeys({
|
||||
"foo": 1,
|
||||
"bar": 2,
|
||||
"x-foo": 3,
|
||||
"x-other": 4,
|
||||
});
|
||||
expect(result).toEqual(["x-foo", "x-other"]);
|
||||
});
|
||||
|
||||
it("omitXDashKeys returns non x- properties keys", () => {
|
||||
// Type validation
|
||||
const result: ("foo" | "bar")[] = omitXDashKeys({
|
||||
"foo": 1,
|
||||
"bar": 2,
|
||||
"x-foo": 3,
|
||||
"x-other": 4,
|
||||
});
|
||||
expect(result).toEqual(["foo", "bar"]);
|
||||
});
|
||||
|
||||
it("includeXDashProperties returns x- properties", () => {
|
||||
const result = includeXDashProperties({
|
||||
"foo": 1,
|
||||
"bar": 2,
|
||||
"x-foo": 3,
|
||||
"x-other": 4,
|
||||
});
|
||||
// Type validation
|
||||
expect<{ "x-foo": number; "x-other": number }>(result).toEqual({
|
||||
"x-foo": 3,
|
||||
"x-other": 4,
|
||||
});
|
||||
});
|
||||
|
||||
it("includeXDashProperties returns undefined if undefined is passed", () => {
|
||||
const result = includeXDashProperties(undefined);
|
||||
// Type validation
|
||||
expect<undefined>(result).toEqual(undefined);
|
||||
});
|
||||
|
||||
it("omitXDashProperties returns x- properties", () => {
|
||||
// Type validation
|
||||
const result = omitXDashProperties({
|
||||
"foo": 1,
|
||||
"bar": 2,
|
||||
"x-foo": 3,
|
||||
"x-other": 4,
|
||||
});
|
||||
expect<{ foo: number; bar: number }>(result).toEqual({
|
||||
foo: 1,
|
||||
bar: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it("omitXDashProperties returns undefined if undefined is passed", () => {
|
||||
const result = omitXDashProperties(undefined);
|
||||
// Type validation
|
||||
expect<undefined>(result).toEqual(undefined);
|
||||
});
|
||||
});
|
|
@ -4,54 +4,55 @@ import { Dereferenced, ExtensionKey, PathReference, Refable } from "./common";
|
|||
* Only return properties starting with x-
|
||||
* @param dictionary
|
||||
*/
|
||||
export const includeXDash = (dictionary: Record<string, unknown>): ExtensionKey[] => {
|
||||
return Object.keys(dictionary).filter((v, i, a) => v.startsWith("x-")) as any;
|
||||
};
|
||||
export function includeXDashKeys<T extends Record<string | ExtensionKey, any>>(
|
||||
dictionary: T,
|
||||
): Extract<keyof T, ExtensionKey>[] {
|
||||
return Object.keys(dictionary).filter((v) => v.startsWith("x-")) as any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only return properties NOT starting with x-
|
||||
* @param dictionary
|
||||
*/
|
||||
export const excludeXDash = <T extends {}>(dictionary: T): string[] => {
|
||||
return Object.keys(dictionary).filter((v, i, a) => !v.startsWith("x-"));
|
||||
};
|
||||
export function omitXDashKeys<T extends {}>(dictionary: T): Exclude<keyof T, ExtensionKey>[] {
|
||||
return Object.keys(dictionary).filter((v) => !v.startsWith("x-")) as any;
|
||||
}
|
||||
|
||||
export function includeXDashProperties<T extends { [key: string]: unknown }>(obj: T | undefined): T | undefined {
|
||||
if (!obj) {
|
||||
return undefined;
|
||||
export function includeXDashProperties<T extends Record<string | ExtensionKey, any> | undefined>(
|
||||
obj: T,
|
||||
): T extends undefined ? undefined : Pick<T, Extract<keyof T, ExtensionKey>> {
|
||||
if (obj === undefined) {
|
||||
return undefined as any;
|
||||
}
|
||||
|
||||
const result: any = {};
|
||||
for (const key of includeXDash(obj)) {
|
||||
for (const key of includeXDashKeys(obj)) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function omitXDashProperties<T extends {}>(obj: T | undefined): T | undefined {
|
||||
if (!obj) {
|
||||
return undefined;
|
||||
export function omitXDashProperties<T extends {} | undefined>(
|
||||
obj: T,
|
||||
): T extends undefined ? undefined : Pick<T, Exclude<keyof T, ExtensionKey>> {
|
||||
if (obj === undefined) {
|
||||
return undefined as any;
|
||||
}
|
||||
|
||||
const result: any = {};
|
||||
for (const key of excludeXDash(obj)) {
|
||||
for (const key of omitXDashKeys(obj)) {
|
||||
result[key] = (obj as any)[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use omitXDashProperties
|
||||
*/
|
||||
export const filterOutXDash = omitXDashProperties;
|
||||
|
||||
/**
|
||||
* Identifies if a given refable is a reference or an instance
|
||||
* @param item Check if item is a reference.
|
||||
*/
|
||||
export const isReference = <T>(item: Refable<T>): item is PathReference => {
|
||||
export function isReference<T>(item: Refable<T>): item is PathReference {
|
||||
return item && (<PathReference>item).$ref ? true : false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object instance for the item, regardless if it's a reference or not.
|
||||
|
@ -59,7 +60,7 @@ export const isReference = <T>(item: Refable<T>): item is PathReference => {
|
|||
* @param item Reference item.
|
||||
* @param stack Stack for circular dependencies.
|
||||
*/
|
||||
export const dereference = <T>(document: any, item: Refable<T>, stack: string[] = []): Dereferenced<T> => {
|
||||
export function dereference<T>(document: any, item: Refable<T>, stack: string[] = []): Dereferenced<T> {
|
||||
let name: string | undefined;
|
||||
|
||||
if (isReference(item)) {
|
||||
|
@ -86,4 +87,4 @@ export const dereference = <T>(document: any, item: Refable<T>, stack: string[]
|
|||
return { instance: node, name: name || "", fromRef: true };
|
||||
}
|
||||
return { instance: item, name: "", fromRef: false };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
it("works", () => {
|
||||
expect("hello").not.toEqual("world");
|
||||
});
|
Загрузка…
Ссылка в новой задаче