Skip to content

Valibot: correctly support format: int64 #2344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 24, 2025
Merged
9 changes: 9 additions & 0 deletions packages/openapi-ts-tests/main/test/3.1.x.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,15 @@ describe(`OpenAPI ${version}`, () => {
}),
description: "validator schemas with merged unions (can't use .merge())",
},
{
config: createConfig({
input: 'integer-formats.json',
output: 'integer-formats',
plugins: ['valibot'],
}),
description:
'generates validator schemas for all integer format combinations (number/integer/string types with int8, int16, int32, int64, uint8, uint16, uint32, uint64 formats)',
},
];

it.each(scenarios)('$description', async ({ config }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import * as v from 'valibot';

export const vFoo = v.object({
bar: v.optional(v.pipe(v.number(), v.integer())),
foo: v.optional(v.bigint(), BigInt(0)),
foo: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1')), BigInt(0)),
id: v.string()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ export const vCollectionFormatData = v.object({
export const vTypesData = v.object({
body: v.optional(v.never()),
path: v.optional(v.object({
id: v.optional(v.pipe(v.number(), v.integer()))
id: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')))
})),
query: v.object({
parameterNumber: v.optional(v.number(), 123),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import * as v from 'valibot';

export const vFoo = v.object({
bar: v.optional(v.pipe(v.number(), v.integer())),
foo: v.optional(v.bigint(), BigInt(0)),
foo: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1')), BigInt(0)),
id: v.string()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,8 @@ export const vDefault = v.object({
});

export const vPageable = v.object({
page: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0)), 0),
size: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))),
page: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1'), v.minValue(0)), 0),
size: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1'), v.minValue(1))),
sort: v.optional(v.array(v.string()))
});

Expand Down Expand Up @@ -775,10 +775,10 @@ export const vCompositionWithOneOfAndProperties = v.intersect([
]),
v.object({
baz: v.union([
v.pipe(v.number(), v.integer(), v.minValue(0)),
v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint16 to be >= 0'), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 2^16-1'), v.minValue(0)),
v.null()
]),
qux: v.pipe(v.number(), v.integer(), v.minValue(0))
qux: v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint8 to be >= 0'), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 2^8-1'), v.minValue(0))
})
]);

Expand Down Expand Up @@ -943,10 +943,10 @@ export const vModelWithOneOfAndProperties = v.intersect([
]),
v.object({
baz: v.union([
v.pipe(v.number(), v.integer(), v.minValue(0)),
v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint16 to be >= 0'), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 2^16-1'), v.minValue(0)),
v.null()
]),
qux: v.pipe(v.number(), v.integer(), v.minValue(0))
qux: v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint8 to be >= 0'), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 2^8-1'), v.minValue(0))
})
]);

Expand Down Expand Up @@ -1812,7 +1812,7 @@ export const vCollectionFormatData = v.object({
export const vTypesData = v.object({
body: v.optional(v.never()),
path: v.optional(v.object({
id: v.optional(v.pipe(v.number(), v.integer()))
id: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')))
})),
query: v.object({
parameterNumber: v.optional(v.number(), 123),
Expand Down Expand Up @@ -1958,15 +1958,15 @@ export const vComplexParamsData = v.object({
vModelWithDictionary
]),
user: v.optional(v.pipe(v.object({
id: v.optional(v.pipe(v.pipe(v.number(), v.integer()), v.readonly())),
id: v.optional(v.pipe(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')), v.readonly())),
name: v.optional(v.pipe(v.union([
v.pipe(v.string(), v.readonly()),
v.null()
]), v.readonly()))
}), v.readonly()))
})),
path: v.object({
id: v.pipe(v.number(), v.integer()),
id: v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')),
'api-version': v.string()
}),
query: v.optional(v.never())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// This file is auto-generated by @hey-api/openapi-ts

import * as v from 'valibot';

export const vIntegerFormats = v.object({
numberNoFormat: v.optional(v.number()),
numberInt8: v.optional(v.pipe(v.number(), v.minValue(-128, 'Invalid value: Expected int8 to be >= -2^7'), v.maxValue(127, 'Invalid value: Expected int8 to be <= 2^7-1'))),
numberInt16: v.optional(v.pipe(v.number(), v.minValue(-32768, 'Invalid value: Expected int16 to be >= -2^15'), v.maxValue(32767, 'Invalid value: Expected int16 to be <= 2^15-1'))),
numberInt32: v.optional(v.pipe(v.number(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1'))),
numberInt64: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1'))),
numberUint8: v.optional(v.pipe(v.number(), v.minValue(0, 'Invalid value: Expected uint8 to be >= 0'), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 2^8-1'))),
numberUint16: v.optional(v.pipe(v.number(), v.minValue(0, 'Invalid value: Expected uint16 to be >= 0'), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 2^16-1'))),
numberUint32: v.optional(v.pipe(v.number(), v.minValue(0, 'Invalid value: Expected uint32 to be >= 0'), v.maxValue(4294967295, 'Invalid value: Expected uint32 to be <= 2^32-1'))),
numberUint64: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('0'), 'Invalid value: Expected uint64 to be >= 0'), v.maxValue(BigInt('18446744073709551615'), 'Invalid value: Expected uint64 to be <= 2^64-1'))),
integerNoFormat: v.optional(v.pipe(v.number(), v.integer())),
integerInt8: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-128, 'Invalid value: Expected int8 to be >= -2^7'), v.maxValue(127, 'Invalid value: Expected int8 to be <= 2^7-1'))),
integerInt16: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-32768, 'Invalid value: Expected int16 to be >= -2^15'), v.maxValue(32767, 'Invalid value: Expected int16 to be <= 2^15-1'))),
integerInt32: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1'))),
integerInt64: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1'))),
integerUint8: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint8 to be >= 0'), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 2^8-1'))),
integerUint16: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint16 to be >= 0'), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 2^16-1'))),
integerUint32: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint32 to be >= 0'), v.maxValue(4294967295, 'Invalid value: Expected uint32 to be <= 2^32-1'))),
integerUint64: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('0'), 'Invalid value: Expected uint64 to be >= 0'), v.maxValue(BigInt('18446744073709551615'), 'Invalid value: Expected uint64 to be <= 2^64-1'))),
stringInt64: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1'))),
stringUint64: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('0'), 'Invalid value: Expected uint64 to be >= 0'), v.maxValue(BigInt('18446744073709551615'), 'Invalid value: Expected uint64 to be <= 2^64-1')))
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import * as v from 'valibot';

export const vFoo = v.object({
bar: v.optional(v.pipe(v.number(), v.integer())),
foo: v.optional(v.bigint(), BigInt(0)),
foo: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1')), BigInt(0)),
id: v.string()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,8 @@ export const vDefault = v.object({
});

export const vPageable = v.object({
page: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0)), 0),
size: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))),
page: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1'), v.minValue(0)), 0),
size: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1'), v.minValue(1))),
sort: v.optional(v.array(v.string()))
});

Expand Down Expand Up @@ -766,10 +766,10 @@ export const vCompositionWithOneOfAndProperties = v.intersect([
]),
v.object({
baz: v.union([
v.pipe(v.number(), v.integer(), v.minValue(0)),
v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint16 to be >= 0'), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 2^16-1'), v.minValue(0)),
v.null()
]),
qux: v.pipe(v.number(), v.integer(), v.minValue(0))
qux: v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint8 to be >= 0'), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 2^8-1'), v.minValue(0))
})
]);

Expand Down Expand Up @@ -941,10 +941,10 @@ export const vModelWithOneOfAndProperties = v.intersect([
]),
v.object({
baz: v.union([
v.pipe(v.number(), v.integer(), v.minValue(0)),
v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint16 to be >= 0'), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 2^16-1'), v.minValue(0)),
v.null()
]),
qux: v.pipe(v.number(), v.integer(), v.minValue(0))
qux: v.pipe(v.number(), v.integer(), v.minValue(0, 'Invalid value: Expected uint8 to be >= 0'), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 2^8-1'), v.minValue(0))
})
]);

Expand Down Expand Up @@ -1817,7 +1817,7 @@ export const vCollectionFormatData = v.object({
export const vTypesData = v.object({
body: v.optional(v.never()),
path: v.optional(v.object({
id: v.optional(v.pipe(v.number(), v.integer()))
id: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')))
})),
query: v.object({
parameterNumber: v.optional(v.number(), 123),
Expand Down Expand Up @@ -1964,15 +1964,15 @@ export const vComplexParamsData = v.object({
vModelWithDictionary
]),
user: v.optional(v.pipe(v.object({
id: v.optional(v.pipe(v.pipe(v.number(), v.integer()), v.readonly())),
id: v.optional(v.pipe(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')), v.readonly())),
name: v.optional(v.pipe(v.union([
v.pipe(v.string(), v.readonly()),
v.null()
]), v.readonly()))
}), v.readonly()))
})),
path: v.object({
id: v.pipe(v.number(), v.integer()),
id: v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2^31'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2^31-1')),
'api-version': v.string()
}),
query: v.optional(v.never())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ export type Foo = {
[key: string]: unknown;
};
garply?: 10n;
numberInt8?: 100;
numberInt16?: 1000;
numberInt32?: 100000;
numberInt64?: 1000000000000;
numberUint8?: 200;
numberUint16?: 50000;
numberUint32?: 3000000000;
numberUint64?: 18000000000000000000;
integerInt8?: -100;
integerInt16?: -1000;
integerInt32?: -100000;
integerInt64?: -1000000000000;
integerUint8?: 255;
integerUint16?: 65535;
integerUint32?: 4294967295;
integerUint64?: 18446744073709551615n;
stringInt64?: '-9223372036854775808';
stringUint64?: '18446744073709551615';
};

export type ClientOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,23 @@ export const vFoo = v.object({
v.literal(true)
])),
corge: v.optional(v.object({})),
garply: v.optional(v.bigint())
garply: v.optional(v.literal(BigInt('10'))),
numberInt8: v.optional(v.literal(100)),
numberInt16: v.optional(v.literal(1000)),
numberInt32: v.optional(v.literal(100000)),
numberInt64: v.optional(v.literal(BigInt('1000000000000'))),
numberUint8: v.optional(v.literal(200)),
numberUint16: v.optional(v.literal(50000)),
numberUint32: v.optional(v.literal(3000000000)),
numberUint64: v.optional(v.literal(BigInt('18000000000000000000'))),
integerInt8: v.optional(v.literal(-100)),
integerInt16: v.optional(v.literal(-1000)),
integerInt32: v.optional(v.literal(-100000)),
integerInt64: v.optional(v.literal(BigInt('-1000000000000'))),
integerUint8: v.optional(v.literal(255)),
integerUint16: v.optional(v.literal(65535)),
integerUint32: v.optional(v.literal(4294967295)),
integerUint64: v.optional(v.literal(BigInt('18446744073709551615'))),
stringInt64: v.optional(v.literal(BigInt('-9223372036854775808'))),
stringUint64: v.optional(v.literal(BigInt('18446744073709551615')))
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
import * as v from 'valibot';

export const vFoo = v.object({
foo: v.optional(v.pipe(v.bigint(), v.minValue(BigInt(0)), v.maxValue(BigInt(100))))
foo: v.optional(v.pipe(v.union([
v.number(),
v.string(),
v.bigint()
]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -2^63'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 2^63-1'), v.minValue(BigInt(0)), v.maxValue(BigInt(100))))
});
Loading
Loading