fork of hey-api/openapi-ts because I need some additional things

Compare changes

Choose any two refs to compare.

Changed files
+7806 -4416
.changeset
dev
docs
.vitepress
config
theme
components
openapi-ts
partials
packages
codegen-core
src
symbols
openapi-ts
openapi-ts-tests
__snapshots__
main
test
__snapshots__
2.0.x
plugins
@hey-api
transformers
type-format-valibot
type-format-zod
valibot
default
3.0.x
plugins
@hey-api
transformers
type-format-valibot
type-format-zod
valibot
default
3.1.x
integer-formats
plugins
@hey-api
transformers
type-format-valibot
type-format-zod
valibot
default
validators-bigint-min-max
webhooks
plugins
@tanstack
valibot
spec
numberTypeToValibotSchema
objectAdditionalProperties
test
zod
v3
__snapshots__
2.0.x
mini
default
type-format-zod
v3
default
type-format-zod
v4
default
type-format-zod
3.0.x
mini
default
type-format-zod
v3
default
type-format-zod
v4
default
type-format-zod
3.1.x
mini
default
schema-const
type-format-zod
v3
default
schema-const
type-format-zod
v4
default
schema-const
type-format-zod
v4
__snapshots__
2.0.x
mini
default
type-format-zod
v3
default
type-format-zod
v4
default
type-format-zod
3.0.x
mini
default
type-format-zod
v3
default
type-format-zod
v4
default
type-format-zod
3.1.x
mini
default
schema-const
type-format-zod
v3
default
schema-const
type-format-zod
v4
default
schema-const
type-format-zod
specs
+5
.changeset/curly-geckos-play.md
··· 1 + --- 2 + '@hey-api/codegen-core': patch 3 + --- 4 + 5 + **types**: document default values for `importKind` and `kind`
+7
.changeset/fruity-camels-type.md
··· 1 + --- 2 + '@hey-api/openapi-ts': minor 3 + --- 4 + 5 + **plugin(valibot)**: **BREAKING:** standardize `~resolvers` API 6 + 7 + The [Resolvers API](https://heyapi.dev/openapi-ts/plugins/concepts/resolvers) has been simplified and expanded to provide a more consistent behavior across plugins. You can view a few common examples on the [Resolvers](https://heyapi.dev/openapi-ts/plugins/concepts/resolvers) page.
+5
.changeset/fuzzy-taxes-cheer.md
··· 1 + --- 2 + '@hey-api/openapi-ts': patch 3 + --- 4 + 5 + **plugin(zod)**: expand support for bigint types
+7
.changeset/upset-weeks-dream.md
··· 1 + --- 2 + '@hey-api/openapi-ts': minor 3 + --- 4 + 5 + **plugin(zod)**: **BREAKING:** standardize `~resolvers` API 6 + 7 + The [Resolvers API](https://heyapi.dev/openapi-ts/plugins/concepts/resolvers) has been simplified and expanded to provide a more consistent behavior across plugins. You can view a few common examples on the [Resolvers](https://heyapi.dev/openapi-ts/plugins/concepts/resolvers) page.
+91 -46
dev/openapi-ts.config.ts
··· 38 38 // }, 39 39 path: path.resolve( 40 40 getSpecsPath(), 41 - '3.0.x', 42 - // '3.1.x', 41 + // '3.0.x', 42 + '3.1.x', 43 43 // 'circular.yaml', 44 44 // 'dutchie.json', 45 45 // 'enum-names-values.yaml', 46 46 // 'full.yaml', 47 - // 'integer-formats.yaml', 47 + 'integer-formats.yaml', 48 48 // 'invalid', 49 49 // 'object-property-names.yaml', 50 50 // 'openai.yaml', ··· 52 52 // 'pagination-ref.yaml', 53 53 // 'schema-const.yaml', 54 54 // 'sdk-instance.yaml', 55 - 'sdk-method-class-conflict.yaml', 55 + // 'sdk-method-class-conflict.yaml', 56 56 // 'sdk-nested-classes.yaml', 57 57 // 'sdk-nested-conflict.yaml', 58 58 // 'string-with-format.yaml', ··· 397 397 definitions: 'z{{name}}', 398 398 exportFromIndex: true, 399 399 // metadata: true, 400 - // name: 'valibot', 400 + name: 'valibot', 401 401 // requests: { 402 402 // case: 'PascalCase', 403 403 // name: '{{name}}Data', ··· 431 431 }, 432 432 }, 433 433 '~resolvers': { 434 - object: { 435 - // base({ $, additional, pipes, shape }) { 436 - // if (additional === undefined) { 437 - // return pipes.push($('v').attr('looseObject').call(shape)); 438 - // } 439 - // return; 440 - // }, 434 + // number(ctx) { 435 + // const { $, plugin, symbols } = ctx; 436 + // const { v } = symbols; 437 + // // ctx.nodes.base = () => { 438 + // // // implement custom base number resolver 439 + // // } 440 + // const big = plugin.symbolOnce('Big', { 441 + // external: 'big.js', 442 + // importKind: 'default', 443 + // }); 444 + // return $(v).attr('instance').call(big); 445 + // }, 446 + object(ctx) { 447 + const { $, symbols } = ctx; 448 + const { v } = symbols; 449 + const additional = ctx.nodes.additionalProperties(ctx); 450 + if (additional === undefined) { 451 + const shape = ctx.nodes.shape(ctx); 452 + ctx.nodes.base = () => $(v).attr('looseObject').call(shape); 453 + } 441 454 }, 442 - string: { 443 - formats: { 444 - // date: ({ $, pipes }) => pipes.push($('v').attr('isoDateTime').call()), 445 - // 'date-time': ({ $, pipes }) => pipes.push($('v').attr('isoDateTime').call()), 446 - }, 447 - }, 448 - // validator({ $, plugin, schema, v }) { 455 + // string(ctx) { 456 + // const { $, schema, symbols } = ctx; 457 + // const { v } = symbols; 458 + // if (schema.format === 'date' || schema.format === 'date-time') { 459 + // ctx.nodes.format = () => $(v).attr('isoDateTime').call(); 460 + // } 461 + // }, 462 + // validator(ctx) { 463 + // const { $, plugin, symbols } = ctx; 464 + // const { schema, v } = symbols; 449 465 // const vShadow = plugin.symbol('v'); 450 466 // const test = plugin.symbol('test'); 451 467 // const e = plugin.symbol('err'); ··· 467 483 { 468 484 // case: 'snake_case', 469 485 // comments: false, 470 - compatibilityVersion: 4, 486 + compatibilityVersion: 'mini', 471 487 dates: { 472 488 // local: true, 473 489 // offset: true, ··· 516 532 }, 517 533 }, 518 534 '~resolvers': { 519 - object: { 520 - // base({ $, additional, shape }) { 521 - // if (!additional) { 522 - // // return $('z').attr('object').call(shape).attr('passthrough').call() 523 - // return $('z').attr('object').call(shape).attr('strict').call(); 524 - // } 525 - // return; 526 - // }, 527 - }, 528 - string: { 529 - formats: { 530 - // date: ({ $ }) => $('z').attr('date').call(), 531 - // 'date-time': ({ $ }) => $('z').attr('date').call(), 532 - // int64: ({ $ }) => $('z').attr('string').call().attr('refine').call( 533 - // $.func().param('val').do( 534 - // $.try( 535 - // $('z').attr('int64').call().attr('parse').call($('BigInt').call('val')), 536 - // $.return($.literal(true)) 537 - // ).catch( 538 - // $.return($.literal(false)) 539 - // ), 540 - // ), 541 - // $.object().prop('message', $.literal('Must be a valid int64 string')) 542 - // ), 543 - }, 544 - }, 535 + // number(ctx) { 536 + // const { $, plugin, symbols } = ctx; 537 + // const { z } = symbols; 538 + // // ctx.nodes.base = () => { 539 + // // // implement custom base number resolver 540 + // // } 541 + // const big = plugin.symbolOnce('Big', { 542 + // external: 'big.js', 543 + // importKind: 'default', 544 + // }); 545 + // return $(z).attr('instanceof').call(big); 546 + // }, 547 + // object(ctx) { 548 + // const { $, symbols } = ctx; 549 + // const { z } = symbols; 550 + // const additional = ctx.nodes.additionalProperties(ctx); 551 + // if (additional === undefined) { 552 + // const shape = ctx.nodes.shape(ctx); 553 + // // return $('z').attr('object').call(shape).attr('passthrough').call() 554 + // ctx.nodes.base = () => 555 + // $(z).attr('object').call(shape).attr('strict').call(); 556 + // } 557 + // }, 558 + // string(ctx) { 559 + // const { $, schema, symbols } = ctx; 560 + // const { z } = symbols; 561 + // if (schema.format === 'date' || schema.format === 'date-time') { 562 + // ctx.nodes.format = () => $(z).attr('date').call(); 563 + // } 564 + // if (schema.format === 'int64') { 565 + // ctx.nodes.format = () => 566 + // $(z) 567 + // .attr('string') 568 + // .call() 569 + // .attr('refine') 570 + // .call( 571 + // $.func() 572 + // .param('val') 573 + // .do( 574 + // $.try( 575 + // $(z) 576 + // .attr('int64') 577 + // .call() 578 + // .attr('parse') 579 + // .call($('BigInt').call('val')), 580 + // $.return($.literal(true)), 581 + // ).catch($.return($.literal(false))), 582 + // ), 583 + // $.object().prop( 584 + // 'message', 585 + // $.literal('Must be a valid int64 string'), 586 + // ), 587 + // ); 588 + // } 589 + // }, 545 590 // validator({ $, schema }) { 546 591 // return [ 547 592 // $.const('parsed').assign(
+1 -1
dev/package.json
··· 18 18 "@tanstack/solid-query": "5.73.3", 19 19 "@tanstack/svelte-query": "5.73.3", 20 20 "@tanstack/vue-query": "5.73.3", 21 - "arktype": "2.1.28", 21 + "arktype": "2.1.29", 22 22 "swr": "2.3.8", 23 23 "typescript": "5.9.3", 24 24 "valibot": "1.2.0",
+11 -1
docs/.vitepress/config/en.ts
··· 2 2 3 3 export default defineConfig({ 4 4 description: 5 - '๐ŸŒ€ OpenAPI to TypeScript code generator. Generate API clients, SDKs, validators, and more.', 5 + '๐ŸŒ€ OpenAPI to TypeScript codegen. Production-ready SDKs, Zod schemas, TanStack Query hooks, and 20+ plugins. Used by Vercel, OpenCode, and PayPal.', 6 6 lang: 'en-US', 7 7 themeConfig: { 8 8 editLink: { ··· 254 254 ], 255 255 link: '/openapi-ts/web-frameworks', 256 256 text: 'Web Frameworks', 257 + }, 258 + { 259 + collapsed: true, 260 + items: [ 261 + { 262 + link: '/openapi-ts/plugins/concepts/resolvers', 263 + text: 'Resolvers', 264 + }, 265 + ], 266 + text: 'Concepts', 257 267 }, 258 268 { 259 269 collapsed: true,
+1 -1
docs/.vitepress/config/shared.ts
··· 98 98 { 99 99 content: 100 100 pageData.frontmatter.description || 101 - '๐ŸŒ€ OpenAPI to TypeScript code generator. Generate API clients, SDKs, validators, and more.', 101 + '๐ŸŒ€ OpenAPI to TypeScript codegen. Production-ready SDKs, Zod schemas, TanStack Query hooks, and 20+ plugins. Used by Vercel, OpenCode, and PayPal.', 102 102 property: 'og:description', 103 103 }, 104 104 ],
+2 -2
docs/.vitepress/theme/components/Layout.vue
··· 8 8 <Layout> 9 9 <template #layout-top> 10 10 <div class="announcement"> 11 - <span>Build better APIs with Hey API Platform</span> 11 + <span>Host your specs. Generate from anywhere.</span> 12 12 <a 13 13 href="https://app.heyapi.dev/" 14 14 rel="noopener noreferrer" 15 15 target="_blank" 16 - >Dashboard</a 16 + >Get started</a 17 17 > 18 18 </div> 19 19 </template>
+4
docs/.vitepress/theme/custom.css
··· 401 401 } 402 402 403 403 @media (min-width: 640px) { 404 + h1.heading .name { 405 + max-width: 600px; 406 + } 407 + 404 408 .VPFeatures.VPHomeFeatures > .container > .items { 405 409 gap: 1rem; 406 410 padding: 0.4rem 0;
+13 -13
docs/index.md
··· 2 2 layout: home 3 3 4 4 hero: 5 - name: One OpenAPI spec.<br/>Infinite outputs. 6 - tagline: Code generator for TypeScript projects. Trusted by companies like Google, Amazon, and PayPal to generate API clients, SDKs, validators, and more. 5 + name: OpenAPI to TypeScript in seconds. 6 + tagline: Generate production-ready SDKs and validators from your OpenAPI spec. Used by Vercel, OpenCode, and PayPal. 7 7 actions: 8 8 - link: /openapi-ts/get-started 9 9 text: Get Started ··· 20 20 21 21 features: 22 22 - icon: <svg class="icon-openapi" width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 32"><path d="M8.96 18.397H.515l.005.123.014.238.007.102.022.275.006.061.033.304.003.03.043.327c.098.677.243 1.343.437 1.999l.003.008.1.326.006.018.093.276.025.07.087.24.04.107.078.2.06.149.065.154.086.188.05.114.105.225.035.072.126.256.02.039.154.293.033.057 7.235-4.366a5.754 5.754 0 0 1-.528-1.885ZM.914 22.27l.002.007.273-.085-.275.078ZM11.034 22.275l-5.97 5.967.092.085.255.227.203.172.055.045.232.187.03.024.255.196a.066.066 0 0 1 .01.007l1.113.752.04.024.219.13.134.076.128.072.232.126.032.017.658.32 3.213-7.805a5.719 5.719 0 0 1-.934-.623l.003.001ZM10.415 21.683l-.186-.219-.154-.199-.165-.233-.154-.241-7.22 4.349.371.584.03.044.002.003.388.547.009.011.008.011.176.229.21.261.045.055.173.203.076.087.15.171.084.092.039.042.114.12.046.047.2.204 5.956-5.956-.195-.209-.003-.003ZM18.31 22.272l-.2.154.016.025 4.342 7.209.594-.41c.42-.31.827-.645 1.22-1.007l-5.949-5.947-.023-.024ZM21.92 30.003l.01-.006-.01.006Zm-.005.003ZM21.929 29.994l.057-.028-.001-.002-.056.033v-.003Zm-.01.009-.002.001.002-.001ZM21.916 30.006l-.011-.018.01.018Zm.004-.003.01-.005-.01.005Z" fill="#fff"></path><path d="m21.837 29.719-4.2-6.97-.25.139-.256.128a5.756 5.756 0 0 1-4.106.319l-.27-.095-.27-.095-3.207 7.788.024.009.024.009.007.003.615.235a14.262 14.262 0 0 0 3.007.708l.349.038.056.005.28.023.095.006.245.014.15.006.195.007.348.004c.788 0 1.575-.066 2.352-.196l.04-.006.246-.045.143-.027.145-.03.24-.053.044-.01a14.241 14.241 0 0 0 3.398-1.267l.209-.115.424-.238-.007-.02.01.018.014-.008.056-.034-.15-.25Zm-10.8-16.335.2-.155-.015-.024-4.343-7.206-.595.41c-.42.31-.827.645-1.218 1.006l5.948 5.945.024.024ZM4.654 7.808l-.395.413c-.44.476-.841.971-1.203 1.491l-.052.075-.121.178-.123.188-.045.068a14.135 14.135 0 0 0-2.2 7.035l-.007.286-.005.285h8.424l.013-.285.016-.286a5.716 5.716 0 0 1 1.27-3.068c.058-.073.128-.142.192-.212.065-.07.124-.144.192-.212L4.654 7.808Zm17.38-2.09L22 5.695l-.224-.132-.13-.075-.132-.073-.228-.123-.036-.019a14.74 14.74 0 0 0-1.52-.686l-.04-.015-.342-.124a14.216 14.216 0 0 0-2.839-.673l-.118-.016-.119-.013-.228-.025-.064-.006-.273-.023-.342-.02-.124-.006v8.444c.433.045.862.138 1.279.279l6.216-6.211a13.96 13.96 0 0 0-.703-.461h.002ZM7.363 5.692l.147.244-.147-.244Zm0 0L7.36 5.69l.004.002Z" fill="#fff"></path><path d="m14.388 3.664-.285.005a14.24 14.24 0 0 0-1.78.184l-.04.007-.247.044-.143.027-.145.03-.24.053-.043.01a14.252 14.252 0 0 0-3.4 1.268l-.705.398v.001l4.349 7.219.25-.14a5.727 5.727 0 0 1 2.141-.657l.285-.022s.19-.01.286-.01V3.658c-.095 0-.19.003-.285.005h.002ZM28.827 17.131l-.014-.227-.007-.113-.022-.267-.006-.07-.032-.297-.002-.024-.002-.012-.043-.32-.001-.01a14.164 14.164 0 0 0-.436-1.992l-.003-.013-.094-.304-.013-.04-.091-.272-.026-.074-.086-.235-.043-.111-.075-.194-.063-.153-.063-.15-.083-.191-.049-.108-.107-.228-.033-.069-.128-.259-.018-.035-.149-.286c-.002-.003-.003-.007-.006-.01a14.217 14.217 0 0 0-.806-1.308l-6.217 6.218c.14.415.233.844.278 1.279h8.444l-.004-.125ZM20.42 17.828l-.013.285-.016.286a5.709 5.709 0 0 1-1.27 3.068c-.057.073-.128.142-.192.212s-.123.144-.191.212l5.956 5.956c.067-.068.13-.138.197-.206l.197-.207c.44-.477.843-.977 1.206-1.496l.043-.06.13-.193.113-.173.057-.084a14.13 14.13 0 0 0 2.196-7.03l.007-.285.005-.286H20.42Z" fill="#fff"></path></svg> 23 - title: OpenAPI Schema 24 - details: You provide OpenAPI schema. We take care of the rest. OpenAPI 2.0, 3.0, and 3.1 supported. 23 + title: OpenAPI to TypeScript 24 + details: Generate production-ready TypeScript from any OpenAPI specification. 25 25 link: /openapi-ts/get-started 26 26 linkText: Get started 27 27 - icon: <svg fill="none" height="24" viewBox="0 0 128 128" width="24" xmlns="http://www.w3.org/2000/svg"><rect fill="#3178c6" height="128" rx="6" width="128"/><path clip-rule="evenodd" d="m74.2622 99.468v14.026c2.2724 1.168 4.9598 2.045 8.0625 2.629 3.1027.585 6.3728.877 9.8105.877 3.3503 0 6.533-.321 9.5478-.964 3.016-.643 5.659-1.702 7.932-3.178 2.272-1.476 4.071-3.404 5.397-5.786 1.325-2.381 1.988-5.325 1.988-8.8313 0-2.5421-.379-4.7701-1.136-6.6841-.758-1.9139-1.85-3.6159-3.278-5.1062-1.427-1.4902-3.139-2.827-5.134-4.0104-1.996-1.1834-4.246-2.3011-6.752-3.353-1.8352-.7597-3.4812-1.4975-4.9378-2.2134-1.4567-.7159-2.6948-1.4464-3.7144-2.1915-1.0197-.7452-1.8063-1.5341-2.3598-2.3669-.5535-.8327-.8303-1.7751-.8303-2.827 0-.9643.2476-1.8336.7429-2.6079s1.1945-1.4391 2.0976-1.9943c.9031-.5551 2.0101-.9861 3.3211-1.2929 1.311-.3069 2.7676-.4603 4.3699-.4603 1.1658 0 2.3958.0877 3.6928.263 1.296.1753 2.6.4456 3.911.8109 1.311.3652 2.585.8254 3.824 1.3806 1.238.5552 2.381 1.198 3.43 1.9285v-13.1051c-2.127-.8182-4.45-1.4245-6.97-1.819s-5.411-.5917-8.6744-.5917c-3.3211 0-6.4674.3579-9.439 1.0738-2.9715.7159-5.5862 1.8336-7.844 3.353-2.2578 1.5195-4.0422 3.4553-5.3531 5.8075-1.311 2.3522-1.9665 5.1646-1.9665 8.4373 0 4.1785 1.2017 7.7433 3.6052 10.6945 2.4035 2.9513 6.0523 5.4496 10.9466 7.495 1.9228.7889 3.7145 1.5633 5.375 2.323 1.6606.7597 3.0954 1.5486 4.3044 2.3668s2.1628 1.7094 2.8618 2.6736c.7.9643 1.049 2.06 1.049 3.2873 0 .9062-.218 1.7462-.655 2.5202s-1.1 1.446-1.9885 2.016c-.8886.57-1.9956 1.016-3.3212 1.337-1.3255.321-2.8768.482-4.6539.482-3.0299 0-6.0305-.533-9.0021-1.6-2.9715-1.066-5.7245-2.666-8.2591-4.799zm-23.5596-34.9136h18.2974v-11.5544h-51v11.5544h18.2079v51.4456h14.4947z" fill="#fff" fill-rule="evenodd"/></svg> 28 - title: Types and SDKs 29 - details: Highly customizable output with sensible defaults. No manual maintenance required. 28 + title: Instant SDKs 29 + details: Highly customizable SDKs and types with sensible defaults that compile out of the box. 30 30 link: /openapi-ts/output 31 31 linkText: See output 32 32 - icon: <svg class="icon-json-schema xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.423 70.423" height="24" width="24"><g fill="#fff"><path d="M122.994 114.19c-4.329-.94-7.58-3.479-8.712-6.801-.79-2.316-.677-6.072.333-11.15.485-2.439.882-5.349.882-6.467-.001-3.718-1.712-5.736-5.1-6.017l-1.955-.162v-4.785l1.852-.251c2.702-.366 3.744-1.029 4.576-2.91.611-1.38.689-2.068.505-4.472-.119-1.562-.535-4.349-.924-6.192-.99-4.683-.949-8.485.117-10.773 1.568-3.369 5.437-5.855 9.932-6.383l1.933-.227v5.036h-1.3c-1.771 0-4.25 1.262-4.883 2.488-.608 1.176-.654 2.864-.158 5.802.783 4.644 1.047 9.099.676 11.422-.425 2.658-1.975 5.796-3.68 7.448l-1.18 1.144 1.615 1.983c1.99 2.443 2.765 4.148 3.243 7.142.378 2.369.085 7.283-.67 11.214-1.054 5.485.162 7.652 4.661 8.306l1.676.244v2.448c0 2.792.171 2.697-3.439 1.913z" style="stroke-width:.35277775" transform="translate(-104.228 -45.508)"/><path d="M152.23 112.25v-2.43l2.05-.424c2.263-.467 4.054-1.863 4.459-3.475.127-.507-.113-3.164-.534-5.903-1.372-8.93-.611-13.537 2.855-17.297l1.482-1.608-1.11-1.266c-3.98-4.53-4.67-8.552-3.154-18.37.763-4.945.764-4.993.087-6.173-.797-1.388-3.284-2.776-4.975-2.776h-1.16v-2.47c0-2.81-.058-2.773 3.246-2.072 3.965.841 6.805 2.853 8.278 5.865.846 1.728.973 2.4.95 5.01-.016 1.66-.358 4.683-.762 6.72-1.499 7.564-1.365 9.576.765 11.533.99.908 1.64 1.173 3.37 1.368l2.145.243v4.848h-1.676c-2.151.001-3.932.91-4.838 2.47-.952 1.637-.893 5.206.173 10.406.907 4.422 1.053 8.459.389 10.729-.701 2.394-3.82 5.296-6.748 6.277-1.261.423-2.968.871-3.792.996l-1.5.228z" style="stroke-width:.35277778" transform="translate(-104.228 -45.508)"/><path d="M131.742 108.266c-1.021-1.299-.873-3.537.381-5.732.928-1.624 4.809-6.948 7.61-10.44l1.132-1.41-1.802-5.226c-2.022-5.86-2.01-5.974.656-6.372l1.468-.219 1.64 3.35c.903 1.843 1.77 3.351 1.928 3.351.158 0 1.775-1.755 3.594-3.9 3.16-3.727 3.357-3.892 4.426-3.694.645.12 1.218.047 1.354-.173.318-.515 1.23.247 1.23 1.027 0 .32-.453 1.134-1.009 1.81-2.267 2.755-7.104 9.27-7.104 9.57 0 .177.975 2.454 2.167 5.059l2.166 4.736-.658.985c-.362.541-.662 1.126-.667 1.299-.005.173-.278.483-.606.69-.832.525-1.447-.115-3.99-4.153-1.164-1.848-2.231-3.365-2.372-3.37-.313-.01-3.79 5.133-6.48 9.581-2.37 3.924-1.938 3.42-3.265 3.801-.956.274-1.194.199-1.799-.57zM131.986 83.677c-2.152-3.847-6.019-9.428-7.579-10.938-.792-.767-1.44-1.575-1.44-1.796 0-.601 1.616-1.22 3.19-1.22 1.698 0 3.496 1.479 5.1 4.193.582.985 1.156 1.794 1.276 1.798.12.004.809-1.651 1.53-3.678 1.547-4.34 5.624-12.778 7.225-14.951 1.373-1.863 3.43-2.865 5.903-2.876 3.234-.013 3.243.13.205 3.297-4.636 4.832-6.764 8.81-11.252 21.037-1.246 3.396-2.39 6.48-2.542 6.852-.23.566-.498.281-1.616-1.718z" style="stroke-width:.35277775" transform="translate(-104.228 -45.508)"/></g></svg> 33 - title: Clients 34 - details: Type-safe data with REST clients for your runtime. Fetch API, Angular, Next.js, Nuxt and more. 33 + title: HTTP Clients 34 + details: Pluggable HTTP clients for Fetch API, Angular, Axios, Next.js, Nuxt, and more. 35 35 link: /openapi-ts/clients 36 36 linkText: Explore clients 37 37 - icon: <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 190"><g fill="none" fill-rule="evenodd"><path d="M150.276 61.344c3.093-14.981 3.756-26.471 1.757-34.815-1.189-4.962-3.362-9.01-6.668-11.93-3.49-3.084-7.901-4.597-12.858-4.597-8.178 0-16.775 3.725-25.963 10.802-3.747 2.887-7.636 6.366-11.676 10.44a8.743 8.743 0 0 0-1.09-1.163C82.36 19.915 72.746 13.599 64.523 11.164c-4.89-1.448-9.48-1.586-13.66-.181-4.414 1.483-7.93 4.55-10.41 8.845-4.094 7.089-5.174 16.403-3.648 27.904.623 4.688 1.686 9.794 3.189 15.327a8.725 8.725 0 0 0-1.698.38c-14.489 4.797-24.749 9.955-30.96 15.85-3.696 3.506-6.109 7.41-6.981 11.733-.921 4.562-.023 9.137 2.454 13.43 4.087 7.078 11.6 12.66 22.304 17.082 4.298 1.776 9.161 3.384 14.595 4.83a8.735 8.735 0 0 0-.57 1.776c-3.092 14.98-3.756 26.47-1.756 34.814 1.188 4.962 3.362 9.01 6.667 11.93 3.49 3.084 7.902 4.597 12.86 4.597 8.177 0 16.774-3.725 25.962-10.802 3.787-2.917 7.72-6.44 11.805-10.57.42.656.936 1.267 1.546 1.81 11.42 10.166 21.034 16.482 29.257 18.917 4.89 1.448 9.48 1.586 13.66.181 4.414-1.483 7.93-4.55 10.41-8.845 4.094-7.089 5.174-16.403 3.648-27.904-.645-4.857-1.764-10.164-3.354-15.929a8.715 8.715 0 0 0 1.863-.398c14.489-4.797 24.749-9.955 30.96-15.85 3.696-3.506 6.109-7.41 6.981-11.733.921-4.562.023-9.137-2.454-13.43-4.087-7.078-11.6-12.66-22.304-17.082-4.427-1.828-9.452-3.48-15.082-4.959.2-.49.36-1.006.47-1.543Z" fill="#002C4B" fill-rule="nonzero"/><path d="M80.397 64h29.211a5 5 0 0 1 4.337 2.512l14.632 25.5a5 5 0 0 1 0 4.976l-14.632 25.5a5 5 0 0 1-4.337 2.512H80.397a5 5 0 0 1-4.337-2.512l-14.632-25.5a5 5 0 0 1 0-4.976l14.632-25.5A5 5 0 0 1 80.397 64Zm25.59 6.277a5 5 0 0 1 4.339 2.513l11.017 19.224a5 5 0 0 1 0 4.972l-11.017 19.224a5 5 0 0 1-4.338 2.513h-21.97a5 5 0 0 1-4.339-2.513L68.662 96.986a5 5 0 0 1 0-4.972L79.679 72.79a5 5 0 0 1 4.338-2.513h21.97Zm-3.906 6.864H87.924a5 5 0 0 0-4.335 2.51l-7.1 12.358a5 5 0 0 0 0 4.982l7.1 12.358a5 5 0 0 0 4.335 2.51h14.157a5 5 0 0 0 4.335-2.51l7.1-12.358a5 5 0 0 0 0-4.982l-7.1-12.358a5 5 0 0 0-4.335-2.51Zm-3.762 6.571a5 5 0 0 1 4.334 2.506l3.33 5.788a5 5 0 0 1 0 4.988l-3.33 5.788a5 5 0 0 1-4.334 2.506h-6.633a5 5 0 0 1-4.334-2.506l-3.33-5.788a5 5 0 0 1 0-4.988l3.33-5.788a5 5 0 0 1 4.334-2.506h6.633Zm-3.315 6.473a4.313 4.313 0 1 0-.003 8.63 4.313 4.313 0 1 0 .003-8.63ZM60 94.5h7.768" fill="#FFD94C"/><path d="M54.86 108.358a2.713 2.713 0 0 1 3.718 1.041l.475.845a269.421 269.421 0 0 0 11.888 19.191c4.867 7.15 10.34 14.39 16.421 21.716a2.776 2.776 0 0 1-.296 3.847l-.612.537c-20.107 17.568-33.176 21.078-39.206 10.527-5.898-10.32-3.764-29.08 6.403-56.28a2.748 2.748 0 0 1 1.21-1.424Zm85.674 20.684a2.708 2.708 0 0 1 3.126 2.152l.153.792c4.97 26.01 1.47 39.014-10.497 39.014-11.706 0-26.607-11.091-44.703-33.273a2.725 2.725 0 0 1-.613-1.745 2.712 2.712 0 0 1 2.73-2.694l.955.007c7.62.041 15.03-.223 22.226-.794 8.498-.673 17.373-1.826 26.623-3.46Zm6.875-55.23c.523-1.41 2.1-2.149 3.546-1.663l.788.266c25.84 8.803 35.66 18.477 29.455 29.022-6.068 10.314-23.714 17.823-52.936 22.527a2.852 2.852 0 0 1-1.88-.345 2.726 2.726 0 0 1-.993-3.772l.5-.837c3.988-6.694 7.592-13.356 10.813-19.986 3.803-7.83 7.372-16.233 10.707-25.212Zm-85.67-7.776a2.852 2.852 0 0 1 1.878.345 2.726 2.726 0 0 1 .994 3.772l-.5.837c-3.988 6.694-7.592 13.356-10.813 19.986-3.803 7.83-7.372 16.233-10.707 25.212-.523 1.41-2.1 2.149-3.546 1.663l-.788-.266c-25.84-8.803-35.66-18.477-29.455-29.022C14.87 78.25 32.516 70.74 61.738 66.036Zm41.807-31.57c20.107-17.57 33.176-21.079 39.206-10.528 5.898 10.32 3.764 29.08-6.403 56.28a2.748 2.748 0 0 1-1.21 1.424 2.713 2.713 0 0 1-3.717-1.041l-.475-.845a269.421 269.421 0 0 0-11.888-19.191c-4.867-7.15-10.34-14.39-16.421-21.716a2.776 2.776 0 0 1 .296-3.847ZM57.684 18c11.706 0 26.607 11.091 44.703 33.273.402.492.618 1.11.613 1.745a2.712 2.712 0 0 1-2.73 2.694l-.955-.007c-7.62-.041-15.03.223-22.226.794-8.498.673-17.373 1.826-26.623 3.46a2.708 2.708 0 0 1-3.126-2.153l-.153-.792C42.217 31.004 45.717 18 57.684 18Z" fill="#FF4154"/></g></svg> 38 - title: Plugins 39 - details: Reduce third-party boilerplate with our plugin ecosystem. 38 + title: Plugin Ecosystem 39 + details: Zod, TanStack Query, and 20+ plugins to reduce third-party boilerplate. 40 40 link: /openapi-ts/core 41 41 linkText: Explore plugins 42 42 - icon: ๐Ÿงฉ 43 - title: Custom 44 - details: Build your own plugins and clients for proprietary use cases. 43 + title: Custom Extensions 44 + details: Build custom plugins for proprietary or advanced use cases. 45 45 link: /openapi-ts/plugins/custom 46 46 linkText: Build a custom plugin 47 47 - icon: <svg class="icon-github" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 98"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg> 48 48 title: Integrations 49 - details: Superpower your codegen with automations and integrations. 49 + details: Sync specs, automate workflows, and integrate with the Hey API Platform. 50 50 link: /openapi-ts/integrations 51 51 linkText: Learn about integrations 52 52 ---
+2 -2
docs/openapi-ts/clients.md
··· 1 1 --- 2 2 title: Clients 3 - description: REST clients for Hey API. Compatible with all our features. 3 + description: HTTP clients for Hey API. Compatible with all our features. 4 4 --- 5 5 6 6 <script setup lang="ts"> 7 7 import { embedProject } from '../embed' 8 8 </script> 9 9 10 - # REST Clients 10 + # HTTP Clients 11 11 12 12 We all send HTTP requests in a slightly different way. Hey API doesn't force you to use any specific technology. What we do, however, is support your choice with great clients. All seamlessly integrated with our other features. 13 13
+11 -8
docs/openapi-ts/get-started.md
··· 9 9 10 10 # Get Started 11 11 12 - [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) is an [open source](/openapi-ts/license) OpenAPI to TypeScript code generator trusted by companies like Google, Amazon, and PayPal to generate API clients, SDKs, validators, and more. We also build complementary tools and [services](https://app.heyapi.dev/) that help teams design, manage, and distribute APIs more effectively. 12 + [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) generates TypeScript code from OpenAPI specifications. Point it at your spec, pick your plugins, and get production-ready code in seconds. 13 + 14 + Used by companies like Vercel, OpenCode, and PayPal. 13 15 14 16 > _โ€œOpenAPI codegen that just works.โ€_ 15 17 > ··· 23 25 24 26 ## Features 25 27 26 - - runs in CLI, Node.js 20+, or npx 27 - - works with OpenAPI 2.0, 3.0, and 3.1 28 - - core plugins for types, SDKs, and schemas 29 - - clients for your runtime (Fetch API, Angular, Axios, Next.js, Nuxt, etc.) 30 - - plugin ecosystem to reduce third-party boilerplate 31 - - custom plugins and custom clients 32 - - [integration](/openapi-ts/integrations) with Hey API Platform 28 + - production-ready code that compiles 29 + - runs in any Node.js 20+ environment 30 + - accepts any OpenAPI specification 31 + - core plugins for SDKs, types, and schemas 32 + - HTTP clients for Fetch API, Angular, Axios, Next.js, Nuxt, and more 33 + - 20+ plugins to reduce third-party boilerplate 34 + - highly customizable via plugins 35 + - [sync with Hey API Registry](/openapi-ts/integrations) for spec management 33 36 34 37 ## Quick Start 35 38
+6
docs/openapi-ts/migrating.md
··· 7 7 8 8 While we try to avoid breaking changes, sometimes it's unavoidable in order to offer you the latest features. This page lists changes that require updates to your code. If you run into a problem with migration, please [open an issue](https://github.com/hey-api/openapi-ts/issues). 9 9 10 + ## v0.90.0 11 + 12 + ### Resolvers API 13 + 14 + The [Resolvers API](/openapi-ts/plugins/concepts/resolvers) has been simplified and expanded to provide a more consistent behavior across plugins. You can view a few common examples on the [Resolvers](/openapi-ts/plugins/concepts/resolvers) page. 15 + 10 16 ## v0.89.0 11 17 12 18 ### Prefer named exports
+181
docs/openapi-ts/plugins/concepts/resolvers.md
··· 1 + --- 2 + title: Resolvers 3 + description: Understand the concepts behind plugins. 4 + --- 5 + 6 + # Resolvers 7 + 8 + Sometimes the default plugin behavior isn't what you need or expect. Resolvers let you patch plugins in a safe and performant way, without forking or reimplementing core logic. 9 + 10 + Currently available for [Valibot](/openapi-ts/plugins/valibot) and [Zod](/openapi-ts/plugins/zod). 11 + 12 + ## Examples 13 + 14 + This page demonstrates resolvers through a few common scenarios. 15 + 16 + 1. [Handle arbitrary schema formats](#example-1) 17 + 2. [Validate high precision numbers](#example-2) 18 + 3. [Replace default base](#example-3) 19 + 20 + ## Terminology 21 + 22 + Before we look at examples, let's go through the resolvers API to help you understand how they work. Plugins that support resolvers expose them through the `~resolvers` option. Each resolver is a function that receives context and returns an implemented node (or patches existing ones). 23 + 24 + The resolver context will usually contain: 25 + 26 + - `$` - The node builder interface. Use it to build your custom logic. 27 + - `nodes` - Parts of the plugin logic. You can use these to avoid reimplementing the functionality, or replace them with custom implementation. 28 + - `plugin` - The plugin instance. You'll most likely use it to register new symbols. 29 + - `symbols` - Frequently used symbols. These are effectively shorthands for commonly used `plugin.referenceSymbol()` calls. 30 + 31 + Other fields may include the current schema or relevant utilities. 32 + 33 + ## Example 1 34 + 35 + ### Handle arbitrary schema formats 36 + 37 + By default, the Valibot plugin may produce the following schemas for `date` and `date-time` strings. 38 + 39 + ```js 40 + export const vDates = v.object({ 41 + created: v.pipe(v.string(), v.isoDate()), 42 + modified: v.pipe(v.string(), v.isoTimestamp()), 43 + }); 44 + ``` 45 + 46 + We can override this behavior by patching the `nodes.format` function only for strings with `date` or `date-time` formats. 47 + 48 + ```js 49 + { 50 + name: 'valibot', 51 + '~resolvers': { 52 + string(ctx) { 53 + const { $, schema, symbols } = ctx; 54 + const { v } = symbols; 55 + if (schema.format === 'date' || schema.format === 'date-time') { 56 + ctx.nodes.format = () => $(v).attr('isoDateTime').call(); 57 + } 58 + } 59 + } 60 + } 61 + ``` 62 + 63 + This applies custom logic with surgical precision, without affecting the rest of the default behavior. 64 + 65 + ::: code-group 66 + 67 + ```js [after] 68 + export const vDates = v.object({ 69 + created: v.pipe(v.string(), v.isoDateTime()), 70 + modified: v.pipe(v.string(), v.isoDateTime()), 71 + }); 72 + ``` 73 + 74 + ```js [before] 75 + export const vDates = v.object({ 76 + created: v.pipe(v.string(), v.isoDate()), 77 + modified: v.pipe(v.string(), v.isoTimestamp()), 78 + }); 79 + ``` 80 + 81 + ::: 82 + 83 + ## Example 2 84 + 85 + ### Validate high precision numbers 86 + 87 + Let's say you're dealing with very large or unsafe numbers. 88 + 89 + ```js 90 + export const vAmount = v.number(); 91 + ``` 92 + 93 + In this case, you'll want to use a third-party library to validate your values. We can use big.js to validate all numbers by replacing the whole resolver. 94 + 95 + ```js 96 + { 97 + name: 'valibot', 98 + '~resolvers': { 99 + number(ctx) { 100 + const { $, plugin, symbols } = ctx; 101 + const { v } = symbols; 102 + const big = plugin.symbolOnce('Big', { 103 + external: 'big.js', 104 + importKind: 'default', 105 + }); 106 + return $(v).attr('instance').call(big); 107 + } 108 + } 109 + } 110 + ``` 111 + 112 + We're calling `plugin.symbolOnce()` to ensure we always use the same symbol reference. 113 + 114 + ::: code-group 115 + 116 + ```js [after] 117 + import Big from 'big.js'; 118 + 119 + export const vAmount = v.instance(Big); 120 + ``` 121 + 122 + ```js [before] 123 + export const vAmount = v.number(); 124 + ``` 125 + 126 + ::: 127 + 128 + ## Example 3 129 + 130 + ### Replace default base 131 + 132 + You might want to replace the default base schema, e.g. `v.object()`. 133 + 134 + ```js 135 + export const vUser = v.object({ 136 + age: v.number(), 137 + }); 138 + ``` 139 + 140 + Let's say we want to interpret any schema without explicitly defined additional properties as a loose object. 141 + 142 + ```js 143 + { 144 + name: 'valibot', 145 + '~resolvers': { 146 + object(ctx) { 147 + const { $, symbols } = ctx; 148 + const { v } = symbols; 149 + const additional = ctx.nodes.additionalProperties(ctx); 150 + if (additional === undefined) { 151 + const shape = ctx.nodes.shape(ctx); 152 + ctx.nodes.base = () => $(v).attr('looseObject').call(shape); 153 + } 154 + } 155 + } 156 + } 157 + ``` 158 + 159 + Above we demonstrate patching a node based on the result of another node. 160 + 161 + ::: code-group 162 + 163 + ```js [after] 164 + export const vUser = v.looseObject({ 165 + age: v.number(), 166 + }); 167 + ``` 168 + 169 + ```js [before] 170 + export const vUser = v.object({ 171 + age: v.number(), 172 + }); 173 + ``` 174 + 175 + ::: 176 + 177 + ## Feedback 178 + 179 + We welcome feedback on the Resolvers API. [Open a GitHub issue](https://github.com/hey-api/openapi-ts/issues) to request support for additional plugins. 180 + 181 + <!--@include: ../../../partials/sponsors.md-->
+4
docs/openapi-ts/plugins/valibot.md
··· 207 207 208 208 ::: 209 209 210 + ## Resolvers 211 + 212 + You can further customize this plugin's behavior using [resolvers](/openapi-ts/plugins/concepts/resolvers). 213 + 210 214 ## API 211 215 212 216 You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/plugins/valibot/types.d.ts) interface.
+4
docs/openapi-ts/plugins/zod/mini.md
··· 312 312 313 313 You can customize the naming and casing pattern for schema-specific `types` using the `.name` and `.case` options. 314 314 315 + ## Resolvers 316 + 317 + You can further customize this plugin's behavior using [resolvers](/openapi-ts/plugins/concepts/resolvers). 318 + 315 319 ## API 316 320 317 321 You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/plugins/zod/types.d.ts) interface.
+4
docs/openapi-ts/plugins/zod/v3.md
··· 310 310 311 311 You can customize the naming and casing pattern for schema-specific `types` using the `.name` and `.case` options. 312 312 313 + ## Resolvers 314 + 315 + You can further customize this plugin's behavior using [resolvers](/openapi-ts/plugins/concepts/resolvers). 316 + 313 317 ## API 314 318 315 319 You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/plugins/zod/types.d.ts) interface.
+4
docs/openapi-ts/plugins/zod.md
··· 299 299 300 300 You can customize the naming and casing pattern for schema-specific `types` using the `.name` and `.case` options. 301 301 302 + ## Resolvers 303 + 304 + You can further customize this plugin's behavior using [resolvers](/openapi-ts/plugins/concepts/resolvers). 305 + 302 306 ## API 303 307 304 308 You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/plugins/zod/types.d.ts) interface.
+1 -1
docs/partials/sponsors.md
··· 1 1 ## Sponsors 2 2 3 - Help Hey API stay around for the long haul by becoming a [sponsor](https://github.com/sponsors/hey-api). 3 + Hey API is sponsor-funded. If your team relies on Hey API in production, consider becoming a [sponsor](https://github.com/sponsors/hey-api) to accelerate the roadmap. 4 4 5 5 <div class="sponsors-list"> 6 6
+1 -1
package.json
··· 73 73 "typescript-eslint": "8.29.1", 74 74 "vitest": "3.2.4" 75 75 }, 76 - "packageManager": "pnpm@10.25.0" 76 + "packageManager": "pnpm@10.26.1" 77 77 }
+4
packages/codegen-core/src/symbols/types.d.ts
··· 44 44 getFilePath?: Symbol['getFilePath']; 45 45 /** 46 46 * Kind of import if this symbol represents an import. 47 + * 48 + * @default 'named' 47 49 */ 48 50 importKind?: BindingKind; 49 51 /** 50 52 * Kind of symbol. 53 + * 54 + * @default 'var' 51 55 */ 52 56 kind?: SymbolKind; 53 57 /**
+14 -13
packages/openapi-ts/README.md
··· 14 14 <p align="center"> 15 15 <a href="https://stackblitz.com/edit/hey-api-example?file=openapi-ts.config.ts,src%2Fclient%2Fschemas.gen.ts,src%2Fclient%2Fsdk.gen.ts,src%2Fclient%2Ftypes.gen.ts">Demo</a> 16 16 <span>&nbsp;โ€ข&nbsp;</span> 17 - <a href="https://heyapi.dev">Docs</a> 17 + <a href="https://heyapi.dev">Manual</a> 18 18 <span>&nbsp;โ€ข&nbsp;</span> 19 19 <a href="https://github.com/hey-api/openapi-ts/issues">Issues</a> 20 20 <span>&nbsp;โ€ข&nbsp;</span> ··· 23 23 24 24 ## About 25 25 26 - [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) is an [open source](https://github.com/hey-api/openapi-ts/blob/main/LICENSE.md) OpenAPI to TypeScript code generator trusted by companies like Google, Amazon, and PayPal to generate API clients, SDKs, validators, and more. We also build complementary tools and [services](https://app.heyapi.dev/) that help teams design, manage, and distribute APIs more effectively. 26 + The OpenAPI to TypeScript code generator used by Vercel, OpenCode, and PayPal. 27 27 28 - ## Features 28 + Generate production-ready SDKs, Zod schemas, TanStack Query hooks, or choose from 20+ other plugins. 29 29 30 - - runs in CLI, Node.js 20+, or npx 31 - - works with OpenAPI 2.0, 3.0, and 3.1 32 - - core plugins for types, SDKs, and schemas 33 - - clients for your runtime (Fetch API, Angular, Axios, Next.js, Nuxt, etc.) 34 - - plugin ecosystem to reduce third-party boilerplate 35 - - custom plugins and custom clients 36 - - [integration](https://heyapi.dev/openapi-ts/integrations) with Hey API Platform 30 + Part of the Hey API ecosystem. 37 31 38 - ## Dashboard 32 + ## Features 39 33 40 - Access your projects and OpenAPI specifications in the [Hey API Platform](https://app.heyapi.dev/). 34 + - production-ready code that compiles 35 + - runs in any Node.js 20+ environment 36 + - accepts any OpenAPI specification 37 + - core plugins for SDKs, types, and schemas 38 + - HTTP clients for Fetch API, Angular, Axios, Next.js, Nuxt, and more 39 + - 20+ plugins to reduce third-party boilerplate 40 + - highly customizable via plugins 41 + - [sync with Hey API Registry](https://heyapi.dev/openapi-ts/integrations) for spec management 41 42 42 43 ## Contributing 43 44 ··· 47 48 48 49 ## Sponsors 49 50 50 - Help Hey API stay around for the long haul by becoming a [sponsor](https://github.com/sponsors/hey-api). 51 + Hey API is sponsor-funded. If your team relies on Hey API in production, consider becoming a [sponsor](https://github.com/sponsors/hey-api) to accelerate the roadmap. 51 52 52 53 <h3 align="center">Gold</h3> 53 54
+2 -2
packages/openapi-ts/package.json
··· 1 1 { 2 2 "name": "@hey-api/openapi-ts", 3 3 "version": "0.89.2", 4 - "description": "๐ŸŒ€ OpenAPI to TypeScript code generator. Generate API clients, SDKs, validators, and more.", 4 + "description": "๐ŸŒ€ OpenAPI to TypeScript codegen. Production-ready SDKs, Zod schemas, TanStack Query hooks, and 20+ plugins. Used by Vercel, OpenCode, and PayPal.", 5 5 "homepage": "https://heyapi.dev/", 6 6 "repository": { 7 7 "type": "git", ··· 92 92 "@hey-api/codegen-core": "workspace:^0.4.0", 93 93 "@hey-api/json-schema-ref-parser": "1.2.2", 94 94 "ansi-colors": "4.1.3", 95 - "c12": "3.3.2", 95 + "c12": "3.3.3", 96 96 "color-support": "1.1.3", 97 97 "commander": "14.0.2", 98 98 "open": "11.0.0",
-8
packages/openapi-ts/src/plugins/arktype/v2/toAst/object.ts
··· 93 93 result.hasLazyExpression = true; 94 94 } 95 95 96 - // Return with typeName for circular references 97 - if (result.hasLazyExpression) { 98 - return { 99 - ...result, 100 - typeName: 'TODO', 101 - } as Ast; 102 - } 103 - 104 96 return result as Omit<Ast, 'typeName'>; 105 97 } 106 98
+28
packages/openapi-ts/src/plugins/shared/utils/coerce.ts
··· 1 + import { $ } from '~/ts-dsl'; 2 + 3 + export type MaybeBigInt = ( 4 + value: unknown, 5 + format: string | undefined, 6 + ) => ReturnType<typeof $.fromValue>; 7 + export type ShouldCoerceToBigInt = (format: string | undefined) => boolean; 8 + 9 + export const shouldCoerceToBigInt: ShouldCoerceToBigInt = (format) => 10 + format === 'int64' || format === 'uint64'; 11 + 12 + export const maybeBigInt: MaybeBigInt = (value, format) => { 13 + if (!shouldCoerceToBigInt(format)) { 14 + return $.fromValue(value); 15 + } 16 + 17 + if (typeof value === 'string') { 18 + // handle invalid input 19 + if (value.endsWith('n')) value = value.slice(0, -1); 20 + return $('BigInt').call($.fromValue(value)); 21 + } 22 + 23 + if (typeof value === 'number') { 24 + return $('BigInt').call($.fromValue(value)); 25 + } 26 + 27 + return $.fromValue(value); 28 + };
+36
packages/openapi-ts/src/plugins/shared/utils/formats.ts
··· 1 + type Range = number | string; 2 + 3 + interface IntegerLimit { 4 + maxError: string; 5 + maxValue: Range; 6 + minError: string; 7 + minValue: Range; 8 + } 9 + 10 + export type GetIntegerLimit = ( 11 + format: string | undefined, 12 + ) => IntegerLimit | undefined; 13 + 14 + const rangeErrors = (format: string, range: [Range, Range]) => ({ 15 + maxError: `Invalid value: Expected ${format} to be <= ${range[1]}`, 16 + minError: `Invalid value: Expected ${format} to be >= ${range[0]}`, 17 + }); 18 + 19 + const integerRange: Record<string, [Range, Range]> = { 20 + int16: [-32768, 32767], 21 + int32: [-2147483648, 2147483647], 22 + int64: ['-9223372036854775808', '9223372036854775807'], 23 + int8: [-128, 127], 24 + uint16: [0, 65535], 25 + uint32: [0, 4294967295], 26 + uint64: ['0', '18446744073709551615'], 27 + uint8: [0, 255], 28 + }; 29 + 30 + export const getIntegerLimit: GetIntegerLimit = (format) => { 31 + if (!format) return; 32 + const range = integerRange[format]; 33 + if (!range) return; 34 + const errors = rangeErrors(format, range); 35 + return { maxValue: range[1], minValue: range[0], ...errors }; 36 + };
+28
packages/openapi-ts/src/plugins/shared/utils/instance.ts
··· 106 106 this.package = props.context.package; 107 107 } 108 108 109 + external( 110 + resource: Required<SymbolMeta>['resource'], 111 + meta?: Omit<SymbolMeta, 'category' | 'resource'>, 112 + ): Symbol { 113 + return this.gen.symbols.reference({ 114 + ...meta, 115 + category: 'external', 116 + resource, 117 + }); 118 + } 119 + 109 120 /** 110 121 * Iterates over various input elements as specified by the event types, in 111 122 * a specific order: servers, schemas, parameters, request bodies, then ··· 376 387 hook({ plugin: this, symbol: symbolOut }); 377 388 } 378 389 return symbolOut; 390 + } 391 + 392 + /** 393 + * Registers a symbol only if it does not already exist based on the provided 394 + * metadata. This prevents duplicate symbols from being created in the project. 395 + */ 396 + symbolOnce(name: SymbolIn['name'], symbol?: Omit<SymbolIn, 'name'>): Symbol { 397 + const meta = { 398 + ...symbol?.meta, 399 + }; 400 + if (symbol?.external) { 401 + meta.category = 'external'; 402 + meta.resource = symbol.external; 403 + } 404 + const existing = this.querySymbol(meta); 405 + if (existing) return existing; 406 + return this.symbol(name, { ...symbol, meta }); 379 407 } 380 408 381 409 private buildEventHooks(): EventHooks {
+2 -2
packages/openapi-ts/src/plugins/valibot/shared/export.ts
··· 5 5 import { $ } from '~/ts-dsl'; 6 6 7 7 import { identifiers } from '../v1/constants'; 8 - import { pipesToAst } from './pipesToAst'; 8 + import { pipesToNode } from './pipes'; 9 9 import type { Ast, IrSchemaToAstOptions } from './types'; 10 10 11 11 export const exportAst = ({ ··· 32 32 .$if(state.hasLazyExpression['~ref'], (c) => 33 33 c.type($.type(v).attr(ast.typeName || identifiers.types.GenericSchema)), 34 34 ) 35 - .assign(pipesToAst({ pipes: ast.pipes, plugin })); 35 + .assign(pipesToNode(ast.pipes, plugin)); 36 36 plugin.node(statement); 37 37 };
-91
packages/openapi-ts/src/plugins/valibot/shared/numbers.ts
··· 1 - import { $ } from '~/ts-dsl'; 2 - 3 - export const INTEGER_FORMATS = { 4 - int16: { 5 - max: 32767, 6 - maxError: 'Invalid value: Expected int16 to be <= 2^15-1', 7 - min: -32768, 8 - minError: 'Invalid value: Expected int16 to be >= -2^15', 9 - needsBigInt: false, 10 - }, 11 - int32: { 12 - max: 2147483647, 13 - maxError: 'Invalid value: Expected int32 to be <= 2^31-1', 14 - min: -2147483648, 15 - minError: 'Invalid value: Expected int32 to be >= -2^31', 16 - needsBigInt: false, 17 - }, 18 - int64: { 19 - max: '9223372036854775807', 20 - maxError: 'Invalid value: Expected int64 to be <= 2^63-1', 21 - min: '-9223372036854775808', 22 - minError: 'Invalid value: Expected int64 to be >= -2^63', 23 - needsBigInt: true, 24 - }, 25 - int8: { 26 - max: 127, 27 - maxError: 'Invalid value: Expected int8 to be <= 2^7-1', 28 - min: -128, 29 - minError: 'Invalid value: Expected int8 to be >= -2^7', 30 - needsBigInt: false, 31 - }, 32 - uint16: { 33 - max: 65535, 34 - maxError: 'Invalid value: Expected uint16 to be <= 2^16-1', 35 - min: 0, 36 - minError: 'Invalid value: Expected uint16 to be >= 0', 37 - needsBigInt: false, 38 - }, 39 - uint32: { 40 - max: 4294967295, 41 - maxError: 'Invalid value: Expected uint32 to be <= 2^32-1', 42 - min: 0, 43 - minError: 'Invalid value: Expected uint32 to be >= 0', 44 - needsBigInt: false, 45 - }, 46 - uint64: { 47 - max: '18446744073709551615', 48 - maxError: 'Invalid value: Expected uint64 to be <= 2^64-1', 49 - min: '0', 50 - minError: 'Invalid value: Expected uint64 to be >= 0', 51 - needsBigInt: true, 52 - }, 53 - uint8: { 54 - max: 255, 55 - maxError: 'Invalid value: Expected uint8 to be <= 2^8-1', 56 - min: 0, 57 - minError: 'Invalid value: Expected uint8 to be >= 0', 58 - needsBigInt: false, 59 - }, 60 - } as const; 61 - 62 - export type IntegerFormat = keyof typeof INTEGER_FORMATS; 63 - 64 - export const isIntegerFormat = ( 65 - format: string | undefined, 66 - ): format is IntegerFormat => format !== undefined && format in INTEGER_FORMATS; 67 - 68 - export const needsBigIntForFormat = (format: string | undefined): boolean => 69 - isIntegerFormat(format) && INTEGER_FORMATS[format].needsBigInt; 70 - 71 - export const numberParameter = ({ 72 - isBigInt, 73 - value, 74 - }: { 75 - isBigInt: boolean; 76 - value: unknown; 77 - }): ReturnType<typeof $.call | typeof $.fromValue> => { 78 - const expression = $.fromValue(value); 79 - 80 - if ( 81 - isBigInt && 82 - (typeof value === 'bigint' || 83 - typeof value === 'number' || 84 - typeof value === 'string' || 85 - typeof value === 'boolean') 86 - ) { 87 - return $('BigInt').call(expression); 88 - } 89 - 90 - return expression; 91 - };
+52
packages/openapi-ts/src/plugins/valibot/shared/pipes.ts
··· 1 + import { $ } from '~/ts-dsl'; 2 + 3 + import type { ValibotPlugin } from '../types'; 4 + import { identifiers } from '../v1/constants'; 5 + 6 + export type Pipe = ReturnType<typeof $.call | typeof $.expr>; 7 + export type Pipes = Array<Pipe>; 8 + export type PipeResult = Pipes | Pipe; 9 + 10 + type PushPipes = (target: Pipes, pipes: PipeResult) => Pipes; 11 + type PipesToNode = ( 12 + pipes: PipeResult, 13 + plugin: ValibotPlugin['Instance'], 14 + ) => Pipe; 15 + 16 + export const pipesToNode: PipesToNode = (pipes, plugin) => { 17 + if (!(pipes instanceof Array)) return pipes; 18 + if (pipes.length === 1) return pipes[0]!; 19 + 20 + const v = plugin.external('valibot.v'); 21 + return $(v) 22 + .attr(identifiers.methods.pipe) 23 + .call(...pipes); 24 + }; 25 + 26 + export const pushPipes: PushPipes = (target, pipes) => { 27 + if (pipes instanceof Array) { 28 + target.push(...pipes); 29 + } else { 30 + target.push(pipes); 31 + } 32 + return target; 33 + }; 34 + 35 + export interface PipesUtils { 36 + /** 37 + * Push pipes into target array. 38 + */ 39 + push: PushPipes; 40 + /** 41 + * Convert pipes to a single node. 42 + */ 43 + toNode: PipesToNode; 44 + } 45 + 46 + /** 47 + * Functions for working with pipes. 48 + */ 49 + export const pipes: PipesUtils = { 50 + push: pushPipes, 51 + toNode: pipesToNode, 52 + };
-24
packages/openapi-ts/src/plugins/valibot/shared/pipesToAst.ts
··· 1 - import { $ } from '~/ts-dsl'; 2 - 3 - import type { ValibotPlugin } from '../types'; 4 - import { identifiers } from '../v1/constants'; 5 - 6 - export const pipesToAst = ({ 7 - pipes, 8 - plugin, 9 - }: { 10 - pipes: ReadonlyArray<ReturnType<typeof $.call | typeof $.expr>>; 11 - plugin: ValibotPlugin['Instance']; 12 - }): ReturnType<typeof $.call | typeof $.expr> => { 13 - if (pipes.length === 1) { 14 - return pipes[0]!; 15 - } 16 - 17 - const v = plugin.referenceSymbol({ 18 - category: 'external', 19 - resource: 'valibot.v', 20 - }); 21 - return $(v) 22 - .attr(identifiers.methods.pipe) 23 - .call(...pipes); 24 - };
+2 -2
packages/openapi-ts/src/plugins/valibot/shared/types.d.ts
··· 2 2 import type ts from 'typescript'; 3 3 4 4 import type { IR } from '~/ir/types'; 5 - import type { $ } from '~/ts-dsl'; 6 5 7 6 import type { ValibotPlugin } from '../types'; 7 + import type { Pipes } from './pipes'; 8 8 9 9 export type Ast = { 10 10 hasLazyExpression?: boolean; 11 - pipes: Array<ReturnType<typeof $.call | typeof $.expr>>; 11 + pipes: Pipes; 12 12 typeName?: string | ts.Identifier; 13 13 }; 14 14
+123 -73
packages/openapi-ts/src/plugins/valibot/types.d.ts
··· 1 - import type { Symbol } from '@hey-api/codegen-core'; 2 - import type ts from 'typescript'; 1 + import type { Refs, Symbol } from '@hey-api/codegen-core'; 3 2 4 3 import type { IR } from '~/ir/types'; 5 - import type { DefinePlugin, Plugin } from '~/plugins'; 6 - import type { $, DollarTsDsl, TsDsl } from '~/ts-dsl'; 4 + import type { DefinePlugin, Plugin, SchemaWithType } from '~/plugins'; 5 + import type { 6 + MaybeBigInt, 7 + ShouldCoerceToBigInt, 8 + } from '~/plugins/shared/utils/coerce'; 9 + import type { GetIntegerLimit } from '~/plugins/shared/utils/formats'; 10 + import type { $, DollarTsDsl } from '~/ts-dsl'; 7 11 import type { StringCase, StringName } from '~/types/case'; 8 - import type { MaybeArray } from '~/types/utils'; 9 12 10 13 import type { IApi } from './api'; 14 + import type { Pipe, PipeResult, PipesUtils } from './shared/pipes'; 15 + import type { Ast, PluginState } from './shared/types'; 11 16 12 17 export type UserConfig = Plugin.Name<'valibot'> & 13 18 Plugin.Hooks & ··· 321 326 }; 322 327 }; 323 328 324 - type SharedResolverArgs = DollarTsDsl & { 329 + interface BaseResolverContext extends DollarTsDsl { 325 330 /** 326 - * The current builder state being processed by this resolver. 327 - * 328 - * In Valibot, this represents the current list of call expressions ("pipes") 329 - * being assembled to form a schema definition. 330 - * 331 - * Each pipe can be extended, modified, or replaced to customize how the 332 - * resulting schema is constructed. Returning `undefined` from a resolver will 333 - * use the default generation behavior. 331 + * Functions for working with pipes. 334 332 */ 335 - pipes: Array<ReturnType<typeof $.call>>; 333 + pipes: PipesUtils & { 334 + /** 335 + * The current pipe. 336 + * 337 + * In Valibot, this represents a list of call expressions ("pipes") 338 + * being assembled to form a schema definition. 339 + * 340 + * Each pipe can be extended, modified, or replaced to customize 341 + * the resulting schema. 342 + */ 343 + current: Pipes; 344 + }; 345 + /** 346 + * The plugin instance. 347 + */ 336 348 plugin: ValibotPlugin['Instance']; 337 - }; 349 + /** 350 + * Provides access to commonly used symbols within the plugin. 351 + */ 352 + symbols: { 353 + v: Symbol; 354 + }; 355 + } 356 + 357 + export interface NumberResolverContext extends BaseResolverContext { 358 + /** 359 + * Nodes used to build different parts of the number schema. 360 + */ 361 + nodes: { 362 + base: (ctx: NumberResolverContext) => PipeResult; 363 + const: (ctx: NumberResolverContext) => PipeResult | undefined; 364 + max: (ctx: NumberResolverContext) => PipeResult | undefined; 365 + min: (ctx: NumberResolverContext) => PipeResult | undefined; 366 + }; 367 + schema: SchemaWithType<'integer' | 'number'>; 368 + /** 369 + * Utility functions for number schema processing. 370 + */ 371 + utils: { 372 + getIntegerLimit: GetIntegerLimit; 373 + maybeBigInt: MaybeBigInt; 374 + shouldCoerceToBigInt: ShouldCoerceToBigInt; 375 + }; 376 + } 338 377 339 - export type FormatResolverArgs = SharedResolverArgs & { 340 - schema: IR.SchemaObject; 341 - }; 378 + export interface ObjectResolverContext extends BaseResolverContext { 379 + /** 380 + * Nodes used to build different parts of the object schema. 381 + */ 382 + nodes: { 383 + /** 384 + * If `additionalProperties` is `false` or `{ type: 'never' }`, returns `null` 385 + * to indicate no additional properties are allowed. 386 + */ 387 + additionalProperties: ( 388 + ctx: ObjectResolverContext, 389 + ) => Pipe | null | undefined; 390 + base: (ctx: ObjectResolverContext) => PipeResult; 391 + shape: (ctx: ObjectResolverContext) => ReturnType<typeof $.object>; 392 + }; 393 + schema: SchemaWithType<'object'>; 394 + /** 395 + * Utility functions for object schema processing. 396 + */ 397 + utils: { 398 + ast: Partial<Omit<Ast, 'typeName'>>; 399 + state: Refs<PluginState>; 400 + }; 401 + } 342 402 343 - export type ObjectBaseResolverArgs = SharedResolverArgs & { 344 - /** Null = never */ 345 - additional?: ReturnType<typeof $.call | typeof $.expr> | null; 346 - schema: IR.SchemaObject; 347 - shape: ReturnType<typeof $.object>; 348 - }; 403 + export interface StringResolverContext extends BaseResolverContext { 404 + /** 405 + * Nodes used to build different parts of the string schema. 406 + */ 407 + nodes: { 408 + base: (ctx: StringResolverContext) => PipeResult; 409 + const: (ctx: StringResolverContext) => PipeResult | undefined; 410 + format: (ctx: StringResolverContext) => PipeResult | undefined; 411 + length: (ctx: StringResolverContext) => PipeResult | undefined; 412 + maxLength: (ctx: StringResolverContext) => PipeResult | undefined; 413 + minLength: (ctx: StringResolverContext) => PipeResult | undefined; 414 + pattern: (ctx: StringResolverContext) => PipeResult | undefined; 415 + }; 416 + schema: SchemaWithType<'string'>; 417 + } 349 418 350 - export type ValidatorResolverArgs = SharedResolverArgs & { 419 + export interface ValidatorResolverContext extends BaseResolverContext { 351 420 operation: IR.Operation; 352 - schema: Symbol; 353 - v: Symbol; 354 - }; 421 + /** 422 + * Provides access to commonly used symbols within the plugin. 423 + */ 424 + symbols: BaseResolverContext['symbols'] & { 425 + schema: Symbol; 426 + }; 427 + } 355 428 356 429 type ValidatorResolver = ( 357 - args: ValidatorResolverArgs, 358 - ) => MaybeArray<TsDsl<ts.Statement>> | null | undefined; 430 + ctx: ValidatorResolverContext, 431 + ) => PipeResult | null | undefined; 359 432 360 433 type Resolvers = Plugin.Resolvers<{ 361 434 /** 362 - * Resolvers for object schemas. 435 + * Resolver for number schemas. 363 436 * 364 - * Allows customization of how object types are rendered. 437 + * Allows customization of how number types are rendered. 365 438 * 366 - * Example path: `~resolvers.object.base` 439 + * Returning `undefined` will execute the default resolver logic. 440 + */ 441 + number?: (ctx: NumberResolverContext) => PipeResult | undefined; 442 + /** 443 + * Resolver for object schemas. 367 444 * 368 - * Returning `undefined` from a resolver will apply the default 369 - * generation behavior for the object schema. 445 + * Allows customization of how object types are rendered. 446 + * 447 + * Returning `undefined` will execute the default resolver logic. 370 448 */ 371 - object?: { 372 - /** 373 - * Controls how object schemas are constructed. 374 - * 375 - * Called with the fully assembled shape (properties) and any additional 376 - * property schema, allowing the resolver to choose the correct Valibot 377 - * base constructor and modify the schema chain if needed. 378 - * 379 - * Returning `undefined` will execute the default resolver logic. 380 - */ 381 - base?: ( 382 - args: ObjectBaseResolverArgs, 383 - ) => ReturnType<typeof $.call> | undefined; 384 - }; 449 + object?: (ctx: ObjectResolverContext) => PipeResult | undefined; 385 450 /** 386 - * Resolvers for string schemas. 451 + * Resolver for string schemas. 452 + * 453 + * Allows customization of how string types are rendered. 387 454 * 388 - * Allows customization of how string types are rendered, including 389 - * per-format handling. 455 + * Returning `undefined` will execute the default resolver logic. 390 456 */ 391 - string?: { 392 - /** 393 - * Resolvers for string formats (e.g., `uuid`, `email`, `date-time`). 394 - * 395 - * Each key represents a specific format name with a custom 396 - * resolver function that controls how that format is rendered. 397 - * 398 - * Example path: `~resolvers.string.formats.uuid` 399 - * 400 - * Returning `undefined` from a resolver will apply the default 401 - * generation behavior for that format. 402 - */ 403 - formats?: Record< 404 - string, 405 - (args: FormatResolverArgs) => boolean | number | undefined 406 - >; 407 - }; 457 + string?: (ctx: StringResolverContext) => PipeResult | undefined; 408 458 /** 409 459 * Resolvers for request and response validators. 410 460 * ··· 412 462 * 413 463 * Example path: `~resolvers.validator.request` or `~resolvers.validator.response` 414 464 * 415 - * Returning `undefined` from a resolver will apply the default generation logic. 465 + * Returning `undefined` will execute the default resolver logic. 416 466 */ 417 467 validator?: 418 468 | ValidatorResolver ··· 420 470 /** 421 471 * Controls how the request validator function body is generated. 422 472 * 423 - * Returning `undefined` will fall back to the default `.await().return()` logic. 473 + * Returning `undefined` will execute the default resolver logic. 424 474 */ 425 475 request?: ValidatorResolver; 426 476 /** 427 477 * Controls how the response validator function body is generated. 428 478 * 429 - * Returning `undefined` will fall back to the default `.await().return()` logic. 479 + * Returning `undefined` will execute the default resolver logic. 430 480 */ 431 481 response?: ValidatorResolver; 432 482 };
+34 -26
packages/openapi-ts/src/plugins/valibot/v1/api.ts
··· 1 1 import { $ } from '~/ts-dsl'; 2 2 3 + import { pipes } from '../shared/pipes'; 3 4 import type { ValidatorArgs } from '../shared/types'; 4 - import type { ValidatorResolverArgs } from '../types'; 5 + import type { ValidatorResolverContext } from '../types'; 5 6 import { identifiers } from './constants'; 6 7 7 - const defaultValidatorResolver = ({ 8 - schema, 9 - v, 10 - }: ValidatorResolverArgs): ReturnType<typeof $.return> => 11 - $(v).attr(identifiers.async.parseAsync).call(schema, 'data').await().return(); 8 + const validatorResolver = ( 9 + ctx: ValidatorResolverContext, 10 + ): ReturnType<typeof $.return> => { 11 + const { schema, v } = ctx.symbols; 12 + return $(v) 13 + .attr(identifiers.async.parseAsync) 14 + .call(schema, 'data') 15 + .await() 16 + .return(); 17 + }; 12 18 13 19 export const createRequestValidatorV1 = ({ 14 20 operation, ··· 23 29 }); 24 30 if (!symbol) return; 25 31 26 - const v = plugin.referenceSymbol({ 27 - category: 'external', 28 - resource: 'valibot.v', 29 - }); 30 - const args: ValidatorResolverArgs = { 32 + const ctx: ValidatorResolverContext = { 31 33 $, 32 34 operation, 33 - pipes: [], 35 + pipes: { 36 + ...pipes, 37 + current: [], 38 + }, 34 39 plugin, 35 - schema: symbol, 36 - v, 40 + symbols: { 41 + schema: symbol, 42 + v: plugin.external('valibot.v'), 43 + }, 37 44 }; 38 45 const validator = plugin.config['~resolvers']?.validator; 39 46 const resolver = 40 47 typeof validator === 'function' ? validator : validator?.request; 41 - const candidates = [resolver, defaultValidatorResolver]; 48 + const candidates = [resolver, validatorResolver]; 42 49 for (const candidate of candidates) { 43 - const statements = candidate?.(args); 50 + const statements = candidate?.(ctx); 44 51 if (statements === null) return; 45 52 if (statements !== undefined) { 46 53 return $.func() ··· 65 72 }); 66 73 if (!symbol) return; 67 74 68 - const v = plugin.referenceSymbol({ 69 - category: 'external', 70 - resource: 'valibot.v', 71 - }); 72 - const args: ValidatorResolverArgs = { 75 + const ctx: ValidatorResolverContext = { 73 76 $, 74 77 operation, 75 - pipes: [], 78 + pipes: { 79 + ...pipes, 80 + current: [], 81 + }, 76 82 plugin, 77 - schema: symbol, 78 - v, 83 + symbols: { 84 + schema: symbol, 85 + v: plugin.external('valibot.v'), 86 + }, 79 87 }; 80 88 const validator = plugin.config['~resolvers']?.validator; 81 89 const resolver = 82 90 typeof validator === 'function' ? validator : validator?.response; 83 - const candidates = [resolver, defaultValidatorResolver]; 91 + const candidates = [resolver, validatorResolver]; 84 92 for (const candidate of candidates) { 85 - const statements = candidate?.(args); 93 + const statements = candidate?.(ctx); 86 94 if (statements === null) return; 87 95 if (statements !== undefined) { 88 96 return $.func()
+11 -12
packages/openapi-ts/src/plugins/valibot/v1/plugin.ts
··· 5 5 import type { IR } from '~/ir/types'; 6 6 import { buildName } from '~/openApi/shared/utils/name'; 7 7 import type { SchemaWithType } from '~/plugins'; 8 + import { maybeBigInt } from '~/plugins/shared/utils/coerce'; 8 9 import { $ } from '~/ts-dsl'; 9 10 import { pathToJsonPointer, refToName } from '~/utils/ref'; 10 11 11 12 import { exportAst } from '../shared/export'; 12 - import { numberParameter } from '../shared/numbers'; 13 13 import { irOperationToAst } from '../shared/operation'; 14 - import { pipesToAst } from '../shared/pipesToAst'; 14 + import { pipesToNode } from '../shared/pipes'; 15 15 import type { Ast, IrSchemaToAstOptions, PluginState } from '../shared/types'; 16 16 import { irWebhookToAst } from '../shared/webhook'; 17 17 import type { ValibotPlugin } from '../types'; ··· 87 87 path: ref([...fromRef(state.path), 'items', index]), 88 88 }, 89 89 }); 90 - return pipesToAst({ pipes: itemAst.pipes, plugin }); 90 + return pipesToNode(itemAst.pipes, plugin); 91 91 }); 92 92 93 93 if (schema.logicalOperator === 'and') { ··· 124 124 ast.pipes.push(readonlyExpression); 125 125 } 126 126 127 - let callParameter: ReturnType<typeof $.fromValue> | undefined; 128 - 129 127 if (schema.default !== undefined) { 130 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 131 - callParameter = numberParameter({ isBigInt, value: schema.default }); 132 128 ast.pipes = [ 133 129 $(v) 134 130 .attr(identifiers.schemas.optional) 135 - .call(pipesToAst({ pipes: ast.pipes, plugin }), callParameter), 131 + .call( 132 + pipesToNode(ast.pipes, plugin), 133 + schema.type === 'integer' || schema.type === 'number' 134 + ? maybeBigInt(schema.default, schema.format) 135 + : $.fromValue(schema.default), 136 + ), 136 137 ]; 137 - } 138 - 139 - if (optional && !callParameter) { 138 + } else if (optional) { 140 139 ast.pipes = [ 141 140 $(v) 142 141 .attr(identifiers.schemas.optional) 143 - .call(pipesToAst({ pipes: ast.pipes, plugin })), 142 + .call(pipesToNode(ast.pipes, plugin)), 144 143 ]; 145 144 } 146 145 }
+2 -2
packages/openapi-ts/src/plugins/valibot/v1/toAst/array.ts
··· 4 4 import type { SchemaWithType } from '~/plugins'; 5 5 import { $ } from '~/ts-dsl'; 6 6 7 - import { pipesToAst } from '../../shared/pipesToAst'; 7 + import { pipesToNode } from '../../shared/pipes'; 8 8 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 9 9 import { identifiers } from '../constants'; 10 10 import { irSchemaToAst } from '../plugin'; ··· 54 54 if (itemAst.hasLazyExpression) { 55 55 result.hasLazyExpression = true; 56 56 } 57 - return pipesToAst({ pipes: itemAst.pipes, plugin }); 57 + return pipesToNode(itemAst.pipes, plugin); 58 58 }); 59 59 60 60 if (itemExpressions.length === 1) {
+3 -3
packages/openapi-ts/src/plugins/valibot/v1/toAst/boolean.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 2 import { $ } from '~/ts-dsl'; 3 3 4 - import { pipesToAst } from '../../shared/pipesToAst'; 4 + import { pipesToNode } from '../../shared/pipes'; 5 5 import type { IrSchemaToAstOptions } from '../../shared/types'; 6 6 import { identifiers } from '../constants'; 7 7 ··· 22 22 pipes.push( 23 23 $(v).attr(identifiers.schemas.literal).call($.literal(schema.const)), 24 24 ); 25 - return pipesToAst({ pipes, plugin }); 25 + return pipesToNode(pipes, plugin); 26 26 } 27 27 28 28 pipes.push($(v).attr(identifiers.schemas.boolean).call()); 29 - return pipesToAst({ pipes, plugin }); 29 + return pipesToNode(pipes, plugin); 30 30 };
+26 -29
packages/openapi-ts/src/plugins/valibot/v1/toAst/index.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { shouldCoerceToBigInt } from '~/plugins/shared/utils/coerce'; 2 3 import type { $ } from '~/ts-dsl'; 3 4 4 - import { pipesToAst } from '../../shared/pipesToAst'; 5 + import { pipesToNode } from '../../shared/pipes'; 5 6 import type { IrSchemaToAstOptions } from '../../shared/types'; 6 7 import { arrayToAst } from './array'; 7 8 import { booleanToAst } from './boolean'; 8 9 import { enumToAst } from './enum'; 9 10 import { neverToAst } from './never'; 10 11 import { nullToAst } from './null'; 11 - import { numberToAst } from './number'; 12 + import { numberToNode } from './number'; 12 13 import { objectToAst } from './object'; 13 - import { stringToAst } from './string'; 14 + import { stringToNode } from './string'; 14 15 import { tupleToAst } from './tuple'; 15 16 import { undefinedToAst } from './undefined'; 16 17 import { unknownToAst } from './unknown'; ··· 28 29 switch (schema.type) { 29 30 case 'array': 30 31 return { 31 - expression: pipesToAst({ 32 - pipes: arrayToAst({ 32 + expression: pipesToNode( 33 + arrayToAst({ 33 34 ...args, 34 35 schema: schema as SchemaWithType<'array'>, 35 36 }).pipes, 36 - plugin: args.plugin, 37 - }), 37 + args.plugin, 38 + ), 38 39 }; 39 40 case 'boolean': 40 41 return { ··· 53 54 case 'integer': 54 55 case 'number': 55 56 return { 56 - expression: numberToAst({ 57 + expression: numberToNode({ 57 58 ...args, 58 59 schema: schema as SchemaWithType<'integer' | 'number'>, 59 60 }), ··· 74 75 }; 75 76 case 'object': 76 77 return { 77 - expression: pipesToAst({ 78 - pipes: objectToAst({ 78 + expression: pipesToNode( 79 + objectToAst({ 79 80 ...args, 80 81 schema: schema as SchemaWithType<'object'>, 81 82 }).pipes, 82 - plugin: args.plugin, 83 - }), 83 + args.plugin, 84 + ), 84 85 }; 85 86 case 'string': 86 - // For string schemas with int64/uint64 formats, use number handler to generate union with transform 87 - if (schema.format === 'int64' || schema.format === 'uint64') { 88 - return { 89 - expression: numberToAst({ 90 - ...args, 91 - schema: schema as SchemaWithType<'integer' | 'number'>, 92 - }), 93 - }; 94 - } 95 87 return { 96 - expression: stringToAst({ 97 - ...args, 98 - schema: schema as SchemaWithType<'string'>, 99 - }), 88 + expression: shouldCoerceToBigInt(schema.format) 89 + ? numberToNode({ 90 + ...args, 91 + schema: { ...schema, type: 'number' }, 92 + }) 93 + : stringToNode({ 94 + ...args, 95 + schema: schema as SchemaWithType<'string'>, 96 + }), 100 97 }; 101 98 case 'tuple': 102 99 return { 103 - expression: pipesToAst({ 104 - pipes: tupleToAst({ 100 + expression: pipesToNode( 101 + tupleToAst({ 105 102 ...args, 106 103 schema: schema as SchemaWithType<'tuple'>, 107 104 }).pipes, 108 - plugin: args.plugin, 109 - }), 105 + args.plugin, 106 + ), 110 107 }; 111 108 case 'undefined': 112 109 return {
+126 -134
packages/openapi-ts/src/plugins/valibot/v1/toAst/number.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { 3 + maybeBigInt, 4 + shouldCoerceToBigInt, 5 + } from '~/plugins/shared/utils/coerce'; 6 + import { getIntegerLimit } from '~/plugins/shared/utils/formats'; 2 7 import { $ } from '~/ts-dsl'; 3 8 4 - import { 5 - INTEGER_FORMATS, 6 - isIntegerFormat, 7 - needsBigIntForFormat, 8 - numberParameter, 9 - } from '../../shared/numbers'; 10 - import { pipesToAst } from '../../shared/pipesToAst'; 9 + import type { Pipe, PipeResult, Pipes } from '../../shared/pipes'; 10 + import { pipes } from '../../shared/pipes'; 11 11 import type { IrSchemaToAstOptions } from '../../shared/types'; 12 + import type { NumberResolverContext } from '../../types'; 12 13 import { identifiers } from '../constants'; 13 14 14 - export const numberToAst = ({ 15 - plugin, 16 - schema, 17 - }: IrSchemaToAstOptions & { 18 - schema: SchemaWithType<'integer' | 'number'>; 19 - }) => { 20 - const format = schema.format; 21 - const isInteger = schema.type === 'integer'; 22 - const isBigInt = needsBigIntForFormat(format); 23 - const formatInfo = isIntegerFormat(format) ? INTEGER_FORMATS[format] : null; 24 - 25 - const v = plugin.referenceSymbol({ 26 - category: 'external', 27 - resource: 'valibot.v', 28 - }); 29 - 30 - // Return early if const is defined since we can create a literal type directly without additional validation 31 - if (schema.const !== undefined && schema.const !== null) { 32 - const constValue = schema.const; 33 - let literalValue: ReturnType<typeof $.fromValue>; 34 - 35 - // Case 1: Number with no format -> generate literal with the number 36 - if (typeof constValue === 'number' && !format) { 37 - literalValue = $.literal(constValue); 38 - } 39 - // Case 2: Number with format -> check if format needs BigInt, generate appropriate literal 40 - else if (typeof constValue === 'number' && format) { 41 - if (isBigInt) { 42 - // Format requires BigInt, convert number to BigInt 43 - literalValue = $('BigInt').call($.literal(constValue)); 44 - } else { 45 - // Regular format, use number as-is 46 - literalValue = $.literal(constValue); 47 - } 48 - } 49 - // Case 3: Format that allows string -> generate BigInt literal (for int64/uint64 formats) 50 - else if (typeof constValue === 'string' && isBigInt) { 51 - // Remove 'n' suffix if present in string 52 - const cleanString = constValue.endsWith('n') 53 - ? constValue.slice(0, -1) 54 - : constValue; 55 - literalValue = $('BigInt').call($.literal(cleanString)); 56 - } 57 - // Case 4: Const is typeof bigint (literal) -> transform from literal to BigInt() 58 - else if (typeof constValue === 'bigint') { 59 - // Convert BigInt to string and remove 'n' suffix that toString() adds 60 - const bigintString = constValue.toString(); 61 - const cleanString = bigintString.endsWith('n') 62 - ? bigintString.slice(0, -1) 63 - : bigintString; 64 - literalValue = $('BigInt').call($.literal(cleanString)); 65 - } 66 - // Default case: use value as-is for other types 67 - else { 68 - literalValue = $.fromValue(constValue); 69 - } 70 - 71 - return $(v).attr(identifiers.schemas.literal).call(literalValue); 72 - } 73 - 74 - const pipes: Array<ReturnType<typeof $.call>> = []; 75 - 76 - // For bigint formats (int64, uint64), create union of number, string, and bigint with transform 77 - if (isBigInt) { 78 - const unionExpression = $(v) 79 - .attr(identifiers.schemas.union) 80 - .call( 81 - $.array( 82 - $(v).attr(identifiers.schemas.number).call(), 83 - $(v).attr(identifiers.schemas.string).call(), 84 - $(v).attr(identifiers.schemas.bigInt).call(), 15 + function baseNode(ctx: NumberResolverContext): PipeResult { 16 + const { schema, symbols } = ctx; 17 + const { v } = symbols; 18 + if (ctx.utils.shouldCoerceToBigInt(schema.format)) { 19 + return [ 20 + $(v) 21 + .attr(identifiers.schemas.union) 22 + .call( 23 + $.array( 24 + $(v).attr(identifiers.schemas.number).call(), 25 + $(v).attr(identifiers.schemas.string).call(), 26 + $(v).attr(identifiers.schemas.bigInt).call(), 27 + ), 85 28 ), 86 - ); 87 - pipes.push(unionExpression); 88 - 89 - // Add transform to convert to BigInt 90 - const transformExpression = $(v) 91 - .attr(identifiers.actions.transform) 92 - .call($.func().param('x').do($('BigInt').call('x').return())); 93 - pipes.push(transformExpression); 94 - } else { 95 - // For regular number formats, use number schema 96 - const expression = $(v).attr(identifiers.schemas.number).call(); 97 - pipes.push(expression); 29 + $(v) 30 + .attr(identifiers.actions.transform) 31 + .call($.func().param('x').do($('BigInt').call('x').return())), 32 + ]; 98 33 } 99 - 100 - // Add integer validation for integer types (except when using bigint union) 101 - if (!isBigInt && isInteger) { 102 - const expression = $(v).attr(identifiers.actions.integer).call(); 103 - pipes.push(expression); 34 + const pipes: Pipes = []; 35 + pipes.push($(v).attr(identifiers.schemas.number).call()); 36 + if (schema.type === 'integer') { 37 + pipes.push($(v).attr(identifiers.actions.integer).call()); 104 38 } 105 - 106 - // Add format-specific range validations 107 - if (formatInfo) { 108 - const minValue = formatInfo.min; 109 - const maxValue = formatInfo.max; 110 - const minErrorMessage = formatInfo.minError; 111 - const maxErrorMessage = formatInfo.maxError; 39 + return pipes; 40 + } 112 41 113 - // Add minimum value validation 114 - const minExpression = $(v) 115 - .attr(identifiers.actions.minValue) 116 - .call( 117 - isBigInt ? $('BigInt').call($.literal(minValue)) : $.literal(minValue), 118 - $.literal(minErrorMessage), 119 - ); 120 - pipes.push(minExpression); 42 + function constNode(ctx: NumberResolverContext): PipeResult | undefined { 43 + const { schema, symbols } = ctx; 44 + const { v } = symbols; 45 + if (schema.const === undefined) return; 46 + return $(v) 47 + .attr(identifiers.schemas.literal) 48 + .call(ctx.utils.maybeBigInt(schema.const, schema.format)); 49 + } 121 50 122 - // Add maximum value validation 123 - const maxExpression = $(v) 51 + function maxNode(ctx: NumberResolverContext): PipeResult | undefined { 52 + const { schema, symbols } = ctx; 53 + const { v } = symbols; 54 + if (schema.exclusiveMaximum !== undefined) { 55 + return $(v) 56 + .attr(identifiers.actions.ltValue) 57 + .call(ctx.utils.maybeBigInt(schema.exclusiveMaximum, schema.format)); 58 + } 59 + if (schema.maximum !== undefined) { 60 + return $(v) 61 + .attr(identifiers.actions.maxValue) 62 + .call(ctx.utils.maybeBigInt(schema.maximum, schema.format)); 63 + } 64 + const limit = ctx.utils.getIntegerLimit(schema.format); 65 + if (limit) { 66 + return $(v) 124 67 .attr(identifiers.actions.maxValue) 125 68 .call( 126 - isBigInt ? $('BigInt').call($.literal(maxValue)) : $.literal(maxValue), 127 - $.literal(maxErrorMessage), 69 + ctx.utils.maybeBigInt(limit.maxValue, schema.format), 70 + $.literal(limit.maxError), 128 71 ); 129 - pipes.push(maxExpression); 130 72 } 73 + return; 74 + } 131 75 76 + function minNode(ctx: NumberResolverContext): PipeResult | undefined { 77 + const { schema, symbols } = ctx; 78 + const { v } = symbols; 132 79 if (schema.exclusiveMinimum !== undefined) { 133 - const expression = $(v) 80 + return $(v) 134 81 .attr(identifiers.actions.gtValue) 135 - .call(numberParameter({ isBigInt, value: schema.exclusiveMinimum })); 136 - pipes.push(expression); 137 - } else if (schema.minimum !== undefined) { 138 - const expression = $(v) 82 + .call(ctx.utils.maybeBigInt(schema.exclusiveMinimum, schema.format)); 83 + } 84 + if (schema.minimum !== undefined) { 85 + return $(v) 139 86 .attr(identifiers.actions.minValue) 140 - .call(numberParameter({ isBigInt, value: schema.minimum })); 141 - pipes.push(expression); 87 + .call(ctx.utils.maybeBigInt(schema.minimum, schema.format)); 142 88 } 143 - 144 - if (schema.exclusiveMaximum !== undefined) { 145 - const expression = $(v) 146 - .attr(identifiers.actions.ltValue) 147 - .call(numberParameter({ isBigInt, value: schema.exclusiveMaximum })); 148 - pipes.push(expression); 149 - } else if (schema.maximum !== undefined) { 150 - const expression = $(v) 151 - .attr(identifiers.actions.maxValue) 152 - .call(numberParameter({ isBigInt, value: schema.maximum })); 153 - pipes.push(expression); 89 + const limit = ctx.utils.getIntegerLimit(schema.format); 90 + if (limit) { 91 + return $(v) 92 + .attr(identifiers.actions.minValue) 93 + .call( 94 + ctx.utils.maybeBigInt(limit.minValue, schema.format), 95 + $.literal(limit.minError), 96 + ); 154 97 } 98 + return; 99 + } 155 100 156 - return pipesToAst({ pipes, plugin }); 101 + function numberResolver(ctx: NumberResolverContext): Pipes { 102 + const constNode = ctx.nodes.const(ctx); 103 + if (constNode) return ctx.pipes.push(ctx.pipes.current, constNode); 104 + 105 + const baseNode = ctx.nodes.base(ctx); 106 + if (baseNode) ctx.pipes.push(ctx.pipes.current, baseNode); 107 + 108 + const minNode = ctx.nodes.min(ctx); 109 + if (minNode) ctx.pipes.push(ctx.pipes.current, minNode); 110 + 111 + const maxNode = ctx.nodes.max(ctx); 112 + if (maxNode) ctx.pipes.push(ctx.pipes.current, maxNode); 113 + 114 + return ctx.pipes.current; 115 + } 116 + 117 + export const numberToNode = ({ 118 + plugin, 119 + schema, 120 + }: IrSchemaToAstOptions & { 121 + schema: SchemaWithType<'integer' | 'number'>; 122 + }): Pipe => { 123 + const ctx: NumberResolverContext = { 124 + $, 125 + nodes: { 126 + base: baseNode, 127 + const: constNode, 128 + max: maxNode, 129 + min: minNode, 130 + }, 131 + pipes: { 132 + ...pipes, 133 + current: [], 134 + }, 135 + plugin, 136 + schema, 137 + symbols: { 138 + v: plugin.external('valibot.v'), 139 + }, 140 + utils: { 141 + getIntegerLimit, 142 + maybeBigInt, 143 + shouldCoerceToBigInt, 144 + }, 145 + }; 146 + const resolver = plugin.config['~resolvers']?.number; 147 + const node = resolver?.(ctx) ?? numberResolver(ctx); 148 + return ctx.pipes.toNode(node, plugin); 157 149 };
+76 -69
packages/openapi-ts/src/plugins/valibot/v1/toAst/object.ts
··· 3 3 import type { SchemaWithType } from '~/plugins'; 4 4 import { $ } from '~/ts-dsl'; 5 5 6 - import { pipesToAst } from '../../shared/pipesToAst'; 6 + import type { Pipe, PipeResult } from '../../shared/pipes'; 7 + import { pipes } from '../../shared/pipes'; 7 8 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 8 - import type { ObjectBaseResolverArgs } from '../../types'; 9 + import type { ObjectResolverContext } from '../../types'; 9 10 import { identifiers } from '../constants'; 10 11 import { irSchemaToAst } from '../plugin'; 11 12 12 - function defaultObjectBaseResolver({ 13 - additional, 14 - pipes, 15 - plugin, 16 - shape, 17 - }: ObjectBaseResolverArgs): number { 18 - const v = plugin.referenceSymbol({ 19 - category: 'external', 20 - resource: 'valibot.v', 13 + function additionalPropertiesNode( 14 + ctx: ObjectResolverContext, 15 + ): Pipe | null | undefined { 16 + const { plugin, schema } = ctx; 17 + 18 + if (!schema.additionalProperties || !schema.additionalProperties.type) return; 19 + if (schema.additionalProperties.type === 'never') return null; 20 + 21 + const additionalAst = irSchemaToAst({ 22 + plugin, 23 + schema: schema.additionalProperties, 24 + state: { 25 + ...ctx.utils.state, 26 + path: ref([...fromRef(ctx.utils.state.path), 'additionalProperties']), 27 + }, 21 28 }); 29 + if (additionalAst.hasLazyExpression) ctx.utils.ast.hasLazyExpression = true; 30 + return pipes.toNode(additionalAst.pipes, plugin); 31 + } 22 32 23 - // Handle `additionalProperties: { type: 'never' }` โ†’ v.strictObject() 33 + function baseNode(ctx: ObjectResolverContext): PipeResult { 34 + const { nodes, symbols } = ctx; 35 + const { v } = symbols; 36 + 37 + const additional = nodes.additionalProperties(ctx); 38 + const shape = nodes.shape(ctx); 39 + 24 40 if (additional === null) { 25 - return pipes.push($(v).attr(identifiers.schemas.strictObject).call(shape)); 41 + return $(v).attr(identifiers.schemas.strictObject).call(shape); 26 42 } 27 43 28 - // Handle additionalProperties as schema โ†’ v.record() or v.objectWithRest() 29 44 if (additional) { 30 45 if (shape.isEmpty) { 31 - return pipes.push( 32 - $(v) 33 - .attr(identifiers.schemas.record) 34 - .call($(v).attr(identifiers.schemas.string).call(), additional), 35 - ); 46 + return $(v) 47 + .attr(identifiers.schemas.record) 48 + .call($(v).attr(identifiers.schemas.string).call(), additional); 36 49 } 37 50 38 - // If there are named properties, use v.objectWithRest() to validate both 39 - return pipes.push( 40 - $(v).attr(identifiers.schemas.objectWithRest).call(shape, additional), 41 - ); 51 + return $(v) 52 + .attr(identifiers.schemas.objectWithRest) 53 + .call(shape, additional); 42 54 } 43 55 44 - // Default case โ†’ v.object() 45 - return pipes.push($(v).attr(identifiers.schemas.object).call(shape)); 56 + return $(v).attr(identifiers.schemas.object).call(shape); 46 57 } 47 58 48 - export const objectToAst = ({ 49 - plugin, 50 - schema, 51 - state, 52 - }: IrSchemaToAstOptions & { 53 - schema: SchemaWithType<'object'>; 54 - }): Omit<Ast, 'typeName'> => { 55 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 56 - const pipes: Array<ReturnType<typeof $.call>> = []; 57 - 59 + function objectResolver(ctx: ObjectResolverContext): PipeResult { 58 60 // TODO: parser - handle constants 61 + return ctx.nodes.base(ctx); 62 + } 59 63 64 + function shapeNode(ctx: ObjectResolverContext): ReturnType<typeof $.object> { 65 + const { plugin, schema } = ctx; 60 66 const shape = $.object().pretty(); 61 - const required = schema.required ?? []; 62 67 63 68 for (const name in schema.properties) { 64 69 const property = schema.properties[name]!; 65 - const isRequired = required.includes(name); 66 70 67 71 const propertyAst = irSchemaToAst({ 68 - optional: !isRequired, 72 + optional: !schema.required?.includes(name), 69 73 plugin, 70 74 schema: property, 71 75 state: { 72 - ...state, 73 - path: ref([...fromRef(state.path), 'properties', name]), 76 + ...ctx.utils.state, 77 + path: ref([...fromRef(ctx.utils.state.path), 'properties', name]), 74 78 }, 75 79 }); 76 - if (propertyAst.hasLazyExpression) result.hasLazyExpression = true; 77 - 78 - shape.prop(name, pipesToAst({ pipes: propertyAst.pipes, plugin })); 80 + if (propertyAst.hasLazyExpression) ctx.utils.ast.hasLazyExpression = true; 81 + shape.prop(name, pipes.toNode(propertyAst.pipes, plugin)); 79 82 } 80 83 81 - let additional: ReturnType<typeof $.call | typeof $.expr> | null | undefined; 82 - if (schema.additionalProperties && schema.additionalProperties.type) { 83 - if (schema.additionalProperties.type === 'never') { 84 - additional = null; 85 - } else { 86 - const additionalAst = irSchemaToAst({ 87 - plugin, 88 - schema: schema.additionalProperties, 89 - state: { 90 - ...state, 91 - path: ref([...fromRef(state.path), 'additionalProperties']), 92 - }, 93 - }); 94 - if (additionalAst.hasLazyExpression) result.hasLazyExpression = true; 95 - additional = pipesToAst({ pipes: additionalAst.pipes, plugin }); 96 - } 97 - } 84 + return shape; 85 + } 98 86 99 - const args: ObjectBaseResolverArgs = { 87 + export const objectToAst = ({ 88 + plugin, 89 + schema, 90 + state, 91 + }: IrSchemaToAstOptions & { 92 + schema: SchemaWithType<'object'>; 93 + }): Omit<Ast, 'typeName'> => { 94 + const ctx: ObjectResolverContext = { 100 95 $, 101 - additional, 102 - pipes, 96 + nodes: { 97 + additionalProperties: additionalPropertiesNode, 98 + base: baseNode, 99 + shape: shapeNode, 100 + }, 101 + pipes: { 102 + ...pipes, 103 + current: [], 104 + }, 103 105 plugin, 104 106 schema, 105 - shape, 107 + symbols: { 108 + v: plugin.external('valibot.v'), 109 + }, 110 + utils: { 111 + ast: {}, 112 + state, 113 + }, 106 114 }; 107 - const resolver = plugin.config['~resolvers']?.object?.base; 108 - if (!resolver?.(args)) defaultObjectBaseResolver(args); 109 - 110 - result.pipes = [pipesToAst({ pipes, plugin })]; 111 - return result as Omit<Ast, 'typeName'>; 115 + const resolver = plugin.config['~resolvers']?.object; 116 + const node = resolver?.(ctx) ?? objectResolver(ctx); 117 + ctx.utils.ast.pipes = [ctx.pipes.toNode(node, plugin)]; 118 + return ctx.utils.ast as Omit<Ast, 'typeName'>; 112 119 };
+108 -68
packages/openapi-ts/src/plugins/valibot/v1/toAst/string.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 2 import { $ } from '~/ts-dsl'; 3 3 4 - import { pipesToAst } from '../../shared/pipesToAst'; 4 + import type { Pipe, PipeResult, Pipes } from '../../shared/pipes'; 5 + import { pipes } from '../../shared/pipes'; 5 6 import type { IrSchemaToAstOptions } from '../../shared/types'; 6 - import type { FormatResolverArgs } from '../../types'; 7 + import type { StringResolverContext } from '../../types'; 7 8 import { identifiers } from '../constants'; 8 9 9 - const defaultFormatResolver = ({ 10 - pipes, 11 - plugin, 12 - schema, 13 - }: FormatResolverArgs): boolean | number => { 14 - const v = plugin.referenceSymbol({ 15 - category: 'external', 16 - resource: 'valibot.v', 17 - }); 10 + function baseNode(ctx: StringResolverContext): PipeResult { 11 + const { v } = ctx.symbols; 12 + return $(v).attr(identifiers.schemas.string).call(); 13 + } 18 14 15 + function constNode(ctx: StringResolverContext): PipeResult | undefined { 16 + const { schema, symbols } = ctx; 17 + const { v } = symbols; 18 + if (typeof schema.const !== 'string') return; 19 + return $(v).attr(identifiers.schemas.literal).call($.literal(schema.const)); 20 + } 21 + 22 + function formatNode(ctx: StringResolverContext): PipeResult | undefined { 23 + const { schema, symbols } = ctx; 24 + const { v } = symbols; 19 25 switch (schema.format) { 20 26 case 'date': 21 - return pipes.push($(v).attr(identifiers.actions.isoDate).call()); 27 + return $(v).attr(identifiers.actions.isoDate).call(); 22 28 case 'date-time': 23 - return pipes.push($(v).attr(identifiers.actions.isoTimestamp).call()); 29 + return $(v).attr(identifiers.actions.isoTimestamp).call(); 24 30 case 'email': 25 - return pipes.push($(v).attr(identifiers.actions.email).call()); 31 + return $(v).attr(identifiers.actions.email).call(); 26 32 case 'ipv4': 27 33 case 'ipv6': 28 - return pipes.push($(v).attr(identifiers.actions.ip).call()); 34 + return $(v).attr(identifiers.actions.ip).call(); 29 35 case 'time': 30 - return pipes.push($(v).attr(identifiers.actions.isoTimeSecond).call()); 36 + return $(v).attr(identifiers.actions.isoTimeSecond).call(); 31 37 case 'uri': 32 - return pipes.push($(v).attr(identifiers.actions.url).call()); 38 + return $(v).attr(identifiers.actions.url).call(); 33 39 case 'uuid': 34 - return pipes.push($(v).attr(identifiers.actions.uuid).call()); 40 + return $(v).attr(identifiers.actions.uuid).call(); 35 41 } 36 42 37 - return true; 38 - }; 43 + return; 44 + } 39 45 40 - export const stringToAst = ({ 41 - plugin, 42 - schema, 43 - }: IrSchemaToAstOptions & { 44 - schema: SchemaWithType<'string'>; 45 - }): ReturnType<typeof $.call | typeof $.expr> => { 46 - const pipes: Array<ReturnType<typeof $.call>> = []; 46 + function lengthNode(ctx: StringResolverContext): PipeResult | undefined { 47 + const { schema, symbols } = ctx; 48 + const { v } = symbols; 49 + if (schema.minLength === undefined || schema.minLength !== schema.maxLength) 50 + return; 51 + return $(v) 52 + .attr(identifiers.actions.length) 53 + .call($.literal(schema.minLength)); 54 + } 47 55 48 - const v = plugin.referenceSymbol({ 49 - category: 'external', 50 - resource: 'valibot.v', 51 - }); 56 + function maxLengthNode(ctx: StringResolverContext): PipeResult | undefined { 57 + const { schema, symbols } = ctx; 58 + const { v } = symbols; 59 + if (schema.maxLength === undefined) return; 60 + return $(v) 61 + .attr(identifiers.actions.maxLength) 62 + .call($.literal(schema.maxLength)); 63 + } 52 64 53 - if (typeof schema.const === 'string') { 54 - pipes.push( 55 - $(v).attr(identifiers.schemas.literal).call($.literal(schema.const)), 56 - ); 57 - return pipesToAst({ pipes, plugin }); 58 - } 65 + function minLengthNode(ctx: StringResolverContext): PipeResult | undefined { 66 + const { schema, symbols } = ctx; 67 + const { v } = symbols; 68 + if (schema.minLength === undefined) return; 69 + return $(v) 70 + .attr(identifiers.actions.minLength) 71 + .call($.literal(schema.minLength)); 72 + } 59 73 60 - pipes.push($(v).attr(identifiers.schemas.string).call()); 74 + function patternNode(ctx: StringResolverContext): PipeResult | undefined { 75 + const { schema, symbols } = ctx; 76 + const { v } = symbols; 77 + if (!schema.pattern) return; 78 + return $(v).attr(identifiers.actions.regex).call($.regexp(schema.pattern)); 79 + } 61 80 62 - if (schema.format) { 63 - const args: FormatResolverArgs = { $, pipes, plugin, schema }; 64 - const resolver = 65 - plugin.config['~resolvers']?.string?.formats?.[schema.format]; 66 - if (!resolver?.(args)) defaultFormatResolver(args); 67 - } 81 + function stringResolver(ctx: StringResolverContext): Pipes { 82 + const constNode = ctx.nodes.const(ctx); 83 + if (constNode) return ctx.pipes.push(ctx.pipes.current, constNode); 68 84 69 - if (schema.minLength === schema.maxLength && schema.minLength !== undefined) { 70 - pipes.push( 71 - $(v).attr(identifiers.actions.length).call($.literal(schema.minLength)), 72 - ); 85 + const baseNode = ctx.nodes.base(ctx); 86 + if (baseNode) ctx.pipes.push(ctx.pipes.current, baseNode); 87 + 88 + const formatNode = ctx.nodes.format(ctx); 89 + if (formatNode) ctx.pipes.push(ctx.pipes.current, formatNode); 90 + 91 + const lengthNode = ctx.nodes.length(ctx); 92 + if (lengthNode) { 93 + ctx.pipes.push(ctx.pipes.current, lengthNode); 73 94 } else { 74 - if (schema.minLength !== undefined) { 75 - pipes.push( 76 - $(v) 77 - .attr(identifiers.actions.minLength) 78 - .call($.literal(schema.minLength)), 79 - ); 80 - } 95 + const minLengthNode = ctx.nodes.minLength(ctx); 96 + if (minLengthNode) ctx.pipes.push(ctx.pipes.current, minLengthNode); 81 97 82 - if (schema.maxLength !== undefined) { 83 - pipes.push( 84 - $(v) 85 - .attr(identifiers.actions.maxLength) 86 - .call($.literal(schema.maxLength)), 87 - ); 88 - } 98 + const maxLengthNode = ctx.nodes.maxLength(ctx); 99 + if (maxLengthNode) ctx.pipes.push(ctx.pipes.current, maxLengthNode); 89 100 } 90 101 91 - if (schema.pattern) { 92 - pipes.push( 93 - $(v).attr(identifiers.actions.regex).call($.regexp(schema.pattern)), 94 - ); 95 - } 102 + const patternNode = ctx.nodes.pattern(ctx); 103 + if (patternNode) ctx.pipes.push(ctx.pipes.current, patternNode); 96 104 97 - return pipesToAst({ pipes, plugin }); 105 + return ctx.pipes.current; 106 + } 107 + 108 + export const stringToNode = ({ 109 + plugin, 110 + schema, 111 + }: IrSchemaToAstOptions & { 112 + schema: SchemaWithType<'string'>; 113 + }): Pipe => { 114 + const ctx: StringResolverContext = { 115 + $, 116 + nodes: { 117 + base: baseNode, 118 + const: constNode, 119 + format: formatNode, 120 + length: lengthNode, 121 + maxLength: maxLengthNode, 122 + minLength: minLengthNode, 123 + pattern: patternNode, 124 + }, 125 + pipes: { 126 + ...pipes, 127 + current: [], 128 + }, 129 + plugin, 130 + schema, 131 + symbols: { 132 + v: plugin.external('valibot.v'), 133 + }, 134 + }; 135 + const resolver = plugin.config['~resolvers']?.string; 136 + const node = resolver?.(ctx) ?? stringResolver(ctx); 137 + return ctx.pipes.toNode(node, plugin); 98 138 };
+2 -2
packages/openapi-ts/src/plugins/valibot/v1/toAst/tuple.ts
··· 3 3 import type { SchemaWithType } from '~/plugins'; 4 4 import { $ } from '~/ts-dsl'; 5 5 6 - import { pipesToAst } from '../../shared/pipesToAst'; 6 + import { pipesToNode } from '../../shared/pipes'; 7 7 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 8 8 import { identifiers } from '../constants'; 9 9 import { irSchemaToAst } from '../plugin'; ··· 48 48 if (schemaPipes.hasLazyExpression) { 49 49 result.hasLazyExpression = true; 50 50 } 51 - return pipesToAst({ pipes: schemaPipes.pipes, plugin }); 51 + return pipesToNode(schemaPipes.pipes, plugin); 52 52 }); 53 53 result.pipes = [ 54 54 $(v)
+2
packages/openapi-ts/src/plugins/zod/constants.ts
··· 32 32 lte: 'lte', 33 33 max: 'max', 34 34 maxLength: 'maxLength', 35 + maximum: 'maximum', // Zod Mini 35 36 min: 'min', 36 37 minLength: 'minLength', 38 + minimum: 'minimum', // Zod Mini 37 39 never: 'never', 38 40 null: 'null', 39 41 nullable: 'nullable',
+29 -15
packages/openapi-ts/src/plugins/zod/mini/api.ts
··· 2 2 3 3 import { identifiers } from '../constants'; 4 4 import type { ValidatorArgs } from '../shared/types'; 5 - import type { ValidatorResolverArgs } from '../types'; 5 + import type { ValidatorResolverContext } from '../types'; 6 6 7 - const defaultValidatorResolver = ({ 8 - schema, 9 - }: ValidatorResolverArgs): ReturnType<typeof $.return> => 10 - $(schema).attr(identifiers.parseAsync).call('data').await().return(); 7 + const validatorResolver = ( 8 + ctx: ValidatorResolverContext, 9 + ): ReturnType<typeof $.return> => { 10 + const { schema } = ctx.symbols; 11 + return $(schema).attr(identifiers.parseAsync).call('data').await().return(); 12 + }; 11 13 12 14 export const createRequestValidatorMini = ({ 13 15 operation, ··· 22 24 }); 23 25 if (!symbol) return; 24 26 25 - const args: ValidatorResolverArgs = { 27 + const z = plugin.external('zod.z'); 28 + const ctx: ValidatorResolverContext = { 26 29 $, 27 - chain: undefined, 30 + chain: { 31 + current: $(z), 32 + }, 28 33 operation, 29 34 plugin, 30 - schema: symbol, 35 + symbols: { 36 + schema: symbol, 37 + z, 38 + }, 31 39 }; 32 40 const validator = plugin.config['~resolvers']?.validator; 33 41 const resolver = 34 42 typeof validator === 'function' ? validator : validator?.request; 35 - const candidates = [resolver, defaultValidatorResolver]; 43 + const candidates = [resolver, validatorResolver]; 36 44 for (const candidate of candidates) { 37 - const statements = candidate?.(args); 45 + const statements = candidate?.(ctx); 38 46 if (statements === null) return; 39 47 if (statements !== undefined) { 40 48 return $.func() ··· 59 67 }); 60 68 if (!symbol) return; 61 69 62 - const args: ValidatorResolverArgs = { 70 + const z = plugin.external('zod.z'); 71 + const ctx: ValidatorResolverContext = { 63 72 $, 64 - chain: undefined, 73 + chain: { 74 + current: $(z), 75 + }, 65 76 operation, 66 77 plugin, 67 - schema: symbol, 78 + symbols: { 79 + schema: symbol, 80 + z, 81 + }, 68 82 }; 69 83 const validator = plugin.config['~resolvers']?.validator; 70 84 const resolver = 71 85 typeof validator === 'function' ? validator : validator?.response; 72 - const candidates = [resolver, defaultValidatorResolver]; 86 + const candidates = [resolver, validatorResolver]; 73 87 for (const candidate of candidates) { 74 - const statements = candidate?.(args); 88 + const statements = candidate?.(ctx); 75 89 if (statements === null) return; 76 90 if (statements !== undefined) { 77 91 return $.func()
+4 -6
packages/openapi-ts/src/plugins/zod/mini/plugin.ts
··· 5 5 import type { IR } from '~/ir/types'; 6 6 import { buildName } from '~/openApi/shared/utils/name'; 7 7 import type { SchemaWithType } from '~/plugins'; 8 + import { maybeBigInt } from '~/plugins/shared/utils/coerce'; 8 9 import { $ } from '~/ts-dsl'; 9 10 import { pathToJsonPointer, refToName } from '~/utils/ref'; 10 11 11 12 import { identifiers } from '../constants'; 12 13 import { exportAst } from '../shared/export'; 13 14 import { getZodModule } from '../shared/module'; 14 - import { numberParameter } from '../shared/numbers'; 15 15 import { irOperationToAst } from '../shared/operation'; 16 16 import type { Ast, IrSchemaToAstOptions, PluginState } from '../shared/types'; 17 17 import { irWebhookToAst } from '../shared/webhook'; ··· 152 152 } 153 153 154 154 if (schema.default !== undefined) { 155 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 156 155 ast.expression = $(z) 157 156 .attr(identifiers._default) 158 157 .call( 159 158 ast.expression, 160 - numberParameter({ 161 - isBigInt, 162 - value: schema.default, 163 - }), 159 + schema.type === 'integer' || schema.type === 'number' 160 + ? maybeBigInt(schema.default, schema.format) 161 + : $.fromValue(schema.default), 164 162 ); 165 163 } 166 164 }
+1 -1
packages/openapi-ts/src/plugins/zod/mini/toAst/array.ts
··· 112 112 } 113 113 } 114 114 115 - if (checks.length) { 115 + if (checks.length > 0) { 116 116 result.expression = result.expression 117 117 .attr(identifiers.check) 118 118 .call(...checks);
+13 -7
packages/openapi-ts/src/plugins/zod/mini/toAst/index.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { shouldCoerceToBigInt } from '~/plugins/shared/utils/coerce'; 2 3 3 4 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 4 5 import { arrayToAst } from './array'; ··· 6 7 import { enumToAst } from './enum'; 7 8 import { neverToAst } from './never'; 8 9 import { nullToAst } from './null'; 9 - import { numberToAst } from './number'; 10 + import { numberToNode } from './number'; 10 11 import { objectToAst } from './object'; 11 - import { stringToAst } from './string'; 12 + import { stringToNode } from './string'; 12 13 import { tupleToAst } from './tuple'; 13 14 import { undefinedToAst } from './undefined'; 14 15 import { unknownToAst } from './unknown'; ··· 38 39 }); 39 40 case 'integer': 40 41 case 'number': 41 - return numberToAst({ 42 + return numberToNode({ 42 43 ...args, 43 44 schema: schema as SchemaWithType<'integer' | 'number'>, 44 45 }); ··· 58 59 schema: schema as SchemaWithType<'object'>, 59 60 }); 60 61 case 'string': 61 - return stringToAst({ 62 - ...args, 63 - schema: schema as SchemaWithType<'string'>, 64 - }); 62 + return shouldCoerceToBigInt(schema.format) 63 + ? numberToNode({ 64 + ...args, 65 + schema: { ...schema, type: 'number' }, 66 + }) 67 + : stringToNode({ 68 + ...args, 69 + schema: schema as SchemaWithType<'string'>, 70 + }); 65 71 case 'tuple': 66 72 return tupleToAst({ 67 73 ...args,
+129 -55
packages/openapi-ts/src/plugins/zod/mini/toAst/number.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { 3 + maybeBigInt, 4 + shouldCoerceToBigInt, 5 + } from '~/plugins/shared/utils/coerce'; 6 + import { getIntegerLimit } from '~/plugins/shared/utils/formats'; 2 7 import { $ } from '~/ts-dsl'; 3 8 4 9 import { identifiers } from '../../constants'; 5 - import { numberParameter } from '../../shared/numbers'; 10 + import type { Chain } from '../../shared/chain'; 6 11 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 7 - 8 - export const numberToAst = ({ 9 - plugin, 10 - schema, 11 - }: IrSchemaToAstOptions & { 12 - schema: SchemaWithType<'integer' | 'number'>; 13 - }): Omit<Ast, 'typeName'> => { 14 - const z = plugin.referenceSymbol({ 15 - category: 'external', 16 - resource: 'zod.z', 17 - }); 18 - 19 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 20 - 21 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 12 + import type { NumberResolverContext } from '../../types'; 22 13 23 - if (typeof schema.const === 'number') { 24 - // TODO: parser - handle bigint constants 25 - result.expression = $(z) 26 - .attr(identifiers.literal) 27 - .call($.literal(schema.const)); 28 - return result as Omit<Ast, 'typeName'>; 14 + function baseNode(ctx: NumberResolverContext): Chain { 15 + const { schema, symbols } = ctx; 16 + const { z } = symbols; 17 + if (ctx.utils.shouldCoerceToBigInt(schema.format)) { 18 + return $(z).attr(identifiers.coerce).attr(identifiers.bigint).call(); 19 + } 20 + let chain = $(z).attr(identifiers.number).call(); 21 + if (schema.type === 'integer') { 22 + chain = $(z).attr(identifiers.int).call(); 29 23 } 24 + return chain; 25 + } 30 26 31 - result.expression = isBigInt 32 - ? $(z).attr(identifiers.coerce).attr(identifiers.bigint).call() 33 - : $(z).attr(identifiers.number).call(); 27 + function constNode(ctx: NumberResolverContext): Chain | undefined { 28 + const { schema, symbols } = ctx; 29 + const { z } = symbols; 30 + if (schema.const === undefined) return; 31 + return $(z) 32 + .attr(identifiers.literal) 33 + .call(ctx.utils.maybeBigInt(schema.const, schema.format)); 34 + } 34 35 35 - if (!isBigInt && schema.type === 'integer') { 36 - result.expression = $(z).attr(identifiers.int).call(); 36 + function maxNode(ctx: NumberResolverContext): Chain | undefined { 37 + const { schema, symbols } = ctx; 38 + const { z } = symbols; 39 + if (schema.exclusiveMaximum !== undefined) { 40 + return $(z) 41 + .attr(identifiers.lt) 42 + .call(ctx.utils.maybeBigInt(schema.exclusiveMaximum, schema.format)); 43 + } 44 + if (schema.maximum !== undefined) { 45 + return $(z) 46 + .attr(identifiers.lte) 47 + .call(ctx.utils.maybeBigInt(schema.maximum, schema.format)); 37 48 } 38 - 39 - const checks: Array<ReturnType<typeof $.call>> = []; 49 + const limit = ctx.utils.getIntegerLimit(schema.format); 50 + if (limit) { 51 + return $(z) 52 + .attr(identifiers.maximum) 53 + .call( 54 + ctx.utils.maybeBigInt(limit.maxValue, schema.format), 55 + $.object().prop('error', $.literal(limit.maxError)), 56 + ); 57 + } 58 + return; 59 + } 40 60 61 + function minNode(ctx: NumberResolverContext): Chain | undefined { 62 + const { schema, symbols } = ctx; 63 + const { z } = symbols; 41 64 if (schema.exclusiveMinimum !== undefined) { 42 - checks.push( 43 - $(z) 44 - .attr(identifiers.gt) 45 - .call(numberParameter({ isBigInt, value: schema.exclusiveMinimum })), 46 - ); 47 - } else if (schema.minimum !== undefined) { 48 - checks.push( 49 - $(z) 50 - .attr(identifiers.gte) 51 - .call(numberParameter({ isBigInt, value: schema.minimum })), 52 - ); 65 + return $(z) 66 + .attr(identifiers.gt) 67 + .call(ctx.utils.maybeBigInt(schema.exclusiveMinimum, schema.format)); 53 68 } 69 + if (schema.minimum !== undefined) { 70 + return $(z) 71 + .attr(identifiers.gte) 72 + .call(ctx.utils.maybeBigInt(schema.minimum, schema.format)); 73 + } 74 + const limit = ctx.utils.getIntegerLimit(schema.format); 75 + if (limit) { 76 + return $(z) 77 + .attr(identifiers.minimum) 78 + .call( 79 + ctx.utils.maybeBigInt(limit.minValue, schema.format), 80 + $.object().prop('error', $.literal(limit.minError)), 81 + ); 82 + } 83 + return; 84 + } 54 85 55 - if (schema.exclusiveMaximum !== undefined) { 56 - checks.push( 57 - $(z) 58 - .attr(identifiers.lt) 59 - .call(numberParameter({ isBigInt, value: schema.exclusiveMaximum })), 60 - ); 61 - } else if (schema.maximum !== undefined) { 62 - checks.push( 63 - $(z) 64 - .attr(identifiers.lte) 65 - .call(numberParameter({ isBigInt, value: schema.maximum })), 66 - ); 86 + function numberResolver(ctx: NumberResolverContext): Chain { 87 + const constNode = ctx.nodes.const(ctx); 88 + if (constNode) { 89 + ctx.chain.current = constNode; 90 + return ctx.chain.current; 67 91 } 68 92 69 - if (checks.length) { 70 - result.expression = result.expression 93 + const baseNode = ctx.nodes.base(ctx); 94 + if (baseNode) ctx.chain.current = baseNode; 95 + 96 + const checks: Array<Chain> = []; 97 + 98 + const minNode = ctx.nodes.min(ctx); 99 + if (minNode) checks.push(minNode); 100 + 101 + const maxNode = ctx.nodes.max(ctx); 102 + if (maxNode) checks.push(maxNode); 103 + 104 + if (checks.length > 0) { 105 + ctx.chain.current = ctx.chain.current 71 106 .attr(identifiers.check) 72 107 .call(...checks); 73 108 } 74 109 75 - return result as Omit<Ast, 'typeName'>; 110 + return ctx.chain.current; 111 + } 112 + 113 + export const numberToNode = ({ 114 + plugin, 115 + schema, 116 + state, 117 + }: IrSchemaToAstOptions & { 118 + schema: SchemaWithType<'integer' | 'number'>; 119 + }): Omit<Ast, 'typeName'> => { 120 + const ast: Partial<Omit<Ast, 'typeName'>> = {}; 121 + const z = plugin.external('zod.z'); 122 + const ctx: NumberResolverContext = { 123 + $, 124 + chain: { 125 + current: $(z), 126 + }, 127 + nodes: { 128 + base: baseNode, 129 + const: constNode, 130 + max: maxNode, 131 + min: minNode, 132 + }, 133 + plugin, 134 + schema, 135 + symbols: { 136 + z, 137 + }, 138 + utils: { 139 + ast, 140 + getIntegerLimit, 141 + maybeBigInt, 142 + shouldCoerceToBigInt, 143 + state, 144 + }, 145 + }; 146 + const resolver = plugin.config['~resolvers']?.number; 147 + const node = resolver?.(ctx) ?? numberResolver(ctx); 148 + ast.expression = node; 149 + return ast as Omit<Ast, 'typeName'>; 76 150 };
+70 -52
packages/openapi-ts/src/plugins/zod/mini/toAst/object.ts
··· 4 4 import { $ } from '~/ts-dsl'; 5 5 6 6 import { identifiers } from '../../constants'; 7 + import type { Chain } from '../../shared/chain'; 7 8 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 8 - import type { ObjectBaseResolverArgs } from '../../types'; 9 + import type { ObjectResolverContext } from '../../types'; 9 10 import { irSchemaToAst } from '../plugin'; 10 11 11 - function defaultObjectBaseResolver({ 12 - additional, 13 - plugin, 14 - shape, 15 - }: ObjectBaseResolverArgs): ReturnType<typeof $.call> { 16 - const z = plugin.referenceSymbol({ 17 - category: 'external', 18 - resource: 'zod.z', 12 + function additionalPropertiesNode( 13 + ctx: ObjectResolverContext, 14 + ): Chain | null | undefined { 15 + const { plugin, schema } = ctx; 16 + 17 + if ( 18 + !schema.additionalProperties || 19 + (schema.properties && Object.keys(schema.properties).length > 0) 20 + ) 21 + return; 22 + 23 + const additionalAst = irSchemaToAst({ 24 + plugin, 25 + schema: schema.additionalProperties, 26 + state: { 27 + ...ctx.utils.state, 28 + path: ref([...fromRef(ctx.utils.state.path), 'additionalProperties']), 29 + }, 19 30 }); 31 + if (additionalAst.hasLazyExpression) ctx.utils.ast.hasLazyExpression = true; 32 + return additionalAst.expression; 33 + } 34 + 35 + function baseNode(ctx: ObjectResolverContext): Chain { 36 + const { nodes, symbols } = ctx; 37 + const { z } = symbols; 38 + 39 + const additional = nodes.additionalProperties(ctx); 40 + const shape = nodes.shape(ctx); 20 41 21 42 if (additional) { 22 43 return $(z) ··· 27 48 return $(z).attr(identifiers.object).call(shape); 28 49 } 29 50 30 - export const objectToAst = ({ 31 - plugin, 32 - schema, 33 - state, 34 - }: IrSchemaToAstOptions & { 35 - schema: SchemaWithType<'object'>; 36 - }): Omit<Ast, 'typeName'> => { 37 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 38 - 51 + function objectResolver(ctx: ObjectResolverContext): Chain { 39 52 // TODO: parser - handle constants 53 + return ctx.nodes.base(ctx); 54 + } 40 55 56 + function shapeNode(ctx: ObjectResolverContext): ReturnType<typeof $.object> { 57 + const { plugin, schema } = ctx; 41 58 const shape = $.object().pretty(); 42 - const required = schema.required ?? []; 43 59 44 60 for (const name in schema.properties) { 45 61 const property = schema.properties[name]!; 46 - const isRequired = required.includes(name); 47 62 48 63 const propertyAst = irSchemaToAst({ 49 - optional: !isRequired, 64 + optional: !schema.required?.includes(name), 50 65 plugin, 51 66 schema: property, 52 67 state: { 53 - ...state, 54 - path: ref([...fromRef(state.path), 'properties', name]), 68 + ...ctx.utils.state, 69 + path: ref([...fromRef(ctx.utils.state.path), 'properties', name]), 55 70 }, 56 71 }); 57 72 if (propertyAst.hasLazyExpression) { 58 - result.hasLazyExpression = true; 59 - } 60 - 61 - if (propertyAst.hasLazyExpression) { 73 + ctx.utils.ast.hasLazyExpression = true; 62 74 shape.getter(name, propertyAst.expression.return()); 63 75 } else { 64 76 shape.prop(name, propertyAst.expression); 65 77 } 66 78 } 67 79 68 - let additional: ReturnType<typeof $.call | typeof $.expr> | null | undefined; 69 - if ( 70 - schema.additionalProperties && 71 - (!schema.properties || !Object.keys(schema.properties).length) 72 - ) { 73 - const additionalAst = irSchemaToAst({ 74 - plugin, 75 - schema: schema.additionalProperties, 76 - state: { 77 - ...state, 78 - path: ref([...fromRef(state.path), 'additionalProperties']), 79 - }, 80 - }); 81 - if (additionalAst.hasLazyExpression) result.hasLazyExpression = true; 82 - additional = additionalAst.expression; 83 - } 80 + return shape; 81 + } 84 82 85 - const args: ObjectBaseResolverArgs = { 83 + export const objectToAst = ({ 84 + plugin, 85 + schema, 86 + state, 87 + }: IrSchemaToAstOptions & { 88 + schema: SchemaWithType<'object'>; 89 + }): Omit<Ast, 'typeName'> => { 90 + const ast: Partial<Omit<Ast, 'typeName'>> = {}; 91 + const z = plugin.external('zod.z'); 92 + const ctx: ObjectResolverContext = { 86 93 $, 87 - additional, 88 - chain: undefined, 94 + chain: { 95 + current: $(z), 96 + }, 97 + nodes: { 98 + additionalProperties: additionalPropertiesNode, 99 + base: baseNode, 100 + shape: shapeNode, 101 + }, 89 102 plugin, 90 103 schema, 91 - shape, 104 + symbols: { 105 + z, 106 + }, 107 + utils: { 108 + ast, 109 + state, 110 + }, 92 111 }; 93 - const resolver = plugin.config['~resolvers']?.object?.base; 94 - const chain = resolver?.(args) ?? defaultObjectBaseResolver(args); 95 - result.expression = chain; 96 - 97 - return result as Omit<Ast, 'typeName'>; 112 + const resolver = plugin.config['~resolvers']?.object; 113 + const node = resolver?.(ctx) ?? objectResolver(ctx); 114 + ast.expression = node; 115 + return ast as Omit<Ast, 'typeName'>; 98 116 };
+105 -58
packages/openapi-ts/src/plugins/zod/mini/toAst/string.ts
··· 2 2 import { $ } from '~/ts-dsl'; 3 3 4 4 import { identifiers } from '../../constants'; 5 + import type { Chain } from '../../shared/chain'; 5 6 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 6 - import type { FormatResolverArgs } from '../../types'; 7 + import type { StringResolverContext } from '../../types'; 8 + 9 + function baseNode(ctx: StringResolverContext): Chain { 10 + const { z } = ctx.symbols; 11 + return $(z).attr(identifiers.string).call(); 12 + } 13 + 14 + function constNode(ctx: StringResolverContext): Chain | undefined { 15 + const { schema, symbols } = ctx; 16 + const { z } = symbols; 17 + if (typeof schema.const !== 'string') return; 18 + return $(z).attr(identifiers.literal).call($.literal(schema.const)); 19 + } 7 20 8 - const defaultFormatResolver = ({ 9 - chain, 10 - plugin, 11 - schema, 12 - }: FormatResolverArgs): ReturnType<typeof $.call> => { 13 - const z = plugin.referenceSymbol({ 14 - category: 'external', 15 - resource: 'zod.z', 16 - }); 21 + function formatNode(ctx: StringResolverContext): Chain | undefined { 22 + const { plugin, schema, symbols } = ctx; 23 + const { z } = symbols; 17 24 18 25 switch (schema.format) { 19 26 case 'date': ··· 43 50 return $(z).attr(identifiers.url).call(); 44 51 case 'uuid': 45 52 return $(z).attr(identifiers.uuid).call(); 46 - default: 47 - return chain; 48 53 } 49 - }; 50 54 51 - export const stringToAst = ({ 52 - plugin, 53 - schema, 54 - }: IrSchemaToAstOptions & { 55 - schema: SchemaWithType<'string'>; 56 - }): Omit<Ast, 'typeName'> => { 57 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 58 - let chain: ReturnType<typeof $.call>; 55 + return; 56 + } 59 57 60 - const z = plugin.referenceSymbol({ 61 - category: 'external', 62 - resource: 'zod.z', 63 - }); 58 + function lengthNode(ctx: StringResolverContext): Chain | undefined { 59 + const { schema, symbols } = ctx; 60 + const { z } = symbols; 61 + if (schema.minLength === undefined || schema.minLength !== schema.maxLength) 62 + return; 63 + return $(z).attr(identifiers.length).call($.literal(schema.minLength)); 64 + } 65 + 66 + function maxLengthNode(ctx: StringResolverContext): Chain | undefined { 67 + const { schema, symbols } = ctx; 68 + const { z } = symbols; 69 + if (schema.maxLength === undefined) return; 70 + return $(z).attr(identifiers.maxLength).call($.literal(schema.maxLength)); 71 + } 72 + 73 + function minLengthNode(ctx: StringResolverContext): Chain | undefined { 74 + const { schema, symbols } = ctx; 75 + const { z } = symbols; 76 + if (schema.minLength === undefined) return; 77 + return $(z).attr(identifiers.minLength).call($.literal(schema.minLength)); 78 + } 64 79 65 - if (typeof schema.const === 'string') { 66 - chain = $(z).attr(identifiers.literal).call($.literal(schema.const)); 67 - result.expression = chain; 68 - return result as Omit<Ast, 'typeName'>; 80 + function patternNode(ctx: StringResolverContext): Chain | undefined { 81 + const { schema, symbols } = ctx; 82 + const { z } = symbols; 83 + if (!schema.pattern) return; 84 + return $(z).attr(identifiers.regex).call($.regexp(schema.pattern)); 85 + } 86 + 87 + function stringResolver(ctx: StringResolverContext): Chain { 88 + const constNode = ctx.nodes.const(ctx); 89 + if (constNode) { 90 + ctx.chain.current = constNode; 91 + return ctx.chain.current; 69 92 } 70 93 71 - chain = $(z).attr(identifiers.string).call(); 94 + const baseNode = ctx.nodes.base(ctx); 95 + if (baseNode) ctx.chain.current = baseNode; 72 96 73 - if (schema.format) { 74 - const args: FormatResolverArgs = { $, chain, plugin, schema }; 75 - const resolver = 76 - plugin.config['~resolvers']?.string?.formats?.[schema.format]; 77 - chain = resolver?.(args) ?? defaultFormatResolver(args); 78 - } 97 + const formatNode = ctx.nodes.format(ctx); 98 + if (formatNode) ctx.chain.current = formatNode; 79 99 80 - const checks: Array<ReturnType<typeof $.call>> = []; 100 + const checks: Array<Chain> = []; 81 101 82 - if (schema.minLength === schema.maxLength && schema.minLength !== undefined) { 83 - checks.push( 84 - $(z).attr(identifiers.length).call($.literal(schema.minLength)), 85 - ); 102 + const lengthNode = ctx.nodes.length(ctx); 103 + if (lengthNode) { 104 + checks.push(lengthNode); 86 105 } else { 87 - if (schema.minLength !== undefined) { 88 - checks.push( 89 - $(z).attr(identifiers.minLength).call($.literal(schema.minLength)), 90 - ); 91 - } 106 + const minLengthNode = ctx.nodes.minLength(ctx); 107 + if (minLengthNode) checks.push(minLengthNode); 92 108 93 - if (schema.maxLength !== undefined) { 94 - checks.push( 95 - $(z).attr(identifiers.maxLength).call($.literal(schema.maxLength)), 96 - ); 97 - } 109 + const maxLengthNode = ctx.nodes.maxLength(ctx); 110 + if (maxLengthNode) checks.push(maxLengthNode); 98 111 } 99 112 100 - if (schema.pattern) { 101 - checks.push($(z).attr(identifiers.regex).call($.regexp(schema.pattern))); 113 + const patternNode = ctx.nodes.pattern(ctx); 114 + if (patternNode) checks.push(patternNode); 115 + 116 + if (checks.length > 0) { 117 + ctx.chain.current = ctx.chain.current 118 + .attr(identifiers.check) 119 + .call(...checks); 102 120 } 103 121 104 - if (checks.length) { 105 - chain = chain.attr(identifiers.check).call(...checks); 106 - } 122 + return ctx.chain.current; 123 + } 107 124 108 - result.expression = chain; 109 - return result as Omit<Ast, 'typeName'>; 125 + export const stringToNode = ({ 126 + plugin, 127 + schema, 128 + }: IrSchemaToAstOptions & { 129 + schema: SchemaWithType<'string'>; 130 + }): Omit<Ast, 'typeName'> => { 131 + const z = plugin.external('zod.z'); 132 + const ctx: StringResolverContext = { 133 + $, 134 + chain: { 135 + current: $(z), 136 + }, 137 + nodes: { 138 + base: baseNode, 139 + const: constNode, 140 + format: formatNode, 141 + length: lengthNode, 142 + maxLength: maxLengthNode, 143 + minLength: minLengthNode, 144 + pattern: patternNode, 145 + }, 146 + plugin, 147 + schema, 148 + symbols: { 149 + z, 150 + }, 151 + }; 152 + const resolver = plugin.config['~resolvers']?.string; 153 + const node = resolver?.(ctx) ?? stringResolver(ctx); 154 + return { 155 + expression: node, 156 + }; 110 157 };
+3
packages/openapi-ts/src/plugins/zod/shared/chain.ts
··· 1 + import type { $ } from '~/ts-dsl'; 2 + 3 + export type Chain = ReturnType<typeof $.call | typeof $.expr>;
-23
packages/openapi-ts/src/plugins/zod/shared/numbers.ts
··· 1 - import { $ } from '~/ts-dsl'; 2 - 3 - export const numberParameter = ({ 4 - isBigInt, 5 - value, 6 - }: { 7 - isBigInt: boolean; 8 - value: unknown; 9 - }): ReturnType<typeof $.call | typeof $.fromValue> => { 10 - const expr = $.fromValue(value); 11 - 12 - if ( 13 - isBigInt && 14 - (typeof value === 'bigint' || 15 - typeof value === 'number' || 16 - typeof value === 'string' || 17 - typeof value === 'boolean') 18 - ) { 19 - return $('BigInt').call(expr); 20 - } 21 - 22 - return expr; 23 - };
+123 -67
packages/openapi-ts/src/plugins/zod/types.d.ts
··· 1 - import type { Symbol } from '@hey-api/codegen-core'; 1 + import type { Refs, Symbol } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { IR } from '~/ir/types'; 5 - import type { DefinePlugin, Plugin } from '~/plugins'; 5 + import type { DefinePlugin, Plugin, SchemaWithType } from '~/plugins'; 6 + import type { 7 + MaybeBigInt, 8 + ShouldCoerceToBigInt, 9 + } from '~/plugins/shared/utils/coerce'; 10 + import type { GetIntegerLimit } from '~/plugins/shared/utils/formats'; 6 11 import type { $, DollarTsDsl, TsDsl } from '~/ts-dsl'; 7 12 import type { StringCase, StringName } from '~/types/case'; 8 13 import type { MaybeArray } from '~/types/utils'; 9 14 10 15 import type { IApi } from './api'; 16 + import type { Chain } from './shared/chain'; 17 + import type { Ast, PluginState } from './shared/types'; 11 18 12 19 export type UserConfig = Plugin.Name<'zod'> & 13 20 Plugin.Hooks & ··· 747 754 }; 748 755 }; 749 756 750 - type SharedResolverArgs = DollarTsDsl & { 757 + interface BaseResolverContext extends DollarTsDsl { 758 + /** 759 + * Functions for working with chains. 760 + */ 761 + chain: { 762 + /** 763 + * The current chain. 764 + * 765 + * In Zod, this represents a chain of call expressions ("chains") 766 + * being assembled to form a schema definition. 767 + * 768 + * Each chain can be extended, modified, or replaced to customize 769 + * the resulting schema. 770 + */ 771 + current: Chain; 772 + }; 751 773 /** 752 - * The current fluent builder chain under construction for this resolver. 753 - * 754 - * Represents the in-progress call sequence (e.g., a Zod or DSL chain) 755 - * that defines the current schema or expression being generated. 756 - * 757 - * This chain can be extended, transformed, or replaced entirely to customize 758 - * the resulting output of the resolver. 774 + * The plugin instance. 759 775 */ 760 - chain?: ReturnType<typeof $.call>; 761 776 plugin: ZodPlugin['Instance']; 762 - }; 777 + /** 778 + * Provides access to commonly used symbols within the plugin. 779 + */ 780 + symbols: { 781 + z: Symbol; 782 + }; 783 + } 763 784 764 - export type FormatResolverArgs = Required<SharedResolverArgs> & { 765 - schema: IR.SchemaObject; 766 - }; 785 + export interface NumberResolverContext extends BaseResolverContext { 786 + /** 787 + * Nodes used to build different parts of the number schema. 788 + */ 789 + nodes: { 790 + base: (ctx: NumberResolverContext) => Chain; 791 + const: (ctx: NumberResolverContext) => Chain | undefined; 792 + max: (ctx: NumberResolverContext) => Chain | undefined; 793 + min: (ctx: NumberResolverContext) => Chain | undefined; 794 + }; 795 + schema: SchemaWithType<'integer' | 'number'>; 796 + /** 797 + * Utility functions for number schema processing. 798 + */ 799 + utils: { 800 + ast: Partial<Omit<Ast, 'typeName'>>; 801 + getIntegerLimit: GetIntegerLimit; 802 + maybeBigInt: MaybeBigInt; 803 + shouldCoerceToBigInt: ShouldCoerceToBigInt; 804 + state: Refs<PluginState>; 805 + }; 806 + } 767 807 768 - export type ObjectBaseResolverArgs = SharedResolverArgs & { 769 - /** Null = never */ 770 - additional?: ReturnType<typeof $.call | typeof $.expr> | null; 771 - schema: IR.SchemaObject; 772 - shape: ReturnType<typeof $.object>; 773 - }; 808 + export interface ObjectResolverContext extends BaseResolverContext { 809 + /** 810 + * Nodes used to build different parts of the object schema. 811 + */ 812 + nodes: { 813 + /** 814 + * If `additionalProperties` is `false` or `{ type: 'never' }`, returns `null` 815 + * to indicate no additional properties are allowed. 816 + */ 817 + additionalProperties: ( 818 + ctx: ObjectResolverContext, 819 + ) => Chain | null | undefined; 820 + base: (ctx: ObjectResolverContext) => Chain; 821 + shape: (ctx: ObjectResolverContext) => ReturnType<typeof $.object>; 822 + }; 823 + schema: SchemaWithType<'object'>; 824 + /** 825 + * Utility functions for object schema processing. 826 + */ 827 + utils: { 828 + ast: Partial<Omit<Ast, 'typeName'>>; 829 + state: Refs<PluginState>; 830 + }; 831 + } 832 + 833 + export interface StringResolverContext extends BaseResolverContext { 834 + /** 835 + * Nodes used to build different parts of the string schema. 836 + */ 837 + nodes: { 838 + base: (ctx: StringResolverContext) => Chain; 839 + const: (ctx: StringResolverContext) => Chain | undefined; 840 + format: (ctx: StringResolverContext) => Chain | undefined; 841 + length: (ctx: StringResolverContext) => Chain | undefined; 842 + maxLength: (ctx: StringResolverContext) => Chain | undefined; 843 + minLength: (ctx: StringResolverContext) => Chain | undefined; 844 + pattern: (ctx: StringResolverContext) => Chain | undefined; 845 + }; 846 + schema: SchemaWithType<'string'>; 847 + } 774 848 775 - export type ValidatorResolverArgs = SharedResolverArgs & { 849 + export interface ValidatorResolverContext extends BaseResolverContext { 776 850 operation: IR.Operation; 777 - schema: Symbol; 778 - }; 851 + /** 852 + * Provides access to commonly used symbols within the plugin. 853 + */ 854 + symbols: BaseResolverContext['symbols'] & { 855 + schema: Symbol; 856 + }; 857 + } 779 858 780 859 type ValidatorResolver = ( 781 - args: ValidatorResolverArgs, 860 + ctx: ValidatorResolverContext, 782 861 ) => MaybeArray<TsDsl<ts.Statement>> | null | undefined; 783 862 784 863 type Resolvers = Plugin.Resolvers<{ 785 864 /** 786 - * Resolvers for object schemas. 865 + * Resolver for number schemas. 787 866 * 788 - * Allows customization of how object types are rendered. 867 + * Allows customization of how number types are rendered. 789 868 * 790 - * Example path: `~resolvers.object.base` 869 + * Returning `undefined` will execute the default resolver logic. 870 + */ 871 + number?: (ctx: NumberResolverContext) => Chain | undefined; 872 + /** 873 + * Resolver for object schemas. 874 + * 875 + * Allows customization of how object types are rendered. 791 876 * 792 - * Returning `undefined` from a resolver will apply the default 793 - * generation behavior for the object schema. 877 + * Returning `undefined` will execute the default resolver logic. 794 878 */ 795 - object?: { 796 - /** 797 - * Controls how object schemas are constructed. 798 - * 799 - * Called with the fully assembled shape (properties) and any additional 800 - * property schema, allowing the resolver to choose the correct Zod 801 - * base constructor and modify the schema chain if needed. 802 - * 803 - * Returning `undefined` will execute the default resolver logic. 804 - */ 805 - base?: ( 806 - args: ObjectBaseResolverArgs, 807 - ) => ReturnType<typeof $.call> | undefined; 808 - }; 879 + object?: (ctx: ObjectResolverContext) => Chain | undefined; 809 880 /** 810 - * Resolvers for string schemas. 881 + * Resolver for string schemas. 882 + * 883 + * Allows customization of how string types are rendered. 811 884 * 812 - * Allows customization of how string types are rendered, including 813 - * per-format handling. 885 + * Returning `undefined` will execute the default resolver logic. 814 886 */ 815 - string?: { 816 - /** 817 - * Resolvers for string formats (e.g., `uuid`, `email`, `date-time`). 818 - * 819 - * Each key represents a specific format name with a custom 820 - * resolver function that controls how that format is rendered. 821 - * 822 - * Example path: `~resolvers.string.formats.uuid` 823 - * 824 - * Returning `undefined` from a resolver will apply the default 825 - * generation logic for that format. 826 - */ 827 - formats?: Record< 828 - string, 829 - (args: FormatResolverArgs) => ReturnType<typeof $.call> | undefined 830 - >; 831 - }; 887 + string?: (ctx: StringResolverContext) => Chain | undefined; 832 888 /** 833 889 * Resolvers for request and response validators. 834 890 * ··· 836 892 * 837 893 * Example path: `~resolvers.validator.request` or `~resolvers.validator.response` 838 894 * 839 - * Returning `undefined` from a resolver will apply the default generation logic. 895 + * Returning `undefined` will execute the default resolver logic. 840 896 */ 841 897 validator?: 842 898 | ValidatorResolver ··· 844 900 /** 845 901 * Controls how the request validator function body is generated. 846 902 * 847 - * Returning `undefined` will fall back to the default `.await().return()` logic. 903 + * Returning `undefined` will execute the default resolver logic. 848 904 */ 849 905 request?: ValidatorResolver; 850 906 /** 851 907 * Controls how the response validator function body is generated. 852 908 * 853 - * Returning `undefined` will fall back to the default `.await().return()` logic. 909 + * Returning `undefined` will execute the default resolver logic. 854 910 */ 855 911 response?: ValidatorResolver; 856 912 };
+29 -15
packages/openapi-ts/src/plugins/zod/v3/api.ts
··· 2 2 3 3 import { identifiers } from '../constants'; 4 4 import type { ValidatorArgs } from '../shared/types'; 5 - import type { ValidatorResolverArgs } from '../types'; 5 + import type { ValidatorResolverContext } from '../types'; 6 6 7 - const defaultValidatorResolver = ({ 8 - schema, 9 - }: ValidatorResolverArgs): ReturnType<typeof $.return> => 10 - $(schema).attr(identifiers.parseAsync).call('data').await().return(); 7 + const validatorResolver = ( 8 + ctx: ValidatorResolverContext, 9 + ): ReturnType<typeof $.return> => { 10 + const { schema } = ctx.symbols; 11 + return $(schema).attr(identifiers.parseAsync).call('data').await().return(); 12 + }; 11 13 12 14 export const createRequestValidatorV3 = ({ 13 15 operation, ··· 22 24 }); 23 25 if (!symbol) return; 24 26 25 - const args: ValidatorResolverArgs = { 27 + const z = plugin.external('zod.z'); 28 + const ctx: ValidatorResolverContext = { 26 29 $, 27 - chain: undefined, 30 + chain: { 31 + current: $(z), 32 + }, 28 33 operation, 29 34 plugin, 30 - schema: symbol, 35 + symbols: { 36 + schema: symbol, 37 + z, 38 + }, 31 39 }; 32 40 const validator = plugin.config['~resolvers']?.validator; 33 41 const resolver = 34 42 typeof validator === 'function' ? validator : validator?.request; 35 - const candidates = [resolver, defaultValidatorResolver]; 43 + const candidates = [resolver, validatorResolver]; 36 44 for (const candidate of candidates) { 37 - const statements = candidate?.(args); 45 + const statements = candidate?.(ctx); 38 46 if (statements === null) return; 39 47 if (statements !== undefined) { 40 48 return $.func() ··· 59 67 }); 60 68 if (!symbol) return; 61 69 62 - const args: ValidatorResolverArgs = { 70 + const z = plugin.external('zod.z'); 71 + const ctx: ValidatorResolverContext = { 63 72 $, 64 - chain: undefined, 73 + chain: { 74 + current: $(z), 75 + }, 65 76 operation, 66 77 plugin, 67 - schema: symbol, 78 + symbols: { 79 + schema: symbol, 80 + z, 81 + }, 68 82 }; 69 83 const validator = plugin.config['~resolvers']?.validator; 70 84 const resolver = 71 85 typeof validator === 'function' ? validator : validator?.response; 72 - const candidates = [resolver, defaultValidatorResolver]; 86 + const candidates = [resolver, validatorResolver]; 73 87 for (const candidate of candidates) { 74 - const statements = candidate?.(args); 88 + const statements = candidate?.(ctx); 75 89 if (statements === null) return; 76 90 if (statements !== undefined) { 77 91 return $.func()
+8 -8
packages/openapi-ts/src/plugins/zod/v3/plugin.ts
··· 5 5 import type { IR } from '~/ir/types'; 6 6 import { buildName } from '~/openApi/shared/utils/name'; 7 7 import type { SchemaWithType } from '~/plugins'; 8 + import { maybeBigInt } from '~/plugins/shared/utils/coerce'; 8 9 import { $ } from '~/ts-dsl'; 9 10 import { pathToJsonPointer, refToName } from '~/utils/ref'; 10 11 11 12 import { identifiers } from '../constants'; 12 13 import { exportAst } from '../shared/export'; 13 14 import { getZodModule } from '../shared/module'; 14 - import { numberParameter } from '../shared/numbers'; 15 15 import { irOperationToAst } from '../shared/operation'; 16 16 import type { Ast, IrSchemaToAstOptions, PluginState } from '../shared/types'; 17 17 import { irWebhookToAst } from '../shared/webhook'; ··· 139 139 } 140 140 141 141 if (schema.default !== undefined) { 142 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 143 - ast.expression = ast.expression.attr(identifiers.default).call( 144 - numberParameter({ 145 - isBigInt, 146 - value: schema.default, 147 - }), 148 - ); 142 + ast.expression = ast.expression 143 + .attr(identifiers.default) 144 + .call( 145 + schema.type === 'integer' || schema.type === 'number' 146 + ? maybeBigInt(schema.default, schema.format) 147 + : $.fromValue(schema.default), 148 + ); 149 149 } 150 150 } 151 151
+13 -7
packages/openapi-ts/src/plugins/zod/v3/toAst/index.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { shouldCoerceToBigInt } from '~/plugins/shared/utils/coerce'; 2 3 3 4 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 4 5 import { arrayToAst } from './array'; ··· 6 7 import { enumToAst } from './enum'; 7 8 import { neverToAst } from './never'; 8 9 import { nullToAst } from './null'; 9 - import { numberToAst } from './number'; 10 + import { numberToNode } from './number'; 10 11 import { objectToAst } from './object'; 11 - import { stringToAst } from './string'; 12 + import { stringToNode } from './string'; 12 13 import { tupleToAst } from './tuple'; 13 14 import { undefinedToAst } from './undefined'; 14 15 import { unknownToAst } from './unknown'; ··· 45 46 case 'integer': 46 47 case 'number': 47 48 return { 48 - expression: numberToAst({ 49 + expression: numberToNode({ 49 50 ...args, 50 51 schema: schema as SchemaWithType<'integer' | 'number'>, 51 52 }), ··· 71 72 }); 72 73 case 'string': 73 74 return { 74 - expression: stringToAst({ 75 - ...args, 76 - schema: schema as SchemaWithType<'string'>, 77 - }), 75 + expression: shouldCoerceToBigInt(schema.format) 76 + ? numberToNode({ 77 + ...args, 78 + schema: { ...schema, type: 'number' }, 79 + }) 80 + : stringToNode({ 81 + ...args, 82 + schema: schema as SchemaWithType<'string'>, 83 + }), 78 84 }; 79 85 case 'tuple': 80 86 return tupleToAst({
+121 -40
packages/openapi-ts/src/plugins/zod/v3/toAst/number.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { 3 + maybeBigInt, 4 + shouldCoerceToBigInt, 5 + } from '~/plugins/shared/utils/coerce'; 6 + import { getIntegerLimit } from '~/plugins/shared/utils/formats'; 2 7 import { $ } from '~/ts-dsl'; 3 8 4 9 import { identifiers } from '../../constants'; 5 - import { numberParameter } from '../../shared/numbers'; 6 - import type { IrSchemaToAstOptions } from '../../shared/types'; 10 + import type { Chain } from '../../shared/chain'; 11 + import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 12 + import type { NumberResolverContext } from '../../types'; 7 13 8 - export const numberToAst = ({ 9 - plugin, 10 - schema, 11 - }: IrSchemaToAstOptions & { 12 - schema: SchemaWithType<'integer' | 'number'>; 13 - }) => { 14 - const z = plugin.referenceSymbol({ 15 - category: 'external', 16 - resource: 'zod.z', 17 - }); 14 + function baseNode(ctx: NumberResolverContext): Chain { 15 + const { schema, symbols } = ctx; 16 + const { z } = symbols; 17 + if (ctx.utils.shouldCoerceToBigInt(schema.format)) { 18 + return $(z).attr(identifiers.coerce).attr(identifiers.bigint).call(); 19 + } 20 + let chain = $(z).attr(identifiers.number).call(); 21 + if (schema.type === 'integer') { 22 + chain = chain.attr(identifiers.int).call(); 23 + } 24 + return chain; 25 + } 18 26 19 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 27 + function constNode(ctx: NumberResolverContext): Chain | undefined { 28 + const { schema, symbols } = ctx; 29 + const { z } = symbols; 30 + if (schema.const === undefined) return; 31 + return $(z) 32 + .attr(identifiers.literal) 33 + .call(ctx.utils.maybeBigInt(schema.const, schema.format)); 34 + } 20 35 21 - if (typeof schema.const === 'number') { 22 - // TODO: parser - handle bigint constants 23 - const expression = $(z) 24 - .attr(identifiers.literal) 25 - .call($.literal(schema.const)); 26 - return expression; 36 + function maxNode(ctx: NumberResolverContext): Chain | undefined { 37 + const { chain, schema } = ctx; 38 + if (schema.exclusiveMaximum !== undefined) { 39 + return chain.current 40 + .attr(identifiers.lt) 41 + .call(ctx.utils.maybeBigInt(schema.exclusiveMaximum, schema.format)); 27 42 } 28 - 29 - let numberExpression = isBigInt 30 - ? $(z).attr(identifiers.coerce).attr(identifiers.bigint).call() 31 - : $(z).attr(identifiers.number).call(); 32 - 33 - if (!isBigInt && schema.type === 'integer') { 34 - numberExpression = numberExpression.attr(identifiers.int).call(); 43 + if (schema.maximum !== undefined) { 44 + return chain.current 45 + .attr(identifiers.lte) 46 + .call(ctx.utils.maybeBigInt(schema.maximum, schema.format)); 35 47 } 48 + const limit = ctx.utils.getIntegerLimit(schema.format); 49 + if (limit) { 50 + return chain.current 51 + .attr(identifiers.max) 52 + .call( 53 + ctx.utils.maybeBigInt(limit.maxValue, schema.format), 54 + $.object().prop('message', $.literal(limit.maxError)), 55 + ); 56 + } 57 + return; 58 + } 36 59 60 + function minNode(ctx: NumberResolverContext): Chain | undefined { 61 + const { chain, schema } = ctx; 37 62 if (schema.exclusiveMinimum !== undefined) { 38 - numberExpression = numberExpression 63 + return chain.current 39 64 .attr(identifiers.gt) 40 - .call(numberParameter({ isBigInt, value: schema.exclusiveMinimum })); 41 - } else if (schema.minimum !== undefined) { 42 - numberExpression = numberExpression 65 + .call(ctx.utils.maybeBigInt(schema.exclusiveMinimum, schema.format)); 66 + } 67 + if (schema.minimum !== undefined) { 68 + return chain.current 43 69 .attr(identifiers.gte) 44 - .call(numberParameter({ isBigInt, value: schema.minimum })); 70 + .call(ctx.utils.maybeBigInt(schema.minimum, schema.format)); 45 71 } 72 + const limit = ctx.utils.getIntegerLimit(schema.format); 73 + if (limit) { 74 + return chain.current 75 + .attr(identifiers.min) 76 + .call( 77 + ctx.utils.maybeBigInt(limit.minValue, schema.format), 78 + $.object().prop('message', $.literal(limit.minError)), 79 + ); 80 + } 81 + return; 82 + } 46 83 47 - if (schema.exclusiveMaximum !== undefined) { 48 - numberExpression = numberExpression 49 - .attr(identifiers.lt) 50 - .call(numberParameter({ isBigInt, value: schema.exclusiveMaximum })); 51 - } else if (schema.maximum !== undefined) { 52 - numberExpression = numberExpression 53 - .attr(identifiers.lte) 54 - .call(numberParameter({ isBigInt, value: schema.maximum })); 84 + function numberResolver(ctx: NumberResolverContext): Chain { 85 + const constNode = ctx.nodes.const(ctx); 86 + if (constNode) { 87 + ctx.chain.current = constNode; 88 + return ctx.chain.current; 55 89 } 56 90 57 - return numberExpression; 91 + const baseNode = ctx.nodes.base(ctx); 92 + if (baseNode) ctx.chain.current = baseNode; 93 + 94 + const minNode = ctx.nodes.min(ctx); 95 + if (minNode) ctx.chain.current = minNode; 96 + 97 + const maxNode = ctx.nodes.max(ctx); 98 + if (maxNode) ctx.chain.current = maxNode; 99 + 100 + return ctx.chain.current; 101 + } 102 + 103 + export const numberToNode = ({ 104 + plugin, 105 + schema, 106 + state, 107 + }: IrSchemaToAstOptions & { 108 + schema: SchemaWithType<'integer' | 'number'>; 109 + }): Chain => { 110 + const ast: Partial<Omit<Ast, 'typeName'>> = {}; 111 + const z = plugin.external('zod.z'); 112 + const ctx: NumberResolverContext = { 113 + $, 114 + chain: { 115 + current: $(z), 116 + }, 117 + nodes: { 118 + base: baseNode, 119 + const: constNode, 120 + max: maxNode, 121 + min: minNode, 122 + }, 123 + plugin, 124 + schema, 125 + symbols: { 126 + z, 127 + }, 128 + utils: { 129 + ast, 130 + getIntegerLimit, 131 + maybeBigInt, 132 + shouldCoerceToBigInt, 133 + state, 134 + }, 135 + }; 136 + const resolver = plugin.config['~resolvers']?.number; 137 + const node = resolver?.(ctx) ?? numberResolver(ctx); 138 + return node; 58 139 };
+76 -57
packages/openapi-ts/src/plugins/zod/v3/toAst/object.ts
··· 4 4 import { $ } from '~/ts-dsl'; 5 5 6 6 import { identifiers } from '../../constants'; 7 + import type { Chain } from '../../shared/chain'; 7 8 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 8 - import type { ObjectBaseResolverArgs } from '../../types'; 9 + import type { ObjectResolverContext } from '../../types'; 9 10 import { irSchemaToAst } from '../plugin'; 10 11 11 - function defaultObjectBaseResolver({ 12 - additional, 13 - plugin, 14 - shape, 15 - }: ObjectBaseResolverArgs): ReturnType<typeof $.call> { 16 - const z = plugin.referenceSymbol({ 17 - category: 'external', 18 - resource: 'zod.z', 12 + function additionalPropertiesNode( 13 + ctx: ObjectResolverContext, 14 + ): Chain | null | undefined { 15 + const { plugin, schema } = ctx; 16 + 17 + if ( 18 + !schema.additionalProperties || 19 + (schema.properties && Object.keys(schema.properties).length > 0) 20 + ) 21 + return; 22 + 23 + const additionalAst = irSchemaToAst({ 24 + plugin, 25 + schema: schema.additionalProperties, 26 + state: { 27 + ...ctx.utils.state, 28 + path: ref([...fromRef(ctx.utils.state.path), 'additionalProperties']), 29 + }, 19 30 }); 31 + if (additionalAst.hasLazyExpression) ctx.utils.ast.hasLazyExpression = true; 32 + return additionalAst.expression; 33 + } 34 + 35 + function baseNode(ctx: ObjectResolverContext): Chain { 36 + const { nodes, symbols } = ctx; 37 + const { z } = symbols; 38 + 39 + const additional = nodes.additionalProperties(ctx); 40 + const shape = nodes.shape(ctx); 20 41 21 42 if (additional) { 22 43 return $(z).attr(identifiers.record).call(additional); ··· 25 46 return $(z).attr(identifiers.object).call(shape); 26 47 } 27 48 28 - export const objectToAst = ({ 29 - plugin, 30 - schema, 31 - state, 32 - }: IrSchemaToAstOptions & { 33 - schema: SchemaWithType<'object'>; 34 - }): Omit<Ast, 'typeName'> & { 35 - anyType?: string; 36 - } => { 37 - let hasLazyExpression = false; 38 - 49 + function objectResolver(ctx: ObjectResolverContext): Chain { 39 50 // TODO: parser - handle constants 51 + return ctx.nodes.base(ctx); 52 + } 40 53 54 + function shapeNode(ctx: ObjectResolverContext): ReturnType<typeof $.object> { 55 + const { plugin, schema } = ctx; 41 56 const shape = $.object().pretty(); 42 - const required = schema.required ?? []; 43 57 44 58 for (const name in schema.properties) { 45 59 const property = schema.properties[name]!; 46 - const isRequired = required.includes(name); 47 60 48 - const propertyExpression = irSchemaToAst({ 49 - optional: !isRequired, 61 + const propertyAst = irSchemaToAst({ 62 + optional: !schema.required?.includes(name), 50 63 plugin, 51 64 schema: property, 52 65 state: { 53 - ...state, 54 - path: ref([...fromRef(state.path), 'properties', name]), 66 + ...ctx.utils.state, 67 + path: ref([...fromRef(ctx.utils.state.path), 'properties', name]), 55 68 }, 56 69 }); 57 - 58 - if (propertyExpression.hasLazyExpression) hasLazyExpression = true; 59 - 60 - shape.prop(name, propertyExpression.expression); 70 + if (propertyAst.hasLazyExpression) ctx.utils.ast.hasLazyExpression = true; 71 + shape.prop(name, propertyAst.expression); 61 72 } 62 73 63 - let additional: ReturnType<typeof $.call | typeof $.expr> | null | undefined; 64 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 65 - if ( 66 - schema.additionalProperties && 67 - (!schema.properties || !Object.keys(schema.properties).length) 68 - ) { 69 - const additionalAst = irSchemaToAst({ 70 - plugin, 71 - schema: schema.additionalProperties, 72 - state: { 73 - ...state, 74 - path: ref([...fromRef(state.path), 'additionalProperties']), 75 - }, 76 - }); 77 - hasLazyExpression = additionalAst.hasLazyExpression || hasLazyExpression; 78 - additional = additionalAst.expression; 79 - } 74 + return shape; 75 + } 80 76 81 - const args: ObjectBaseResolverArgs = { 77 + export const objectToAst = ({ 78 + plugin, 79 + schema, 80 + state, 81 + }: IrSchemaToAstOptions & { 82 + schema: SchemaWithType<'object'>; 83 + }): Omit<Ast, 'typeName'> & { 84 + anyType?: string; 85 + } => { 86 + const ast: Partial<Omit<Ast, 'typeName'>> = {}; 87 + const z = plugin.external('zod.z'); 88 + const ctx: ObjectResolverContext = { 82 89 $, 83 - additional, 84 - chain: undefined, 90 + chain: { 91 + current: $(z), 92 + }, 93 + nodes: { 94 + additionalProperties: additionalPropertiesNode, 95 + base: baseNode, 96 + shape: shapeNode, 97 + }, 85 98 plugin, 86 99 schema, 87 - shape, 100 + symbols: { 101 + z, 102 + }, 103 + utils: { 104 + ast, 105 + state, 106 + }, 88 107 }; 89 - const resolver = plugin.config['~resolvers']?.object?.base; 90 - const chain = resolver?.(args) ?? defaultObjectBaseResolver(args); 91 - result.expression = chain; 92 - 108 + const resolver = plugin.config['~resolvers']?.object; 109 + const node = resolver?.(ctx) ?? objectResolver(ctx); 110 + ast.expression = node; 93 111 return { 112 + ...ast, 94 113 anyType: 'AnyZodObject', 95 - expression: result.expression!, 96 - hasLazyExpression, 114 + } as Omit<Ast, 'typeName'> & { 115 + anyType: string; 97 116 }; 98 117 };
+103 -49
packages/openapi-ts/src/plugins/zod/v3/toAst/string.ts
··· 2 2 import { $ } from '~/ts-dsl'; 3 3 4 4 import { identifiers } from '../../constants'; 5 + import type { Chain } from '../../shared/chain'; 5 6 import type { IrSchemaToAstOptions } from '../../shared/types'; 6 - import type { FormatResolverArgs } from '../../types'; 7 + import type { StringResolverContext } from '../../types'; 7 8 8 - const defaultFormatResolver = ({ 9 - chain, 10 - plugin, 11 - schema, 12 - }: FormatResolverArgs): ReturnType<typeof $.call> => { 9 + function baseNode(ctx: StringResolverContext): Chain { 10 + const { z } = ctx.symbols; 11 + return $(z).attr(identifiers.string).call(); 12 + } 13 + 14 + function constNode(ctx: StringResolverContext): Chain | undefined { 15 + const { schema, symbols } = ctx; 16 + const { z } = symbols; 17 + if (typeof schema.const !== 'string') return; 18 + return $(z).attr(identifiers.literal).call($.literal(schema.const)); 19 + } 20 + 21 + function formatNode(ctx: StringResolverContext): Chain | undefined { 22 + const { chain, plugin, schema } = ctx; 23 + 13 24 switch (schema.format) { 14 25 case 'date': 15 - return chain.attr(identifiers.date).call(); 26 + return chain.current.attr(identifiers.date).call(); 16 27 case 'date-time': { 17 28 const obj = $.object() 18 29 .$if(plugin.config.dates.offset, (o) => ··· 21 32 .$if(plugin.config.dates.local, (o) => 22 33 o.prop('local', $.literal(true)), 23 34 ); 24 - return chain 35 + return chain.current 25 36 .attr(identifiers.datetime) 26 37 .call(obj.hasProps() ? obj : undefined); 27 38 } 28 39 case 'email': 29 - return chain.attr(identifiers.email).call(); 40 + return chain.current.attr(identifiers.email).call(); 30 41 case 'ipv4': 31 42 case 'ipv6': 32 - return chain.attr(identifiers.ip).call(); 43 + return chain.current.attr(identifiers.ip).call(); 33 44 case 'time': 34 - return chain.attr(identifiers.time).call(); 45 + return chain.current.attr(identifiers.time).call(); 35 46 case 'uri': 36 - return chain.attr(identifiers.url).call(); 47 + return chain.current.attr(identifiers.url).call(); 37 48 case 'uuid': 38 - return chain.attr(identifiers.uuid).call(); 39 - default: 40 - return chain; 49 + return chain.current.attr(identifiers.uuid).call(); 41 50 } 42 - }; 43 51 44 - export const stringToAst = ({ 45 - plugin, 46 - schema, 47 - }: IrSchemaToAstOptions & { 48 - schema: SchemaWithType<'string'>; 49 - }): ReturnType<typeof $.call> => { 50 - let chain: ReturnType<typeof $.call>; 52 + return; 53 + } 51 54 52 - const z = plugin.referenceSymbol({ 53 - category: 'external', 54 - resource: 'zod.z', 55 - }); 55 + function lengthNode(ctx: StringResolverContext): Chain | undefined { 56 + const { chain, schema } = ctx; 57 + if (schema.minLength === undefined || schema.minLength !== schema.maxLength) 58 + return; 59 + return chain.current 60 + .attr(identifiers.length) 61 + .call($.literal(schema.minLength)); 62 + } 56 63 57 - if (typeof schema.const === 'string') { 58 - chain = $(z).attr(identifiers.literal).call($.literal(schema.const)); 59 - return chain; 60 - } 64 + function maxLengthNode(ctx: StringResolverContext): Chain | undefined { 65 + const { chain, schema } = ctx; 66 + if (schema.maxLength === undefined) return; 67 + return chain.current.attr(identifiers.max).call($.literal(schema.maxLength)); 68 + } 61 69 62 - chain = $(z).attr(identifiers.string).call(); 70 + function minLengthNode(ctx: StringResolverContext): Chain | undefined { 71 + const { chain, schema } = ctx; 72 + if (schema.minLength === undefined) return; 73 + return chain.current.attr(identifiers.min).call($.literal(schema.minLength)); 74 + } 63 75 64 - if (schema.format) { 65 - const args: FormatResolverArgs = { $, chain, plugin, schema }; 66 - const resolver = 67 - plugin.config['~resolvers']?.string?.formats?.[schema.format]; 68 - chain = resolver?.(args) ?? defaultFormatResolver(args); 76 + function patternNode(ctx: StringResolverContext): Chain | undefined { 77 + const { chain, schema } = ctx; 78 + if (!schema.pattern) return; 79 + return chain.current.attr(identifiers.regex).call($.regexp(schema.pattern)); 80 + } 81 + 82 + function stringResolver(ctx: StringResolverContext): Chain { 83 + const constNode = ctx.nodes.const(ctx); 84 + if (constNode) { 85 + ctx.chain.current = constNode; 86 + return ctx.chain.current; 69 87 } 70 88 71 - if (schema.minLength === schema.maxLength && schema.minLength !== undefined) { 72 - chain = chain.attr(identifiers.length).call($.literal(schema.minLength)); 89 + const baseNode = ctx.nodes.base(ctx); 90 + if (baseNode) ctx.chain.current = baseNode; 91 + 92 + const formatNode = ctx.nodes.format(ctx); 93 + if (formatNode) ctx.chain.current = formatNode; 94 + 95 + const lengthNode = ctx.nodes.length(ctx); 96 + if (lengthNode) { 97 + ctx.chain.current = lengthNode; 73 98 } else { 74 - if (schema.minLength !== undefined) { 75 - chain = chain.attr(identifiers.min).call($.literal(schema.minLength)); 76 - } 99 + const minLengthNode = ctx.nodes.minLength(ctx); 100 + if (minLengthNode) ctx.chain.current = minLengthNode; 77 101 78 - if (schema.maxLength !== undefined) { 79 - chain = chain.attr(identifiers.max).call($.literal(schema.maxLength)); 80 - } 102 + const maxLengthNode = ctx.nodes.maxLength(ctx); 103 + if (maxLengthNode) ctx.chain.current = maxLengthNode; 81 104 } 82 105 83 - if (schema.pattern) { 84 - chain = chain.attr(identifiers.regex).call($.regexp(schema.pattern)); 85 - } 106 + const patternNode = ctx.nodes.pattern(ctx); 107 + if (patternNode) ctx.chain.current = patternNode; 86 108 87 - return chain; 109 + return ctx.chain.current; 110 + } 111 + 112 + export const stringToNode = ({ 113 + plugin, 114 + schema, 115 + }: IrSchemaToAstOptions & { 116 + schema: SchemaWithType<'string'>; 117 + }): Chain => { 118 + const z = plugin.external('zod.z'); 119 + const ctx: StringResolverContext = { 120 + $, 121 + chain: { 122 + current: $(z), 123 + }, 124 + nodes: { 125 + base: baseNode, 126 + const: constNode, 127 + format: formatNode, 128 + length: lengthNode, 129 + maxLength: maxLengthNode, 130 + minLength: minLengthNode, 131 + pattern: patternNode, 132 + }, 133 + plugin, 134 + schema, 135 + symbols: { 136 + z, 137 + }, 138 + }; 139 + const resolver = plugin.config['~resolvers']?.string; 140 + const node = resolver?.(ctx) ?? stringResolver(ctx); 141 + return node; 88 142 };
+29 -15
packages/openapi-ts/src/plugins/zod/v4/api.ts
··· 2 2 3 3 import { identifiers } from '../constants'; 4 4 import type { ValidatorArgs } from '../shared/types'; 5 - import type { ValidatorResolverArgs } from '../types'; 5 + import type { ValidatorResolverContext } from '../types'; 6 6 7 - const defaultValidatorResolver = ({ 8 - schema, 9 - }: ValidatorResolverArgs): ReturnType<typeof $.return> => 10 - $(schema).attr(identifiers.parseAsync).call('data').await().return(); 7 + const validatorResolver = ( 8 + ctx: ValidatorResolverContext, 9 + ): ReturnType<typeof $.return> => { 10 + const { schema } = ctx.symbols; 11 + return $(schema).attr(identifiers.parseAsync).call('data').await().return(); 12 + }; 11 13 12 14 export const createRequestValidatorV4 = ({ 13 15 operation, ··· 22 24 }); 23 25 if (!symbol) return; 24 26 25 - const args: ValidatorResolverArgs = { 27 + const z = plugin.external('zod.z'); 28 + const ctx: ValidatorResolverContext = { 26 29 $, 27 - chain: undefined, 30 + chain: { 31 + current: $(z), 32 + }, 28 33 operation, 29 34 plugin, 30 - schema: symbol, 35 + symbols: { 36 + schema: symbol, 37 + z, 38 + }, 31 39 }; 32 40 const validator = plugin.config['~resolvers']?.validator; 33 41 const resolver = 34 42 typeof validator === 'function' ? validator : validator?.request; 35 - const candidates = [resolver, defaultValidatorResolver]; 43 + const candidates = [resolver, validatorResolver]; 36 44 for (const candidate of candidates) { 37 - const statements = candidate?.(args); 45 + const statements = candidate?.(ctx); 38 46 if (statements === null) return; 39 47 if (statements !== undefined) { 40 48 return $.func() ··· 59 67 }); 60 68 if (!symbol) return; 61 69 62 - const args: ValidatorResolverArgs = { 70 + const z = plugin.external('zod.z'); 71 + const ctx: ValidatorResolverContext = { 63 72 $, 64 - chain: undefined, 73 + chain: { 74 + current: $(z), 75 + }, 65 76 operation, 66 77 plugin, 67 - schema: symbol, 78 + symbols: { 79 + schema: symbol, 80 + z, 81 + }, 68 82 }; 69 83 const validator = plugin.config['~resolvers']?.validator; 70 84 const resolver = 71 85 typeof validator === 'function' ? validator : validator?.response; 72 - const candidates = [resolver, defaultValidatorResolver]; 86 + const candidates = [resolver, validatorResolver]; 73 87 for (const candidate of candidates) { 74 - const statements = candidate?.(args); 88 + const statements = candidate?.(ctx); 75 89 if (statements === null) return; 76 90 if (statements !== undefined) { 77 91 return $.func()
+8 -8
packages/openapi-ts/src/plugins/zod/v4/plugin.ts
··· 5 5 import type { IR } from '~/ir/types'; 6 6 import { buildName } from '~/openApi/shared/utils/name'; 7 7 import type { SchemaWithType } from '~/plugins'; 8 + import { maybeBigInt } from '~/plugins/shared/utils/coerce'; 8 9 import { $ } from '~/ts-dsl'; 9 10 import { pathToJsonPointer, refToName } from '~/utils/ref'; 10 11 11 12 import { identifiers } from '../constants'; 12 13 import { exportAst } from '../shared/export'; 13 14 import { getZodModule } from '../shared/module'; 14 - import { numberParameter } from '../shared/numbers'; 15 15 import { irOperationToAst } from '../shared/operation'; 16 16 import type { Ast, IrSchemaToAstOptions, PluginState } from '../shared/types'; 17 17 import { irWebhookToAst } from '../shared/webhook'; ··· 155 155 } 156 156 157 157 if (schema.default !== undefined) { 158 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 159 - ast.expression = ast.expression.attr(identifiers.default).call( 160 - numberParameter({ 161 - isBigInt, 162 - value: schema.default, 163 - }), 164 - ); 158 + ast.expression = ast.expression 159 + .attr(identifiers.default) 160 + .call( 161 + schema.type === 'integer' || schema.type === 'number' 162 + ? maybeBigInt(schema.default, schema.format) 163 + : $.fromValue(schema.default), 164 + ); 165 165 } 166 166 } 167 167
+13 -7
packages/openapi-ts/src/plugins/zod/v4/toAst/index.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { shouldCoerceToBigInt } from '~/plugins/shared/utils/coerce'; 2 3 3 4 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 4 5 import { arrayToAst } from './array'; ··· 6 7 import { enumToAst } from './enum'; 7 8 import { neverToAst } from './never'; 8 9 import { nullToAst } from './null'; 9 - import { numberToAst } from './number'; 10 + import { numberToNode } from './number'; 10 11 import { objectToAst } from './object'; 11 - import { stringToAst } from './string'; 12 + import { stringToNode } from './string'; 12 13 import { tupleToAst } from './tuple'; 13 14 import { undefinedToAst } from './undefined'; 14 15 import { unknownToAst } from './unknown'; ··· 38 39 }); 39 40 case 'integer': 40 41 case 'number': 41 - return numberToAst({ 42 + return numberToNode({ 42 43 ...args, 43 44 schema: schema as SchemaWithType<'integer' | 'number'>, 44 45 }); ··· 58 59 schema: schema as SchemaWithType<'object'>, 59 60 }); 60 61 case 'string': 61 - return stringToAst({ 62 - ...args, 63 - schema: schema as SchemaWithType<'string'>, 64 - }); 62 + return shouldCoerceToBigInt(schema.format) 63 + ? numberToNode({ 64 + ...args, 65 + schema: { ...schema, type: 'number' }, 66 + }) 67 + : stringToNode({ 68 + ...args, 69 + schema: schema as SchemaWithType<'string'>, 70 + }); 65 71 case 'tuple': 66 72 return tupleToAst({ 67 73 ...args,
+121 -41
packages/openapi-ts/src/plugins/zod/v4/toAst/number.ts
··· 1 1 import type { SchemaWithType } from '~/plugins'; 2 + import { 3 + maybeBigInt, 4 + shouldCoerceToBigInt, 5 + } from '~/plugins/shared/utils/coerce'; 6 + import { getIntegerLimit } from '~/plugins/shared/utils/formats'; 2 7 import { $ } from '~/ts-dsl'; 3 8 4 9 import { identifiers } from '../../constants'; 5 - import { numberParameter } from '../../shared/numbers'; 10 + import type { Chain } from '../../shared/chain'; 6 11 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 12 + import type { NumberResolverContext } from '../../types'; 7 13 8 - export const numberToAst = ({ 9 - plugin, 10 - schema, 11 - }: IrSchemaToAstOptions & { 12 - schema: SchemaWithType<'integer' | 'number'>; 13 - }): Omit<Ast, 'typeName'> => { 14 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 14 + function baseNode(ctx: NumberResolverContext): Chain { 15 + const { schema, symbols } = ctx; 16 + const { z } = symbols; 17 + if (ctx.utils.shouldCoerceToBigInt(schema.format)) { 18 + return $(z).attr(identifiers.coerce).attr(identifiers.bigint).call(); 19 + } 20 + let chain = $(z).attr(identifiers.number).call(); 21 + if (schema.type === 'integer') { 22 + chain = $(z).attr(identifiers.int).call(); 23 + } 24 + return chain; 25 + } 15 26 16 - const isBigInt = schema.type === 'integer' && schema.format === 'int64'; 27 + function constNode(ctx: NumberResolverContext): Chain | undefined { 28 + const { schema, symbols } = ctx; 29 + const { z } = symbols; 30 + if (schema.const === undefined) return; 31 + return $(z) 32 + .attr(identifiers.literal) 33 + .call(ctx.utils.maybeBigInt(schema.const, schema.format)); 34 + } 17 35 18 - const z = plugin.referenceSymbol({ 19 - category: 'external', 20 - resource: 'zod.z', 21 - }); 22 - 23 - if (typeof schema.const === 'number') { 24 - // TODO: parser - handle bigint constants 25 - result.expression = $(z) 26 - .attr(identifiers.literal) 27 - .call($.literal(schema.const)); 28 - return result as Omit<Ast, 'typeName'>; 36 + function maxNode(ctx: NumberResolverContext): Chain | undefined { 37 + const { chain, schema } = ctx; 38 + if (schema.exclusiveMaximum !== undefined) { 39 + return chain.current 40 + .attr(identifiers.lt) 41 + .call(ctx.utils.maybeBigInt(schema.exclusiveMaximum, schema.format)); 29 42 } 30 - 31 - result.expression = isBigInt 32 - ? $(z).attr(identifiers.coerce).attr(identifiers.bigint).call() 33 - : $(z).attr(identifiers.number).call(); 34 - 35 - if (!isBigInt && schema.type === 'integer') { 36 - result.expression = $(z).attr(identifiers.int).call(); 43 + if (schema.maximum !== undefined) { 44 + return chain.current 45 + .attr(identifiers.lte) 46 + .call(ctx.utils.maybeBigInt(schema.maximum, schema.format)); 37 47 } 48 + const limit = ctx.utils.getIntegerLimit(schema.format); 49 + if (limit) { 50 + return chain.current 51 + .attr(identifiers.max) 52 + .call( 53 + ctx.utils.maybeBigInt(limit.maxValue, schema.format), 54 + $.object().prop('error', $.literal(limit.maxError)), 55 + ); 56 + } 57 + return; 58 + } 38 59 60 + function minNode(ctx: NumberResolverContext): Chain | undefined { 61 + const { chain, schema } = ctx; 39 62 if (schema.exclusiveMinimum !== undefined) { 40 - result.expression = result.expression 63 + return chain.current 41 64 .attr(identifiers.gt) 42 - .call(numberParameter({ isBigInt, value: schema.exclusiveMinimum })); 43 - } else if (schema.minimum !== undefined) { 44 - result.expression = result.expression 65 + .call(ctx.utils.maybeBigInt(schema.exclusiveMinimum, schema.format)); 66 + } 67 + if (schema.minimum !== undefined) { 68 + return chain.current 45 69 .attr(identifiers.gte) 46 - .call(numberParameter({ isBigInt, value: schema.minimum })); 70 + .call(ctx.utils.maybeBigInt(schema.minimum, schema.format)); 71 + } 72 + const limit = ctx.utils.getIntegerLimit(schema.format); 73 + if (limit) { 74 + return chain.current 75 + .attr(identifiers.min) 76 + .call( 77 + ctx.utils.maybeBigInt(limit.minValue, schema.format), 78 + $.object().prop('error', $.literal(limit.minError)), 79 + ); 47 80 } 81 + return; 82 + } 48 83 49 - if (schema.exclusiveMaximum !== undefined) { 50 - result.expression = result.expression 51 - .attr(identifiers.lt) 52 - .call(numberParameter({ isBigInt, value: schema.exclusiveMaximum })); 53 - } else if (schema.maximum !== undefined) { 54 - result.expression = result.expression 55 - .attr(identifiers.lte) 56 - .call(numberParameter({ isBigInt, value: schema.maximum })); 84 + function numberResolver(ctx: NumberResolverContext): Chain { 85 + const constNode = ctx.nodes.const(ctx); 86 + if (constNode) { 87 + ctx.chain.current = constNode; 88 + return ctx.chain.current; 57 89 } 58 90 59 - return result as Omit<Ast, 'typeName'>; 91 + const baseNode = ctx.nodes.base(ctx); 92 + if (baseNode) ctx.chain.current = baseNode; 93 + 94 + const minNode = ctx.nodes.min(ctx); 95 + if (minNode) ctx.chain.current = minNode; 96 + 97 + const maxNode = ctx.nodes.max(ctx); 98 + if (maxNode) ctx.chain.current = maxNode; 99 + 100 + return ctx.chain.current; 101 + } 102 + 103 + export const numberToNode = ({ 104 + plugin, 105 + schema, 106 + state, 107 + }: IrSchemaToAstOptions & { 108 + schema: SchemaWithType<'integer' | 'number'>; 109 + }): Omit<Ast, 'typeName'> => { 110 + const ast: Partial<Omit<Ast, 'typeName'>> = {}; 111 + const z = plugin.external('zod.z'); 112 + const ctx: NumberResolverContext = { 113 + $, 114 + chain: { 115 + current: $(z), 116 + }, 117 + nodes: { 118 + base: baseNode, 119 + const: constNode, 120 + max: maxNode, 121 + min: minNode, 122 + }, 123 + plugin, 124 + schema, 125 + symbols: { 126 + z, 127 + }, 128 + utils: { 129 + ast, 130 + getIntegerLimit, 131 + maybeBigInt, 132 + shouldCoerceToBigInt, 133 + state, 134 + }, 135 + }; 136 + const resolver = plugin.config['~resolvers']?.number; 137 + const node = resolver?.(ctx) ?? numberResolver(ctx); 138 + ast.expression = node; 139 + return ast as Omit<Ast, 'typeName'>; 60 140 };
+70 -60
packages/openapi-ts/src/plugins/zod/v4/toAst/object.ts
··· 4 4 import { $ } from '~/ts-dsl'; 5 5 6 6 import { identifiers } from '../../constants'; 7 + import type { Chain } from '../../shared/chain'; 7 8 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 8 - import type { ObjectBaseResolverArgs } from '../../types'; 9 + import type { ObjectResolverContext } from '../../types'; 9 10 import { irSchemaToAst } from '../plugin'; 10 11 11 - function defaultObjectBaseResolver({ 12 - additional, 13 - plugin, 14 - shape, 15 - }: ObjectBaseResolverArgs): ReturnType<typeof $.call> { 16 - const z = plugin.referenceSymbol({ 17 - category: 'external', 18 - resource: 'zod.z', 12 + function additionalPropertiesNode( 13 + ctx: ObjectResolverContext, 14 + ): Chain | null | undefined { 15 + const { plugin, schema } = ctx; 16 + 17 + if ( 18 + !schema.additionalProperties || 19 + (schema.properties && Object.keys(schema.properties).length > 0) 20 + ) 21 + return; 22 + 23 + const additionalAst = irSchemaToAst({ 24 + plugin, 25 + schema: schema.additionalProperties, 26 + state: { 27 + ...ctx.utils.state, 28 + path: ref([...fromRef(ctx.utils.state.path), 'additionalProperties']), 29 + }, 19 30 }); 31 + if (additionalAst.hasLazyExpression) ctx.utils.ast.hasLazyExpression = true; 32 + return additionalAst.expression; 33 + } 34 + 35 + function baseNode(ctx: ObjectResolverContext): Chain { 36 + const { nodes, symbols } = ctx; 37 + const { z } = symbols; 38 + 39 + const additional = nodes.additionalProperties(ctx); 40 + const shape = nodes.shape(ctx); 20 41 21 42 if (additional) { 22 43 return $(z) ··· 27 48 return $(z).attr(identifiers.object).call(shape); 28 49 } 29 50 30 - export const objectToAst = ({ 31 - plugin, 32 - schema, 33 - state, 34 - }: IrSchemaToAstOptions & { 35 - schema: SchemaWithType<'object'>; 36 - }): Omit<Ast, 'typeName'> => { 37 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 38 - 51 + function objectResolver(ctx: ObjectResolverContext): Chain { 39 52 // TODO: parser - handle constants 53 + return ctx.nodes.base(ctx); 54 + } 40 55 56 + function shapeNode(ctx: ObjectResolverContext): ReturnType<typeof $.object> { 57 + const { plugin, schema } = ctx; 41 58 const shape = $.object().pretty(); 42 - const required = schema.required ?? []; 43 59 44 60 for (const name in schema.properties) { 45 61 const property = schema.properties[name]!; 46 - const isRequired = required.includes(name); 47 62 48 63 const propertyAst = irSchemaToAst({ 49 - optional: !isRequired, 64 + optional: !schema.required?.includes(name), 50 65 plugin, 51 66 schema: property, 52 67 state: { 53 - ...state, 54 - path: ref([...fromRef(state.path), 'properties', name]), 68 + ...ctx.utils.state, 69 + path: ref([...fromRef(ctx.utils.state.path), 'properties', name]), 55 70 }, 56 71 }); 57 72 if (propertyAst.hasLazyExpression) { 58 - result.hasLazyExpression = true; 59 - } 60 - 61 - if (propertyAst.hasLazyExpression) { 73 + ctx.utils.ast.hasLazyExpression = true; 62 74 shape.getter(name, propertyAst.expression.return()); 63 75 } else { 64 76 shape.prop(name, propertyAst.expression); 65 77 } 66 78 } 67 79 68 - let additional: ReturnType<typeof $.call | typeof $.expr> | null | undefined; 69 - if ( 70 - schema.additionalProperties && 71 - (!schema.properties || !Object.keys(schema.properties).length) 72 - ) { 73 - const additionalAst = irSchemaToAst({ 74 - plugin, 75 - schema: schema.additionalProperties, 76 - state: { 77 - ...state, 78 - path: ref([...fromRef(state.path), 'additionalProperties']), 79 - }, 80 - }); 81 - if (additionalAst.hasLazyExpression) result.hasLazyExpression = true; 82 - additional = additionalAst.expression; 83 - } 80 + return shape; 81 + } 84 82 85 - const args: ObjectBaseResolverArgs = { 83 + export const objectToAst = ({ 84 + plugin, 85 + schema, 86 + state, 87 + }: IrSchemaToAstOptions & { 88 + schema: SchemaWithType<'object'>; 89 + }): Omit<Ast, 'typeName'> => { 90 + const ast: Partial<Omit<Ast, 'typeName'>> = {}; 91 + const z = plugin.external('zod.z'); 92 + const ctx: ObjectResolverContext = { 86 93 $, 87 - additional, 88 - chain: undefined, 94 + chain: { 95 + current: $(z), 96 + }, 97 + nodes: { 98 + additionalProperties: additionalPropertiesNode, 99 + base: baseNode, 100 + shape: shapeNode, 101 + }, 89 102 plugin, 90 103 schema, 91 - shape, 104 + symbols: { 105 + z, 106 + }, 107 + utils: { 108 + ast, 109 + state, 110 + }, 92 111 }; 93 - const resolver = plugin.config['~resolvers']?.object?.base; 94 - const chain = resolver?.(args) ?? defaultObjectBaseResolver(args); 95 - result.expression = chain; 96 - 97 - // Return with typeName for circular references 98 - if (result.hasLazyExpression) { 99 - return { 100 - ...result, 101 - typeName: 'ZodType', 102 - } as Ast; 103 - } 104 - 105 - return result as Omit<Ast, 'typeName'>; 112 + const resolver = plugin.config['~resolvers']?.object; 113 + const node = resolver?.(ctx) ?? objectResolver(ctx); 114 + ast.expression = node; 115 + return ast as Omit<Ast, 'typeName'>; 106 116 };
+98 -49
packages/openapi-ts/src/plugins/zod/v4/toAst/string.ts
··· 2 2 import { $ } from '~/ts-dsl'; 3 3 4 4 import { identifiers } from '../../constants'; 5 + import type { Chain } from '../../shared/chain'; 5 6 import type { Ast, IrSchemaToAstOptions } from '../../shared/types'; 6 - import type { FormatResolverArgs } from '../../types'; 7 + import type { StringResolverContext } from '../../types'; 8 + 9 + function baseNode(ctx: StringResolverContext): Chain { 10 + const { z } = ctx.symbols; 11 + return $(z).attr(identifiers.string).call(); 12 + } 13 + 14 + function constNode(ctx: StringResolverContext): Chain | undefined { 15 + const { schema, symbols } = ctx; 16 + const { z } = symbols; 17 + if (typeof schema.const !== 'string') return; 18 + return $(z).attr(identifiers.literal).call($.literal(schema.const)); 19 + } 7 20 8 - const defaultFormatResolver = ({ 9 - chain, 10 - plugin, 11 - schema, 12 - }: FormatResolverArgs): ReturnType<typeof $.call> => { 13 - const z = plugin.referenceSymbol({ 14 - category: 'external', 15 - resource: 'zod.z', 16 - }); 21 + function formatNode(ctx: StringResolverContext): Chain | undefined { 22 + const { plugin, schema, symbols } = ctx; 23 + const { z } = symbols; 17 24 18 25 switch (schema.format) { 19 26 case 'date': ··· 43 50 return $(z).attr(identifiers.url).call(); 44 51 case 'uuid': 45 52 return $(z).attr(identifiers.uuid).call(); 46 - default: 47 - return chain; 48 53 } 49 - }; 50 54 51 - export const stringToAst = ({ 52 - plugin, 53 - schema, 54 - }: IrSchemaToAstOptions & { 55 - schema: SchemaWithType<'string'>; 56 - }): Omit<Ast, 'typeName'> => { 57 - const result: Partial<Omit<Ast, 'typeName'>> = {}; 58 - let chain: ReturnType<typeof $.call>; 55 + return; 56 + } 57 + 58 + function lengthNode(ctx: StringResolverContext): Chain | undefined { 59 + const { chain, schema } = ctx; 60 + if (schema.minLength === undefined || schema.minLength !== schema.maxLength) 61 + return; 62 + return chain.current 63 + .attr(identifiers.length) 64 + .call($.literal(schema.minLength)); 65 + } 66 + 67 + function maxLengthNode(ctx: StringResolverContext): Chain | undefined { 68 + const { chain, schema } = ctx; 69 + if (schema.maxLength === undefined) return; 70 + return chain.current.attr(identifiers.max).call($.literal(schema.maxLength)); 71 + } 72 + 73 + function minLengthNode(ctx: StringResolverContext): Chain | undefined { 74 + const { chain, schema } = ctx; 75 + if (schema.minLength === undefined) return; 76 + return chain.current.attr(identifiers.min).call($.literal(schema.minLength)); 77 + } 59 78 60 - const z = plugin.referenceSymbol({ 61 - category: 'external', 62 - resource: 'zod.z', 63 - }); 79 + function patternNode(ctx: StringResolverContext): Chain | undefined { 80 + const { chain, schema } = ctx; 81 + if (!schema.pattern) return; 82 + return chain.current.attr(identifiers.regex).call($.regexp(schema.pattern)); 83 + } 64 84 65 - if (typeof schema.const === 'string') { 66 - chain = $(z).attr(identifiers.literal).call($.literal(schema.const)); 67 - result.expression = chain; 68 - return result as Omit<Ast, 'typeName'>; 85 + function stringResolver(ctx: StringResolverContext): Chain { 86 + const constNode = ctx.nodes.const(ctx); 87 + if (constNode) { 88 + ctx.chain.current = constNode; 89 + return ctx.chain.current; 69 90 } 70 91 71 - chain = $(z).attr(identifiers.string).call(); 92 + const baseNode = ctx.nodes.base(ctx); 93 + if (baseNode) ctx.chain.current = baseNode; 72 94 73 - if (schema.format) { 74 - const args: FormatResolverArgs = { $, chain, plugin, schema }; 75 - const resolver = 76 - plugin.config['~resolvers']?.string?.formats?.[schema.format]; 77 - chain = resolver?.(args) ?? defaultFormatResolver(args); 78 - } 95 + const formatNode = ctx.nodes.format(ctx); 96 + if (formatNode) ctx.chain.current = formatNode; 79 97 80 - if (schema.minLength === schema.maxLength && schema.minLength !== undefined) { 81 - chain = chain.attr(identifiers.length).call($.literal(schema.minLength)); 98 + const lengthNode = ctx.nodes.length(ctx); 99 + if (lengthNode) { 100 + ctx.chain.current = lengthNode; 82 101 } else { 83 - if (schema.minLength !== undefined) { 84 - chain = chain.attr(identifiers.min).call($.literal(schema.minLength)); 85 - } 102 + const minLengthNode = ctx.nodes.minLength(ctx); 103 + if (minLengthNode) ctx.chain.current = minLengthNode; 86 104 87 - if (schema.maxLength !== undefined) { 88 - chain = chain.attr(identifiers.max).call($.literal(schema.maxLength)); 89 - } 105 + const maxLengthNode = ctx.nodes.maxLength(ctx); 106 + if (maxLengthNode) ctx.chain.current = maxLengthNode; 90 107 } 91 108 92 - if (schema.pattern) { 93 - chain = chain.attr(identifiers.regex).call($.regexp(schema.pattern)); 94 - } 109 + const patternNode = ctx.nodes.pattern(ctx); 110 + if (patternNode) ctx.chain.current = patternNode; 111 + 112 + return ctx.chain.current; 113 + } 95 114 96 - result.expression = chain; 97 - return result as Omit<Ast, 'typeName'>; 115 + export const stringToNode = ({ 116 + plugin, 117 + schema, 118 + }: IrSchemaToAstOptions & { 119 + schema: SchemaWithType<'string'>; 120 + }): Omit<Ast, 'typeName'> => { 121 + const z = plugin.external('zod.z'); 122 + const ctx: StringResolverContext = { 123 + $, 124 + chain: { 125 + current: $(z), 126 + }, 127 + nodes: { 128 + base: baseNode, 129 + const: constNode, 130 + format: formatNode, 131 + length: lengthNode, 132 + maxLength: maxLengthNode, 133 + minLength: minLengthNode, 134 + pattern: patternNode, 135 + }, 136 + plugin, 137 + schema, 138 + symbols: { 139 + z, 140 + }, 141 + }; 142 + const resolver = plugin.config['~resolvers']?.string; 143 + const node = resolver?.(ctx) ?? stringResolver(ctx); 144 + return { 145 + expression: node, 146 + }; 98 147 };
+3 -5
packages/openapi-ts/src/ts-dsl/expr/fromValue.ts
··· 16 16 return input as TsDsl<ts.Expression>; 17 17 } 18 18 19 - if (input === null) { 20 - return new LiteralTsDsl(input); 21 - } 22 - 23 19 if ( 20 + input === null || 24 21 typeof input === 'number' || 25 22 typeof input === 'boolean' || 26 - typeof input === 'string' 23 + typeof input === 'string' || 24 + typeof input === 'bigint' 27 25 ) { 28 26 return new LiteralTsDsl(input); 29 27 }
+7 -2
packages/openapi-ts/src/ts-dsl/expr/literal.ts
··· 5 5 import { PrefixTsDsl } from '../expr/prefix'; 6 6 import { AsMixin } from '../mixins/as'; 7 7 8 + export type LiteralValue = string | number | boolean | bigint | null; 9 + 8 10 const Mixed = AsMixin(TsDsl<ts.LiteralTypeNode['literal']>); 9 11 10 12 export class LiteralTsDsl extends Mixed { 11 13 readonly '~dsl' = 'LiteralTsDsl'; 12 14 13 - protected value: string | number | boolean | null; 15 + protected value: LiteralValue; 14 16 15 - constructor(value: string | number | boolean | null) { 17 + constructor(value: LiteralValue) { 16 18 super(); 17 19 this.value = value; 18 20 } ··· 33 35 } 34 36 if (typeof this.value === 'string') { 35 37 return ts.factory.createStringLiteral(this.value, true); 38 + } 39 + if (typeof this.value === 'bigint') { 40 + return ts.factory.createBigIntLiteral(this.value.toString()); 36 41 } 37 42 if (this.value === null) { 38 43 return ts.factory.createNull();
+80
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/angular-query-experimental.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { type DefaultError, queryOptions } from '@tanstack/angular-query-experimental'; 4 + 5 + import { client } from '../client.gen'; 6 + import { getBar, getFoo, type Options } from '../sdk.gen'; 7 + import type { GetBarData, GetFooData } from '../types.gen'; 8 + 9 + export type QueryKey<TOptions extends Options> = [ 10 + Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & { 11 + _id: string; 12 + _infinite?: boolean; 13 + tags?: ReadonlyArray<string>; 14 + } 15 + ]; 16 + 17 + const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean, tags?: ReadonlyArray<string>): [ 18 + QueryKey<TOptions>[0] 19 + ] => { 20 + const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: options?.baseUrl || (options?.client ?? client).getConfig().baseUrl } as QueryKey<TOptions>[0]; 21 + if (infinite) { 22 + params._infinite = infinite; 23 + } 24 + if (tags) { 25 + params.tags = tags; 26 + } 27 + if (options?.body) { 28 + params.body = options.body; 29 + } 30 + if (options?.headers) { 31 + params.headers = options.headers; 32 + } 33 + if (options?.path) { 34 + params.path = options.path; 35 + } 36 + if (options?.query) { 37 + params.query = options.query; 38 + } 39 + return [params]; 40 + }; 41 + 42 + export const getFooQueryKey = (options?: Options<GetFooData>) => createQueryKey('getFoo', options); 43 + 44 + export const getFooOptions = (options?: Options<GetFooData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getFooQueryKey>>({ 45 + queryFn: async ({ queryKey, signal }) => { 46 + const { data } = await getFoo({ 47 + ...options, 48 + ...queryKey[0], 49 + signal, 50 + throwOnError: true 51 + }); 52 + return data; 53 + }, 54 + queryKey: getFooQueryKey(options), 55 + meta: { 56 + id: 'getFoo', 57 + method: 'get', 58 + path: '/foo' 59 + } 60 + }); 61 + 62 + export const getBarQueryKey = (options?: Options<GetBarData>) => createQueryKey('getBar', options); 63 + 64 + export const getBarOptions = (options?: Options<GetBarData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getBarQueryKey>>({ 65 + queryFn: async ({ queryKey, signal }) => { 66 + const { data } = await getBar({ 67 + ...options, 68 + ...queryKey[0], 69 + signal, 70 + throwOnError: true 71 + }); 72 + return data; 73 + }, 74 + queryKey: getBarQueryKey(options), 75 + meta: { 76 + id: 'getBar', 77 + method: 'get', 78 + path: '/bar' 79 + } 80 + });
+80
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/react-query.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { type DefaultError, queryOptions } from '@tanstack/react-query'; 4 + 5 + import { client } from '../client.gen'; 6 + import { getBar, getFoo, type Options } from '../sdk.gen'; 7 + import type { GetBarData, GetFooData } from '../types.gen'; 8 + 9 + export type QueryKey<TOptions extends Options> = [ 10 + Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & { 11 + _id: string; 12 + _infinite?: boolean; 13 + tags?: ReadonlyArray<string>; 14 + } 15 + ]; 16 + 17 + const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean, tags?: ReadonlyArray<string>): [ 18 + QueryKey<TOptions>[0] 19 + ] => { 20 + const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: options?.baseUrl || (options?.client ?? client).getConfig().baseUrl } as QueryKey<TOptions>[0]; 21 + if (infinite) { 22 + params._infinite = infinite; 23 + } 24 + if (tags) { 25 + params.tags = tags; 26 + } 27 + if (options?.body) { 28 + params.body = options.body; 29 + } 30 + if (options?.headers) { 31 + params.headers = options.headers; 32 + } 33 + if (options?.path) { 34 + params.path = options.path; 35 + } 36 + if (options?.query) { 37 + params.query = options.query; 38 + } 39 + return [params]; 40 + }; 41 + 42 + export const getFooQueryKey = (options?: Options<GetFooData>) => createQueryKey('getFoo', options); 43 + 44 + export const getFooOptions = (options?: Options<GetFooData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getFooQueryKey>>({ 45 + queryFn: async ({ queryKey, signal }) => { 46 + const { data } = await getFoo({ 47 + ...options, 48 + ...queryKey[0], 49 + signal, 50 + throwOnError: true 51 + }); 52 + return data; 53 + }, 54 + queryKey: getFooQueryKey(options), 55 + meta: { 56 + id: 'getFoo', 57 + method: 'get', 58 + path: '/foo' 59 + } 60 + }); 61 + 62 + export const getBarQueryKey = (options?: Options<GetBarData>) => createQueryKey('getBar', options); 63 + 64 + export const getBarOptions = (options?: Options<GetBarData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getBarQueryKey>>({ 65 + queryFn: async ({ queryKey, signal }) => { 66 + const { data } = await getBar({ 67 + ...options, 68 + ...queryKey[0], 69 + signal, 70 + throwOnError: true 71 + }); 72 + return data; 73 + }, 74 + queryKey: getBarQueryKey(options), 75 + meta: { 76 + id: 'getBar', 77 + method: 'get', 78 + path: '/bar' 79 + } 80 + });
+80
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/solid-query.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { type DefaultError, queryOptions } from '@tanstack/solid-query'; 4 + 5 + import { client } from '../client.gen'; 6 + import { getBar, getFoo, type Options } from '../sdk.gen'; 7 + import type { GetBarData, GetFooData } from '../types.gen'; 8 + 9 + export type QueryKey<TOptions extends Options> = [ 10 + Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & { 11 + _id: string; 12 + _infinite?: boolean; 13 + tags?: ReadonlyArray<string>; 14 + } 15 + ]; 16 + 17 + const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean, tags?: ReadonlyArray<string>): [ 18 + QueryKey<TOptions>[0] 19 + ] => { 20 + const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: options?.baseUrl || (options?.client ?? client).getConfig().baseUrl } as QueryKey<TOptions>[0]; 21 + if (infinite) { 22 + params._infinite = infinite; 23 + } 24 + if (tags) { 25 + params.tags = tags; 26 + } 27 + if (options?.body) { 28 + params.body = options.body; 29 + } 30 + if (options?.headers) { 31 + params.headers = options.headers; 32 + } 33 + if (options?.path) { 34 + params.path = options.path; 35 + } 36 + if (options?.query) { 37 + params.query = options.query; 38 + } 39 + return [params]; 40 + }; 41 + 42 + export const getFooQueryKey = (options?: Options<GetFooData>) => createQueryKey('getFoo', options); 43 + 44 + export const getFooOptions = (options?: Options<GetFooData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getFooQueryKey>>({ 45 + queryFn: async ({ queryKey, signal }) => { 46 + const { data } = await getFoo({ 47 + ...options, 48 + ...queryKey[0], 49 + signal, 50 + throwOnError: true 51 + }); 52 + return data; 53 + }, 54 + queryKey: getFooQueryKey(options), 55 + meta: { 56 + id: 'getFoo', 57 + method: 'get', 58 + path: '/foo' 59 + } 60 + }); 61 + 62 + export const getBarQueryKey = (options?: Options<GetBarData>) => createQueryKey('getBar', options); 63 + 64 + export const getBarOptions = (options?: Options<GetBarData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getBarQueryKey>>({ 65 + queryFn: async ({ queryKey, signal }) => { 66 + const { data } = await getBar({ 67 + ...options, 68 + ...queryKey[0], 69 + signal, 70 + throwOnError: true 71 + }); 72 + return data; 73 + }, 74 + queryKey: getBarQueryKey(options), 75 + meta: { 76 + id: 'getBar', 77 + method: 'get', 78 + path: '/bar' 79 + } 80 + });
+80
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/svelte-query.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { type DefaultError, queryOptions } from '@tanstack/svelte-query'; 4 + 5 + import { client } from '../client.gen'; 6 + import { getBar, getFoo, type Options } from '../sdk.gen'; 7 + import type { GetBarData, GetFooData } from '../types.gen'; 8 + 9 + export type QueryKey<TOptions extends Options> = [ 10 + Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & { 11 + _id: string; 12 + _infinite?: boolean; 13 + tags?: ReadonlyArray<string>; 14 + } 15 + ]; 16 + 17 + const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean, tags?: ReadonlyArray<string>): [ 18 + QueryKey<TOptions>[0] 19 + ] => { 20 + const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: options?.baseUrl || (options?.client ?? client).getConfig().baseUrl } as QueryKey<TOptions>[0]; 21 + if (infinite) { 22 + params._infinite = infinite; 23 + } 24 + if (tags) { 25 + params.tags = tags; 26 + } 27 + if (options?.body) { 28 + params.body = options.body; 29 + } 30 + if (options?.headers) { 31 + params.headers = options.headers; 32 + } 33 + if (options?.path) { 34 + params.path = options.path; 35 + } 36 + if (options?.query) { 37 + params.query = options.query; 38 + } 39 + return [params]; 40 + }; 41 + 42 + export const getFooQueryKey = (options?: Options<GetFooData>) => createQueryKey('getFoo', options); 43 + 44 + export const getFooOptions = (options?: Options<GetFooData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getFooQueryKey>>({ 45 + queryFn: async ({ queryKey, signal }) => { 46 + const { data } = await getFoo({ 47 + ...options, 48 + ...queryKey[0], 49 + signal, 50 + throwOnError: true 51 + }); 52 + return data; 53 + }, 54 + queryKey: getFooQueryKey(options), 55 + meta: { 56 + id: 'getFoo', 57 + method: 'get', 58 + path: '/foo' 59 + } 60 + }); 61 + 62 + export const getBarQueryKey = (options?: Options<GetBarData>) => createQueryKey('getBar', options); 63 + 64 + export const getBarOptions = (options?: Options<GetBarData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getBarQueryKey>>({ 65 + queryFn: async ({ queryKey, signal }) => { 66 + const { data } = await getBar({ 67 + ...options, 68 + ...queryKey[0], 69 + signal, 70 + throwOnError: true 71 + }); 72 + return data; 73 + }, 74 + queryKey: getBarQueryKey(options), 75 + meta: { 76 + id: 'getBar', 77 + method: 'get', 78 + path: '/bar' 79 + } 80 + });
+80
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/vue-query.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { type DefaultError, queryOptions } from '@tanstack/vue-query'; 4 + 5 + import { client } from '../client.gen'; 6 + import { getBar, getFoo, type Options } from '../sdk.gen'; 7 + import type { GetBarData, GetFooData } from '../types.gen'; 8 + 9 + export type QueryKey<TOptions extends Options> = [ 10 + Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & { 11 + _id: string; 12 + _infinite?: boolean; 13 + tags?: ReadonlyArray<string>; 14 + } 15 + ]; 16 + 17 + const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean, tags?: ReadonlyArray<string>): [ 18 + QueryKey<TOptions>[0] 19 + ] => { 20 + const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: options?.baseUrl || (options?.client ?? client).getConfig().baseUrl } as QueryKey<TOptions>[0]; 21 + if (infinite) { 22 + params._infinite = infinite; 23 + } 24 + if (tags) { 25 + params.tags = tags; 26 + } 27 + if (options?.body) { 28 + params.body = options.body; 29 + } 30 + if (options?.headers) { 31 + params.headers = options.headers; 32 + } 33 + if (options?.path) { 34 + params.path = options.path; 35 + } 36 + if (options?.query) { 37 + params.query = options.query; 38 + } 39 + return [params]; 40 + }; 41 + 42 + export const getFooQueryKey = (options?: Options<GetFooData>) => createQueryKey('getFoo', options); 43 + 44 + export const getFooOptions = (options?: Options<GetFooData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getFooQueryKey>>({ 45 + queryFn: async ({ queryKey, signal }) => { 46 + const { data } = await getFoo({ 47 + ...options, 48 + ...queryKey[0], 49 + signal, 50 + throwOnError: true 51 + }); 52 + return data; 53 + }, 54 + queryKey: getFooQueryKey(options), 55 + meta: { 56 + id: 'getFoo', 57 + method: 'get', 58 + path: '/foo' 59 + } 60 + }); 61 + 62 + export const getBarQueryKey = (options?: Options<GetBarData>) => createQueryKey('getBar', options); 63 + 64 + export const getBarOptions = (options?: Options<GetBarData>) => queryOptions<unknown, DefaultError, unknown, ReturnType<typeof getBarQueryKey>>({ 65 + queryFn: async ({ queryKey, signal }) => { 66 + const { data } = await getBar({ 67 + ...options, 68 + ...queryKey[0], 69 + signal, 70 + throwOnError: true 71 + }); 72 + return data; 73 + }, 74 + queryKey: getBarQueryKey(options), 75 + meta: { 76 + id: 'getBar', 77 + method: 'get', 78 + path: '/bar' 79 + } 80 + });
+301
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/client/client.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { createSseClient } from '../core/serverSentEvents.gen'; 4 + import type { HttpMethod } from '../core/types.gen'; 5 + import { getValidRequestBody } from '../core/utils.gen'; 6 + import type { 7 + Client, 8 + Config, 9 + RequestOptions, 10 + ResolvedRequestOptions, 11 + } from './types.gen'; 12 + import { 13 + buildUrl, 14 + createConfig, 15 + createInterceptors, 16 + getParseAs, 17 + mergeConfigs, 18 + mergeHeaders, 19 + setAuthParams, 20 + } from './utils.gen'; 21 + 22 + type ReqInit = Omit<RequestInit, 'body' | 'headers'> & { 23 + body?: any; 24 + headers: ReturnType<typeof mergeHeaders>; 25 + }; 26 + 27 + export const createClient = (config: Config = {}): Client => { 28 + let _config = mergeConfigs(createConfig(), config); 29 + 30 + const getConfig = (): Config => ({ ..._config }); 31 + 32 + const setConfig = (config: Config): Config => { 33 + _config = mergeConfigs(_config, config); 34 + return getConfig(); 35 + }; 36 + 37 + const interceptors = createInterceptors< 38 + Request, 39 + Response, 40 + unknown, 41 + ResolvedRequestOptions 42 + >(); 43 + 44 + const beforeRequest = async (options: RequestOptions) => { 45 + const opts = { 46 + ..._config, 47 + ...options, 48 + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, 49 + headers: mergeHeaders(_config.headers, options.headers), 50 + serializedBody: undefined, 51 + }; 52 + 53 + if (opts.security) { 54 + await setAuthParams({ 55 + ...opts, 56 + security: opts.security, 57 + }); 58 + } 59 + 60 + if (opts.requestValidator) { 61 + await opts.requestValidator(opts); 62 + } 63 + 64 + if (opts.body !== undefined && opts.bodySerializer) { 65 + opts.serializedBody = opts.bodySerializer(opts.body); 66 + } 67 + 68 + // remove Content-Type header if body is empty to avoid sending invalid requests 69 + if (opts.body === undefined || opts.serializedBody === '') { 70 + opts.headers.delete('Content-Type'); 71 + } 72 + 73 + const url = buildUrl(opts); 74 + 75 + return { opts, url }; 76 + }; 77 + 78 + const request: Client['request'] = async (options) => { 79 + // @ts-expect-error 80 + const { opts, url } = await beforeRequest(options); 81 + const requestInit: ReqInit = { 82 + redirect: 'follow', 83 + ...opts, 84 + body: getValidRequestBody(opts), 85 + }; 86 + 87 + let request = new Request(url, requestInit); 88 + 89 + for (const fn of interceptors.request.fns) { 90 + if (fn) { 91 + request = await fn(request, opts); 92 + } 93 + } 94 + 95 + // fetch must be assigned here, otherwise it would throw the error: 96 + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation 97 + const _fetch = opts.fetch!; 98 + let response: Response; 99 + 100 + try { 101 + response = await _fetch(request); 102 + } catch (error) { 103 + // Handle fetch exceptions (AbortError, network errors, etc.) 104 + let finalError = error; 105 + 106 + for (const fn of interceptors.error.fns) { 107 + if (fn) { 108 + finalError = (await fn( 109 + error, 110 + undefined as any, 111 + request, 112 + opts, 113 + )) as unknown; 114 + } 115 + } 116 + 117 + finalError = finalError || ({} as unknown); 118 + 119 + if (opts.throwOnError) { 120 + throw finalError; 121 + } 122 + 123 + // Return error response 124 + return opts.responseStyle === 'data' 125 + ? undefined 126 + : { 127 + error: finalError, 128 + request, 129 + response: undefined as any, 130 + }; 131 + } 132 + 133 + for (const fn of interceptors.response.fns) { 134 + if (fn) { 135 + response = await fn(response, request, opts); 136 + } 137 + } 138 + 139 + const result = { 140 + request, 141 + response, 142 + }; 143 + 144 + if (response.ok) { 145 + const parseAs = 146 + (opts.parseAs === 'auto' 147 + ? getParseAs(response.headers.get('Content-Type')) 148 + : opts.parseAs) ?? 'json'; 149 + 150 + if ( 151 + response.status === 204 || 152 + response.headers.get('Content-Length') === '0' 153 + ) { 154 + let emptyData: any; 155 + switch (parseAs) { 156 + case 'arrayBuffer': 157 + case 'blob': 158 + case 'text': 159 + emptyData = await response[parseAs](); 160 + break; 161 + case 'formData': 162 + emptyData = new FormData(); 163 + break; 164 + case 'stream': 165 + emptyData = response.body; 166 + break; 167 + case 'json': 168 + default: 169 + emptyData = {}; 170 + break; 171 + } 172 + return opts.responseStyle === 'data' 173 + ? emptyData 174 + : { 175 + data: emptyData, 176 + ...result, 177 + }; 178 + } 179 + 180 + let data: any; 181 + switch (parseAs) { 182 + case 'arrayBuffer': 183 + case 'blob': 184 + case 'formData': 185 + case 'json': 186 + case 'text': 187 + data = await response[parseAs](); 188 + break; 189 + case 'stream': 190 + return opts.responseStyle === 'data' 191 + ? response.body 192 + : { 193 + data: response.body, 194 + ...result, 195 + }; 196 + } 197 + 198 + if (parseAs === 'json') { 199 + if (opts.responseValidator) { 200 + await opts.responseValidator(data); 201 + } 202 + 203 + if (opts.responseTransformer) { 204 + data = await opts.responseTransformer(data); 205 + } 206 + } 207 + 208 + return opts.responseStyle === 'data' 209 + ? data 210 + : { 211 + data, 212 + ...result, 213 + }; 214 + } 215 + 216 + const textError = await response.text(); 217 + let jsonError: unknown; 218 + 219 + try { 220 + jsonError = JSON.parse(textError); 221 + } catch { 222 + // noop 223 + } 224 + 225 + const error = jsonError ?? textError; 226 + let finalError = error; 227 + 228 + for (const fn of interceptors.error.fns) { 229 + if (fn) { 230 + finalError = (await fn(error, response, request, opts)) as string; 231 + } 232 + } 233 + 234 + finalError = finalError || ({} as string); 235 + 236 + if (opts.throwOnError) { 237 + throw finalError; 238 + } 239 + 240 + // TODO: we probably want to return error and improve types 241 + return opts.responseStyle === 'data' 242 + ? undefined 243 + : { 244 + error: finalError, 245 + ...result, 246 + }; 247 + }; 248 + 249 + const makeMethodFn = 250 + (method: Uppercase<HttpMethod>) => (options: RequestOptions) => 251 + request({ ...options, method }); 252 + 253 + const makeSseFn = 254 + (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => { 255 + const { opts, url } = await beforeRequest(options); 256 + return createSseClient({ 257 + ...opts, 258 + body: opts.body as BodyInit | null | undefined, 259 + headers: opts.headers as unknown as Record<string, string>, 260 + method, 261 + onRequest: async (url, init) => { 262 + let request = new Request(url, init); 263 + for (const fn of interceptors.request.fns) { 264 + if (fn) { 265 + request = await fn(request, opts); 266 + } 267 + } 268 + return request; 269 + }, 270 + url, 271 + }); 272 + }; 273 + 274 + return { 275 + buildUrl, 276 + connect: makeMethodFn('CONNECT'), 277 + delete: makeMethodFn('DELETE'), 278 + get: makeMethodFn('GET'), 279 + getConfig, 280 + head: makeMethodFn('HEAD'), 281 + interceptors, 282 + options: makeMethodFn('OPTIONS'), 283 + patch: makeMethodFn('PATCH'), 284 + post: makeMethodFn('POST'), 285 + put: makeMethodFn('PUT'), 286 + request, 287 + setConfig, 288 + sse: { 289 + connect: makeSseFn('CONNECT'), 290 + delete: makeSseFn('DELETE'), 291 + get: makeSseFn('GET'), 292 + head: makeSseFn('HEAD'), 293 + options: makeSseFn('OPTIONS'), 294 + patch: makeSseFn('PATCH'), 295 + post: makeSseFn('POST'), 296 + put: makeSseFn('PUT'), 297 + trace: makeSseFn('TRACE'), 298 + }, 299 + trace: makeMethodFn('TRACE'), 300 + } as Client; 301 + };
+25
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/client/index.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type { Auth } from '../core/auth.gen'; 4 + export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; 5 + export { 6 + formDataBodySerializer, 7 + jsonBodySerializer, 8 + urlSearchParamsBodySerializer, 9 + } from '../core/bodySerializer.gen'; 10 + export { buildClientParams } from '../core/params.gen'; 11 + export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; 12 + export { createClient } from './client.gen'; 13 + export type { 14 + Client, 15 + ClientOptions, 16 + Config, 17 + CreateClientConfig, 18 + Options, 19 + RequestOptions, 20 + RequestResult, 21 + ResolvedRequestOptions, 22 + ResponseStyle, 23 + TDataShape, 24 + } from './types.gen'; 25 + export { createConfig, mergeHeaders } from './utils.gen';
+241
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/client/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Auth } from '../core/auth.gen'; 4 + import type { 5 + ServerSentEventsOptions, 6 + ServerSentEventsResult, 7 + } from '../core/serverSentEvents.gen'; 8 + import type { 9 + Client as CoreClient, 10 + Config as CoreConfig, 11 + } from '../core/types.gen'; 12 + import type { Middleware } from './utils.gen'; 13 + 14 + export type ResponseStyle = 'data' | 'fields'; 15 + 16 + export interface Config<T extends ClientOptions = ClientOptions> 17 + extends Omit<RequestInit, 'body' | 'headers' | 'method'>, 18 + CoreConfig { 19 + /** 20 + * Base URL for all requests made by this client. 21 + */ 22 + baseUrl?: T['baseUrl']; 23 + /** 24 + * Fetch API implementation. You can use this option to provide a custom 25 + * fetch instance. 26 + * 27 + * @default globalThis.fetch 28 + */ 29 + fetch?: typeof fetch; 30 + /** 31 + * Please don't use the Fetch client for Next.js applications. The `next` 32 + * options won't have any effect. 33 + * 34 + * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. 35 + */ 36 + next?: never; 37 + /** 38 + * Return the response data parsed in a specified format. By default, `auto` 39 + * will infer the appropriate method from the `Content-Type` response header. 40 + * You can override this behavior with any of the {@link Body} methods. 41 + * Select `stream` if you don't want to parse response data at all. 42 + * 43 + * @default 'auto' 44 + */ 45 + parseAs?: 46 + | 'arrayBuffer' 47 + | 'auto' 48 + | 'blob' 49 + | 'formData' 50 + | 'json' 51 + | 'stream' 52 + | 'text'; 53 + /** 54 + * Should we return only data or multiple fields (data, error, response, etc.)? 55 + * 56 + * @default 'fields' 57 + */ 58 + responseStyle?: ResponseStyle; 59 + /** 60 + * Throw an error instead of returning it in the response? 61 + * 62 + * @default false 63 + */ 64 + throwOnError?: T['throwOnError']; 65 + } 66 + 67 + export interface RequestOptions< 68 + TData = unknown, 69 + TResponseStyle extends ResponseStyle = 'fields', 70 + ThrowOnError extends boolean = boolean, 71 + Url extends string = string, 72 + > extends Config<{ 73 + responseStyle: TResponseStyle; 74 + throwOnError: ThrowOnError; 75 + }>, 76 + Pick< 77 + ServerSentEventsOptions<TData>, 78 + | 'onSseError' 79 + | 'onSseEvent' 80 + | 'sseDefaultRetryDelay' 81 + | 'sseMaxRetryAttempts' 82 + | 'sseMaxRetryDelay' 83 + > { 84 + /** 85 + * Any body that you want to add to your request. 86 + * 87 + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} 88 + */ 89 + body?: unknown; 90 + path?: Record<string, unknown>; 91 + query?: Record<string, unknown>; 92 + /** 93 + * Security mechanism(s) to use for the request. 94 + */ 95 + security?: ReadonlyArray<Auth>; 96 + url: Url; 97 + } 98 + 99 + export interface ResolvedRequestOptions< 100 + TResponseStyle extends ResponseStyle = 'fields', 101 + ThrowOnError extends boolean = boolean, 102 + Url extends string = string, 103 + > extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> { 104 + serializedBody?: string; 105 + } 106 + 107 + export type RequestResult< 108 + TData = unknown, 109 + TError = unknown, 110 + ThrowOnError extends boolean = boolean, 111 + TResponseStyle extends ResponseStyle = 'fields', 112 + > = ThrowOnError extends true 113 + ? Promise< 114 + TResponseStyle extends 'data' 115 + ? TData extends Record<string, unknown> 116 + ? TData[keyof TData] 117 + : TData 118 + : { 119 + data: TData extends Record<string, unknown> 120 + ? TData[keyof TData] 121 + : TData; 122 + request: Request; 123 + response: Response; 124 + } 125 + > 126 + : Promise< 127 + TResponseStyle extends 'data' 128 + ? 129 + | (TData extends Record<string, unknown> 130 + ? TData[keyof TData] 131 + : TData) 132 + | undefined 133 + : ( 134 + | { 135 + data: TData extends Record<string, unknown> 136 + ? TData[keyof TData] 137 + : TData; 138 + error: undefined; 139 + } 140 + | { 141 + data: undefined; 142 + error: TError extends Record<string, unknown> 143 + ? TError[keyof TError] 144 + : TError; 145 + } 146 + ) & { 147 + request: Request; 148 + response: Response; 149 + } 150 + >; 151 + 152 + export interface ClientOptions { 153 + baseUrl?: string; 154 + responseStyle?: ResponseStyle; 155 + throwOnError?: boolean; 156 + } 157 + 158 + type MethodFn = < 159 + TData = unknown, 160 + TError = unknown, 161 + ThrowOnError extends boolean = false, 162 + TResponseStyle extends ResponseStyle = 'fields', 163 + >( 164 + options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>, 165 + ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>; 166 + 167 + type SseFn = < 168 + TData = unknown, 169 + TError = unknown, 170 + ThrowOnError extends boolean = false, 171 + TResponseStyle extends ResponseStyle = 'fields', 172 + >( 173 + options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>, 174 + ) => Promise<ServerSentEventsResult<TData, TError>>; 175 + 176 + type RequestFn = < 177 + TData = unknown, 178 + TError = unknown, 179 + ThrowOnError extends boolean = false, 180 + TResponseStyle extends ResponseStyle = 'fields', 181 + >( 182 + options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> & 183 + Pick< 184 + Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 185 + 'method' 186 + >, 187 + ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>; 188 + 189 + type BuildUrlFn = < 190 + TData extends { 191 + body?: unknown; 192 + path?: Record<string, unknown>; 193 + query?: Record<string, unknown>; 194 + url: string; 195 + }, 196 + >( 197 + options: TData & Options<TData>, 198 + ) => string; 199 + 200 + export type Client = CoreClient< 201 + RequestFn, 202 + Config, 203 + MethodFn, 204 + BuildUrlFn, 205 + SseFn 206 + > & { 207 + interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>; 208 + }; 209 + 210 + /** 211 + * The `createClientConfig()` function will be called on client initialization 212 + * and the returned object will become the client's initial configuration. 213 + * 214 + * You may want to initialize your client this way instead of calling 215 + * `setConfig()`. This is useful for example if you're using Next.js 216 + * to ensure your client always has the correct values. 217 + */ 218 + export type CreateClientConfig<T extends ClientOptions = ClientOptions> = ( 219 + override?: Config<ClientOptions & T>, 220 + ) => Config<Required<ClientOptions> & T>; 221 + 222 + export interface TDataShape { 223 + body?: unknown; 224 + headers?: unknown; 225 + path?: unknown; 226 + query?: unknown; 227 + url: string; 228 + } 229 + 230 + type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>; 231 + 232 + export type Options< 233 + TData extends TDataShape = TDataShape, 234 + ThrowOnError extends boolean = boolean, 235 + TResponse = unknown, 236 + TResponseStyle extends ResponseStyle = 'fields', 237 + > = OmitKeys< 238 + RequestOptions<TResponse, TResponseStyle, ThrowOnError>, 239 + 'body' | 'path' | 'query' | 'url' 240 + > & 241 + ([TData] extends [never] ? unknown : Omit<TData, 'url'>);
+332
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/client/utils.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { getAuthToken } from '../core/auth.gen'; 4 + import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; 5 + import { jsonBodySerializer } from '../core/bodySerializer.gen'; 6 + import { 7 + serializeArrayParam, 8 + serializeObjectParam, 9 + serializePrimitiveParam, 10 + } from '../core/pathSerializer.gen'; 11 + import { getUrl } from '../core/utils.gen'; 12 + import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; 13 + 14 + export const createQuerySerializer = <T = unknown>({ 15 + parameters = {}, 16 + ...args 17 + }: QuerySerializerOptions = {}) => { 18 + const querySerializer = (queryParams: T) => { 19 + const search: string[] = []; 20 + if (queryParams && typeof queryParams === 'object') { 21 + for (const name in queryParams) { 22 + const value = queryParams[name]; 23 + 24 + if (value === undefined || value === null) { 25 + continue; 26 + } 27 + 28 + const options = parameters[name] || args; 29 + 30 + if (Array.isArray(value)) { 31 + const serializedArray = serializeArrayParam({ 32 + allowReserved: options.allowReserved, 33 + explode: true, 34 + name, 35 + style: 'form', 36 + value, 37 + ...options.array, 38 + }); 39 + if (serializedArray) search.push(serializedArray); 40 + } else if (typeof value === 'object') { 41 + const serializedObject = serializeObjectParam({ 42 + allowReserved: options.allowReserved, 43 + explode: true, 44 + name, 45 + style: 'deepObject', 46 + value: value as Record<string, unknown>, 47 + ...options.object, 48 + }); 49 + if (serializedObject) search.push(serializedObject); 50 + } else { 51 + const serializedPrimitive = serializePrimitiveParam({ 52 + allowReserved: options.allowReserved, 53 + name, 54 + value: value as string, 55 + }); 56 + if (serializedPrimitive) search.push(serializedPrimitive); 57 + } 58 + } 59 + } 60 + return search.join('&'); 61 + }; 62 + return querySerializer; 63 + }; 64 + 65 + /** 66 + * Infers parseAs value from provided Content-Type header. 67 + */ 68 + export const getParseAs = ( 69 + contentType: string | null, 70 + ): Exclude<Config['parseAs'], 'auto'> => { 71 + if (!contentType) { 72 + // If no Content-Type header is provided, the best we can do is return the raw response body, 73 + // which is effectively the same as the 'stream' option. 74 + return 'stream'; 75 + } 76 + 77 + const cleanContent = contentType.split(';')[0]?.trim(); 78 + 79 + if (!cleanContent) { 80 + return; 81 + } 82 + 83 + if ( 84 + cleanContent.startsWith('application/json') || 85 + cleanContent.endsWith('+json') 86 + ) { 87 + return 'json'; 88 + } 89 + 90 + if (cleanContent === 'multipart/form-data') { 91 + return 'formData'; 92 + } 93 + 94 + if ( 95 + ['application/', 'audio/', 'image/', 'video/'].some((type) => 96 + cleanContent.startsWith(type), 97 + ) 98 + ) { 99 + return 'blob'; 100 + } 101 + 102 + if (cleanContent.startsWith('text/')) { 103 + return 'text'; 104 + } 105 + 106 + return; 107 + }; 108 + 109 + const checkForExistence = ( 110 + options: Pick<RequestOptions, 'auth' | 'query'> & { 111 + headers: Headers; 112 + }, 113 + name?: string, 114 + ): boolean => { 115 + if (!name) { 116 + return false; 117 + } 118 + if ( 119 + options.headers.has(name) || 120 + options.query?.[name] || 121 + options.headers.get('Cookie')?.includes(`${name}=`) 122 + ) { 123 + return true; 124 + } 125 + return false; 126 + }; 127 + 128 + export const setAuthParams = async ({ 129 + security, 130 + ...options 131 + }: Pick<Required<RequestOptions>, 'security'> & 132 + Pick<RequestOptions, 'auth' | 'query'> & { 133 + headers: Headers; 134 + }) => { 135 + for (const auth of security) { 136 + if (checkForExistence(options, auth.name)) { 137 + continue; 138 + } 139 + 140 + const token = await getAuthToken(auth, options.auth); 141 + 142 + if (!token) { 143 + continue; 144 + } 145 + 146 + const name = auth.name ?? 'Authorization'; 147 + 148 + switch (auth.in) { 149 + case 'query': 150 + if (!options.query) { 151 + options.query = {}; 152 + } 153 + options.query[name] = token; 154 + break; 155 + case 'cookie': 156 + options.headers.append('Cookie', `${name}=${token}`); 157 + break; 158 + case 'header': 159 + default: 160 + options.headers.set(name, token); 161 + break; 162 + } 163 + } 164 + }; 165 + 166 + export const buildUrl: Client['buildUrl'] = (options) => 167 + getUrl({ 168 + baseUrl: options.baseUrl as string, 169 + path: options.path, 170 + query: options.query, 171 + querySerializer: 172 + typeof options.querySerializer === 'function' 173 + ? options.querySerializer 174 + : createQuerySerializer(options.querySerializer), 175 + url: options.url, 176 + }); 177 + 178 + export const mergeConfigs = (a: Config, b: Config): Config => { 179 + const config = { ...a, ...b }; 180 + if (config.baseUrl?.endsWith('/')) { 181 + config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1); 182 + } 183 + config.headers = mergeHeaders(a.headers, b.headers); 184 + return config; 185 + }; 186 + 187 + const headersEntries = (headers: Headers): Array<[string, string]> => { 188 + const entries: Array<[string, string]> = []; 189 + headers.forEach((value, key) => { 190 + entries.push([key, value]); 191 + }); 192 + return entries; 193 + }; 194 + 195 + export const mergeHeaders = ( 196 + ...headers: Array<Required<Config>['headers'] | undefined> 197 + ): Headers => { 198 + const mergedHeaders = new Headers(); 199 + for (const header of headers) { 200 + if (!header) { 201 + continue; 202 + } 203 + 204 + const iterator = 205 + header instanceof Headers 206 + ? headersEntries(header) 207 + : Object.entries(header); 208 + 209 + for (const [key, value] of iterator) { 210 + if (value === null) { 211 + mergedHeaders.delete(key); 212 + } else if (Array.isArray(value)) { 213 + for (const v of value) { 214 + mergedHeaders.append(key, v as string); 215 + } 216 + } else if (value !== undefined) { 217 + // assume object headers are meant to be JSON stringified, i.e. their 218 + // content value in OpenAPI specification is 'application/json' 219 + mergedHeaders.set( 220 + key, 221 + typeof value === 'object' ? JSON.stringify(value) : (value as string), 222 + ); 223 + } 224 + } 225 + } 226 + return mergedHeaders; 227 + }; 228 + 229 + type ErrInterceptor<Err, Res, Req, Options> = ( 230 + error: Err, 231 + response: Res, 232 + request: Req, 233 + options: Options, 234 + ) => Err | Promise<Err>; 235 + 236 + type ReqInterceptor<Req, Options> = ( 237 + request: Req, 238 + options: Options, 239 + ) => Req | Promise<Req>; 240 + 241 + type ResInterceptor<Res, Req, Options> = ( 242 + response: Res, 243 + request: Req, 244 + options: Options, 245 + ) => Res | Promise<Res>; 246 + 247 + class Interceptors<Interceptor> { 248 + fns: Array<Interceptor | null> = []; 249 + 250 + clear(): void { 251 + this.fns = []; 252 + } 253 + 254 + eject(id: number | Interceptor): void { 255 + const index = this.getInterceptorIndex(id); 256 + if (this.fns[index]) { 257 + this.fns[index] = null; 258 + } 259 + } 260 + 261 + exists(id: number | Interceptor): boolean { 262 + const index = this.getInterceptorIndex(id); 263 + return Boolean(this.fns[index]); 264 + } 265 + 266 + getInterceptorIndex(id: number | Interceptor): number { 267 + if (typeof id === 'number') { 268 + return this.fns[id] ? id : -1; 269 + } 270 + return this.fns.indexOf(id); 271 + } 272 + 273 + update( 274 + id: number | Interceptor, 275 + fn: Interceptor, 276 + ): number | Interceptor | false { 277 + const index = this.getInterceptorIndex(id); 278 + if (this.fns[index]) { 279 + this.fns[index] = fn; 280 + return id; 281 + } 282 + return false; 283 + } 284 + 285 + use(fn: Interceptor): number { 286 + this.fns.push(fn); 287 + return this.fns.length - 1; 288 + } 289 + } 290 + 291 + export interface Middleware<Req, Res, Err, Options> { 292 + error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>; 293 + request: Interceptors<ReqInterceptor<Req, Options>>; 294 + response: Interceptors<ResInterceptor<Res, Req, Options>>; 295 + } 296 + 297 + export const createInterceptors = <Req, Res, Err, Options>(): Middleware< 298 + Req, 299 + Res, 300 + Err, 301 + Options 302 + > => ({ 303 + error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(), 304 + request: new Interceptors<ReqInterceptor<Req, Options>>(), 305 + response: new Interceptors<ResInterceptor<Res, Req, Options>>(), 306 + }); 307 + 308 + const defaultQuerySerializer = createQuerySerializer({ 309 + allowReserved: false, 310 + array: { 311 + explode: true, 312 + style: 'form', 313 + }, 314 + object: { 315 + explode: true, 316 + style: 'deepObject', 317 + }, 318 + }); 319 + 320 + const defaultHeaders = { 321 + 'Content-Type': 'application/json', 322 + }; 323 + 324 + export const createConfig = <T extends ClientOptions = ClientOptions>( 325 + override: Config<Omit<ClientOptions, keyof T> & T> = {}, 326 + ): Config<Omit<ClientOptions, keyof T> & T> => ({ 327 + ...jsonBodySerializer, 328 + headers: defaultHeaders, 329 + parseAs: 'auto', 330 + querySerializer: defaultQuerySerializer, 331 + ...override, 332 + });
+16
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/client.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { type ClientOptions, type Config, createClient, createConfig } from './client'; 4 + import type { ClientOptions as ClientOptions2 } from './types.gen'; 5 + 6 + /** 7 + * The `createClientConfig()` function will be called on client initialization 8 + * and the returned object will become the client's initial configuration. 9 + * 10 + * You may want to initialize your client this way instead of calling 11 + * `setConfig()`. This is useful for example if you're using Next.js 12 + * to ensure your client always has the correct values. 13 + */ 14 + export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>; 15 + 16 + export const client = createClient(createConfig<ClientOptions2>());
+42
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/auth.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type AuthToken = string | undefined; 4 + 5 + export interface Auth { 6 + /** 7 + * Which part of the request do we use to send the auth? 8 + * 9 + * @default 'header' 10 + */ 11 + in?: 'header' | 'query' | 'cookie'; 12 + /** 13 + * Header or query parameter name. 14 + * 15 + * @default 'Authorization' 16 + */ 17 + name?: string; 18 + scheme?: 'basic' | 'bearer'; 19 + type: 'apiKey' | 'http'; 20 + } 21 + 22 + export const getAuthToken = async ( 23 + auth: Auth, 24 + callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken, 25 + ): Promise<string | undefined> => { 26 + const token = 27 + typeof callback === 'function' ? await callback(auth) : callback; 28 + 29 + if (!token) { 30 + return; 31 + } 32 + 33 + if (auth.scheme === 'bearer') { 34 + return `Bearer ${token}`; 35 + } 36 + 37 + if (auth.scheme === 'basic') { 38 + return `Basic ${btoa(token)}`; 39 + } 40 + 41 + return token; 42 + };
+100
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/bodySerializer.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { 4 + ArrayStyle, 5 + ObjectStyle, 6 + SerializerOptions, 7 + } from './pathSerializer.gen'; 8 + 9 + export type QuerySerializer = (query: Record<string, unknown>) => string; 10 + 11 + export type BodySerializer = (body: any) => any; 12 + 13 + type QuerySerializerOptionsObject = { 14 + allowReserved?: boolean; 15 + array?: Partial<SerializerOptions<ArrayStyle>>; 16 + object?: Partial<SerializerOptions<ObjectStyle>>; 17 + }; 18 + 19 + export type QuerySerializerOptions = QuerySerializerOptionsObject & { 20 + /** 21 + * Per-parameter serialization overrides. When provided, these settings 22 + * override the global array/object settings for specific parameter names. 23 + */ 24 + parameters?: Record<string, QuerySerializerOptionsObject>; 25 + }; 26 + 27 + const serializeFormDataPair = ( 28 + data: FormData, 29 + key: string, 30 + value: unknown, 31 + ): void => { 32 + if (typeof value === 'string' || value instanceof Blob) { 33 + data.append(key, value); 34 + } else if (value instanceof Date) { 35 + data.append(key, value.toISOString()); 36 + } else { 37 + data.append(key, JSON.stringify(value)); 38 + } 39 + }; 40 + 41 + const serializeUrlSearchParamsPair = ( 42 + data: URLSearchParams, 43 + key: string, 44 + value: unknown, 45 + ): void => { 46 + if (typeof value === 'string') { 47 + data.append(key, value); 48 + } else { 49 + data.append(key, JSON.stringify(value)); 50 + } 51 + }; 52 + 53 + export const formDataBodySerializer = { 54 + bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>( 55 + body: T, 56 + ): FormData => { 57 + const data = new FormData(); 58 + 59 + Object.entries(body).forEach(([key, value]) => { 60 + if (value === undefined || value === null) { 61 + return; 62 + } 63 + if (Array.isArray(value)) { 64 + value.forEach((v) => serializeFormDataPair(data, key, v)); 65 + } else { 66 + serializeFormDataPair(data, key, value); 67 + } 68 + }); 69 + 70 + return data; 71 + }, 72 + }; 73 + 74 + export const jsonBodySerializer = { 75 + bodySerializer: <T>(body: T): string => 76 + JSON.stringify(body, (_key, value) => 77 + typeof value === 'bigint' ? value.toString() : value, 78 + ), 79 + }; 80 + 81 + export const urlSearchParamsBodySerializer = { 82 + bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>( 83 + body: T, 84 + ): string => { 85 + const data = new URLSearchParams(); 86 + 87 + Object.entries(body).forEach(([key, value]) => { 88 + if (value === undefined || value === null) { 89 + return; 90 + } 91 + if (Array.isArray(value)) { 92 + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); 93 + } else { 94 + serializeUrlSearchParamsPair(data, key, value); 95 + } 96 + }); 97 + 98 + return data.toString(); 99 + }, 100 + };
+176
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/params.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + type Slot = 'body' | 'headers' | 'path' | 'query'; 4 + 5 + export type Field = 6 + | { 7 + in: Exclude<Slot, 'body'>; 8 + /** 9 + * Field name. This is the name we want the user to see and use. 10 + */ 11 + key: string; 12 + /** 13 + * Field mapped name. This is the name we want to use in the request. 14 + * If omitted, we use the same value as `key`. 15 + */ 16 + map?: string; 17 + } 18 + | { 19 + in: Extract<Slot, 'body'>; 20 + /** 21 + * Key isn't required for bodies. 22 + */ 23 + key?: string; 24 + map?: string; 25 + } 26 + | { 27 + /** 28 + * Field name. This is the name we want the user to see and use. 29 + */ 30 + key: string; 31 + /** 32 + * Field mapped name. This is the name we want to use in the request. 33 + * If `in` is omitted, `map` aliases `key` to the transport layer. 34 + */ 35 + map: Slot; 36 + }; 37 + 38 + export interface Fields { 39 + allowExtra?: Partial<Record<Slot, boolean>>; 40 + args?: ReadonlyArray<Field>; 41 + } 42 + 43 + export type FieldsConfig = ReadonlyArray<Field | Fields>; 44 + 45 + const extraPrefixesMap: Record<string, Slot> = { 46 + $body_: 'body', 47 + $headers_: 'headers', 48 + $path_: 'path', 49 + $query_: 'query', 50 + }; 51 + const extraPrefixes = Object.entries(extraPrefixesMap); 52 + 53 + type KeyMap = Map< 54 + string, 55 + | { 56 + in: Slot; 57 + map?: string; 58 + } 59 + | { 60 + in?: never; 61 + map: Slot; 62 + } 63 + >; 64 + 65 + const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { 66 + if (!map) { 67 + map = new Map(); 68 + } 69 + 70 + for (const config of fields) { 71 + if ('in' in config) { 72 + if (config.key) { 73 + map.set(config.key, { 74 + in: config.in, 75 + map: config.map, 76 + }); 77 + } 78 + } else if ('key' in config) { 79 + map.set(config.key, { 80 + map: config.map, 81 + }); 82 + } else if (config.args) { 83 + buildKeyMap(config.args, map); 84 + } 85 + } 86 + 87 + return map; 88 + }; 89 + 90 + interface Params { 91 + body: unknown; 92 + headers: Record<string, unknown>; 93 + path: Record<string, unknown>; 94 + query: Record<string, unknown>; 95 + } 96 + 97 + const stripEmptySlots = (params: Params) => { 98 + for (const [slot, value] of Object.entries(params)) { 99 + if (value && typeof value === 'object' && !Object.keys(value).length) { 100 + delete params[slot as Slot]; 101 + } 102 + } 103 + }; 104 + 105 + export const buildClientParams = ( 106 + args: ReadonlyArray<unknown>, 107 + fields: FieldsConfig, 108 + ) => { 109 + const params: Params = { 110 + body: {}, 111 + headers: {}, 112 + path: {}, 113 + query: {}, 114 + }; 115 + 116 + const map = buildKeyMap(fields); 117 + 118 + let config: FieldsConfig[number] | undefined; 119 + 120 + for (const [index, arg] of args.entries()) { 121 + if (fields[index]) { 122 + config = fields[index]; 123 + } 124 + 125 + if (!config) { 126 + continue; 127 + } 128 + 129 + if ('in' in config) { 130 + if (config.key) { 131 + const field = map.get(config.key)!; 132 + const name = field.map || config.key; 133 + if (field.in) { 134 + (params[field.in] as Record<string, unknown>)[name] = arg; 135 + } 136 + } else { 137 + params.body = arg; 138 + } 139 + } else { 140 + for (const [key, value] of Object.entries(arg ?? {})) { 141 + const field = map.get(key); 142 + 143 + if (field) { 144 + if (field.in) { 145 + const name = field.map || key; 146 + (params[field.in] as Record<string, unknown>)[name] = value; 147 + } else { 148 + params[field.map] = value; 149 + } 150 + } else { 151 + const extra = extraPrefixes.find(([prefix]) => 152 + key.startsWith(prefix), 153 + ); 154 + 155 + if (extra) { 156 + const [prefix, slot] = extra; 157 + (params[slot] as Record<string, unknown>)[ 158 + key.slice(prefix.length) 159 + ] = value; 160 + } else if ('allowExtra' in config && config.allowExtra) { 161 + for (const [slot, allowed] of Object.entries(config.allowExtra)) { 162 + if (allowed) { 163 + (params[slot as Slot] as Record<string, unknown>)[key] = value; 164 + break; 165 + } 166 + } 167 + } 168 + } 169 + } 170 + } 171 + } 172 + 173 + stripEmptySlots(params); 174 + 175 + return params; 176 + };
+181
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/pathSerializer.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + interface SerializeOptions<T> 4 + extends SerializePrimitiveOptions, 5 + SerializerOptions<T> {} 6 + 7 + interface SerializePrimitiveOptions { 8 + allowReserved?: boolean; 9 + name: string; 10 + } 11 + 12 + export interface SerializerOptions<T> { 13 + /** 14 + * @default true 15 + */ 16 + explode: boolean; 17 + style: T; 18 + } 19 + 20 + export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; 21 + export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; 22 + type MatrixStyle = 'label' | 'matrix' | 'simple'; 23 + export type ObjectStyle = 'form' | 'deepObject'; 24 + type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; 25 + 26 + interface SerializePrimitiveParam extends SerializePrimitiveOptions { 27 + value: string; 28 + } 29 + 30 + export const separatorArrayExplode = (style: ArraySeparatorStyle) => { 31 + switch (style) { 32 + case 'label': 33 + return '.'; 34 + case 'matrix': 35 + return ';'; 36 + case 'simple': 37 + return ','; 38 + default: 39 + return '&'; 40 + } 41 + }; 42 + 43 + export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { 44 + switch (style) { 45 + case 'form': 46 + return ','; 47 + case 'pipeDelimited': 48 + return '|'; 49 + case 'spaceDelimited': 50 + return '%20'; 51 + default: 52 + return ','; 53 + } 54 + }; 55 + 56 + export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { 57 + switch (style) { 58 + case 'label': 59 + return '.'; 60 + case 'matrix': 61 + return ';'; 62 + case 'simple': 63 + return ','; 64 + default: 65 + return '&'; 66 + } 67 + }; 68 + 69 + export const serializeArrayParam = ({ 70 + allowReserved, 71 + explode, 72 + name, 73 + style, 74 + value, 75 + }: SerializeOptions<ArraySeparatorStyle> & { 76 + value: unknown[]; 77 + }) => { 78 + if (!explode) { 79 + const joinedValues = ( 80 + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) 81 + ).join(separatorArrayNoExplode(style)); 82 + switch (style) { 83 + case 'label': 84 + return `.${joinedValues}`; 85 + case 'matrix': 86 + return `;${name}=${joinedValues}`; 87 + case 'simple': 88 + return joinedValues; 89 + default: 90 + return `${name}=${joinedValues}`; 91 + } 92 + } 93 + 94 + const separator = separatorArrayExplode(style); 95 + const joinedValues = value 96 + .map((v) => { 97 + if (style === 'label' || style === 'simple') { 98 + return allowReserved ? v : encodeURIComponent(v as string); 99 + } 100 + 101 + return serializePrimitiveParam({ 102 + allowReserved, 103 + name, 104 + value: v as string, 105 + }); 106 + }) 107 + .join(separator); 108 + return style === 'label' || style === 'matrix' 109 + ? separator + joinedValues 110 + : joinedValues; 111 + }; 112 + 113 + export const serializePrimitiveParam = ({ 114 + allowReserved, 115 + name, 116 + value, 117 + }: SerializePrimitiveParam) => { 118 + if (value === undefined || value === null) { 119 + return ''; 120 + } 121 + 122 + if (typeof value === 'object') { 123 + throw new Error( 124 + 'Deeply-nested arrays/objects arenโ€™t supported. Provide your own `querySerializer()` to handle these.', 125 + ); 126 + } 127 + 128 + return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; 129 + }; 130 + 131 + export const serializeObjectParam = ({ 132 + allowReserved, 133 + explode, 134 + name, 135 + style, 136 + value, 137 + valueOnly, 138 + }: SerializeOptions<ObjectSeparatorStyle> & { 139 + value: Record<string, unknown> | Date; 140 + valueOnly?: boolean; 141 + }) => { 142 + if (value instanceof Date) { 143 + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; 144 + } 145 + 146 + if (style !== 'deepObject' && !explode) { 147 + let values: string[] = []; 148 + Object.entries(value).forEach(([key, v]) => { 149 + values = [ 150 + ...values, 151 + key, 152 + allowReserved ? (v as string) : encodeURIComponent(v as string), 153 + ]; 154 + }); 155 + const joinedValues = values.join(','); 156 + switch (style) { 157 + case 'form': 158 + return `${name}=${joinedValues}`; 159 + case 'label': 160 + return `.${joinedValues}`; 161 + case 'matrix': 162 + return `;${name}=${joinedValues}`; 163 + default: 164 + return joinedValues; 165 + } 166 + } 167 + 168 + const separator = separatorObjectExplode(style); 169 + const joinedValues = Object.entries(value) 170 + .map(([key, v]) => 171 + serializePrimitiveParam({ 172 + allowReserved, 173 + name: style === 'deepObject' ? `${name}[${key}]` : key, 174 + value: v as string, 175 + }), 176 + ) 177 + .join(separator); 178 + return style === 'label' || style === 'matrix' 179 + ? separator + joinedValues 180 + : joinedValues; 181 + };
+136
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/queryKeySerializer.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + /** 4 + * JSON-friendly union that mirrors what Pinia Colada can hash. 5 + */ 6 + export type JsonValue = 7 + | null 8 + | string 9 + | number 10 + | boolean 11 + | JsonValue[] 12 + | { [key: string]: JsonValue }; 13 + 14 + /** 15 + * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. 16 + */ 17 + export const queryKeyJsonReplacer = (_key: string, value: unknown) => { 18 + if ( 19 + value === undefined || 20 + typeof value === 'function' || 21 + typeof value === 'symbol' 22 + ) { 23 + return undefined; 24 + } 25 + if (typeof value === 'bigint') { 26 + return value.toString(); 27 + } 28 + if (value instanceof Date) { 29 + return value.toISOString(); 30 + } 31 + return value; 32 + }; 33 + 34 + /** 35 + * Safely stringifies a value and parses it back into a JsonValue. 36 + */ 37 + export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => { 38 + try { 39 + const json = JSON.stringify(input, queryKeyJsonReplacer); 40 + if (json === undefined) { 41 + return undefined; 42 + } 43 + return JSON.parse(json) as JsonValue; 44 + } catch { 45 + return undefined; 46 + } 47 + }; 48 + 49 + /** 50 + * Detects plain objects (including objects with a null prototype). 51 + */ 52 + const isPlainObject = (value: unknown): value is Record<string, unknown> => { 53 + if (value === null || typeof value !== 'object') { 54 + return false; 55 + } 56 + const prototype = Object.getPrototypeOf(value as object); 57 + return prototype === Object.prototype || prototype === null; 58 + }; 59 + 60 + /** 61 + * Turns URLSearchParams into a sorted JSON object for deterministic keys. 62 + */ 63 + const serializeSearchParams = (params: URLSearchParams): JsonValue => { 64 + const entries = Array.from(params.entries()).sort(([a], [b]) => 65 + a.localeCompare(b), 66 + ); 67 + const result: Record<string, JsonValue> = {}; 68 + 69 + for (const [key, value] of entries) { 70 + const existing = result[key]; 71 + if (existing === undefined) { 72 + result[key] = value; 73 + continue; 74 + } 75 + 76 + if (Array.isArray(existing)) { 77 + (existing as string[]).push(value); 78 + } else { 79 + result[key] = [existing, value]; 80 + } 81 + } 82 + 83 + return result; 84 + }; 85 + 86 + /** 87 + * Normalizes any accepted value into a JSON-friendly shape for query keys. 88 + */ 89 + export const serializeQueryKeyValue = ( 90 + value: unknown, 91 + ): JsonValue | undefined => { 92 + if (value === null) { 93 + return null; 94 + } 95 + 96 + if ( 97 + typeof value === 'string' || 98 + typeof value === 'number' || 99 + typeof value === 'boolean' 100 + ) { 101 + return value; 102 + } 103 + 104 + if ( 105 + value === undefined || 106 + typeof value === 'function' || 107 + typeof value === 'symbol' 108 + ) { 109 + return undefined; 110 + } 111 + 112 + if (typeof value === 'bigint') { 113 + return value.toString(); 114 + } 115 + 116 + if (value instanceof Date) { 117 + return value.toISOString(); 118 + } 119 + 120 + if (Array.isArray(value)) { 121 + return stringifyToJsonValue(value); 122 + } 123 + 124 + if ( 125 + typeof URLSearchParams !== 'undefined' && 126 + value instanceof URLSearchParams 127 + ) { 128 + return serializeSearchParams(value); 129 + } 130 + 131 + if (isPlainObject(value)) { 132 + return stringifyToJsonValue(value); 133 + } 134 + 135 + return undefined; 136 + };
+266
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/serverSentEvents.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Config } from './types.gen'; 4 + 5 + export type ServerSentEventsOptions<TData = unknown> = Omit< 6 + RequestInit, 7 + 'method' 8 + > & 9 + Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & { 10 + /** 11 + * Fetch API implementation. You can use this option to provide a custom 12 + * fetch instance. 13 + * 14 + * @default globalThis.fetch 15 + */ 16 + fetch?: typeof fetch; 17 + /** 18 + * Implementing clients can call request interceptors inside this hook. 19 + */ 20 + onRequest?: (url: string, init: RequestInit) => Promise<Request>; 21 + /** 22 + * Callback invoked when a network or parsing error occurs during streaming. 23 + * 24 + * This option applies only if the endpoint returns a stream of events. 25 + * 26 + * @param error The error that occurred. 27 + */ 28 + onSseError?: (error: unknown) => void; 29 + /** 30 + * Callback invoked when an event is streamed from the server. 31 + * 32 + * This option applies only if the endpoint returns a stream of events. 33 + * 34 + * @param event Event streamed from the server. 35 + * @returns Nothing (void). 36 + */ 37 + onSseEvent?: (event: StreamEvent<TData>) => void; 38 + serializedBody?: RequestInit['body']; 39 + /** 40 + * Default retry delay in milliseconds. 41 + * 42 + * This option applies only if the endpoint returns a stream of events. 43 + * 44 + * @default 3000 45 + */ 46 + sseDefaultRetryDelay?: number; 47 + /** 48 + * Maximum number of retry attempts before giving up. 49 + */ 50 + sseMaxRetryAttempts?: number; 51 + /** 52 + * Maximum retry delay in milliseconds. 53 + * 54 + * Applies only when exponential backoff is used. 55 + * 56 + * This option applies only if the endpoint returns a stream of events. 57 + * 58 + * @default 30000 59 + */ 60 + sseMaxRetryDelay?: number; 61 + /** 62 + * Optional sleep function for retry backoff. 63 + * 64 + * Defaults to using `setTimeout`. 65 + */ 66 + sseSleepFn?: (ms: number) => Promise<void>; 67 + url: string; 68 + }; 69 + 70 + export interface StreamEvent<TData = unknown> { 71 + data: TData; 72 + event?: string; 73 + id?: string; 74 + retry?: number; 75 + } 76 + 77 + export type ServerSentEventsResult< 78 + TData = unknown, 79 + TReturn = void, 80 + TNext = unknown, 81 + > = { 82 + stream: AsyncGenerator< 83 + TData extends Record<string, unknown> ? TData[keyof TData] : TData, 84 + TReturn, 85 + TNext 86 + >; 87 + }; 88 + 89 + export const createSseClient = <TData = unknown>({ 90 + onRequest, 91 + onSseError, 92 + onSseEvent, 93 + responseTransformer, 94 + responseValidator, 95 + sseDefaultRetryDelay, 96 + sseMaxRetryAttempts, 97 + sseMaxRetryDelay, 98 + sseSleepFn, 99 + url, 100 + ...options 101 + }: ServerSentEventsOptions): ServerSentEventsResult<TData> => { 102 + let lastEventId: string | undefined; 103 + 104 + const sleep = 105 + sseSleepFn ?? 106 + ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))); 107 + 108 + const createStream = async function* () { 109 + let retryDelay: number = sseDefaultRetryDelay ?? 3000; 110 + let attempt = 0; 111 + const signal = options.signal ?? new AbortController().signal; 112 + 113 + while (true) { 114 + if (signal.aborted) break; 115 + 116 + attempt++; 117 + 118 + const headers = 119 + options.headers instanceof Headers 120 + ? options.headers 121 + : new Headers(options.headers as Record<string, string> | undefined); 122 + 123 + if (lastEventId !== undefined) { 124 + headers.set('Last-Event-ID', lastEventId); 125 + } 126 + 127 + try { 128 + const requestInit: RequestInit = { 129 + redirect: 'follow', 130 + ...options, 131 + body: options.serializedBody, 132 + headers, 133 + signal, 134 + }; 135 + let request = new Request(url, requestInit); 136 + if (onRequest) { 137 + request = await onRequest(url, requestInit); 138 + } 139 + // fetch must be assigned here, otherwise it would throw the error: 140 + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation 141 + const _fetch = options.fetch ?? globalThis.fetch; 142 + const response = await _fetch(request); 143 + 144 + if (!response.ok) 145 + throw new Error( 146 + `SSE failed: ${response.status} ${response.statusText}`, 147 + ); 148 + 149 + if (!response.body) throw new Error('No body in SSE response'); 150 + 151 + const reader = response.body 152 + .pipeThrough(new TextDecoderStream()) 153 + .getReader(); 154 + 155 + let buffer = ''; 156 + 157 + const abortHandler = () => { 158 + try { 159 + reader.cancel(); 160 + } catch { 161 + // noop 162 + } 163 + }; 164 + 165 + signal.addEventListener('abort', abortHandler); 166 + 167 + try { 168 + while (true) { 169 + const { done, value } = await reader.read(); 170 + if (done) break; 171 + buffer += value; 172 + // Normalize line endings: CRLF -> LF, then CR -> LF 173 + buffer = buffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); 174 + 175 + const chunks = buffer.split('\n\n'); 176 + buffer = chunks.pop() ?? ''; 177 + 178 + for (const chunk of chunks) { 179 + const lines = chunk.split('\n'); 180 + const dataLines: Array<string> = []; 181 + let eventName: string | undefined; 182 + 183 + for (const line of lines) { 184 + if (line.startsWith('data:')) { 185 + dataLines.push(line.replace(/^data:\s*/, '')); 186 + } else if (line.startsWith('event:')) { 187 + eventName = line.replace(/^event:\s*/, ''); 188 + } else if (line.startsWith('id:')) { 189 + lastEventId = line.replace(/^id:\s*/, ''); 190 + } else if (line.startsWith('retry:')) { 191 + const parsed = Number.parseInt( 192 + line.replace(/^retry:\s*/, ''), 193 + 10, 194 + ); 195 + if (!Number.isNaN(parsed)) { 196 + retryDelay = parsed; 197 + } 198 + } 199 + } 200 + 201 + let data: unknown; 202 + let parsedJson = false; 203 + 204 + if (dataLines.length) { 205 + const rawData = dataLines.join('\n'); 206 + try { 207 + data = JSON.parse(rawData); 208 + parsedJson = true; 209 + } catch { 210 + data = rawData; 211 + } 212 + } 213 + 214 + if (parsedJson) { 215 + if (responseValidator) { 216 + await responseValidator(data); 217 + } 218 + 219 + if (responseTransformer) { 220 + data = await responseTransformer(data); 221 + } 222 + } 223 + 224 + onSseEvent?.({ 225 + data, 226 + event: eventName, 227 + id: lastEventId, 228 + retry: retryDelay, 229 + }); 230 + 231 + if (dataLines.length) { 232 + yield data as any; 233 + } 234 + } 235 + } 236 + } finally { 237 + signal.removeEventListener('abort', abortHandler); 238 + reader.releaseLock(); 239 + } 240 + 241 + break; // exit loop on normal completion 242 + } catch (error) { 243 + // connection failed or aborted; retry after delay 244 + onSseError?.(error); 245 + 246 + if ( 247 + sseMaxRetryAttempts !== undefined && 248 + attempt >= sseMaxRetryAttempts 249 + ) { 250 + break; // stop after firing error 251 + } 252 + 253 + // exponential backoff: double retry each attempt, cap at 30s 254 + const backoff = Math.min( 255 + retryDelay * 2 ** (attempt - 1), 256 + sseMaxRetryDelay ?? 30000, 257 + ); 258 + await sleep(backoff); 259 + } 260 + } 261 + }; 262 + 263 + const stream = createStream(); 264 + 265 + return { stream }; 266 + };
+118
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Auth, AuthToken } from './auth.gen'; 4 + import type { 5 + BodySerializer, 6 + QuerySerializer, 7 + QuerySerializerOptions, 8 + } from './bodySerializer.gen'; 9 + 10 + export type HttpMethod = 11 + | 'connect' 12 + | 'delete' 13 + | 'get' 14 + | 'head' 15 + | 'options' 16 + | 'patch' 17 + | 'post' 18 + | 'put' 19 + | 'trace'; 20 + 21 + export type Client< 22 + RequestFn = never, 23 + Config = unknown, 24 + MethodFn = never, 25 + BuildUrlFn = never, 26 + SseFn = never, 27 + > = { 28 + /** 29 + * Returns the final request URL. 30 + */ 31 + buildUrl: BuildUrlFn; 32 + getConfig: () => Config; 33 + request: RequestFn; 34 + setConfig: (config: Config) => Config; 35 + } & { 36 + [K in HttpMethod]: MethodFn; 37 + } & ([SseFn] extends [never] 38 + ? { sse?: never } 39 + : { sse: { [K in HttpMethod]: SseFn } }); 40 + 41 + export interface Config { 42 + /** 43 + * Auth token or a function returning auth token. The resolved value will be 44 + * added to the request payload as defined by its `security` array. 45 + */ 46 + auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken; 47 + /** 48 + * A function for serializing request body parameter. By default, 49 + * {@link JSON.stringify()} will be used. 50 + */ 51 + bodySerializer?: BodySerializer | null; 52 + /** 53 + * An object containing any HTTP headers that you want to pre-populate your 54 + * `Headers` object with. 55 + * 56 + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} 57 + */ 58 + headers?: 59 + | RequestInit['headers'] 60 + | Record< 61 + string, 62 + | string 63 + | number 64 + | boolean 65 + | (string | number | boolean)[] 66 + | null 67 + | undefined 68 + | unknown 69 + >; 70 + /** 71 + * The request method. 72 + * 73 + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} 74 + */ 75 + method?: Uppercase<HttpMethod>; 76 + /** 77 + * A function for serializing request query parameters. By default, arrays 78 + * will be exploded in form style, objects will be exploded in deepObject 79 + * style, and reserved characters are percent-encoded. 80 + * 81 + * This method will have no effect if the native `paramsSerializer()` Axios 82 + * API function is used. 83 + * 84 + * {@link https://swagger.io/docs/specification/serialization/#query View examples} 85 + */ 86 + querySerializer?: QuerySerializer | QuerySerializerOptions; 87 + /** 88 + * A function validating request data. This is useful if you want to ensure 89 + * the request conforms to the desired shape, so it can be safely sent to 90 + * the server. 91 + */ 92 + requestValidator?: (data: unknown) => Promise<unknown>; 93 + /** 94 + * A function transforming response data before it's returned. This is useful 95 + * for post-processing data, e.g. converting ISO strings into Date objects. 96 + */ 97 + responseTransformer?: (data: unknown) => Promise<unknown>; 98 + /** 99 + * A function validating response data. This is useful if you want to ensure 100 + * the response conforms to the desired shape, so it can be safely passed to 101 + * the transformers and returned to the user. 102 + */ 103 + responseValidator?: (data: unknown) => Promise<unknown>; 104 + } 105 + 106 + type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never] 107 + ? true 108 + : [T] extends [never | undefined] 109 + ? [undefined] extends [T] 110 + ? false 111 + : true 112 + : false; 113 + 114 + export type OmitNever<T extends Record<string, unknown>> = { 115 + [K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true 116 + ? never 117 + : K]: T[K]; 118 + };
+143
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/core/utils.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; 4 + import { 5 + type ArraySeparatorStyle, 6 + serializeArrayParam, 7 + serializeObjectParam, 8 + serializePrimitiveParam, 9 + } from './pathSerializer.gen'; 10 + 11 + export interface PathSerializer { 12 + path: Record<string, unknown>; 13 + url: string; 14 + } 15 + 16 + export const PATH_PARAM_RE = /\{[^{}]+\}/g; 17 + 18 + export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { 19 + let url = _url; 20 + const matches = _url.match(PATH_PARAM_RE); 21 + if (matches) { 22 + for (const match of matches) { 23 + let explode = false; 24 + let name = match.substring(1, match.length - 1); 25 + let style: ArraySeparatorStyle = 'simple'; 26 + 27 + if (name.endsWith('*')) { 28 + explode = true; 29 + name = name.substring(0, name.length - 1); 30 + } 31 + 32 + if (name.startsWith('.')) { 33 + name = name.substring(1); 34 + style = 'label'; 35 + } else if (name.startsWith(';')) { 36 + name = name.substring(1); 37 + style = 'matrix'; 38 + } 39 + 40 + const value = path[name]; 41 + 42 + if (value === undefined || value === null) { 43 + continue; 44 + } 45 + 46 + if (Array.isArray(value)) { 47 + url = url.replace( 48 + match, 49 + serializeArrayParam({ explode, name, style, value }), 50 + ); 51 + continue; 52 + } 53 + 54 + if (typeof value === 'object') { 55 + url = url.replace( 56 + match, 57 + serializeObjectParam({ 58 + explode, 59 + name, 60 + style, 61 + value: value as Record<string, unknown>, 62 + valueOnly: true, 63 + }), 64 + ); 65 + continue; 66 + } 67 + 68 + if (style === 'matrix') { 69 + url = url.replace( 70 + match, 71 + `;${serializePrimitiveParam({ 72 + name, 73 + value: value as string, 74 + })}`, 75 + ); 76 + continue; 77 + } 78 + 79 + const replaceValue = encodeURIComponent( 80 + style === 'label' ? `.${value as string}` : (value as string), 81 + ); 82 + url = url.replace(match, replaceValue); 83 + } 84 + } 85 + return url; 86 + }; 87 + 88 + export const getUrl = ({ 89 + baseUrl, 90 + path, 91 + query, 92 + querySerializer, 93 + url: _url, 94 + }: { 95 + baseUrl?: string; 96 + path?: Record<string, unknown>; 97 + query?: Record<string, unknown>; 98 + querySerializer: QuerySerializer; 99 + url: string; 100 + }) => { 101 + const pathUrl = _url.startsWith('/') ? _url : `/${_url}`; 102 + let url = (baseUrl ?? '') + pathUrl; 103 + if (path) { 104 + url = defaultPathSerializer({ path, url }); 105 + } 106 + let search = query ? querySerializer(query) : ''; 107 + if (search.startsWith('?')) { 108 + search = search.substring(1); 109 + } 110 + if (search) { 111 + url += `?${search}`; 112 + } 113 + return url; 114 + }; 115 + 116 + export function getValidRequestBody(options: { 117 + body?: unknown; 118 + bodySerializer?: BodySerializer | null; 119 + serializedBody?: unknown; 120 + }) { 121 + const hasBody = options.body !== undefined; 122 + const isSerializedBody = hasBody && options.bodySerializer; 123 + 124 + if (isSerializedBody) { 125 + if ('serializedBody' in options) { 126 + const hasSerializedBody = 127 + options.serializedBody !== undefined && options.serializedBody !== ''; 128 + 129 + return hasSerializedBody ? options.serializedBody : null; 130 + } 131 + 132 + // not all clients implement a serializedBody property (i.e. client-axios) 133 + return options.body !== '' ? options.body : null; 134 + } 135 + 136 + // plain/text body 137 + if (hasBody) { 138 + return options.body; 139 + } 140 + 141 + // no body was provided 142 + return undefined; 143 + }
+4
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/index.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export { getBar, getFoo, type Options } from './sdk.gen'; 4 + export type { ClientOptions, GetBarData, GetBarResponses, GetFooData, GetFooResponses } from './types.gen';
+39
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/sdk.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Client, Options as Options2, TDataShape } from './client'; 4 + import { client } from './client.gen'; 5 + import type { GetBarData, GetBarResponses, GetFooData, GetFooResponses } from './types.gen'; 6 + 7 + export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & { 8 + /** 9 + * You can provide a client instance returned by `createClient()` instead of 10 + * individual options. This might be also useful if you want to implement a 11 + * custom client. 12 + */ 13 + client?: Client; 14 + /** 15 + * You can pass arbitrary values through the `meta` object. This can be 16 + * used to access values that aren't defined as part of the SDK function. 17 + */ 18 + meta?: Record<string, unknown>; 19 + }; 20 + 21 + export const getFoo = <ThrowOnError extends boolean = false>(options?: Options<GetFooData, ThrowOnError>) => (options?.client ?? client).get<GetFooResponses, unknown, ThrowOnError>({ 22 + security: [{ 23 + in: 'query', 24 + name: 'foo', 25 + type: 'apiKey' 26 + }], 27 + url: '/foo', 28 + ...options 29 + }); 30 + 31 + export const getBar = <ThrowOnError extends boolean = false>(options?: Options<GetBarData, ThrowOnError>) => (options?.client ?? client).get<GetBarResponses, unknown, ThrowOnError>({ 32 + security: [{ 33 + in: 'cookie', 34 + name: 'bar', 35 + type: 'apiKey' 36 + }], 37 + url: '/bar', 38 + ...options 39 + });
+33
packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type ClientOptions = { 4 + baseUrl: `${string}://${string}` | (string & {}); 5 + }; 6 + 7 + export type GetFooData = { 8 + body?: never; 9 + path?: never; 10 + query?: never; 11 + url: '/foo'; 12 + }; 13 + 14 + export type GetFooResponses = { 15 + /** 16 + * OK 17 + */ 18 + 200: unknown; 19 + }; 20 + 21 + export type GetBarData = { 22 + body?: never; 23 + path?: never; 24 + query?: never; 25 + url: '/bar'; 26 + }; 27 + 28 + export type GetBarResponses = { 29 + /** 30 + * OK 31 + */ 32 + 200: unknown; 33 + };
+1 -1
packages/openapi-ts-tests/main/package.json
··· 38 38 "@tanstack/vue-query": "5.73.3", 39 39 "@types/cross-spawn": "6.0.6", 40 40 "ajv": "8.17.1", 41 - "arktype": "2.1.28", 41 + "arktype": "2.1.29", 42 42 "axios": "1.13.2", 43 43 "cross-spawn": "7.0.6", 44 44 "eslint": "9.39.1",
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/valibot.gen.ts
··· 8 8 v.number(), 9 9 v.string(), 10 10 v.bigint() 11 - ]), 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)), 11 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), BigInt(0)), 12 12 id: v.string() 13 13 }); 14 14
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/valibot/default/valibot.gen.ts
··· 689 689 export const vTypesData = v.object({ 690 690 body: v.optional(v.never()), 691 691 path: v.optional(v.object({ 692 - 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'))) 692 + id: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))) 693 693 })), 694 694 query: v.object({ 695 695 parameterNumber: v.optional(v.number(), 123),
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/valibot.gen.ts
··· 8 8 v.number(), 9 9 v.string(), 10 10 v.bigint() 11 - ]), 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)), 11 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), BigInt(0)), 12 12 id: v.string() 13 13 }); 14 14
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/valibot/default/valibot.gen.ts
··· 630 630 }); 631 631 632 632 export const vPageable = v.object({ 633 - 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), 634 - 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))), 633 + page: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647')), 0), 634 + size: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))), 635 635 sort: v.optional(v.array(v.string())) 636 636 }); 637 637 ··· 962 962 }), v.strictObject({ 963 963 bar: vNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 964 964 })]), v.object({ 965 - baz: v.union([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()]), 966 - 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)) 965 + baz: v.union([v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 65535')), v.null()]), 966 + qux: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 255')) 967 967 })]); 968 968 969 969 export const vModelWithOneOfAndProperties = v.intersect([v.union([vSimpleParameter, vNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ]), v.object({ 970 - baz: v.union([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()]), 971 - 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)) 970 + baz: v.union([v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 65535')), v.null()]), 971 + qux: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 255')) 972 972 })]); 973 973 974 974 /** ··· 1331 1331 export const vTypesData = v.object({ 1332 1332 body: v.optional(v.never()), 1333 1333 path: v.optional(v.object({ 1334 - 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'))) 1334 + id: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))) 1335 1335 })), 1336 1336 query: v.object({ 1337 1337 parameterNumber: v.optional(v.number(), 123), ··· 1444 1444 vModelWithDictionary 1445 1445 ]), 1446 1446 user: v.optional(v.pipe(v.object({ 1447 - 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())), 1447 + id: v.optional(v.pipe(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647')), v.readonly())), 1448 1448 name: v.optional(v.pipe(v.union([v.pipe(v.string(), v.readonly()), v.null()]), v.readonly())) 1449 1449 }), v.readonly())) 1450 1450 })), 1451 1451 path: v.object({ 1452 - 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')), 1452 + id: v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647')), 1453 1453 'api-version': v.string() 1454 1454 }), 1455 1455 query: v.optional(v.never())
+18 -18
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/integer-formats/valibot.gen.ts
··· 4 4 5 5 export const vIntegerFormats = v.object({ 6 6 numberNoFormat: v.optional(v.number()), 7 - 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'))), 8 - 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'))), 9 - 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'))), 7 + numberInt8: v.optional(v.pipe(v.number(), v.minValue(-128, 'Invalid value: Expected int8 to be >= -128'), v.maxValue(127, 'Invalid value: Expected int8 to be <= 127'))), 8 + numberInt16: v.optional(v.pipe(v.number(), v.minValue(-32768, 'Invalid value: Expected int16 to be >= -32768'), v.maxValue(32767, 'Invalid value: Expected int16 to be <= 32767'))), 9 + numberInt32: v.optional(v.pipe(v.number(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))), 10 10 numberInt64: v.optional(v.pipe(v.union([ 11 11 v.number(), 12 12 v.string(), 13 13 v.bigint() 14 - ]), 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'))), 15 - 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'))), 16 - 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'))), 17 - 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'))), 14 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 15 + 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 <= 255'))), 16 + 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 <= 65535'))), 17 + 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 <= 4294967295'))), 18 18 numberUint64: v.optional(v.pipe(v.union([ 19 19 v.number(), 20 20 v.string(), 21 21 v.bigint() 22 - ]), 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'))), 22 + ]), 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 <= 18446744073709551615'))), 23 23 integerNoFormat: v.optional(v.pipe(v.number(), v.integer())), 24 - 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'))), 25 - 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'))), 26 - 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'))), 24 + integerInt8: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-128, 'Invalid value: Expected int8 to be >= -128'), v.maxValue(127, 'Invalid value: Expected int8 to be <= 127'))), 25 + integerInt16: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-32768, 'Invalid value: Expected int16 to be >= -32768'), v.maxValue(32767, 'Invalid value: Expected int16 to be <= 32767'))), 26 + integerInt32: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))), 27 27 integerInt64: v.optional(v.pipe(v.union([ 28 28 v.number(), 29 29 v.string(), 30 30 v.bigint() 31 - ]), 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'))), 32 - 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'))), 33 - 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'))), 34 - 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'))), 31 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 32 + 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 <= 255'))), 33 + 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 <= 65535'))), 34 + 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 <= 4294967295'))), 35 35 integerUint64: v.optional(v.pipe(v.union([ 36 36 v.number(), 37 37 v.string(), 38 38 v.bigint() 39 - ]), 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'))), 39 + ]), 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 <= 18446744073709551615'))), 40 40 stringInt64: v.optional(v.pipe(v.union([ 41 41 v.number(), 42 42 v.string(), 43 43 v.bigint() 44 - ]), 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'))), 44 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 45 45 stringUint64: v.optional(v.pipe(v.union([ 46 46 v.number(), 47 47 v.string(), 48 48 v.bigint() 49 - ]), 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'))) 49 + ]), 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 <= 18446744073709551615'))) 50 50 });
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/transformers/type-format-valibot/valibot.gen.ts
··· 8 8 v.number(), 9 9 v.string(), 10 10 v.bigint() 11 - ]), 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)), 11 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), BigInt(0)), 12 12 id: v.string() 13 13 }); 14 14
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/transformers/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/valibot/default/valibot.gen.ts
··· 630 630 }); 631 631 632 632 export const vPageable = v.object({ 633 - 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), 634 - 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))), 633 + page: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647')), 0), 634 + size: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))), 635 635 sort: v.optional(v.array(v.string())) 636 636 }); 637 637 ··· 972 972 }), v.strictObject({ 973 973 bar: vNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 974 974 })]), v.object({ 975 - baz: v.union([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()]), 976 - 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)) 975 + baz: v.union([v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 65535')), v.null()]), 976 + qux: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 255')) 977 977 })]); 978 978 979 979 export const vModelWithOneOfAndProperties = v.intersect([v.union([vSimpleParameter, vNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ]), v.object({ 980 - baz: v.union([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()]), 981 - 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)) 980 + baz: v.union([v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(65535, 'Invalid value: Expected uint16 to be <= 65535')), v.null()]), 981 + qux: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(255, 'Invalid value: Expected uint8 to be <= 255')) 982 982 })]); 983 983 984 984 /** ··· 1347 1347 export const vTypesData = v.object({ 1348 1348 body: v.optional(v.never()), 1349 1349 path: v.optional(v.object({ 1350 - 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'))) 1350 + id: v.optional(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647'))) 1351 1351 })), 1352 1352 query: v.object({ 1353 1353 parameterNumber: v.optional(v.number(), 123), ··· 1461 1461 vModelWithDictionary 1462 1462 ]), 1463 1463 user: v.optional(v.pipe(v.object({ 1464 - 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())), 1464 + id: v.optional(v.pipe(v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647')), v.readonly())), 1465 1465 name: v.optional(v.pipe(v.union([v.pipe(v.string(), v.readonly()), v.null()]), v.readonly())) 1466 1466 }), v.readonly())) 1467 1467 })), 1468 1468 path: v.object({ 1469 - 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')), 1469 + id: v.pipe(v.number(), v.integer(), v.minValue(-2147483648, 'Invalid value: Expected int32 to be >= -2147483648'), v.maxValue(2147483647, 'Invalid value: Expected int32 to be <= 2147483647')), 1470 1470 'api-version': v.string() 1471 1471 }), 1472 1472 query: v.optional(v.never())
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/validators-bigint-min-max/valibot.gen.ts
··· 7 7 v.number(), 8 8 v.string(), 9 9 v.bigint() 10 - ]), 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)))) 10 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt(0)), v.maxValue(BigInt(100)))) 11 11 });
+53 -53
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/webhooks/valibot.gen.ts
··· 9 9 v.number(), 10 10 v.string(), 11 11 v.bigint() 12 - ]), 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')), 12 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 13 13 payload: v.strictObject({ 14 14 account_id: v.string(), 15 15 object: v.strictObject({ ··· 17 17 v.number(), 18 18 v.string(), 19 19 v.bigint() 20 - ]), 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'))), 20 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 21 21 uuid: v.optional(v.string()), 22 22 session_id: v.string(), 23 23 session_name: v.string(), ··· 30 30 v.number(), 31 31 v.string(), 32 32 v.bigint() 33 - ]), 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')), 33 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 34 34 from_number: v.pipe(v.union([ 35 35 v.number(), 36 36 v.string(), 37 37 v.bigint() 38 - ]), 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')) 38 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')) 39 39 }) 40 40 }) 41 41 }) ··· 51 51 v.number(), 52 52 v.string(), 53 53 v.bigint() 54 - ]), 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')), 54 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 55 55 payload: v.strictObject({ 56 56 account_id: v.string(), 57 57 object: v.strictObject({ ··· 59 59 v.number(), 60 60 v.string(), 61 61 v.bigint() 62 - ]), 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'))), 62 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 63 63 uuid: v.optional(v.string()), 64 64 session_id: v.string(), 65 65 session_name: v.string(), ··· 84 84 v.number(), 85 85 v.string(), 86 86 v.bigint() 87 - ]), 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')), 87 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 88 88 payload: v.strictObject({ 89 89 account_id: v.string(), 90 90 object: v.strictObject({ ··· 111 111 v.number(), 112 112 v.string(), 113 113 v.bigint() 114 - ]), 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')), 114 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 115 115 payload: v.strictObject({ 116 116 account_id: v.string(), 117 117 object: v.strictObject({ ··· 138 138 v.number(), 139 139 v.string(), 140 140 v.bigint() 141 - ]), 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')), 141 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 142 142 payload: v.strictObject({ 143 143 account_id: v.string(), 144 144 object: v.strictObject({ ··· 176 176 v.number(), 177 177 v.string(), 178 178 v.bigint() 179 - ]), 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')), 179 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 180 180 payload: v.strictObject({ 181 181 account_id: v.string(), 182 182 object: v.strictObject({ ··· 205 205 v.number(), 206 206 v.string(), 207 207 v.bigint() 208 - ]), 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')), 208 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 209 209 payload: v.strictObject({ 210 210 account_id: v.string(), 211 211 object: v.strictObject({ ··· 213 213 v.number(), 214 214 v.string(), 215 215 v.bigint() 216 - ]), 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'))), 216 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 217 217 uuid: v.optional(v.string()), 218 218 session_id: v.string(), 219 219 session_name: v.string(), ··· 238 238 v.number(), 239 239 v.string(), 240 240 v.bigint() 241 - ]), 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')), 241 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 242 242 payload: v.strictObject({ 243 243 account_id: v.string(), 244 244 object: v.strictObject({ ··· 267 267 v.number(), 268 268 v.string(), 269 269 v.bigint() 270 - ]), 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')), 270 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 271 271 payload: v.strictObject({ 272 272 account_id: v.string(), 273 273 object: v.strictObject({ ··· 303 303 v.number(), 304 304 v.string(), 305 305 v.bigint() 306 - ]), 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')), 306 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 307 307 payload: v.strictObject({ 308 308 account_id: v.string(), 309 309 object: v.strictObject({ ··· 330 330 v.number(), 331 331 v.string(), 332 332 v.bigint() 333 - ]), 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')), 333 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 334 334 payload: v.strictObject({ 335 335 account_id: v.string(), 336 336 object: v.strictObject({ ··· 354 354 v.number(), 355 355 v.string(), 356 356 v.bigint() 357 - ]), 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')), 357 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 358 358 payload: v.strictObject({ 359 359 account_id: v.string(), 360 360 object: v.strictObject({ ··· 377 377 v.number(), 378 378 v.string(), 379 379 v.bigint() 380 - ]), 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')), 380 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 381 381 payload: v.strictObject({ 382 382 account_id: v.string(), 383 383 object: v.strictObject({ ··· 406 406 v.number(), 407 407 v.string(), 408 408 v.bigint() 409 - ]), 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')), 409 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 410 410 payload: v.strictObject({ 411 411 account_id: v.string(), 412 412 object: v.strictObject({ ··· 444 444 v.number(), 445 445 v.string(), 446 446 v.bigint() 447 - ]), 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')), 447 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 448 448 payload: v.strictObject({ 449 449 account_id: v.string(), 450 450 object: v.strictObject({ ··· 452 452 v.number(), 453 453 v.string(), 454 454 v.bigint() 455 - ]), 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'))), 455 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 456 456 uuid: v.optional(v.string()), 457 457 session_id: v.string(), 458 458 session_name: v.string(), ··· 477 477 v.number(), 478 478 v.string(), 479 479 v.bigint() 480 - ]), 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')), 480 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 481 481 payload: v.strictObject({ 482 482 account_id: v.string(), 483 483 object: v.strictObject({ ··· 485 485 v.number(), 486 486 v.string(), 487 487 v.bigint() 488 - ]), 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'))), 488 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 489 489 uuid: v.optional(v.string()), 490 490 session_id: v.string(), 491 491 session_name: v.string(), ··· 498 498 v.number(), 499 499 v.string(), 500 500 v.bigint() 501 - ]), 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')), 501 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 502 502 from_number: v.pipe(v.union([ 503 503 v.number(), 504 504 v.string(), 505 505 v.bigint() 506 - ]), 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')) 506 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')) 507 507 }) 508 508 }) 509 509 }) ··· 519 519 v.number(), 520 520 v.string(), 521 521 v.bigint() 522 - ]), 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')), 522 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 523 523 payload: v.strictObject({ 524 524 account_id: v.string(), 525 525 object: v.strictObject({ ··· 550 550 v.number(), 551 551 v.string(), 552 552 v.bigint() 553 - ]), 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')), 553 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 554 554 payload: v.strictObject({ 555 555 account_id: v.string(), 556 556 object: v.strictObject({ ··· 586 586 v.number(), 587 587 v.string(), 588 588 v.bigint() 589 - ]), 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')), 589 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 590 590 payload: v.strictObject({ 591 591 account_id: v.string(), 592 592 object: v.strictObject({ ··· 600 600 v.number(), 601 601 v.string(), 602 602 v.bigint() 603 - ]), 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')), 603 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 604 604 from_number: v.pipe(v.union([ 605 605 v.number(), 606 606 v.string(), 607 607 v.bigint() 608 - ]), 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')) 608 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')) 609 609 }) 610 610 }) 611 611 }) ··· 621 621 v.number(), 622 622 v.string(), 623 623 v.bigint() 624 - ]), 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')), 624 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 625 625 download_token: v.string(), 626 626 payload: v.strictObject({ 627 627 account_id: v.string(), ··· 694 694 v.number(), 695 695 v.string(), 696 696 v.bigint() 697 - ]), 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')), 697 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 698 698 payload: v.strictObject({ 699 699 account_id: v.string(), 700 700 operator: v.pipe(v.string(), v.email()), ··· 719 719 v.number(), 720 720 v.string(), 721 721 v.bigint() 722 - ]), 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')), 722 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 723 723 payload: v.strictObject({ 724 724 account_id: v.string(), 725 725 object: v.strictObject({ ··· 727 727 v.number(), 728 728 v.string(), 729 729 v.bigint() 730 - ]), 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'))), 730 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 731 731 uuid: v.optional(v.string()), 732 732 session_id: v.string(), 733 733 session_name: v.string(), ··· 753 753 v.number(), 754 754 v.string(), 755 755 v.bigint() 756 - ]), 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')), 756 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 757 757 download_token: v.string(), 758 758 payload: v.strictObject({ 759 759 account_id: v.string(), ··· 890 890 v.number(), 891 891 v.string(), 892 892 v.bigint() 893 - ]), 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')), 893 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 894 894 payload: v.strictObject({ 895 895 account_id: v.string(), 896 896 object: v.strictObject({ ··· 913 913 v.number(), 914 914 v.string(), 915 915 v.bigint() 916 - ]), 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')), 916 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 917 917 payload: v.strictObject({ 918 918 account_id: v.string(), 919 919 operator: v.pipe(v.string(), v.email()), ··· 938 938 v.number(), 939 939 v.string(), 940 940 v.bigint() 941 - ]), 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')), 941 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 942 942 payload: v.strictObject({ 943 943 account_id: v.string(), 944 944 object: v.strictObject({ ··· 968 968 v.number(), 969 969 v.string(), 970 970 v.bigint() 971 - ]), 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')), 971 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 972 972 payload: v.strictObject({ 973 973 account_id: v.string(), 974 974 object: v.strictObject({ ··· 997 997 v.number(), 998 998 v.string(), 999 999 v.bigint() 1000 - ]), 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')), 1000 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1001 1001 payload: v.strictObject({ 1002 1002 account_id: v.string(), 1003 1003 object: v.strictObject({ ··· 1026 1026 v.number(), 1027 1027 v.string(), 1028 1028 v.bigint() 1029 - ]), 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')), 1029 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1030 1030 payload: v.strictObject({ 1031 1031 account_id: v.string(), 1032 1032 object: v.strictObject({ ··· 1055 1055 v.number(), 1056 1056 v.string(), 1057 1057 v.bigint() 1058 - ]), 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')), 1058 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1059 1059 payload: v.strictObject({ 1060 1060 account_id: v.string(), 1061 1061 operator: v.pipe(v.string(), v.email()), ··· 1080 1080 v.number(), 1081 1081 v.string(), 1082 1082 v.bigint() 1083 - ]), 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')), 1083 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1084 1084 payload: v.strictObject({ 1085 1085 account_id: v.string(), 1086 1086 object: v.strictObject({ ··· 1088 1088 v.number(), 1089 1089 v.string(), 1090 1090 v.bigint() 1091 - ]), 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'))), 1091 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 1092 1092 uuid: v.optional(v.string()), 1093 1093 session_id: v.string(), 1094 1094 session_name: v.string(), ··· 1101 1101 v.number(), 1102 1102 v.string(), 1103 1103 v.bigint() 1104 - ]), 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')), 1104 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1105 1105 from_number: v.pipe(v.union([ 1106 1106 v.number(), 1107 1107 v.string(), 1108 1108 v.bigint() 1109 - ]), 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')) 1109 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')) 1110 1110 }) 1111 1111 }) 1112 1112 }) ··· 1122 1122 v.number(), 1123 1123 v.string(), 1124 1124 v.bigint() 1125 - ]), 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')), 1125 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1126 1126 payload: v.strictObject({ 1127 1127 account_id: v.string(), 1128 1128 object: v.strictObject({ ··· 1130 1130 v.number(), 1131 1131 v.string(), 1132 1132 v.bigint() 1133 - ]), 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'))), 1133 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 1134 1134 uuid: v.optional(v.string()), 1135 1135 session_id: v.string(), 1136 1136 session_name: v.string(), ··· 1143 1143 v.number(), 1144 1144 v.string(), 1145 1145 v.bigint() 1146 - ]), 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')), 1146 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1147 1147 from_number: v.pipe(v.union([ 1148 1148 v.number(), 1149 1149 v.string(), 1150 1150 v.bigint() 1151 - ]), 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')) 1151 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')) 1152 1152 }) 1153 1153 }) 1154 1154 }) ··· 1164 1164 v.number(), 1165 1165 v.string(), 1166 1166 v.bigint() 1167 - ]), 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')), 1167 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1168 1168 payload: v.strictObject({ 1169 1169 account_id: v.string(), 1170 1170 object: v.strictObject({ ··· 1172 1172 v.number(), 1173 1173 v.string(), 1174 1174 v.bigint() 1175 - ]), 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'))), 1175 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807'))), 1176 1176 uuid: v.optional(v.string()), 1177 1177 session_id: v.string(), 1178 1178 session_name: v.string(), ··· 1197 1197 v.number(), 1198 1198 v.string(), 1199 1199 v.bigint() 1200 - ]), 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')), 1200 + ]), v.transform(x => BigInt(x)), v.minValue(BigInt('-9223372036854775808'), 'Invalid value: Expected int64 to be >= -9223372036854775808'), v.maxValue(BigInt('9223372036854775807'), 'Invalid value: Expected int64 to be <= 9223372036854775807')), 1201 1201 payload: v.strictObject({ 1202 1202 account_id: v.string(), 1203 1203 object: v.strictObject({
+53 -53
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/webhooks/zod.gen.ts
··· 5 5 export const zSessionUserPhoneCalloutRingingWebhookRequest = z.object({ 6 6 body: z.optional(z.object({ 7 7 event: z.string(), 8 - event_ts: z.coerce.bigint(), 8 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 9 9 payload: z.object({ 10 10 account_id: z.string(), 11 11 object: z.object({ 12 - id: z.optional(z.coerce.bigint()), 12 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 13 13 uuid: z.optional(z.string()), 14 14 session_id: z.string(), 15 15 session_name: z.string(), ··· 18 18 host_id: z.string(), 19 19 participant: z.object({ 20 20 invitee_name: z.string(), 21 - phone_number: z.coerce.bigint(), 22 - from_number: z.coerce.bigint() 21 + phone_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 22 + from_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }) 23 23 }) 24 24 }) 25 25 }) ··· 31 31 export const zSessionUserRoomSystemCalloutRingingWebhookRequest = z.object({ 32 32 body: z.optional(z.object({ 33 33 event: z.string(), 34 - event_ts: z.coerce.bigint(), 34 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 35 35 payload: z.object({ 36 36 account_id: z.string(), 37 37 object: z.object({ 38 - id: z.optional(z.coerce.bigint()), 38 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 39 39 uuid: z.optional(z.string()), 40 40 session_id: z.string(), 41 41 session_name: z.string(), ··· 56 56 export const zSessionRecordingStartedWebhookRequest = z.object({ 57 57 body: z.optional(z.object({ 58 58 event: z.enum(['session.recording_started']), 59 - event_ts: z.coerce.bigint(), 59 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 60 60 payload: z.object({ 61 61 account_id: z.string(), 62 62 object: z.object({ ··· 79 79 export const zSessionRecordingResumedWebhookRequest = z.object({ 80 80 body: z.optional(z.object({ 81 81 event: z.enum(['session.recording_resumed']), 82 - event_ts: z.coerce.bigint(), 82 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 83 83 payload: z.object({ 84 84 account_id: z.string(), 85 85 object: z.object({ ··· 102 102 export const zSessionLiveStreamingStoppedWebhookRequest = z.object({ 103 103 body: z.optional(z.object({ 104 104 event: z.enum(['session.live_streaming_stopped']), 105 - event_ts: z.coerce.bigint(), 105 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 106 106 payload: z.object({ 107 107 account_id: z.string(), 108 108 object: z.object({ ··· 136 136 export const zSessionStreamIngestionStoppedWebhookRequest = z.object({ 137 137 body: z.optional(z.object({ 138 138 event: z.enum(['session.stream_ingestion_stopped']), 139 - event_ts: z.coerce.bigint(), 139 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 140 140 payload: z.object({ 141 141 account_id: z.string(), 142 142 object: z.object({ ··· 161 161 export const zSessionUserRoomSystemCalloutRejectedWebhookRequest = z.object({ 162 162 body: z.optional(z.object({ 163 163 event: z.string(), 164 - event_ts: z.coerce.bigint(), 164 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 165 165 payload: z.object({ 166 166 account_id: z.string(), 167 167 object: z.object({ 168 - id: z.optional(z.coerce.bigint()), 168 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 169 169 uuid: z.optional(z.string()), 170 170 session_id: z.string(), 171 171 session_name: z.string(), ··· 186 186 export const zSessionAlertWebhookRequest = z.object({ 187 187 body: z.optional(z.object({ 188 188 event: z.enum(['session.alert']), 189 - event_ts: z.coerce.bigint(), 189 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 190 190 payload: z.object({ 191 191 account_id: z.string(), 192 192 object: z.object({ ··· 211 211 export const zSessionSharingEndedWebhookRequest = z.object({ 212 212 body: z.optional(z.object({ 213 213 event: z.enum(['session.sharing_ended']), 214 - event_ts: z.coerce.bigint(), 214 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 215 215 payload: z.object({ 216 216 account_id: z.string(), 217 217 object: z.object({ ··· 243 243 export const zSessionRecordingPausedWebhookRequest = z.object({ 244 244 body: z.optional(z.object({ 245 245 event: z.enum(['session.recording_paused']), 246 - event_ts: z.coerce.bigint(), 246 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 247 247 payload: z.object({ 248 248 account_id: z.string(), 249 249 object: z.object({ ··· 266 266 export const zSessionEndedWebhookRequest = z.object({ 267 267 body: z.optional(z.object({ 268 268 event: z.enum(['session.ended']), 269 - event_ts: z.coerce.bigint(), 269 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 270 270 payload: z.object({ 271 271 account_id: z.string(), 272 272 object: z.object({ ··· 286 286 export const zSessionStartedWebhookRequest = z.object({ 287 287 body: z.optional(z.object({ 288 288 event: z.enum(['session.started']), 289 - event_ts: z.coerce.bigint(), 289 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 290 290 payload: z.object({ 291 291 account_id: z.string(), 292 292 object: z.object({ ··· 305 305 export const zSessionStreamIngestionUnbindWebhookRequest = z.object({ 306 306 body: z.optional(z.object({ 307 307 event: z.enum(['session.stream_ingestion_unbind']), 308 - event_ts: z.coerce.bigint(), 308 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 309 309 payload: z.object({ 310 310 account_id: z.string(), 311 311 object: z.object({ ··· 330 330 export const zSessionLiveStreamingStartedWebhookRequest = z.object({ 331 331 body: z.optional(z.object({ 332 332 event: z.enum(['session.live_streaming_started']), 333 - event_ts: z.coerce.bigint(), 333 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 334 334 payload: z.object({ 335 335 account_id: z.string(), 336 336 object: z.object({ ··· 364 364 export const zSessionUserRoomSystemCalloutMissedWebhookRequest = z.object({ 365 365 body: z.optional(z.object({ 366 366 event: z.string(), 367 - event_ts: z.coerce.bigint(), 367 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 368 368 payload: z.object({ 369 369 account_id: z.string(), 370 370 object: z.object({ 371 - id: z.optional(z.coerce.bigint()), 371 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 372 372 uuid: z.optional(z.string()), 373 373 session_id: z.string(), 374 374 session_name: z.string(), ··· 389 389 export const zSessionUserPhoneCalloutAcceptedWebhookRequest = z.object({ 390 390 body: z.optional(z.object({ 391 391 event: z.string(), 392 - event_ts: z.coerce.bigint(), 392 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 393 393 payload: z.object({ 394 394 account_id: z.string(), 395 395 object: z.object({ 396 - id: z.optional(z.coerce.bigint()), 396 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 397 397 uuid: z.optional(z.string()), 398 398 session_id: z.string(), 399 399 session_name: z.string(), ··· 402 402 host_id: z.string(), 403 403 participant: z.object({ 404 404 invitee_name: z.string(), 405 - phone_number: z.coerce.bigint(), 406 - from_number: z.coerce.bigint() 405 + phone_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 406 + from_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }) 407 407 }) 408 408 }) 409 409 }) ··· 415 415 export const zSessionUserLeftWebhookRequest = z.object({ 416 416 body: z.optional(z.object({ 417 417 event: z.enum(['session.user_left']), 418 - event_ts: z.coerce.bigint(), 418 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 419 419 payload: z.object({ 420 420 account_id: z.string(), 421 421 object: z.object({ ··· 442 442 export const zSessionSharingStartedWebhookRequest = z.object({ 443 443 body: z.optional(z.object({ 444 444 event: z.enum(['session.sharing_started']), 445 - event_ts: z.coerce.bigint(), 445 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 446 446 payload: z.object({ 447 447 account_id: z.string(), 448 448 object: z.object({ ··· 474 474 export const zSessionUserPhoneCalloutCanceledWebhookRequest = z.object({ 475 475 body: z.optional(z.object({ 476 476 event: z.string(), 477 - event_ts: z.coerce.bigint(), 477 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 478 478 payload: z.object({ 479 479 account_id: z.string(), 480 480 object: z.object({ ··· 484 484 user_key: z.string(), 485 485 participant: z.object({ 486 486 invitee_name: z.string(), 487 - phone_number: z.coerce.bigint(), 488 - from_number: z.coerce.bigint() 487 + phone_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 488 + from_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }) 489 489 }) 490 490 }) 491 491 }) ··· 497 497 export const zSessionRecordingTranscriptCompletedWebhookRequest = z.object({ 498 498 body: z.optional(z.object({ 499 499 event: z.enum(['session.recording_transcript_completed']), 500 - event_ts: z.coerce.bigint(), 500 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 501 501 download_token: z.string(), 502 502 payload: z.object({ 503 503 account_id: z.string(), ··· 566 566 export const zSessionRecordingDeletedWebhookRequest = z.object({ 567 567 body: z.optional(z.object({ 568 568 event: z.enum(['session.recording_deleted']), 569 - event_ts: z.coerce.bigint(), 569 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 570 570 payload: z.object({ 571 571 account_id: z.string(), 572 572 operator: z.email(), ··· 587 587 export const zSessionUserRoomSystemCalloutFailedWebhookRequest = z.object({ 588 588 body: z.optional(z.object({ 589 589 event: z.string(), 590 - event_ts: z.coerce.bigint(), 590 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 591 591 payload: z.object({ 592 592 account_id: z.string(), 593 593 object: z.object({ 594 - id: z.optional(z.coerce.bigint()), 594 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 595 595 uuid: z.optional(z.string()), 596 596 session_id: z.string(), 597 597 session_name: z.string(), ··· 627 627 export const zSessionRecordingCompletedWebhookRequest = z.object({ 628 628 body: z.optional(z.object({ 629 629 event: z.enum(['session.recording_completed']), 630 - event_ts: z.coerce.bigint(), 630 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 631 631 download_token: z.string(), 632 632 payload: z.object({ 633 633 account_id: z.string(), ··· 760 760 export const zSessionRecordingTranscriptFailedWebhookRequest = z.object({ 761 761 body: z.optional(z.object({ 762 762 event: z.enum(['session.recording_transcript_failed']), 763 - event_ts: z.coerce.bigint(), 763 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 764 764 payload: z.object({ 765 765 account_id: z.string(), 766 766 object: z.object({ ··· 779 779 export const zSessionRecordingTrashedWebhookRequest = z.object({ 780 780 body: z.optional(z.object({ 781 781 event: z.enum(['session.recording_trashed']), 782 - event_ts: z.coerce.bigint(), 782 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 783 783 payload: z.object({ 784 784 account_id: z.string(), 785 785 operator: z.email(), ··· 800 800 export const zSessionUserJoinedWebhookRequest = z.object({ 801 801 body: z.optional(z.object({ 802 802 event: z.enum(['session.user_joined']), 803 - event_ts: z.coerce.bigint(), 803 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 804 804 payload: z.object({ 805 805 account_id: z.string(), 806 806 object: z.object({ ··· 826 826 export const zSessionStreamIngestionStartedWebhookRequest = z.object({ 827 827 body: z.optional(z.object({ 828 828 event: z.enum(['session.stream_ingestion_started']), 829 - event_ts: z.coerce.bigint(), 829 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 830 830 payload: z.object({ 831 831 account_id: z.string(), 832 832 object: z.object({ ··· 851 851 export const zSessionStreamIngestionConnectedWebhookRequest = z.object({ 852 852 body: z.optional(z.object({ 853 853 event: z.enum(['session.stream_ingestion_connected']), 854 - event_ts: z.coerce.bigint(), 854 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 855 855 payload: z.object({ 856 856 account_id: z.string(), 857 857 object: z.object({ ··· 876 876 export const zSessionStreamIngestionDisconnectedWebhookRequest = z.object({ 877 877 body: z.optional(z.object({ 878 878 event: z.enum(['session.stream_ingestion_disconnected']), 879 - event_ts: z.coerce.bigint(), 879 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 880 880 payload: z.object({ 881 881 account_id: z.string(), 882 882 object: z.object({ ··· 901 901 export const zSessionRecordingRecoveredWebhookRequest = z.object({ 902 902 body: z.optional(z.object({ 903 903 event: z.enum(['session.recording_recovered']), 904 - event_ts: z.coerce.bigint(), 904 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 905 905 payload: z.object({ 906 906 account_id: z.string(), 907 907 operator: z.email(), ··· 922 922 export const zSessionUserPhoneCalloutMissedWebhookRequest = z.object({ 923 923 body: z.optional(z.object({ 924 924 event: z.string(), 925 - event_ts: z.coerce.bigint(), 925 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 926 926 payload: z.object({ 927 927 account_id: z.string(), 928 928 object: z.object({ 929 - id: z.optional(z.coerce.bigint()), 929 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 930 930 uuid: z.optional(z.string()), 931 931 session_id: z.string(), 932 932 session_name: z.string(), ··· 935 935 host_id: z.string(), 936 936 participant: z.object({ 937 937 invitee_name: z.string(), 938 - phone_number: z.coerce.bigint(), 939 - from_number: z.coerce.bigint() 938 + phone_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 939 + from_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }) 940 940 }) 941 941 }) 942 942 }) ··· 948 948 export const zSessionUserPhoneCalloutRejectedWebhookRequest = z.object({ 949 949 body: z.optional(z.object({ 950 950 event: z.string(), 951 - event_ts: z.coerce.bigint(), 951 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 952 952 payload: z.object({ 953 953 account_id: z.string(), 954 954 object: z.object({ 955 - id: z.optional(z.coerce.bigint()), 955 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 956 956 uuid: z.optional(z.string()), 957 957 session_id: z.string(), 958 958 session_name: z.string(), ··· 961 961 host_id: z.string(), 962 962 participant: z.object({ 963 963 invitee_name: z.string(), 964 - phone_number: z.coerce.bigint(), 965 - from_number: z.coerce.bigint() 964 + phone_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 965 + from_number: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }) 966 966 }) 967 967 }) 968 968 }) ··· 974 974 export const zSessionUserRoomSystemCalloutAcceptedWebhookRequest = z.object({ 975 975 body: z.optional(z.object({ 976 976 event: z.string(), 977 - event_ts: z.coerce.bigint(), 977 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 978 978 payload: z.object({ 979 979 account_id: z.string(), 980 980 object: z.object({ 981 - id: z.optional(z.coerce.bigint()), 981 + id: z.optional(z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), 982 982 uuid: z.optional(z.string()), 983 983 session_id: z.string(), 984 984 session_name: z.string(), ··· 999 999 export const zSessionRecordingStoppedWebhookRequest = z.object({ 1000 1000 body: z.optional(z.object({ 1001 1001 event: z.enum(['session.recording_stopped']), 1002 - event_ts: z.coerce.bigint(), 1002 + event_ts: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), 1003 1003 payload: z.object({ 1004 1004 account_id: z.string(), 1005 1005 object: z.object({
+318
packages/openapi-ts-tests/main/test/additional-properties.test.ts
··· 1 + import * as v from 'valibot'; 2 + import { beforeAll, describe, expect, it } from 'vitest'; 3 + 4 + import { setupValibotTest } from './test-helper'; 5 + 6 + // TODO: further clean up 7 + describe('Object Additional Properties Tests', () => { 8 + let generatedSchemas: any; 9 + 10 + beforeAll(async () => { 11 + generatedSchemas = await setupValibotTest( 12 + 'additional-properties.yaml', 13 + 'additional-properties', 14 + ); 15 + }); 16 + 17 + describe('ObjectWithAdditionalPropertiesString', () => { 18 + it('should preserve string additional properties in nested headers object', () => { 19 + const input = { 20 + headers: { 21 + Authorization: 'Bearer token', 22 + 'Content-Type': 'application/json', 23 + }, 24 + }; 25 + const result = v.safeParse( 26 + generatedSchemas.vObjectWithAdditionalPropertiesString, 27 + input, 28 + ); 29 + expect(result.success).toBe(true); 30 + if (result.success) { 31 + expect(result.output.headers).toEqual({ 32 + Authorization: 'Bearer token', 33 + 'Content-Type': 'application/json', 34 + }); 35 + } 36 + }); 37 + 38 + it('should reject non-string values in additional properties', () => { 39 + const input = { 40 + headers: { 41 + Authorization: 'Bearer token', 42 + Count: 123, // Invalid: should be string 43 + }, 44 + }; 45 + const result = v.safeParse( 46 + generatedSchemas.vObjectWithAdditionalPropertiesString, 47 + input, 48 + ); 49 + expect(result.success).toBe(false); 50 + }); 51 + 52 + it('should accept empty headers object', () => { 53 + const input = { 54 + headers: {}, 55 + }; 56 + const result = v.safeParse( 57 + generatedSchemas.vObjectWithAdditionalPropertiesString, 58 + input, 59 + ); 60 + expect(result.success).toBe(true); 61 + }); 62 + }); 63 + 64 + describe('ObjectOnlyAdditionalPropertiesString', () => { 65 + it('should preserve string additional properties', () => { 66 + const input = { 67 + key1: 'value1', 68 + key2: 'value2', 69 + key3: 'value3', 70 + }; 71 + const result = v.safeParse( 72 + generatedSchemas.vObjectOnlyAdditionalPropertiesString, 73 + input, 74 + ); 75 + expect(result.success).toBe(true); 76 + if (result.success) { 77 + expect(result.output).toEqual(input); 78 + } 79 + }); 80 + 81 + it('should reject non-string values', () => { 82 + const input = { 83 + key1: 'value1', 84 + key2: 123, // Invalid: should be string 85 + }; 86 + const result = v.safeParse( 87 + generatedSchemas.vObjectOnlyAdditionalPropertiesString, 88 + input, 89 + ); 90 + expect(result.success).toBe(false); 91 + }); 92 + }); 93 + 94 + describe('ObjectOnlyAdditionalPropertiesNumber', () => { 95 + it('should preserve number additional properties', () => { 96 + const input = { 97 + score1: 100, 98 + score2: 95.5, 99 + score3: 0, 100 + }; 101 + const result = v.safeParse( 102 + generatedSchemas.vObjectOnlyAdditionalPropertiesNumber, 103 + input, 104 + ); 105 + expect(result.success).toBe(true); 106 + if (result.success) { 107 + expect(result.output).toEqual(input); 108 + } 109 + }); 110 + 111 + it('should reject non-number values', () => { 112 + const input = { 113 + score1: 100, 114 + score2: 'invalid', // Invalid: should be number 115 + }; 116 + const result = v.safeParse( 117 + generatedSchemas.vObjectOnlyAdditionalPropertiesNumber, 118 + input, 119 + ); 120 + expect(result.success).toBe(false); 121 + }); 122 + }); 123 + 124 + describe('ObjectOnlyAdditionalPropertiesBoolean', () => { 125 + it('should preserve boolean additional properties', () => { 126 + const input = { 127 + flag1: true, 128 + flag2: false, 129 + flag3: true, 130 + }; 131 + const result = v.safeParse( 132 + generatedSchemas.vObjectOnlyAdditionalPropertiesBoolean, 133 + input, 134 + ); 135 + expect(result.success).toBe(true); 136 + if (result.success) { 137 + expect(result.output).toEqual(input); 138 + } 139 + }); 140 + 141 + it('should reject non-boolean values', () => { 142 + const input = { 143 + flag1: true, 144 + flag2: 'true', // Invalid: should be boolean 145 + }; 146 + const result = v.safeParse( 147 + generatedSchemas.vObjectOnlyAdditionalPropertiesBoolean, 148 + input, 149 + ); 150 + expect(result.success).toBe(false); 151 + }); 152 + }); 153 + 154 + describe('ObjectWithPropertiesAndAdditionalPropertiesNumber', () => { 155 + it('should preserve both named properties and additional properties', () => { 156 + const input = { 157 + count: 42, 158 + extra1: 1.5, 159 + extra2: 2.5, 160 + id: 'abc123', 161 + }; 162 + const result = v.safeParse( 163 + generatedSchemas.vObjectWithPropertiesAndAdditionalPropertiesNumber, 164 + input, 165 + ); 166 + if (!result.success) { 167 + console.log('Validation failed:', result.issues); 168 + } 169 + expect(result.success).toBe(true); 170 + if (result.success) { 171 + expect(result.output).toEqual(input); 172 + } 173 + }); 174 + 175 + it('should validate types of both named and additional properties', () => { 176 + const input = { 177 + count: 42, 178 + extra1: 'invalid', 179 + id: 'abc123', // Invalid: should be number 180 + }; 181 + const result = v.safeParse( 182 + generatedSchemas.vObjectWithPropertiesAndAdditionalPropertiesNumber, 183 + input, 184 + ); 185 + expect(result.success).toBe(false); 186 + }); 187 + 188 + it('should require named properties but allow empty additional properties', () => { 189 + const input = { 190 + count: 42, 191 + id: 'abc123', 192 + }; 193 + const result = v.safeParse( 194 + generatedSchemas.vObjectWithPropertiesAndAdditionalPropertiesNumber, 195 + input, 196 + ); 197 + expect(result.success).toBe(true); 198 + }); 199 + }); 200 + 201 + describe('ObjectWithAdditionalPropertiesObject', () => { 202 + it('should preserve nested object additional properties', () => { 203 + const input = { 204 + metadata: { 205 + field1: { value: 'test1' }, 206 + field2: { value: 'test2' }, 207 + }, 208 + }; 209 + const result = v.safeParse( 210 + generatedSchemas.vObjectWithAdditionalPropertiesObject, 211 + input, 212 + ); 213 + expect(result.success).toBe(true); 214 + if (result.success) { 215 + expect(result.output.metadata).toEqual({ 216 + field1: { value: 'test1' }, 217 + field2: { value: 'test2' }, 218 + }); 219 + } 220 + }); 221 + 222 + it('should validate nested object structure', () => { 223 + const input = { 224 + metadata: { 225 + field1: { value: 'test1' }, 226 + field2: { invalidKey: 'test2' }, // Object without required structure 227 + }, 228 + }; 229 + const result = v.safeParse( 230 + generatedSchemas.vObjectWithAdditionalPropertiesObject, 231 + input, 232 + ); 233 + // Should succeed as the nested object properties are optional 234 + expect(result.success).toBe(true); 235 + }); 236 + }); 237 + 238 + describe('ObjectOnlyAdditionalPropertiesObject', () => { 239 + it('should preserve object additional properties', () => { 240 + const input = { 241 + item1: { name: 'Item 1' }, 242 + item2: { name: 'Item 2' }, 243 + }; 244 + const result = v.safeParse( 245 + generatedSchemas.vObjectOnlyAdditionalPropertiesObject, 246 + input, 247 + ); 248 + expect(result.success).toBe(true); 249 + if (result.success) { 250 + expect(result.output).toEqual(input); 251 + } 252 + }); 253 + }); 254 + 255 + describe('ObjectWithAdditionalPropertiesFalse', () => { 256 + it('should accept object with only defined properties', () => { 257 + const input = { 258 + count: 42, 259 + id: 'abc123', 260 + }; 261 + const result = v.safeParse( 262 + generatedSchemas.vObjectWithAdditionalPropertiesFalse, 263 + input, 264 + ); 265 + expect(result.success).toBe(true); 266 + if (result.success) { 267 + expect(result.output).toEqual(input); 268 + } 269 + }); 270 + 271 + it('should reject object with additional properties', () => { 272 + const input = { 273 + count: 42, 274 + extra: 'not allowed', 275 + id: 'abc123', 276 + }; 277 + const result = v.safeParse( 278 + generatedSchemas.vObjectWithAdditionalPropertiesFalse, 279 + input, 280 + ); 281 + expect(result.success).toBe(false); 282 + }); 283 + }); 284 + 285 + describe('ObjectWithNestedAdditionalPropertiesFalse', () => { 286 + it('should accept object with correct nested properties', () => { 287 + const input = { 288 + membership: { 289 + calendar_membership_tier_id: 'tier_id', 290 + status: 'approved', 291 + }, 292 + }; 293 + const result = v.safeParse( 294 + generatedSchemas.vObjectWithNestedAdditionalPropertiesFalse, 295 + input, 296 + ); 297 + expect(result.success).toBe(true); 298 + if (result.success) { 299 + expect(result.output).toEqual(input); 300 + } 301 + }); 302 + 303 + it('should reject object with additional properties in nested object', () => { 304 + const input = { 305 + membership: { 306 + calendar_membership_tier_id: 'tier_id', 307 + extra: 'not allowed', 308 + status: 'approved', 309 + }, 310 + }; 311 + const result = v.safeParse( 312 + generatedSchemas.vObjectWithNestedAdditionalPropertiesFalse, 313 + input, 314 + ); 315 + expect(result.success).toBe(false); 316 + }); 317 + }); 318 + });
+296
packages/openapi-ts-tests/main/test/const-values.test.ts
··· 1 + import * as v from 'valibot'; 2 + import { beforeAll, describe, expect, it } from 'vitest'; 3 + 4 + import { setupValibotTest } from './test-helper'; 5 + 6 + // TODO: further clean up 7 + describe('Number Type Const Values Tests', () => { 8 + let generatedSchemas: any; 9 + 10 + beforeAll(async () => { 11 + generatedSchemas = await setupValibotTest( 12 + 'const-values.yaml', 13 + 'const-values', 14 + ); 15 + }); 16 + 17 + describe('Number Type Const Validation', () => { 18 + it('should accept exact const value', () => { 19 + const result = v.safeParse(generatedSchemas.vNumberNoFormat, 42.5); 20 + expect(result.success).toBe(true); 21 + }); 22 + 23 + it('should reject non-matching values', () => { 24 + const result = v.safeParse(generatedSchemas.vNumberNoFormat, 42.6); 25 + expect(result.success).toBe(false); 26 + }); 27 + }); 28 + 29 + describe('Number Type Format Const Validation', () => { 30 + it('should accept NumberInt8 exact const value', () => { 31 + const result = v.safeParse(generatedSchemas.vNumberInt8, 100); 32 + expect(result.success).toBe(true); 33 + }); 34 + 35 + it('should reject NumberInt8 non-matching values', () => { 36 + const result = v.safeParse(generatedSchemas.vNumberInt8, 101); 37 + expect(result.success).toBe(false); 38 + }); 39 + 40 + it('should accept NumberInt16 exact const value', () => { 41 + const result = v.safeParse(generatedSchemas.vNumberInt16, 1000); 42 + expect(result.success).toBe(true); 43 + }); 44 + 45 + it('should reject NumberInt16 non-matching values', () => { 46 + const result = v.safeParse(generatedSchemas.vNumberInt16, 1001); 47 + expect(result.success).toBe(false); 48 + }); 49 + 50 + it('should accept NumberInt32 exact const value', () => { 51 + const result = v.safeParse(generatedSchemas.vNumberInt32, 100000); 52 + expect(result.success).toBe(true); 53 + }); 54 + 55 + it('should reject NumberInt32 non-matching values', () => { 56 + const result = v.safeParse(generatedSchemas.vNumberInt32, 100001); 57 + expect(result.success).toBe(false); 58 + }); 59 + 60 + it('should accept NumberInt64 exact const value', () => { 61 + const result = v.safeParse( 62 + generatedSchemas.vNumberInt64, 63 + BigInt('1000000000000'), 64 + ); 65 + expect(result.success).toBe(true); 66 + }); 67 + 68 + it('should reject NumberInt64 non-matching values', () => { 69 + const result = v.safeParse( 70 + generatedSchemas.vNumberInt64, 71 + BigInt('1000000000001'), 72 + ); 73 + expect(result.success).toBe(false); 74 + }); 75 + 76 + it('should accept NumberUint8 exact const value', () => { 77 + const result = v.safeParse(generatedSchemas.vNumberUint8, 200); 78 + expect(result.success).toBe(true); 79 + }); 80 + 81 + it('should reject NumberUint8 non-matching values', () => { 82 + const result = v.safeParse(generatedSchemas.vNumberUint8, 201); 83 + expect(result.success).toBe(false); 84 + }); 85 + 86 + it('should accept NumberUint16 exact const value', () => { 87 + const result = v.safeParse(generatedSchemas.vNumberUint16, 50000); 88 + expect(result.success).toBe(true); 89 + }); 90 + 91 + it('should reject NumberUint16 non-matching values', () => { 92 + const result = v.safeParse(generatedSchemas.vNumberUint16, 50001); 93 + expect(result.success).toBe(false); 94 + }); 95 + 96 + it('should accept NumberUint32 exact const value', () => { 97 + const result = v.safeParse(generatedSchemas.vNumberUint32, 3000000000); 98 + expect(result.success).toBe(true); 99 + }); 100 + 101 + it('should reject NumberUint32 non-matching values', () => { 102 + const result = v.safeParse(generatedSchemas.vNumberUint32, 3000000001); 103 + expect(result.success).toBe(false); 104 + }); 105 + 106 + it('should accept NumberUint64 exact const value', () => { 107 + const result = v.safeParse( 108 + generatedSchemas.vNumberUint64, 109 + BigInt('18000000000000000000'), 110 + ); 111 + expect(result.success).toBe(true); 112 + }); 113 + 114 + it('should reject NumberUint64 non-matching values', () => { 115 + const result = v.safeParse( 116 + generatedSchemas.vNumberUint64, 117 + BigInt('18000000000000000001'), 118 + ); 119 + expect(result.success).toBe(false); 120 + }); 121 + }); 122 + 123 + describe('Integer Type Const Validation', () => { 124 + it('should accept exact const value', () => { 125 + const result = v.safeParse(generatedSchemas.vIntegerNoFormat, -1); 126 + expect(result.success).toBe(true); 127 + }); 128 + 129 + it('should reject non-matching values', () => { 130 + const result = v.safeParse(generatedSchemas.vIntegerNoFormat, 0); 131 + expect(result.success).toBe(false); 132 + }); 133 + }); 134 + 135 + describe('Integer Type Format Const Validation', () => { 136 + it('should accept IntegerInt8 exact const value', () => { 137 + const result = v.safeParse(generatedSchemas.vIntegerInt8, -100); 138 + expect(result.success).toBe(true); 139 + }); 140 + 141 + it('should reject IntegerInt8 non-matching values', () => { 142 + const result = v.safeParse(generatedSchemas.vIntegerInt8, -99); 143 + expect(result.success).toBe(false); 144 + }); 145 + 146 + it('should accept IntegerInt16 exact const value', () => { 147 + const result = v.safeParse(generatedSchemas.vIntegerInt16, -1000); 148 + expect(result.success).toBe(true); 149 + }); 150 + 151 + it('should reject IntegerInt16 non-matching values', () => { 152 + const result = v.safeParse(generatedSchemas.vIntegerInt16, -999); 153 + expect(result.success).toBe(false); 154 + }); 155 + 156 + it('should accept IntegerInt32 exact const value', () => { 157 + const result = v.safeParse(generatedSchemas.vIntegerInt32, -100000); 158 + expect(result.success).toBe(true); 159 + }); 160 + 161 + it('should reject IntegerInt32 non-matching values', () => { 162 + const result = v.safeParse(generatedSchemas.vIntegerInt32, -99999); 163 + expect(result.success).toBe(false); 164 + }); 165 + 166 + it('should accept IntegerInt64 exact const value', () => { 167 + const result = v.safeParse( 168 + generatedSchemas.vIntegerInt64, 169 + BigInt('-1000000000000'), 170 + ); 171 + expect(result.success).toBe(true); 172 + }); 173 + 174 + it('should reject IntegerInt64 non-matching values', () => { 175 + const result = v.safeParse( 176 + generatedSchemas.vIntegerInt64, 177 + BigInt('-999999999999'), 178 + ); 179 + expect(result.success).toBe(false); 180 + }); 181 + 182 + it('should accept IntegerUint8 exact const value', () => { 183 + const result = v.safeParse(generatedSchemas.vIntegerUint8, 255); 184 + expect(result.success).toBe(true); 185 + }); 186 + 187 + it('should reject IntegerUint8 non-matching values', () => { 188 + const result = v.safeParse(generatedSchemas.vIntegerUint8, 254); 189 + expect(result.success).toBe(false); 190 + }); 191 + 192 + it('should accept IntegerUint16 exact const value', () => { 193 + const result = v.safeParse(generatedSchemas.vIntegerUint16, 65535); 194 + expect(result.success).toBe(true); 195 + }); 196 + 197 + it('should reject IntegerUint16 non-matching values', () => { 198 + const result = v.safeParse(generatedSchemas.vIntegerUint16, 65534); 199 + expect(result.success).toBe(false); 200 + }); 201 + 202 + it('should accept IntegerUint32 exact const value', () => { 203 + const result = v.safeParse(generatedSchemas.vIntegerUint32, 4294967295); 204 + expect(result.success).toBe(true); 205 + }); 206 + 207 + it('should reject IntegerUint32 non-matching values', () => { 208 + const result = v.safeParse(generatedSchemas.vIntegerUint32, 4294967294); 209 + expect(result.success).toBe(false); 210 + }); 211 + 212 + it('should accept IntegerUint64 exact const value', () => { 213 + const result = v.safeParse( 214 + generatedSchemas.vIntegerUint64, 215 + BigInt('1000000000000'), 216 + ); 217 + expect(result.success).toBe(true); 218 + }); 219 + 220 + it('should reject IntegerUint64 non-matching values', () => { 221 + const result = v.safeParse( 222 + generatedSchemas.vIntegerUint64, 223 + BigInt('1000000000001'), 224 + ); 225 + expect(result.success).toBe(false); 226 + }); 227 + }); 228 + 229 + describe('String Type Format Const Validation', () => { 230 + it('should accept StringInt64 exact const value', () => { 231 + const result = v.safeParse( 232 + generatedSchemas.vStringInt64, 233 + BigInt('-9223372036854775808'), 234 + ); 235 + expect(result.success).toBe(true); 236 + }); 237 + 238 + it('should reject StringInt64 non-matching values', () => { 239 + const result = v.safeParse( 240 + generatedSchemas.vStringInt64, 241 + BigInt('-9223372036854775807'), 242 + ); 243 + expect(result.success).toBe(false); 244 + }); 245 + 246 + it('should accept StringUint64 exact const value', () => { 247 + const result = v.safeParse( 248 + generatedSchemas.vStringUint64, 249 + BigInt('18446744073709551615'), 250 + ); 251 + expect(result.success).toBe(true); 252 + }); 253 + 254 + it('should reject StringUint64 non-matching values', () => { 255 + const result = v.safeParse( 256 + generatedSchemas.vStringUint64, 257 + BigInt('18446744073709551614'), 258 + ); 259 + expect(result.success).toBe(false); 260 + }); 261 + }); 262 + 263 + describe('String Type Format Const Validation (BigInt Literal)', () => { 264 + it('should accept StringInt64n exact const value', () => { 265 + const result = v.safeParse( 266 + generatedSchemas.vStringInt64n, 267 + BigInt('-9223372036854775808'), 268 + ); 269 + expect(result.success).toBe(true); 270 + }); 271 + 272 + it('should reject StringInt64n non-matching values', () => { 273 + const result = v.safeParse( 274 + generatedSchemas.vStringInt64n, 275 + BigInt('-9223372036854775807'), 276 + ); 277 + expect(result.success).toBe(false); 278 + }); 279 + 280 + it('should accept StringUint64n exact const value', () => { 281 + const result = v.safeParse( 282 + generatedSchemas.vStringUint64n, 283 + BigInt('18446744073709551615'), 284 + ); 285 + expect(result.success).toBe(true); 286 + }); 287 + 288 + it('should reject StringUint64n non-matching values', () => { 289 + const result = v.safeParse( 290 + generatedSchemas.vStringUint64n, 291 + BigInt('18446744073709551614'), 292 + ); 293 + expect(result.success).toBe(false); 294 + }); 295 + }); 296 + });
+551
packages/openapi-ts-tests/main/test/formats.test.ts
··· 1 + import * as v from 'valibot'; 2 + import { beforeAll, describe, expect, it } from 'vitest'; 3 + 4 + import { setupValibotTest } from './test-helper'; 5 + 6 + // TODO: further clean up 7 + describe('Number Type Formats Tests', () => { 8 + let generatedSchemas: any; 9 + 10 + beforeAll(async () => { 11 + generatedSchemas = await setupValibotTest('formats.yaml', 'formats'); 12 + }); 13 + 14 + // Format bounds and error messages from INTEGER_FORMATS 15 + const FORMAT_BOUNDS = { 16 + int16: { 17 + max: 32767, 18 + maxError: 'Invalid value: Expected int16 to be <= 32767', 19 + min: -32768, 20 + minError: 'Invalid value: Expected int16 to be >= -32768', 21 + }, 22 + int32: { 23 + max: 2147483647, 24 + maxError: 'Invalid value: Expected int32 to be <= 2147483647', 25 + min: -2147483648, 26 + minError: 'Invalid value: Expected int32 to be >= -2147483648', 27 + }, 28 + int64: { 29 + max: '9223372036854775807', 30 + maxError: 'Invalid value: Expected int64 to be <= 9223372036854775807', 31 + min: '-9223372036854775808', 32 + minError: 'Invalid value: Expected int64 to be >= -9223372036854775808', 33 + }, 34 + int8: { 35 + max: 127, 36 + maxError: 'Invalid value: Expected int8 to be <= 127', 37 + min: -128, 38 + minError: 'Invalid value: Expected int8 to be >= -128', 39 + }, 40 + uint16: { 41 + max: 65535, 42 + maxError: 'Invalid value: Expected uint16 to be <= 65535', 43 + min: 0, 44 + minError: 'Invalid value: Expected uint16 to be >= 0', 45 + }, 46 + uint32: { 47 + max: 4294967295, 48 + maxError: 'Invalid value: Expected uint32 to be <= 4294967295', 49 + min: 0, 50 + minError: 'Invalid value: Expected uint32 to be >= 0', 51 + }, 52 + uint64: { 53 + max: '18446744073709551615', 54 + maxError: 'Invalid value: Expected uint64 to be <= 18446744073709551615', 55 + min: '0', 56 + minError: 'Invalid value: Expected uint64 to be >= 0', 57 + }, 58 + uint8: { 59 + max: 255, 60 + maxError: 'Invalid value: Expected uint8 to be <= 255', 61 + min: 0, 62 + minError: 'Invalid value: Expected uint8 to be >= 0', 63 + }, 64 + }; 65 + 66 + describe('Number Type Format Validation', () => { 67 + describe('numberNoFormat', () => { 68 + it('should validate any number value', () => { 69 + const result = v.safeParse(generatedSchemas.vNumberNoFormat, 123.456); 70 + expect(result.success).toBe(true); 71 + }); 72 + }); 73 + 74 + describe('numberInt8', () => { 75 + it('should validate values within int8 range', () => { 76 + const result = v.safeParse(generatedSchemas.vNumberInt8, 100); 77 + expect(result.success).toBe(true); 78 + }); 79 + 80 + it('should reject values below int8 minimum', () => { 81 + const result = v.safeParse(generatedSchemas.vNumberInt8, -129); 82 + expect(result.success).toBe(false); 83 + expect(result.issues![0].message).toContain( 84 + FORMAT_BOUNDS.int8.minError, 85 + ); 86 + }); 87 + 88 + it('should reject values above int8 maximum', () => { 89 + const result = v.safeParse(generatedSchemas.vNumberInt8, 128); 90 + expect(result.success).toBe(false); 91 + expect(result.issues![0].message).toContain( 92 + FORMAT_BOUNDS.int8.maxError, 93 + ); 94 + }); 95 + }); 96 + 97 + describe('numberInt16', () => { 98 + it('should validate values within int16 range', () => { 99 + const result = v.safeParse(generatedSchemas.vNumberInt16, 30000); 100 + expect(result.success).toBe(true); 101 + }); 102 + 103 + it('should reject values below int16 minimum', () => { 104 + const result = v.safeParse(generatedSchemas.vNumberInt16, -32769); 105 + expect(result.success).toBe(false); 106 + expect(result.issues![0].message).toContain( 107 + FORMAT_BOUNDS.int16.minError, 108 + ); 109 + }); 110 + 111 + it('should reject values above int16 maximum', () => { 112 + const result = v.safeParse(generatedSchemas.vNumberInt16, 32768); 113 + expect(result.success).toBe(false); 114 + expect(result.issues![0].message).toContain( 115 + FORMAT_BOUNDS.int16.maxError, 116 + ); 117 + }); 118 + }); 119 + 120 + describe('numberInt32', () => { 121 + it('should validate values within int32 range', () => { 122 + const result = v.safeParse(generatedSchemas.vNumberInt32, 2000000000); 123 + expect(result.success).toBe(true); 124 + }); 125 + 126 + it('should reject values below int32 minimum', () => { 127 + const result = v.safeParse(generatedSchemas.vNumberInt32, -2147483649); 128 + expect(result.success).toBe(false); 129 + expect(result.issues![0].message).toContain( 130 + FORMAT_BOUNDS.int32.minError, 131 + ); 132 + }); 133 + 134 + it('should reject values above int32 maximum', () => { 135 + const result = v.safeParse(generatedSchemas.vNumberInt32, 2147483648); 136 + expect(result.success).toBe(false); 137 + expect(result.issues![0].message).toContain( 138 + FORMAT_BOUNDS.int32.maxError, 139 + ); 140 + }); 141 + }); 142 + 143 + describe('numberInt64', () => { 144 + it('should validate values within int64 range and convert to BigInt', () => { 145 + const result = v.safeParse( 146 + generatedSchemas.vNumberInt64, 147 + 1000000000000, 148 + ); 149 + expect(result.success).toBe(true); 150 + expect(typeof result.output).toBe('bigint'); 151 + }); 152 + 153 + it('should validate string values within int64 range', () => { 154 + const result = v.safeParse( 155 + generatedSchemas.vNumberInt64, 156 + '1000000000000', 157 + ); 158 + expect(result.success).toBe(true); 159 + expect(typeof result.output).toBe('bigint'); 160 + }); 161 + 162 + it('should reject values above int64 maximum', () => { 163 + const result = v.safeParse( 164 + generatedSchemas.vNumberInt64, 165 + '9223372036854775808', 166 + ); 167 + expect(result.success).toBe(false); 168 + expect(result.issues![0].message).toContain( 169 + FORMAT_BOUNDS.int64.maxError, 170 + ); 171 + }); 172 + }); 173 + 174 + describe('numberUint8', () => { 175 + it('should validate values within uint8 range', () => { 176 + const result = v.safeParse(generatedSchemas.vNumberUint8, 200); 177 + expect(result.success).toBe(true); 178 + }); 179 + 180 + it('should reject negative values', () => { 181 + const result = v.safeParse(generatedSchemas.vNumberUint8, -1); 182 + expect(result.success).toBe(false); 183 + expect(result.issues![0].message).toContain( 184 + FORMAT_BOUNDS.uint8.minError, 185 + ); 186 + }); 187 + 188 + it('should reject values above uint8 maximum', () => { 189 + const result = v.safeParse(generatedSchemas.vNumberUint8, 256); 190 + expect(result.success).toBe(false); 191 + expect(result.issues![0].message).toContain( 192 + FORMAT_BOUNDS.uint8.maxError, 193 + ); 194 + }); 195 + }); 196 + 197 + describe('numberUint16', () => { 198 + it('should validate values within uint16 range', () => { 199 + const result = v.safeParse(generatedSchemas.vNumberUint16, 60000); 200 + expect(result.success).toBe(true); 201 + }); 202 + 203 + it('should reject negative values', () => { 204 + const result = v.safeParse(generatedSchemas.vNumberUint16, -1); 205 + expect(result.success).toBe(false); 206 + expect(result.issues![0].message).toContain( 207 + FORMAT_BOUNDS.uint16.minError, 208 + ); 209 + }); 210 + 211 + it('should reject values above uint16 maximum', () => { 212 + const result = v.safeParse(generatedSchemas.vNumberUint16, 65536); 213 + expect(result.success).toBe(false); 214 + expect(result.issues![0].message).toContain( 215 + FORMAT_BOUNDS.uint16.maxError, 216 + ); 217 + }); 218 + }); 219 + 220 + describe('numberUint32', () => { 221 + it('should validate values within uint32 range', () => { 222 + const result = v.safeParse(generatedSchemas.vNumberUint32, 4000000000); 223 + expect(result.success).toBe(true); 224 + }); 225 + 226 + it('should reject negative values', () => { 227 + const result = v.safeParse(generatedSchemas.vNumberUint32, -1); 228 + expect(result.success).toBe(false); 229 + expect(result.issues![0].message).toContain( 230 + FORMAT_BOUNDS.uint32.minError, 231 + ); 232 + }); 233 + 234 + it('should reject values above uint32 maximum', () => { 235 + const result = v.safeParse(generatedSchemas.vNumberUint32, 4294967296); 236 + expect(result.success).toBe(false); 237 + expect(result.issues![0].message).toContain( 238 + FORMAT_BOUNDS.uint32.maxError, 239 + ); 240 + }); 241 + }); 242 + 243 + describe('numberUint64', () => { 244 + it('should validate values within uint64 range and convert to BigInt', () => { 245 + const result = v.safeParse( 246 + generatedSchemas.vNumberUint64, 247 + 1000000000000, 248 + ); 249 + expect(result.success).toBe(true); 250 + expect(typeof result.output).toBe('bigint'); 251 + }); 252 + 253 + it('should reject negative values', () => { 254 + const result = v.safeParse(generatedSchemas.vNumberUint64, -1); 255 + expect(result.success).toBe(false); 256 + expect(result.issues![0].message).toContain( 257 + FORMAT_BOUNDS.uint64.minError, 258 + ); 259 + }); 260 + 261 + it('should reject values above uint64 maximum', () => { 262 + const result = v.safeParse( 263 + generatedSchemas.vNumberUint64, 264 + '18446744073709551616', 265 + ); 266 + expect(result.success).toBe(false); 267 + expect(result.issues![0].message).toContain( 268 + FORMAT_BOUNDS.uint64.maxError, 269 + ); 270 + }); 271 + }); 272 + }); 273 + 274 + describe('Integer Type Format Validation', () => { 275 + describe('integerNoFormat', () => { 276 + it('should validate any integer value', () => { 277 + const result = v.safeParse(generatedSchemas.vIntegerNoFormat, 123); 278 + expect(result.success).toBe(true); 279 + }); 280 + 281 + it('should reject non-integer values', () => { 282 + const result = v.safeParse(generatedSchemas.vIntegerNoFormat, 123.456); 283 + expect(result.success).toBe(false); 284 + }); 285 + }); 286 + 287 + describe('integerInt8', () => { 288 + it('should validate values within int8 range', () => { 289 + const result = v.safeParse(generatedSchemas.vIntegerInt8, 100); 290 + expect(result.success).toBe(true); 291 + }); 292 + 293 + it('should reject values below int8 minimum', () => { 294 + const result = v.safeParse(generatedSchemas.vIntegerInt8, -129); 295 + expect(result.success).toBe(false); 296 + expect(result.issues![0].message).toContain( 297 + FORMAT_BOUNDS.int8.minError, 298 + ); 299 + }); 300 + 301 + it('should reject values above int8 maximum', () => { 302 + const result = v.safeParse(generatedSchemas.vIntegerInt8, 128); 303 + expect(result.success).toBe(false); 304 + expect(result.issues![0].message).toContain( 305 + FORMAT_BOUNDS.int8.maxError, 306 + ); 307 + }); 308 + }); 309 + 310 + describe('integerInt16', () => { 311 + it('should validate values within int16 range', () => { 312 + const result = v.safeParse(generatedSchemas.vIntegerInt16, 30000); 313 + expect(result.success).toBe(true); 314 + }); 315 + 316 + it('should reject values below int16 minimum', () => { 317 + const result = v.safeParse(generatedSchemas.vIntegerInt16, -32769); 318 + expect(result.success).toBe(false); 319 + expect(result.issues![0].message).toContain( 320 + FORMAT_BOUNDS.int16.minError, 321 + ); 322 + }); 323 + 324 + it('should reject values above int16 maximum', () => { 325 + const result = v.safeParse(generatedSchemas.vIntegerInt16, 32768); 326 + expect(result.success).toBe(false); 327 + expect(result.issues![0].message).toContain( 328 + FORMAT_BOUNDS.int16.maxError, 329 + ); 330 + }); 331 + }); 332 + 333 + describe('integerInt32', () => { 334 + it('should validate values within int32 range', () => { 335 + const result = v.safeParse(generatedSchemas.vIntegerInt32, 2000000000); 336 + expect(result.success).toBe(true); 337 + }); 338 + 339 + it('should reject values below int32 minimum', () => { 340 + const result = v.safeParse(generatedSchemas.vIntegerInt32, -2147483649); 341 + expect(result.success).toBe(false); 342 + expect(result.issues![0].message).toContain( 343 + FORMAT_BOUNDS.int32.minError, 344 + ); 345 + }); 346 + 347 + it('should reject values above int32 maximum', () => { 348 + const result = v.safeParse(generatedSchemas.vIntegerInt32, 2147483648); 349 + expect(result.success).toBe(false); 350 + expect(result.issues![0].message).toContain( 351 + FORMAT_BOUNDS.int32.maxError, 352 + ); 353 + }); 354 + }); 355 + 356 + describe('integerInt64', () => { 357 + it('should validate values within int64 range and convert to BigInt', () => { 358 + const result = v.safeParse( 359 + generatedSchemas.vIntegerInt64, 360 + 1000000000000, 361 + ); 362 + expect(result.success).toBe(true); 363 + expect(typeof result.output).toBe('bigint'); 364 + }); 365 + 366 + it('should validate string values within int64 range', () => { 367 + const result = v.safeParse( 368 + generatedSchemas.vIntegerInt64, 369 + '1000000000000', 370 + ); 371 + expect(result.success).toBe(true); 372 + expect(typeof result.output).toBe('bigint'); 373 + }); 374 + 375 + it('should reject values above int64 maximum', () => { 376 + const result = v.safeParse( 377 + generatedSchemas.vIntegerInt64, 378 + '9223372036854775808', 379 + ); 380 + expect(result.success).toBe(false); 381 + expect(result.issues![0].message).toContain( 382 + FORMAT_BOUNDS.int64.maxError, 383 + ); 384 + }); 385 + }); 386 + 387 + describe('integerUint8', () => { 388 + it('should validate values within uint8 range', () => { 389 + const result = v.safeParse(generatedSchemas.vIntegerUint8, 200); 390 + expect(result.success).toBe(true); 391 + }); 392 + 393 + it('should reject negative values', () => { 394 + const result = v.safeParse(generatedSchemas.vIntegerUint8, -1); 395 + expect(result.success).toBe(false); 396 + expect(result.issues![0].message).toContain( 397 + FORMAT_BOUNDS.uint8.minError, 398 + ); 399 + }); 400 + 401 + it('should reject values above uint8 maximum', () => { 402 + const result = v.safeParse(generatedSchemas.vIntegerUint8, 256); 403 + expect(result.success).toBe(false); 404 + expect(result.issues![0].message).toContain( 405 + FORMAT_BOUNDS.uint8.maxError, 406 + ); 407 + }); 408 + }); 409 + 410 + describe('integerUint16', () => { 411 + it('should validate values within uint16 range', () => { 412 + const result = v.safeParse(generatedSchemas.vIntegerUint16, 60000); 413 + expect(result.success).toBe(true); 414 + }); 415 + 416 + it('should reject negative values', () => { 417 + const result = v.safeParse(generatedSchemas.vIntegerUint16, -1); 418 + expect(result.success).toBe(false); 419 + expect(result.issues![0].message).toContain( 420 + FORMAT_BOUNDS.uint16.minError, 421 + ); 422 + }); 423 + 424 + it('should reject values above uint16 maximum', () => { 425 + const result = v.safeParse(generatedSchemas.vIntegerUint16, 65536); 426 + expect(result.success).toBe(false); 427 + expect(result.issues![0].message).toContain( 428 + FORMAT_BOUNDS.uint16.maxError, 429 + ); 430 + }); 431 + }); 432 + 433 + describe('integerUint32', () => { 434 + it('should validate values within uint32 range', () => { 435 + const result = v.safeParse(generatedSchemas.vIntegerUint32, 4000000000); 436 + expect(result.success).toBe(true); 437 + }); 438 + 439 + it('should reject negative values', () => { 440 + const result = v.safeParse(generatedSchemas.vIntegerUint32, -1); 441 + expect(result.success).toBe(false); 442 + expect(result.issues![0].message).toContain( 443 + FORMAT_BOUNDS.uint32.minError, 444 + ); 445 + }); 446 + 447 + it('should reject values above uint32 maximum', () => { 448 + const result = v.safeParse(generatedSchemas.vIntegerUint32, 4294967296); 449 + expect(result.success).toBe(false); 450 + expect(result.issues![0].message).toContain( 451 + FORMAT_BOUNDS.uint32.maxError, 452 + ); 453 + }); 454 + }); 455 + 456 + describe('integerUint64', () => { 457 + it('should validate values within uint64 range and convert to BigInt', () => { 458 + const result = v.safeParse( 459 + generatedSchemas.vIntegerUint64, 460 + 1000000000000, 461 + ); 462 + expect(result.success).toBe(true); 463 + expect(typeof result.output).toBe('bigint'); 464 + }); 465 + 466 + it('should reject negative values', () => { 467 + const result = v.safeParse(generatedSchemas.vIntegerUint64, -1); 468 + expect(result.success).toBe(false); 469 + expect(result.issues![0].message).toContain( 470 + FORMAT_BOUNDS.uint64.minError, 471 + ); 472 + }); 473 + 474 + it('should reject values above uint64 maximum', () => { 475 + const result = v.safeParse( 476 + generatedSchemas.vIntegerUint64, 477 + '18446744073709551616', 478 + ); 479 + expect(result.success).toBe(false); 480 + expect(result.issues![0].message).toContain( 481 + FORMAT_BOUNDS.uint64.maxError, 482 + ); 483 + }); 484 + }); 485 + }); 486 + 487 + describe('String Type Format Validation', () => { 488 + describe('stringInt64', () => { 489 + it('should validate string values within int64 range and convert to BigInt', () => { 490 + const result = v.safeParse( 491 + generatedSchemas.vStringInt64, 492 + '1000000000000', 493 + ); 494 + expect(result.success).toBe(true); 495 + expect(typeof result.output).toBe('bigint'); 496 + }); 497 + 498 + it('should reject values below int64 minimum', () => { 499 + const result = v.safeParse( 500 + generatedSchemas.vStringInt64, 501 + '-9223372036854775809', 502 + ); 503 + expect(result.success).toBe(false); 504 + expect(result.issues![0].message).toContain( 505 + FORMAT_BOUNDS.int64.minError, 506 + ); 507 + }); 508 + 509 + it('should reject values above int64 maximum', () => { 510 + const result = v.safeParse( 511 + generatedSchemas.vStringInt64, 512 + '9223372036854775808', 513 + ); 514 + expect(result.success).toBe(false); 515 + expect(result.issues![0].message).toContain( 516 + FORMAT_BOUNDS.int64.maxError, 517 + ); 518 + }); 519 + }); 520 + 521 + describe('stringUint64', () => { 522 + it('should validate string values within uint64 range and convert to BigInt', () => { 523 + const result = v.safeParse( 524 + generatedSchemas.vStringUint64, 525 + '1000000000000', 526 + ); 527 + expect(result.success).toBe(true); 528 + expect(typeof result.output).toBe('bigint'); 529 + }); 530 + 531 + it('should reject negative values', () => { 532 + const result = v.safeParse(generatedSchemas.vStringUint64, '-1'); 533 + expect(result.success).toBe(false); 534 + expect(result.issues![0].message).toContain( 535 + FORMAT_BOUNDS.uint64.minError, 536 + ); 537 + }); 538 + 539 + it('should reject values above uint64 maximum', () => { 540 + const result = v.safeParse( 541 + generatedSchemas.vStringUint64, 542 + '18446744073709551616', 543 + ); 544 + expect(result.success).toBe(false); 545 + expect(result.issues![0].message).toContain( 546 + FORMAT_BOUNDS.uint64.maxError, 547 + ); 548 + }); 549 + }); 550 + }); 551 + });
+127
packages/openapi-ts-tests/main/test/meta-function.test.ts
··· 1 + import fs from 'node:fs'; 2 + import path from 'node:path'; 3 + import { fileURLToPath } from 'node:url'; 4 + 5 + import { createClient, type UserConfig } from '@hey-api/openapi-ts'; 6 + import { describe, expect, it } from 'vitest'; 7 + 8 + import { getFilePaths, getSpecsPath } from '../../utils'; 9 + 10 + const __filename = fileURLToPath(import.meta.url); 11 + const __dirname = path.dirname(__filename); 12 + 13 + const version = '3.1.x'; 14 + const namespace = 'plugins'; 15 + const outputDir = path.join(__dirname, 'generated', version, namespace); 16 + 17 + // TODO: further clean up 18 + describe('TanStack Query Meta Function Customization', () => { 19 + const createConfig = ( 20 + userConfig: Omit<UserConfig, 'input'> & Pick<Partial<UserConfig>, 'input'>, 21 + ): UserConfig => ({ 22 + input: path.join(getSpecsPath(), version, 'security-api-key.json'), 23 + logs: { 24 + level: 'silent', 25 + }, 26 + ...userConfig, 27 + }); 28 + 29 + // Framework configurations 30 + const frameworks = [ 31 + { 32 + description: 'React Query', 33 + name: '@tanstack/react-query', 34 + output: 'react-query', 35 + }, 36 + { 37 + description: 'Vue Query', 38 + name: '@tanstack/vue-query', 39 + output: 'vue-query', 40 + }, 41 + { 42 + description: 'Svelte Query', 43 + name: '@tanstack/svelte-query', 44 + output: 'svelte-query', 45 + }, 46 + { 47 + description: 'Solid Query', 48 + name: '@tanstack/solid-query', 49 + output: 'solid-query', 50 + }, 51 + { 52 + description: 'Angular Query', 53 + name: '@tanstack/angular-query-experimental', 54 + output: 'angular-query-experimental', 55 + }, 56 + ] as const; 57 + 58 + // Generate scenarios for each framework 59 + const scenarios = frameworks.map((framework) => ({ 60 + config: createConfig({ 61 + output: path.join( 62 + outputDir, 63 + '@tanstack', 64 + framework.output, 65 + 'meta-function', 66 + ), 67 + plugins: [ 68 + { 69 + infiniteQueryOptions: { 70 + meta: (operation) => ({ 71 + id: operation.id, 72 + method: operation.method, 73 + path: operation.path, 74 + }), 75 + }, 76 + mutationOptions: { 77 + meta: (operation) => ({ 78 + id: operation.id, 79 + method: operation.method, 80 + path: operation.path, 81 + }), 82 + }, 83 + name: framework.name, 84 + queryOptions: { 85 + meta: (operation) => ({ 86 + id: operation.id, 87 + method: operation.method, 88 + path: operation.path, 89 + }), 90 + }, 91 + }, 92 + '@hey-api/client-fetch', 93 + ], 94 + }), 95 + description: `generates ${framework.description} options with custom meta function`, 96 + })); 97 + 98 + it.each(scenarios)('$description', async ({ config }) => { 99 + await createClient(config); 100 + 101 + const outputPath = config.output as string; 102 + const filePaths = getFilePaths(outputPath); 103 + 104 + // Create snapshots for all generated files 105 + await Promise.all( 106 + filePaths.map(async (filePath) => { 107 + const fileContent = fs.readFileSync(filePath, 'utf-8'); 108 + const relativePath = filePath.slice(outputPath.length + 1); 109 + const fileName = path.basename(relativePath); 110 + const frameworkDir = path.dirname(relativePath).split(path.sep).pop()!; 111 + await expect(fileContent).toMatchFileSnapshot( 112 + path.join( 113 + __dirname, 114 + '..', 115 + '..', 116 + '__snapshots__', 117 + 'plugins', 118 + '@tanstack', 119 + 'meta', 120 + frameworkDir, 121 + fileName, 122 + ), 123 + ); 124 + }), 125 + ); 126 + }); 127 + });
+913
packages/openapi-ts-tests/main/test/min-max-constraints.test.ts
··· 1 + import * as v from 'valibot'; 2 + import { beforeAll, describe, expect, it } from 'vitest'; 3 + 4 + import { setupValibotTest } from './test-helper'; 5 + 6 + // TODO: further clean up 7 + describe('Number Type Min/Max Constraints Tests', () => { 8 + let generatedSchemas: any; 9 + 10 + beforeAll(async () => { 11 + generatedSchemas = await setupValibotTest( 12 + 'min-max-constraints.yaml', 13 + 'min-max-constraints', 14 + ); 15 + }); 16 + 17 + describe('Basic Number Constraints', () => { 18 + describe('NumberWithMinimum', () => { 19 + it('should accept values at minimum boundary', () => { 20 + const result = v.safeParse(generatedSchemas.vNumberWithMinimum, 10); 21 + expect(result.success).toBe(true); 22 + }); 23 + 24 + it('should accept values above minimum', () => { 25 + const result = v.safeParse(generatedSchemas.vNumberWithMinimum, 15); 26 + expect(result.success).toBe(true); 27 + }); 28 + 29 + it('should reject values below minimum', () => { 30 + const result = v.safeParse(generatedSchemas.vNumberWithMinimum, 9); 31 + expect(result.success).toBe(false); 32 + }); 33 + }); 34 + 35 + describe('NumberWithMaximum', () => { 36 + it('should accept values at maximum boundary', () => { 37 + const result = v.safeParse(generatedSchemas.vNumberWithMaximum, 100); 38 + expect(result.success).toBe(true); 39 + }); 40 + 41 + it('should accept values below maximum', () => { 42 + const result = v.safeParse(generatedSchemas.vNumberWithMaximum, 50); 43 + expect(result.success).toBe(true); 44 + }); 45 + 46 + it('should reject values above maximum', () => { 47 + const result = v.safeParse(generatedSchemas.vNumberWithMaximum, 101); 48 + expect(result.success).toBe(false); 49 + }); 50 + }); 51 + 52 + describe('NumberWithMinMax', () => { 53 + it('should accept values within range', () => { 54 + const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 50); 55 + expect(result.success).toBe(true); 56 + }); 57 + 58 + it('should accept values at minimum boundary', () => { 59 + const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 0); 60 + expect(result.success).toBe(true); 61 + }); 62 + 63 + it('should accept values at maximum boundary', () => { 64 + const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 100); 65 + expect(result.success).toBe(true); 66 + }); 67 + 68 + it('should reject values below minimum', () => { 69 + const result = v.safeParse(generatedSchemas.vNumberWithMinMax, -1); 70 + expect(result.success).toBe(false); 71 + }); 72 + 73 + it('should reject values above maximum', () => { 74 + const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 101); 75 + expect(result.success).toBe(false); 76 + }); 77 + }); 78 + }); 79 + 80 + describe('Basic Integer Constraints', () => { 81 + describe('IntegerWithMinimum', () => { 82 + it('should accept values at minimum boundary', () => { 83 + const result = v.safeParse(generatedSchemas.vIntegerWithMinimum, 5); 84 + expect(result.success).toBe(true); 85 + }); 86 + 87 + it('should accept values above minimum', () => { 88 + const result = v.safeParse(generatedSchemas.vIntegerWithMinimum, 10); 89 + expect(result.success).toBe(true); 90 + }); 91 + 92 + it('should reject values below minimum', () => { 93 + const result = v.safeParse(generatedSchemas.vIntegerWithMinimum, 4); 94 + expect(result.success).toBe(false); 95 + }); 96 + }); 97 + 98 + describe('IntegerWithMaximum', () => { 99 + it('should accept values at maximum boundary', () => { 100 + const result = v.safeParse(generatedSchemas.vIntegerWithMaximum, 999); 101 + expect(result.success).toBe(true); 102 + }); 103 + 104 + it('should accept values below maximum', () => { 105 + const result = v.safeParse(generatedSchemas.vIntegerWithMaximum, 500); 106 + expect(result.success).toBe(true); 107 + }); 108 + 109 + it('should reject values above maximum', () => { 110 + const result = v.safeParse(generatedSchemas.vIntegerWithMaximum, 1000); 111 + expect(result.success).toBe(false); 112 + }); 113 + }); 114 + 115 + describe('IntegerWithMinMax', () => { 116 + it('should accept values within range', () => { 117 + const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 500); 118 + expect(result.success).toBe(true); 119 + }); 120 + 121 + it('should accept values at minimum boundary', () => { 122 + const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 1); 123 + expect(result.success).toBe(true); 124 + }); 125 + 126 + it('should accept values at maximum boundary', () => { 127 + const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 999); 128 + expect(result.success).toBe(true); 129 + }); 130 + 131 + it('should reject values below minimum', () => { 132 + const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 0); 133 + expect(result.success).toBe(false); 134 + }); 135 + 136 + it('should reject values above maximum', () => { 137 + const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 1000); 138 + expect(result.success).toBe(false); 139 + }); 140 + }); 141 + }); 142 + 143 + describe('Exclusive Constraints', () => { 144 + describe('NumberWithExclusiveMin', () => { 145 + it('should accept values above exclusive minimum', () => { 146 + const result = v.safeParse( 147 + generatedSchemas.vNumberWithExclusiveMin, 148 + 0.1, 149 + ); 150 + expect(result.success).toBe(true); 151 + }); 152 + 153 + it('should reject values at exclusive minimum', () => { 154 + const result = v.safeParse(generatedSchemas.vNumberWithExclusiveMin, 0); 155 + expect(result.success).toBe(false); 156 + }); 157 + 158 + it('should reject values below exclusive minimum', () => { 159 + const result = v.safeParse( 160 + generatedSchemas.vNumberWithExclusiveMin, 161 + -1, 162 + ); 163 + expect(result.success).toBe(false); 164 + }); 165 + }); 166 + 167 + describe('NumberWithExclusiveMax', () => { 168 + it('should accept values below exclusive maximum', () => { 169 + const result = v.safeParse( 170 + generatedSchemas.vNumberWithExclusiveMax, 171 + 99.9, 172 + ); 173 + expect(result.success).toBe(true); 174 + }); 175 + 176 + it('should reject values at exclusive maximum', () => { 177 + const result = v.safeParse( 178 + generatedSchemas.vNumberWithExclusiveMax, 179 + 100, 180 + ); 181 + expect(result.success).toBe(false); 182 + }); 183 + 184 + it('should reject values above exclusive maximum', () => { 185 + const result = v.safeParse( 186 + generatedSchemas.vNumberWithExclusiveMax, 187 + 101, 188 + ); 189 + expect(result.success).toBe(false); 190 + }); 191 + }); 192 + 193 + describe('NumberWithExclusiveMinMax', () => { 194 + it('should accept values within exclusive range', () => { 195 + const result = v.safeParse( 196 + generatedSchemas.vNumberWithExclusiveMinMax, 197 + 0.5, 198 + ); 199 + expect(result.success).toBe(true); 200 + }); 201 + 202 + it('should reject values at exclusive minimum', () => { 203 + const result = v.safeParse( 204 + generatedSchemas.vNumberWithExclusiveMinMax, 205 + 0, 206 + ); 207 + expect(result.success).toBe(false); 208 + }); 209 + 210 + it('should reject values at exclusive maximum', () => { 211 + const result = v.safeParse( 212 + generatedSchemas.vNumberWithExclusiveMinMax, 213 + 1, 214 + ); 215 + expect(result.success).toBe(false); 216 + }); 217 + }); 218 + 219 + describe('IntegerWithExclusiveMin', () => { 220 + it('should accept values above exclusive minimum', () => { 221 + const result = v.safeParse( 222 + generatedSchemas.vIntegerWithExclusiveMin, 223 + 11, 224 + ); 225 + expect(result.success).toBe(true); 226 + }); 227 + 228 + it('should reject values at exclusive minimum', () => { 229 + const result = v.safeParse( 230 + generatedSchemas.vIntegerWithExclusiveMin, 231 + 10, 232 + ); 233 + expect(result.success).toBe(false); 234 + }); 235 + 236 + it('should reject values below exclusive minimum', () => { 237 + const result = v.safeParse( 238 + generatedSchemas.vIntegerWithExclusiveMin, 239 + 9, 240 + ); 241 + expect(result.success).toBe(false); 242 + }); 243 + }); 244 + 245 + describe('IntegerWithExclusiveMax', () => { 246 + it('should accept values below exclusive maximum', () => { 247 + const result = v.safeParse( 248 + generatedSchemas.vIntegerWithExclusiveMax, 249 + 49, 250 + ); 251 + expect(result.success).toBe(true); 252 + }); 253 + 254 + it('should reject values at exclusive maximum', () => { 255 + const result = v.safeParse( 256 + generatedSchemas.vIntegerWithExclusiveMax, 257 + 50, 258 + ); 259 + expect(result.success).toBe(false); 260 + }); 261 + 262 + it('should reject values above exclusive maximum', () => { 263 + const result = v.safeParse( 264 + generatedSchemas.vIntegerWithExclusiveMax, 265 + 51, 266 + ); 267 + expect(result.success).toBe(false); 268 + }); 269 + }); 270 + 271 + describe('IntegerWithExclusiveMinMax', () => { 272 + it('should accept values within exclusive range', () => { 273 + const result = v.safeParse( 274 + generatedSchemas.vIntegerWithExclusiveMinMax, 275 + 10, 276 + ); 277 + expect(result.success).toBe(true); 278 + }); 279 + 280 + it('should reject values at exclusive minimum', () => { 281 + const result = v.safeParse( 282 + generatedSchemas.vIntegerWithExclusiveMinMax, 283 + 5, 284 + ); 285 + expect(result.success).toBe(false); 286 + }); 287 + 288 + it('should reject values at exclusive maximum', () => { 289 + const result = v.safeParse( 290 + generatedSchemas.vIntegerWithExclusiveMinMax, 291 + 15, 292 + ); 293 + expect(result.success).toBe(false); 294 + }); 295 + }); 296 + }); 297 + 298 + describe('Mixed Constraints', () => { 299 + describe('NumberWithExclusiveMinInclusiveMax', () => { 300 + it('should accept values above exclusive minimum and at inclusive maximum', () => { 301 + const result = v.safeParse( 302 + generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 303 + 90, 304 + ); 305 + expect(result.success).toBe(true); 306 + }); 307 + 308 + it('should accept values above exclusive minimum and below inclusive maximum', () => { 309 + const result = v.safeParse( 310 + generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 311 + 50, 312 + ); 313 + expect(result.success).toBe(true); 314 + }); 315 + 316 + it('should reject values at exclusive minimum', () => { 317 + const result = v.safeParse( 318 + generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 319 + 10, 320 + ); 321 + expect(result.success).toBe(false); 322 + }); 323 + 324 + it('should reject values above inclusive maximum', () => { 325 + const result = v.safeParse( 326 + generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 327 + 91, 328 + ); 329 + expect(result.success).toBe(false); 330 + }); 331 + }); 332 + 333 + describe('NumberWithInclusiveMinExclusiveMax', () => { 334 + it('should accept values at inclusive minimum and below exclusive maximum', () => { 335 + const result = v.safeParse( 336 + generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 337 + 20, 338 + ); 339 + expect(result.success).toBe(true); 340 + }); 341 + 342 + it('should accept values above inclusive minimum and below exclusive maximum', () => { 343 + const result = v.safeParse( 344 + generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 345 + 50, 346 + ); 347 + expect(result.success).toBe(true); 348 + }); 349 + 350 + it('should reject values below inclusive minimum', () => { 351 + const result = v.safeParse( 352 + generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 353 + 19, 354 + ); 355 + expect(result.success).toBe(false); 356 + }); 357 + 358 + it('should reject values at exclusive maximum', () => { 359 + const result = v.safeParse( 360 + generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 361 + 80, 362 + ); 363 + expect(result.success).toBe(false); 364 + }); 365 + }); 366 + 367 + describe('IntegerWithExclusiveMinInclusiveMax', () => { 368 + it('should accept values above exclusive minimum and at inclusive maximum', () => { 369 + const result = v.safeParse( 370 + generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 371 + 50, 372 + ); 373 + expect(result.success).toBe(true); 374 + }); 375 + 376 + it('should accept values above exclusive minimum and below inclusive maximum', () => { 377 + const result = v.safeParse( 378 + generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 379 + 25, 380 + ); 381 + expect(result.success).toBe(true); 382 + }); 383 + 384 + it('should reject values at exclusive minimum', () => { 385 + const result = v.safeParse( 386 + generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 387 + 5, 388 + ); 389 + expect(result.success).toBe(false); 390 + }); 391 + 392 + it('should reject values above inclusive maximum', () => { 393 + const result = v.safeParse( 394 + generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 395 + 51, 396 + ); 397 + expect(result.success).toBe(false); 398 + }); 399 + }); 400 + 401 + describe('IntegerWithInclusiveMinExclusiveMax', () => { 402 + it('should accept values at inclusive minimum and below exclusive maximum', () => { 403 + const result = v.safeParse( 404 + generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 405 + 10, 406 + ); 407 + expect(result.success).toBe(true); 408 + }); 409 + 410 + it('should accept values above inclusive minimum and below exclusive maximum', () => { 411 + const result = v.safeParse( 412 + generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 413 + 55, 414 + ); 415 + expect(result.success).toBe(true); 416 + }); 417 + 418 + it('should reject values below inclusive minimum', () => { 419 + const result = v.safeParse( 420 + generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 421 + 9, 422 + ); 423 + expect(result.success).toBe(false); 424 + }); 425 + 426 + it('should reject values at exclusive maximum', () => { 427 + const result = v.safeParse( 428 + generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 429 + 100, 430 + ); 431 + expect(result.success).toBe(false); 432 + }); 433 + }); 434 + }); 435 + 436 + describe('Format-Specific Constraints (Int64)', () => { 437 + describe('Int64WithMinimum', () => { 438 + it('should accept BigInt values at minimum boundary', () => { 439 + const result = v.safeParse( 440 + generatedSchemas.vInt64WithMinimum, 441 + BigInt('-5000000000000'), 442 + ); 443 + expect(result.success).toBe(true); 444 + }); 445 + 446 + it('should accept BigInt values above minimum', () => { 447 + const result = v.safeParse( 448 + generatedSchemas.vInt64WithMinimum, 449 + BigInt('0'), 450 + ); 451 + expect(result.success).toBe(true); 452 + }); 453 + 454 + it('should reject BigInt values below minimum', () => { 455 + const result = v.safeParse( 456 + generatedSchemas.vInt64WithMinimum, 457 + BigInt('-5000000000001'), 458 + ); 459 + expect(result.success).toBe(false); 460 + }); 461 + }); 462 + 463 + describe('Int64WithMaximum', () => { 464 + it('should accept BigInt values at maximum boundary', () => { 465 + const result = v.safeParse( 466 + generatedSchemas.vInt64WithMaximum, 467 + BigInt('5000000000000'), 468 + ); 469 + expect(result.success).toBe(true); 470 + }); 471 + 472 + it('should accept BigInt values below maximum', () => { 473 + const result = v.safeParse( 474 + generatedSchemas.vInt64WithMaximum, 475 + BigInt('1000000000000'), 476 + ); 477 + expect(result.success).toBe(true); 478 + }); 479 + 480 + it('should reject BigInt values above maximum', () => { 481 + const result = v.safeParse( 482 + generatedSchemas.vInt64WithMaximum, 483 + BigInt('5000000000001'), 484 + ); 485 + expect(result.success).toBe(false); 486 + }); 487 + }); 488 + 489 + describe('Int64WithMinMax', () => { 490 + it('should accept BigInt values within range', () => { 491 + const result = v.safeParse( 492 + generatedSchemas.vInt64WithMinMax, 493 + BigInt('0'), 494 + ); 495 + expect(result.success).toBe(true); 496 + }); 497 + 498 + it('should accept BigInt values at minimum boundary', () => { 499 + const result = v.safeParse( 500 + generatedSchemas.vInt64WithMinMax, 501 + BigInt('-4000000000000'), 502 + ); 503 + expect(result.success).toBe(true); 504 + }); 505 + 506 + it('should accept BigInt values at maximum boundary', () => { 507 + const result = v.safeParse( 508 + generatedSchemas.vInt64WithMinMax, 509 + BigInt('4000000000000'), 510 + ); 511 + expect(result.success).toBe(true); 512 + }); 513 + 514 + it('should reject BigInt values below minimum', () => { 515 + const result = v.safeParse( 516 + generatedSchemas.vInt64WithMinMax, 517 + BigInt('-4000000000001'), 518 + ); 519 + expect(result.success).toBe(false); 520 + }); 521 + 522 + it('should reject BigInt values above maximum', () => { 523 + const result = v.safeParse( 524 + generatedSchemas.vInt64WithMinMax, 525 + BigInt('4000000000001'), 526 + ); 527 + expect(result.success).toBe(false); 528 + }); 529 + }); 530 + 531 + describe('Int64WithExclusiveMin', () => { 532 + it('should accept BigInt values above exclusive minimum', () => { 533 + const result = v.safeParse( 534 + generatedSchemas.vInt64WithExclusiveMin, 535 + BigInt('-2999999999999'), 536 + ); 537 + expect(result.success).toBe(true); 538 + }); 539 + 540 + it('should reject BigInt values at exclusive minimum', () => { 541 + const result = v.safeParse( 542 + generatedSchemas.vInt64WithExclusiveMin, 543 + BigInt('-3000000000000'), 544 + ); 545 + expect(result.success).toBe(false); 546 + }); 547 + }); 548 + 549 + describe('Int64WithExclusiveMax', () => { 550 + it('should accept BigInt values below exclusive maximum', () => { 551 + const result = v.safeParse( 552 + generatedSchemas.vInt64WithExclusiveMax, 553 + BigInt('2999999999999'), 554 + ); 555 + expect(result.success).toBe(true); 556 + }); 557 + 558 + it('should reject BigInt values at exclusive maximum', () => { 559 + const result = v.safeParse( 560 + generatedSchemas.vInt64WithExclusiveMax, 561 + BigInt('3000000000000'), 562 + ); 563 + expect(result.success).toBe(false); 564 + }); 565 + }); 566 + 567 + describe('Int64WithExclusiveMinMax', () => { 568 + it('should accept BigInt values within exclusive range', () => { 569 + const result = v.safeParse( 570 + generatedSchemas.vInt64WithExclusiveMinMax, 571 + BigInt('0'), 572 + ); 573 + expect(result.success).toBe(true); 574 + }); 575 + 576 + it('should reject BigInt values at exclusive minimum', () => { 577 + const result = v.safeParse( 578 + generatedSchemas.vInt64WithExclusiveMinMax, 579 + BigInt('-2000000000000'), 580 + ); 581 + expect(result.success).toBe(false); 582 + }); 583 + 584 + it('should reject BigInt values at exclusive maximum', () => { 585 + const result = v.safeParse( 586 + generatedSchemas.vInt64WithExclusiveMinMax, 587 + BigInt('2000000000000'), 588 + ); 589 + expect(result.success).toBe(false); 590 + }); 591 + }); 592 + 593 + describe('Int64WithExclusiveMinInclusiveMax', () => { 594 + it('should accept values above exclusive minimum and at inclusive maximum', () => { 595 + const result = v.safeParse( 596 + generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 597 + BigInt('6000000000000'), 598 + ); 599 + expect(result.success).toBe(true); 600 + }); 601 + 602 + it('should accept values above exclusive minimum and below inclusive maximum', () => { 603 + const result = v.safeParse( 604 + generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 605 + BigInt('0'), 606 + ); 607 + expect(result.success).toBe(true); 608 + }); 609 + 610 + it('should reject values at exclusive minimum', () => { 611 + const result = v.safeParse( 612 + generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 613 + BigInt('-6000000000000'), 614 + ); 615 + expect(result.success).toBe(false); 616 + }); 617 + 618 + it('should reject values above inclusive maximum', () => { 619 + const result = v.safeParse( 620 + generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 621 + BigInt('6000000000001'), 622 + ); 623 + expect(result.success).toBe(false); 624 + }); 625 + }); 626 + 627 + describe('Int64WithInclusiveMinExclusiveMax', () => { 628 + it('should accept values at inclusive minimum and below exclusive maximum', () => { 629 + const result = v.safeParse( 630 + generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 631 + BigInt('-7000000000000'), 632 + ); 633 + expect(result.success).toBe(true); 634 + }); 635 + 636 + it('should accept values above inclusive minimum and below exclusive maximum', () => { 637 + const result = v.safeParse( 638 + generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 639 + BigInt('0'), 640 + ); 641 + expect(result.success).toBe(true); 642 + }); 643 + 644 + it('should reject values below inclusive minimum', () => { 645 + const result = v.safeParse( 646 + generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 647 + BigInt('-7000000000001'), 648 + ); 649 + expect(result.success).toBe(false); 650 + }); 651 + 652 + it('should reject values at exclusive maximum', () => { 653 + const result = v.safeParse( 654 + generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 655 + BigInt('7000000000000'), 656 + ); 657 + expect(result.success).toBe(false); 658 + }); 659 + }); 660 + }); 661 + 662 + describe('Format-Specific Constraints (UInt64)', () => { 663 + describe('UInt64WithMinimum', () => { 664 + it('should accept BigInt values at minimum boundary', () => { 665 + const result = v.safeParse( 666 + generatedSchemas.vUInt64WithMinimum, 667 + BigInt('5000000000000'), 668 + ); 669 + expect(result.success).toBe(true); 670 + }); 671 + 672 + it('should accept BigInt values above minimum', () => { 673 + const result = v.safeParse( 674 + generatedSchemas.vUInt64WithMinimum, 675 + BigInt('8000000000000'), 676 + ); 677 + expect(result.success).toBe(true); 678 + }); 679 + 680 + it('should reject BigInt values below minimum', () => { 681 + const result = v.safeParse( 682 + generatedSchemas.vUInt64WithMinimum, 683 + BigInt('4999999999999'), 684 + ); 685 + expect(result.success).toBe(false); 686 + }); 687 + }); 688 + 689 + describe('UInt64WithMaximum', () => { 690 + it('should accept BigInt values at maximum boundary', () => { 691 + const result = v.safeParse( 692 + generatedSchemas.vUInt64WithMaximum, 693 + BigInt('15000000000000'), 694 + ); 695 + expect(result.success).toBe(true); 696 + }); 697 + 698 + it('should accept BigInt values below maximum', () => { 699 + const result = v.safeParse( 700 + generatedSchemas.vUInt64WithMaximum, 701 + BigInt('10000000000000'), 702 + ); 703 + expect(result.success).toBe(true); 704 + }); 705 + 706 + it('should reject BigInt values above maximum', () => { 707 + const result = v.safeParse( 708 + generatedSchemas.vUInt64WithMaximum, 709 + BigInt('15000000000001'), 710 + ); 711 + expect(result.success).toBe(false); 712 + }); 713 + }); 714 + 715 + describe('UInt64WithMinMax', () => { 716 + it('should accept BigInt values within range', () => { 717 + const result = v.safeParse( 718 + generatedSchemas.vUInt64WithMinMax, 719 + BigInt('5000000000000'), 720 + ); 721 + expect(result.success).toBe(true); 722 + }); 723 + 724 + it('should accept BigInt values at minimum boundary', () => { 725 + const result = v.safeParse( 726 + generatedSchemas.vUInt64WithMinMax, 727 + BigInt('1000000000000'), 728 + ); 729 + expect(result.success).toBe(true); 730 + }); 731 + 732 + it('should accept BigInt values at maximum boundary', () => { 733 + const result = v.safeParse( 734 + generatedSchemas.vUInt64WithMinMax, 735 + BigInt('10000000000000'), 736 + ); 737 + expect(result.success).toBe(true); 738 + }); 739 + 740 + it('should reject BigInt values below minimum', () => { 741 + const result = v.safeParse( 742 + generatedSchemas.vUInt64WithMinMax, 743 + BigInt('999999999999'), 744 + ); 745 + expect(result.success).toBe(false); 746 + }); 747 + 748 + it('should reject BigInt values above maximum', () => { 749 + const result = v.safeParse( 750 + generatedSchemas.vUInt64WithMinMax, 751 + BigInt('10000000000001'), 752 + ); 753 + expect(result.success).toBe(false); 754 + }); 755 + }); 756 + 757 + describe('UInt64WithExclusiveMin', () => { 758 + it('should accept BigInt values above exclusive minimum', () => { 759 + const result = v.safeParse( 760 + generatedSchemas.vUInt64WithExclusiveMin, 761 + BigInt('8000000000001'), 762 + ); 763 + expect(result.success).toBe(true); 764 + }); 765 + 766 + it('should reject BigInt values at exclusive minimum', () => { 767 + const result = v.safeParse( 768 + generatedSchemas.vUInt64WithExclusiveMin, 769 + BigInt('8000000000000'), 770 + ); 771 + expect(result.success).toBe(false); 772 + }); 773 + }); 774 + 775 + describe('UInt64WithExclusiveMax', () => { 776 + it('should accept BigInt values below exclusive maximum', () => { 777 + const result = v.safeParse( 778 + generatedSchemas.vUInt64WithExclusiveMax, 779 + BigInt('11999999999999'), 780 + ); 781 + expect(result.success).toBe(true); 782 + }); 783 + 784 + it('should reject BigInt values at exclusive maximum', () => { 785 + const result = v.safeParse( 786 + generatedSchemas.vUInt64WithExclusiveMax, 787 + BigInt('12000000000000'), 788 + ); 789 + expect(result.success).toBe(false); 790 + }); 791 + }); 792 + 793 + describe('UInt64WithExclusiveMinMax', () => { 794 + it('should accept BigInt values within exclusive range', () => { 795 + const result = v.safeParse( 796 + generatedSchemas.vUInt64WithExclusiveMinMax, 797 + BigInt('5000000000000'), 798 + ); 799 + expect(result.success).toBe(true); 800 + }); 801 + 802 + it('should reject BigInt values at exclusive minimum', () => { 803 + const result = v.safeParse( 804 + generatedSchemas.vUInt64WithExclusiveMinMax, 805 + BigInt('2000000000000'), 806 + ); 807 + expect(result.success).toBe(false); 808 + }); 809 + 810 + it('should reject BigInt values at exclusive maximum', () => { 811 + const result = v.safeParse( 812 + generatedSchemas.vUInt64WithExclusiveMinMax, 813 + BigInt('8000000000000'), 814 + ); 815 + expect(result.success).toBe(false); 816 + }); 817 + }); 818 + 819 + describe('UInt64WithExclusiveMinInclusiveMax', () => { 820 + it('should accept values above exclusive minimum and at inclusive maximum', () => { 821 + const result = v.safeParse( 822 + generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 823 + BigInt('13000000000000'), 824 + ); 825 + expect(result.success).toBe(true); 826 + }); 827 + 828 + it('should accept values above exclusive minimum and below inclusive maximum', () => { 829 + const result = v.safeParse( 830 + generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 831 + BigInt('8000000000000'), 832 + ); 833 + expect(result.success).toBe(true); 834 + }); 835 + 836 + it('should reject values at exclusive minimum', () => { 837 + const result = v.safeParse( 838 + generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 839 + BigInt('3000000000000'), 840 + ); 841 + expect(result.success).toBe(false); 842 + }); 843 + 844 + it('should reject values above inclusive maximum', () => { 845 + const result = v.safeParse( 846 + generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 847 + BigInt('13000000000001'), 848 + ); 849 + expect(result.success).toBe(false); 850 + }); 851 + }); 852 + 853 + describe('UInt64WithInclusiveMinExclusiveMax', () => { 854 + it('should accept values at inclusive minimum and below exclusive maximum', () => { 855 + const result = v.safeParse( 856 + generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 857 + BigInt('4000000000000'), 858 + ); 859 + expect(result.success).toBe(true); 860 + }); 861 + 862 + it('should accept values above inclusive minimum and below exclusive maximum', () => { 863 + const result = v.safeParse( 864 + generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 865 + BigInt('9000000000000'), 866 + ); 867 + expect(result.success).toBe(true); 868 + }); 869 + 870 + it('should reject values below inclusive minimum', () => { 871 + const result = v.safeParse( 872 + generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 873 + BigInt('3999999999999'), 874 + ); 875 + expect(result.success).toBe(false); 876 + }); 877 + 878 + it('should reject values at exclusive maximum', () => { 879 + const result = v.safeParse( 880 + generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 881 + BigInt('14000000000000'), 882 + ); 883 + expect(result.success).toBe(false); 884 + }); 885 + }); 886 + }); 887 + 888 + describe('Special Cases', () => { 889 + describe('PrecedenceTest', () => { 890 + it('should use exclusive constraints over inclusive (exclusive minimum takes precedence)', () => { 891 + // exclusiveMinimum: 5, minimum: 10 - exclusive should take precedence 892 + const result = v.safeParse(generatedSchemas.vPrecedenceTest, 6); 893 + expect(result.success).toBe(true); 894 + }); 895 + 896 + it('should use exclusive constraints over inclusive (exclusive maximum takes precedence)', () => { 897 + // exclusiveMaximum: 95, maximum: 90 - exclusive should take precedence 898 + const result = v.safeParse(generatedSchemas.vPrecedenceTest, 94); 899 + expect(result.success).toBe(true); 900 + }); 901 + 902 + it('should reject values at exclusive minimum boundary', () => { 903 + const result = v.safeParse(generatedSchemas.vPrecedenceTest, 5); 904 + expect(result.success).toBe(false); 905 + }); 906 + 907 + it('should reject values at exclusive maximum boundary', () => { 908 + const result = v.safeParse(generatedSchemas.vPrecedenceTest, 95); 909 + expect(result.success).toBe(false); 910 + }); 911 + }); 912 + }); 913 + });
-127
packages/openapi-ts-tests/main/test/plugins/@tanstack/meta-function.test.ts
··· 1 - import fs from 'node:fs'; 2 - import path from 'node:path'; 3 - import { fileURLToPath } from 'node:url'; 4 - 5 - import { createClient, type UserConfig } from '@hey-api/openapi-ts'; 6 - import { describe, expect, it } from 'vitest'; 7 - 8 - import { getFilePaths, getSpecsPath } from '../../../../utils'; 9 - 10 - const __filename = fileURLToPath(import.meta.url); 11 - const __dirname = path.dirname(__filename); 12 - 13 - describe('TanStack Query Meta Function Customization', () => { 14 - const version = '3.1.x'; 15 - const namespace = 'plugins'; 16 - 17 - const createConfig = ( 18 - userConfig: Omit<UserConfig, 'input'> & Pick<Partial<UserConfig>, 'input'>, 19 - ): UserConfig => ({ 20 - input: path.join(getSpecsPath(), version, 'security-api-key.json'), 21 - logs: { 22 - level: 'silent', 23 - }, 24 - ...userConfig, 25 - }); 26 - 27 - // Framework configurations 28 - const frameworks = [ 29 - { 30 - description: 'React Query', 31 - name: '@tanstack/react-query', 32 - output: 'react-query', 33 - }, 34 - { 35 - description: 'Vue Query', 36 - name: '@tanstack/vue-query', 37 - output: 'vue-query', 38 - }, 39 - { 40 - description: 'Svelte Query', 41 - name: '@tanstack/svelte-query', 42 - output: 'svelte-query', 43 - }, 44 - { 45 - description: 'Solid Query', 46 - name: '@tanstack/solid-query', 47 - output: 'solid-query', 48 - }, 49 - { 50 - description: 'Angular Query', 51 - name: '@tanstack/angular-query-experimental', 52 - output: 'angular-query-experimental', 53 - }, 54 - ] as const; 55 - 56 - // Generate scenarios for each framework 57 - const scenarios = frameworks.map((framework) => ({ 58 - config: createConfig({ 59 - output: path.join( 60 - __dirname, 61 - 'generated', 62 - version, 63 - namespace, 64 - '@tanstack', 65 - `${framework.output}/meta-function`, 66 - ), 67 - plugins: [ 68 - { 69 - infiniteQueryOptions: { 70 - meta: (operation) => ({ 71 - id: operation.id, 72 - method: operation.method, 73 - path: operation.path, 74 - }), 75 - }, 76 - mutationOptions: { 77 - meta: (operation) => ({ 78 - id: operation.id, 79 - method: operation.method, 80 - path: operation.path, 81 - }), 82 - }, 83 - name: framework.name, 84 - queryOptions: { 85 - meta: (operation) => ({ 86 - id: operation.id, 87 - method: operation.method, 88 - path: operation.path, 89 - }), 90 - }, 91 - }, 92 - '@hey-api/client-fetch', 93 - ], 94 - }), 95 - description: `generates ${framework.description} options with custom meta function`, 96 - })); 97 - 98 - it.each(scenarios)('$description', async ({ config }) => { 99 - await createClient(config); 100 - 101 - const outputPath = config.output as string; 102 - const filePaths = getFilePaths(outputPath); 103 - 104 - // Create snapshots for all generated files 105 - await Promise.all( 106 - filePaths.map(async (filePath) => { 107 - const fileContent = fs.readFileSync(filePath, 'utf-8'); 108 - const relativePath = filePath.slice(outputPath.length + 1); 109 - const fileName = path.basename(relativePath); 110 - const frameworkDir = path.dirname(relativePath).split(path.sep).pop()!; 111 - await expect(fileContent).toMatchFileSnapshot( 112 - path.join( 113 - __dirname, 114 - '..', 115 - '..', 116 - '__snapshots__', 117 - 'plugins', 118 - '@tanstack', 119 - 'meta', 120 - frameworkDir, 121 - fileName, 122 - ), 123 - ); 124 - }), 125 - ); 126 - }); 127 - });
-93
packages/openapi-ts-tests/main/test/plugins/valibot/spec/numberTypeToValibotSchema/const-values.yaml
··· 1 - openapi: '3.1.0' 2 - info: 3 - title: Number Type Const Values Test API 4 - version: '1.0.0' 5 - paths: {} 6 - components: 7 - schemas: 8 - NumberNoFormat: 9 - type: number 10 - const: 42.5 11 - IntegerNoFormat: 12 - type: integer 13 - const: -1 14 - NumberInt8: 15 - type: number 16 - format: int8 17 - const: 100 18 - NumberInt16: 19 - type: number 20 - format: int16 21 - const: 1000 22 - NumberInt32: 23 - type: number 24 - format: int32 25 - const: 100000 26 - NumberInt64: 27 - type: number 28 - format: int64 29 - const: 1000000000000 30 - NumberUint8: 31 - type: number 32 - format: uint8 33 - const: 200 34 - NumberUint16: 35 - type: number 36 - format: uint16 37 - const: 50000 38 - NumberUint32: 39 - type: number 40 - format: uint32 41 - const: 3000000000 42 - NumberUint64: 43 - type: number 44 - format: uint64 45 - const: 18000000000000000000 46 - IntegerInt8: 47 - type: integer 48 - format: int8 49 - const: -100 50 - IntegerInt16: 51 - type: integer 52 - format: int16 53 - const: -1000 54 - IntegerInt32: 55 - type: integer 56 - format: int32 57 - const: -100000 58 - IntegerInt64: 59 - type: integer 60 - format: int64 61 - const: -1000000000000 62 - IntegerUint8: 63 - type: integer 64 - format: uint8 65 - const: 255 66 - IntegerUint16: 67 - type: integer 68 - format: uint16 69 - const: 65535 70 - IntegerUint32: 71 - type: integer 72 - format: uint32 73 - const: 4294967295 74 - IntegerUint64: 75 - type: integer 76 - format: uint64 77 - const: 1000000000000 78 - StringInt64: 79 - type: string 80 - format: int64 81 - const: '-9223372036854775808' 82 - StringUint64: 83 - type: string 84 - format: uint64 85 - const: '18446744073709551615' 86 - StringInt64n: 87 - type: string 88 - format: int64 89 - const: '-9223372036854775808n' 90 - StringUint64n: 91 - type: string 92 - format: uint64 93 - const: '18446744073709551615n'
-64
packages/openapi-ts-tests/main/test/plugins/valibot/spec/numberTypeToValibotSchema/formats.yaml
··· 1 - openapi: '3.1.0' 2 - info: 3 - title: Integer Formats Test 4 - version: '1.0.0' 5 - components: 6 - schemas: 7 - NumberNoFormat: 8 - type: number 9 - NumberInt8: 10 - type: number 11 - format: int8 12 - NumberInt16: 13 - type: number 14 - format: int16 15 - NumberInt32: 16 - type: number 17 - format: int32 18 - NumberInt64: 19 - type: number 20 - format: int64 21 - NumberUint8: 22 - type: number 23 - format: uint8 24 - NumberUint16: 25 - type: number 26 - format: uint16 27 - NumberUint32: 28 - type: number 29 - format: uint32 30 - NumberUint64: 31 - type: number 32 - format: uint64 33 - IntegerNoFormat: 34 - type: integer 35 - IntegerInt8: 36 - type: integer 37 - format: int8 38 - IntegerInt16: 39 - type: integer 40 - format: int16 41 - IntegerInt32: 42 - type: integer 43 - format: int32 44 - IntegerInt64: 45 - type: integer 46 - format: int64 47 - IntegerUint8: 48 - type: integer 49 - format: uint8 50 - IntegerUint16: 51 - type: integer 52 - format: uint16 53 - IntegerUint32: 54 - type: integer 55 - format: uint32 56 - IntegerUint64: 57 - type: integer 58 - format: uint64 59 - StringInt64: 60 - type: string 61 - format: int64 62 - StringUint64: 63 - type: string 64 - format: uint64
-141
packages/openapi-ts-tests/main/test/plugins/valibot/spec/numberTypeToValibotSchema/min-max-constraints.yaml
··· 1 - openapi: '3.1.0' 2 - info: 3 - title: Number Type Min/Max Constraints Test API 4 - version: '1.0.0' 5 - paths: {} 6 - components: 7 - schemas: 8 - NumberWithMinimum: 9 - type: number 10 - minimum: 10 11 - NumberWithMaximum: 12 - type: number 13 - maximum: 100 14 - NumberWithMinMax: 15 - type: number 16 - minimum: 0 17 - maximum: 100 18 - IntegerWithMinimum: 19 - type: integer 20 - minimum: 5 21 - IntegerWithMaximum: 22 - type: integer 23 - maximum: 999 24 - IntegerWithMinMax: 25 - type: integer 26 - minimum: 1 27 - maximum: 999 28 - NumberWithExclusiveMin: 29 - type: number 30 - exclusiveMinimum: 0 31 - NumberWithExclusiveMax: 32 - type: number 33 - exclusiveMaximum: 100 34 - NumberWithExclusiveMinMax: 35 - type: number 36 - exclusiveMinimum: 0 37 - exclusiveMaximum: 1 38 - IntegerWithExclusiveMin: 39 - type: integer 40 - exclusiveMinimum: 10 41 - IntegerWithExclusiveMax: 42 - type: integer 43 - exclusiveMaximum: 50 44 - IntegerWithExclusiveMinMax: 45 - type: integer 46 - exclusiveMinimum: 5 47 - exclusiveMaximum: 15 48 - NumberWithExclusiveMinInclusiveMax: 49 - type: number 50 - exclusiveMinimum: 10 51 - maximum: 90 52 - NumberWithInclusiveMinExclusiveMax: 53 - type: number 54 - minimum: 20 55 - exclusiveMaximum: 80 56 - IntegerWithExclusiveMinInclusiveMax: 57 - type: integer 58 - exclusiveMinimum: 5 59 - maximum: 50 60 - IntegerWithInclusiveMinExclusiveMax: 61 - type: integer 62 - minimum: 10 63 - exclusiveMaximum: 100 64 - Int64WithMinimum: 65 - type: integer 66 - format: int64 67 - minimum: -5000000000000 68 - Int64WithMaximum: 69 - type: integer 70 - format: int64 71 - maximum: 5000000000000 72 - Int64WithMinMax: 73 - type: integer 74 - format: int64 75 - minimum: -4000000000000 76 - maximum: 4000000000000 77 - Int64WithExclusiveMin: 78 - type: integer 79 - format: int64 80 - exclusiveMinimum: -3000000000000 81 - Int64WithExclusiveMax: 82 - type: integer 83 - format: int64 84 - exclusiveMaximum: 3000000000000 85 - Int64WithExclusiveMinMax: 86 - type: integer 87 - format: int64 88 - exclusiveMinimum: -2000000000000 89 - exclusiveMaximum: 2000000000000 90 - Int64WithExclusiveMinInclusiveMax: 91 - type: integer 92 - format: int64 93 - exclusiveMinimum: -6000000000000 94 - maximum: 6000000000000 95 - Int64WithInclusiveMinExclusiveMax: 96 - type: integer 97 - format: int64 98 - minimum: -7000000000000 99 - exclusiveMaximum: 7000000000000 100 - UInt64WithMinimum: 101 - type: integer 102 - format: uint64 103 - minimum: 5000000000000 104 - UInt64WithMaximum: 105 - type: integer 106 - format: uint64 107 - maximum: 15000000000000 108 - UInt64WithMinMax: 109 - type: integer 110 - format: uint64 111 - minimum: 1000000000000 112 - maximum: 10000000000000 113 - UInt64WithExclusiveMin: 114 - type: integer 115 - format: uint64 116 - exclusiveMinimum: 8000000000000 117 - UInt64WithExclusiveMax: 118 - type: integer 119 - format: uint64 120 - exclusiveMaximum: 12000000000000 121 - UInt64WithExclusiveMinMax: 122 - type: integer 123 - format: uint64 124 - exclusiveMinimum: 2000000000000 125 - exclusiveMaximum: 8000000000000 126 - UInt64WithExclusiveMinInclusiveMax: 127 - type: integer 128 - format: uint64 129 - exclusiveMinimum: 3000000000000 130 - maximum: 13000000000000 131 - UInt64WithInclusiveMinExclusiveMax: 132 - type: integer 133 - format: uint64 134 - minimum: 4000000000000 135 - exclusiveMaximum: 14000000000000 136 - PrecedenceTest: 137 - type: number 138 - minimum: 10 139 - maximum: 90 140 - exclusiveMinimum: 5 141 - exclusiveMaximum: 95
-89
packages/openapi-ts-tests/main/test/plugins/valibot/spec/objectAdditionalProperties/additional-properties.yaml
··· 1 - openapi: '3.1.0' 2 - info: 3 - title: Object Additional Properties Test API 4 - version: '1.0.0' 5 - paths: {} 6 - components: 7 - schemas: 8 - # Test case from the issue: object with additionalProperties type string 9 - ObjectWithAdditionalPropertiesString: 10 - type: object 11 - properties: 12 - headers: 13 - type: object 14 - additionalProperties: 15 - type: string 16 - 17 - # Object with no properties, only additionalProperties with string type 18 - ObjectOnlyAdditionalPropertiesString: 19 - type: object 20 - additionalProperties: 21 - type: string 22 - 23 - # Object with no properties, only additionalProperties with number type 24 - ObjectOnlyAdditionalPropertiesNumber: 25 - type: object 26 - additionalProperties: 27 - type: number 28 - 29 - # Object with no properties, only additionalProperties with boolean type 30 - ObjectOnlyAdditionalPropertiesBoolean: 31 - type: object 32 - additionalProperties: 33 - type: boolean 34 - 35 - # Object with properties and additionalProperties number 36 - ObjectWithPropertiesAndAdditionalPropertiesNumber: 37 - type: object 38 - properties: 39 - id: 40 - type: string 41 - count: 42 - type: integer 43 - additionalProperties: 44 - type: number 45 - 46 - # Object with additionalProperties as object type 47 - ObjectWithAdditionalPropertiesObject: 48 - type: object 49 - properties: 50 - metadata: 51 - type: object 52 - additionalProperties: 53 - type: object 54 - properties: 55 - value: 56 - type: string 57 - 58 - # Already working case: object with no properties and additionalProperties object 59 - ObjectOnlyAdditionalPropertiesObject: 60 - type: object 61 - additionalProperties: 62 - type: object 63 - properties: 64 - name: 65 - type: string 66 - 67 - # Object with additionalProperties set to false (no additional properties allowed) 68 - ObjectWithAdditionalPropertiesFalse: 69 - type: object 70 - properties: 71 - id: 72 - type: string 73 - count: 74 - type: integer 75 - additionalProperties: false 76 - 77 - # Object with nested object that has additionalProperties: false 78 - ObjectWithNestedAdditionalPropertiesFalse: 79 - type: object 80 - properties: 81 - membership: 82 - type: object 83 - properties: 84 - status: 85 - type: string 86 - enum: [approved, declined, pending] 87 - calendar_membership_tier_id: 88 - type: string 89 - additionalProperties: false
-292
packages/openapi-ts-tests/main/test/plugins/valibot/test/numberTypeToValibotSchema/const-values.test.ts
··· 1 - import * as v from 'valibot'; 2 - import { beforeAll, describe, expect, it } from 'vitest'; 3 - 4 - import { setupValibotTest } from '../../test-helper'; 5 - 6 - describe('Number Type Const Values Tests', () => { 7 - let generatedSchemas: any; 8 - 9 - beforeAll(async () => { 10 - generatedSchemas = await setupValibotTest(); 11 - }); 12 - 13 - describe('Number Type Const Validation', () => { 14 - it('should accept exact const value', () => { 15 - const result = v.safeParse(generatedSchemas.vNumberNoFormat, 42.5); 16 - expect(result.success).toBe(true); 17 - }); 18 - 19 - it('should reject non-matching values', () => { 20 - const result = v.safeParse(generatedSchemas.vNumberNoFormat, 42.6); 21 - expect(result.success).toBe(false); 22 - }); 23 - }); 24 - 25 - describe('Number Type Format Const Validation', () => { 26 - it('should accept NumberInt8 exact const value', () => { 27 - const result = v.safeParse(generatedSchemas.vNumberInt8, 100); 28 - expect(result.success).toBe(true); 29 - }); 30 - 31 - it('should reject NumberInt8 non-matching values', () => { 32 - const result = v.safeParse(generatedSchemas.vNumberInt8, 101); 33 - expect(result.success).toBe(false); 34 - }); 35 - 36 - it('should accept NumberInt16 exact const value', () => { 37 - const result = v.safeParse(generatedSchemas.vNumberInt16, 1000); 38 - expect(result.success).toBe(true); 39 - }); 40 - 41 - it('should reject NumberInt16 non-matching values', () => { 42 - const result = v.safeParse(generatedSchemas.vNumberInt16, 1001); 43 - expect(result.success).toBe(false); 44 - }); 45 - 46 - it('should accept NumberInt32 exact const value', () => { 47 - const result = v.safeParse(generatedSchemas.vNumberInt32, 100000); 48 - expect(result.success).toBe(true); 49 - }); 50 - 51 - it('should reject NumberInt32 non-matching values', () => { 52 - const result = v.safeParse(generatedSchemas.vNumberInt32, 100001); 53 - expect(result.success).toBe(false); 54 - }); 55 - 56 - it('should accept NumberInt64 exact const value', () => { 57 - const result = v.safeParse( 58 - generatedSchemas.vNumberInt64, 59 - BigInt('1000000000000'), 60 - ); 61 - expect(result.success).toBe(true); 62 - }); 63 - 64 - it('should reject NumberInt64 non-matching values', () => { 65 - const result = v.safeParse( 66 - generatedSchemas.vNumberInt64, 67 - BigInt('1000000000001'), 68 - ); 69 - expect(result.success).toBe(false); 70 - }); 71 - 72 - it('should accept NumberUint8 exact const value', () => { 73 - const result = v.safeParse(generatedSchemas.vNumberUint8, 200); 74 - expect(result.success).toBe(true); 75 - }); 76 - 77 - it('should reject NumberUint8 non-matching values', () => { 78 - const result = v.safeParse(generatedSchemas.vNumberUint8, 201); 79 - expect(result.success).toBe(false); 80 - }); 81 - 82 - it('should accept NumberUint16 exact const value', () => { 83 - const result = v.safeParse(generatedSchemas.vNumberUint16, 50000); 84 - expect(result.success).toBe(true); 85 - }); 86 - 87 - it('should reject NumberUint16 non-matching values', () => { 88 - const result = v.safeParse(generatedSchemas.vNumberUint16, 50001); 89 - expect(result.success).toBe(false); 90 - }); 91 - 92 - it('should accept NumberUint32 exact const value', () => { 93 - const result = v.safeParse(generatedSchemas.vNumberUint32, 3000000000); 94 - expect(result.success).toBe(true); 95 - }); 96 - 97 - it('should reject NumberUint32 non-matching values', () => { 98 - const result = v.safeParse(generatedSchemas.vNumberUint32, 3000000001); 99 - expect(result.success).toBe(false); 100 - }); 101 - 102 - it('should accept NumberUint64 exact const value', () => { 103 - const result = v.safeParse( 104 - generatedSchemas.vNumberUint64, 105 - BigInt('18000000000000000000'), 106 - ); 107 - expect(result.success).toBe(true); 108 - }); 109 - 110 - it('should reject NumberUint64 non-matching values', () => { 111 - const result = v.safeParse( 112 - generatedSchemas.vNumberUint64, 113 - BigInt('18000000000000000001'), 114 - ); 115 - expect(result.success).toBe(false); 116 - }); 117 - }); 118 - 119 - describe('Integer Type Const Validation', () => { 120 - it('should accept exact const value', () => { 121 - const result = v.safeParse(generatedSchemas.vIntegerNoFormat, -1); 122 - expect(result.success).toBe(true); 123 - }); 124 - 125 - it('should reject non-matching values', () => { 126 - const result = v.safeParse(generatedSchemas.vIntegerNoFormat, 0); 127 - expect(result.success).toBe(false); 128 - }); 129 - }); 130 - 131 - describe('Integer Type Format Const Validation', () => { 132 - it('should accept IntegerInt8 exact const value', () => { 133 - const result = v.safeParse(generatedSchemas.vIntegerInt8, -100); 134 - expect(result.success).toBe(true); 135 - }); 136 - 137 - it('should reject IntegerInt8 non-matching values', () => { 138 - const result = v.safeParse(generatedSchemas.vIntegerInt8, -99); 139 - expect(result.success).toBe(false); 140 - }); 141 - 142 - it('should accept IntegerInt16 exact const value', () => { 143 - const result = v.safeParse(generatedSchemas.vIntegerInt16, -1000); 144 - expect(result.success).toBe(true); 145 - }); 146 - 147 - it('should reject IntegerInt16 non-matching values', () => { 148 - const result = v.safeParse(generatedSchemas.vIntegerInt16, -999); 149 - expect(result.success).toBe(false); 150 - }); 151 - 152 - it('should accept IntegerInt32 exact const value', () => { 153 - const result = v.safeParse(generatedSchemas.vIntegerInt32, -100000); 154 - expect(result.success).toBe(true); 155 - }); 156 - 157 - it('should reject IntegerInt32 non-matching values', () => { 158 - const result = v.safeParse(generatedSchemas.vIntegerInt32, -99999); 159 - expect(result.success).toBe(false); 160 - }); 161 - 162 - it('should accept IntegerInt64 exact const value', () => { 163 - const result = v.safeParse( 164 - generatedSchemas.vIntegerInt64, 165 - BigInt('-1000000000000'), 166 - ); 167 - expect(result.success).toBe(true); 168 - }); 169 - 170 - it('should reject IntegerInt64 non-matching values', () => { 171 - const result = v.safeParse( 172 - generatedSchemas.vIntegerInt64, 173 - BigInt('-999999999999'), 174 - ); 175 - expect(result.success).toBe(false); 176 - }); 177 - 178 - it('should accept IntegerUint8 exact const value', () => { 179 - const result = v.safeParse(generatedSchemas.vIntegerUint8, 255); 180 - expect(result.success).toBe(true); 181 - }); 182 - 183 - it('should reject IntegerUint8 non-matching values', () => { 184 - const result = v.safeParse(generatedSchemas.vIntegerUint8, 254); 185 - expect(result.success).toBe(false); 186 - }); 187 - 188 - it('should accept IntegerUint16 exact const value', () => { 189 - const result = v.safeParse(generatedSchemas.vIntegerUint16, 65535); 190 - expect(result.success).toBe(true); 191 - }); 192 - 193 - it('should reject IntegerUint16 non-matching values', () => { 194 - const result = v.safeParse(generatedSchemas.vIntegerUint16, 65534); 195 - expect(result.success).toBe(false); 196 - }); 197 - 198 - it('should accept IntegerUint32 exact const value', () => { 199 - const result = v.safeParse(generatedSchemas.vIntegerUint32, 4294967295); 200 - expect(result.success).toBe(true); 201 - }); 202 - 203 - it('should reject IntegerUint32 non-matching values', () => { 204 - const result = v.safeParse(generatedSchemas.vIntegerUint32, 4294967294); 205 - expect(result.success).toBe(false); 206 - }); 207 - 208 - it('should accept IntegerUint64 exact const value', () => { 209 - const result = v.safeParse( 210 - generatedSchemas.vIntegerUint64, 211 - BigInt('1000000000000'), 212 - ); 213 - expect(result.success).toBe(true); 214 - }); 215 - 216 - it('should reject IntegerUint64 non-matching values', () => { 217 - const result = v.safeParse( 218 - generatedSchemas.vIntegerUint64, 219 - BigInt('1000000000001'), 220 - ); 221 - expect(result.success).toBe(false); 222 - }); 223 - }); 224 - 225 - describe('String Type Format Const Validation', () => { 226 - it('should accept StringInt64 exact const value', () => { 227 - const result = v.safeParse( 228 - generatedSchemas.vStringInt64, 229 - BigInt('-9223372036854775808'), 230 - ); 231 - expect(result.success).toBe(true); 232 - }); 233 - 234 - it('should reject StringInt64 non-matching values', () => { 235 - const result = v.safeParse( 236 - generatedSchemas.vStringInt64, 237 - BigInt('-9223372036854775807'), 238 - ); 239 - expect(result.success).toBe(false); 240 - }); 241 - 242 - it('should accept StringUint64 exact const value', () => { 243 - const result = v.safeParse( 244 - generatedSchemas.vStringUint64, 245 - BigInt('18446744073709551615'), 246 - ); 247 - expect(result.success).toBe(true); 248 - }); 249 - 250 - it('should reject StringUint64 non-matching values', () => { 251 - const result = v.safeParse( 252 - generatedSchemas.vStringUint64, 253 - BigInt('18446744073709551614'), 254 - ); 255 - expect(result.success).toBe(false); 256 - }); 257 - }); 258 - 259 - describe('String Type Format Const Validation (BigInt Literal)', () => { 260 - it('should accept StringInt64n exact const value', () => { 261 - const result = v.safeParse( 262 - generatedSchemas.vStringInt64n, 263 - BigInt('-9223372036854775808'), 264 - ); 265 - expect(result.success).toBe(true); 266 - }); 267 - 268 - it('should reject StringInt64n non-matching values', () => { 269 - const result = v.safeParse( 270 - generatedSchemas.vStringInt64n, 271 - BigInt('-9223372036854775807'), 272 - ); 273 - expect(result.success).toBe(false); 274 - }); 275 - 276 - it('should accept StringUint64n exact const value', () => { 277 - const result = v.safeParse( 278 - generatedSchemas.vStringUint64n, 279 - BigInt('18446744073709551615'), 280 - ); 281 - expect(result.success).toBe(true); 282 - }); 283 - 284 - it('should reject StringUint64n non-matching values', () => { 285 - const result = v.safeParse( 286 - generatedSchemas.vStringUint64n, 287 - BigInt('18446744073709551614'), 288 - ); 289 - expect(result.success).toBe(false); 290 - }); 291 - }); 292 - });
-550
packages/openapi-ts-tests/main/test/plugins/valibot/test/numberTypeToValibotSchema/formats.test.ts
··· 1 - import * as v from 'valibot'; 2 - import { beforeAll, describe, expect, it } from 'vitest'; 3 - 4 - import { setupValibotTest } from '../../test-helper'; 5 - 6 - describe('Number Type Formats Tests', () => { 7 - let generatedSchemas: any; 8 - 9 - beforeAll(async () => { 10 - generatedSchemas = await setupValibotTest(); 11 - }); 12 - 13 - // Format bounds and error messages from INTEGER_FORMATS 14 - const FORMAT_BOUNDS = { 15 - int16: { 16 - max: 32767, 17 - maxError: 'Expected int16 to be <= 2^15-1', 18 - min: -32768, 19 - minError: 'Expected int16 to be >= -2^15', 20 - }, 21 - int32: { 22 - max: 2147483647, 23 - maxError: 'Expected int32 to be <= 2^31-1', 24 - min: -2147483648, 25 - minError: 'Expected int32 to be >= -2^31', 26 - }, 27 - int64: { 28 - max: '9223372036854775807', 29 - maxError: 'Expected int64 to be <= 2^63-1', 30 - min: '-9223372036854775808', 31 - minError: 'Expected int64 to be >= -2^63', 32 - }, 33 - int8: { 34 - max: 127, 35 - maxError: 'Expected int8 to be <= 2^7-1', 36 - min: -128, 37 - minError: 'Expected int8 to be >= -2^7', 38 - }, 39 - uint16: { 40 - max: 65535, 41 - maxError: 'Expected uint16 to be <= 2^16-1', 42 - min: 0, 43 - minError: 'Expected uint16 to be >= 0', 44 - }, 45 - uint32: { 46 - max: 4294967295, 47 - maxError: 'Expected uint32 to be <= 2^32-1', 48 - min: 0, 49 - minError: 'Expected uint32 to be >= 0', 50 - }, 51 - uint64: { 52 - max: '18446744073709551615', 53 - maxError: 'Expected uint64 to be <= 2^64-1', 54 - min: '0', 55 - minError: 'Expected uint64 to be >= 0', 56 - }, 57 - uint8: { 58 - max: 255, 59 - maxError: 'Expected uint8 to be <= 2^8-1', 60 - min: 0, 61 - minError: 'Expected uint8 to be >= 0', 62 - }, 63 - }; 64 - 65 - describe('Number Type Format Validation', () => { 66 - describe('numberNoFormat', () => { 67 - it('should validate any number value', () => { 68 - const result = v.safeParse(generatedSchemas.vNumberNoFormat, 123.456); 69 - expect(result.success).toBe(true); 70 - }); 71 - }); 72 - 73 - describe('numberInt8', () => { 74 - it('should validate values within int8 range', () => { 75 - const result = v.safeParse(generatedSchemas.vNumberInt8, 100); 76 - expect(result.success).toBe(true); 77 - }); 78 - 79 - it('should reject values below int8 minimum', () => { 80 - const result = v.safeParse(generatedSchemas.vNumberInt8, -129); 81 - expect(result.success).toBe(false); 82 - expect(result.issues![0].message).toContain( 83 - FORMAT_BOUNDS.int8.minError, 84 - ); 85 - }); 86 - 87 - it('should reject values above int8 maximum', () => { 88 - const result = v.safeParse(generatedSchemas.vNumberInt8, 128); 89 - expect(result.success).toBe(false); 90 - expect(result.issues![0].message).toContain( 91 - FORMAT_BOUNDS.int8.maxError, 92 - ); 93 - }); 94 - }); 95 - 96 - describe('numberInt16', () => { 97 - it('should validate values within int16 range', () => { 98 - const result = v.safeParse(generatedSchemas.vNumberInt16, 30000); 99 - expect(result.success).toBe(true); 100 - }); 101 - 102 - it('should reject values below int16 minimum', () => { 103 - const result = v.safeParse(generatedSchemas.vNumberInt16, -32769); 104 - expect(result.success).toBe(false); 105 - expect(result.issues![0].message).toContain( 106 - FORMAT_BOUNDS.int16.minError, 107 - ); 108 - }); 109 - 110 - it('should reject values above int16 maximum', () => { 111 - const result = v.safeParse(generatedSchemas.vNumberInt16, 32768); 112 - expect(result.success).toBe(false); 113 - expect(result.issues![0].message).toContain( 114 - FORMAT_BOUNDS.int16.maxError, 115 - ); 116 - }); 117 - }); 118 - 119 - describe('numberInt32', () => { 120 - it('should validate values within int32 range', () => { 121 - const result = v.safeParse(generatedSchemas.vNumberInt32, 2000000000); 122 - expect(result.success).toBe(true); 123 - }); 124 - 125 - it('should reject values below int32 minimum', () => { 126 - const result = v.safeParse(generatedSchemas.vNumberInt32, -2147483649); 127 - expect(result.success).toBe(false); 128 - expect(result.issues![0].message).toContain( 129 - FORMAT_BOUNDS.int32.minError, 130 - ); 131 - }); 132 - 133 - it('should reject values above int32 maximum', () => { 134 - const result = v.safeParse(generatedSchemas.vNumberInt32, 2147483648); 135 - expect(result.success).toBe(false); 136 - expect(result.issues![0].message).toContain( 137 - FORMAT_BOUNDS.int32.maxError, 138 - ); 139 - }); 140 - }); 141 - 142 - describe('numberInt64', () => { 143 - it('should validate values within int64 range and convert to BigInt', () => { 144 - const result = v.safeParse( 145 - generatedSchemas.vNumberInt64, 146 - 1000000000000, 147 - ); 148 - expect(result.success).toBe(true); 149 - expect(typeof result.output).toBe('bigint'); 150 - }); 151 - 152 - it('should validate string values within int64 range', () => { 153 - const result = v.safeParse( 154 - generatedSchemas.vNumberInt64, 155 - '1000000000000', 156 - ); 157 - expect(result.success).toBe(true); 158 - expect(typeof result.output).toBe('bigint'); 159 - }); 160 - 161 - it('should reject values above int64 maximum', () => { 162 - const result = v.safeParse( 163 - generatedSchemas.vNumberInt64, 164 - '9223372036854775808', 165 - ); 166 - expect(result.success).toBe(false); 167 - expect(result.issues![0].message).toContain( 168 - FORMAT_BOUNDS.int64.maxError, 169 - ); 170 - }); 171 - }); 172 - 173 - describe('numberUint8', () => { 174 - it('should validate values within uint8 range', () => { 175 - const result = v.safeParse(generatedSchemas.vNumberUint8, 200); 176 - expect(result.success).toBe(true); 177 - }); 178 - 179 - it('should reject negative values', () => { 180 - const result = v.safeParse(generatedSchemas.vNumberUint8, -1); 181 - expect(result.success).toBe(false); 182 - expect(result.issues![0].message).toContain( 183 - FORMAT_BOUNDS.uint8.minError, 184 - ); 185 - }); 186 - 187 - it('should reject values above uint8 maximum', () => { 188 - const result = v.safeParse(generatedSchemas.vNumberUint8, 256); 189 - expect(result.success).toBe(false); 190 - expect(result.issues![0].message).toContain( 191 - FORMAT_BOUNDS.uint8.maxError, 192 - ); 193 - }); 194 - }); 195 - 196 - describe('numberUint16', () => { 197 - it('should validate values within uint16 range', () => { 198 - const result = v.safeParse(generatedSchemas.vNumberUint16, 60000); 199 - expect(result.success).toBe(true); 200 - }); 201 - 202 - it('should reject negative values', () => { 203 - const result = v.safeParse(generatedSchemas.vNumberUint16, -1); 204 - expect(result.success).toBe(false); 205 - expect(result.issues![0].message).toContain( 206 - FORMAT_BOUNDS.uint16.minError, 207 - ); 208 - }); 209 - 210 - it('should reject values above uint16 maximum', () => { 211 - const result = v.safeParse(generatedSchemas.vNumberUint16, 65536); 212 - expect(result.success).toBe(false); 213 - expect(result.issues![0].message).toContain( 214 - FORMAT_BOUNDS.uint16.maxError, 215 - ); 216 - }); 217 - }); 218 - 219 - describe('numberUint32', () => { 220 - it('should validate values within uint32 range', () => { 221 - const result = v.safeParse(generatedSchemas.vNumberUint32, 4000000000); 222 - expect(result.success).toBe(true); 223 - }); 224 - 225 - it('should reject negative values', () => { 226 - const result = v.safeParse(generatedSchemas.vNumberUint32, -1); 227 - expect(result.success).toBe(false); 228 - expect(result.issues![0].message).toContain( 229 - FORMAT_BOUNDS.uint32.minError, 230 - ); 231 - }); 232 - 233 - it('should reject values above uint32 maximum', () => { 234 - const result = v.safeParse(generatedSchemas.vNumberUint32, 4294967296); 235 - expect(result.success).toBe(false); 236 - expect(result.issues![0].message).toContain( 237 - FORMAT_BOUNDS.uint32.maxError, 238 - ); 239 - }); 240 - }); 241 - 242 - describe('numberUint64', () => { 243 - it('should validate values within uint64 range and convert to BigInt', () => { 244 - const result = v.safeParse( 245 - generatedSchemas.vNumberUint64, 246 - 1000000000000, 247 - ); 248 - expect(result.success).toBe(true); 249 - expect(typeof result.output).toBe('bigint'); 250 - }); 251 - 252 - it('should reject negative values', () => { 253 - const result = v.safeParse(generatedSchemas.vNumberUint64, -1); 254 - expect(result.success).toBe(false); 255 - expect(result.issues![0].message).toContain( 256 - FORMAT_BOUNDS.uint64.minError, 257 - ); 258 - }); 259 - 260 - it('should reject values above uint64 maximum', () => { 261 - const result = v.safeParse( 262 - generatedSchemas.vNumberUint64, 263 - '18446744073709551616', 264 - ); 265 - expect(result.success).toBe(false); 266 - expect(result.issues![0].message).toContain( 267 - FORMAT_BOUNDS.uint64.maxError, 268 - ); 269 - }); 270 - }); 271 - }); 272 - 273 - describe('Integer Type Format Validation', () => { 274 - describe('integerNoFormat', () => { 275 - it('should validate any integer value', () => { 276 - const result = v.safeParse(generatedSchemas.vIntegerNoFormat, 123); 277 - expect(result.success).toBe(true); 278 - }); 279 - 280 - it('should reject non-integer values', () => { 281 - const result = v.safeParse(generatedSchemas.vIntegerNoFormat, 123.456); 282 - expect(result.success).toBe(false); 283 - }); 284 - }); 285 - 286 - describe('integerInt8', () => { 287 - it('should validate values within int8 range', () => { 288 - const result = v.safeParse(generatedSchemas.vIntegerInt8, 100); 289 - expect(result.success).toBe(true); 290 - }); 291 - 292 - it('should reject values below int8 minimum', () => { 293 - const result = v.safeParse(generatedSchemas.vIntegerInt8, -129); 294 - expect(result.success).toBe(false); 295 - expect(result.issues![0].message).toContain( 296 - FORMAT_BOUNDS.int8.minError, 297 - ); 298 - }); 299 - 300 - it('should reject values above int8 maximum', () => { 301 - const result = v.safeParse(generatedSchemas.vIntegerInt8, 128); 302 - expect(result.success).toBe(false); 303 - expect(result.issues![0].message).toContain( 304 - FORMAT_BOUNDS.int8.maxError, 305 - ); 306 - }); 307 - }); 308 - 309 - describe('integerInt16', () => { 310 - it('should validate values within int16 range', () => { 311 - const result = v.safeParse(generatedSchemas.vIntegerInt16, 30000); 312 - expect(result.success).toBe(true); 313 - }); 314 - 315 - it('should reject values below int16 minimum', () => { 316 - const result = v.safeParse(generatedSchemas.vIntegerInt16, -32769); 317 - expect(result.success).toBe(false); 318 - expect(result.issues![0].message).toContain( 319 - FORMAT_BOUNDS.int16.minError, 320 - ); 321 - }); 322 - 323 - it('should reject values above int16 maximum', () => { 324 - const result = v.safeParse(generatedSchemas.vIntegerInt16, 32768); 325 - expect(result.success).toBe(false); 326 - expect(result.issues![0].message).toContain( 327 - FORMAT_BOUNDS.int16.maxError, 328 - ); 329 - }); 330 - }); 331 - 332 - describe('integerInt32', () => { 333 - it('should validate values within int32 range', () => { 334 - const result = v.safeParse(generatedSchemas.vIntegerInt32, 2000000000); 335 - expect(result.success).toBe(true); 336 - }); 337 - 338 - it('should reject values below int32 minimum', () => { 339 - const result = v.safeParse(generatedSchemas.vIntegerInt32, -2147483649); 340 - expect(result.success).toBe(false); 341 - expect(result.issues![0].message).toContain( 342 - FORMAT_BOUNDS.int32.minError, 343 - ); 344 - }); 345 - 346 - it('should reject values above int32 maximum', () => { 347 - const result = v.safeParse(generatedSchemas.vIntegerInt32, 2147483648); 348 - expect(result.success).toBe(false); 349 - expect(result.issues![0].message).toContain( 350 - FORMAT_BOUNDS.int32.maxError, 351 - ); 352 - }); 353 - }); 354 - 355 - describe('integerInt64', () => { 356 - it('should validate values within int64 range and convert to BigInt', () => { 357 - const result = v.safeParse( 358 - generatedSchemas.vIntegerInt64, 359 - 1000000000000, 360 - ); 361 - expect(result.success).toBe(true); 362 - expect(typeof result.output).toBe('bigint'); 363 - }); 364 - 365 - it('should validate string values within int64 range', () => { 366 - const result = v.safeParse( 367 - generatedSchemas.vIntegerInt64, 368 - '1000000000000', 369 - ); 370 - expect(result.success).toBe(true); 371 - expect(typeof result.output).toBe('bigint'); 372 - }); 373 - 374 - it('should reject values above int64 maximum', () => { 375 - const result = v.safeParse( 376 - generatedSchemas.vIntegerInt64, 377 - '9223372036854775808', 378 - ); 379 - expect(result.success).toBe(false); 380 - expect(result.issues![0].message).toContain( 381 - FORMAT_BOUNDS.int64.maxError, 382 - ); 383 - }); 384 - }); 385 - 386 - describe('integerUint8', () => { 387 - it('should validate values within uint8 range', () => { 388 - const result = v.safeParse(generatedSchemas.vIntegerUint8, 200); 389 - expect(result.success).toBe(true); 390 - }); 391 - 392 - it('should reject negative values', () => { 393 - const result = v.safeParse(generatedSchemas.vIntegerUint8, -1); 394 - expect(result.success).toBe(false); 395 - expect(result.issues![0].message).toContain( 396 - FORMAT_BOUNDS.uint8.minError, 397 - ); 398 - }); 399 - 400 - it('should reject values above uint8 maximum', () => { 401 - const result = v.safeParse(generatedSchemas.vIntegerUint8, 256); 402 - expect(result.success).toBe(false); 403 - expect(result.issues![0].message).toContain( 404 - FORMAT_BOUNDS.uint8.maxError, 405 - ); 406 - }); 407 - }); 408 - 409 - describe('integerUint16', () => { 410 - it('should validate values within uint16 range', () => { 411 - const result = v.safeParse(generatedSchemas.vIntegerUint16, 60000); 412 - expect(result.success).toBe(true); 413 - }); 414 - 415 - it('should reject negative values', () => { 416 - const result = v.safeParse(generatedSchemas.vIntegerUint16, -1); 417 - expect(result.success).toBe(false); 418 - expect(result.issues![0].message).toContain( 419 - FORMAT_BOUNDS.uint16.minError, 420 - ); 421 - }); 422 - 423 - it('should reject values above uint16 maximum', () => { 424 - const result = v.safeParse(generatedSchemas.vIntegerUint16, 65536); 425 - expect(result.success).toBe(false); 426 - expect(result.issues![0].message).toContain( 427 - FORMAT_BOUNDS.uint16.maxError, 428 - ); 429 - }); 430 - }); 431 - 432 - describe('integerUint32', () => { 433 - it('should validate values within uint32 range', () => { 434 - const result = v.safeParse(generatedSchemas.vIntegerUint32, 4000000000); 435 - expect(result.success).toBe(true); 436 - }); 437 - 438 - it('should reject negative values', () => { 439 - const result = v.safeParse(generatedSchemas.vIntegerUint32, -1); 440 - expect(result.success).toBe(false); 441 - expect(result.issues![0].message).toContain( 442 - FORMAT_BOUNDS.uint32.minError, 443 - ); 444 - }); 445 - 446 - it('should reject values above uint32 maximum', () => { 447 - const result = v.safeParse(generatedSchemas.vIntegerUint32, 4294967296); 448 - expect(result.success).toBe(false); 449 - expect(result.issues![0].message).toContain( 450 - FORMAT_BOUNDS.uint32.maxError, 451 - ); 452 - }); 453 - }); 454 - 455 - describe('integerUint64', () => { 456 - it('should validate values within uint64 range and convert to BigInt', () => { 457 - const result = v.safeParse( 458 - generatedSchemas.vIntegerUint64, 459 - 1000000000000, 460 - ); 461 - expect(result.success).toBe(true); 462 - expect(typeof result.output).toBe('bigint'); 463 - }); 464 - 465 - it('should reject negative values', () => { 466 - const result = v.safeParse(generatedSchemas.vIntegerUint64, -1); 467 - expect(result.success).toBe(false); 468 - expect(result.issues![0].message).toContain( 469 - FORMAT_BOUNDS.uint64.minError, 470 - ); 471 - }); 472 - 473 - it('should reject values above uint64 maximum', () => { 474 - const result = v.safeParse( 475 - generatedSchemas.vIntegerUint64, 476 - '18446744073709551616', 477 - ); 478 - expect(result.success).toBe(false); 479 - expect(result.issues![0].message).toContain( 480 - FORMAT_BOUNDS.uint64.maxError, 481 - ); 482 - }); 483 - }); 484 - }); 485 - 486 - describe('String Type Format Validation', () => { 487 - describe('stringInt64', () => { 488 - it('should validate string values within int64 range and convert to BigInt', () => { 489 - const result = v.safeParse( 490 - generatedSchemas.vStringInt64, 491 - '1000000000000', 492 - ); 493 - expect(result.success).toBe(true); 494 - expect(typeof result.output).toBe('bigint'); 495 - }); 496 - 497 - it('should reject values below int64 minimum', () => { 498 - const result = v.safeParse( 499 - generatedSchemas.vStringInt64, 500 - '-9223372036854775809', 501 - ); 502 - expect(result.success).toBe(false); 503 - expect(result.issues![0].message).toContain( 504 - FORMAT_BOUNDS.int64.minError, 505 - ); 506 - }); 507 - 508 - it('should reject values above int64 maximum', () => { 509 - const result = v.safeParse( 510 - generatedSchemas.vStringInt64, 511 - '9223372036854775808', 512 - ); 513 - expect(result.success).toBe(false); 514 - expect(result.issues![0].message).toContain( 515 - FORMAT_BOUNDS.int64.maxError, 516 - ); 517 - }); 518 - }); 519 - 520 - describe('stringUint64', () => { 521 - it('should validate string values within uint64 range and convert to BigInt', () => { 522 - const result = v.safeParse( 523 - generatedSchemas.vStringUint64, 524 - '1000000000000', 525 - ); 526 - expect(result.success).toBe(true); 527 - expect(typeof result.output).toBe('bigint'); 528 - }); 529 - 530 - it('should reject negative values', () => { 531 - const result = v.safeParse(generatedSchemas.vStringUint64, '-1'); 532 - expect(result.success).toBe(false); 533 - expect(result.issues![0].message).toContain( 534 - FORMAT_BOUNDS.uint64.minError, 535 - ); 536 - }); 537 - 538 - it('should reject values above uint64 maximum', () => { 539 - const result = v.safeParse( 540 - generatedSchemas.vStringUint64, 541 - '18446744073709551616', 542 - ); 543 - expect(result.success).toBe(false); 544 - expect(result.issues![0].message).toContain( 545 - FORMAT_BOUNDS.uint64.maxError, 546 - ); 547 - }); 548 - }); 549 - }); 550 - });
-909
packages/openapi-ts-tests/main/test/plugins/valibot/test/numberTypeToValibotSchema/min-max-constraints.test.ts
··· 1 - import * as v from 'valibot'; 2 - import { beforeAll, describe, expect, it } from 'vitest'; 3 - 4 - import { setupValibotTest } from '../../test-helper'; 5 - 6 - describe('Number Type Min/Max Constraints Tests', () => { 7 - let generatedSchemas: any; 8 - 9 - beforeAll(async () => { 10 - generatedSchemas = await setupValibotTest(); 11 - }); 12 - 13 - describe('Basic Number Constraints', () => { 14 - describe('NumberWithMinimum', () => { 15 - it('should accept values at minimum boundary', () => { 16 - const result = v.safeParse(generatedSchemas.vNumberWithMinimum, 10); 17 - expect(result.success).toBe(true); 18 - }); 19 - 20 - it('should accept values above minimum', () => { 21 - const result = v.safeParse(generatedSchemas.vNumberWithMinimum, 15); 22 - expect(result.success).toBe(true); 23 - }); 24 - 25 - it('should reject values below minimum', () => { 26 - const result = v.safeParse(generatedSchemas.vNumberWithMinimum, 9); 27 - expect(result.success).toBe(false); 28 - }); 29 - }); 30 - 31 - describe('NumberWithMaximum', () => { 32 - it('should accept values at maximum boundary', () => { 33 - const result = v.safeParse(generatedSchemas.vNumberWithMaximum, 100); 34 - expect(result.success).toBe(true); 35 - }); 36 - 37 - it('should accept values below maximum', () => { 38 - const result = v.safeParse(generatedSchemas.vNumberWithMaximum, 50); 39 - expect(result.success).toBe(true); 40 - }); 41 - 42 - it('should reject values above maximum', () => { 43 - const result = v.safeParse(generatedSchemas.vNumberWithMaximum, 101); 44 - expect(result.success).toBe(false); 45 - }); 46 - }); 47 - 48 - describe('NumberWithMinMax', () => { 49 - it('should accept values within range', () => { 50 - const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 50); 51 - expect(result.success).toBe(true); 52 - }); 53 - 54 - it('should accept values at minimum boundary', () => { 55 - const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 0); 56 - expect(result.success).toBe(true); 57 - }); 58 - 59 - it('should accept values at maximum boundary', () => { 60 - const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 100); 61 - expect(result.success).toBe(true); 62 - }); 63 - 64 - it('should reject values below minimum', () => { 65 - const result = v.safeParse(generatedSchemas.vNumberWithMinMax, -1); 66 - expect(result.success).toBe(false); 67 - }); 68 - 69 - it('should reject values above maximum', () => { 70 - const result = v.safeParse(generatedSchemas.vNumberWithMinMax, 101); 71 - expect(result.success).toBe(false); 72 - }); 73 - }); 74 - }); 75 - 76 - describe('Basic Integer Constraints', () => { 77 - describe('IntegerWithMinimum', () => { 78 - it('should accept values at minimum boundary', () => { 79 - const result = v.safeParse(generatedSchemas.vIntegerWithMinimum, 5); 80 - expect(result.success).toBe(true); 81 - }); 82 - 83 - it('should accept values above minimum', () => { 84 - const result = v.safeParse(generatedSchemas.vIntegerWithMinimum, 10); 85 - expect(result.success).toBe(true); 86 - }); 87 - 88 - it('should reject values below minimum', () => { 89 - const result = v.safeParse(generatedSchemas.vIntegerWithMinimum, 4); 90 - expect(result.success).toBe(false); 91 - }); 92 - }); 93 - 94 - describe('IntegerWithMaximum', () => { 95 - it('should accept values at maximum boundary', () => { 96 - const result = v.safeParse(generatedSchemas.vIntegerWithMaximum, 999); 97 - expect(result.success).toBe(true); 98 - }); 99 - 100 - it('should accept values below maximum', () => { 101 - const result = v.safeParse(generatedSchemas.vIntegerWithMaximum, 500); 102 - expect(result.success).toBe(true); 103 - }); 104 - 105 - it('should reject values above maximum', () => { 106 - const result = v.safeParse(generatedSchemas.vIntegerWithMaximum, 1000); 107 - expect(result.success).toBe(false); 108 - }); 109 - }); 110 - 111 - describe('IntegerWithMinMax', () => { 112 - it('should accept values within range', () => { 113 - const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 500); 114 - expect(result.success).toBe(true); 115 - }); 116 - 117 - it('should accept values at minimum boundary', () => { 118 - const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 1); 119 - expect(result.success).toBe(true); 120 - }); 121 - 122 - it('should accept values at maximum boundary', () => { 123 - const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 999); 124 - expect(result.success).toBe(true); 125 - }); 126 - 127 - it('should reject values below minimum', () => { 128 - const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 0); 129 - expect(result.success).toBe(false); 130 - }); 131 - 132 - it('should reject values above maximum', () => { 133 - const result = v.safeParse(generatedSchemas.vIntegerWithMinMax, 1000); 134 - expect(result.success).toBe(false); 135 - }); 136 - }); 137 - }); 138 - 139 - describe('Exclusive Constraints', () => { 140 - describe('NumberWithExclusiveMin', () => { 141 - it('should accept values above exclusive minimum', () => { 142 - const result = v.safeParse( 143 - generatedSchemas.vNumberWithExclusiveMin, 144 - 0.1, 145 - ); 146 - expect(result.success).toBe(true); 147 - }); 148 - 149 - it('should reject values at exclusive minimum', () => { 150 - const result = v.safeParse(generatedSchemas.vNumberWithExclusiveMin, 0); 151 - expect(result.success).toBe(false); 152 - }); 153 - 154 - it('should reject values below exclusive minimum', () => { 155 - const result = v.safeParse( 156 - generatedSchemas.vNumberWithExclusiveMin, 157 - -1, 158 - ); 159 - expect(result.success).toBe(false); 160 - }); 161 - }); 162 - 163 - describe('NumberWithExclusiveMax', () => { 164 - it('should accept values below exclusive maximum', () => { 165 - const result = v.safeParse( 166 - generatedSchemas.vNumberWithExclusiveMax, 167 - 99.9, 168 - ); 169 - expect(result.success).toBe(true); 170 - }); 171 - 172 - it('should reject values at exclusive maximum', () => { 173 - const result = v.safeParse( 174 - generatedSchemas.vNumberWithExclusiveMax, 175 - 100, 176 - ); 177 - expect(result.success).toBe(false); 178 - }); 179 - 180 - it('should reject values above exclusive maximum', () => { 181 - const result = v.safeParse( 182 - generatedSchemas.vNumberWithExclusiveMax, 183 - 101, 184 - ); 185 - expect(result.success).toBe(false); 186 - }); 187 - }); 188 - 189 - describe('NumberWithExclusiveMinMax', () => { 190 - it('should accept values within exclusive range', () => { 191 - const result = v.safeParse( 192 - generatedSchemas.vNumberWithExclusiveMinMax, 193 - 0.5, 194 - ); 195 - expect(result.success).toBe(true); 196 - }); 197 - 198 - it('should reject values at exclusive minimum', () => { 199 - const result = v.safeParse( 200 - generatedSchemas.vNumberWithExclusiveMinMax, 201 - 0, 202 - ); 203 - expect(result.success).toBe(false); 204 - }); 205 - 206 - it('should reject values at exclusive maximum', () => { 207 - const result = v.safeParse( 208 - generatedSchemas.vNumberWithExclusiveMinMax, 209 - 1, 210 - ); 211 - expect(result.success).toBe(false); 212 - }); 213 - }); 214 - 215 - describe('IntegerWithExclusiveMin', () => { 216 - it('should accept values above exclusive minimum', () => { 217 - const result = v.safeParse( 218 - generatedSchemas.vIntegerWithExclusiveMin, 219 - 11, 220 - ); 221 - expect(result.success).toBe(true); 222 - }); 223 - 224 - it('should reject values at exclusive minimum', () => { 225 - const result = v.safeParse( 226 - generatedSchemas.vIntegerWithExclusiveMin, 227 - 10, 228 - ); 229 - expect(result.success).toBe(false); 230 - }); 231 - 232 - it('should reject values below exclusive minimum', () => { 233 - const result = v.safeParse( 234 - generatedSchemas.vIntegerWithExclusiveMin, 235 - 9, 236 - ); 237 - expect(result.success).toBe(false); 238 - }); 239 - }); 240 - 241 - describe('IntegerWithExclusiveMax', () => { 242 - it('should accept values below exclusive maximum', () => { 243 - const result = v.safeParse( 244 - generatedSchemas.vIntegerWithExclusiveMax, 245 - 49, 246 - ); 247 - expect(result.success).toBe(true); 248 - }); 249 - 250 - it('should reject values at exclusive maximum', () => { 251 - const result = v.safeParse( 252 - generatedSchemas.vIntegerWithExclusiveMax, 253 - 50, 254 - ); 255 - expect(result.success).toBe(false); 256 - }); 257 - 258 - it('should reject values above exclusive maximum', () => { 259 - const result = v.safeParse( 260 - generatedSchemas.vIntegerWithExclusiveMax, 261 - 51, 262 - ); 263 - expect(result.success).toBe(false); 264 - }); 265 - }); 266 - 267 - describe('IntegerWithExclusiveMinMax', () => { 268 - it('should accept values within exclusive range', () => { 269 - const result = v.safeParse( 270 - generatedSchemas.vIntegerWithExclusiveMinMax, 271 - 10, 272 - ); 273 - expect(result.success).toBe(true); 274 - }); 275 - 276 - it('should reject values at exclusive minimum', () => { 277 - const result = v.safeParse( 278 - generatedSchemas.vIntegerWithExclusiveMinMax, 279 - 5, 280 - ); 281 - expect(result.success).toBe(false); 282 - }); 283 - 284 - it('should reject values at exclusive maximum', () => { 285 - const result = v.safeParse( 286 - generatedSchemas.vIntegerWithExclusiveMinMax, 287 - 15, 288 - ); 289 - expect(result.success).toBe(false); 290 - }); 291 - }); 292 - }); 293 - 294 - describe('Mixed Constraints', () => { 295 - describe('NumberWithExclusiveMinInclusiveMax', () => { 296 - it('should accept values above exclusive minimum and at inclusive maximum', () => { 297 - const result = v.safeParse( 298 - generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 299 - 90, 300 - ); 301 - expect(result.success).toBe(true); 302 - }); 303 - 304 - it('should accept values above exclusive minimum and below inclusive maximum', () => { 305 - const result = v.safeParse( 306 - generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 307 - 50, 308 - ); 309 - expect(result.success).toBe(true); 310 - }); 311 - 312 - it('should reject values at exclusive minimum', () => { 313 - const result = v.safeParse( 314 - generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 315 - 10, 316 - ); 317 - expect(result.success).toBe(false); 318 - }); 319 - 320 - it('should reject values above inclusive maximum', () => { 321 - const result = v.safeParse( 322 - generatedSchemas.vNumberWithExclusiveMinInclusiveMax, 323 - 91, 324 - ); 325 - expect(result.success).toBe(false); 326 - }); 327 - }); 328 - 329 - describe('NumberWithInclusiveMinExclusiveMax', () => { 330 - it('should accept values at inclusive minimum and below exclusive maximum', () => { 331 - const result = v.safeParse( 332 - generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 333 - 20, 334 - ); 335 - expect(result.success).toBe(true); 336 - }); 337 - 338 - it('should accept values above inclusive minimum and below exclusive maximum', () => { 339 - const result = v.safeParse( 340 - generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 341 - 50, 342 - ); 343 - expect(result.success).toBe(true); 344 - }); 345 - 346 - it('should reject values below inclusive minimum', () => { 347 - const result = v.safeParse( 348 - generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 349 - 19, 350 - ); 351 - expect(result.success).toBe(false); 352 - }); 353 - 354 - it('should reject values at exclusive maximum', () => { 355 - const result = v.safeParse( 356 - generatedSchemas.vNumberWithInclusiveMinExclusiveMax, 357 - 80, 358 - ); 359 - expect(result.success).toBe(false); 360 - }); 361 - }); 362 - 363 - describe('IntegerWithExclusiveMinInclusiveMax', () => { 364 - it('should accept values above exclusive minimum and at inclusive maximum', () => { 365 - const result = v.safeParse( 366 - generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 367 - 50, 368 - ); 369 - expect(result.success).toBe(true); 370 - }); 371 - 372 - it('should accept values above exclusive minimum and below inclusive maximum', () => { 373 - const result = v.safeParse( 374 - generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 375 - 25, 376 - ); 377 - expect(result.success).toBe(true); 378 - }); 379 - 380 - it('should reject values at exclusive minimum', () => { 381 - const result = v.safeParse( 382 - generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 383 - 5, 384 - ); 385 - expect(result.success).toBe(false); 386 - }); 387 - 388 - it('should reject values above inclusive maximum', () => { 389 - const result = v.safeParse( 390 - generatedSchemas.vIntegerWithExclusiveMinInclusiveMax, 391 - 51, 392 - ); 393 - expect(result.success).toBe(false); 394 - }); 395 - }); 396 - 397 - describe('IntegerWithInclusiveMinExclusiveMax', () => { 398 - it('should accept values at inclusive minimum and below exclusive maximum', () => { 399 - const result = v.safeParse( 400 - generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 401 - 10, 402 - ); 403 - expect(result.success).toBe(true); 404 - }); 405 - 406 - it('should accept values above inclusive minimum and below exclusive maximum', () => { 407 - const result = v.safeParse( 408 - generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 409 - 55, 410 - ); 411 - expect(result.success).toBe(true); 412 - }); 413 - 414 - it('should reject values below inclusive minimum', () => { 415 - const result = v.safeParse( 416 - generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 417 - 9, 418 - ); 419 - expect(result.success).toBe(false); 420 - }); 421 - 422 - it('should reject values at exclusive maximum', () => { 423 - const result = v.safeParse( 424 - generatedSchemas.vIntegerWithInclusiveMinExclusiveMax, 425 - 100, 426 - ); 427 - expect(result.success).toBe(false); 428 - }); 429 - }); 430 - }); 431 - 432 - describe('Format-Specific Constraints (Int64)', () => { 433 - describe('Int64WithMinimum', () => { 434 - it('should accept BigInt values at minimum boundary', () => { 435 - const result = v.safeParse( 436 - generatedSchemas.vInt64WithMinimum, 437 - BigInt('-5000000000000'), 438 - ); 439 - expect(result.success).toBe(true); 440 - }); 441 - 442 - it('should accept BigInt values above minimum', () => { 443 - const result = v.safeParse( 444 - generatedSchemas.vInt64WithMinimum, 445 - BigInt('0'), 446 - ); 447 - expect(result.success).toBe(true); 448 - }); 449 - 450 - it('should reject BigInt values below minimum', () => { 451 - const result = v.safeParse( 452 - generatedSchemas.vInt64WithMinimum, 453 - BigInt('-5000000000001'), 454 - ); 455 - expect(result.success).toBe(false); 456 - }); 457 - }); 458 - 459 - describe('Int64WithMaximum', () => { 460 - it('should accept BigInt values at maximum boundary', () => { 461 - const result = v.safeParse( 462 - generatedSchemas.vInt64WithMaximum, 463 - BigInt('5000000000000'), 464 - ); 465 - expect(result.success).toBe(true); 466 - }); 467 - 468 - it('should accept BigInt values below maximum', () => { 469 - const result = v.safeParse( 470 - generatedSchemas.vInt64WithMaximum, 471 - BigInt('1000000000000'), 472 - ); 473 - expect(result.success).toBe(true); 474 - }); 475 - 476 - it('should reject BigInt values above maximum', () => { 477 - const result = v.safeParse( 478 - generatedSchemas.vInt64WithMaximum, 479 - BigInt('5000000000001'), 480 - ); 481 - expect(result.success).toBe(false); 482 - }); 483 - }); 484 - 485 - describe('Int64WithMinMax', () => { 486 - it('should accept BigInt values within range', () => { 487 - const result = v.safeParse( 488 - generatedSchemas.vInt64WithMinMax, 489 - BigInt('0'), 490 - ); 491 - expect(result.success).toBe(true); 492 - }); 493 - 494 - it('should accept BigInt values at minimum boundary', () => { 495 - const result = v.safeParse( 496 - generatedSchemas.vInt64WithMinMax, 497 - BigInt('-4000000000000'), 498 - ); 499 - expect(result.success).toBe(true); 500 - }); 501 - 502 - it('should accept BigInt values at maximum boundary', () => { 503 - const result = v.safeParse( 504 - generatedSchemas.vInt64WithMinMax, 505 - BigInt('4000000000000'), 506 - ); 507 - expect(result.success).toBe(true); 508 - }); 509 - 510 - it('should reject BigInt values below minimum', () => { 511 - const result = v.safeParse( 512 - generatedSchemas.vInt64WithMinMax, 513 - BigInt('-4000000000001'), 514 - ); 515 - expect(result.success).toBe(false); 516 - }); 517 - 518 - it('should reject BigInt values above maximum', () => { 519 - const result = v.safeParse( 520 - generatedSchemas.vInt64WithMinMax, 521 - BigInt('4000000000001'), 522 - ); 523 - expect(result.success).toBe(false); 524 - }); 525 - }); 526 - 527 - describe('Int64WithExclusiveMin', () => { 528 - it('should accept BigInt values above exclusive minimum', () => { 529 - const result = v.safeParse( 530 - generatedSchemas.vInt64WithExclusiveMin, 531 - BigInt('-2999999999999'), 532 - ); 533 - expect(result.success).toBe(true); 534 - }); 535 - 536 - it('should reject BigInt values at exclusive minimum', () => { 537 - const result = v.safeParse( 538 - generatedSchemas.vInt64WithExclusiveMin, 539 - BigInt('-3000000000000'), 540 - ); 541 - expect(result.success).toBe(false); 542 - }); 543 - }); 544 - 545 - describe('Int64WithExclusiveMax', () => { 546 - it('should accept BigInt values below exclusive maximum', () => { 547 - const result = v.safeParse( 548 - generatedSchemas.vInt64WithExclusiveMax, 549 - BigInt('2999999999999'), 550 - ); 551 - expect(result.success).toBe(true); 552 - }); 553 - 554 - it('should reject BigInt values at exclusive maximum', () => { 555 - const result = v.safeParse( 556 - generatedSchemas.vInt64WithExclusiveMax, 557 - BigInt('3000000000000'), 558 - ); 559 - expect(result.success).toBe(false); 560 - }); 561 - }); 562 - 563 - describe('Int64WithExclusiveMinMax', () => { 564 - it('should accept BigInt values within exclusive range', () => { 565 - const result = v.safeParse( 566 - generatedSchemas.vInt64WithExclusiveMinMax, 567 - BigInt('0'), 568 - ); 569 - expect(result.success).toBe(true); 570 - }); 571 - 572 - it('should reject BigInt values at exclusive minimum', () => { 573 - const result = v.safeParse( 574 - generatedSchemas.vInt64WithExclusiveMinMax, 575 - BigInt('-2000000000000'), 576 - ); 577 - expect(result.success).toBe(false); 578 - }); 579 - 580 - it('should reject BigInt values at exclusive maximum', () => { 581 - const result = v.safeParse( 582 - generatedSchemas.vInt64WithExclusiveMinMax, 583 - BigInt('2000000000000'), 584 - ); 585 - expect(result.success).toBe(false); 586 - }); 587 - }); 588 - 589 - describe('Int64WithExclusiveMinInclusiveMax', () => { 590 - it('should accept values above exclusive minimum and at inclusive maximum', () => { 591 - const result = v.safeParse( 592 - generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 593 - BigInt('6000000000000'), 594 - ); 595 - expect(result.success).toBe(true); 596 - }); 597 - 598 - it('should accept values above exclusive minimum and below inclusive maximum', () => { 599 - const result = v.safeParse( 600 - generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 601 - BigInt('0'), 602 - ); 603 - expect(result.success).toBe(true); 604 - }); 605 - 606 - it('should reject values at exclusive minimum', () => { 607 - const result = v.safeParse( 608 - generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 609 - BigInt('-6000000000000'), 610 - ); 611 - expect(result.success).toBe(false); 612 - }); 613 - 614 - it('should reject values above inclusive maximum', () => { 615 - const result = v.safeParse( 616 - generatedSchemas.vInt64WithExclusiveMinInclusiveMax, 617 - BigInt('6000000000001'), 618 - ); 619 - expect(result.success).toBe(false); 620 - }); 621 - }); 622 - 623 - describe('Int64WithInclusiveMinExclusiveMax', () => { 624 - it('should accept values at inclusive minimum and below exclusive maximum', () => { 625 - const result = v.safeParse( 626 - generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 627 - BigInt('-7000000000000'), 628 - ); 629 - expect(result.success).toBe(true); 630 - }); 631 - 632 - it('should accept values above inclusive minimum and below exclusive maximum', () => { 633 - const result = v.safeParse( 634 - generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 635 - BigInt('0'), 636 - ); 637 - expect(result.success).toBe(true); 638 - }); 639 - 640 - it('should reject values below inclusive minimum', () => { 641 - const result = v.safeParse( 642 - generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 643 - BigInt('-7000000000001'), 644 - ); 645 - expect(result.success).toBe(false); 646 - }); 647 - 648 - it('should reject values at exclusive maximum', () => { 649 - const result = v.safeParse( 650 - generatedSchemas.vInt64WithInclusiveMinExclusiveMax, 651 - BigInt('7000000000000'), 652 - ); 653 - expect(result.success).toBe(false); 654 - }); 655 - }); 656 - }); 657 - 658 - describe('Format-Specific Constraints (UInt64)', () => { 659 - describe('UInt64WithMinimum', () => { 660 - it('should accept BigInt values at minimum boundary', () => { 661 - const result = v.safeParse( 662 - generatedSchemas.vUInt64WithMinimum, 663 - BigInt('5000000000000'), 664 - ); 665 - expect(result.success).toBe(true); 666 - }); 667 - 668 - it('should accept BigInt values above minimum', () => { 669 - const result = v.safeParse( 670 - generatedSchemas.vUInt64WithMinimum, 671 - BigInt('8000000000000'), 672 - ); 673 - expect(result.success).toBe(true); 674 - }); 675 - 676 - it('should reject BigInt values below minimum', () => { 677 - const result = v.safeParse( 678 - generatedSchemas.vUInt64WithMinimum, 679 - BigInt('4999999999999'), 680 - ); 681 - expect(result.success).toBe(false); 682 - }); 683 - }); 684 - 685 - describe('UInt64WithMaximum', () => { 686 - it('should accept BigInt values at maximum boundary', () => { 687 - const result = v.safeParse( 688 - generatedSchemas.vUInt64WithMaximum, 689 - BigInt('15000000000000'), 690 - ); 691 - expect(result.success).toBe(true); 692 - }); 693 - 694 - it('should accept BigInt values below maximum', () => { 695 - const result = v.safeParse( 696 - generatedSchemas.vUInt64WithMaximum, 697 - BigInt('10000000000000'), 698 - ); 699 - expect(result.success).toBe(true); 700 - }); 701 - 702 - it('should reject BigInt values above maximum', () => { 703 - const result = v.safeParse( 704 - generatedSchemas.vUInt64WithMaximum, 705 - BigInt('15000000000001'), 706 - ); 707 - expect(result.success).toBe(false); 708 - }); 709 - }); 710 - 711 - describe('UInt64WithMinMax', () => { 712 - it('should accept BigInt values within range', () => { 713 - const result = v.safeParse( 714 - generatedSchemas.vUInt64WithMinMax, 715 - BigInt('5000000000000'), 716 - ); 717 - expect(result.success).toBe(true); 718 - }); 719 - 720 - it('should accept BigInt values at minimum boundary', () => { 721 - const result = v.safeParse( 722 - generatedSchemas.vUInt64WithMinMax, 723 - BigInt('1000000000000'), 724 - ); 725 - expect(result.success).toBe(true); 726 - }); 727 - 728 - it('should accept BigInt values at maximum boundary', () => { 729 - const result = v.safeParse( 730 - generatedSchemas.vUInt64WithMinMax, 731 - BigInt('10000000000000'), 732 - ); 733 - expect(result.success).toBe(true); 734 - }); 735 - 736 - it('should reject BigInt values below minimum', () => { 737 - const result = v.safeParse( 738 - generatedSchemas.vUInt64WithMinMax, 739 - BigInt('999999999999'), 740 - ); 741 - expect(result.success).toBe(false); 742 - }); 743 - 744 - it('should reject BigInt values above maximum', () => { 745 - const result = v.safeParse( 746 - generatedSchemas.vUInt64WithMinMax, 747 - BigInt('10000000000001'), 748 - ); 749 - expect(result.success).toBe(false); 750 - }); 751 - }); 752 - 753 - describe('UInt64WithExclusiveMin', () => { 754 - it('should accept BigInt values above exclusive minimum', () => { 755 - const result = v.safeParse( 756 - generatedSchemas.vUInt64WithExclusiveMin, 757 - BigInt('8000000000001'), 758 - ); 759 - expect(result.success).toBe(true); 760 - }); 761 - 762 - it('should reject BigInt values at exclusive minimum', () => { 763 - const result = v.safeParse( 764 - generatedSchemas.vUInt64WithExclusiveMin, 765 - BigInt('8000000000000'), 766 - ); 767 - expect(result.success).toBe(false); 768 - }); 769 - }); 770 - 771 - describe('UInt64WithExclusiveMax', () => { 772 - it('should accept BigInt values below exclusive maximum', () => { 773 - const result = v.safeParse( 774 - generatedSchemas.vUInt64WithExclusiveMax, 775 - BigInt('11999999999999'), 776 - ); 777 - expect(result.success).toBe(true); 778 - }); 779 - 780 - it('should reject BigInt values at exclusive maximum', () => { 781 - const result = v.safeParse( 782 - generatedSchemas.vUInt64WithExclusiveMax, 783 - BigInt('12000000000000'), 784 - ); 785 - expect(result.success).toBe(false); 786 - }); 787 - }); 788 - 789 - describe('UInt64WithExclusiveMinMax', () => { 790 - it('should accept BigInt values within exclusive range', () => { 791 - const result = v.safeParse( 792 - generatedSchemas.vUInt64WithExclusiveMinMax, 793 - BigInt('5000000000000'), 794 - ); 795 - expect(result.success).toBe(true); 796 - }); 797 - 798 - it('should reject BigInt values at exclusive minimum', () => { 799 - const result = v.safeParse( 800 - generatedSchemas.vUInt64WithExclusiveMinMax, 801 - BigInt('2000000000000'), 802 - ); 803 - expect(result.success).toBe(false); 804 - }); 805 - 806 - it('should reject BigInt values at exclusive maximum', () => { 807 - const result = v.safeParse( 808 - generatedSchemas.vUInt64WithExclusiveMinMax, 809 - BigInt('8000000000000'), 810 - ); 811 - expect(result.success).toBe(false); 812 - }); 813 - }); 814 - 815 - describe('UInt64WithExclusiveMinInclusiveMax', () => { 816 - it('should accept values above exclusive minimum and at inclusive maximum', () => { 817 - const result = v.safeParse( 818 - generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 819 - BigInt('13000000000000'), 820 - ); 821 - expect(result.success).toBe(true); 822 - }); 823 - 824 - it('should accept values above exclusive minimum and below inclusive maximum', () => { 825 - const result = v.safeParse( 826 - generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 827 - BigInt('8000000000000'), 828 - ); 829 - expect(result.success).toBe(true); 830 - }); 831 - 832 - it('should reject values at exclusive minimum', () => { 833 - const result = v.safeParse( 834 - generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 835 - BigInt('3000000000000'), 836 - ); 837 - expect(result.success).toBe(false); 838 - }); 839 - 840 - it('should reject values above inclusive maximum', () => { 841 - const result = v.safeParse( 842 - generatedSchemas.vUInt64WithExclusiveMinInclusiveMax, 843 - BigInt('13000000000001'), 844 - ); 845 - expect(result.success).toBe(false); 846 - }); 847 - }); 848 - 849 - describe('UInt64WithInclusiveMinExclusiveMax', () => { 850 - it('should accept values at inclusive minimum and below exclusive maximum', () => { 851 - const result = v.safeParse( 852 - generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 853 - BigInt('4000000000000'), 854 - ); 855 - expect(result.success).toBe(true); 856 - }); 857 - 858 - it('should accept values above inclusive minimum and below exclusive maximum', () => { 859 - const result = v.safeParse( 860 - generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 861 - BigInt('9000000000000'), 862 - ); 863 - expect(result.success).toBe(true); 864 - }); 865 - 866 - it('should reject values below inclusive minimum', () => { 867 - const result = v.safeParse( 868 - generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 869 - BigInt('3999999999999'), 870 - ); 871 - expect(result.success).toBe(false); 872 - }); 873 - 874 - it('should reject values at exclusive maximum', () => { 875 - const result = v.safeParse( 876 - generatedSchemas.vUInt64WithInclusiveMinExclusiveMax, 877 - BigInt('14000000000000'), 878 - ); 879 - expect(result.success).toBe(false); 880 - }); 881 - }); 882 - }); 883 - 884 - describe('Special Cases', () => { 885 - describe('PrecedenceTest', () => { 886 - it('should use exclusive constraints over inclusive (exclusive minimum takes precedence)', () => { 887 - // exclusiveMinimum: 5, minimum: 10 - exclusive should take precedence 888 - const result = v.safeParse(generatedSchemas.vPrecedenceTest, 6); 889 - expect(result.success).toBe(true); 890 - }); 891 - 892 - it('should use exclusive constraints over inclusive (exclusive maximum takes precedence)', () => { 893 - // exclusiveMaximum: 95, maximum: 90 - exclusive should take precedence 894 - const result = v.safeParse(generatedSchemas.vPrecedenceTest, 94); 895 - expect(result.success).toBe(true); 896 - }); 897 - 898 - it('should reject values at exclusive minimum boundary', () => { 899 - const result = v.safeParse(generatedSchemas.vPrecedenceTest, 5); 900 - expect(result.success).toBe(false); 901 - }); 902 - 903 - it('should reject values at exclusive maximum boundary', () => { 904 - const result = v.safeParse(generatedSchemas.vPrecedenceTest, 95); 905 - expect(result.success).toBe(false); 906 - }); 907 - }); 908 - }); 909 - });
-314
packages/openapi-ts-tests/main/test/plugins/valibot/test/objectAdditionalProperties/additional-properties.test.ts
··· 1 - import * as v from 'valibot'; 2 - import { beforeAll, describe, expect, it } from 'vitest'; 3 - 4 - import { setupValibotTest } from '../../test-helper'; 5 - 6 - describe('Object Additional Properties Tests', () => { 7 - let generatedSchemas: any; 8 - 9 - beforeAll(async () => { 10 - generatedSchemas = await setupValibotTest(); 11 - }); 12 - 13 - describe('ObjectWithAdditionalPropertiesString', () => { 14 - it('should preserve string additional properties in nested headers object', () => { 15 - const input = { 16 - headers: { 17 - Authorization: 'Bearer token', 18 - 'Content-Type': 'application/json', 19 - }, 20 - }; 21 - const result = v.safeParse( 22 - generatedSchemas.vObjectWithAdditionalPropertiesString, 23 - input, 24 - ); 25 - expect(result.success).toBe(true); 26 - if (result.success) { 27 - expect(result.output.headers).toEqual({ 28 - Authorization: 'Bearer token', 29 - 'Content-Type': 'application/json', 30 - }); 31 - } 32 - }); 33 - 34 - it('should reject non-string values in additional properties', () => { 35 - const input = { 36 - headers: { 37 - Authorization: 'Bearer token', 38 - Count: 123, // Invalid: should be string 39 - }, 40 - }; 41 - const result = v.safeParse( 42 - generatedSchemas.vObjectWithAdditionalPropertiesString, 43 - input, 44 - ); 45 - expect(result.success).toBe(false); 46 - }); 47 - 48 - it('should accept empty headers object', () => { 49 - const input = { 50 - headers: {}, 51 - }; 52 - const result = v.safeParse( 53 - generatedSchemas.vObjectWithAdditionalPropertiesString, 54 - input, 55 - ); 56 - expect(result.success).toBe(true); 57 - }); 58 - }); 59 - 60 - describe('ObjectOnlyAdditionalPropertiesString', () => { 61 - it('should preserve string additional properties', () => { 62 - const input = { 63 - key1: 'value1', 64 - key2: 'value2', 65 - key3: 'value3', 66 - }; 67 - const result = v.safeParse( 68 - generatedSchemas.vObjectOnlyAdditionalPropertiesString, 69 - input, 70 - ); 71 - expect(result.success).toBe(true); 72 - if (result.success) { 73 - expect(result.output).toEqual(input); 74 - } 75 - }); 76 - 77 - it('should reject non-string values', () => { 78 - const input = { 79 - key1: 'value1', 80 - key2: 123, // Invalid: should be string 81 - }; 82 - const result = v.safeParse( 83 - generatedSchemas.vObjectOnlyAdditionalPropertiesString, 84 - input, 85 - ); 86 - expect(result.success).toBe(false); 87 - }); 88 - }); 89 - 90 - describe('ObjectOnlyAdditionalPropertiesNumber', () => { 91 - it('should preserve number additional properties', () => { 92 - const input = { 93 - score1: 100, 94 - score2: 95.5, 95 - score3: 0, 96 - }; 97 - const result = v.safeParse( 98 - generatedSchemas.vObjectOnlyAdditionalPropertiesNumber, 99 - input, 100 - ); 101 - expect(result.success).toBe(true); 102 - if (result.success) { 103 - expect(result.output).toEqual(input); 104 - } 105 - }); 106 - 107 - it('should reject non-number values', () => { 108 - const input = { 109 - score1: 100, 110 - score2: 'invalid', // Invalid: should be number 111 - }; 112 - const result = v.safeParse( 113 - generatedSchemas.vObjectOnlyAdditionalPropertiesNumber, 114 - input, 115 - ); 116 - expect(result.success).toBe(false); 117 - }); 118 - }); 119 - 120 - describe('ObjectOnlyAdditionalPropertiesBoolean', () => { 121 - it('should preserve boolean additional properties', () => { 122 - const input = { 123 - flag1: true, 124 - flag2: false, 125 - flag3: true, 126 - }; 127 - const result = v.safeParse( 128 - generatedSchemas.vObjectOnlyAdditionalPropertiesBoolean, 129 - input, 130 - ); 131 - expect(result.success).toBe(true); 132 - if (result.success) { 133 - expect(result.output).toEqual(input); 134 - } 135 - }); 136 - 137 - it('should reject non-boolean values', () => { 138 - const input = { 139 - flag1: true, 140 - flag2: 'true', // Invalid: should be boolean 141 - }; 142 - const result = v.safeParse( 143 - generatedSchemas.vObjectOnlyAdditionalPropertiesBoolean, 144 - input, 145 - ); 146 - expect(result.success).toBe(false); 147 - }); 148 - }); 149 - 150 - describe('ObjectWithPropertiesAndAdditionalPropertiesNumber', () => { 151 - it('should preserve both named properties and additional properties', () => { 152 - const input = { 153 - count: 42, 154 - extra1: 1.5, 155 - extra2: 2.5, 156 - id: 'abc123', 157 - }; 158 - const result = v.safeParse( 159 - generatedSchemas.vObjectWithPropertiesAndAdditionalPropertiesNumber, 160 - input, 161 - ); 162 - if (!result.success) { 163 - console.log('Validation failed:', result.issues); 164 - } 165 - expect(result.success).toBe(true); 166 - if (result.success) { 167 - expect(result.output).toEqual(input); 168 - } 169 - }); 170 - 171 - it('should validate types of both named and additional properties', () => { 172 - const input = { 173 - count: 42, 174 - extra1: 'invalid', 175 - id: 'abc123', // Invalid: should be number 176 - }; 177 - const result = v.safeParse( 178 - generatedSchemas.vObjectWithPropertiesAndAdditionalPropertiesNumber, 179 - input, 180 - ); 181 - expect(result.success).toBe(false); 182 - }); 183 - 184 - it('should require named properties but allow empty additional properties', () => { 185 - const input = { 186 - count: 42, 187 - id: 'abc123', 188 - }; 189 - const result = v.safeParse( 190 - generatedSchemas.vObjectWithPropertiesAndAdditionalPropertiesNumber, 191 - input, 192 - ); 193 - expect(result.success).toBe(true); 194 - }); 195 - }); 196 - 197 - describe('ObjectWithAdditionalPropertiesObject', () => { 198 - it('should preserve nested object additional properties', () => { 199 - const input = { 200 - metadata: { 201 - field1: { value: 'test1' }, 202 - field2: { value: 'test2' }, 203 - }, 204 - }; 205 - const result = v.safeParse( 206 - generatedSchemas.vObjectWithAdditionalPropertiesObject, 207 - input, 208 - ); 209 - expect(result.success).toBe(true); 210 - if (result.success) { 211 - expect(result.output.metadata).toEqual({ 212 - field1: { value: 'test1' }, 213 - field2: { value: 'test2' }, 214 - }); 215 - } 216 - }); 217 - 218 - it('should validate nested object structure', () => { 219 - const input = { 220 - metadata: { 221 - field1: { value: 'test1' }, 222 - field2: { invalidKey: 'test2' }, // Object without required structure 223 - }, 224 - }; 225 - const result = v.safeParse( 226 - generatedSchemas.vObjectWithAdditionalPropertiesObject, 227 - input, 228 - ); 229 - // Should succeed as the nested object properties are optional 230 - expect(result.success).toBe(true); 231 - }); 232 - }); 233 - 234 - describe('ObjectOnlyAdditionalPropertiesObject', () => { 235 - it('should preserve object additional properties', () => { 236 - const input = { 237 - item1: { name: 'Item 1' }, 238 - item2: { name: 'Item 2' }, 239 - }; 240 - const result = v.safeParse( 241 - generatedSchemas.vObjectOnlyAdditionalPropertiesObject, 242 - input, 243 - ); 244 - expect(result.success).toBe(true); 245 - if (result.success) { 246 - expect(result.output).toEqual(input); 247 - } 248 - }); 249 - }); 250 - 251 - describe('ObjectWithAdditionalPropertiesFalse', () => { 252 - it('should accept object with only defined properties', () => { 253 - const input = { 254 - count: 42, 255 - id: 'abc123', 256 - }; 257 - const result = v.safeParse( 258 - generatedSchemas.vObjectWithAdditionalPropertiesFalse, 259 - input, 260 - ); 261 - expect(result.success).toBe(true); 262 - if (result.success) { 263 - expect(result.output).toEqual(input); 264 - } 265 - }); 266 - 267 - it('should reject object with additional properties', () => { 268 - const input = { 269 - count: 42, 270 - extra: 'not allowed', 271 - id: 'abc123', 272 - }; 273 - const result = v.safeParse( 274 - generatedSchemas.vObjectWithAdditionalPropertiesFalse, 275 - input, 276 - ); 277 - expect(result.success).toBe(false); 278 - }); 279 - }); 280 - 281 - describe('ObjectWithNestedAdditionalPropertiesFalse', () => { 282 - it('should accept object with correct nested properties', () => { 283 - const input = { 284 - membership: { 285 - calendar_membership_tier_id: 'tier_id', 286 - status: 'approved', 287 - }, 288 - }; 289 - const result = v.safeParse( 290 - generatedSchemas.vObjectWithNestedAdditionalPropertiesFalse, 291 - input, 292 - ); 293 - expect(result.success).toBe(true); 294 - if (result.success) { 295 - expect(result.output).toEqual(input); 296 - } 297 - }); 298 - 299 - it('should reject object with additional properties in nested object', () => { 300 - const input = { 301 - membership: { 302 - calendar_membership_tier_id: 'tier_id', 303 - extra: 'not allowed', 304 - status: 'approved', 305 - }, 306 - }; 307 - const result = v.safeParse( 308 - generatedSchemas.vObjectWithNestedAdditionalPropertiesFalse, 309 - input, 310 - ); 311 - expect(result.success).toBe(false); 312 - }); 313 - }); 314 - });
-211
packages/openapi-ts-tests/main/test/plugins/valibot/test-helper.ts
··· 1 - /** 2 - * Test helper for Valibot plugin tests 3 - * Provides common functionality for schema generation and loading 4 - */ 5 - 6 - import fs from 'node:fs'; 7 - import path from 'node:path'; 8 - 9 - import { createClient } from '@hey-api/openapi-ts'; 10 - import * as v from 'valibot'; 11 - 12 - /** 13 - * Detect test name from the calling file 14 - */ 15 - function detectTestName(): string { 16 - const stack = new Error().stack; 17 - if (!stack) { 18 - throw new Error('Unable to detect test name: no stack trace available'); 19 - } 20 - 21 - // Find the first stack frame that contains a .test.ts file 22 - const testFileMatch = stack.match(/([^\\/]+)\.test\.ts/); 23 - if (!testFileMatch || !testFileMatch[1]) { 24 - throw new Error( 25 - 'Unable to detect test name: no .test.ts file found in stack trace', 26 - ); 27 - } 28 - 29 - return testFileMatch[1]; 30 - } 31 - 32 - /** 33 - * Detect base directory from the calling file 34 - */ 35 - function detectBaseDir(): string { 36 - const stack = new Error().stack; 37 - if (!stack) { 38 - throw new Error( 39 - 'Unable to detect base directory: no stack trace available', 40 - ); 41 - } 42 - 43 - // Try multiple regex patterns to match different stack trace formats 44 - const patterns = [ 45 - /at .* \(([^)]+\.test\.ts):\d+:\d+\)/, // Original pattern 46 - /at ([^:]+\.test\.ts):\d+:\d+/, // Alternative pattern without parentheses 47 - /([^:\s]+\.test\.ts):\d+:\d+/, // Simple pattern 48 - ]; 49 - 50 - for (const pattern of patterns) { 51 - const testFileMatch = stack.match(pattern); 52 - if (testFileMatch && testFileMatch[1]) { 53 - return path.dirname(testFileMatch[1]); 54 - } 55 - } 56 - 57 - throw new Error( 58 - 'Unable to detect base directory: no .test.ts file found in stack trace', 59 - ); 60 - } 61 - 62 - /** 63 - * Detect function name from the test file path 64 - * Extracts the directory name between 'test/' and the test file 65 - * e.g., from 'test/plugins/valibot/test/numberTypeToValibotSchema/formats.test.ts' 66 - * extracts 'numberTypeToValibotSchema' 67 - */ 68 - function detectFunctionName(): string { 69 - const stack = new Error().stack; 70 - if (!stack) { 71 - throw new Error('Unable to detect function name: no stack trace available'); 72 - } 73 - 74 - // Try multiple regex patterns to match different stack trace formats 75 - const patterns = [ 76 - /at .* \(([^)]+\.test\.ts):\d+:\d+\)/, // Original pattern 77 - /at ([^:]+\.test\.ts):\d+:\d+/, // Alternative pattern without parentheses 78 - /([^:\s]+\.test\.ts):\d+:\d+/, // Simple pattern 79 - ]; 80 - 81 - for (const pattern of patterns) { 82 - const testFileMatch = stack.match(pattern); 83 - if (testFileMatch && testFileMatch[1]) { 84 - const testFilePath = testFileMatch[1]; 85 - 86 - // Extract function name from path pattern: .../test/[FUNCTION_NAME]/[TEST_NAME].test.ts 87 - const pathParts = testFilePath.split(/[/\\]/); 88 - const testIndex = pathParts.lastIndexOf('test'); 89 - 90 - if (testIndex !== -1 && testIndex < pathParts.length - 2) { 91 - const functionName = pathParts[testIndex + 1]; 92 - if (functionName) { 93 - return functionName; 94 - } 95 - } 96 - 97 - throw new Error( 98 - `Unable to extract function name from test path: ${testFilePath}\n` + 99 - `Expected path pattern: .../test/[FUNCTION_NAME]/[TEST_NAME].test.ts`, 100 - ); 101 - } 102 - } 103 - 104 - throw new Error( 105 - 'Unable to detect function name: no .test.ts file found in stack trace', 106 - ); 107 - } 108 - 109 - /** 110 - * Load and evaluate the generated schemas 111 - */ 112 - function loadGeneratedSchemas(generatedPath: string): any { 113 - if (!fs.existsSync(generatedPath)) { 114 - throw new Error( 115 - `Generated schema file not found: ${generatedPath}\n` + 116 - `Schema generation may have failed. Check the input schema file for errors.`, 117 - ); 118 - } 119 - 120 - try { 121 - const generatedCode = fs.readFileSync(generatedPath, 'utf-8'); 122 - 123 - // Extract all export statements and create a proper return object 124 - const exportMatches = generatedCode.match(/export const (\w+)/g); 125 - if (!exportMatches) { 126 - // noinspection ExceptionCaughtLocallyJS 127 - throw new Error('No exported schemas found in generated code'); 128 - } 129 - 130 - // Create evaluation code that returns an object with all exports 131 - const schemaNames = exportMatches.map((match: string) => 132 - match.replace('export const ', ''), 133 - ); 134 - const evalCode = 135 - generatedCode 136 - .replace(/import \* as v from 'valibot';/, '') 137 - .replace(/export const/g, 'const') 138 - .replace(/v\./g, 'vModule.') + 139 - `\n\nreturn { ${schemaNames.join(', ')} };`; 140 - 141 - // Wrap in a function to capture the return value 142 - const schemaFunction = new Function('vModule', evalCode); 143 - return schemaFunction(v); 144 - } catch (error) { 145 - throw new Error( 146 - `Failed to load generated schemas from ${generatedPath}: ${error instanceof Error ? error.message : String(error)}\n` + 147 - `The generated file may contain syntax errors or be malformed.`, 148 - ); 149 - } 150 - } 151 - 152 - /** 153 - * Setup function for Valibot tests 154 - * Automatically detects test name and paths, generates schemas, and returns them 155 - */ 156 - export async function setupValibotTest(): Promise<any> { 157 - // Detect test name, function name, and base directory from calling file 158 - const testName = detectTestName(); 159 - const functionName = detectFunctionName(); 160 - const baseDir = detectBaseDir(); 161 - 162 - // Construct paths dynamically based on detected function name 163 - const schemaPath = path.join( 164 - baseDir, 165 - '..', 166 - '..', 167 - 'spec', 168 - functionName, 169 - `${testName}.yaml`, 170 - ); 171 - const outputPath = path.join( 172 - baseDir, 173 - '..', 174 - '..', 175 - 'generated', 176 - functionName, 177 - testName, 178 - ); 179 - 180 - // Check if spec file exists 181 - if (!fs.existsSync(schemaPath)) { 182 - throw new Error( 183 - `Schema file not found: ${schemaPath}\n` + 184 - `Expected schema file for test '${testName}' in function '${functionName}' at the above location.\n` + 185 - `Please ensure the spec file exists and matches the test name.`, 186 - ); 187 - } 188 - 189 - try { 190 - // Create output directory 191 - fs.mkdirSync(outputPath, { recursive: true }); 192 - 193 - // Generate Valibot schemas 194 - await createClient({ 195 - input: schemaPath, 196 - logs: { level: 'silent' }, 197 - output: outputPath, 198 - plugins: ['valibot'], 199 - }); 200 - 201 - // Load and return the generated schemas 202 - const generatedPath = path.join(outputPath, 'valibot.gen.ts'); 203 - return loadGeneratedSchemas(generatedPath); 204 - } catch (error) { 205 - throw new Error( 206 - `Failed to generate schemas for test '${testName}' in function '${functionName}': ${error instanceof Error ? error.message : String(error)}\n` + 207 - `Schema path: ${schemaPath}\n` + 208 - `Output path: ${outputPath}`, 209 - ); 210 - } 211 - }
+80
packages/openapi-ts-tests/main/test/test-helper.ts
··· 1 + import fs from 'node:fs'; 2 + import path from 'node:path'; 3 + import { fileURLToPath } from 'node:url'; 4 + 5 + import { createClient } from '@hey-api/openapi-ts'; 6 + import * as v from 'valibot'; 7 + 8 + import { getSpecsPath } from '../../utils'; 9 + 10 + const __filename = fileURLToPath(import.meta.url); 11 + const __dirname = path.dirname(__filename); 12 + 13 + const version = '3.1.x'; 14 + 15 + const outputDir = path.join(__dirname, 'generated', version); 16 + 17 + /** 18 + * Load and evaluate the generated schemas 19 + */ 20 + function loadGeneratedSchemas(generatedPath: string): any { 21 + if (!fs.existsSync(generatedPath)) { 22 + throw new Error( 23 + `Generated schema file not found: ${generatedPath}\n` + 24 + `Schema generation may have failed. Check the input schema file for errors.`, 25 + ); 26 + } 27 + 28 + try { 29 + const generatedCode = fs.readFileSync(generatedPath, 'utf-8'); 30 + 31 + // Extract all export statements and create a proper return object 32 + const exportMatches = generatedCode.match(/export const (\w+)/g); 33 + if (!exportMatches) { 34 + // noinspection ExceptionCaughtLocallyJS 35 + throw new Error('No exported schemas found in generated code'); 36 + } 37 + 38 + // Create evaluation code that returns an object with all exports 39 + const schemaNames = exportMatches.map((match: string) => 40 + match.replace('export const ', ''), 41 + ); 42 + const evalCode = 43 + generatedCode 44 + .replace(/import \* as v from 'valibot';/, '') 45 + .replace(/export const/g, 'const') 46 + .replace(/v\./g, 'vModule.') + 47 + `\n\nreturn { ${schemaNames.join(', ')} };`; 48 + 49 + // Wrap in a function to capture the return value 50 + const schemaFunction = new Function('vModule', evalCode); 51 + return schemaFunction(v); 52 + } catch (error) { 53 + throw new Error( 54 + `Failed to load generated schemas from ${generatedPath}: ${error instanceof Error ? error.message : String(error)}\n` + 55 + `The generated file may contain syntax errors or be malformed.`, 56 + ); 57 + } 58 + } 59 + 60 + // TODO: further clean up 61 + export async function setupValibotTest( 62 + input: string, 63 + output: string, 64 + ): Promise<any> { 65 + const inputPath = path.join(getSpecsPath(), version, input); 66 + const outputPath = path.join(outputDir, output); 67 + 68 + fs.mkdirSync(outputPath, { recursive: true }); 69 + 70 + await createClient({ 71 + input: inputPath, 72 + logs: { level: 'silent' }, 73 + output: outputPath, 74 + plugins: ['valibot'], 75 + }); 76 + 77 + // Load and return the generated schemas 78 + const generatedPath = path.join(outputPath, 'valibot.gen.ts'); 79 + return loadGeneratedSchemas(generatedPath); 80 + }
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/mini/default/zod.gen.ts
··· 722 722 export const zTypesData = z.object({ 723 723 body: z.optional(z.never()), 724 724 path: z.optional(z.object({ 725 - id: z.optional(z.int()) 725 + id: z.optional(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))) 726 726 })), 727 727 query: z.object({ 728 728 parameterNumber: z._default(z.number(), 123),
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/mini/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z._default(z.coerce.bigint(), BigInt(0)), 7 + foo: z._default(z.coerce.bigint().check(z.minimum(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }), z.maximum(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/v3/default/zod.gen.ts
··· 720 720 export const zTypesData = z.object({ 721 721 body: z.never().optional(), 722 722 path: z.object({ 723 - id: z.number().int().optional() 723 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional() 724 724 }).optional(), 725 725 query: z.object({ 726 726 parameterNumber: z.number().default(123),
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/v3/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.number().int().optional(), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { message: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { message: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/v4/default/zod.gen.ts
··· 722 722 export const zTypesData = z.object({ 723 723 body: z.optional(z.never()), 724 724 path: z.optional(z.object({ 725 - id: z.optional(z.int()) 725 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })) 726 726 })), 727 727 query: z.object({ 728 728 parameterNumber: z.number().default(123),
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/v4/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/mini/default/zod.gen.ts
··· 710 710 }); 711 711 712 712 export const zPageable = z.object({ 713 - page: z._default(z.optional(z.int().check(z.gte(0))), 0), 714 - size: z.optional(z.int().check(z.gte(1))), 713 + page: z._default(z.optional(z.int().check(z.gte(0), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 0), 714 + size: z.optional(z.int().check(z.gte(1), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 715 715 sort: z.optional(z.array(z.string())) 716 716 }); 717 717 ··· 1127 1127 }) 1128 1128 ]), z.object({ 1129 1129 baz: z.union([ 1130 - z.int().check(z.gte(0)), 1130 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1131 1131 z.null() 1132 1132 ]), 1133 - qux: z.int().check(z.gte(0)) 1133 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1134 1134 })); 1135 1135 1136 1136 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1138 1138 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1139 1139 ]), z.object({ 1140 1140 baz: z.union([ 1141 - z.int().check(z.gte(0)), 1141 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1142 1142 z.null() 1143 1143 ]), 1144 - qux: z.int().check(z.gte(0)) 1144 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1145 1145 })); 1146 1146 1147 1147 /** ··· 1585 1585 export const zTypesData = z.object({ 1586 1586 body: z.optional(z.never()), 1587 1587 path: z.optional(z.object({ 1588 - id: z.optional(z.int()) 1588 + id: z.optional(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))) 1589 1589 })), 1590 1590 query: z.object({ 1591 1591 parameterNumber: z._default(z.number(), 123), ··· 1731 1731 zModelWithDictionary 1732 1732 ]), 1733 1733 user: z.optional(z.readonly(z.object({ 1734 - id: z.optional(z.readonly(z.int())), 1734 + id: z.optional(z.readonly(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })))), 1735 1735 name: z.optional(z.readonly(z.union([ 1736 1736 z.readonly(z.string()), 1737 1737 z.null() ··· 1739 1739 }))) 1740 1740 })), 1741 1741 path: z.object({ 1742 - id: z.int(), 1742 + id: z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 1743 1743 'api-version': z.string() 1744 1744 }), 1745 1745 query: z.optional(z.never())
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/mini/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z._default(z.coerce.bigint(), BigInt(0)), 7 + foo: z._default(z.coerce.bigint().check(z.minimum(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }), z.maximum(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v3/default/zod.gen.ts
··· 708 708 }); 709 709 710 710 export const zPageable = z.object({ 711 - page: z.number().int().gte(0).optional().default(0), 712 - size: z.number().int().gte(1).optional(), 711 + page: z.number().int().gte(0).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional().default(0), 712 + size: z.number().int().gte(1).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(), 713 713 sort: z.array(z.string()).optional() 714 714 }); 715 715 ··· 1125 1125 }) 1126 1126 ]), z.object({ 1127 1127 baz: z.union([ 1128 - z.number().int().gte(0), 1128 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1129 1129 z.null() 1130 1130 ]), 1131 - qux: z.number().int().gte(0) 1131 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1132 1132 })); 1133 1133 1134 1134 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1136 1136 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1137 1137 ]), z.object({ 1138 1138 baz: z.union([ 1139 - z.number().int().gte(0), 1139 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1140 1140 z.null() 1141 1141 ]), 1142 - qux: z.number().int().gte(0) 1142 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1143 1143 })); 1144 1144 1145 1145 /** ··· 1583 1583 export const zTypesData = z.object({ 1584 1584 body: z.never().optional(), 1585 1585 path: z.object({ 1586 - id: z.number().int().optional() 1586 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional() 1587 1587 }).optional(), 1588 1588 query: z.object({ 1589 1589 parameterNumber: z.number().default(123), ··· 1729 1729 zModelWithDictionary 1730 1730 ]), 1731 1731 user: z.object({ 1732 - id: z.number().int().readonly().optional(), 1732 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly().optional(), 1733 1733 name: z.union([ 1734 1734 z.string().readonly(), 1735 1735 z.null() ··· 1737 1737 }).readonly().optional() 1738 1738 }).optional(), 1739 1739 path: z.object({ 1740 - id: z.number().int(), 1740 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }), 1741 1741 'api-version': z.string() 1742 1742 }), 1743 1743 query: z.never().optional()
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v3/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.number().int().optional(), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { message: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { message: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v4/default/zod.gen.ts
··· 710 710 }); 711 711 712 712 export const zPageable = z.object({ 713 - page: z.optional(z.int().gte(0)).default(0), 714 - size: z.optional(z.int().gte(1)), 713 + page: z.optional(z.int().gte(0).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })).default(0), 714 + size: z.optional(z.int().gte(1).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 715 715 sort: z.optional(z.array(z.string())) 716 716 }); 717 717 ··· 1127 1127 }) 1128 1128 ]), z.object({ 1129 1129 baz: z.union([ 1130 - z.int().gte(0), 1130 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1131 1131 z.null() 1132 1132 ]), 1133 - qux: z.int().gte(0) 1133 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1134 1134 })); 1135 1135 1136 1136 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1138 1138 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1139 1139 ]), z.object({ 1140 1140 baz: z.union([ 1141 - z.int().gte(0), 1141 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1142 1142 z.null() 1143 1143 ]), 1144 - qux: z.int().gte(0) 1144 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1145 1145 })); 1146 1146 1147 1147 /** ··· 1585 1585 export const zTypesData = z.object({ 1586 1586 body: z.optional(z.never()), 1587 1587 path: z.optional(z.object({ 1588 - id: z.optional(z.int()) 1588 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })) 1589 1589 })), 1590 1590 query: z.object({ 1591 1591 parameterNumber: z.number().default(123), ··· 1731 1731 zModelWithDictionary 1732 1732 ]), 1733 1733 user: z.optional(z.object({ 1734 - id: z.optional(z.int().readonly()), 1734 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly()), 1735 1735 name: z.optional(z.union([ 1736 1736 z.string().readonly(), 1737 1737 z.null() ··· 1739 1739 }).readonly()) 1740 1740 })), 1741 1741 path: z.object({ 1742 - id: z.int(), 1742 + id: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }), 1743 1743 'api-version': z.string() 1744 1744 }), 1745 1745 query: z.optional(z.never())
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v4/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/default/zod.gen.ts
··· 707 707 }); 708 708 709 709 export const zPageable = z.object({ 710 - page: z._default(z.optional(z.int().check(z.gte(0))), 0), 711 - size: z.optional(z.int().check(z.gte(1))), 710 + page: z._default(z.optional(z.int().check(z.gte(0), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 0), 711 + size: z.optional(z.int().check(z.gte(1), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 712 712 sort: z.optional(z.array(z.string())) 713 713 }); 714 714 ··· 1133 1133 }) 1134 1134 ]), z.object({ 1135 1135 baz: z.union([ 1136 - z.int().check(z.gte(0)), 1136 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1137 1137 z.null() 1138 1138 ]), 1139 - qux: z.int().check(z.gte(0)) 1139 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1140 1140 })); 1141 1141 1142 1142 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1144 1144 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1145 1145 ]), z.object({ 1146 1146 baz: z.union([ 1147 - z.int().check(z.gte(0)), 1147 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1148 1148 z.null() 1149 1149 ]), 1150 - qux: z.int().check(z.gte(0)) 1150 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1151 1151 })); 1152 1152 1153 1153 /** ··· 1600 1600 export const zTypesData = z.object({ 1601 1601 body: z.optional(z.never()), 1602 1602 path: z.optional(z.object({ 1603 - id: z.optional(z.int()) 1603 + id: z.optional(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))) 1604 1604 })), 1605 1605 query: z.object({ 1606 1606 parameterNumber: z._default(z.number(), 123), ··· 1747 1747 zModelWithDictionary 1748 1748 ]), 1749 1749 user: z.optional(z.readonly(z.object({ 1750 - id: z.optional(z.readonly(z.int())), 1750 + id: z.optional(z.readonly(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })))), 1751 1751 name: z.optional(z.readonly(z.union([ 1752 1752 z.readonly(z.string()), 1753 1753 z.null() ··· 1755 1755 }))) 1756 1756 })), 1757 1757 path: z.object({ 1758 - id: z.int(), 1758 + id: z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 1759 1759 'api-version': z.string() 1760 1760 }), 1761 1761 query: z.optional(z.never())
+7 -7
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/schema-const/zod.gen.ts
··· 15 15 z.literal(true) 16 16 ])), 17 17 corge: z.optional(z.record(z.string(), z.unknown())), 18 - garply: z.optional(z.coerce.bigint()), 18 + garply: z.optional(z.literal(BigInt('10'))), 19 19 numberInt8: z.optional(z.literal(100)), 20 20 numberInt16: z.optional(z.literal(1000)), 21 21 numberInt32: z.optional(z.literal(100000)), 22 - numberInt64: z.optional(z.literal(1000000000000)), 22 + numberInt64: z.optional(z.literal(BigInt(1000000000000))), 23 23 numberUint8: z.optional(z.literal(200)), 24 24 numberUint16: z.optional(z.literal(50000)), 25 25 numberUint32: z.optional(z.literal(3000000000)), 26 - numberUint64: z.optional(z.literal(18000000000000000000)), 26 + numberUint64: z.optional(z.literal(BigInt(18000000000000000000))), 27 27 integerInt8: z.optional(z.literal(-100)), 28 28 integerInt16: z.optional(z.literal(-1000)), 29 29 integerInt32: z.optional(z.literal(-100000)), 30 - integerInt64: z.optional(z.literal(-1000000000000)), 30 + integerInt64: z.optional(z.literal(BigInt(-1000000000000))), 31 31 integerUint8: z.optional(z.literal(255)), 32 32 integerUint16: z.optional(z.literal(65535)), 33 33 integerUint32: z.optional(z.literal(4294967295)), 34 - integerUint64: z.optional(z.int()), 35 - stringInt64: z.optional(z.literal('-9223372036854775808')), 36 - stringUint64: z.optional(z.literal('18446744073709551615')) 34 + integerUint64: z.optional(z.literal(BigInt('18446744073709551615'))), 35 + stringInt64: z.optional(z.literal(BigInt('-9223372036854775808'))), 36 + stringUint64: z.optional(z.literal(BigInt('18446744073709551615'))) 37 37 });
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z._default(z.coerce.bigint(), BigInt(0)), 7 + foo: z._default(z.coerce.bigint().check(z.minimum(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }), z.maximum(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/default/zod.gen.ts
··· 705 705 }); 706 706 707 707 export const zPageable = z.object({ 708 - page: z.number().int().gte(0).optional().default(0), 709 - size: z.number().int().gte(1).optional(), 708 + page: z.number().int().gte(0).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional().default(0), 709 + size: z.number().int().gte(1).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(), 710 710 sort: z.array(z.string()).optional() 711 711 }); 712 712 ··· 1131 1131 }) 1132 1132 ]), z.object({ 1133 1133 baz: z.union([ 1134 - z.number().int().gte(0), 1134 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1135 1135 z.null() 1136 1136 ]), 1137 - qux: z.number().int().gte(0) 1137 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1138 1138 })); 1139 1139 1140 1140 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1142 1142 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1143 1143 ]), z.object({ 1144 1144 baz: z.union([ 1145 - z.number().int().gte(0), 1145 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1146 1146 z.null() 1147 1147 ]), 1148 - qux: z.number().int().gte(0) 1148 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1149 1149 })); 1150 1150 1151 1151 /** ··· 1598 1598 export const zTypesData = z.object({ 1599 1599 body: z.never().optional(), 1600 1600 path: z.object({ 1601 - id: z.number().int().optional() 1601 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional() 1602 1602 }).optional(), 1603 1603 query: z.object({ 1604 1604 parameterNumber: z.number().default(123), ··· 1745 1745 zModelWithDictionary 1746 1746 ]), 1747 1747 user: z.object({ 1748 - id: z.number().int().readonly().optional(), 1748 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly().optional(), 1749 1749 name: z.union([ 1750 1750 z.string().readonly(), 1751 1751 z.null() ··· 1753 1753 }).readonly().optional() 1754 1754 }).optional(), 1755 1755 path: z.object({ 1756 - id: z.number().int(), 1756 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }), 1757 1757 'api-version': z.string() 1758 1758 }), 1759 1759 query: z.never().optional()
+7 -7
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/schema-const/zod.gen.ts
··· 15 15 z.literal(true) 16 16 ]).optional(), 17 17 corge: z.record(z.unknown()).optional(), 18 - garply: z.coerce.bigint().optional(), 18 + garply: z.literal(BigInt('10')).optional(), 19 19 numberInt8: z.literal(100).optional(), 20 20 numberInt16: z.literal(1000).optional(), 21 21 numberInt32: z.literal(100000).optional(), 22 - numberInt64: z.literal(1000000000000).optional(), 22 + numberInt64: z.literal(BigInt(1000000000000)).optional(), 23 23 numberUint8: z.literal(200).optional(), 24 24 numberUint16: z.literal(50000).optional(), 25 25 numberUint32: z.literal(3000000000).optional(), 26 - numberUint64: z.literal(18000000000000000000).optional(), 26 + numberUint64: z.literal(BigInt(18000000000000000000)).optional(), 27 27 integerInt8: z.literal(-100).optional(), 28 28 integerInt16: z.literal(-1000).optional(), 29 29 integerInt32: z.literal(-100000).optional(), 30 - integerInt64: z.literal(-1000000000000).optional(), 30 + integerInt64: z.literal(BigInt(-1000000000000)).optional(), 31 31 integerUint8: z.literal(255).optional(), 32 32 integerUint16: z.literal(65535).optional(), 33 33 integerUint32: z.literal(4294967295).optional(), 34 - integerUint64: z.number().int().optional(), 35 - stringInt64: z.literal('-9223372036854775808').optional(), 36 - stringUint64: z.literal('18446744073709551615').optional() 34 + integerUint64: z.literal(BigInt('18446744073709551615')).optional(), 35 + stringInt64: z.literal(BigInt('-9223372036854775808')).optional(), 36 + stringUint64: z.literal(BigInt('18446744073709551615')).optional() 37 37 });
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.number().int().optional(), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { message: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { message: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/default/zod.gen.ts
··· 707 707 }); 708 708 709 709 export const zPageable = z.object({ 710 - page: z.optional(z.int().gte(0)).default(0), 711 - size: z.optional(z.int().gte(1)), 710 + page: z.optional(z.int().gte(0).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })).default(0), 711 + size: z.optional(z.int().gte(1).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 712 712 sort: z.optional(z.array(z.string())) 713 713 }); 714 714 ··· 1133 1133 }) 1134 1134 ]), z.object({ 1135 1135 baz: z.union([ 1136 - z.int().gte(0), 1136 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1137 1137 z.null() 1138 1138 ]), 1139 - qux: z.int().gte(0) 1139 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1140 1140 })); 1141 1141 1142 1142 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1144 1144 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1145 1145 ]), z.object({ 1146 1146 baz: z.union([ 1147 - z.int().gte(0), 1147 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1148 1148 z.null() 1149 1149 ]), 1150 - qux: z.int().gte(0) 1150 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1151 1151 })); 1152 1152 1153 1153 /** ··· 1600 1600 export const zTypesData = z.object({ 1601 1601 body: z.optional(z.never()), 1602 1602 path: z.optional(z.object({ 1603 - id: z.optional(z.int()) 1603 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })) 1604 1604 })), 1605 1605 query: z.object({ 1606 1606 parameterNumber: z.number().default(123), ··· 1747 1747 zModelWithDictionary 1748 1748 ]), 1749 1749 user: z.optional(z.object({ 1750 - id: z.optional(z.int().readonly()), 1750 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly()), 1751 1751 name: z.optional(z.union([ 1752 1752 z.string().readonly(), 1753 1753 z.null() ··· 1755 1755 }).readonly()) 1756 1756 })), 1757 1757 path: z.object({ 1758 - id: z.int(), 1758 + id: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }), 1759 1759 'api-version': z.string() 1760 1760 }), 1761 1761 query: z.optional(z.never())
+7 -7
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/schema-const/zod.gen.ts
··· 15 15 z.literal(true) 16 16 ])), 17 17 corge: z.optional(z.record(z.string(), z.unknown())), 18 - garply: z.optional(z.coerce.bigint()), 18 + garply: z.optional(z.literal(BigInt('10'))), 19 19 numberInt8: z.optional(z.literal(100)), 20 20 numberInt16: z.optional(z.literal(1000)), 21 21 numberInt32: z.optional(z.literal(100000)), 22 - numberInt64: z.optional(z.literal(1000000000000)), 22 + numberInt64: z.optional(z.literal(BigInt(1000000000000))), 23 23 numberUint8: z.optional(z.literal(200)), 24 24 numberUint16: z.optional(z.literal(50000)), 25 25 numberUint32: z.optional(z.literal(3000000000)), 26 - numberUint64: z.optional(z.literal(18000000000000000000)), 26 + numberUint64: z.optional(z.literal(BigInt(18000000000000000000))), 27 27 integerInt8: z.optional(z.literal(-100)), 28 28 integerInt16: z.optional(z.literal(-1000)), 29 29 integerInt32: z.optional(z.literal(-100000)), 30 - integerInt64: z.optional(z.literal(-1000000000000)), 30 + integerInt64: z.optional(z.literal(BigInt(-1000000000000))), 31 31 integerUint8: z.optional(z.literal(255)), 32 32 integerUint16: z.optional(z.literal(65535)), 33 33 integerUint32: z.optional(z.literal(4294967295)), 34 - integerUint64: z.optional(z.int()), 35 - stringInt64: z.optional(z.literal('-9223372036854775808')), 36 - stringUint64: z.optional(z.literal('18446744073709551615')) 34 + integerUint64: z.optional(z.literal(BigInt('18446744073709551615'))), 35 + stringInt64: z.optional(z.literal(BigInt('-9223372036854775808'))), 36 + stringUint64: z.optional(z.literal(BigInt('18446744073709551615'))) 37 37 });
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/mini/default/zod.gen.ts
··· 722 722 export const zTypesData = z.object({ 723 723 body: z.optional(z.never()), 724 724 path: z.optional(z.object({ 725 - id: z.optional(z.int()) 725 + id: z.optional(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))) 726 726 })), 727 727 query: z.object({ 728 728 parameterNumber: z._default(z.number(), 123),
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/mini/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z._default(z.coerce.bigint(), BigInt(0)), 7 + foo: z._default(z.coerce.bigint().check(z.minimum(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }), z.maximum(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/v3/default/zod.gen.ts
··· 720 720 export const zTypesData = z.object({ 721 721 body: z.never().optional(), 722 722 path: z.object({ 723 - id: z.number().int().optional() 723 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional() 724 724 }).optional(), 725 725 query: z.object({ 726 726 parameterNumber: z.number().default(123),
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/v3/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.number().int().optional(), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { message: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { message: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/v4/default/zod.gen.ts
··· 722 722 export const zTypesData = z.object({ 723 723 body: z.optional(z.never()), 724 724 path: z.optional(z.object({ 725 - id: z.optional(z.int()) 725 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })) 726 726 })), 727 727 query: z.object({ 728 728 parameterNumber: z.number().default(123),
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/v4/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/mini/default/zod.gen.ts
··· 710 710 }); 711 711 712 712 export const zPageable = z.object({ 713 - page: z._default(z.optional(z.int().check(z.gte(0))), 0), 714 - size: z.optional(z.int().check(z.gte(1))), 713 + page: z._default(z.optional(z.int().check(z.gte(0), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 0), 714 + size: z.optional(z.int().check(z.gte(1), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 715 715 sort: z.optional(z.array(z.string())) 716 716 }); 717 717 ··· 1127 1127 }) 1128 1128 ]), z.object({ 1129 1129 baz: z.union([ 1130 - z.int().check(z.gte(0)), 1130 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1131 1131 z.null() 1132 1132 ]), 1133 - qux: z.int().check(z.gte(0)) 1133 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1134 1134 })); 1135 1135 1136 1136 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1138 1138 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1139 1139 ]), z.object({ 1140 1140 baz: z.union([ 1141 - z.int().check(z.gte(0)), 1141 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1142 1142 z.null() 1143 1143 ]), 1144 - qux: z.int().check(z.gte(0)) 1144 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1145 1145 })); 1146 1146 1147 1147 /** ··· 1585 1585 export const zTypesData = z.object({ 1586 1586 body: z.optional(z.never()), 1587 1587 path: z.optional(z.object({ 1588 - id: z.optional(z.int()) 1588 + id: z.optional(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))) 1589 1589 })), 1590 1590 query: z.object({ 1591 1591 parameterNumber: z._default(z.number(), 123), ··· 1731 1731 zModelWithDictionary 1732 1732 ]), 1733 1733 user: z.optional(z.readonly(z.object({ 1734 - id: z.optional(z.readonly(z.int())), 1734 + id: z.optional(z.readonly(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })))), 1735 1735 name: z.optional(z.readonly(z.union([ 1736 1736 z.readonly(z.string()), 1737 1737 z.null() ··· 1739 1739 }))) 1740 1740 })), 1741 1741 path: z.object({ 1742 - id: z.int(), 1742 + id: z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 1743 1743 'api-version': z.string() 1744 1744 }), 1745 1745 query: z.optional(z.never())
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/mini/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z._default(z.coerce.bigint(), BigInt(0)), 7 + foo: z._default(z.coerce.bigint().check(z.minimum(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }), z.maximum(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v3/default/zod.gen.ts
··· 708 708 }); 709 709 710 710 export const zPageable = z.object({ 711 - page: z.number().int().gte(0).optional().default(0), 712 - size: z.number().int().gte(1).optional(), 711 + page: z.number().int().gte(0).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional().default(0), 712 + size: z.number().int().gte(1).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(), 713 713 sort: z.array(z.string()).optional() 714 714 }); 715 715 ··· 1125 1125 }) 1126 1126 ]), z.object({ 1127 1127 baz: z.union([ 1128 - z.number().int().gte(0), 1128 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1129 1129 z.null() 1130 1130 ]), 1131 - qux: z.number().int().gte(0) 1131 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1132 1132 })); 1133 1133 1134 1134 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1136 1136 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1137 1137 ]), z.object({ 1138 1138 baz: z.union([ 1139 - z.number().int().gte(0), 1139 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1140 1140 z.null() 1141 1141 ]), 1142 - qux: z.number().int().gte(0) 1142 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1143 1143 })); 1144 1144 1145 1145 /** ··· 1583 1583 export const zTypesData = z.object({ 1584 1584 body: z.never().optional(), 1585 1585 path: z.object({ 1586 - id: z.number().int().optional() 1586 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional() 1587 1587 }).optional(), 1588 1588 query: z.object({ 1589 1589 parameterNumber: z.number().default(123), ··· 1729 1729 zModelWithDictionary 1730 1730 ]), 1731 1731 user: z.object({ 1732 - id: z.number().int().readonly().optional(), 1732 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly().optional(), 1733 1733 name: z.union([ 1734 1734 z.string().readonly(), 1735 1735 z.null() ··· 1737 1737 }).readonly().optional() 1738 1738 }).optional(), 1739 1739 path: z.object({ 1740 - id: z.number().int(), 1740 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }), 1741 1741 'api-version': z.string() 1742 1742 }), 1743 1743 query: z.never().optional()
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v3/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.number().int().optional(), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { message: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { message: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v4/default/zod.gen.ts
··· 710 710 }); 711 711 712 712 export const zPageable = z.object({ 713 - page: z.optional(z.int().gte(0)).default(0), 714 - size: z.optional(z.int().gte(1)), 713 + page: z.optional(z.int().gte(0).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })).default(0), 714 + size: z.optional(z.int().gte(1).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 715 715 sort: z.optional(z.array(z.string())) 716 716 }); 717 717 ··· 1127 1127 }) 1128 1128 ]), z.object({ 1129 1129 baz: z.union([ 1130 - z.int().gte(0), 1130 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1131 1131 z.null() 1132 1132 ]), 1133 - qux: z.int().gte(0) 1133 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1134 1134 })); 1135 1135 1136 1136 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1138 1138 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1139 1139 ]), z.object({ 1140 1140 baz: z.union([ 1141 - z.int().gte(0), 1141 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1142 1142 z.null() 1143 1143 ]), 1144 - qux: z.int().gte(0) 1144 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1145 1145 })); 1146 1146 1147 1147 /** ··· 1585 1585 export const zTypesData = z.object({ 1586 1586 body: z.optional(z.never()), 1587 1587 path: z.optional(z.object({ 1588 - id: z.optional(z.int()) 1588 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })) 1589 1589 })), 1590 1590 query: z.object({ 1591 1591 parameterNumber: z.number().default(123), ··· 1731 1731 zModelWithDictionary 1732 1732 ]), 1733 1733 user: z.optional(z.object({ 1734 - id: z.optional(z.int().readonly()), 1734 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly()), 1735 1735 name: z.optional(z.union([ 1736 1736 z.string().readonly(), 1737 1737 z.null() ··· 1739 1739 }).readonly()) 1740 1740 })), 1741 1741 path: z.object({ 1742 - id: z.int(), 1742 + id: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }), 1743 1743 'api-version': z.string() 1744 1744 }), 1745 1745 query: z.optional(z.never())
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v4/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/default/zod.gen.ts
··· 707 707 }); 708 708 709 709 export const zPageable = z.object({ 710 - page: z._default(z.optional(z.int().check(z.gte(0))), 0), 711 - size: z.optional(z.int().check(z.gte(1))), 710 + page: z._default(z.optional(z.int().check(z.gte(0), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 0), 711 + size: z.optional(z.int().check(z.gte(1), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))), 712 712 sort: z.optional(z.array(z.string())) 713 713 }); 714 714 ··· 1133 1133 }) 1134 1134 ]), z.object({ 1135 1135 baz: z.union([ 1136 - z.int().check(z.gte(0)), 1136 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1137 1137 z.null() 1138 1138 ]), 1139 - qux: z.int().check(z.gte(0)) 1139 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1140 1140 })); 1141 1141 1142 1142 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1144 1144 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1145 1145 ]), z.object({ 1146 1146 baz: z.union([ 1147 - z.int().check(z.gte(0)), 1147 + z.int().check(z.gte(0), z.maximum(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' })), 1148 1148 z.null() 1149 1149 ]), 1150 - qux: z.int().check(z.gte(0)) 1150 + qux: z.int().check(z.gte(0), z.maximum(255, { error: 'Invalid value: Expected uint8 to be <= 255' })) 1151 1151 })); 1152 1152 1153 1153 /** ··· 1600 1600 export const zTypesData = z.object({ 1601 1601 body: z.optional(z.never()), 1602 1602 path: z.optional(z.object({ 1603 - id: z.optional(z.int()) 1603 + id: z.optional(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }))) 1604 1604 })), 1605 1605 query: z.object({ 1606 1606 parameterNumber: z._default(z.number(), 123), ··· 1747 1747 zModelWithDictionary 1748 1748 ]), 1749 1749 user: z.optional(z.readonly(z.object({ 1750 - id: z.optional(z.readonly(z.int())), 1750 + id: z.optional(z.readonly(z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })))), 1751 1751 name: z.optional(z.readonly(z.union([ 1752 1752 z.readonly(z.string()), 1753 1753 z.null() ··· 1755 1755 }))) 1756 1756 })), 1757 1757 path: z.object({ 1758 - id: z.int(), 1758 + id: z.int().check(z.minimum(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }), z.maximum(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 1759 1759 'api-version': z.string() 1760 1760 }), 1761 1761 query: z.optional(z.never())
+7 -7
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/schema-const/zod.gen.ts
··· 15 15 z.literal(true) 16 16 ])), 17 17 corge: z.optional(z.record(z.string(), z.unknown())), 18 - garply: z.optional(z.coerce.bigint()), 18 + garply: z.optional(z.literal(BigInt('10'))), 19 19 numberInt8: z.optional(z.literal(100)), 20 20 numberInt16: z.optional(z.literal(1000)), 21 21 numberInt32: z.optional(z.literal(100000)), 22 - numberInt64: z.optional(z.literal(1000000000000)), 22 + numberInt64: z.optional(z.literal(BigInt(1000000000000))), 23 23 numberUint8: z.optional(z.literal(200)), 24 24 numberUint16: z.optional(z.literal(50000)), 25 25 numberUint32: z.optional(z.literal(3000000000)), 26 - numberUint64: z.optional(z.literal(18000000000000000000)), 26 + numberUint64: z.optional(z.literal(BigInt(18000000000000000000))), 27 27 integerInt8: z.optional(z.literal(-100)), 28 28 integerInt16: z.optional(z.literal(-1000)), 29 29 integerInt32: z.optional(z.literal(-100000)), 30 - integerInt64: z.optional(z.literal(-1000000000000)), 30 + integerInt64: z.optional(z.literal(BigInt(-1000000000000))), 31 31 integerUint8: z.optional(z.literal(255)), 32 32 integerUint16: z.optional(z.literal(65535)), 33 33 integerUint32: z.optional(z.literal(4294967295)), 34 - integerUint64: z.optional(z.int()), 35 - stringInt64: z.optional(z.literal('-9223372036854775808')), 36 - stringUint64: z.optional(z.literal('18446744073709551615')) 34 + integerUint64: z.optional(z.literal(BigInt('18446744073709551615'))), 35 + stringInt64: z.optional(z.literal(BigInt('-9223372036854775808'))), 36 + stringUint64: z.optional(z.literal(BigInt('18446744073709551615'))) 37 37 });
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z._default(z.coerce.bigint(), BigInt(0)), 7 + foo: z._default(z.coerce.bigint().check(z.minimum(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }), z.maximum(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })), BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/default/zod.gen.ts
··· 705 705 }); 706 706 707 707 export const zPageable = z.object({ 708 - page: z.number().int().gte(0).optional().default(0), 709 - size: z.number().int().gte(1).optional(), 708 + page: z.number().int().gte(0).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional().default(0), 709 + size: z.number().int().gte(1).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(), 710 710 sort: z.array(z.string()).optional() 711 711 }); 712 712 ··· 1131 1131 }) 1132 1132 ]), z.object({ 1133 1133 baz: z.union([ 1134 - z.number().int().gte(0), 1134 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1135 1135 z.null() 1136 1136 ]), 1137 - qux: z.number().int().gte(0) 1137 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1138 1138 })); 1139 1139 1140 1140 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1142 1142 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1143 1143 ]), z.object({ 1144 1144 baz: z.union([ 1145 - z.number().int().gte(0), 1145 + z.number().int().gte(0).max(65535, { message: 'Invalid value: Expected uint16 to be <= 65535' }), 1146 1146 z.null() 1147 1147 ]), 1148 - qux: z.number().int().gte(0) 1148 + qux: z.number().int().gte(0).max(255, { message: 'Invalid value: Expected uint8 to be <= 255' }) 1149 1149 })); 1150 1150 1151 1151 /** ··· 1598 1598 export const zTypesData = z.object({ 1599 1599 body: z.never().optional(), 1600 1600 path: z.object({ 1601 - id: z.number().int().optional() 1601 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).optional() 1602 1602 }).optional(), 1603 1603 query: z.object({ 1604 1604 parameterNumber: z.number().default(123), ··· 1745 1745 zModelWithDictionary 1746 1746 ]), 1747 1747 user: z.object({ 1748 - id: z.number().int().readonly().optional(), 1748 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly().optional(), 1749 1749 name: z.union([ 1750 1750 z.string().readonly(), 1751 1751 z.null() ··· 1753 1753 }).readonly().optional() 1754 1754 }).optional(), 1755 1755 path: z.object({ 1756 - id: z.number().int(), 1756 + id: z.number().int().min(-2147483648, { message: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { message: 'Invalid value: Expected int32 to be <= 2147483647' }), 1757 1757 'api-version': z.string() 1758 1758 }), 1759 1759 query: z.never().optional()
+7 -7
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/schema-const/zod.gen.ts
··· 15 15 z.literal(true) 16 16 ]).optional(), 17 17 corge: z.record(z.unknown()).optional(), 18 - garply: z.coerce.bigint().optional(), 18 + garply: z.literal(BigInt('10')).optional(), 19 19 numberInt8: z.literal(100).optional(), 20 20 numberInt16: z.literal(1000).optional(), 21 21 numberInt32: z.literal(100000).optional(), 22 - numberInt64: z.literal(1000000000000).optional(), 22 + numberInt64: z.literal(BigInt(1000000000000)).optional(), 23 23 numberUint8: z.literal(200).optional(), 24 24 numberUint16: z.literal(50000).optional(), 25 25 numberUint32: z.literal(3000000000).optional(), 26 - numberUint64: z.literal(18000000000000000000).optional(), 26 + numberUint64: z.literal(BigInt(18000000000000000000)).optional(), 27 27 integerInt8: z.literal(-100).optional(), 28 28 integerInt16: z.literal(-1000).optional(), 29 29 integerInt32: z.literal(-100000).optional(), 30 - integerInt64: z.literal(-1000000000000).optional(), 30 + integerInt64: z.literal(BigInt(-1000000000000)).optional(), 31 31 integerUint8: z.literal(255).optional(), 32 32 integerUint16: z.literal(65535).optional(), 33 33 integerUint32: z.literal(4294967295).optional(), 34 - integerUint64: z.number().int().optional(), 35 - stringInt64: z.literal('-9223372036854775808').optional(), 36 - stringUint64: z.literal('18446744073709551615').optional() 34 + integerUint64: z.literal(BigInt('18446744073709551615')).optional(), 35 + stringInt64: z.literal(BigInt('-9223372036854775808')).optional(), 36 + stringUint64: z.literal(BigInt('18446744073709551615')).optional() 37 37 });
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.number().int().optional(), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { message: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { message: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+9 -9
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/default/zod.gen.ts
··· 707 707 }); 708 708 709 709 export const zPageable = z.object({ 710 - page: z.optional(z.int().gte(0)).default(0), 711 - size: z.optional(z.int().gte(1)), 710 + page: z.optional(z.int().gte(0).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })).default(0), 711 + size: z.optional(z.int().gte(1).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })), 712 712 sort: z.optional(z.array(z.string())) 713 713 }); 714 714 ··· 1133 1133 }) 1134 1134 ]), z.object({ 1135 1135 baz: z.union([ 1136 - z.int().gte(0), 1136 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1137 1137 z.null() 1138 1138 ]), 1139 - qux: z.int().gte(0) 1139 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1140 1140 })); 1141 1141 1142 1142 export const zModelWithOneOfAndProperties = z.intersection(z.union([ ··· 1144 1144 zNonAsciiStringรฆรธรฅร†รธร…รถรดรชรŠๅญ—็ฌฆไธฒ 1145 1145 ]), z.object({ 1146 1146 baz: z.union([ 1147 - z.int().gte(0), 1147 + z.int().gte(0).max(65535, { error: 'Invalid value: Expected uint16 to be <= 65535' }), 1148 1148 z.null() 1149 1149 ]), 1150 - qux: z.int().gte(0) 1150 + qux: z.int().gte(0).max(255, { error: 'Invalid value: Expected uint8 to be <= 255' }) 1151 1151 })); 1152 1152 1153 1153 /** ··· 1600 1600 export const zTypesData = z.object({ 1601 1601 body: z.optional(z.never()), 1602 1602 path: z.optional(z.object({ 1603 - id: z.optional(z.int()) 1603 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })) 1604 1604 })), 1605 1605 query: z.object({ 1606 1606 parameterNumber: z.number().default(123), ··· 1747 1747 zModelWithDictionary 1748 1748 ]), 1749 1749 user: z.optional(z.object({ 1750 - id: z.optional(z.int().readonly()), 1750 + id: z.optional(z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).readonly()), 1751 1751 name: z.optional(z.union([ 1752 1752 z.string().readonly(), 1753 1753 z.null() ··· 1755 1755 }).readonly()) 1756 1756 })), 1757 1757 path: z.object({ 1758 - id: z.int(), 1758 + id: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }), 1759 1759 'api-version': z.string() 1760 1760 }), 1761 1761 query: z.optional(z.never())
+7 -7
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/schema-const/zod.gen.ts
··· 15 15 z.literal(true) 16 16 ])), 17 17 corge: z.optional(z.record(z.string(), z.unknown())), 18 - garply: z.optional(z.coerce.bigint()), 18 + garply: z.optional(z.literal(BigInt('10'))), 19 19 numberInt8: z.optional(z.literal(100)), 20 20 numberInt16: z.optional(z.literal(1000)), 21 21 numberInt32: z.optional(z.literal(100000)), 22 - numberInt64: z.optional(z.literal(1000000000000)), 22 + numberInt64: z.optional(z.literal(BigInt(1000000000000))), 23 23 numberUint8: z.optional(z.literal(200)), 24 24 numberUint16: z.optional(z.literal(50000)), 25 25 numberUint32: z.optional(z.literal(3000000000)), 26 - numberUint64: z.optional(z.literal(18000000000000000000)), 26 + numberUint64: z.optional(z.literal(BigInt(18000000000000000000))), 27 27 integerInt8: z.optional(z.literal(-100)), 28 28 integerInt16: z.optional(z.literal(-1000)), 29 29 integerInt32: z.optional(z.literal(-100000)), 30 - integerInt64: z.optional(z.literal(-1000000000000)), 30 + integerInt64: z.optional(z.literal(BigInt(-1000000000000))), 31 31 integerUint8: z.optional(z.literal(255)), 32 32 integerUint16: z.optional(z.literal(65535)), 33 33 integerUint32: z.optional(z.literal(4294967295)), 34 - integerUint64: z.optional(z.int()), 35 - stringInt64: z.optional(z.literal('-9223372036854775808')), 36 - stringUint64: z.optional(z.literal('18446744073709551615')) 34 + integerUint64: z.optional(z.literal(BigInt('18446744073709551615'))), 35 + stringInt64: z.optional(z.literal(BigInt('-9223372036854775808'))), 36 + stringUint64: z.optional(z.literal(BigInt('18446744073709551615'))) 37 37 });
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/type-format-zod/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 bar: z.optional(z.int()), 7 - foo: z.coerce.bigint().default(BigInt(0)), 7 + foo: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).default(BigInt(0)), 8 8 id: z.string() 9 9 }); 10 10
+54 -15
pnpm-lock.yaml
··· 137 137 specifier: 5.73.3 138 138 version: 5.73.3(vue@3.5.25(typescript@5.9.3)) 139 139 arktype: 140 - specifier: 2.1.28 141 - version: 2.1.28 140 + specifier: 2.1.29 141 + version: 2.1.29 142 142 swr: 143 143 specifier: 2.3.8 144 144 version: 2.3.8(react@19.0.0) ··· 1323 1323 specifier: 4.1.3 1324 1324 version: 4.1.3 1325 1325 c12: 1326 - specifier: 3.3.2 1327 - version: 3.3.2(magicast@0.3.5) 1326 + specifier: 3.3.3 1327 + version: 3.3.3(magicast@0.3.5) 1328 1328 color-support: 1329 1329 specifier: 1.1.3 1330 1330 version: 1.1.3 ··· 1480 1480 specifier: 8.17.1 1481 1481 version: 8.17.1 1482 1482 arktype: 1483 - specifier: 2.1.28 1484 - version: 2.1.28 1483 + specifier: 2.1.29 1484 + version: 2.1.29 1485 1485 axios: 1486 1486 specifier: 1.13.2 1487 1487 version: 1.13.2 ··· 7539 7539 resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} 7540 7540 engines: {node: '>= 0.4'} 7541 7541 7542 - arkregex@0.0.4: 7543 - resolution: {integrity: sha512-biS/FkvSwQq59TZ453piUp8bxMui11pgOMV9WHAnli1F8o0ayNCZzUwQadL/bGIUic5TkS/QlPcyMuI8ZIwedQ==} 7542 + arkregex@0.0.5: 7543 + resolution: {integrity: sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw==} 7544 7544 7545 - arktype@2.1.28: 7546 - resolution: {integrity: sha512-LVZqXl2zWRpNFnbITrtFmqeqNkPPo+KemuzbGSY6jvJwCb4v8NsDzrWOLHnQgWl26TkJeWWcUNUeBpq2Mst1/Q==} 7545 + arktype@2.1.29: 7546 + resolution: {integrity: sha512-jyfKk4xIOzvYNayqnD8ZJQqOwcrTOUbIU4293yrzAjA3O1dWh61j71ArMQ6tS/u4pD7vabSPe7nG3RCyoXW6RQ==} 7547 7547 7548 7548 array-buffer-byte-length@1.0.2: 7549 7549 resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} ··· 7824 7824 magicast: 7825 7825 optional: true 7826 7826 7827 + c12@3.3.3: 7828 + resolution: {integrity: sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==} 7829 + peerDependencies: 7830 + magicast: '*' 7831 + peerDependenciesMeta: 7832 + magicast: 7833 + optional: true 7834 + 7827 7835 cac@6.7.14: 7828 7836 resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 7829 7837 engines: {node: '>=8'} ··· 7906 7914 chokidar@4.0.3: 7907 7915 resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} 7908 7916 engines: {node: '>= 14.16.0'} 7917 + 7918 + chokidar@5.0.0: 7919 + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} 7920 + engines: {node: '>= 20.19.0'} 7909 7921 7910 7922 chownr@2.0.0: 7911 7923 resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} ··· 12129 12141 resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} 12130 12142 engines: {node: '>= 14.18.0'} 12131 12143 12144 + readdirp@5.0.0: 12145 + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} 12146 + engines: {node: '>= 20.19.0'} 12147 + 12132 12148 real-require@0.2.0: 12133 12149 resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} 12134 12150 engines: {node: '>= 12.13.0'} ··· 18904 18920 18905 18921 '@nuxt/kit@3.20.2(magicast@0.3.5)': 18906 18922 dependencies: 18907 - c12: 3.3.2(magicast@0.3.5) 18923 + c12: 3.3.3(magicast@0.3.5) 18908 18924 consola: 3.4.2 18909 18925 defu: 6.1.4 18910 18926 destr: 2.0.5 ··· 22023 22039 22024 22040 aria-query@5.3.2: {} 22025 22041 22026 - arkregex@0.0.4: 22042 + arkregex@0.0.5: 22027 22043 dependencies: 22028 22044 '@ark/util': 0.56.0 22029 22045 22030 - arktype@2.1.28: 22046 + arktype@2.1.29: 22031 22047 dependencies: 22032 22048 '@ark/schema': 0.56.0 22033 22049 '@ark/util': 0.56.0 22034 - arkregex: 0.0.4 22050 + arkregex: 0.0.5 22035 22051 22036 22052 array-buffer-byte-length@1.0.2: 22037 22053 dependencies: ··· 22453 22469 optionalDependencies: 22454 22470 magicast: 0.3.5 22455 22471 22472 + c12@3.3.3(magicast@0.3.5): 22473 + dependencies: 22474 + chokidar: 5.0.0 22475 + confbox: 0.2.2 22476 + defu: 6.1.4 22477 + dotenv: 17.2.3 22478 + exsolve: 1.0.8 22479 + giget: 2.0.0 22480 + jiti: 2.6.1 22481 + ohash: 2.0.11 22482 + pathe: 2.0.3 22483 + perfect-debounce: 2.0.0 22484 + pkg-types: 2.3.0 22485 + rc9: 2.1.2 22486 + optionalDependencies: 22487 + magicast: 0.3.5 22488 + 22456 22489 cac@6.7.14: {} 22457 22490 22458 22491 cacache@19.0.1: ··· 22548 22581 chokidar@4.0.3: 22549 22582 dependencies: 22550 22583 readdirp: 4.1.2 22584 + 22585 + chokidar@5.0.0: 22586 + dependencies: 22587 + readdirp: 5.0.0 22551 22588 22552 22589 chownr@2.0.0: {} 22553 22590 ··· 26294 26331 '@rollup/plugin-terser': 0.4.4(rollup@4.54.0) 26295 26332 '@vercel/nft': 0.29.4(encoding@0.1.13)(rollup@4.54.0) 26296 26333 archiver: 7.0.1 26297 - c12: 3.3.2(magicast@0.3.5) 26334 + c12: 3.3.3(magicast@0.3.5) 26298 26335 chokidar: 4.0.3 26299 26336 citty: 0.1.6 26300 26337 compatx: 0.2.0 ··· 28031 28068 picomatch: 2.3.1 28032 28069 28033 28070 readdirp@4.1.2: {} 28071 + 28072 + readdirp@5.0.0: {} 28034 28073 28035 28074 real-require@0.2.0: {} 28036 28075
+71
specs/3.1.x/additional-properties.yaml
··· 1 + openapi: 3.1.0 2 + info: 3 + title: OpenAPI 3.1.0 additional properties example 4 + version: '1' 5 + components: 6 + schemas: 7 + ObjectWithAdditionalPropertiesString: 8 + type: object 9 + properties: 10 + headers: 11 + type: object 12 + additionalProperties: 13 + type: string 14 + ObjectOnlyAdditionalPropertiesString: 15 + type: object 16 + additionalProperties: 17 + type: string 18 + ObjectOnlyAdditionalPropertiesNumber: 19 + type: object 20 + additionalProperties: 21 + type: number 22 + ObjectOnlyAdditionalPropertiesBoolean: 23 + type: object 24 + additionalProperties: 25 + type: boolean 26 + ObjectWithPropertiesAndAdditionalPropertiesNumber: 27 + type: object 28 + properties: 29 + id: 30 + type: string 31 + count: 32 + type: integer 33 + additionalProperties: 34 + type: number 35 + ObjectWithAdditionalPropertiesObject: 36 + type: object 37 + properties: 38 + metadata: 39 + type: object 40 + additionalProperties: 41 + type: object 42 + properties: 43 + value: 44 + type: string 45 + ObjectOnlyAdditionalPropertiesObject: 46 + type: object 47 + additionalProperties: 48 + type: object 49 + properties: 50 + name: 51 + type: string 52 + ObjectWithAdditionalPropertiesFalse: 53 + type: object 54 + properties: 55 + id: 56 + type: string 57 + count: 58 + type: integer 59 + additionalProperties: false 60 + ObjectWithNestedAdditionalPropertiesFalse: 61 + type: object 62 + properties: 63 + membership: 64 + type: object 65 + properties: 66 + status: 67 + type: string 68 + enum: [approved, declined, pending] 69 + calendar_membership_tier_id: 70 + type: string 71 + additionalProperties: false
-3
specs/3.1.x/array-items-all-of.yaml
··· 4 4 version: '1' 5 5 components: 6 6 schemas: 7 - # Test case 1: Array with allOf of object schemas 8 7 ArrayWithAllOfObjects: 9 8 type: array 10 9 items: ··· 17 16 properties: 18 17 name: 19 18 type: string 20 - # Test case 2: Array with allOf of primitives 21 19 ArrayWithAllOfPrimitives: 22 20 type: array 23 21 items: 24 22 allOf: 25 23 - type: number 26 24 - type: string 27 - # Test case 3: Array with allOf including refs 28 25 ArrayWithAllOfRefs: 29 26 type: array 30 27 items:
+92
specs/3.1.x/const-values.yaml
··· 1 + openapi: 3.1.0 2 + info: 3 + title: OpenAPI 3.1.0 const values example 4 + version: '1' 5 + components: 6 + schemas: 7 + NumberNoFormat: 8 + type: number 9 + const: 42.5 10 + IntegerNoFormat: 11 + type: integer 12 + const: -1 13 + NumberInt8: 14 + type: number 15 + format: int8 16 + const: 100 17 + NumberInt16: 18 + type: number 19 + format: int16 20 + const: 1000 21 + NumberInt32: 22 + type: number 23 + format: int32 24 + const: 100000 25 + NumberInt64: 26 + type: number 27 + format: int64 28 + const: 1000000000000 29 + NumberUint8: 30 + type: number 31 + format: uint8 32 + const: 200 33 + NumberUint16: 34 + type: number 35 + format: uint16 36 + const: 50000 37 + NumberUint32: 38 + type: number 39 + format: uint32 40 + const: 3000000000 41 + NumberUint64: 42 + type: number 43 + format: uint64 44 + const: 18000000000000000000 45 + IntegerInt8: 46 + type: integer 47 + format: int8 48 + const: -100 49 + IntegerInt16: 50 + type: integer 51 + format: int16 52 + const: -1000 53 + IntegerInt32: 54 + type: integer 55 + format: int32 56 + const: -100000 57 + IntegerInt64: 58 + type: integer 59 + format: int64 60 + const: -1000000000000 61 + IntegerUint8: 62 + type: integer 63 + format: uint8 64 + const: 255 65 + IntegerUint16: 66 + type: integer 67 + format: uint16 68 + const: 65535 69 + IntegerUint32: 70 + type: integer 71 + format: uint32 72 + const: 4294967295 73 + IntegerUint64: 74 + type: integer 75 + format: uint64 76 + const: 1000000000000 77 + StringInt64: 78 + type: string 79 + format: int64 80 + const: '-9223372036854775808' 81 + StringUint64: 82 + type: string 83 + format: uint64 84 + const: '18446744073709551615' 85 + StringInt64n: 86 + type: string 87 + format: int64 88 + const: '-9223372036854775808n' 89 + StringUint64n: 90 + type: string 91 + format: uint64 92 + const: '18446744073709551615n'
+64
specs/3.1.x/formats.yaml
··· 1 + openapi: 3.1.0 2 + info: 3 + title: OpenAPI 3.1.0 formats example 4 + version: '1' 5 + components: 6 + schemas: 7 + NumberNoFormat: 8 + type: number 9 + NumberInt8: 10 + type: number 11 + format: int8 12 + NumberInt16: 13 + type: number 14 + format: int16 15 + NumberInt32: 16 + type: number 17 + format: int32 18 + NumberInt64: 19 + type: number 20 + format: int64 21 + NumberUint8: 22 + type: number 23 + format: uint8 24 + NumberUint16: 25 + type: number 26 + format: uint16 27 + NumberUint32: 28 + type: number 29 + format: uint32 30 + NumberUint64: 31 + type: number 32 + format: uint64 33 + IntegerNoFormat: 34 + type: integer 35 + IntegerInt8: 36 + type: integer 37 + format: int8 38 + IntegerInt16: 39 + type: integer 40 + format: int16 41 + IntegerInt32: 42 + type: integer 43 + format: int32 44 + IntegerInt64: 45 + type: integer 46 + format: int64 47 + IntegerUint8: 48 + type: integer 49 + format: uint8 50 + IntegerUint16: 51 + type: integer 52 + format: uint16 53 + IntegerUint32: 54 + type: integer 55 + format: uint32 56 + IntegerUint64: 57 + type: integer 58 + format: uint64 59 + StringInt64: 60 + type: string 61 + format: int64 62 + StringUint64: 63 + type: string 64 + format: uint64
+140
specs/3.1.x/min-max-constraints.yaml
··· 1 + openapi: 3.1.0 2 + info: 3 + title: OpenAPI 3.1.0 min max constraints example 4 + version: '1' 5 + components: 6 + schemas: 7 + NumberWithMinimum: 8 + type: number 9 + minimum: 10 10 + NumberWithMaximum: 11 + type: number 12 + maximum: 100 13 + NumberWithMinMax: 14 + type: number 15 + minimum: 0 16 + maximum: 100 17 + IntegerWithMinimum: 18 + type: integer 19 + minimum: 5 20 + IntegerWithMaximum: 21 + type: integer 22 + maximum: 999 23 + IntegerWithMinMax: 24 + type: integer 25 + minimum: 1 26 + maximum: 999 27 + NumberWithExclusiveMin: 28 + type: number 29 + exclusiveMinimum: 0 30 + NumberWithExclusiveMax: 31 + type: number 32 + exclusiveMaximum: 100 33 + NumberWithExclusiveMinMax: 34 + type: number 35 + exclusiveMinimum: 0 36 + exclusiveMaximum: 1 37 + IntegerWithExclusiveMin: 38 + type: integer 39 + exclusiveMinimum: 10 40 + IntegerWithExclusiveMax: 41 + type: integer 42 + exclusiveMaximum: 50 43 + IntegerWithExclusiveMinMax: 44 + type: integer 45 + exclusiveMinimum: 5 46 + exclusiveMaximum: 15 47 + NumberWithExclusiveMinInclusiveMax: 48 + type: number 49 + exclusiveMinimum: 10 50 + maximum: 90 51 + NumberWithInclusiveMinExclusiveMax: 52 + type: number 53 + minimum: 20 54 + exclusiveMaximum: 80 55 + IntegerWithExclusiveMinInclusiveMax: 56 + type: integer 57 + exclusiveMinimum: 5 58 + maximum: 50 59 + IntegerWithInclusiveMinExclusiveMax: 60 + type: integer 61 + minimum: 10 62 + exclusiveMaximum: 100 63 + Int64WithMinimum: 64 + type: integer 65 + format: int64 66 + minimum: -5000000000000 67 + Int64WithMaximum: 68 + type: integer 69 + format: int64 70 + maximum: 5000000000000 71 + Int64WithMinMax: 72 + type: integer 73 + format: int64 74 + minimum: -4000000000000 75 + maximum: 4000000000000 76 + Int64WithExclusiveMin: 77 + type: integer 78 + format: int64 79 + exclusiveMinimum: -3000000000000 80 + Int64WithExclusiveMax: 81 + type: integer 82 + format: int64 83 + exclusiveMaximum: 3000000000000 84 + Int64WithExclusiveMinMax: 85 + type: integer 86 + format: int64 87 + exclusiveMinimum: -2000000000000 88 + exclusiveMaximum: 2000000000000 89 + Int64WithExclusiveMinInclusiveMax: 90 + type: integer 91 + format: int64 92 + exclusiveMinimum: -6000000000000 93 + maximum: 6000000000000 94 + Int64WithInclusiveMinExclusiveMax: 95 + type: integer 96 + format: int64 97 + minimum: -7000000000000 98 + exclusiveMaximum: 7000000000000 99 + UInt64WithMinimum: 100 + type: integer 101 + format: uint64 102 + minimum: 5000000000000 103 + UInt64WithMaximum: 104 + type: integer 105 + format: uint64 106 + maximum: 15000000000000 107 + UInt64WithMinMax: 108 + type: integer 109 + format: uint64 110 + minimum: 1000000000000 111 + maximum: 10000000000000 112 + UInt64WithExclusiveMin: 113 + type: integer 114 + format: uint64 115 + exclusiveMinimum: 8000000000000 116 + UInt64WithExclusiveMax: 117 + type: integer 118 + format: uint64 119 + exclusiveMaximum: 12000000000000 120 + UInt64WithExclusiveMinMax: 121 + type: integer 122 + format: uint64 123 + exclusiveMinimum: 2000000000000 124 + exclusiveMaximum: 8000000000000 125 + UInt64WithExclusiveMinInclusiveMax: 126 + type: integer 127 + format: uint64 128 + exclusiveMinimum: 3000000000000 129 + maximum: 13000000000000 130 + UInt64WithInclusiveMinExclusiveMax: 131 + type: integer 132 + format: uint64 133 + minimum: 4000000000000 134 + exclusiveMaximum: 14000000000000 135 + PrecedenceTest: 136 + type: number 137 + minimum: 10 138 + maximum: 90 139 + exclusiveMinimum: 5 140 + exclusiveMaximum: 95