From 59be4e234e47d26cb3f885f52ed890afe09629a8 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Fri, 16 Jul 2021 13:55:41 -0700 Subject: [PATCH] Tweak OpenAPI include/exclude `x-dash` utils types (#4218) --- .../openapi-ts4.3-feat_2021-07-16-16-50.json | 11 +++ .../openapi-ts4.3-feat_2021-07-16-16-50.json | 11 +++ .../openapi-ts4.3-feat_2021-07-16-16-50.json | 11 +++ .../openapi-ts4.3-feat_2021-07-16-16-50.json | 11 +++ .../refs-siblings-validator.test.ts | 1 - .../validators/refs-siblings-validator.ts | 2 +- .../extensions/core/test/end-to-end.test.ts | 83 +------------------ .../src/modeler/interpretations.ts | 6 +- .../modelerfour/src/modeler/modelerfour.ts | 6 +- packages/libs/codegen/package.json | 4 +- .../libs/codegen/src/dictionary-filter.ts | 12 --- .../libs/codegen/src/{exports.ts => index.ts} | 1 - packages/libs/openapi/src/utils.test.ts | 65 +++++++++++++++ packages/libs/openapi/src/utils.ts | 47 ++++++----- packages/libs/openapi/test/hello.test.ts | 3 - 15 files changed, 144 insertions(+), 130 deletions(-) create mode 100644 common/changes/@autorest/core/openapi-ts4.3-feat_2021-07-16-16-50.json create mode 100644 common/changes/@autorest/modelerfour/openapi-ts4.3-feat_2021-07-16-16-50.json create mode 100644 common/changes/@azure-tools/codegen/openapi-ts4.3-feat_2021-07-16-16-50.json create mode 100644 common/changes/@azure-tools/openapi/openapi-ts4.3-feat_2021-07-16-16-50.json delete mode 100644 packages/libs/codegen/src/dictionary-filter.ts rename packages/libs/codegen/src/{exports.ts => index.ts} (91%) create mode 100644 packages/libs/openapi/src/utils.test.ts delete mode 100644 packages/libs/openapi/test/hello.test.ts diff --git a/common/changes/@autorest/core/openapi-ts4.3-feat_2021-07-16-16-50.json b/common/changes/@autorest/core/openapi-ts4.3-feat_2021-07-16-16-50.json new file mode 100644 index 000000000..895c2cfb9 --- /dev/null +++ b/common/changes/@autorest/core/openapi-ts4.3-feat_2021-07-16-16-50.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@autorest/core", + "comment": "", + "type": "none" + } + ], + "packageName": "@autorest/core", + "email": "tiguerin@microsoft.com" +} \ No newline at end of file diff --git a/common/changes/@autorest/modelerfour/openapi-ts4.3-feat_2021-07-16-16-50.json b/common/changes/@autorest/modelerfour/openapi-ts4.3-feat_2021-07-16-16-50.json new file mode 100644 index 000000000..cf78927a9 --- /dev/null +++ b/common/changes/@autorest/modelerfour/openapi-ts4.3-feat_2021-07-16-16-50.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@autorest/modelerfour", + "comment": "", + "type": "none" + } + ], + "packageName": "@autorest/modelerfour", + "email": "tiguerin@microsoft.com" +} \ No newline at end of file diff --git a/common/changes/@azure-tools/codegen/openapi-ts4.3-feat_2021-07-16-16-50.json b/common/changes/@azure-tools/codegen/openapi-ts4.3-feat_2021-07-16-16-50.json new file mode 100644 index 000000000..be1aa55b7 --- /dev/null +++ b/common/changes/@azure-tools/codegen/openapi-ts4.3-feat_2021-07-16-16-50.json @@ -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" +} \ No newline at end of file diff --git a/common/changes/@azure-tools/openapi/openapi-ts4.3-feat_2021-07-16-16-50.json b/common/changes/@azure-tools/openapi/openapi-ts4.3-feat_2021-07-16-16-50.json new file mode 100644 index 000000000..7e5a7b144 --- /dev/null +++ b/common/changes/@azure-tools/openapi/openapi-ts4.3-feat_2021-07-16-16-50.json @@ -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" +} \ No newline at end of file diff --git a/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.test.ts b/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.test.ts index cd2bc4a3e..3ccc3aab0 100644 --- a/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.test.ts +++ b/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.test.ts @@ -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 = { diff --git a/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.ts b/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.ts index 97a8e56a2..cdf088a95 100644 --- a/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.ts +++ b/packages/extensions/core/src/lib/plugins/semantics-validation/validators/refs-siblings-validator.ts @@ -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"; /** diff --git a/packages/extensions/core/test/end-to-end.test.ts b/packages/extensions/core/test/end-to-end.test.ts index a1ac13a46..a7808692c 100644 --- a/packages/extensions/core/test/end-to-end.test.ts +++ b/packages/extensions/core/test/end-to-end.test.ts @@ -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 = []; - - 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 = []; - - 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 = []; - - 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); - }); }); diff --git a/packages/extensions/modelerfour/src/modeler/interpretations.ts b/packages/extensions/modelerfour/src/modeler/interpretations.ts index 7f644b0be..475edc91c 100644 --- a/packages/extensions/modelerfour/src/modeler/interpretations.ts +++ b/packages/extensions/modelerfour/src/modeler/interpretations.ts @@ -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): Dictionary | 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]; } diff --git a/packages/extensions/modelerfour/src/modeler/modelerfour.ts b/packages/extensions/modelerfour/src/modeler/modelerfour.ts index 6b3ef7c8c..21e2b26d1 100644 --- a/packages/extensions/modelerfour/src/modeler/modelerfour.ts +++ b/packages/extensions/modelerfour/src/modeler/modelerfour.ts @@ -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(this.input.externalDocs as any), + externalDocs: omitXDashProperties(this.input.externalDocs as any), extensions: Interpretations.getExtensionProperties(i), }, extensions: Interpretations.getExtensionProperties(this.input), diff --git a/packages/libs/codegen/package.json b/packages/libs/codegen/package.json index 6f38f2c66..aa27a87e7 100644 --- a/packages/libs/codegen/package.json +++ b/packages/libs/codegen/package.json @@ -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" }, diff --git a/packages/libs/codegen/src/dictionary-filter.ts b/packages/libs/codegen/src/dictionary-filter.ts deleted file mode 100644 index fb15fb001..000000000 --- a/packages/libs/codegen/src/dictionary-filter.ts +++ /dev/null @@ -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(dictionary: Dictionary) { - return Object.keys(dictionary).filter((v, i, a) => v.startsWith("x-")); -} -export function excludeXDash(dictionary: Dictionary) { - return Object.keys(dictionary).filter((v, i, a) => !v.startsWith("x-")); -} diff --git a/packages/libs/codegen/src/exports.ts b/packages/libs/codegen/src/index.ts similarity index 91% rename from packages/libs/codegen/src/exports.ts rename to packages/libs/codegen/src/index.ts index 2ae58064b..099365b39 100644 --- a/packages/libs/codegen/src/exports.ts +++ b/packages/libs/codegen/src/index.ts @@ -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"; diff --git a/packages/libs/openapi/src/utils.test.ts b/packages/libs/openapi/src/utils.test.ts new file mode 100644 index 000000000..4b8bee7df --- /dev/null +++ b/packages/libs/openapi/src/utils.test.ts @@ -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(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(result).toEqual(undefined); + }); +}); diff --git a/packages/libs/openapi/src/utils.ts b/packages/libs/openapi/src/utils.ts index e71e6bc91..be0d0d2bb 100644 --- a/packages/libs/openapi/src/utils.ts +++ b/packages/libs/openapi/src/utils.ts @@ -4,54 +4,55 @@ import { Dereferenced, ExtensionKey, PathReference, Refable } from "./common"; * Only return properties starting with x- * @param dictionary */ -export const includeXDash = (dictionary: Record): ExtensionKey[] => { - return Object.keys(dictionary).filter((v, i, a) => v.startsWith("x-")) as any; -}; +export function includeXDashKeys>( + dictionary: T, +): Extract[] { + return Object.keys(dictionary).filter((v) => v.startsWith("x-")) as any; +} /** * Only return properties NOT starting with x- * @param dictionary */ -export const excludeXDash = (dictionary: T): string[] => { - return Object.keys(dictionary).filter((v, i, a) => !v.startsWith("x-")); -}; +export function omitXDashKeys(dictionary: T): Exclude[] { + return Object.keys(dictionary).filter((v) => !v.startsWith("x-")) as any; +} -export function includeXDashProperties(obj: T | undefined): T | undefined { - if (!obj) { - return undefined; +export function includeXDashProperties | undefined>( + obj: T, +): T extends undefined ? undefined : Pick> { + 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(obj: T | undefined): T | undefined { - if (!obj) { - return undefined; +export function omitXDashProperties( + obj: T, +): T extends undefined ? undefined : Pick> { + 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 = (item: Refable): item is PathReference => { +export function isReference(item: Refable): item is PathReference { return item && (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 = (item: Refable): item is PathReference => { * @param item Reference item. * @param stack Stack for circular dependencies. */ -export const dereference = (document: any, item: Refable, stack: string[] = []): Dereferenced => { +export function dereference(document: any, item: Refable, stack: string[] = []): Dereferenced { let name: string | undefined; if (isReference(item)) { @@ -86,4 +87,4 @@ export const dereference = (document: any, item: Refable, stack: string[] return { instance: node, name: name || "", fromRef: true }; } return { instance: item, name: "", fromRef: false }; -}; +} diff --git a/packages/libs/openapi/test/hello.test.ts b/packages/libs/openapi/test/hello.test.ts deleted file mode 100644 index 6edb10195..000000000 --- a/packages/libs/openapi/test/hello.test.ts +++ /dev/null @@ -1,3 +0,0 @@ -it("works", () => { - expect("hello").not.toEqual("world"); -});