From b87ac527916e3dada7229ed3e1c9a80838b5b185 Mon Sep 17 00:00:00 2001 From: Microsoft Auto Changeset Bot Date: Tue, 5 Sep 2023 13:03:51 -0700 Subject: [PATCH 1/4] Fix openapi3 min max exclusive --- packages/openapi3/src/openapi.ts | 6 +- packages/openapi3/src/types.ts | 42 +++++------ .../openapi3/test/primitive-types.test.ts | 75 ++++++++++++++++++- 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/packages/openapi3/src/openapi.ts b/packages/openapi3/src/openapi.ts index c999adf561b..df8f5f5ee17 100644 --- a/packages/openapi3/src/openapi.ts +++ b/packages/openapi3/src/openapi.ts @@ -1713,7 +1713,8 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt const minValueExclusive = getMinValueExclusive(program, typespecType); if (isNumeric && minValueExclusive !== undefined) { - newTarget.exclusiveMinimum = minValueExclusive; + newTarget.minimum = minValueExclusive; + newTarget.exclusiveMinimum = true; } const maxValue = getMaxValue(program, typespecType); @@ -1723,7 +1724,8 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt const maxValueExclusive = getMaxValueExclusive(program, typespecType); if (isNumeric && maxValueExclusive !== undefined) { - newTarget.exclusiveMaximum = maxValueExclusive; + newTarget.maximum = maxValueExclusive; + newTarget.exclusiveMaximum = true; } const minItems = getMinItems(program, typespecType); diff --git a/packages/openapi3/src/types.ts b/packages/openapi3/src/types.ts index 591c2996929..1584e5a0777 100644 --- a/packages/openapi3/src/types.ts +++ b/packages/openapi3/src/types.ts @@ -322,42 +322,42 @@ export type OpenAPI3Schema = Extensions & { /** * Must be strictly greater than 0. * A numeric instance is valid only if division by this keyword's value results in an integer. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.1 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.1 */ multipleOf?: number; /** * Representing an inclusive upper limit for a numeric instance. * This keyword validates only if the instance is less than or exactly equal to "maximum". - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.2 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.2 */ maximum?: number; /** * Representing an exclusive upper limit for a numeric instance. * This keyword validates only if the instance is strictly less than (not equal to) to "exclusiveMaximum". - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.3 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.3 */ - exclusiveMaximum?: number; + exclusiveMaximum?: boolean; /** * Representing an inclusive lower limit for a numeric instance. * This keyword validates only if the instance is greater than or exactly equal to "minimum". - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.4 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.4 */ minimum?: number; /** * Representing an exclusive lower limit for a numeric instance. * This keyword validates only if the instance is strictly greater than (not equal to) to "exclusiveMinimum". - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.5 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.5 */ - exclusiveMinimum?: number; + exclusiveMinimum?: boolean; /** * Must be a non-negative integer. * A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.6 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.6 */ maxLength?: number; @@ -365,19 +365,19 @@ export type OpenAPI3Schema = Extensions & { * Must be a non-negative integer. * A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword. * Omitting this keyword has the same behavior as a value of 0. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.7 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.7 */ minLength?: number; /** * Should be a valid regular expression, according to the ECMA 262 regular expression dialect. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.8 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.8 */ pattern?: string; /** * Must be a non-negative integer. * An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.11 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.11 */ maxItems?: number; @@ -385,7 +385,7 @@ export type OpenAPI3Schema = Extensions & { * Must be a non-negative integer. * An array instance is valid against "maxItems" if its size is greater than, or equal to, the value of this keyword. * Omitting this keyword has the same behavior as a value of 0. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.12 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.12 */ minItems?: number; @@ -393,14 +393,14 @@ export type OpenAPI3Schema = Extensions & { * If this keyword has boolean value false, the instance validates successfully. * If it has boolean value true, the instance validates successfully if all of its elements are unique. * Omitting this keyword has the same behavior as a value of false. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.13 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.13 */ uniqueItems?: boolean; /** * Must be a non-negative integer. * An object instance is valid against "maxProperties" if its number of properties is less than, or equal to, the value of this keyword. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.15 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.15 */ maxProperties?: number; @@ -409,7 +409,7 @@ export type OpenAPI3Schema = Extensions & { * An object instance is valid against "maxProperties" if its number of properties is greater than, * or equal to, the value of this keyword. * Omitting this keyword has the same behavior as a value of 0. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.16 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.16 */ minProperties?: number; @@ -418,7 +418,7 @@ export type OpenAPI3Schema = Extensions & { * An object instance is valid against this keyword if every item in the array is the name of a property in the instance. * Omitting this keyword has the same behavior as an empty array. * - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.17 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.17 */ required?: Array; @@ -429,7 +429,7 @@ export type OpenAPI3Schema = Extensions & { * this attribute is defined, the instance value MUST be one of the * values in the array in order for the schema to be valid. * - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.23 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.23 */ enum?: (string | number | boolean)[]; @@ -447,7 +447,7 @@ export type OpenAPI3Schema = Extensions & { * * An instance validates successfully against this keyword if it validates successfully against all schemas defined by this keyword's value. * - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.26 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.26 */ allOf?: Refable[]; @@ -456,7 +456,7 @@ export type OpenAPI3Schema = Extensions & { * * An instance validates successfully against this keyword if it validates successfully against at least one schema defined by this keyword's value. * - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.27 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.27 */ anyOf?: Refable[]; @@ -465,13 +465,13 @@ export type OpenAPI3Schema = Extensions & { * * An instance validates successfully against this keyword if it validates successfully against exactly one schema defined by this keyword's value. * - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.28 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.28 */ oneOf?: Refable[]; /** * An instance is valid against this keyword if it fails to validate successfully against the schema defined by this keyword. - * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.29 + * @see https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.29 */ not?: Refable; diff --git a/packages/openapi3/test/primitive-types.test.ts b/packages/openapi3/test/primitive-types.test.ts index 8c86f112470..670acdc0aa3 100644 --- a/packages/openapi3/test/primitive-types.test.ts +++ b/packages/openapi3/test/primitive-types.test.ts @@ -1,4 +1,4 @@ -import { deepStrictEqual, ok } from "assert"; +import { deepStrictEqual, ok, strictEqual } from "assert"; import { OpenAPI3Schema } from "../src/types.js"; import { oapiForModel } from "./test-host.js"; @@ -270,4 +270,77 @@ describe("openapi3: primitives", () => { testEncode("bytes", { type: "string", format: "base64url" }, "base64url")); }); }); + + describe("constraints", () => { + const scalarNumberTypes = [ + "int8", + "int16", + "int32", + "uint8", + "uint16", + "uint32", + "integer", + "float32", + "float64", + "numeric", + "float", + "safeint", + ]; + + it("@min/maxValueExclusive wins over @min/maxValue", async () => { + const schemas = await oapiForModel( + "Test", + ` + @minValueExclusive(1) + @minValueExclusive(2) + @maxValueExclusive(3) + @maxValue(4) + scalar Test extends int32; + ` + ); + + strictEqual(schemas.schemas.Test.minimum, 2); + strictEqual(schemas.schemas.Test.exclusiveMaximum, true); + strictEqual(schemas.schemas.Test.maximum, 3); + strictEqual(schemas.schemas.Test.exclusiveMaximum, true); + }); + + describe("@minValue/@maxValue", () => { + for (const numType of scalarNumberTypes) { + it(numType, async () => { + const schemas = await oapiForModel( + "Test", + ` + @minValue(1) + @maxValue(2) + scalar Test extends ${numType}; + ` + ); + + strictEqual(schemas.schemas.Test.minimum, 1); + strictEqual(schemas.schemas.Test.maximum, 2); + }); + } + }); + + describe("@minValueExclusive/@maxValueExclusive", () => { + for (const numType of scalarNumberTypes) { + it(numType, async () => { + const schemas = await oapiForModel( + "Test", + ` + @minValueExclusive(1) + @maxValueExclusive(2) + scalar Test extends ${numType}; + ` + ); + + strictEqual(schemas.schemas.Test.minimum, 1); + strictEqual(schemas.schemas.Test.exclusiveMaximum, true); + strictEqual(schemas.schemas.Test.maximum, 2); + strictEqual(schemas.schemas.Test.exclusiveMaximum, true); + }); + } + }); + }); }); From b393d28e3c2db13c17f61c4b2cab8329ff3c51b8 Mon Sep 17 00:00:00 2001 From: Microsoft Auto Changeset Bot Date: Tue, 5 Sep 2023 13:05:10 -0700 Subject: [PATCH 2/4] Changelog --- .../fix-exclusive-min-max_2023-09-05-20-05.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json diff --git a/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json b/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json new file mode 100644 index 00000000000..d5d5a5c8597 --- /dev/null +++ b/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@typespec/openapi3", + "comment": "Fix: `exclusiveMinimum` and `exclusiveMaxiumum` properties are booleans in openapi3", + "type": "none" + } + ], + "packageName": "@typespec/openapi3" +} \ No newline at end of file From ad20a2920e3f89d6993f7d100e76b44fcd33d597 Mon Sep 17 00:00:00 2001 From: Microsoft Auto Changeset Bot Date: Wed, 6 Sep 2023 10:41:27 -0700 Subject: [PATCH 3/4] Remove test as it is invalid --- packages/openapi3/test/primitive-types.test.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/openapi3/test/primitive-types.test.ts b/packages/openapi3/test/primitive-types.test.ts index 670acdc0aa3..b0fb2b737ca 100644 --- a/packages/openapi3/test/primitive-types.test.ts +++ b/packages/openapi3/test/primitive-types.test.ts @@ -287,24 +287,6 @@ describe("openapi3: primitives", () => { "safeint", ]; - it("@min/maxValueExclusive wins over @min/maxValue", async () => { - const schemas = await oapiForModel( - "Test", - ` - @minValueExclusive(1) - @minValueExclusive(2) - @maxValueExclusive(3) - @maxValue(4) - scalar Test extends int32; - ` - ); - - strictEqual(schemas.schemas.Test.minimum, 2); - strictEqual(schemas.schemas.Test.exclusiveMaximum, true); - strictEqual(schemas.schemas.Test.maximum, 3); - strictEqual(schemas.schemas.Test.exclusiveMaximum, true); - }); - describe("@minValue/@maxValue", () => { for (const numType of scalarNumberTypes) { it(numType, async () => { From c18a7c00adfbd4332ea0d3a3472e121e9e7bebb3 Mon Sep 17 00:00:00 2001 From: Microsoft Auto Changeset Bot Date: Wed, 6 Sep 2023 11:20:23 -0700 Subject: [PATCH 4/4] . --- .../openapi3/fix-exclusive-min-max_2023-09-05-20-05.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json b/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json index d5d5a5c8597..270765f8daf 100644 --- a/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json +++ b/common/changes/@typespec/openapi3/fix-exclusive-min-max_2023-09-05-20-05.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@typespec/openapi3", - "comment": "Fix: `exclusiveMinimum` and `exclusiveMaxiumum` properties are booleans in openapi3", + "comment": "Fix: `exclusiveMinimum` and `exclusiveMaximum` properties are booleans in openapi3", "type": "none" } ], "packageName": "@typespec/openapi3" -} \ No newline at end of file +}