juniper
Version:
ESM JSON Schema builder for static Typescript inference.
142 lines (141 loc) • 4.32 kB
JavaScript
import { AbstractSchema } from '../lib/schema.js';
import { mergeAllOf } from '../lib/utils.js';
const gcd = (x, y)=>{
let a = x;
let b = y;
while(b){
const t = b;
b = a % b;
a = t;
}
return a;
};
const lcm = (x, y)=>x * y / gcd(x, y);
const numToExclusive = (value)=>typeof value === 'number' ? {
value,
exclusive: false
} : value;
export class NumberSchema extends AbstractSchema {
#maximum;
#minimum;
#multipleOfs;
constructor(options = {}){
super(options);
this.schemaType = options.type ?? 'number';
this.#maximum = numToExclusive(options.maximum ?? Number.POSITIVE_INFINITY);
this.#minimum = numToExclusive(options.minimum ?? Number.NEGATIVE_INFINITY);
this.#multipleOfs = [
options.multipleOf ?? []
].flat();
}
static create(options) {
return new NumberSchema(options);
}
type(type) {
return this.clone({
type
});
}
multipleOf(multipleOf) {
return this.clone({
multipleOf: [
...this.#multipleOfs,
multipleOf
]
});
}
maximum(maximum) {
return this.clone({
maximum: numToExclusive(maximum)
});
}
exclusiveMaximum(exclusiveMaximum) {
return this.maximum({
value: exclusiveMaximum,
exclusive: true
});
}
minimum(minimum) {
return this.clone({
minimum: numToExclusive(minimum)
});
}
exclusiveMinimum(exclusiveMinimum) {
return this.minimum({
value: exclusiveMinimum,
exclusive: true
});
}
getCloneParams() {
return {
...super.getCloneParams(),
maximum: this.#maximum,
minimum: this.#minimum,
multipleOf: [
...this.#multipleOfs
],
type: this.schemaType
};
}
static getDefaultValues(params) {
const superParams = super.getDefaultValues(params);
if (params.openApi30) {
return {
...superParams,
minimum: -Number.MAX_VALUE,
exclusiveMinimum: false,
maximum: Number.MAX_VALUE,
exclusiveMaximum: false
};
}
return {
...superParams,
minimum: -Number.MAX_VALUE,
exclusiveMinimum: -Number.MAX_VALUE,
maximum: Number.MAX_VALUE,
exclusiveMaximum: Number.MAX_VALUE
};
}
toSchema(params) {
const base = super.toSchema(params);
if (this.#minimum.value > Number.NEGATIVE_INFINITY) {
if (this.#minimum.exclusive) {
if (params.openApi30) {
base.minimum = this.#minimum.value;
base.exclusiveMinimum = true;
} else {
base.exclusiveMinimum = this.#minimum.value;
}
} else {
base.minimum = this.#minimum.value;
}
}
if (this.#maximum.value < Number.POSITIVE_INFINITY) {
if (this.#maximum.exclusive) {
if (params.openApi30) {
base.maximum = this.#maximum.value;
base.exclusiveMaximum = true;
} else {
base.exclusiveMaximum = this.#maximum.value;
}
} else {
base.maximum = this.#maximum.value;
}
}
const integerMultiples = this.#multipleOfs.filter((x)=>Number.isInteger(x));
const floatMultiples = this.#multipleOfs.filter((x)=>!Number.isInteger(x));
if (integerMultiples.length > 0) {
base.multipleOf = integerMultiples.reduce((acc, val)=>lcm(acc, val), 1);
mergeAllOf(base, floatMultiples.map((multipleOf)=>({
multipleOf
})));
} else if (floatMultiples.length > 0) {
[base.multipleOf] = floatMultiples;
mergeAllOf(base, floatMultiples.slice(1).map((multipleOf)=>({
multipleOf
})));
}
return base;
}
}
//# sourceMappingURL=number.js.map