Skip to content

Commit

Permalink
Fix openapi3 min max exclusive property to be a boolean (#2365)
Browse files Browse the repository at this point in the history
fix [#2230](#2230)

Emitter used value as a number which is like that in later version of
openapi (3.1+)

---------

Co-authored-by: Microsoft Auto Changeset Bot <autochangesetbot@microsoft.com>
  • Loading branch information
timotheeguerin and Microsoft Auto Changeset Bot authored Sep 6, 2023
1 parent f4a0488 commit e881658
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/openapi3",
"comment": "Fix: `exclusiveMinimum` and `exclusiveMaximum` properties are booleans in openapi3",
"type": "none"
}
],
"packageName": "@typespec/openapi3"
}
6 changes: 4 additions & 2 deletions packages/openapi3/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
42 changes: 21 additions & 21 deletions packages/openapi3/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,85 +322,85 @@ 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;

/**
* 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;

/**
* 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;

/**
* 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;

Expand All @@ -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;

Expand All @@ -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<string>;

Expand All @@ -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)[];

Expand All @@ -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<OpenAPI3Schema>[];

Expand All @@ -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<OpenAPI3Schema>[];

Expand All @@ -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<OpenAPI3Schema>[];

/**
* 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<OpenAPI3Schema>;

Expand Down
57 changes: 56 additions & 1 deletion packages/openapi3/test/primitive-types.test.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand Down Expand Up @@ -270,4 +270,59 @@ 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",
];

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);
});
}
});
});
});

0 comments on commit e881658

Please sign in to comment.