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

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #2201 from hey-api/fix/plugin-transform

Zod: add `name` builders and `case` options

authored by

Lubos and committed by
GitHub
5e8f1be8 fcb77c96

+2274 -1525
+25
.changeset/famous-ducks-lay.md
··· 1 + --- 2 + '@hey-api/openapi-ts': minor 3 + --- 4 + 5 + feat(zod): generate a single schema for requests 6 + 7 + ### Single Zod schema per request 8 + 9 + Previously, we generated a separate schema for each endpoint parameter and request body. In v0.74.0, a single request schema is generated for the whole endpoint. It may contain a request body, parameters, and headers. 10 + 11 + ```ts 12 + const zData = z.object({ 13 + body: z.object({ 14 + foo: z.string().optional(), 15 + bar: z.union([z.number(), z.null()]).optional(), 16 + }).optional(), 17 + headers: z.never().optional(), 18 + path: z.object({ 19 + baz: z.string() 20 + }), 21 + query: z.never().optional() 22 + }); 23 + ``` 24 + 25 + If you need to access individual fields, you can do so using the [`.shape`](https://zod.dev/api?id=shape) API. For example, we can get the request body schema with `zData.shape.body`.
+5
.changeset/poor-stingrays-remember.md
··· 1 + --- 2 + '@hey-api/openapi-ts': patch 3 + --- 4 + 5 + fix(parser): do not mark schemas as duplicate if they have different format
+24
docs/openapi-ts/migrating.md
··· 27 27 28 28 This config option is deprecated and will be removed. 29 29 30 + ## v0.74.0 31 + 32 + ### Single Zod schema per request 33 + 34 + Previously, we generated a separate schema for each endpoint parameter and request body. In v0.74.0, a single request schema is generated for the whole endpoint. It may contain a request body, parameters, and headers. 35 + 36 + ```ts 37 + const zData = z.object({ 38 + body: z 39 + .object({ 40 + foo: z.string().optional(), 41 + bar: z.union([z.number(), z.null()]).optional(), 42 + }) 43 + .optional(), 44 + headers: z.never().optional(), 45 + path: z.object({ 46 + baz: z.string(), 47 + }), 48 + query: z.never().optional(), 49 + }); 50 + ``` 51 + 52 + If you need to access individual fields, you can do so using the [`.shape`](https://zod.dev/api?id=shape) API. For example, we can get the request body schema with `zData.shape.body`. 53 + 30 54 ## v0.73.0 31 55 32 56 ### Bundle `@hey-api/client-*` plugins
+2 -2
docs/openapi-ts/plugins/custom.md
··· 110 110 111 111 import type { Config } from './types'; 112 112 113 - export const handler: Plugin.Handler<Config> = ({ context, plugin }) => { 113 + export const handler: Plugin.Handler<Config> = ({ plugin }) => { 114 114 // create an output file. it will not be 115 115 // generated until it contains nodes 116 - const file = context.createFile({ 116 + const file = plugin.createFile({ 117 117 id: plugin.name, 118 118 path: plugin.output, 119 119 });
+33 -24
docs/openapi-ts/plugins/zod.md
··· 26 26 ## Features 27 27 28 28 - seamless integration with `@hey-api/openapi-ts` ecosystem 29 - - Zod schemas for request payloads, parameters, and responses 29 + - Zod schemas for requests, responses, and reusable definitions 30 30 31 31 ## Installation 32 32 ··· 66 66 67 67 The Zod plugin will generate the following artifacts, depending on the input specification. 68 68 69 + ## Requests 70 + 71 + A single request schema is generated for each endpoint. It may contain a request body, parameters, and headers. 72 + 73 + ```ts 74 + const zData = z.object({ 75 + body: z 76 + .object({ 77 + foo: z.string().optional(), 78 + bar: z.union([z.number(), z.null()]).optional(), 79 + }) 80 + .optional(), 81 + headers: z.never().optional(), 82 + path: z.object({ 83 + baz: z.string(), 84 + }), 85 + query: z.never().optional(), 86 + }); 87 + ``` 88 + 89 + ::: tip 90 + If you need to access individual fields, you can do so using the [`.shape`](https://zod.dev/api?id=shape) API. For example, we can get the request body schema with `zData.shape.body`. 91 + ::: 92 + 93 + You can customize the naming and casing pattern for requests using the `requests.name` and `requests.case` options. 94 + 69 95 ## Responses 70 96 71 97 A single Zod schema is generated for all endpoint's responses. If the endpoint describes multiple responses, the generated schema is a union of all possible response shapes. ··· 81 107 ]); 82 108 ``` 83 109 84 - ## Request Bodies 85 - 86 - If an endpoint describes a request body, we will generate a Zod schema representing its shape. 87 - 88 - ```ts 89 - const zData = z.object({ 90 - foo: z.string().optional(), 91 - bar: z.union([z.number(), z.null()]).optional(), 92 - }); 93 - ``` 94 - 95 - ## Parameters 96 - 97 - A separate Zod schema is generated for every request parameter. 110 + You can customize the naming and casing pattern for responses using the `responses.name` and `responses.case` options. 98 111 99 - ```ts 100 - const zParameterFoo = z.number().int(); 101 - 102 - const zParameterBar = z.string(); 103 - ``` 104 - 105 - ## Schemas 112 + ## Definitions 106 113 107 - A separate Zod schema is generated for every reusable schema. 114 + A Zod schema is generated for every reusable definition from your input. 108 115 109 116 ```ts 110 117 const zFoo = z.number().int(); ··· 114 121 }); 115 122 ``` 116 123 124 + You can customize the naming and casing pattern for definitions using the `definitions.name` and `definitions.case` options. 125 + 117 126 ## Metadata 118 127 119 - It's often useful to associate a schema with some additional metadata for documentation, code generation, AI structured outputs, form validation, and other purposes. If this is your use case, you can set `metadata` to `true` to generate additional metadata about schemas. 128 + It's often useful to associate a schema with some additional [metadata](https://zod.dev/metadata) for documentation, code generation, AI structured outputs, form validation, and other purposes. If this is your use case, you can set `metadata` to `true` to generate additional metadata about schemas. 120 129 121 130 ```js 122 131 export default {
+7
packages/openapi-ts-tests/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/zod.gen.ts
··· 12 12 foo: z.number().int() 13 13 }); 14 14 15 + export const zPostFooData = z.object({ 16 + body: z.never().optional(), 17 + headers: z.never().optional(), 18 + path: z.never().optional(), 19 + query: z.never().optional() 20 + }); 21 + 15 22 /** 16 23 * OK 17 24 */
+304 -258
packages/openapi-ts-tests/test/__snapshots__/2.0.x/plugins/zod/default/zod.gen.ts
··· 388 388 reference_code: z.string().optional() 389 389 }); 390 390 391 - /** 392 - * Testing multiline comments in string: First line 393 - * Second line 394 - * 395 - * Fourth line 396 - */ 397 - export const zCallWithDescriptionsParameterParameterWithBreaks = z.string(); 391 + export const zServiceWithEmptyTagData = z.object({ 392 + body: z.never().optional(), 393 + headers: z.never().optional(), 394 + path: z.never().optional(), 395 + query: z.never().optional() 396 + }); 398 397 399 - /** 400 - * Testing backticks in string: `backticks` and ```multiple backticks``` should work 401 - */ 402 - export const zCallWithDescriptionsParameterParameterWithBackticks = z.string(); 398 + export const zPatchApiVbyApiVersionNoTagData = z.object({ 399 + body: z.never().optional(), 400 + headers: z.never().optional(), 401 + path: z.never().optional(), 402 + query: z.never().optional() 403 + }); 403 404 404 - /** 405 - * Testing slashes in string: \backwards\\\ and /forwards/// should work 406 - */ 407 - export const zCallWithDescriptionsParameterParameterWithSlashes = z.string(); 405 + export const zFooWowData = z.object({ 406 + body: z.never().optional(), 407 + headers: z.never().optional(), 408 + path: z.never().optional(), 409 + query: z.never().optional() 410 + }); 408 411 409 - /** 410 - * Testing expression placeholders in string: ${expression} should work 411 - */ 412 - export const zCallWithDescriptionsParameterParameterWithExpressionPlaceholders = z.string(); 412 + export const zDeleteCallWithoutParametersAndResponseData = z.object({ 413 + body: z.never().optional(), 414 + headers: z.never().optional(), 415 + path: z.never().optional(), 416 + query: z.never().optional() 417 + }); 413 418 414 - /** 415 - * Testing quotes in string: 'single quote''' and "double quotes""" should work 416 - */ 417 - export const zCallWithDescriptionsParameterParameterWithQuotes = z.string(); 419 + export const zGetCallWithoutParametersAndResponseData = z.object({ 420 + body: z.never().optional(), 421 + headers: z.never().optional(), 422 + path: z.never().optional(), 423 + query: z.never().optional() 424 + }); 418 425 419 - /** 420 - * Testing reserved characters in string: * inline * and ** inline ** should work 421 - */ 422 - export const zCallWithDescriptionsParameterParameterWithReservedCharacters = z.string(); 426 + export const zHeadCallWithoutParametersAndResponseData = z.object({ 427 + body: z.never().optional(), 428 + headers: z.never().optional(), 429 + path: z.never().optional(), 430 + query: z.never().optional() 431 + }); 423 432 424 - /** 425 - * This is the parameter that goes into the header 426 - */ 427 - export const zCallWithParametersParameterParameterHeader = z.string(); 433 + export const zOptionsCallWithoutParametersAndResponseData = z.object({ 434 + body: z.never().optional(), 435 + headers: z.never().optional(), 436 + path: z.never().optional(), 437 + query: z.never().optional() 438 + }); 428 439 429 - /** 430 - * This is the parameter that goes into the path 431 - */ 432 - export const zCallWithParametersParameterParameterPath = z.string(); 440 + export const zPatchCallWithoutParametersAndResponseData = z.object({ 441 + body: z.never().optional(), 442 + headers: z.never().optional(), 443 + path: z.never().optional(), 444 + query: z.never().optional() 445 + }); 433 446 434 - /** 435 - * api-version should be required in standalone clients 436 - */ 437 - export const zCallWithParametersParameterApiVersion = z.string(); 447 + export const zPostCallWithoutParametersAndResponseData = z.object({ 448 + body: z.never().optional(), 449 + headers: z.never().optional(), 450 + path: z.never().optional(), 451 + query: z.never().optional() 452 + }); 438 453 439 - /** 440 - * This is the parameter that goes into the query params 441 - */ 442 - export const zCallWithParametersParameterParameterQuery = z.string(); 454 + export const zPutCallWithoutParametersAndResponseData = z.object({ 455 + body: z.never().optional(), 456 + headers: z.never().optional(), 457 + path: z.never().optional(), 458 + query: z.never().optional() 459 + }); 443 460 444 - /** 445 - * This is the parameter that goes into the request header 446 - */ 447 - export const zCallWithWeirdParameterNamesParameterParameterHeader = z.string(); 461 + export const zCallWithDescriptionsData = z.object({ 462 + body: z.never().optional(), 463 + headers: z.never().optional(), 464 + path: z.never().optional(), 465 + query: z.object({ 466 + parameterWithBreaks: z.string().optional(), 467 + parameterWithBackticks: z.string().optional(), 468 + parameterWithSlashes: z.string().optional(), 469 + parameterWithExpressionPlaceholders: z.string().optional(), 470 + parameterWithQuotes: z.string().optional(), 471 + parameterWithReservedCharacters: z.string().optional() 472 + }).optional() 473 + }); 448 474 449 - /** 450 - * This is the parameter that goes into the path 451 - */ 452 - export const zCallWithWeirdParameterNamesParameterParameterPath1 = z.string(); 475 + export const zCallWithParametersData = z.object({ 476 + body: z.never().optional(), 477 + headers: z.object({ 478 + parameterHeader: z.string() 479 + }), 480 + path: z.object({ 481 + parameterPath: z.string(), 482 + 'api-version': z.string() 483 + }), 484 + query: z.object({ 485 + parameterQuery: z.string() 486 + }) 487 + }); 453 488 454 - /** 455 - * This is the parameter that goes into the path 456 - */ 457 - export const zCallWithWeirdParameterNamesParameterParameterPath2 = z.string(); 458 - 459 - /** 460 - * This is the parameter that goes into the path 461 - */ 462 - export const zCallWithWeirdParameterNamesParameterParameterPath3 = z.string(); 463 - 464 - /** 465 - * api-version should be required in standalone clients 466 - */ 467 - export const zCallWithWeirdParameterNamesParameterApiVersion = z.string(); 468 - 469 - /** 470 - * This is the parameter with a reserved keyword 471 - */ 472 - export const zCallWithWeirdParameterNamesParameterDefault = z.string(); 473 - 474 - /** 475 - * This is the parameter that goes into the request query params 476 - */ 477 - export const zCallWithWeirdParameterNamesParameterParameterQuery = z.string(); 478 - 479 - /** 480 - * This is a simple string with default value 481 - */ 482 - export const zCallWithDefaultParametersParameterParameterString = z.string().default('Hello World!'); 483 - 484 - /** 485 - * This is a simple number with default value 486 - */ 487 - export const zCallWithDefaultParametersParameterParameterNumber = z.number().default(123); 488 - 489 - /** 490 - * This is a simple boolean with default value 491 - */ 492 - export const zCallWithDefaultParametersParameterParameterBoolean = z.boolean().default(true); 493 - 494 - /** 495 - * This is a simple enum with default value 496 - */ 497 - export const zCallWithDefaultParametersParameterParameterEnum = z.enum([ 498 - 'Success', 499 - 'Warning', 500 - 'Error' 501 - ]); 502 - 503 - /** 504 - * This is a model with one string property 505 - */ 506 - export const zCallWithDefaultParametersParameterParameterModel = z.object({ 507 - prop: z.string().optional() 508 - }).default({ 509 - prop: 'Hello World!' 489 + export const zCallWithWeirdParameterNamesData = z.object({ 490 + body: z.never().optional(), 491 + headers: z.object({ 492 + 'parameter.header': z.string() 493 + }), 494 + path: z.object({ 495 + 'parameter.path.1': z.string().optional(), 496 + 'parameter-path-2': z.string().optional(), 497 + 'PARAMETER-PATH-3': z.string().optional(), 498 + 'api-version': z.string() 499 + }), 500 + query: z.object({ 501 + default: z.string().optional(), 502 + 'parameter-query': z.string() 503 + }) 510 504 }); 511 505 512 - /** 513 - * This is a simple string that is optional with default value 514 - */ 515 - export const zCallWithDefaultOptionalParametersParameterParameterString = z.string().default('Hello World!'); 516 - 517 - /** 518 - * This is a simple number that is optional with default value 519 - */ 520 - export const zCallWithDefaultOptionalParametersParameterParameterNumber = z.number().default(123); 521 - 522 - /** 523 - * This is a simple boolean that is optional with default value 524 - */ 525 - export const zCallWithDefaultOptionalParametersParameterParameterBoolean = z.boolean().default(true); 526 - 527 - /** 528 - * This is a simple enum that is optional with default value 529 - */ 530 - export const zCallWithDefaultOptionalParametersParameterParameterEnum = z.enum([ 531 - 'Success', 532 - 'Warning', 533 - 'Error' 534 - ]); 506 + export const zCallWithDefaultParametersData = z.object({ 507 + body: z.never().optional(), 508 + headers: z.never().optional(), 509 + path: z.never().optional(), 510 + query: z.object({ 511 + parameterString: z.string().default('Hello World!'), 512 + parameterNumber: z.number().default(123), 513 + parameterBoolean: z.boolean().default(true), 514 + parameterEnum: z.enum([ 515 + 'Success', 516 + 'Warning', 517 + 'Error' 518 + ]), 519 + parameterModel: z.object({ 520 + prop: z.string().optional() 521 + }).default({ 522 + prop: 'Hello World!' 523 + }) 524 + }) 525 + }); 535 526 536 - /** 537 - * This is a optional string with default 538 - */ 539 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithDefault = z.string().default('Hello World!'); 527 + export const zCallWithDefaultOptionalParametersData = z.object({ 528 + body: z.never().optional(), 529 + headers: z.never().optional(), 530 + path: z.never().optional(), 531 + query: z.object({ 532 + parameterString: z.string().optional().default('Hello World!'), 533 + parameterNumber: z.number().optional().default(123), 534 + parameterBoolean: z.boolean().optional().default(true), 535 + parameterEnum: z.enum([ 536 + 'Success', 537 + 'Warning', 538 + 'Error' 539 + ]).optional() 540 + }).optional() 541 + }); 540 542 541 - /** 542 - * This is a optional string with empty default 543 - */ 544 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithEmptyDefault = z.string().default(''); 543 + export const zCallToTestOrderOfParamsData = z.object({ 544 + body: z.never().optional(), 545 + headers: z.never().optional(), 546 + path: z.never().optional(), 547 + query: z.object({ 548 + parameterOptionalStringWithDefault: z.string().optional().default('Hello World!'), 549 + parameterOptionalStringWithEmptyDefault: z.string().optional().default(''), 550 + parameterOptionalStringWithNoDefault: z.string().optional(), 551 + parameterStringWithDefault: z.string().default('Hello World!'), 552 + parameterStringWithEmptyDefault: z.string().default(''), 553 + parameterStringWithNoDefault: z.string(), 554 + parameterStringNullableWithNoDefault: z.union([ 555 + z.string(), 556 + z.null() 557 + ]).optional(), 558 + parameterStringNullableWithDefault: z.union([ 559 + z.string(), 560 + z.null() 561 + ]).optional().default(null) 562 + }) 563 + }); 545 564 546 - /** 547 - * This is a optional string with no default 548 - */ 549 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithNoDefault = z.string(); 565 + export const zDuplicateNameData = z.object({ 566 + body: z.never().optional(), 567 + headers: z.never().optional(), 568 + path: z.never().optional(), 569 + query: z.never().optional() 570 + }); 550 571 551 - /** 552 - * This is a string with default 553 - */ 554 - export const zCallToTestOrderOfParamsParameterParameterStringWithDefault = z.string().default('Hello World!'); 572 + export const zDuplicateName2Data = z.object({ 573 + body: z.never().optional(), 574 + headers: z.never().optional(), 575 + path: z.never().optional(), 576 + query: z.never().optional() 577 + }); 555 578 556 - /** 557 - * This is a string with empty default 558 - */ 559 - export const zCallToTestOrderOfParamsParameterParameterStringWithEmptyDefault = z.string().default(''); 579 + export const zDuplicateName3Data = z.object({ 580 + body: z.never().optional(), 581 + headers: z.never().optional(), 582 + path: z.never().optional(), 583 + query: z.never().optional() 584 + }); 560 585 561 - /** 562 - * This is a string with no default 563 - */ 564 - export const zCallToTestOrderOfParamsParameterParameterStringWithNoDefault = z.string(); 586 + export const zDuplicateName4Data = z.object({ 587 + body: z.never().optional(), 588 + headers: z.never().optional(), 589 + path: z.never().optional(), 590 + query: z.never().optional() 591 + }); 565 592 566 - /** 567 - * This is a string that can be null with no default 568 - */ 569 - export const zCallToTestOrderOfParamsParameterParameterStringNullableWithNoDefault = z.union([ 570 - z.string(), 571 - z.null() 572 - ]); 593 + export const zCallWithNoContentResponseData = z.object({ 594 + body: z.never().optional(), 595 + headers: z.never().optional(), 596 + path: z.never().optional(), 597 + query: z.never().optional() 598 + }); 573 599 574 - /** 575 - * This is a string that can be null with default 576 - */ 577 - export const zCallToTestOrderOfParamsParameterParameterStringNullableWithDefault = z.union([ 578 - z.string(), 579 - z.null() 580 - ]).default(null); 600 + export const zCallWithResponseAndNoContentResponseData = z.object({ 601 + body: z.never().optional(), 602 + headers: z.never().optional(), 603 + path: z.never().optional(), 604 + query: z.never().optional() 605 + }); 581 606 582 607 export const zCallWithResponseAndNoContentResponseResponse = z.union([ 583 608 z.number(), 584 609 z.unknown() 585 610 ]); 586 611 612 + export const zDummyAData = z.object({ 613 + body: z.never().optional(), 614 + headers: z.never().optional(), 615 + path: z.never().optional(), 616 + query: z.never().optional() 617 + }); 618 + 619 + export const zDummyBData = z.object({ 620 + body: z.never().optional(), 621 + headers: z.never().optional(), 622 + path: z.never().optional(), 623 + query: z.never().optional() 624 + }); 625 + 626 + export const zCallWithResponseData = z.object({ 627 + body: z.never().optional(), 628 + headers: z.never().optional(), 629 + path: z.never().optional(), 630 + query: z.never().optional() 631 + }); 632 + 587 633 /** 588 634 * Message for default response 589 635 */ 590 636 export const zCallWithResponseResponse = zModelWithString; 591 637 638 + export const zCallWithDuplicateResponsesData = z.object({ 639 + body: z.never().optional(), 640 + headers: z.never().optional(), 641 + path: z.never().optional(), 642 + query: z.never().optional() 643 + }); 644 + 592 645 /** 593 646 * Message for 201 response 594 647 */ 595 648 export const zCallWithDuplicateResponsesResponse = zModelWithString; 649 + 650 + export const zCallWithResponsesData = z.object({ 651 + body: z.never().optional(), 652 + headers: z.never().optional(), 653 + path: z.never().optional(), 654 + query: z.never().optional() 655 + }); 596 656 597 657 export const zCallWithResponsesResponse = z.union([ 598 658 z.object({ ··· 604 664 zModelThatExtendsExtends 605 665 ]); 606 666 607 - /** 608 - * This is an array parameter that is sent as csv format (comma-separated values) 609 - */ 610 - export const zCollectionFormatParameterParameterArrayCsv = z.array(z.string()); 667 + export const zCollectionFormatData = z.object({ 668 + body: z.never().optional(), 669 + headers: z.never().optional(), 670 + path: z.never().optional(), 671 + query: z.object({ 672 + parameterArrayCSV: z.array(z.string()), 673 + parameterArraySSV: z.array(z.string()), 674 + parameterArrayTSV: z.array(z.string()), 675 + parameterArrayPipes: z.array(z.string()), 676 + parameterArrayMulti: z.array(z.string()) 677 + }) 678 + }); 611 679 612 - /** 613 - * This is an array parameter that is sent as ssv format (space-separated values) 614 - */ 615 - export const zCollectionFormatParameterParameterArraySsv = z.array(z.string()); 616 - 617 - /** 618 - * This is an array parameter that is sent as tsv format (tab-separated values) 619 - */ 620 - export const zCollectionFormatParameterParameterArrayTsv = z.array(z.string()); 621 - 622 - /** 623 - * This is an array parameter that is sent as pipes format (pipe-separated values) 624 - */ 625 - export const zCollectionFormatParameterParameterArrayPipes = z.array(z.string()); 626 - 627 - /** 628 - * This is an array parameter that is sent as multi format (multiple parameter instances) 629 - */ 630 - export const zCollectionFormatParameterParameterArrayMulti = z.array(z.string()); 631 - 632 - /** 633 - * This is a number parameter 634 - */ 635 - export const zTypesParameterId = z.number().int(); 636 - 637 - /** 638 - * This is a number parameter 639 - */ 640 - export const zTypesParameterParameterNumber = z.number().default(123); 641 - 642 - /** 643 - * This is a string parameter 644 - */ 645 - export const zTypesParameterParameterString = z.string().default('default'); 646 - 647 - /** 648 - * This is a boolean parameter 649 - */ 650 - export const zTypesParameterParameterBoolean = z.boolean().default(true); 651 - 652 - /** 653 - * This is an array parameter 654 - */ 655 - export const zTypesParameterParameterArray = z.array(z.string()); 656 - 657 - /** 658 - * This is a dictionary parameter 659 - */ 660 - export const zTypesParameterParameterDictionary = z.object({}); 661 - 662 - /** 663 - * This is an enum parameter 664 - */ 665 - export const zTypesParameterParameterEnum = z.enum([ 666 - 'Success', 667 - 'Warning', 668 - 'Error' 669 - ]); 680 + export const zTypesData = z.object({ 681 + body: z.never().optional(), 682 + headers: z.never().optional(), 683 + path: z.object({ 684 + id: z.number().int().optional() 685 + }).optional(), 686 + query: z.object({ 687 + parameterNumber: z.number().default(123), 688 + parameterString: z.string().default('default'), 689 + parameterBoolean: z.boolean().default(true), 690 + parameterArray: z.array(z.string()), 691 + parameterDictionary: z.object({}), 692 + parameterEnum: z.enum([ 693 + 'Success', 694 + 'Warning', 695 + 'Error' 696 + ]) 697 + }) 698 + }); 670 699 671 700 export const zTypesResponse = z.union([ 672 701 z.number(), ··· 675 704 z.object({}) 676 705 ]); 677 706 678 - /** 679 - * Parameter containing object 680 - */ 681 - export const zComplexTypesParameterParameterObject = z.object({ 682 - first: z.object({ 683 - second: z.object({ 684 - third: z.string().optional() 685 - }).optional() 686 - }).optional() 687 - }); 688 - 689 - /** 690 - * This is a model with one string property 691 - */ 692 - export const zComplexTypesParameterParameterReference = z.object({ 693 - prop: z.string().optional() 707 + export const zComplexTypesData = z.object({ 708 + body: z.never().optional(), 709 + headers: z.never().optional(), 710 + path: z.never().optional(), 711 + query: z.object({ 712 + parameterObject: z.object({ 713 + first: z.object({ 714 + second: z.object({ 715 + third: z.string().optional() 716 + }).optional() 717 + }).optional() 718 + }), 719 + parameterReference: z.object({ 720 + prop: z.string().optional() 721 + }) 722 + }) 694 723 }); 695 724 696 725 /** ··· 698 727 */ 699 728 export const zComplexTypesResponse = z.array(zModelWithString); 700 729 701 - /** 702 - * Status code to return 703 - */ 704 - export const zTestErrorCodeParameterStatus = z.string(); 730 + export const zCallWithResultFromHeaderData = z.object({ 731 + body: z.never().optional(), 732 + headers: z.never().optional(), 733 + path: z.never().optional(), 734 + query: z.never().optional() 735 + }); 705 736 706 - /** 707 - * Dummy input param 708 - */ 709 - export const zNonAsciiæøåÆøÅöôêÊ字符串ParameterNonAsciiParamæøåÆøÅöôêÊ = z.number().int(); 737 + export const zTestErrorCodeData = z.object({ 738 + body: z.never().optional(), 739 + headers: z.never().optional(), 740 + path: z.never().optional(), 741 + query: z.object({ 742 + status: z.string() 743 + }) 744 + }); 745 + 746 + export const zNonAsciiæøåÆøÅöôêÊ字符串Data = z.object({ 747 + body: z.never().optional(), 748 + headers: z.never().optional(), 749 + path: z.never().optional(), 750 + query: z.object({ 751 + 'nonAsciiParamæøåÆØÅöôêÊ': z.number().int() 752 + }) 753 + }); 710 754 711 755 /** 712 756 * Successful response 713 757 */ 714 758 export const zNonAsciiæøåÆøÅöôêÊ字符串Response = zNonAsciiStringæøåÆøÅöôêÊ字符串; 715 759 716 - /** 717 - * Body should not be unknown 718 - */ 719 - export const zPostApiVbyApiVersionBodyData = zParameterActivityParams; 760 + export const zPostApiVbyApiVersionBodyData = z.object({ 761 + body: zParameterActivityParams, 762 + headers: z.never().optional(), 763 + path: z.never().optional(), 764 + query: z.never().optional() 765 + }); 720 766 721 767 /** 722 768 * OK
+7
packages/openapi-ts-tests/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/zod.gen.ts
··· 12 12 foo: z.number().int() 13 13 }); 14 14 15 + export const zPostFooData = z.object({ 16 + body: z.never().optional(), 17 + headers: z.never().optional(), 18 + path: z.never().optional(), 19 + query: z.never().optional() 20 + }); 21 + 15 22 /** 16 23 * OK 17 24 */
+535 -492
packages/openapi-ts-tests/test/__snapshots__/3.0.x/plugins/zod/default/zod.gen.ts
··· 1052 1052 1053 1053 export const zSimpleFormData = zModelWithString; 1054 1054 1055 - export const zImportData = z.union([ 1056 - zModelWithReadOnlyAndWriteOnly, 1057 - zModelWithArrayReadOnlyAndWriteOnly 1058 - ]); 1055 + export const zExportData = z.object({ 1056 + body: z.never().optional(), 1057 + headers: z.never().optional(), 1058 + path: z.never().optional(), 1059 + query: z.never().optional() 1060 + }); 1061 + 1062 + export const zPatchApiVbyApiVersionNoTagData = z.object({ 1063 + body: z.never().optional(), 1064 + headers: z.never().optional(), 1065 + path: z.never().optional(), 1066 + query: z.never().optional() 1067 + }); 1068 + 1069 + export const zImportData = z.object({ 1070 + body: z.union([ 1071 + zModelWithReadOnlyAndWriteOnly, 1072 + zModelWithArrayReadOnlyAndWriteOnly 1073 + ]), 1074 + headers: z.never().optional(), 1075 + path: z.never().optional(), 1076 + query: z.never().optional() 1077 + }); 1059 1078 1060 1079 export const zImportResponse = z.union([ 1061 1080 zModelFromZendesk, 1062 1081 zModelWithReadOnlyAndWriteOnly 1063 1082 ]); 1064 1083 1084 + export const zFooWowData = z.object({ 1085 + body: z.never().optional(), 1086 + headers: z.never().optional(), 1087 + path: z.never().optional(), 1088 + query: z.never().optional() 1089 + }); 1090 + 1091 + export const zApiVVersionODataControllerCountData = z.object({ 1092 + body: z.never().optional(), 1093 + headers: z.never().optional(), 1094 + path: z.never().optional(), 1095 + query: z.never().optional() 1096 + }); 1097 + 1065 1098 /** 1066 1099 * Success 1067 1100 */ 1068 1101 export const zApiVVersionODataControllerCountResponse = zModelFromZendesk; 1069 1102 1070 - /** 1071 - * foo in method 1072 - */ 1073 - export const zGetApiVbyApiVersionSimpleOperationParameterFooParam = z.string(); 1103 + export const zGetApiVbyApiVersionSimpleOperationData = z.object({ 1104 + body: z.never().optional(), 1105 + headers: z.never().optional(), 1106 + path: z.object({ 1107 + foo_param: z.string() 1108 + }), 1109 + query: z.never().optional() 1110 + }); 1074 1111 1075 1112 /** 1076 1113 * Response is a simple number 1077 1114 */ 1078 1115 export const zGetApiVbyApiVersionSimpleOperationResponse = z.number(); 1079 1116 1080 - /** 1081 - * foo in method 1082 - */ 1083 - export const zDeleteFooParameterFooParam = z.string(); 1117 + export const zDeleteCallWithoutParametersAndResponseData = z.object({ 1118 + body: z.never().optional(), 1119 + headers: z.never().optional(), 1120 + path: z.never().optional(), 1121 + query: z.never().optional() 1122 + }); 1084 1123 1085 - /** 1086 - * bar in method 1087 - */ 1088 - export const zDeleteFooParameterBarParam = z.string(); 1124 + export const zGetCallWithoutParametersAndResponseData = z.object({ 1125 + body: z.never().optional(), 1126 + headers: z.never().optional(), 1127 + path: z.never().optional(), 1128 + query: z.never().optional() 1129 + }); 1089 1130 1090 - /** 1091 - * Parameter with illegal characters 1092 - */ 1093 - export const zDeleteFooParameterXFooBar = zModelWithString; 1131 + export const zHeadCallWithoutParametersAndResponseData = z.object({ 1132 + body: z.never().optional(), 1133 + headers: z.never().optional(), 1134 + path: z.never().optional(), 1135 + query: z.never().optional() 1136 + }); 1094 1137 1095 - /** 1096 - * Testing multiline comments in string: First line 1097 - * Second line 1098 - * 1099 - * Fourth line 1100 - */ 1101 - export const zCallWithDescriptionsParameterParameterWithBreaks = z.string(); 1138 + export const zOptionsCallWithoutParametersAndResponseData = z.object({ 1139 + body: z.never().optional(), 1140 + headers: z.never().optional(), 1141 + path: z.never().optional(), 1142 + query: z.never().optional() 1143 + }); 1102 1144 1103 - /** 1104 - * Testing backticks in string: `backticks` and ```multiple backticks``` should work 1105 - */ 1106 - export const zCallWithDescriptionsParameterParameterWithBackticks = z.string(); 1145 + export const zPatchCallWithoutParametersAndResponseData = z.object({ 1146 + body: z.never().optional(), 1147 + headers: z.never().optional(), 1148 + path: z.never().optional(), 1149 + query: z.never().optional() 1150 + }); 1107 1151 1108 - /** 1109 - * Testing slashes in string: \backwards\\\ and /forwards/// should work 1110 - */ 1111 - export const zCallWithDescriptionsParameterParameterWithSlashes = z.string(); 1152 + export const zPostCallWithoutParametersAndResponseData = z.object({ 1153 + body: z.never().optional(), 1154 + headers: z.never().optional(), 1155 + path: z.never().optional(), 1156 + query: z.never().optional() 1157 + }); 1112 1158 1113 - /** 1114 - * Testing expression placeholders in string: ${expression} should work 1115 - */ 1116 - export const zCallWithDescriptionsParameterParameterWithExpressionPlaceholders = z.string(); 1159 + export const zPutCallWithoutParametersAndResponseData = z.object({ 1160 + body: z.never().optional(), 1161 + headers: z.never().optional(), 1162 + path: z.never().optional(), 1163 + query: z.never().optional() 1164 + }); 1117 1165 1118 - /** 1119 - * Testing quotes in string: 'single quote''' and "double quotes""" should work 1120 - */ 1121 - export const zCallWithDescriptionsParameterParameterWithQuotes = z.string(); 1122 - 1123 - /** 1124 - * Testing reserved characters in string: * inline * and ** inline ** should work 1125 - */ 1126 - export const zCallWithDescriptionsParameterParameterWithReservedCharacters = z.string(); 1127 - 1128 - /** 1129 - * This parameter is deprecated 1130 - * @deprecated 1131 - */ 1132 - export const zDeprecatedCallParameterParameter = z.union([ 1133 - zDeprecatedModel, 1134 - z.null() 1135 - ]); 1136 - 1137 - /** 1138 - * This is the parameter that goes into the body 1139 - */ 1140 - export const zCallWithParametersData = z.union([ 1141 - z.object({}), 1142 - z.null() 1143 - ]); 1144 - 1145 - /** 1146 - * This is the parameter that goes into the cookie 1147 - */ 1148 - export const zCallWithParametersParameterParameterCookie = z.union([ 1149 - z.string(), 1150 - z.null() 1151 - ]); 1152 - 1153 - /** 1154 - * This is the parameter that goes into the header 1155 - */ 1156 - export const zCallWithParametersParameterParameterHeader = z.union([ 1157 - z.string(), 1158 - z.null() 1159 - ]); 1160 - 1161 - /** 1162 - * This is the parameter that goes into the path 1163 - */ 1164 - export const zCallWithParametersParameterParameterPath = z.union([ 1165 - z.string(), 1166 - z.null() 1167 - ]); 1168 - 1169 - /** 1170 - * api-version should be required in standalone clients 1171 - */ 1172 - export const zCallWithParametersParameterApiVersion = z.union([ 1173 - z.string(), 1174 - z.null() 1175 - ]); 1176 - 1177 - export const zCallWithParametersParameterFooRefEnum = zModelWithNestedArrayEnumsDataFoo; 1178 - 1179 - export const zCallWithParametersParameterFooAllOfEnum = zModelWithNestedArrayEnumsDataFoo; 1180 - 1181 - /** 1182 - * This is the parameter that goes into the query params 1183 - */ 1184 - export const zCallWithParametersParameterCursor = z.union([ 1185 - z.string(), 1186 - z.null() 1187 - ]); 1188 - 1189 - /** 1190 - * This is the parameter that goes into the body 1191 - */ 1192 - export const zCallWithWeirdParameterNamesData = z.union([ 1193 - zModelWithString, 1194 - z.null() 1195 - ]); 1196 - 1197 - /** 1198 - * This is the parameter that goes into the cookie 1199 - */ 1200 - export const zCallWithWeirdParameterNamesParameterParameterCookie = z.union([ 1201 - z.string(), 1202 - z.null() 1203 - ]); 1204 - 1205 - /** 1206 - * This is the parameter that goes into the request header 1207 - */ 1208 - export const zCallWithWeirdParameterNamesParameterParameterHeader = z.union([ 1209 - z.string(), 1210 - z.null() 1211 - ]); 1212 - 1213 - /** 1214 - * This is the parameter that goes into the path 1215 - */ 1216 - export const zCallWithWeirdParameterNamesParameterParameterPath1 = z.string(); 1217 - 1218 - /** 1219 - * This is the parameter that goes into the path 1220 - */ 1221 - export const zCallWithWeirdParameterNamesParameterParameterPath2 = z.string(); 1222 - 1223 - /** 1224 - * This is the parameter that goes into the path 1225 - */ 1226 - export const zCallWithWeirdParameterNamesParameterParameterPath3 = z.string(); 1166 + export const zDeleteFooData3 = z.object({ 1167 + body: z.never().optional(), 1168 + headers: z.object({ 1169 + 'x-Foo-Bar': zModelWithString 1170 + }), 1171 + path: z.object({ 1172 + foo_param: z.string(), 1173 + BarParam: z.string() 1174 + }), 1175 + query: z.never().optional() 1176 + }); 1227 1177 1228 - /** 1229 - * api-version should be required in standalone clients 1230 - */ 1231 - export const zCallWithWeirdParameterNamesParameterApiVersion = z.union([ 1232 - z.string(), 1233 - z.null() 1234 - ]); 1178 + export const zCallWithDescriptionsData = z.object({ 1179 + body: z.never().optional(), 1180 + headers: z.never().optional(), 1181 + path: z.never().optional(), 1182 + query: z.object({ 1183 + parameterWithBreaks: z.string().optional(), 1184 + parameterWithBackticks: z.string().optional(), 1185 + parameterWithSlashes: z.string().optional(), 1186 + parameterWithExpressionPlaceholders: z.string().optional(), 1187 + parameterWithQuotes: z.string().optional(), 1188 + parameterWithReservedCharacters: z.string().optional() 1189 + }).optional() 1190 + }); 1235 1191 1236 - /** 1237 - * This is the parameter with a reserved keyword 1238 - */ 1239 - export const zCallWithWeirdParameterNamesParameterDefault = z.string(); 1192 + export const zDeprecatedCallData = z.object({ 1193 + body: z.never().optional(), 1194 + headers: z.object({ 1195 + parameter: z.union([ 1196 + zDeprecatedModel, 1197 + z.null() 1198 + ]) 1199 + }).optional(), 1200 + path: z.never().optional(), 1201 + query: z.never().optional() 1202 + }); 1240 1203 1241 - /** 1242 - * This is the parameter that goes into the request query params 1243 - */ 1244 - export const zCallWithWeirdParameterNamesParameterParameterQuery = z.union([ 1245 - z.string(), 1246 - z.null() 1247 - ]); 1204 + export const zCallWithParametersData = z.object({ 1205 + body: z.union([ 1206 + z.object({}), 1207 + z.null() 1208 + ]), 1209 + headers: z.object({ 1210 + parameterHeader: z.union([ 1211 + z.string(), 1212 + z.null() 1213 + ]) 1214 + }), 1215 + path: z.object({ 1216 + parameterPath: z.union([ 1217 + z.string(), 1218 + z.null() 1219 + ]), 1220 + 'api-version': z.union([ 1221 + z.string(), 1222 + z.null() 1223 + ]) 1224 + }), 1225 + query: z.object({ 1226 + foo_ref_enum: zModelWithNestedArrayEnumsDataFoo.optional(), 1227 + foo_all_of_enum: zModelWithNestedArrayEnumsDataFoo, 1228 + cursor: z.union([ 1229 + z.string(), 1230 + z.null() 1231 + ]) 1232 + }) 1233 + }); 1248 1234 1249 - /** 1250 - * This is a required parameter 1251 - */ 1252 - export const zGetCallWithOptionalParamData = zModelWithOneOfEnum; 1235 + export const zCallWithWeirdParameterNamesData = z.object({ 1236 + body: z.union([ 1237 + zModelWithString, 1238 + z.null() 1239 + ]), 1240 + headers: z.object({ 1241 + 'parameter.header': z.union([ 1242 + z.string(), 1243 + z.null() 1244 + ]) 1245 + }), 1246 + path: z.object({ 1247 + 'parameter.path.1': z.string().optional(), 1248 + 'parameter-path-2': z.string().optional(), 1249 + 'PARAMETER-PATH-3': z.string().optional(), 1250 + 'api-version': z.union([ 1251 + z.string(), 1252 + z.null() 1253 + ]) 1254 + }), 1255 + query: z.object({ 1256 + default: z.string().optional(), 1257 + 'parameter-query': z.union([ 1258 + z.string(), 1259 + z.null() 1260 + ]) 1261 + }) 1262 + }); 1253 1263 1254 - /** 1255 - * This is an optional parameter 1256 - */ 1257 - export const zGetCallWithOptionalParamParameterPage = z.number(); 1264 + export const zGetCallWithOptionalParamData = z.object({ 1265 + body: zModelWithOneOfEnum, 1266 + headers: z.never().optional(), 1267 + path: z.never().optional(), 1268 + query: z.object({ 1269 + page: z.number().optional() 1270 + }).optional() 1271 + }); 1258 1272 1259 - /** 1260 - * This is an optional parameter 1261 - */ 1262 1273 export const zPostCallWithOptionalParamData = z.object({ 1263 - offset: z.union([ 1264 - z.number(), 1265 - z.null() 1266 - ]).optional() 1274 + body: z.object({ 1275 + offset: z.union([ 1276 + z.number(), 1277 + z.null() 1278 + ]).optional() 1279 + }).optional(), 1280 + headers: z.never().optional(), 1281 + path: z.never().optional(), 1282 + query: z.object({ 1283 + parameter: zPageable 1284 + }) 1267 1285 }); 1268 - 1269 - /** 1270 - * This is a required parameter 1271 - */ 1272 - export const zPostCallWithOptionalParamParameterParameter = zPageable; 1273 1286 1274 1287 export const zPostCallWithOptionalParamResponse = z.union([ 1275 1288 z.number(), 1276 1289 z.void() 1277 1290 ]); 1278 1291 1279 - /** 1280 - * A reusable request body 1281 - */ 1282 - export const zPostApiVbyApiVersionRequestBodyData = zSimpleRequestBody; 1292 + export const zPostApiVbyApiVersionRequestBodyData = z.object({ 1293 + body: zSimpleRequestBody.optional(), 1294 + headers: z.never().optional(), 1295 + path: z.never().optional(), 1296 + query: z.object({ 1297 + parameter: z.string().optional() 1298 + }).optional() 1299 + }); 1283 1300 1284 - /** 1285 - * This is a reusable parameter 1286 - */ 1287 - export const zPostApiVbyApiVersionRequestBodyParameterParameter = z.string(); 1301 + export const zPostApiVbyApiVersionFormDataData = z.object({ 1302 + body: zSimpleFormData.optional(), 1303 + headers: z.never().optional(), 1304 + path: z.never().optional(), 1305 + query: z.object({ 1306 + parameter: z.string().optional() 1307 + }).optional() 1308 + }); 1288 1309 1289 - /** 1290 - * A reusable request body 1291 - */ 1292 - export const zPostApiVbyApiVersionFormDataData = zSimpleFormData; 1310 + export const zCallWithDefaultParametersData = z.object({ 1311 + body: z.never().optional(), 1312 + headers: z.never().optional(), 1313 + path: z.never().optional(), 1314 + query: z.object({ 1315 + parameterString: z.union([ 1316 + z.string().default('Hello World!'), 1317 + z.null() 1318 + ]).optional().default('Hello World!'), 1319 + parameterNumber: z.union([ 1320 + z.number().default(123), 1321 + z.null() 1322 + ]).optional().default(123), 1323 + parameterBoolean: z.union([ 1324 + z.boolean().default(true), 1325 + z.null() 1326 + ]).optional().default(true), 1327 + parameterEnum: z.enum([ 1328 + 'Success', 1329 + 'Warning', 1330 + 'Error' 1331 + ]).optional(), 1332 + parameterModel: z.union([ 1333 + zModelWithString, 1334 + z.null() 1335 + ]).optional() 1336 + }).optional() 1337 + }); 1293 1338 1294 - /** 1295 - * This is a reusable parameter 1296 - */ 1297 - export const zPostApiVbyApiVersionFormDataParameterParameter = z.string(); 1339 + export const zCallWithDefaultOptionalParametersData = z.object({ 1340 + body: z.never().optional(), 1341 + headers: z.never().optional(), 1342 + path: z.never().optional(), 1343 + query: z.object({ 1344 + parameterString: z.string().optional().default('Hello World!'), 1345 + parameterNumber: z.number().optional().default(123), 1346 + parameterBoolean: z.boolean().optional().default(true), 1347 + parameterEnum: z.enum([ 1348 + 'Success', 1349 + 'Warning', 1350 + 'Error' 1351 + ]).optional(), 1352 + parameterModel: zModelWithString.optional() 1353 + }).optional() 1354 + }); 1298 1355 1299 - /** 1300 - * This is a simple string with default value 1301 - */ 1302 - export const zCallWithDefaultParametersParameterParameterString = z.union([ 1303 - z.string().default('Hello World!'), 1304 - z.null() 1305 - ]).default('Hello World!'); 1356 + export const zCallToTestOrderOfParamsData = z.object({ 1357 + body: z.never().optional(), 1358 + headers: z.never().optional(), 1359 + path: z.never().optional(), 1360 + query: z.object({ 1361 + parameterOptionalStringWithDefault: z.string().optional().default('Hello World!'), 1362 + parameterOptionalStringWithEmptyDefault: z.string().optional().default(''), 1363 + parameterOptionalStringWithNoDefault: z.string().optional(), 1364 + parameterStringWithDefault: z.string().default('Hello World!'), 1365 + parameterStringWithEmptyDefault: z.string().default(''), 1366 + parameterStringWithNoDefault: z.string(), 1367 + parameterStringNullableWithNoDefault: z.union([ 1368 + z.string(), 1369 + z.null() 1370 + ]).optional(), 1371 + parameterStringNullableWithDefault: z.union([ 1372 + z.string(), 1373 + z.null() 1374 + ]).optional().default(null) 1375 + }) 1376 + }); 1306 1377 1307 - /** 1308 - * This is a simple number with default value 1309 - */ 1310 - export const zCallWithDefaultParametersParameterParameterNumber = z.union([ 1311 - z.number().default(123), 1312 - z.null() 1313 - ]).default(123); 1378 + export const zDuplicateNameData = z.object({ 1379 + body: z.never().optional(), 1380 + headers: z.never().optional(), 1381 + path: z.never().optional(), 1382 + query: z.never().optional() 1383 + }); 1314 1384 1315 - /** 1316 - * This is a simple boolean with default value 1317 - */ 1318 - export const zCallWithDefaultParametersParameterParameterBoolean = z.union([ 1319 - z.boolean().default(true), 1320 - z.null() 1321 - ]).default(true); 1385 + export const zDuplicateName2Data = z.object({ 1386 + body: z.never().optional(), 1387 + headers: z.never().optional(), 1388 + path: z.never().optional(), 1389 + query: z.never().optional() 1390 + }); 1322 1391 1323 - /** 1324 - * This is a simple enum with default value 1325 - */ 1326 - export const zCallWithDefaultParametersParameterParameterEnum = z.enum([ 1327 - 'Success', 1328 - 'Warning', 1329 - 'Error' 1330 - ]); 1392 + export const zDuplicateName3Data = z.object({ 1393 + body: z.never().optional(), 1394 + headers: z.never().optional(), 1395 + path: z.never().optional(), 1396 + query: z.never().optional() 1397 + }); 1331 1398 1332 - /** 1333 - * This is a simple model with default value 1334 - */ 1335 - export const zCallWithDefaultParametersParameterParameterModel = z.union([ 1336 - zModelWithString, 1337 - z.null() 1338 - ]); 1399 + export const zDuplicateName4Data = z.object({ 1400 + body: z.never().optional(), 1401 + headers: z.never().optional(), 1402 + path: z.never().optional(), 1403 + query: z.never().optional() 1404 + }); 1339 1405 1340 - /** 1341 - * This is a simple string that is optional with default value 1342 - */ 1343 - export const zCallWithDefaultOptionalParametersParameterParameterString = z.string().default('Hello World!'); 1344 - 1345 - /** 1346 - * This is a simple number that is optional with default value 1347 - */ 1348 - export const zCallWithDefaultOptionalParametersParameterParameterNumber = z.number().default(123); 1349 - 1350 - /** 1351 - * This is a simple boolean that is optional with default value 1352 - */ 1353 - export const zCallWithDefaultOptionalParametersParameterParameterBoolean = z.boolean().default(true); 1354 - 1355 - /** 1356 - * This is a simple enum that is optional with default value 1357 - */ 1358 - export const zCallWithDefaultOptionalParametersParameterParameterEnum = z.enum([ 1359 - 'Success', 1360 - 'Warning', 1361 - 'Error' 1362 - ]); 1363 - 1364 - /** 1365 - * This is a simple model that is optional with default value 1366 - */ 1367 - export const zCallWithDefaultOptionalParametersParameterParameterModel = zModelWithString; 1368 - 1369 - /** 1370 - * This is a optional string with default 1371 - */ 1372 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithDefault = z.string().default('Hello World!'); 1373 - 1374 - /** 1375 - * This is a optional string with empty default 1376 - */ 1377 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithEmptyDefault = z.string().default(''); 1378 - 1379 - /** 1380 - * This is a optional string with no default 1381 - */ 1382 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithNoDefault = z.string(); 1383 - 1384 - /** 1385 - * This is a string with default 1386 - */ 1387 - export const zCallToTestOrderOfParamsParameterParameterStringWithDefault = z.string().default('Hello World!'); 1388 - 1389 - /** 1390 - * This is a string with empty default 1391 - */ 1392 - export const zCallToTestOrderOfParamsParameterParameterStringWithEmptyDefault = z.string().default(''); 1393 - 1394 - /** 1395 - * This is a string with no default 1396 - */ 1397 - export const zCallToTestOrderOfParamsParameterParameterStringWithNoDefault = z.string(); 1398 - 1399 - /** 1400 - * This is a string that can be null with no default 1401 - */ 1402 - export const zCallToTestOrderOfParamsParameterParameterStringNullableWithNoDefault = z.union([ 1403 - z.string(), 1404 - z.null() 1405 - ]); 1406 - 1407 - /** 1408 - * This is a string that can be null with default 1409 - */ 1410 - export const zCallToTestOrderOfParamsParameterParameterStringNullableWithDefault = z.union([ 1411 - z.string(), 1412 - z.null() 1413 - ]).default(null); 1406 + export const zCallWithNoContentResponseData = z.object({ 1407 + body: z.never().optional(), 1408 + headers: z.never().optional(), 1409 + path: z.never().optional(), 1410 + query: z.never().optional() 1411 + }); 1414 1412 1415 1413 /** 1416 1414 * Success 1417 1415 */ 1418 1416 export const zCallWithNoContentResponseResponse = z.void(); 1419 1417 1418 + export const zCallWithResponseAndNoContentResponseData = z.object({ 1419 + body: z.never().optional(), 1420 + headers: z.never().optional(), 1421 + path: z.never().optional(), 1422 + query: z.never().optional() 1423 + }); 1424 + 1420 1425 export const zCallWithResponseAndNoContentResponseResponse = z.union([ 1421 1426 z.number(), 1422 1427 z.void() 1423 1428 ]); 1424 1429 1430 + export const zDummyAData = z.object({ 1431 + body: z.never().optional(), 1432 + headers: z.never().optional(), 1433 + path: z.never().optional(), 1434 + query: z.never().optional() 1435 + }); 1436 + 1425 1437 export const zDummyAResponse = z400; 1438 + 1439 + export const zDummyBData = z.object({ 1440 + body: z.never().optional(), 1441 + headers: z.never().optional(), 1442 + path: z.never().optional(), 1443 + query: z.never().optional() 1444 + }); 1426 1445 1427 1446 /** 1428 1447 * Success 1429 1448 */ 1430 1449 export const zDummyBResponse = z.void(); 1431 1450 1451 + export const zCallWithResponseData = z.object({ 1452 + body: z.never().optional(), 1453 + headers: z.never().optional(), 1454 + path: z.never().optional(), 1455 + query: z.never().optional() 1456 + }); 1457 + 1432 1458 export const zCallWithResponseResponse = zImport; 1433 1459 1460 + export const zCallWithDuplicateResponsesData = z.object({ 1461 + body: z.never().optional(), 1462 + headers: z.never().optional(), 1463 + path: z.never().optional(), 1464 + query: z.never().optional() 1465 + }); 1466 + 1434 1467 export const zCallWithDuplicateResponsesResponse = z.union([ 1435 1468 zModelWithBoolean.and(zModelWithInteger), 1436 1469 zModelWithString 1437 1470 ]); 1438 1471 1472 + export const zCallWithResponsesData = z.object({ 1473 + body: z.never().optional(), 1474 + headers: z.never().optional(), 1475 + path: z.never().optional(), 1476 + query: z.never().optional() 1477 + }); 1478 + 1439 1479 export const zCallWithResponsesResponse = z.union([ 1440 1480 z.object({ 1441 1481 '@namespace.string': z.string().readonly().optional(), ··· 1446 1486 zModelThatExtendsExtends 1447 1487 ]); 1448 1488 1449 - /** 1450 - * This is an array parameter that is sent as csv format (comma-separated values) 1451 - */ 1452 - export const zCollectionFormatParameterParameterArrayCsv = z.union([ 1453 - z.array(z.string()), 1454 - z.null() 1455 - ]); 1456 - 1457 - /** 1458 - * This is an array parameter that is sent as ssv format (space-separated values) 1459 - */ 1460 - export const zCollectionFormatParameterParameterArraySsv = z.union([ 1461 - z.array(z.string()), 1462 - z.null() 1463 - ]); 1464 - 1465 - /** 1466 - * This is an array parameter that is sent as tsv format (tab-separated values) 1467 - */ 1468 - export const zCollectionFormatParameterParameterArrayTsv = z.union([ 1469 - z.array(z.string()), 1470 - z.null() 1471 - ]); 1472 - 1473 - /** 1474 - * This is an array parameter that is sent as pipes format (pipe-separated values) 1475 - */ 1476 - export const zCollectionFormatParameterParameterArrayPipes = z.union([ 1477 - z.array(z.string()), 1478 - z.null() 1479 - ]); 1480 - 1481 - /** 1482 - * This is an array parameter that is sent as multi format (multiple parameter instances) 1483 - */ 1484 - export const zCollectionFormatParameterParameterArrayMulti = z.union([ 1485 - z.array(z.string()), 1486 - z.null() 1487 - ]); 1489 + export const zCollectionFormatData = z.object({ 1490 + body: z.never().optional(), 1491 + headers: z.never().optional(), 1492 + path: z.never().optional(), 1493 + query: z.object({ 1494 + parameterArrayCSV: z.union([ 1495 + z.array(z.string()), 1496 + z.null() 1497 + ]), 1498 + parameterArraySSV: z.union([ 1499 + z.array(z.string()), 1500 + z.null() 1501 + ]), 1502 + parameterArrayTSV: z.union([ 1503 + z.array(z.string()), 1504 + z.null() 1505 + ]), 1506 + parameterArrayPipes: z.union([ 1507 + z.array(z.string()), 1508 + z.null() 1509 + ]), 1510 + parameterArrayMulti: z.union([ 1511 + z.array(z.string()), 1512 + z.null() 1513 + ]) 1514 + }) 1515 + }); 1488 1516 1489 - /** 1490 - * This is a number parameter 1491 - */ 1492 - export const zTypesParameterId = z.number().int(); 1493 - 1494 - /** 1495 - * This is a number parameter 1496 - */ 1497 - export const zTypesParameterParameterNumber = z.number().default(123); 1498 - 1499 - /** 1500 - * This is a string parameter 1501 - */ 1502 - export const zTypesParameterParameterString = z.union([ 1503 - z.string().default('default'), 1504 - z.null() 1505 - ]).default('default'); 1506 - 1507 - /** 1508 - * This is a boolean parameter 1509 - */ 1510 - export const zTypesParameterParameterBoolean = z.union([ 1511 - z.boolean().default(true), 1512 - z.null() 1513 - ]).default(true); 1514 - 1515 - /** 1516 - * This is an object parameter 1517 - */ 1518 - export const zTypesParameterParameterObject = z.union([ 1519 - z.object({}), 1520 - z.null() 1521 - ]).default(null); 1522 - 1523 - /** 1524 - * This is an array parameter 1525 - */ 1526 - export const zTypesParameterParameterArray = z.union([ 1527 - z.array(z.string()), 1528 - z.null() 1529 - ]); 1530 - 1531 - /** 1532 - * This is a dictionary parameter 1533 - */ 1534 - export const zTypesParameterParameterDictionary = z.union([ 1535 - z.object({}), 1536 - z.null() 1537 - ]); 1538 - 1539 - /** 1540 - * This is an enum parameter 1541 - */ 1542 - export const zTypesParameterParameterEnum = z.enum([ 1543 - 'Success', 1544 - 'Warning', 1545 - 'Error' 1546 - ]); 1517 + export const zTypesData = z.object({ 1518 + body: z.never().optional(), 1519 + headers: z.never().optional(), 1520 + path: z.object({ 1521 + id: z.number().int().optional() 1522 + }).optional(), 1523 + query: z.object({ 1524 + parameterNumber: z.number().default(123), 1525 + parameterString: z.union([ 1526 + z.string().default('default'), 1527 + z.null() 1528 + ]).default('default'), 1529 + parameterBoolean: z.union([ 1530 + z.boolean().default(true), 1531 + z.null() 1532 + ]).default(true), 1533 + parameterObject: z.union([ 1534 + z.object({}), 1535 + z.null() 1536 + ]).default(null), 1537 + parameterArray: z.union([ 1538 + z.array(z.string()), 1539 + z.null() 1540 + ]), 1541 + parameterDictionary: z.union([ 1542 + z.object({}), 1543 + z.null() 1544 + ]), 1545 + parameterEnum: z.enum([ 1546 + 'Success', 1547 + 'Warning', 1548 + 'Error' 1549 + ]) 1550 + }) 1551 + }); 1547 1552 1548 1553 export const zTypesResponse = z.union([ 1549 1554 z.number(), ··· 1552 1557 z.object({}) 1553 1558 ]); 1554 1559 1555 - export const zUploadFileData = z.string(); 1556 - 1557 - /** 1558 - * api-version should be required in standalone clients 1559 - */ 1560 - export const zUploadFileParameterApiVersion = z.union([ 1561 - z.string(), 1562 - z.null() 1563 - ]); 1560 + export const zUploadFileData = z.object({ 1561 + body: z.string(), 1562 + headers: z.never().optional(), 1563 + path: z.object({ 1564 + 'api-version': z.union([ 1565 + z.string(), 1566 + z.null() 1567 + ]) 1568 + }), 1569 + query: z.never().optional() 1570 + }); 1564 1571 1565 1572 export const zUploadFileResponse = z.boolean(); 1566 1573 1567 - export const zFileResponseParameterId = z.string(); 1568 - 1569 - /** 1570 - * api-version should be required in standalone clients 1571 - */ 1572 - export const zFileResponseParameterApiVersion = z.string(); 1574 + export const zFileResponseData = z.object({ 1575 + body: z.never().optional(), 1576 + headers: z.never().optional(), 1577 + path: z.object({ 1578 + id: z.string(), 1579 + 'api-version': z.string() 1580 + }), 1581 + query: z.never().optional() 1582 + }); 1573 1583 1574 1584 /** 1575 1585 * Success 1576 1586 */ 1577 1587 export const zFileResponseResponse = z.string(); 1578 1588 1579 - /** 1580 - * Parameter containing object 1581 - */ 1582 - export const zComplexTypesParameterParameterObject = z.object({ 1583 - first: z.object({ 1584 - second: z.object({ 1585 - third: z.string().optional() 1586 - }).optional() 1587 - }).optional() 1589 + export const zComplexTypesData = z.object({ 1590 + body: z.never().optional(), 1591 + headers: z.never().optional(), 1592 + path: z.never().optional(), 1593 + query: z.object({ 1594 + parameterObject: z.object({ 1595 + first: z.object({ 1596 + second: z.object({ 1597 + third: z.string().optional() 1598 + }).optional() 1599 + }).optional() 1600 + }), 1601 + parameterReference: zModelWithString 1602 + }) 1588 1603 }); 1589 1604 1590 1605 /** 1591 - * Parameter containing reference 1592 - */ 1593 - export const zComplexTypesParameterParameterReference = zModelWithString; 1594 - 1595 - /** 1596 1606 * Successful response 1597 1607 */ 1598 1608 export const zComplexTypesResponse = z.array(zModelWithString); 1609 + 1610 + export const zMultipartResponseData = z.object({ 1611 + body: z.never().optional(), 1612 + headers: z.never().optional(), 1613 + path: z.never().optional(), 1614 + query: z.never().optional() 1615 + }); 1599 1616 1600 1617 /** 1601 1618 * OK ··· 1609 1626 }); 1610 1627 1611 1628 export const zMultipartRequestData = z.object({ 1612 - content: z.string().optional(), 1613 - data: z.union([ 1614 - zModelWithString, 1615 - z.null() 1616 - ]).optional() 1629 + body: z.object({ 1630 + content: z.string().optional(), 1631 + data: z.union([ 1632 + zModelWithString, 1633 + z.null() 1634 + ]).optional() 1635 + }).optional(), 1636 + headers: z.never().optional(), 1637 + path: z.never().optional(), 1638 + query: z.never().optional() 1617 1639 }); 1618 1640 1619 1641 export const zComplexParamsData = z.object({ 1620 - key: z.union([ 1621 - z.string().max(64).regex(/^[a-zA-Z0-9_]*$/).readonly(), 1622 - z.null() 1623 - ]).readonly(), 1624 - name: z.union([ 1625 - z.string().max(255), 1626 - z.null() 1627 - ]), 1628 - enabled: z.boolean().optional().default(true), 1629 - type: z.enum([ 1630 - 'Monkey', 1631 - 'Horse', 1632 - 'Bird' 1633 - ]), 1634 - listOfModels: z.union([ 1635 - z.array(zModelWithString), 1636 - z.null() 1637 - ]).optional(), 1638 - listOfStrings: z.union([ 1639 - z.array(z.string()), 1640 - z.null() 1641 - ]).optional(), 1642 - parameters: z.union([ 1643 - zModelWithString, 1644 - zModelWithEnum, 1645 - zModelWithArray, 1646 - zModelWithDictionary 1647 - ]), 1648 - user: z.object({ 1649 - id: z.number().int().readonly().optional(), 1642 + body: z.object({ 1643 + key: z.union([ 1644 + z.string().max(64).regex(/^[a-zA-Z0-9_]*$/).readonly(), 1645 + z.null() 1646 + ]).readonly(), 1650 1647 name: z.union([ 1651 - z.string().readonly(), 1648 + z.string().max(255), 1652 1649 z.null() 1653 - ]).readonly().optional() 1654 - }).readonly().optional() 1650 + ]), 1651 + enabled: z.boolean().optional().default(true), 1652 + type: z.enum([ 1653 + 'Monkey', 1654 + 'Horse', 1655 + 'Bird' 1656 + ]), 1657 + listOfModels: z.union([ 1658 + z.array(zModelWithString), 1659 + z.null() 1660 + ]).optional(), 1661 + listOfStrings: z.union([ 1662 + z.array(z.string()), 1663 + z.null() 1664 + ]).optional(), 1665 + parameters: z.union([ 1666 + zModelWithString, 1667 + zModelWithEnum, 1668 + zModelWithArray, 1669 + zModelWithDictionary 1670 + ]), 1671 + user: z.object({ 1672 + id: z.number().int().readonly().optional(), 1673 + name: z.union([ 1674 + z.string().readonly(), 1675 + z.null() 1676 + ]).readonly().optional() 1677 + }).readonly().optional() 1678 + }).optional(), 1679 + headers: z.never().optional(), 1680 + path: z.object({ 1681 + id: z.number().int(), 1682 + 'api-version': z.string() 1683 + }), 1684 + query: z.never().optional() 1655 1685 }); 1656 1686 1657 - export const zComplexParamsParameterId = z.number().int(); 1658 - 1659 - /** 1660 - * api-version should be required in standalone clients 1661 - */ 1662 - export const zComplexParamsParameterApiVersion = z.string(); 1663 - 1664 1687 /** 1665 1688 * Success 1666 1689 */ 1667 1690 export const zComplexParamsResponse = zModelWithString; 1668 1691 1669 - /** 1670 - * Status code to return 1671 - */ 1672 - export const zTestErrorCodeParameterStatus = z.number().int(); 1692 + export const zCallWithResultFromHeaderData = z.object({ 1693 + body: z.never().optional(), 1694 + headers: z.never().optional(), 1695 + path: z.never().optional(), 1696 + query: z.never().optional() 1697 + }); 1673 1698 1674 - /** 1675 - * Dummy input param 1676 - */ 1677 - export const zNonAsciiæøåÆøÅöôêÊ字符串ParameterNonAsciiParamæøåÆøÅöôêÊ = z.number().int(); 1699 + export const zTestErrorCodeData = z.object({ 1700 + body: z.never().optional(), 1701 + headers: z.never().optional(), 1702 + path: z.never().optional(), 1703 + query: z.object({ 1704 + status: z.number().int() 1705 + }) 1706 + }); 1707 + 1708 + export const zNonAsciiæøåÆøÅöôêÊ字符串Data = z.object({ 1709 + body: z.never().optional(), 1710 + headers: z.never().optional(), 1711 + path: z.never().optional(), 1712 + query: z.object({ 1713 + 'nonAsciiParamæøåÆØÅöôêÊ': z.number().int() 1714 + }) 1715 + }); 1678 1716 1679 1717 /** 1680 1718 * Successful response 1681 1719 */ 1682 1720 export const zNonAsciiæøåÆøÅöôêÊ字符串Response = z.array(zNonAsciiStringæøåÆøÅöôêÊ字符串); 1683 1721 1684 - export const zPutWithFormUrlEncodedData = zArrayWithStrings; 1722 + export const zPutWithFormUrlEncodedData = z.object({ 1723 + body: zArrayWithStrings, 1724 + headers: z.never().optional(), 1725 + path: z.never().optional(), 1726 + query: z.never().optional() 1727 + });
+7
packages/openapi-ts-tests/test/__snapshots__/3.1.x/plugins/@hey-api/transformers/type-format-zod/zod.gen.ts
··· 12 12 foo: z.number().int() 13 13 }); 14 14 15 + export const zPostFooData = z.object({ 16 + body: z.never().optional(), 17 + headers: z.never().optional(), 18 + path: z.never().optional(), 19 + query: z.never().optional() 20 + }); 21 + 15 22 /** 16 23 * OK 17 24 */
+4 -1
packages/openapi-ts-tests/test/__snapshots__/3.1.x/plugins/valibot/default/valibot.gen.ts
··· 1089 1089 /** 1090 1090 * foo in method 1091 1091 */ 1092 - export const vGetApiVbyApiVersionSimpleOperationParameterFooParam = v.string(); 1092 + export const vGetApiVbyApiVersionSimpleOperationParameterFooParam = v.union([ 1093 + v.string(), 1094 + v.pipe(v.string(), v.uuid()) 1095 + ]); 1093 1096 1094 1097 /** 1095 1098 * Response is a simple number
+539 -493
packages/openapi-ts-tests/test/__snapshots__/3.1.x/plugins/zod/default/zod.gen.ts
··· 1058 1058 */ 1059 1059 export const zSimpleFormData = zModelWithString; 1060 1060 1061 - export const zImportData = z.union([ 1062 - zModelWithReadOnlyAndWriteOnly, 1063 - zModelWithArrayReadOnlyAndWriteOnly 1064 - ]); 1061 + export const zExportData = z.object({ 1062 + body: z.never().optional(), 1063 + headers: z.never().optional(), 1064 + path: z.never().optional(), 1065 + query: z.never().optional() 1066 + }); 1067 + 1068 + export const zPatchApiVbyApiVersionNoTagData = z.object({ 1069 + body: z.never().optional(), 1070 + headers: z.never().optional(), 1071 + path: z.never().optional(), 1072 + query: z.never().optional() 1073 + }); 1074 + 1075 + export const zImportData = z.object({ 1076 + body: z.union([ 1077 + zModelWithReadOnlyAndWriteOnly, 1078 + zModelWithArrayReadOnlyAndWriteOnly 1079 + ]), 1080 + headers: z.never().optional(), 1081 + path: z.never().optional(), 1082 + query: z.never().optional() 1083 + }); 1065 1084 1066 1085 export const zImportResponse = z.union([ 1067 1086 zModelFromZendesk, 1068 1087 zModelWithReadOnlyAndWriteOnly 1069 1088 ]); 1070 1089 1090 + export const zFooWowData = z.object({ 1091 + body: z.never().optional(), 1092 + headers: z.never().optional(), 1093 + path: z.never().optional(), 1094 + query: z.never().optional() 1095 + }); 1096 + 1097 + export const zApiVVersionODataControllerCountData = z.object({ 1098 + body: z.never().optional(), 1099 + headers: z.never().optional(), 1100 + path: z.never().optional(), 1101 + query: z.never().optional() 1102 + }); 1103 + 1071 1104 /** 1072 1105 * Success 1073 1106 */ 1074 1107 export const zApiVVersionODataControllerCountResponse = zModelFromZendesk; 1075 1108 1076 - /** 1077 - * foo in method 1078 - */ 1079 - export const zGetApiVbyApiVersionSimpleOperationParameterFooParam = z.string(); 1109 + export const zGetApiVbyApiVersionSimpleOperationData = z.object({ 1110 + body: z.never().optional(), 1111 + headers: z.never().optional(), 1112 + path: z.object({ 1113 + foo_param: z.union([ 1114 + z.string(), 1115 + z.string().uuid() 1116 + ]) 1117 + }), 1118 + query: z.never().optional() 1119 + }); 1080 1120 1081 1121 /** 1082 1122 * Response is a simple number 1083 1123 */ 1084 1124 export const zGetApiVbyApiVersionSimpleOperationResponse = z.number(); 1085 1125 1086 - /** 1087 - * foo in method 1088 - */ 1089 - export const zDeleteFooParameterFooParam = z.string(); 1090 - 1091 - /** 1092 - * bar in method 1093 - */ 1094 - export const zDeleteFooParameterBarParam = z.string(); 1095 - 1096 - /** 1097 - * Parameter with illegal characters 1098 - */ 1099 - export const zDeleteFooParameterXFooBar = zModelWithString; 1100 - 1101 - /** 1102 - * Testing multiline comments in string: First line 1103 - * Second line 1104 - * 1105 - * Fourth line 1106 - */ 1107 - export const zCallWithDescriptionsParameterParameterWithBreaks = z.string(); 1108 - 1109 - /** 1110 - * Testing backticks in string: `backticks` and ```multiple backticks``` should work 1111 - */ 1112 - export const zCallWithDescriptionsParameterParameterWithBackticks = z.string(); 1113 - 1114 - /** 1115 - * Testing slashes in string: \backwards\\\ and /forwards/// should work 1116 - */ 1117 - export const zCallWithDescriptionsParameterParameterWithSlashes = z.string(); 1118 - 1119 - /** 1120 - * Testing expression placeholders in string: ${expression} should work 1121 - */ 1122 - export const zCallWithDescriptionsParameterParameterWithExpressionPlaceholders = z.string(); 1123 - 1124 - /** 1125 - * Testing quotes in string: 'single quote''' and "double quotes""" should work 1126 - */ 1127 - export const zCallWithDescriptionsParameterParameterWithQuotes = z.string(); 1128 - 1129 - /** 1130 - * Testing reserved characters in string: * inline * and ** inline ** should work 1131 - */ 1132 - export const zCallWithDescriptionsParameterParameterWithReservedCharacters = z.string(); 1133 - 1134 - /** 1135 - * This parameter is deprecated 1136 - * @deprecated 1137 - */ 1138 - export const zDeprecatedCallParameterParameter = z.union([ 1139 - zDeprecatedModel, 1140 - z.null() 1141 - ]); 1142 - 1143 - /** 1144 - * This is the parameter that goes into the body 1145 - */ 1146 - export const zCallWithParametersData = z.union([ 1147 - z.object({}), 1148 - z.null() 1149 - ]); 1150 - 1151 - /** 1152 - * This is the parameter that goes into the cookie 1153 - */ 1154 - export const zCallWithParametersParameterParameterCookie = z.union([ 1155 - z.string(), 1156 - z.null() 1157 - ]); 1158 - 1159 - /** 1160 - * This is the parameter that goes into the header 1161 - */ 1162 - export const zCallWithParametersParameterParameterHeader = z.union([ 1163 - z.string(), 1164 - z.null() 1165 - ]); 1126 + export const zDeleteCallWithoutParametersAndResponseData = z.object({ 1127 + body: z.never().optional(), 1128 + headers: z.never().optional(), 1129 + path: z.never().optional(), 1130 + query: z.never().optional() 1131 + }); 1166 1132 1167 - /** 1168 - * This is the parameter that goes into the path 1169 - */ 1170 - export const zCallWithParametersParameterParameterPath = z.union([ 1171 - z.string(), 1172 - z.null() 1173 - ]); 1133 + export const zGetCallWithoutParametersAndResponseData = z.object({ 1134 + body: z.never().optional(), 1135 + headers: z.never().optional(), 1136 + path: z.never().optional(), 1137 + query: z.never().optional() 1138 + }); 1174 1139 1175 - /** 1176 - * api-version should be required in standalone clients 1177 - */ 1178 - export const zCallWithParametersParameterApiVersion = z.union([ 1179 - z.string(), 1180 - z.null() 1181 - ]); 1140 + export const zHeadCallWithoutParametersAndResponseData = z.object({ 1141 + body: z.never().optional(), 1142 + headers: z.never().optional(), 1143 + path: z.never().optional(), 1144 + query: z.never().optional() 1145 + }); 1182 1146 1183 - export const zCallWithParametersParameterFooRefEnum = zModelWithNestedArrayEnumsDataFoo; 1147 + export const zOptionsCallWithoutParametersAndResponseData = z.object({ 1148 + body: z.never().optional(), 1149 + headers: z.never().optional(), 1150 + path: z.never().optional(), 1151 + query: z.never().optional() 1152 + }); 1184 1153 1185 - export const zCallWithParametersParameterFooAllOfEnum = zModelWithNestedArrayEnumsDataFoo; 1154 + export const zPatchCallWithoutParametersAndResponseData = z.object({ 1155 + body: z.never().optional(), 1156 + headers: z.never().optional(), 1157 + path: z.never().optional(), 1158 + query: z.never().optional() 1159 + }); 1186 1160 1187 - /** 1188 - * This is the parameter that goes into the query params 1189 - */ 1190 - export const zCallWithParametersParameterCursor = z.union([ 1191 - z.string(), 1192 - z.null() 1193 - ]); 1161 + export const zPostCallWithoutParametersAndResponseData = z.object({ 1162 + body: z.never().optional(), 1163 + headers: z.never().optional(), 1164 + path: z.never().optional(), 1165 + query: z.never().optional() 1166 + }); 1194 1167 1195 - /** 1196 - * This is the parameter that goes into the body 1197 - */ 1198 - export const zCallWithWeirdParameterNamesData = z.union([ 1199 - zModelWithString, 1200 - z.null() 1201 - ]); 1202 - 1203 - /** 1204 - * This is the parameter that goes into the cookie 1205 - */ 1206 - export const zCallWithWeirdParameterNamesParameterParameterCookie = z.union([ 1207 - z.string(), 1208 - z.null() 1209 - ]); 1210 - 1211 - /** 1212 - * This is the parameter that goes into the request header 1213 - */ 1214 - export const zCallWithWeirdParameterNamesParameterParameterHeader = z.union([ 1215 - z.string(), 1216 - z.null() 1217 - ]); 1218 - 1219 - /** 1220 - * This is the parameter that goes into the path 1221 - */ 1222 - export const zCallWithWeirdParameterNamesParameterParameterPath1 = z.string(); 1223 - 1224 - /** 1225 - * This is the parameter that goes into the path 1226 - */ 1227 - export const zCallWithWeirdParameterNamesParameterParameterPath2 = z.string(); 1168 + export const zPutCallWithoutParametersAndResponseData = z.object({ 1169 + body: z.never().optional(), 1170 + headers: z.never().optional(), 1171 + path: z.never().optional(), 1172 + query: z.never().optional() 1173 + }); 1228 1174 1229 - /** 1230 - * This is the parameter that goes into the path 1231 - */ 1232 - export const zCallWithWeirdParameterNamesParameterParameterPath3 = z.string(); 1175 + export const zDeleteFooData3 = z.object({ 1176 + body: z.never().optional(), 1177 + headers: z.object({ 1178 + 'x-Foo-Bar': zModelWithString 1179 + }), 1180 + path: z.object({ 1181 + foo_param: z.string(), 1182 + BarParam: z.string() 1183 + }), 1184 + query: z.never().optional() 1185 + }); 1233 1186 1234 - /** 1235 - * api-version should be required in standalone clients 1236 - */ 1237 - export const zCallWithWeirdParameterNamesParameterApiVersion = z.union([ 1238 - z.string(), 1239 - z.null() 1240 - ]); 1187 + export const zCallWithDescriptionsData = z.object({ 1188 + body: z.never().optional(), 1189 + headers: z.never().optional(), 1190 + path: z.never().optional(), 1191 + query: z.object({ 1192 + parameterWithBreaks: z.string().optional(), 1193 + parameterWithBackticks: z.string().optional(), 1194 + parameterWithSlashes: z.string().optional(), 1195 + parameterWithExpressionPlaceholders: z.string().optional(), 1196 + parameterWithQuotes: z.string().optional(), 1197 + parameterWithReservedCharacters: z.string().optional() 1198 + }).optional() 1199 + }); 1241 1200 1242 - /** 1243 - * This is the parameter with a reserved keyword 1244 - */ 1245 - export const zCallWithWeirdParameterNamesParameterDefault = z.string(); 1201 + export const zDeprecatedCallData = z.object({ 1202 + body: z.never().optional(), 1203 + headers: z.object({ 1204 + parameter: z.union([ 1205 + zDeprecatedModel, 1206 + z.null() 1207 + ]) 1208 + }).optional(), 1209 + path: z.never().optional(), 1210 + query: z.never().optional() 1211 + }); 1246 1212 1247 - /** 1248 - * This is the parameter that goes into the request query params 1249 - */ 1250 - export const zCallWithWeirdParameterNamesParameterParameterQuery = z.union([ 1251 - z.string(), 1252 - z.null() 1253 - ]); 1213 + export const zCallWithParametersData = z.object({ 1214 + body: z.union([ 1215 + z.object({}), 1216 + z.null() 1217 + ]), 1218 + headers: z.object({ 1219 + parameterHeader: z.union([ 1220 + z.string(), 1221 + z.null() 1222 + ]) 1223 + }), 1224 + path: z.object({ 1225 + parameterPath: z.union([ 1226 + z.string(), 1227 + z.null() 1228 + ]), 1229 + 'api-version': z.union([ 1230 + z.string(), 1231 + z.null() 1232 + ]) 1233 + }), 1234 + query: z.object({ 1235 + foo_ref_enum: zModelWithNestedArrayEnumsDataFoo.optional(), 1236 + foo_all_of_enum: zModelWithNestedArrayEnumsDataFoo, 1237 + cursor: z.union([ 1238 + z.string(), 1239 + z.null() 1240 + ]) 1241 + }) 1242 + }); 1254 1243 1255 - /** 1256 - * This is a required parameter 1257 - */ 1258 - export const zGetCallWithOptionalParamData = zModelWithOneOfEnum; 1244 + export const zCallWithWeirdParameterNamesData = z.object({ 1245 + body: z.union([ 1246 + zModelWithString, 1247 + z.null() 1248 + ]), 1249 + headers: z.object({ 1250 + 'parameter.header': z.union([ 1251 + z.string(), 1252 + z.null() 1253 + ]) 1254 + }), 1255 + path: z.object({ 1256 + 'parameter.path.1': z.string().optional(), 1257 + 'parameter-path-2': z.string().optional(), 1258 + 'PARAMETER-PATH-3': z.string().optional(), 1259 + 'api-version': z.union([ 1260 + z.string(), 1261 + z.null() 1262 + ]) 1263 + }), 1264 + query: z.object({ 1265 + default: z.string().optional(), 1266 + 'parameter-query': z.union([ 1267 + z.string(), 1268 + z.null() 1269 + ]) 1270 + }) 1271 + }); 1259 1272 1260 - /** 1261 - * This is an optional parameter 1262 - */ 1263 - export const zGetCallWithOptionalParamParameterPage = z.number(); 1273 + export const zGetCallWithOptionalParamData = z.object({ 1274 + body: zModelWithOneOfEnum, 1275 + headers: z.never().optional(), 1276 + path: z.never().optional(), 1277 + query: z.object({ 1278 + page: z.number().optional() 1279 + }).optional() 1280 + }); 1264 1281 1265 - /** 1266 - * This is an optional parameter 1267 - */ 1268 1282 export const zPostCallWithOptionalParamData = z.object({ 1269 - offset: z.union([ 1270 - z.number(), 1271 - z.null() 1272 - ]).optional() 1283 + body: z.object({ 1284 + offset: z.union([ 1285 + z.number(), 1286 + z.null() 1287 + ]).optional() 1288 + }).optional(), 1289 + headers: z.never().optional(), 1290 + path: z.never().optional(), 1291 + query: z.object({ 1292 + parameter: zPageable 1293 + }) 1273 1294 }); 1274 1295 1275 - /** 1276 - * This is a required parameter 1277 - */ 1278 - export const zPostCallWithOptionalParamParameterParameter = zPageable; 1279 - 1280 1296 export const zPostCallWithOptionalParamResponse = z.union([ 1281 1297 z.number(), 1282 1298 z.void() 1283 1299 ]); 1284 1300 1285 - /** 1286 - * A reusable request body 1287 - */ 1288 - export const zPostApiVbyApiVersionRequestBodyData = zSimpleRequestBody; 1301 + export const zPostApiVbyApiVersionRequestBodyData = z.object({ 1302 + body: zSimpleRequestBody.optional(), 1303 + headers: z.never().optional(), 1304 + path: z.never().optional(), 1305 + query: z.object({ 1306 + parameter: z.string().optional() 1307 + }).optional() 1308 + }); 1289 1309 1290 - /** 1291 - * This is a reusable parameter 1292 - */ 1293 - export const zPostApiVbyApiVersionRequestBodyParameterParameter = z.string(); 1310 + export const zPostApiVbyApiVersionFormDataData = z.object({ 1311 + body: zSimpleFormData.optional(), 1312 + headers: z.never().optional(), 1313 + path: z.never().optional(), 1314 + query: z.object({ 1315 + parameter: z.string().optional() 1316 + }).optional() 1317 + }); 1294 1318 1295 - /** 1296 - * A reusable request body 1297 - */ 1298 - export const zPostApiVbyApiVersionFormDataData = zSimpleFormData; 1299 - 1300 - /** 1301 - * This is a reusable parameter 1302 - */ 1303 - export const zPostApiVbyApiVersionFormDataParameterParameter = z.string(); 1304 - 1305 - /** 1306 - * This is a simple string with default value 1307 - */ 1308 - export const zCallWithDefaultParametersParameterParameterString = z.union([ 1309 - z.string().default('Hello World!'), 1310 - z.null() 1311 - ]).default('Hello World!'); 1312 - 1313 - /** 1314 - * This is a simple number with default value 1315 - */ 1316 - export const zCallWithDefaultParametersParameterParameterNumber = z.union([ 1317 - z.number().default(123), 1318 - z.null() 1319 - ]).default(123); 1320 - 1321 - /** 1322 - * This is a simple boolean with default value 1323 - */ 1324 - export const zCallWithDefaultParametersParameterParameterBoolean = z.union([ 1325 - z.boolean().default(true), 1326 - z.null() 1327 - ]).default(true); 1328 - 1329 - /** 1330 - * This is a simple enum with default value 1331 - */ 1332 - export const zCallWithDefaultParametersParameterParameterEnum = z.enum([ 1333 - 'Success', 1334 - 'Warning', 1335 - 'Error' 1336 - ]); 1337 - 1338 - /** 1339 - * This is a simple model with default value 1340 - */ 1341 - export const zCallWithDefaultParametersParameterParameterModel = z.union([ 1342 - zModelWithString, 1343 - z.null() 1344 - ]); 1345 - 1346 - /** 1347 - * This is a simple string that is optional with default value 1348 - */ 1349 - export const zCallWithDefaultOptionalParametersParameterParameterString = z.string().default('Hello World!'); 1350 - 1351 - /** 1352 - * This is a simple number that is optional with default value 1353 - */ 1354 - export const zCallWithDefaultOptionalParametersParameterParameterNumber = z.number().default(123); 1355 - 1356 - /** 1357 - * This is a simple boolean that is optional with default value 1358 - */ 1359 - export const zCallWithDefaultOptionalParametersParameterParameterBoolean = z.boolean().default(true); 1360 - 1361 - /** 1362 - * This is a simple enum that is optional with default value 1363 - */ 1364 - export const zCallWithDefaultOptionalParametersParameterParameterEnum = z.enum([ 1365 - 'Success', 1366 - 'Warning', 1367 - 'Error' 1368 - ]); 1369 - 1370 - /** 1371 - * This is a simple model that is optional with default value 1372 - */ 1373 - export const zCallWithDefaultOptionalParametersParameterParameterModel = zModelWithString; 1374 - 1375 - /** 1376 - * This is a optional string with default 1377 - */ 1378 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithDefault = z.string().default('Hello World!'); 1319 + export const zCallWithDefaultParametersData = z.object({ 1320 + body: z.never().optional(), 1321 + headers: z.never().optional(), 1322 + path: z.never().optional(), 1323 + query: z.object({ 1324 + parameterString: z.union([ 1325 + z.string().default('Hello World!'), 1326 + z.null() 1327 + ]).optional().default('Hello World!'), 1328 + parameterNumber: z.union([ 1329 + z.number().default(123), 1330 + z.null() 1331 + ]).optional().default(123), 1332 + parameterBoolean: z.union([ 1333 + z.boolean().default(true), 1334 + z.null() 1335 + ]).optional().default(true), 1336 + parameterEnum: z.enum([ 1337 + 'Success', 1338 + 'Warning', 1339 + 'Error' 1340 + ]).optional(), 1341 + parameterModel: z.union([ 1342 + zModelWithString, 1343 + z.null() 1344 + ]).optional() 1345 + }).optional() 1346 + }); 1379 1347 1380 - /** 1381 - * This is a optional string with empty default 1382 - */ 1383 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithEmptyDefault = z.string().default(''); 1348 + export const zCallWithDefaultOptionalParametersData = z.object({ 1349 + body: z.never().optional(), 1350 + headers: z.never().optional(), 1351 + path: z.never().optional(), 1352 + query: z.object({ 1353 + parameterString: z.string().optional().default('Hello World!'), 1354 + parameterNumber: z.number().optional().default(123), 1355 + parameterBoolean: z.boolean().optional().default(true), 1356 + parameterEnum: z.enum([ 1357 + 'Success', 1358 + 'Warning', 1359 + 'Error' 1360 + ]).optional(), 1361 + parameterModel: zModelWithString.optional() 1362 + }).optional() 1363 + }); 1384 1364 1385 - /** 1386 - * This is a optional string with no default 1387 - */ 1388 - export const zCallToTestOrderOfParamsParameterParameterOptionalStringWithNoDefault = z.string(); 1365 + export const zCallToTestOrderOfParamsData = z.object({ 1366 + body: z.never().optional(), 1367 + headers: z.never().optional(), 1368 + path: z.never().optional(), 1369 + query: z.object({ 1370 + parameterOptionalStringWithDefault: z.string().optional().default('Hello World!'), 1371 + parameterOptionalStringWithEmptyDefault: z.string().optional().default(''), 1372 + parameterOptionalStringWithNoDefault: z.string().optional(), 1373 + parameterStringWithDefault: z.string().default('Hello World!'), 1374 + parameterStringWithEmptyDefault: z.string().default(''), 1375 + parameterStringWithNoDefault: z.string(), 1376 + parameterStringNullableWithNoDefault: z.union([ 1377 + z.string(), 1378 + z.null() 1379 + ]).optional(), 1380 + parameterStringNullableWithDefault: z.union([ 1381 + z.string(), 1382 + z.null() 1383 + ]).optional().default(null) 1384 + }) 1385 + }); 1389 1386 1390 - /** 1391 - * This is a string with default 1392 - */ 1393 - export const zCallToTestOrderOfParamsParameterParameterStringWithDefault = z.string().default('Hello World!'); 1387 + export const zDuplicateNameData = z.object({ 1388 + body: z.never().optional(), 1389 + headers: z.never().optional(), 1390 + path: z.never().optional(), 1391 + query: z.never().optional() 1392 + }); 1394 1393 1395 - /** 1396 - * This is a string with empty default 1397 - */ 1398 - export const zCallToTestOrderOfParamsParameterParameterStringWithEmptyDefault = z.string().default(''); 1394 + export const zDuplicateName2Data = z.object({ 1395 + body: z.never().optional(), 1396 + headers: z.never().optional(), 1397 + path: z.never().optional(), 1398 + query: z.never().optional() 1399 + }); 1399 1400 1400 - /** 1401 - * This is a string with no default 1402 - */ 1403 - export const zCallToTestOrderOfParamsParameterParameterStringWithNoDefault = z.string(); 1401 + export const zDuplicateName3Data = z.object({ 1402 + body: z.never().optional(), 1403 + headers: z.never().optional(), 1404 + path: z.never().optional(), 1405 + query: z.never().optional() 1406 + }); 1404 1407 1405 - /** 1406 - * This is a string that can be null with no default 1407 - */ 1408 - export const zCallToTestOrderOfParamsParameterParameterStringNullableWithNoDefault = z.union([ 1409 - z.string(), 1410 - z.null() 1411 - ]); 1408 + export const zDuplicateName4Data = z.object({ 1409 + body: z.never().optional(), 1410 + headers: z.never().optional(), 1411 + path: z.never().optional(), 1412 + query: z.never().optional() 1413 + }); 1412 1414 1413 - /** 1414 - * This is a string that can be null with default 1415 - */ 1416 - export const zCallToTestOrderOfParamsParameterParameterStringNullableWithDefault = z.union([ 1417 - z.string(), 1418 - z.null() 1419 - ]).default(null); 1415 + export const zCallWithNoContentResponseData = z.object({ 1416 + body: z.never().optional(), 1417 + headers: z.never().optional(), 1418 + path: z.never().optional(), 1419 + query: z.never().optional() 1420 + }); 1420 1421 1421 1422 /** 1422 1423 * Success 1423 1424 */ 1424 1425 export const zCallWithNoContentResponseResponse = z.void(); 1425 1426 1427 + export const zCallWithResponseAndNoContentResponseData = z.object({ 1428 + body: z.never().optional(), 1429 + headers: z.never().optional(), 1430 + path: z.never().optional(), 1431 + query: z.never().optional() 1432 + }); 1433 + 1426 1434 export const zCallWithResponseAndNoContentResponseResponse = z.union([ 1427 1435 z.number(), 1428 1436 z.void() 1429 1437 ]); 1430 1438 1439 + export const zDummyAData = z.object({ 1440 + body: z.never().optional(), 1441 + headers: z.never().optional(), 1442 + path: z.never().optional(), 1443 + query: z.never().optional() 1444 + }); 1445 + 1431 1446 export const zDummyAResponse = z400; 1432 1447 1448 + export const zDummyBData = z.object({ 1449 + body: z.never().optional(), 1450 + headers: z.never().optional(), 1451 + path: z.never().optional(), 1452 + query: z.never().optional() 1453 + }); 1454 + 1433 1455 /** 1434 1456 * Success 1435 1457 */ 1436 1458 export const zDummyBResponse = z.void(); 1437 1459 1460 + export const zCallWithResponseData = z.object({ 1461 + body: z.never().optional(), 1462 + headers: z.never().optional(), 1463 + path: z.never().optional(), 1464 + query: z.never().optional() 1465 + }); 1466 + 1438 1467 export const zCallWithResponseResponse = zImport; 1439 1468 1469 + export const zCallWithDuplicateResponsesData = z.object({ 1470 + body: z.never().optional(), 1471 + headers: z.never().optional(), 1472 + path: z.never().optional(), 1473 + query: z.never().optional() 1474 + }); 1475 + 1440 1476 export const zCallWithDuplicateResponsesResponse = z.union([ 1441 1477 zModelWithBoolean.and(zModelWithInteger), 1442 1478 zModelWithString 1443 1479 ]); 1444 1480 1481 + export const zCallWithResponsesData = z.object({ 1482 + body: z.never().optional(), 1483 + headers: z.never().optional(), 1484 + path: z.never().optional(), 1485 + query: z.never().optional() 1486 + }); 1487 + 1445 1488 export const zCallWithResponsesResponse = z.union([ 1446 1489 z.object({ 1447 1490 '@namespace.string': z.string().readonly().optional(), ··· 1452 1495 zModelThatExtendsExtends 1453 1496 ]); 1454 1497 1455 - /** 1456 - * This is an array parameter that is sent as csv format (comma-separated values) 1457 - */ 1458 - export const zCollectionFormatParameterParameterArrayCsv = z.union([ 1459 - z.array(z.string()), 1460 - z.null() 1461 - ]); 1462 - 1463 - /** 1464 - * This is an array parameter that is sent as ssv format (space-separated values) 1465 - */ 1466 - export const zCollectionFormatParameterParameterArraySsv = z.union([ 1467 - z.array(z.string()), 1468 - z.null() 1469 - ]); 1470 - 1471 - /** 1472 - * This is an array parameter that is sent as tsv format (tab-separated values) 1473 - */ 1474 - export const zCollectionFormatParameterParameterArrayTsv = z.union([ 1475 - z.array(z.string()), 1476 - z.null() 1477 - ]); 1478 - 1479 - /** 1480 - * This is an array parameter that is sent as pipes format (pipe-separated values) 1481 - */ 1482 - export const zCollectionFormatParameterParameterArrayPipes = z.union([ 1483 - z.array(z.string()), 1484 - z.null() 1485 - ]); 1486 - 1487 - /** 1488 - * This is an array parameter that is sent as multi format (multiple parameter instances) 1489 - */ 1490 - export const zCollectionFormatParameterParameterArrayMulti = z.union([ 1491 - z.array(z.string()), 1492 - z.null() 1493 - ]); 1494 - 1495 - /** 1496 - * This is a number parameter 1497 - */ 1498 - export const zTypesParameterId = z.number().int(); 1499 - 1500 - /** 1501 - * This is a number parameter 1502 - */ 1503 - export const zTypesParameterParameterNumber = z.number().default(123); 1504 - 1505 - /** 1506 - * This is a string parameter 1507 - */ 1508 - export const zTypesParameterParameterString = z.union([ 1509 - z.string().default('default'), 1510 - z.null() 1511 - ]).default('default'); 1512 - 1513 - /** 1514 - * This is a boolean parameter 1515 - */ 1516 - export const zTypesParameterParameterBoolean = z.union([ 1517 - z.boolean().default(true), 1518 - z.null() 1519 - ]).default(true); 1520 - 1521 - /** 1522 - * This is an object parameter 1523 - */ 1524 - export const zTypesParameterParameterObject = z.union([ 1525 - z.object({}), 1526 - z.null() 1527 - ]).default(null); 1528 - 1529 - /** 1530 - * This is an array parameter 1531 - */ 1532 - export const zTypesParameterParameterArray = z.union([ 1533 - z.array(z.string()), 1534 - z.null() 1535 - ]); 1536 - 1537 - /** 1538 - * This is a dictionary parameter 1539 - */ 1540 - export const zTypesParameterParameterDictionary = z.union([ 1541 - z.object({}), 1542 - z.null() 1543 - ]); 1498 + export const zCollectionFormatData = z.object({ 1499 + body: z.never().optional(), 1500 + headers: z.never().optional(), 1501 + path: z.never().optional(), 1502 + query: z.object({ 1503 + parameterArrayCSV: z.union([ 1504 + z.array(z.string()), 1505 + z.null() 1506 + ]), 1507 + parameterArraySSV: z.union([ 1508 + z.array(z.string()), 1509 + z.null() 1510 + ]), 1511 + parameterArrayTSV: z.union([ 1512 + z.array(z.string()), 1513 + z.null() 1514 + ]), 1515 + parameterArrayPipes: z.union([ 1516 + z.array(z.string()), 1517 + z.null() 1518 + ]), 1519 + parameterArrayMulti: z.union([ 1520 + z.array(z.string()), 1521 + z.null() 1522 + ]) 1523 + }) 1524 + }); 1544 1525 1545 - /** 1546 - * This is an enum parameter 1547 - */ 1548 - export const zTypesParameterParameterEnum = z.union([ 1549 - z.literal('Success'), 1550 - z.literal('Warning'), 1551 - z.literal('Error'), 1552 - z.null() 1553 - ]); 1526 + export const zTypesData = z.object({ 1527 + body: z.never().optional(), 1528 + headers: z.never().optional(), 1529 + path: z.object({ 1530 + id: z.number().int().optional() 1531 + }).optional(), 1532 + query: z.object({ 1533 + parameterNumber: z.number().default(123), 1534 + parameterString: z.union([ 1535 + z.string().default('default'), 1536 + z.null() 1537 + ]).default('default'), 1538 + parameterBoolean: z.union([ 1539 + z.boolean().default(true), 1540 + z.null() 1541 + ]).default(true), 1542 + parameterObject: z.union([ 1543 + z.object({}), 1544 + z.null() 1545 + ]).default(null), 1546 + parameterArray: z.union([ 1547 + z.array(z.string()), 1548 + z.null() 1549 + ]), 1550 + parameterDictionary: z.union([ 1551 + z.object({}), 1552 + z.null() 1553 + ]), 1554 + parameterEnum: z.union([ 1555 + z.literal('Success'), 1556 + z.literal('Warning'), 1557 + z.literal('Error'), 1558 + z.null() 1559 + ]) 1560 + }) 1561 + }); 1554 1562 1555 1563 export const zTypesResponse = z.union([ 1556 1564 z.number(), ··· 1559 1567 z.object({}) 1560 1568 ]); 1561 1569 1562 - export const zUploadFileData = z.string(); 1563 - 1564 - /** 1565 - * api-version should be required in standalone clients 1566 - */ 1567 - export const zUploadFileParameterApiVersion = z.union([ 1568 - z.string(), 1569 - z.null() 1570 - ]); 1570 + export const zUploadFileData = z.object({ 1571 + body: z.string(), 1572 + headers: z.never().optional(), 1573 + path: z.object({ 1574 + 'api-version': z.union([ 1575 + z.string(), 1576 + z.null() 1577 + ]) 1578 + }), 1579 + query: z.never().optional() 1580 + }); 1571 1581 1572 1582 export const zUploadFileResponse = z.boolean(); 1573 1583 1574 - export const zFileResponseParameterId = z.string(); 1575 - 1576 - /** 1577 - * api-version should be required in standalone clients 1578 - */ 1579 - export const zFileResponseParameterApiVersion = z.string(); 1584 + export const zFileResponseData = z.object({ 1585 + body: z.never().optional(), 1586 + headers: z.never().optional(), 1587 + path: z.object({ 1588 + id: z.string(), 1589 + 'api-version': z.string() 1590 + }), 1591 + query: z.never().optional() 1592 + }); 1580 1593 1581 1594 /** 1582 1595 * Success 1583 1596 */ 1584 1597 export const zFileResponseResponse = z.string(); 1585 1598 1586 - /** 1587 - * Parameter containing object 1588 - */ 1589 - export const zComplexTypesParameterParameterObject = z.object({ 1590 - first: z.object({ 1591 - second: z.object({ 1592 - third: z.string().optional() 1593 - }).optional() 1594 - }).optional() 1599 + export const zComplexTypesData = z.object({ 1600 + body: z.never().optional(), 1601 + headers: z.never().optional(), 1602 + path: z.never().optional(), 1603 + query: z.object({ 1604 + parameterObject: z.object({ 1605 + first: z.object({ 1606 + second: z.object({ 1607 + third: z.string().optional() 1608 + }).optional() 1609 + }).optional() 1610 + }), 1611 + parameterReference: zModelWithString 1612 + }) 1595 1613 }); 1596 1614 1597 1615 /** 1598 - * Parameter containing reference 1599 - */ 1600 - export const zComplexTypesParameterParameterReference = zModelWithString; 1601 - 1602 - /** 1603 1616 * Successful response 1604 1617 */ 1605 1618 export const zComplexTypesResponse = z.array(zModelWithString); 1619 + 1620 + export const zMultipartResponseData = z.object({ 1621 + body: z.never().optional(), 1622 + headers: z.never().optional(), 1623 + path: z.never().optional(), 1624 + query: z.never().optional() 1625 + }); 1606 1626 1607 1627 /** 1608 1628 * OK ··· 1616 1636 }); 1617 1637 1618 1638 export const zMultipartRequestData = z.object({ 1619 - content: z.string().optional(), 1620 - data: z.union([ 1621 - zModelWithString, 1622 - z.null() 1623 - ]).optional() 1639 + body: z.object({ 1640 + content: z.string().optional(), 1641 + data: z.union([ 1642 + zModelWithString, 1643 + z.null() 1644 + ]).optional() 1645 + }).optional(), 1646 + headers: z.never().optional(), 1647 + path: z.never().optional(), 1648 + query: z.never().optional() 1624 1649 }); 1625 1650 1626 1651 export const zComplexParamsData = z.object({ 1627 - key: z.union([ 1628 - z.string().max(64).regex(/^[a-zA-Z0-9_]*$/).readonly(), 1629 - z.null() 1630 - ]).readonly(), 1631 - name: z.union([ 1632 - z.string().max(255), 1633 - z.null() 1634 - ]), 1635 - enabled: z.boolean().optional().default(true), 1636 - type: z.enum([ 1637 - 'Monkey', 1638 - 'Horse', 1639 - 'Bird' 1640 - ]), 1641 - listOfModels: z.union([ 1642 - z.array(zModelWithString), 1643 - z.null() 1644 - ]).optional(), 1645 - listOfStrings: z.union([ 1646 - z.array(z.string()), 1647 - z.null() 1648 - ]).optional(), 1649 - parameters: z.union([ 1650 - zModelWithString, 1651 - zModelWithEnum, 1652 - zModelWithArray, 1653 - zModelWithDictionary 1654 - ]), 1655 - user: z.object({ 1656 - id: z.number().int().readonly().optional(), 1652 + body: z.object({ 1653 + key: z.union([ 1654 + z.string().max(64).regex(/^[a-zA-Z0-9_]*$/).readonly(), 1655 + z.null() 1656 + ]).readonly(), 1657 1657 name: z.union([ 1658 - z.string().readonly(), 1658 + z.string().max(255), 1659 1659 z.null() 1660 - ]).readonly().optional() 1661 - }).readonly().optional() 1660 + ]), 1661 + enabled: z.boolean().optional().default(true), 1662 + type: z.enum([ 1663 + 'Monkey', 1664 + 'Horse', 1665 + 'Bird' 1666 + ]), 1667 + listOfModels: z.union([ 1668 + z.array(zModelWithString), 1669 + z.null() 1670 + ]).optional(), 1671 + listOfStrings: z.union([ 1672 + z.array(z.string()), 1673 + z.null() 1674 + ]).optional(), 1675 + parameters: z.union([ 1676 + zModelWithString, 1677 + zModelWithEnum, 1678 + zModelWithArray, 1679 + zModelWithDictionary 1680 + ]), 1681 + user: z.object({ 1682 + id: z.number().int().readonly().optional(), 1683 + name: z.union([ 1684 + z.string().readonly(), 1685 + z.null() 1686 + ]).readonly().optional() 1687 + }).readonly().optional() 1688 + }).optional(), 1689 + headers: z.never().optional(), 1690 + path: z.object({ 1691 + id: z.number().int(), 1692 + 'api-version': z.string() 1693 + }), 1694 + query: z.never().optional() 1662 1695 }); 1663 1696 1664 - export const zComplexParamsParameterId = z.number().int(); 1665 - 1666 - /** 1667 - * api-version should be required in standalone clients 1668 - */ 1669 - export const zComplexParamsParameterApiVersion = z.string(); 1670 - 1671 1697 /** 1672 1698 * Success 1673 1699 */ 1674 1700 export const zComplexParamsResponse = zModelWithString; 1675 1701 1676 - /** 1677 - * Status code to return 1678 - */ 1679 - export const zTestErrorCodeParameterStatus = z.number().int(); 1702 + export const zCallWithResultFromHeaderData = z.object({ 1703 + body: z.never().optional(), 1704 + headers: z.never().optional(), 1705 + path: z.never().optional(), 1706 + query: z.never().optional() 1707 + }); 1680 1708 1681 - /** 1682 - * Dummy input param 1683 - */ 1684 - export const zNonAsciiæøåÆøÅöôêÊ字符串ParameterNonAsciiParamæøåÆøÅöôêÊ = z.number().int(); 1709 + export const zTestErrorCodeData = z.object({ 1710 + body: z.never().optional(), 1711 + headers: z.never().optional(), 1712 + path: z.never().optional(), 1713 + query: z.object({ 1714 + status: z.number().int() 1715 + }) 1716 + }); 1717 + 1718 + export const zNonAsciiæøåÆøÅöôêÊ字符串Data = z.object({ 1719 + body: z.never().optional(), 1720 + headers: z.never().optional(), 1721 + path: z.never().optional(), 1722 + query: z.object({ 1723 + 'nonAsciiParamæøåÆØÅöôêÊ': z.number().int() 1724 + }) 1725 + }); 1685 1726 1686 1727 /** 1687 1728 * Successful response 1688 1729 */ 1689 1730 export const zNonAsciiæøåÆøÅöôêÊ字符串Response = z.array(zNonAsciiStringæøåÆøÅöôêÊ字符串); 1690 1731 1691 - export const zPutWithFormUrlEncodedData = zArrayWithStrings; 1732 + export const zPutWithFormUrlEncodedData = z.object({ 1733 + body: zArrayWithStrings, 1734 + headers: z.never().optional(), 1735 + path: z.never().optional(), 1736 + query: z.never().optional() 1737 + });
+20 -17
packages/openapi-ts-tests/test/__snapshots__/3.1.x/validators-metadata/zod.gen.ts
··· 38 38 }); 39 39 40 40 export const zPatchFooData = z.object({ 41 - foo: z.string().optional() 41 + body: z.object({ 42 + foo: z.string().optional() 43 + }), 44 + headers: z.never().optional(), 45 + path: z.never().optional(), 46 + query: z.object({ 47 + foo: z.string().describe('This is Foo parameter.').optional(), 48 + bar: zBar.optional(), 49 + baz: z.object({ 50 + baz: z.string().optional() 51 + }).optional(), 52 + qux: z.string().date().optional(), 53 + quux: z.string().datetime().optional() 54 + }).optional() 42 55 }); 43 56 44 - /** 45 - * This is Foo parameter. 46 - */ 47 - export const zPatchFooParameterFoo = z.string().describe('This is Foo parameter.'); 48 - 49 - export const zPatchFooParameterBar = zBar; 50 - 51 - export const zPatchFooParameterBaz = z.object({ 52 - baz: z.string().optional() 53 - }); 54 - 55 - export const zPatchFooParameterQux = z.string().date(); 56 - 57 - export const zPatchFooParameterQuux = z.string().datetime(); 58 - 59 - export const zPostFooData = zFoo3; 57 + export const zPostFooData = z.object({ 58 + body: zFoo3, 59 + headers: z.never().optional(), 60 + path: z.never().optional(), 61 + query: z.never().optional() 62 + });
+20 -17
packages/openapi-ts-tests/test/__snapshots__/3.1.x/validators/zod.gen.ts
··· 38 38 }); 39 39 40 40 export const zPatchFooData = z.object({ 41 - foo: z.string().optional() 41 + body: z.object({ 42 + foo: z.string().optional() 43 + }), 44 + headers: z.never().optional(), 45 + path: z.never().optional(), 46 + query: z.object({ 47 + foo: z.string().optional(), 48 + bar: zBar.optional(), 49 + baz: z.object({ 50 + baz: z.string().optional() 51 + }).optional(), 52 + qux: z.string().date().optional(), 53 + quux: z.string().datetime().optional() 54 + }).optional() 42 55 }); 43 56 44 - /** 45 - * This is Foo parameter. 46 - */ 47 - export const zPatchFooParameterFoo = z.string(); 48 - 49 - export const zPatchFooParameterBar = zBar; 50 - 51 - export const zPatchFooParameterBaz = z.object({ 52 - baz: z.string().optional() 53 - }); 54 - 55 - export const zPatchFooParameterQux = z.string().date(); 56 - 57 - export const zPatchFooParameterQuux = z.string().datetime(); 58 - 59 - export const zPostFooData = zFoo3; 57 + export const zPostFooData = z.object({ 58 + body: zFoo3, 59 + headers: z.never().optional(), 60 + path: z.never().optional(), 61 + query: z.never().optional() 62 + });
+16 -6
packages/openapi-ts-tests/test/openapi-ts.config.ts
··· 57 57 // 'invalid', 58 58 // 'servers-entry.yaml', 59 59 // ), 60 - path: path.resolve(__dirname, 'spec', '3.1.x', 'full.yaml'), 60 + path: path.resolve(__dirname, 'spec', '3.1.x', 'validators.yaml'), 61 61 // path: path.resolve(__dirname, 'spec', 'v3-transforms.json'), 62 62 // path: 'http://localhost:4000/', 63 63 // path: 'https://get.heyapi.dev/', ··· 124 124 // responseStyle: 'data', 125 125 // throwOnError: true, 126 126 // transformer: '@hey-api/transformers', 127 - transformer: true, 128 - // validator: 'zod', 127 + // transformer: true, 128 + validator: 'zod', 129 129 }, 130 130 { 131 131 // bigInt: true, 132 132 dates: true, 133 - name: '@hey-api/transformers', 133 + // name: '@hey-api/transformers', 134 134 }, 135 135 { 136 136 enums: 'typescript+namespace', ··· 152 152 infiniteQueryKeyNameBuilder: '{{name}}IQK', 153 153 infiniteQueryOptionsNameBuilder: '{{name}}InfiniteQuery', 154 154 mutationOptionsNameBuilder: '{{name}}MutationOptions', 155 - name: '@tanstack/react-query', 155 + // name: '@tanstack/react-query', 156 156 queryKeyNameBuilder: '{{name}}QK', 157 157 queryOptionsNameBuilder: '{{name}}Query', 158 158 }, 159 159 { 160 160 // comments: false, 161 161 // exportFromIndex: true, 162 - name: 'valibot', 162 + // name: 'valibot', 163 163 }, 164 164 { 165 + // case: 'snake_case', 165 166 // comments: false, 167 + definitions: 'z{{name}}Definition', 166 168 // exportFromIndex: true, 167 169 // metadata: true, 168 170 name: 'zod', 171 + requests: { 172 + // case: 'SCREAMING_SNAKE_CASE', 173 + // name: 'z{{name}}TestData', 174 + }, 175 + responses: { 176 + // case: 'snake_case', 177 + // name: 'z{{name}}TestResponse', 178 + }, 169 179 }, 170 180 ], 171 181 // useOptions: false,
+37 -1
packages/openapi-ts/src/generate/__tests__/files.test.ts
··· 166 166 created: true, 167 167 name: 'prefixUser', 168 168 }); 169 - expect(identifiers).toHaveProperty('user', { 169 + expect(identifiers).toHaveProperty('prefixuser', { 170 170 type: { 171 171 '#/components/User': { 172 172 $ref: '#/components/User', ··· 209 209 }, 210 210 user2: { 211 211 $ref: '#/components/User', 212 + name: 'user2', 213 + }, 214 + }, 215 + }); 216 + }); 217 + 218 + it('resolves naming conflicts with name transformer by appending count', () => { 219 + const identifiers: Identifiers = { 220 + user: { 221 + type: { 222 + user: { $ref: '#/components/Other', name: 'user' }, 223 + }, 224 + }, 225 + }; 226 + 227 + const result = ensureUniqueIdentifier({ 228 + $ref: '#/components/Foo', 229 + case: 'camelCase', 230 + create: true, 231 + identifiers, 232 + nameTransformer: () => 'user', 233 + namespace: 'type', 234 + }); 235 + 236 + expect(result).toEqual({ 237 + created: true, 238 + name: 'user2', 239 + }); 240 + expect(identifiers).toHaveProperty('user2', { 241 + type: { 242 + '#/components/Foo': { 243 + $ref: '#/components/Foo', 244 + name: 'user2', 245 + }, 246 + user2: { 247 + $ref: '#/components/Foo', 212 248 name: 'user2', 213 249 }, 214 250 },
+22 -14
packages/openapi-ts/src/generate/files.ts
··· 171 171 EnsureUniqueIdentifierData, 172 172 '$ref' | 'count' | 'create' | 'nameTransformer' 173 173 > & { 174 + case?: StringCase; 174 175 namespace: Namespace; 175 176 }, 176 177 ): Identifier { 177 178 return ensureUniqueIdentifier({ 178 - case: this._identifierCase, 179 + case: args.case ?? this._identifierCase, 179 180 identifiers: this.identifiers, 180 181 ...args, 181 182 }); ··· 407 408 }; 408 409 }; 409 410 411 + const transformName = ( 412 + name: string, 413 + transformer: ((name: string) => string) | string, 414 + identifierCase?: StringCase, 415 + ): string => { 416 + if (typeof transformer === 'function') { 417 + return transformer(name); 418 + } 419 + 420 + const separator = identifierCase === 'preserve' ? '' : '-'; 421 + return transformer.replace('{{name}}', `${separator}${name}${separator}`); 422 + }; 423 + 410 424 interface EnsureUniqueIdentifierData { 411 425 $ref: string; 412 426 case: StringCase | undefined; ··· 416 430 /** 417 431 * Transforms name obtained from `$ref` before it's passed to `stringCase()`. 418 432 */ 419 - nameTransformer?: (name: string) => string; 433 + nameTransformer?: ((name: string) => string) | string; 420 434 namespace: Namespace; 421 435 } 422 436 ··· 438 452 }; 439 453 } 440 454 441 - let nameWithCasing = stringCase({ 455 + let nameWithCasingAndTransformer = stringCase({ 442 456 case: identifierCase, 443 - value: name, 457 + value: nameTransformer 458 + ? transformName(name, nameTransformer, identifierCase) 459 + : name, 444 460 }); 445 461 if (count > 1) { 446 - nameWithCasing = `${nameWithCasing}${count}`; 462 + nameWithCasingAndTransformer = `${nameWithCasingAndTransformer}${count}`; 447 463 } 448 - const lowercaseName = nameWithCasing.toLocaleLowerCase(); 464 + const lowercaseName = nameWithCasingAndTransformer.toLocaleLowerCase(); 449 465 if (!identifiers[lowercaseName]) { 450 466 identifiers[lowercaseName] = {}; 451 467 } ··· 483 499 created: false, 484 500 name: name as string, 485 501 }; 486 - } 487 - 488 - let nameWithCasingAndTransformer = stringCase({ 489 - case: identifierCase, 490 - value: nameTransformer?.(name) ?? name, 491 - }); 492 - if (count > 1) { 493 - nameWithCasingAndTransformer = `${nameWithCasingAndTransformer}${count}`; 494 502 } 495 503 496 504 let nameValue = id[nameWithCasingAndTransformer];
+35 -1
packages/openapi-ts/src/initConfigs.ts
··· 158 158 `missing plugin - no plugin with tag "${tag}" found`, 159 159 ); 160 160 }, 161 + valueToObject: ({ defaultValue, mappers, value }) => { 162 + let result = { ...defaultValue }; 163 + switch (typeof value) { 164 + case 'boolean': 165 + if ('boolean' in mappers) { 166 + const mapper = mappers.boolean as ( 167 + value: boolean, 168 + ) => Record<string, any>; 169 + result = { ...result, ...mapper(value) }; 170 + } 171 + break; 172 + case 'number': 173 + if ('number' in mappers) { 174 + const mapper = mappers.number as ( 175 + value: number, 176 + ) => Record<string, any>; 177 + result = { ...result, ...mapper(value) }; 178 + } 179 + break; 180 + case 'string': 181 + if ('string' in mappers) { 182 + const mapper = mappers.string as ( 183 + value: string, 184 + ) => Record<string, any>; 185 + result = { ...result, ...mapper(value) }; 186 + } 187 + break; 188 + case 'object': 189 + if (value !== null) { 190 + result = { ...result, ...value }; 191 + } 192 + break; 193 + } 194 + return result; 195 + }, 161 196 }; 162 - // @ts-expect-error 163 197 plugin.resolveConfig(plugin, context); 164 198 } 165 199
+66
packages/openapi-ts/src/ir/__tests__/schema.test.ts
··· 1 + import { describe, expect, it } from 'vitest'; 2 + 3 + import { deduplicateSchema } from '../schema'; 4 + import type { IR } from '../types'; 5 + 6 + describe('deduplicateSchema', () => { 7 + const scenarios: ReadonlyArray<{ 8 + description: string; 9 + detectFormat?: boolean; 10 + result: IR.SchemaObject; 11 + schema: IR.SchemaObject; 12 + }> = [ 13 + { 14 + description: 'keeps multiple strings if they have different formats', 15 + result: { 16 + items: [ 17 + { 18 + format: 'uuid', 19 + type: 'string', 20 + }, 21 + { 22 + type: 'string', 23 + }, 24 + ], 25 + logicalOperator: 'or', 26 + }, 27 + schema: { 28 + items: [ 29 + { 30 + format: 'uuid', 31 + type: 'string', 32 + }, 33 + { 34 + type: 'string', 35 + }, 36 + ], 37 + logicalOperator: 'or', 38 + }, 39 + }, 40 + { 41 + description: 42 + 'discards duplicate strings if they have different formats and `detectFormat` is `false`', 43 + detectFormat: false, 44 + result: { 45 + format: 'uuid', 46 + type: 'string', 47 + }, 48 + schema: { 49 + items: [ 50 + { 51 + format: 'uuid', 52 + type: 'string', 53 + }, 54 + { 55 + type: 'string', 56 + }, 57 + ], 58 + logicalOperator: 'or', 59 + }, 60 + }, 61 + ]; 62 + 63 + it.each(scenarios)('$description', ({ detectFormat, result, schema }) => { 64 + expect(deduplicateSchema({ detectFormat, schema })).toEqual(result); 65 + }); 66 + });
+4 -2
packages/openapi-ts/src/ir/parser.ts
··· 7 7 export const parseIR = async ({ context }: { context: IR.Context }) => { 8 8 await context.broadcast('before'); 9 9 10 - for (const server of context.ir.servers ?? []) { 11 - await context.broadcast('server', { server }); 10 + if (context.ir.servers) { 11 + for (const server of context.ir.servers) { 12 + await context.broadcast('server', { server }); 13 + } 12 14 } 13 15 14 16 if (context.ir.components) {
+21 -13
packages/openapi-ts/src/ir/schema.ts
··· 4 4 * Ensure we don't produce redundant types, e.g. string | string. 5 5 */ 6 6 export const deduplicateSchema = <T extends IR.SchemaObject>({ 7 + detectFormat = true, 7 8 schema, 8 9 }: { 10 + detectFormat?: boolean; 9 11 schema: T; 10 12 }): T => { 11 13 if (!schema.items) { ··· 35 37 ) { 36 38 // const needs namespace to handle empty string values, otherwise 37 39 // fallback would equal an actual value and we would skip an item 38 - const typeId = `${item.$ref ?? ''}${item.type ?? ''}${item.const !== undefined ? `const-${item.const}` : ''}`; 40 + const constant = item.const !== undefined ? `const-${item.const}` : ''; 41 + const format = 42 + item.format !== undefined && detectFormat 43 + ? `format-${item.format}` 44 + : ''; 45 + const typeId = `${item.$ref ?? ''}${item.type ?? ''}${constant}${format}`; 39 46 if (!typeIds.includes(typeId)) { 40 47 typeIds.push(typeId); 41 48 uniqueItems.push(item); ··· 46 53 uniqueItems.push(item); 47 54 } 48 55 49 - schema.items = uniqueItems; 56 + let result = { ...schema }; 57 + result.items = uniqueItems; 50 58 51 59 if ( 52 - schema.items.length <= 1 && 53 - schema.type !== 'array' && 54 - schema.type !== 'enum' && 55 - schema.type !== 'tuple' 60 + result.items.length <= 1 && 61 + result.type !== 'array' && 62 + result.type !== 'enum' && 63 + result.type !== 'tuple' 56 64 ) { 57 65 // bring the only item up to clean up the schema 58 - const liftedSchema = schema.items[0]; 59 - delete schema.logicalOperator; 60 - delete schema.items; 61 - schema = { 62 - ...schema, 66 + const liftedSchema = result.items[0]; 67 + delete result.logicalOperator; 68 + delete result.items; 69 + result = { 70 + ...result, 63 71 ...liftedSchema, 64 72 }; 65 73 } 66 74 67 75 // exclude unknown if it's the only type left 68 - if (schema.type === 'unknown') { 76 + if (result.type === 'unknown') { 69 77 return {} as T; 70 78 } 71 79 72 - return schema; 80 + return result; 73 81 };
+1 -5
packages/openapi-ts/src/plugins/@hey-api/sdk/operation.ts
··· 406 406 } 407 407 } 408 408 409 - const responseValidator = createResponseValidator({ 410 - context, 411 - operation, 412 - plugin, 413 - }); 409 + const responseValidator = createResponseValidator({ operation, plugin }); 414 410 if (responseValidator) { 415 411 requestOptions.push({ 416 412 key: 'responseValidator',
+21 -21
packages/openapi-ts/src/plugins/@hey-api/sdk/validator.ts
··· 3 3 import { operationIrRef } from '../../shared/utils/ref'; 4 4 import type { Plugin } from '../../types'; 5 5 import { valibotId } from '../../valibot/constants'; 6 + import { nameTransformer } from '../../valibot/plugin'; 6 7 import { zodId } from '../../zod/plugin'; 7 8 import { sdkId } from './constants'; 8 9 import type { Config } from './types'; ··· 14 15 }; 15 16 16 17 const valibotResponseValidator = ({ 17 - context, 18 18 operation, 19 + plugin, 19 20 }: { 20 - context: IR.Context; 21 21 operation: IR.OperationObject; 22 + plugin: Plugin.Instance<Config>; 22 23 }) => { 23 - const file = context.file({ id: sdkId })!; 24 + const file = plugin.context.file({ id: sdkId })!; 24 25 25 - const identifierSchema = context.file({ id: valibotId })!.identifier({ 26 + const identifierSchema = plugin.context.file({ id: valibotId })!.identifier({ 26 27 $ref: operationIrRef({ 27 28 case: 'camelCase', 28 - config: context.config, 29 + config: plugin.context.config, 29 30 id: operation.id, 30 31 type: 'response', 31 32 }), 33 + // TODO: refactor to not have to define nameTransformer 34 + nameTransformer, 32 35 namespace: 'value', 33 36 }); 34 37 ··· 38 41 39 42 file.import({ 40 43 module: file.relativePathToFile({ 41 - context, 44 + context: plugin.context, 42 45 id: valibotId, 43 46 }), 44 47 name: identifierSchema.name, ··· 77 80 }; 78 81 79 82 const zodResponseValidator = ({ 80 - context, 81 83 operation, 84 + plugin, 82 85 }: { 83 - context: IR.Context; 84 86 operation: IR.OperationObject; 87 + plugin: Plugin.Instance<Config>; 85 88 }) => { 86 - const file = context.file({ id: sdkId })!; 89 + const file = plugin.context.file({ id: sdkId })!; 87 90 88 - const identifierSchema = context.file({ id: zodId })!.identifier({ 89 - $ref: operationIrRef({ 90 - case: 'camelCase', 91 - config: context.config, 92 - id: operation.id, 93 - type: 'response', 94 - }), 91 + const responses = plugin.getPlugin('zod')?.config.responses; 92 + const identifierSchema = plugin.context.file({ id: zodId })!.identifier({ 93 + // TODO: refactor for better cross-plugin compatibility 94 + $ref: `#/zod-response/${operation.id}`, 95 + // TODO: refactor to not have to define nameTransformer 96 + nameTransformer: typeof responses === 'object' ? responses.name : undefined, 95 97 namespace: 'value', 96 98 }); 97 99 ··· 101 103 102 104 file.import({ 103 105 module: file.relativePathToFile({ 104 - context, 106 + context: plugin.context, 105 107 id: zodId, 106 108 }), 107 109 name: identifierSchema.name, ··· 131 133 }; 132 134 133 135 export const createResponseValidator = ({ 134 - context, 135 136 operation, 136 137 plugin, 137 138 }: { 138 - context: IR.Context; 139 139 operation: IR.OperationObject; 140 140 plugin: Plugin.Instance<Config>; 141 141 }) => { 142 142 switch (plugin.config.validator) { 143 143 case 'valibot': 144 - return valibotResponseValidator({ context, operation }); 144 + return valibotResponseValidator({ operation, plugin }); 145 145 case 'zod': 146 - return zodResponseValidator({ context, operation }); 146 + return zodResponseValidator({ operation, plugin }); 147 147 default: 148 148 return; 149 149 }
+3 -2
packages/openapi-ts/src/plugins/@hey-api/typescript/plugin.ts
··· 367 367 ); 368 368 } 369 369 370 - schema = deduplicateSchema({ schema }); 370 + schema = deduplicateSchema({ detectFormat: false, schema }); 371 371 372 372 const itemTypes: Array<ts.TypeNode> = []; 373 373 ··· 859 859 const parameter = parameters[key]!; 860 860 861 861 properties[parameter.name] = deduplicateSchema({ 862 + detectFormat: false, 862 863 schema: parameter.schema, 863 864 }); 864 865 ··· 1233 1234 state, 1234 1235 }); 1235 1236 } else if (schema.items) { 1236 - schema = deduplicateSchema({ schema }); 1237 + schema = deduplicateSchema({ detectFormat: false, schema }); 1237 1238 if (schema.items) { 1238 1239 const itemTypes: Array<ts.TypeNode> = []; 1239 1240
+1 -5
packages/openapi-ts/src/plugins/index.ts
··· 128 128 | Plugin.Config<Zod>; 129 129 130 130 export const defaultPluginConfigs: { 131 - [K in PluginNames]: Plugin.Config<{ 132 - exportFromIndex?: any; 133 - name: any; 134 - output?: any; 135 - }>; 131 + [K in PluginNames]: any; 136 132 } = { 137 133 '@hey-api/client-axios': heyApiClientAxios, 138 134 '@hey-api/client-fetch': heyApiClientFetch,
+4 -2
packages/openapi-ts/src/plugins/shared/utils/config.ts
··· 1 1 import type { BaseConfig, Plugin } from '../../types'; 2 2 3 3 export const definePluginConfig = 4 - <Config extends BaseConfig>(defaultConfig: Plugin.Config<Config>) => 4 + <Config extends BaseConfig, ResolvedConfig extends BaseConfig = Config>( 5 + defaultConfig: Plugin.Config<Config, ResolvedConfig>, 6 + ) => 5 7 ( 6 8 userConfig?: Omit<Plugin.UserConfig<Config>, 'name'>, 7 - ): Omit<Plugin.Config<Config>, 'name'> & { 9 + ): Omit<Plugin.Config<Config, ResolvedConfig>, 'name'> & { 8 10 /** 9 11 * Cast name to `any` so it doesn't throw type error in `plugins` array. 10 12 * We could allow any `string` as plugin `name` in the object syntax, but
+1 -1
packages/openapi-ts/src/plugins/shared/utils/ref.ts
··· 50 50 affix, 51 51 ]; 52 52 if (parameterId) { 53 - parts.push(separator); 54 53 parts.push( 54 + separator, 55 55 stringCase({ 56 56 case: _case, 57 57 value: parameterId,
+43 -12
packages/openapi-ts/src/plugins/types.d.ts
··· 34 34 35 35 type PluginTag = 'client' | 'transformer' | 'validator'; 36 36 37 + type ObjectType<T> = 38 + Extract<T, Record<string, any>> extends never 39 + ? Record<string, any> 40 + : Extract<T, Record<string, any>>; 41 + 37 42 export interface PluginContext { 38 43 pluginByTag: <T extends AnyPluginName | boolean = AnyPluginName>( 39 44 tag: PluginTag, ··· 42 47 errorMessage?: string; 43 48 }, 44 49 ) => Exclude<T, boolean> | undefined; 50 + valueToObject: < 51 + T extends undefined | string | boolean | number | Record<string, any>, 52 + >(args: { 53 + defaultValue: ObjectType<T>; 54 + mappers: { 55 + boolean: T extends boolean 56 + ? (value: boolean) => Partial<ObjectType<T>> 57 + : never; 58 + number: T extends number 59 + ? (value: number) => Partial<ObjectType<T>> 60 + : never; 61 + string: T extends string 62 + ? (value: string) => Partial<ObjectType<T>> 63 + : never; 64 + } extends infer U 65 + ? { [K in keyof U as U[K] extends never ? never : K]: U[K] } 66 + : never; 67 + value: T; 68 + }) => ObjectType<T>; 45 69 } 46 70 47 71 export interface BaseConfig { ··· 54 78 output?: string; 55 79 } 56 80 57 - interface Meta<Config extends BaseConfig> { 81 + interface Meta< 82 + Config extends BaseConfig, 83 + ResolvedConfig extends BaseConfig = Config, 84 + > { 58 85 /** 59 86 * Dependency plugins will be always processed, regardless of whether user 60 87 * explicitly defines them in their `plugins` config. ··· 66 93 * should be used for validation. 67 94 */ 68 95 resolveConfig?: ( 69 - config: Omit<Plugin.Config<Config>, 'dependencies'> & { 96 + plugin: Omit<Plugin.Config<Config, ResolvedConfig>, 'dependencies'> & { 70 97 dependencies: Set<AnyPluginName>; 71 98 }, 72 99 context: PluginContext, ··· 82 109 * Public Plugin API. 83 110 */ 84 111 export namespace Plugin { 85 - export type Config<Config extends BaseConfig> = Pick< 86 - Config, 87 - 'name' | 'output' 88 - > & 89 - Meta<Config> & { 112 + export type Config< 113 + Config extends BaseConfig, 114 + ResolvedConfig extends BaseConfig = Config, 115 + > = Pick<Config, 'name' | 'output'> & 116 + Meta<Config, ResolvedConfig> & { 90 117 config: Omit<Config, 'name' | 'output'>; 91 118 handler: Plugin.Handler< 92 - Omit<Config, 'name'> & { 119 + Omit<ResolvedConfig, 'name'> & { 93 120 name: any; 94 121 } 95 122 >; 96 123 handlerLegacy: Plugin.LegacyHandler< 97 - Omit<Config, 'name'> & { 124 + Omit<ResolvedConfig, 'name'> & { 98 125 name: any; 99 126 } 100 127 >; 101 128 }; 102 129 103 130 /** @deprecated - use `definePluginConfig()` instead */ 104 - export type DefineConfig<Config extends BaseConfig> = ( 105 - config?: Plugin.UserConfig<Omit<Config, 'name'>>, 106 - ) => Omit<Plugin.Config<Config>, 'name'> & { 131 + export type DefineConfig< 132 + Config extends BaseConfig, 133 + ResolvedConfig extends BaseConfig = Config, 134 + > = (config?: Plugin.UserConfig<Omit<Config, 'name'>>) => Omit< 135 + Plugin.Config<Config, ResolvedConfig>, 136 + 'name' 137 + > & { 107 138 /** 108 139 * Cast name to `any` so it doesn't throw type error in `plugins` array. 109 140 * We could allow any `string` as plugin `name` in the object syntax, but
+1 -1
packages/openapi-ts/src/plugins/valibot/plugin.ts
··· 21 21 hasCircularReference: boolean; 22 22 } 23 23 24 - const nameTransformer = (name: string) => `v-${name}`; 24 + export const nameTransformer = (name: string) => `v-${name}`; 25 25 26 26 const pipesToExpression = (pipes: Array<ts.Expression>) => { 27 27 if (pipes.length === 1) {
+43 -2
packages/openapi-ts/src/plugins/zod/config.ts
··· 1 1 import { definePluginConfig } from '../shared/utils/config'; 2 2 import type { Plugin } from '../types'; 3 3 import { handler } from './plugin'; 4 - import type { Config } from './types'; 4 + import type { Config, ResolvedConfig } from './types'; 5 5 6 - export const defaultConfig: Plugin.Config<Config> = { 6 + export const defaultConfig: Plugin.Config<Config, ResolvedConfig> = { 7 7 config: { 8 + case: 'camelCase', 8 9 comments: true, 9 10 exportFromIndex: false, 10 11 metadata: false, ··· 13 14 handlerLegacy: () => {}, 14 15 name: 'zod', 15 16 output: 'zod', 17 + resolveConfig: (plugin, context) => { 18 + plugin.config.definitions = context.valueToObject({ 19 + defaultValue: { 20 + case: plugin.config.case ?? 'camelCase', 21 + enabled: true, 22 + name: 'z{{name}}', 23 + }, 24 + mappers: { 25 + boolean: (enabled) => ({ enabled }), 26 + string: (name) => ({ enabled: true, name }), 27 + }, 28 + value: plugin.config.definitions, 29 + }); 30 + 31 + plugin.config.requests = context.valueToObject({ 32 + defaultValue: { 33 + case: plugin.config.case ?? 'camelCase', 34 + enabled: true, 35 + name: 'z{{name}}Data', 36 + }, 37 + mappers: { 38 + boolean: (enabled) => ({ enabled }), 39 + string: (name) => ({ enabled: true, name }), 40 + }, 41 + value: plugin.config.requests, 42 + }); 43 + 44 + plugin.config.responses = context.valueToObject({ 45 + defaultValue: { 46 + case: plugin.config.case ?? 'camelCase', 47 + enabled: true, 48 + name: 'z{{name}}Response', 49 + }, 50 + mappers: { 51 + boolean: (enabled) => ({ enabled }), 52 + string: (name) => ({ enabled: true, name }), 53 + }, 54 + value: plugin.config.responses, 55 + }); 56 + }, 16 57 tags: ['validator'], 17 58 }; 18 59
+207 -128
packages/openapi-ts/src/plugins/zod/plugin.ts
··· 1 1 import ts from 'typescript'; 2 2 3 3 import { compiler } from '../../compiler'; 4 + import type { Identifier } from '../../generate/files'; 4 5 import { operationResponsesMap } from '../../ir/operation'; 6 + import { hasParameterGroupObjectRequired } from '../../ir/parameter'; 5 7 import { deduplicateSchema } from '../../ir/schema'; 6 8 import type { IR } from '../../ir/types'; 9 + import type { StringCase } from '../../types/config'; 7 10 import { numberRegExp } from '../../utils/regexp'; 8 - import { operationIrRef } from '../shared/utils/ref'; 9 11 import { createSchemaComment } from '../shared/utils/schema'; 10 12 import type { Plugin } from '../types'; 11 - import type { Config } from './types'; 13 + import type { ResolvedConfig } from './types'; 12 14 13 15 interface SchemaWithType<T extends Required<IR.SchemaObject>['type']> 14 16 extends Omit<IR.SchemaObject, 'type'> { 15 17 type: Extract<Required<IR.SchemaObject>['type'], T>; 16 18 } 17 19 18 - interface Result { 20 + interface State { 19 21 circularReferenceTracker: Set<string>; 20 22 hasCircularReference: boolean; 23 + nameCase: StringCase; 24 + nameTransformer: string | ((name: string) => string); 21 25 } 22 26 23 27 export const zodId = 'zod'; ··· 41 45 const unionIdentifier = compiler.identifier({ text: 'union' }); 42 46 const zIdentifier = compiler.identifier({ text: 'z' }); 43 47 44 - const nameTransformer = (name: string) => `z-${name}`; 45 - 46 48 const arrayTypeToZodSchema = ({ 47 49 context, 48 50 plugin, 49 - result, 50 51 schema, 52 + state, 51 53 }: { 52 54 context: IR.Context; 53 - plugin: Plugin.Instance<Config>; 54 - result: Result; 55 + plugin: Plugin.Instance<ResolvedConfig>; 55 56 schema: SchemaWithType<'array'>; 57 + state: State; 56 58 }): ts.CallExpression => { 57 59 const functionName = compiler.propertyAccessExpression({ 58 60 expression: zIdentifier, ··· 79 81 // at least one item is guaranteed 80 82 const itemExpressions = schema.items!.map((item) => 81 83 schemaToZodSchema({ 82 - context, 83 84 plugin, 84 - result, 85 85 schema: item, 86 + state, 86 87 }), 87 88 ); 88 89 ··· 383 384 }; 384 385 385 386 const objectTypeToZodSchema = ({ 386 - context, 387 387 plugin, 388 - result, 389 388 schema, 389 + state, 390 390 }: { 391 - context: IR.Context; 392 - plugin: Plugin.Instance<Config>; 393 - result: Result; 391 + plugin: Plugin.Instance<ResolvedConfig>; 394 392 schema: SchemaWithType<'object'>; 393 + state: State; 395 394 }): { 396 395 anyType: string; 397 396 expression: ts.CallExpression; ··· 410 409 const isRequired = required.includes(name); 411 410 412 411 const propertyExpression = schemaToZodSchema({ 413 - context, 414 412 optional: !isRequired, 415 413 plugin, 416 - result, 417 414 schema: property, 415 + state, 418 416 }); 419 417 420 418 numberRegExp.lastIndex = 0; ··· 469 467 // isRequired: true, 470 468 // name: 'key', 471 469 // type: schemaToZodSchema({ 472 - // context, 473 470 // schema: 474 471 // indexPropertyItems.length === 1 475 472 // ? indexPropertyItems[0] ··· 608 605 }; 609 606 610 607 const tupleTypeToZodSchema = ({ 611 - context, 612 608 plugin, 613 - result, 614 609 schema, 610 + state, 615 611 }: { 616 - context: IR.Context; 617 - plugin: Plugin.Instance<Config>; 618 - result: Result; 612 + plugin: Plugin.Instance<ResolvedConfig>; 619 613 schema: SchemaWithType<'tuple'>; 614 + state: State; 620 615 }) => { 621 616 if (schema.const && Array.isArray(schema.const)) { 622 617 const tupleElements = schema.const.map((value) => ··· 647 642 for (const item of schema.items ?? []) { 648 643 tupleElements.push( 649 644 schemaToZodSchema({ 650 - context, 651 645 plugin, 652 - result, 653 646 schema: item, 647 + state, 654 648 }), 655 649 ); 656 650 } ··· 720 714 const schemaTypeToZodSchema = ({ 721 715 context, 722 716 plugin, 723 - result, 724 717 schema, 718 + state, 725 719 }: { 726 720 context: IR.Context; 727 - plugin: Plugin.Instance<Config>; 728 - result: Result; 721 + plugin: Plugin.Instance<ResolvedConfig>; 729 722 schema: IR.SchemaObject; 723 + state: State; 730 724 }): { 731 725 anyType?: string; 732 726 expression: ts.Expression; ··· 737 731 expression: arrayTypeToZodSchema({ 738 732 context, 739 733 plugin, 740 - result, 741 734 schema: schema as SchemaWithType<'array'>, 735 + state, 742 736 }), 743 737 }; 744 738 case 'boolean': ··· 779 773 }; 780 774 case 'object': 781 775 return objectTypeToZodSchema({ 782 - context, 783 776 plugin, 784 - result, 785 777 schema: schema as SchemaWithType<'object'>, 778 + state, 786 779 }); 787 780 case 'string': 788 781 return { ··· 794 787 case 'tuple': 795 788 return { 796 789 expression: tupleTypeToZodSchema({ 797 - context, 798 790 plugin, 799 - result, 800 791 schema: schema as SchemaWithType<'tuple'>, 792 + state, 801 793 }), 802 794 }; 803 795 case 'undefined': ··· 825 817 }; 826 818 827 819 const operationToZodSchema = ({ 828 - context, 829 820 operation, 830 821 plugin, 831 - result, 822 + state, 832 823 }: { 833 - context: IR.Context; 834 824 operation: IR.OperationObject; 835 - plugin: Plugin.Instance<Config>; 836 - result: Result; 825 + plugin: Plugin.Instance<ResolvedConfig>; 826 + state: State; 837 827 }) => { 838 - if (operation.body) { 828 + const file = plugin.context.file({ id: zodId })!; 829 + 830 + if (plugin.config.requests.enabled) { 831 + const requiredProperties: Array<string> = []; 832 + if (operation.body?.required) { 833 + requiredProperties.push('body'); 834 + } 835 + 836 + const headersPropertyProperties: Record<string, IR.SchemaObject> = {}; 837 + const headersPropertyRequired: Array<string> = []; 838 + const pathPropertyProperties: Record<string, IR.SchemaObject> = {}; 839 + const pathPropertyRequired: Array<string> = []; 840 + const queryPropertyProperties: Record<string, IR.SchemaObject> = {}; 841 + const queryPropertyRequired: Array<string> = []; 842 + 843 + if (operation.parameters) { 844 + // TODO: add support for cookies 845 + 846 + if (operation.parameters.header) { 847 + if (hasParameterGroupObjectRequired(operation.parameters.path)) { 848 + requiredProperties.push('headers'); 849 + } 850 + 851 + for (const key in operation.parameters.header) { 852 + const parameter = operation.parameters.header[key]!; 853 + headersPropertyProperties[parameter.name] = parameter.schema; 854 + if (parameter.required) { 855 + headersPropertyRequired.push(parameter.name); 856 + } 857 + } 858 + } 859 + 860 + if (operation.parameters.path) { 861 + if (hasParameterGroupObjectRequired(operation.parameters.path)) { 862 + requiredProperties.push('path'); 863 + } 864 + 865 + for (const key in operation.parameters.path) { 866 + const parameter = operation.parameters.path[key]!; 867 + pathPropertyProperties[parameter.name] = parameter.schema; 868 + if (parameter.required) { 869 + pathPropertyRequired.push(parameter.name); 870 + } 871 + } 872 + } 873 + 874 + if (operation.parameters.query) { 875 + if (hasParameterGroupObjectRequired(operation.parameters.query)) { 876 + requiredProperties.push('query'); 877 + } 878 + 879 + for (const key in operation.parameters.query) { 880 + const parameter = operation.parameters.query[key]!; 881 + queryPropertyProperties[parameter.name] = parameter.schema; 882 + if (parameter.required) { 883 + queryPropertyRequired.push(parameter.name); 884 + } 885 + } 886 + } 887 + } 888 + 889 + const identifierData = file.identifier({ 890 + // TODO: refactor for better cross-plugin compatibility 891 + $ref: `#/zod-data/${operation.id}`, 892 + case: plugin.config.requests.case, 893 + create: true, 894 + nameTransformer: plugin.config.requests.name, 895 + namespace: 'value', 896 + }); 839 897 schemaToZodSchema({ 840 - $ref: operationIrRef({ 841 - case: 'camelCase', 842 - config: context.config, 843 - id: operation.id, 844 - type: 'data', 845 - }), 846 - context, 898 + // TODO: refactor for better cross-plugin compatibility 899 + $ref: `#/zod-data/${operation.id}`, 900 + identifier: identifierData, 847 901 plugin, 848 - result, 849 - schema: operation.body.schema, 902 + schema: { 903 + properties: { 904 + body: operation.body 905 + ? operation.body.schema 906 + : { 907 + type: 'never', 908 + }, 909 + headers: Object.keys(headersPropertyProperties).length 910 + ? { 911 + properties: headersPropertyProperties, 912 + required: headersPropertyRequired, 913 + type: 'object', 914 + } 915 + : { 916 + type: 'never', 917 + }, 918 + path: Object.keys(pathPropertyProperties).length 919 + ? { 920 + properties: pathPropertyProperties, 921 + required: pathPropertyRequired, 922 + type: 'object', 923 + } 924 + : { 925 + type: 'never', 926 + }, 927 + query: Object.keys(queryPropertyProperties).length 928 + ? { 929 + properties: queryPropertyProperties, 930 + required: queryPropertyRequired, 931 + type: 'object', 932 + } 933 + : { 934 + type: 'never', 935 + }, 936 + }, 937 + required: requiredProperties, 938 + type: 'object', 939 + }, 940 + state, 850 941 }); 851 942 } 852 943 853 - if (operation.parameters) { 854 - for (const type in operation.parameters) { 855 - const group = operation.parameters[type as keyof IR.ParametersObject]!; 856 - for (const key in group) { 857 - const parameter = group[key]!; 944 + if (plugin.config.responses.enabled) { 945 + if (operation.responses) { 946 + const { response } = operationResponsesMap(operation); 947 + 948 + if (response) { 949 + const identifierResponse = file.identifier({ 950 + // TODO: refactor for better cross-plugin compatibility 951 + $ref: `#/zod-response/${operation.id}`, 952 + case: plugin.config.responses.case, 953 + create: true, 954 + nameTransformer: plugin.config.responses.name, 955 + namespace: 'value', 956 + }); 858 957 schemaToZodSchema({ 859 - $ref: operationIrRef({ 860 - case: 'camelCase', 861 - config: context.config, 862 - id: operation.id, 863 - parameterId: parameter.name, 864 - type: 'parameter', 865 - }), 866 - context, 958 + // TODO: refactor for better cross-plugin compatibility 959 + $ref: `#/zod-response/${operation.id}`, 960 + identifier: identifierResponse, 867 961 plugin, 868 - result, 869 - schema: parameter.schema, 962 + schema: response, 963 + state, 870 964 }); 871 965 } 872 966 } 873 967 } 874 - 875 - if (operation.responses) { 876 - const { response } = operationResponsesMap(operation); 877 - 878 - if (response) { 879 - schemaToZodSchema({ 880 - $ref: operationIrRef({ 881 - case: 'camelCase', 882 - config: context.config, 883 - id: operation.id, 884 - type: 'response', 885 - }), 886 - context, 887 - plugin, 888 - result, 889 - schema: response, 890 - }); 891 - } 892 - } 893 968 }; 894 969 895 970 const schemaToZodSchema = ({ 896 971 $ref, 897 - context, 972 + identifier: _identifier, 898 973 optional, 899 974 plugin, 900 - result, 901 975 schema, 976 + state, 902 977 }: { 903 978 /** 904 979 * When $ref is supplied, a node will be emitted to the file. 905 980 */ 906 981 $ref?: string; 907 - context: IR.Context; 982 + identifier?: Identifier; 908 983 /** 909 984 * Accept `optional` to handle optional object properties. We can't handle 910 985 * this inside the object function because `.optional()` must come before 911 986 * `.default()` which is handled in this function. 912 987 */ 913 988 optional?: boolean; 914 - plugin: Plugin.Instance<Config>; 915 - result: Result; 989 + plugin: Plugin.Instance<ResolvedConfig>; 916 990 schema: IR.SchemaObject; 991 + state: State; 917 992 }): ts.Expression => { 918 - const file = context.file({ id: zodId })!; 993 + const file = plugin.context.file({ id: zodId })!; 919 994 920 995 let anyType: string | undefined; 921 996 let expression: ts.Expression | undefined; 922 - let identifier: ReturnType<typeof file.identifier> | undefined; 997 + let identifier: ReturnType<typeof file.identifier> | undefined = _identifier; 923 998 924 999 if ($ref) { 925 - result.circularReferenceTracker.add($ref); 1000 + state.circularReferenceTracker.add($ref); 926 1001 927 - identifier = file.identifier({ 928 - $ref, 929 - create: true, 930 - nameTransformer, 931 - namespace: 'value', 932 - }); 1002 + if (!identifier) { 1003 + identifier = file.identifier({ 1004 + $ref, 1005 + case: state.nameCase, 1006 + create: true, 1007 + nameTransformer: state.nameTransformer, 1008 + namespace: 'value', 1009 + }); 1010 + } 933 1011 } 934 1012 935 1013 if (schema.$ref) { 936 - const isCircularReference = result.circularReferenceTracker.has( 937 - schema.$ref, 938 - ); 1014 + const isCircularReference = state.circularReferenceTracker.has(schema.$ref); 939 1015 940 1016 // if $ref hasn't been processed yet, inline it to avoid the 941 1017 // "Block-scoped variable used before its declaration." error 942 1018 // this could be (maybe?) fixed by reshuffling the generation order 943 1019 let identifierRef = file.identifier({ 944 1020 $ref: schema.$ref, 945 - nameTransformer, 1021 + case: state.nameCase, 1022 + nameTransformer: state.nameTransformer, 946 1023 namespace: 'value', 947 1024 }); 948 1025 949 1026 if (!identifierRef.name) { 950 - const ref = context.resolveIrRef<IR.SchemaObject>(schema.$ref); 1027 + const ref = plugin.context.resolveIrRef<IR.SchemaObject>(schema.$ref); 951 1028 expression = schemaToZodSchema({ 952 1029 $ref: schema.$ref, 953 - context, 954 1030 plugin, 955 - result, 956 1031 schema: ref, 1032 + state, 957 1033 }); 958 1034 959 1035 identifierRef = file.identifier({ 960 1036 $ref: schema.$ref, 961 - nameTransformer, 1037 + case: state.nameCase, 1038 + nameTransformer: state.nameTransformer, 962 1039 namespace: 'value', 963 1040 }); 964 1041 } ··· 982 1059 }), 983 1060 ], 984 1061 }); 985 - result.hasCircularReference = true; 1062 + state.hasCircularReference = true; 986 1063 } else { 987 1064 expression = refIdentifier; 988 1065 } 989 1066 } 990 1067 } else if (schema.type) { 991 1068 const zodSchema = schemaTypeToZodSchema({ 992 - context, 1069 + context: plugin.context, 993 1070 plugin, 994 - result, 995 1071 schema, 1072 + state, 996 1073 }); 997 1074 anyType = zodSchema.anyType; 998 1075 expression = zodSchema.expression; ··· 1012 1089 if (schema.items) { 1013 1090 const itemTypes = schema.items.map((item) => 1014 1091 schemaToZodSchema({ 1015 - context, 1016 1092 plugin, 1017 - result, 1018 1093 schema: item, 1094 + state, 1019 1095 }), 1020 1096 ); 1021 1097 ··· 1062 1138 } 1063 1139 } else { 1064 1140 expression = schemaToZodSchema({ 1065 - context, 1066 1141 plugin, 1067 - result, 1068 1142 schema, 1143 + state, 1069 1144 }); 1070 1145 } 1071 1146 } else { 1072 1147 // catch-all fallback for failed schemas 1073 1148 const zodSchema = schemaTypeToZodSchema({ 1074 - context, 1149 + context: plugin.context, 1075 1150 plugin, 1076 - result, 1077 1151 schema: { 1078 1152 type: 'unknown', 1079 1153 }, 1154 + state, 1080 1155 }); 1081 1156 anyType = zodSchema.anyType; 1082 1157 expression = zodSchema.expression; 1083 1158 } 1084 1159 1085 1160 if ($ref) { 1086 - result.circularReferenceTracker.delete($ref); 1161 + state.circularReferenceTracker.delete($ref); 1087 1162 } 1088 1163 1089 1164 if (expression) { ··· 1132 1207 exportConst: true, 1133 1208 expression: expression!, 1134 1209 name: identifier.name, 1135 - typeName: result.hasCircularReference 1210 + typeName: state.hasCircularReference 1136 1211 ? (compiler.propertyAccessExpression({ 1137 1212 expression: zIdentifier, 1138 1213 name: anyType || 'ZodTypeAny', ··· 1145 1220 return expression!; 1146 1221 }; 1147 1222 1148 - export const handler: Plugin.Handler<Config> = ({ plugin }) => { 1223 + export const handler: Plugin.Handler<ResolvedConfig> = ({ plugin }) => { 1149 1224 const file = plugin.createFile({ 1150 1225 id: zodId, 1151 1226 identifierCase: 'camelCase', ··· 1158 1233 }); 1159 1234 1160 1235 plugin.subscribe('operation', ({ operation }) => { 1161 - const result: Result = { 1236 + const state: State = { 1162 1237 circularReferenceTracker: new Set(), 1163 1238 hasCircularReference: false, 1239 + nameCase: plugin.config.definitions.case, 1240 + nameTransformer: plugin.config.definitions.name, 1164 1241 }; 1165 1242 1166 1243 operationToZodSchema({ 1167 - context: plugin.context, 1168 1244 operation, 1169 1245 plugin, 1170 - result, 1246 + state, 1171 1247 }); 1172 1248 }); 1173 1249 1174 1250 plugin.subscribe('parameter', ({ $ref, parameter }) => { 1175 - const result: Result = { 1251 + const state: State = { 1176 1252 circularReferenceTracker: new Set(), 1177 1253 hasCircularReference: false, 1254 + nameCase: plugin.config.definitions.case, 1255 + nameTransformer: plugin.config.definitions.name, 1178 1256 }; 1179 1257 1180 1258 schemaToZodSchema({ 1181 1259 $ref, 1182 - context: plugin.context, 1183 1260 plugin, 1184 - result, 1185 1261 schema: parameter.schema, 1262 + state, 1186 1263 }); 1187 1264 }); 1188 1265 1189 1266 plugin.subscribe('requestBody', ({ $ref, requestBody }) => { 1190 - const result: Result = { 1267 + const state: State = { 1191 1268 circularReferenceTracker: new Set(), 1192 1269 hasCircularReference: false, 1270 + nameCase: plugin.config.definitions.case, 1271 + nameTransformer: plugin.config.definitions.name, 1193 1272 }; 1194 1273 1195 1274 schemaToZodSchema({ 1196 1275 $ref, 1197 - context: plugin.context, 1198 1276 plugin, 1199 - result, 1200 1277 schema: requestBody.schema, 1278 + state, 1201 1279 }); 1202 1280 }); 1203 1281 1204 1282 plugin.subscribe('schema', ({ $ref, schema }) => { 1205 - const result: Result = { 1283 + const state: State = { 1206 1284 circularReferenceTracker: new Set(), 1207 1285 hasCircularReference: false, 1286 + nameCase: plugin.config.definitions.case, 1287 + nameTransformer: plugin.config.definitions.name, 1208 1288 }; 1209 1289 1210 1290 schemaToZodSchema({ 1211 1291 $ref, 1212 - context: plugin.context, 1213 1292 plugin, 1214 - result, 1215 1293 schema, 1294 + state, 1216 1295 }); 1217 1296 }); 1218 1297 };
+216 -5
packages/openapi-ts/src/plugins/zod/types.d.ts
··· 1 - // import type { IR } from '../../ir/types'; 1 + import type { StringCase } from '../../types/config'; 2 2 import type { Plugin } from '../types'; 3 3 4 4 export interface Config extends Plugin.Name<'zod'> { 5 5 /** 6 + * The casing convention to use for generated names. 7 + * 8 + * @default 'camelCase' 9 + */ 10 + case?: StringCase; 11 + /** 6 12 * Add comments from input to the generated Zod schemas? 7 13 * 8 14 * @default true 9 15 */ 10 16 comments?: boolean; 11 17 /** 18 + * Configuration for reusable schema definitions. Controls generation of 19 + * shared Zod schemas that can be referenced across requests and responses. 20 + * 21 + * Can be: 22 + * - `boolean`: Shorthand for `{ enabled: boolean }` 23 + * - `string`: Shorthand for `{ enabled: true; name: string }` 24 + * - `object`: Full configuration object 25 + */ 26 + definitions?: 27 + | boolean 28 + | string 29 + | { 30 + /** 31 + * The casing convention to use for generated names. 32 + * 33 + * @default 'camelCase' 34 + */ 35 + case?: StringCase; 36 + /** 37 + * Whether to generate Zod schemas for reusable definitions. 38 + * 39 + * @default true 40 + */ 41 + enabled?: boolean; 42 + /** 43 + * Custom naming pattern for generated schema names. The name variable is 44 + * obtained from the schema name. 45 + * 46 + * @default 'z{{name}}' 47 + */ 48 + name?: string | ((name: string) => string); 49 + }; 50 + /** 12 51 * Should the exports from the generated files be re-exported in the index 13 52 * barrel file? 14 53 * ··· 24 63 */ 25 64 metadata?: boolean; 26 65 /** 27 - * Customise the Zod schema name. By default, `z{{name}}` is used, 28 - * where `name` is a definition name or an operation name. 66 + * Name of the generated file. 67 + * 68 + * @default 'zod' 69 + */ 70 + output?: string; 71 + /** 72 + * Configuration for request-specific Zod schemas. 73 + * Controls generation of Zod schemas for request bodies, query parameters, path parameters, and headers. 74 + * 75 + * Can be: 76 + * - `boolean`: Shorthand for `{ enabled: boolean }` 77 + * - `string`: Shorthand for `{ enabled: true; name: string }` 78 + * - `object`: Full configuration object 79 + */ 80 + requests?: 81 + | boolean 82 + | string 83 + | { 84 + /** 85 + * The casing convention to use for generated names. 86 + * 87 + * @default 'camelCase' 88 + */ 89 + case?: StringCase; 90 + /** 91 + * Whether to generate Zod schemas for request definitions. 92 + * 93 + * @default true 94 + */ 95 + enabled?: boolean; 96 + /** 97 + * Custom naming pattern for generated schema names. The name variable is 98 + * obtained from the operation name. 99 + * 100 + * @default 'z{{name}}Data' 101 + */ 102 + name?: string | ((name: string) => string); 103 + }; 104 + /** 105 + * Configuration for response-specific Zod schemas. 106 + * Controls generation of Zod schemas for response bodies, error responses, and status codes. 107 + * 108 + * Can be: 109 + * - `boolean`: Shorthand for `{ enabled: boolean }` 110 + * - `string`: Shorthand for `{ enabled: true; name: string }` 111 + * - `object`: Full configuration object 112 + */ 113 + responses?: 114 + | boolean 115 + | string 116 + | { 117 + /** 118 + * The casing convention to use for generated names. 119 + * 120 + * @default 'camelCase' 121 + */ 122 + case?: StringCase; 123 + /** 124 + * Whether to generate Zod schemas for response definitions. 125 + * 126 + * @default true 127 + */ 128 + enabled?: boolean; 129 + /** 130 + * Custom naming pattern for generated schema names. The name variable is 131 + * obtained from the operation name. 132 + * 133 + * @default 'z{{name}}Response' 134 + */ 135 + name?: string | ((name: string) => string); 136 + }; 137 + } 138 + 139 + export interface ResolvedConfig extends Plugin.Name<'zod'> { 140 + /** 141 + * The casing convention to use for generated names. 142 + * 143 + * @default 'camelCase' 144 + */ 145 + case: StringCase; 146 + /** 147 + * Add comments from input to the generated Zod schemas? 148 + * 149 + * @default true 150 + */ 151 + comments: boolean; 152 + /** 153 + * Configuration for reusable schema definitions. Controls generation of 154 + * shared Zod schemas that can be referenced across requests and responses. 155 + */ 156 + definitions: { 157 + /** 158 + * The casing convention to use for generated names. 159 + * 160 + * @default 'camelCase' 161 + */ 162 + case: StringCase; 163 + /** 164 + * Whether to generate Zod schemas for reusable definitions. 165 + * 166 + * @default true 167 + */ 168 + enabled: boolean; 169 + /** 170 + * Custom naming pattern for generated schema names. The name variable is 171 + * obtained from the schema name. 172 + * 173 + * @default 'z{{name}}' 174 + */ 175 + name: string | ((name: string) => string); 176 + }; 177 + /** 178 + * Should the exports from the generated files be re-exported in the index 179 + * barrel file? 180 + * 181 + * @default false 29 182 */ 30 - // nameBuilder?: (model: IR.OperationObject | IR.SchemaObject) => string; 183 + exportFromIndex: boolean; 184 + /** 185 + * Enable Zod metadata support? It's often useful to associate a schema with 186 + * some additional metadata for documentation, code generation, AI 187 + * structured outputs, form validation, and other purposes. 188 + * 189 + * @default false 190 + */ 191 + metadata: boolean; 31 192 /** 32 193 * Name of the generated file. 33 194 * 34 195 * @default 'zod' 35 196 */ 36 - output?: string; 197 + output: string; 198 + /** 199 + * Configuration for request-specific Zod schemas. 200 + * Controls generation of Zod schemas for request bodies, query parameters, path parameters, and headers. 201 + */ 202 + requests: { 203 + /** 204 + * The casing convention to use for generated names. 205 + * 206 + * @default 'camelCase' 207 + */ 208 + case: StringCase; 209 + /** 210 + * Whether to generate Zod schemas for request definitions. 211 + * 212 + * @default true 213 + */ 214 + enabled: boolean; 215 + /** 216 + * Custom naming pattern for generated schema names. The name variable is 217 + * obtained from the operation name. 218 + * 219 + * @default 'z{{name}}Data' 220 + */ 221 + name: string | ((name: string) => string); 222 + }; 223 + /** 224 + * Configuration for response-specific Zod schemas. 225 + * Controls generation of Zod schemas for response bodies, error responses, and status codes. 226 + */ 227 + responses: { 228 + /** 229 + * The casing convention to use for generated names. 230 + * 231 + * @default 'camelCase' 232 + */ 233 + case: StringCase; 234 + /** 235 + * Whether to generate Zod schemas for response definitions. 236 + * 237 + * @default true 238 + */ 239 + enabled: boolean; 240 + /** 241 + * Custom naming pattern for generated schema names. The name variable is 242 + * obtained from the operation name. 243 + * 244 + * @default 'z{{name}}Response' 245 + */ 246 + name: string | ((name: string) => string); 247 + }; 37 248 }