@kubb/ast 5.0.0-beta.3 → 5.0.0-beta.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -199,7 +199,7 @@ declare const mediaTypes: {
199
199
  * const kind: NodeKind = 'Schema'
200
200
  * ```
201
201
  */
202
- type NodeKind = 'Input' | 'Output' | 'Operation' | 'Schema' | 'Property' | 'Parameter' | 'Response' | 'FunctionParameter' | 'ParameterGroup' | 'FunctionParameters' | 'Type' | 'ParamsType' | 'File' | 'Import' | 'Export' | 'Source' | 'Const' | 'Function' | 'ArrowFunction' | 'Text' | 'Break' | 'Jsx';
202
+ type NodeKind = 'Input' | 'Output' | 'Operation' | 'Schema' | 'Property' | 'Parameter' | 'Response' | 'RequestBody' | 'Content' | 'FunctionParameter' | 'ParameterGroup' | 'FunctionParameters' | 'Type' | 'ParamsType' | 'File' | 'Import' | 'Export' | 'Source' | 'Const' | 'Function' | 'ArrowFunction' | 'Text' | 'Break' | 'Jsx';
203
203
  /**
204
204
  * Base shape shared by all AST nodes.
205
205
  *
@@ -251,21 +251,21 @@ type ConstNode = BaseNode & {
251
251
  * Whether the declaration should be exported.
252
252
  * @default false
253
253
  */
254
- export?: boolean;
254
+ export?: boolean | null;
255
255
  /**
256
256
  * Optional explicit type annotation.
257
257
  * @example 'Pet'
258
258
  */
259
- type?: string;
259
+ type?: string | null;
260
260
  /**
261
261
  * JSDoc documentation metadata.
262
262
  */
263
- JSDoc?: JSDocNode;
263
+ JSDoc?: JSDocNode | null;
264
264
  /**
265
265
  * Whether to append `as const` to the declaration.
266
266
  * @default false
267
267
  */
268
- asConst?: boolean;
268
+ asConst?: boolean | null;
269
269
  /**
270
270
  * Child nodes representing the value of the constant (children of the `Const` component).
271
271
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -297,11 +297,11 @@ type TypeNode = BaseNode & {
297
297
  * Whether the declaration should be exported.
298
298
  * @default false
299
299
  */
300
- export?: boolean;
300
+ export?: boolean | null;
301
301
  /**
302
302
  * JSDoc documentation metadata.
303
303
  */
304
- JSDoc?: JSDocNode;
304
+ JSDoc?: JSDocNode | null;
305
305
  /**
306
306
  * Child nodes representing the type body (children of the `Type` component).
307
307
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -338,35 +338,35 @@ type FunctionNode = BaseNode & {
338
338
  * Whether the function is a default export.
339
339
  * @default false
340
340
  */
341
- default?: boolean;
341
+ default?: boolean | null;
342
342
  /**
343
343
  * Function parameter list rendered as a string (e.g. from `FunctionParams.toConstructor()`).
344
344
  */
345
- params?: string;
345
+ params?: string | null;
346
346
  /**
347
347
  * Whether the function should be exported.
348
348
  * @default false
349
349
  */
350
- export?: boolean;
350
+ export?: boolean | null;
351
351
  /**
352
352
  * Whether the function is async. When `true`, the return type is wrapped in `Promise<>`.
353
353
  * @default false
354
354
  */
355
- async?: boolean;
355
+ async?: boolean | null;
356
356
  /**
357
357
  * TypeScript generic type parameters.
358
358
  * @example ['T', 'U extends string']
359
359
  */
360
- generics?: string | string[];
360
+ generics?: string | Array<string> | null;
361
361
  /**
362
362
  * Return type annotation.
363
363
  * @example 'Pet'
364
364
  */
365
- returnType?: string;
365
+ returnType?: string | null;
366
366
  /**
367
367
  * JSDoc documentation metadata.
368
368
  */
369
- JSDoc?: JSDocNode;
369
+ JSDoc?: JSDocNode | null;
370
370
  /**
371
371
  * Child nodes representing the function body (children of the `Function` component).
372
372
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -398,40 +398,40 @@ type ArrowFunctionNode = BaseNode & {
398
398
  * Whether the function is a default export.
399
399
  * @default false
400
400
  */
401
- default?: boolean;
401
+ default?: boolean | null;
402
402
  /**
403
403
  * Function parameter list rendered as a string (e.g. from `FunctionParams.toConstructor()`).
404
404
  */
405
- params?: string;
405
+ params?: string | null;
406
406
  /**
407
407
  * Whether the arrow function should be exported.
408
408
  * @default false
409
409
  */
410
- export?: boolean;
410
+ export?: boolean | null;
411
411
  /**
412
412
  * Whether the arrow function is async. When `true`, the return type is wrapped in `Promise<>`.
413
413
  * @default false
414
414
  */
415
- async?: boolean;
415
+ async?: boolean | null;
416
416
  /**
417
417
  * TypeScript generic type parameters.
418
418
  * @example ['T', 'U extends string']
419
419
  */
420
- generics?: string | string[];
420
+ generics?: string | Array<string> | null;
421
421
  /**
422
422
  * Return type annotation.
423
423
  * @example 'Pet'
424
424
  */
425
- returnType?: string;
425
+ returnType?: string | null;
426
426
  /**
427
427
  * JSDoc documentation metadata.
428
428
  */
429
- JSDoc?: JSDocNode;
429
+ JSDoc?: JSDocNode | null;
430
430
  /**
431
431
  * Render the arrow function body as a single-line expression.
432
432
  * @default false
433
433
  */
434
- singleLine?: boolean;
434
+ singleLine?: boolean | null;
435
435
  /**
436
436
  * Child nodes representing the function body (children of the `Function.Arrow` component).
437
437
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -510,1079 +510,1123 @@ type JsxNode = BaseNode & {
510
510
  */
511
511
  type CodeNode = ConstNode | TypeNode | FunctionNode | ArrowFunctionNode | TextNode | BreakNode | JsxNode;
512
512
  //#endregion
513
- //#region src/nodes/file.d.ts
514
- /**
515
- * Supported file extensions.
516
- */
517
- type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`;
518
- type ImportName = string | Array<string | {
519
- propertyName: string;
520
- name?: string;
521
- }>;
513
+ //#region src/nodes/property.d.ts
522
514
  /**
523
- * Represents a language-agnostic import/dependency declaration.
524
- *
525
- * @example Named import (TypeScript: `import { useState } from 'react'`)
526
- * ```ts
527
- * createImport({ name: ['useState'], path: 'react' })
528
- * ```
529
- *
530
- * @example Default import (TypeScript: `import React from 'react'`)
531
- * ```ts
532
- * createImport({ name: 'React', path: 'react' })
533
- * ```
534
- *
535
- * @example Type-only import (TypeScript: `import type { FC } from 'react'`)
536
- * ```ts
537
- * createImport({ name: ['FC'], path: 'react', isTypeOnly: true })
538
- * ```
515
+ * AST node representing one named object property.
539
516
  *
540
- * @example Namespace import (TypeScript: `import * as React from 'react'`)
517
+ * @example
541
518
  * ```ts
542
- * createImport({ name: 'React', path: 'react', isNameSpace: true })
519
+ * const property: PropertyNode = {
520
+ * kind: 'Property',
521
+ * name: 'id',
522
+ * schema: createSchema({ type: 'integer' }),
523
+ * required: true,
524
+ * }
543
525
  * ```
544
526
  */
545
- type ImportNode = BaseNode & {
546
- kind: 'Import';
547
- /**
548
- * Import name(s) to be used.
549
- * @example ['useState']
550
- * @example 'React'
551
- */
552
- name: ImportName;
527
+ type PropertyNode = BaseNode & {
553
528
  /**
554
- * Path for the import.
555
- * @example '@kubb/core'
529
+ * Node kind.
556
530
  */
557
- path: string;
531
+ kind: 'Property';
558
532
  /**
559
- * Add type-only import prefix.
560
- * - `true` generates `import type { Type } from './path'`
561
- * - `false` generates `import { Type } from './path'`
562
- * @default false
533
+ * Property key.
563
534
  */
564
- isTypeOnly?: boolean;
535
+ name: string;
565
536
  /**
566
- * Import entire module as namespace.
567
- * - `true` generates `import * as Name from './path'`
568
- * - `false` generates standard import
569
- * @default false
537
+ * Property schema.
570
538
  */
571
- isNameSpace?: boolean;
539
+ schema: SchemaNode;
572
540
  /**
573
- * When set, the import path is resolved relative to this root.
541
+ * Whether the property is required.
574
542
  */
575
- root?: string;
543
+ required: boolean;
576
544
  };
545
+ //#endregion
546
+ //#region src/nodes/schema.d.ts
547
+ type PrimitiveSchemaType =
577
548
  /**
578
- * Represents a language-agnostic export/public API declaration.
579
- *
580
- * @example Named export (TypeScript: `export { Pets } from './Pets'`)
581
- * ```ts
582
- * createExport({ name: ['Pets'], path: './Pets' })
583
- * ```
584
- *
585
- * @example Type-only export (TypeScript: `export type { Pet } from './Pet'`)
586
- * ```ts
587
- * createExport({ name: ['Pet'], path: './Pet', isTypeOnly: true })
588
- * ```
589
- *
590
- * @example Wildcard export (TypeScript: `export * from './utils'`)
591
- * ```ts
592
- * createExport({ path: './utils' })
593
- * ```
594
- *
595
- * @example Namespace alias (TypeScript: `export * as utils from './utils'`)
596
- * ```ts
597
- * createExport({ name: 'utils', path: './utils', asAlias: true })
598
- * ```
549
+ * Text value.
599
550
  */
600
- type ExportNode = BaseNode & {
601
- kind: 'Export';
602
- /**
603
- * Export name(s) to be used. When omitted, generates a wildcard export.
604
- * @example ['useState']
605
- * @example 'React'
606
- */
607
- name?: string | Array<string>;
608
- /**
609
- * Path for the export.
610
- * @example '@kubb/core'
611
- */
612
- path: string;
613
- /**
614
- * Add type-only export prefix.
615
- * - `true` generates `export type { Type } from './path'`
616
- * - `false` generates `export { Type } from './path'`
617
- * @default false
618
- */
619
- isTypeOnly?: boolean;
620
- /**
621
- * Export as an aliased namespace.
622
- * - `true` generates `export * as aliasName from './path'`
623
- * - `false` generates a standard export
624
- * @default false
625
- */
626
- asAlias?: boolean;
627
- };
551
+ 'string'
628
552
  /**
629
- * Represents a fragment of source code within a file.
630
- *
631
- * @example Named exportable source
632
- * ```ts
633
- * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true, isIndexable: true })
634
- * ```
635
- *
636
- * @example Inline unnamed code block
637
- * ```ts
638
- * createSource({ nodes: [createText('const x = 1')] })
639
- * ```
553
+ * Floating-point number.
640
554
  */
641
- type SourceNode = BaseNode & {
642
- kind: 'Source';
643
- /**
644
- * Optional name identifying this source (used for deduplication and barrel generation).
645
- */
646
- name?: string;
647
- /**
648
- * Mark this source as a type-only export.
649
- * @default false
650
- */
651
- isTypeOnly?: boolean;
555
+ | 'number'
556
+ /**
557
+ * Integer number.
558
+ */
559
+ | 'integer'
560
+ /**
561
+ * Big integer number.
562
+ */
563
+ | 'bigint'
564
+ /**
565
+ * Boolean value.
566
+ */
567
+ | 'boolean'
568
+ /**
569
+ * Null value.
570
+ */
571
+ | 'null'
572
+ /**
573
+ * Any value.
574
+ */
575
+ | 'any'
576
+ /**
577
+ * Unknown value.
578
+ */
579
+ | 'unknown'
580
+ /**
581
+ * No value (`void`).
582
+ */
583
+ | 'void'
584
+ /**
585
+ * Never value.
586
+ */
587
+ | 'never'
588
+ /**
589
+ * Object value.
590
+ */
591
+ | 'object'
592
+ /**
593
+ * Array value.
594
+ */
595
+ | 'array'
596
+ /**
597
+ * Date value.
598
+ */
599
+ | 'date';
600
+ /**
601
+ * Composite schema types.
602
+ */
603
+ type ComplexSchemaType = 'tuple' | 'union' | 'intersection' | 'enum';
604
+ /**
605
+ * Schema types that need special handling in generators.
606
+ */
607
+ type SpecialSchemaType = 'ref' | 'datetime' | 'time' | 'uuid' | 'email' | 'url' | 'ipv4' | 'ipv6' | 'blob';
608
+ /**
609
+ * All schema type strings.
610
+ */
611
+ type SchemaType = PrimitiveSchemaType | ComplexSchemaType | SpecialSchemaType;
612
+ /**
613
+ * Scalar schema types without extra object/array/ref structure.
614
+ */
615
+ type ScalarSchemaType = Exclude<SchemaType, 'object' | 'array' | 'tuple' | 'union' | 'intersection' | 'enum' | 'ref' | 'datetime' | 'date' | 'time' | 'string' | 'number' | 'integer' | 'bigint' | 'url' | 'uuid' | 'email'>;
616
+ /**
617
+ * Fields shared by all schema nodes.
618
+ */
619
+ type SchemaNodeBase = BaseNode & {
652
620
  /**
653
- * Include `export` keyword in the generated source.
654
- * @default false
621
+ * Node kind.
655
622
  */
656
- isExportable?: boolean;
623
+ kind: 'Schema';
657
624
  /**
658
- * Include this source in barrel/index file generation.
659
- * @default false
625
+ * Schema name for named definitions (for example, `"Pet"`).
626
+ * Inline schemas omit this field.
627
+ * `null` means kubb has processed this and determined there is no applicable name.
628
+ * `undefined` means the name has not been set yet.
660
629
  */
661
- isIndexable?: boolean;
630
+ name?: string | null;
662
631
  /**
663
- * Structured child nodes representing the content of this source fragment, in DOM order.
664
- * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
632
+ * Short schema title.
665
633
  */
666
- nodes?: Array<CodeNode>;
667
- };
668
- /**
669
- * Represents a fully resolved file in the AST.
670
- *
671
- * Created via `createFile()`, which computes the `id`, `name`, and `extname` from the input
672
- * and deduplicates `imports`, `exports`, and `sources`.
673
- *
674
- * @example
675
- * ```ts
676
- * const file = createFile({
677
- * baseName: 'petStore.ts',
678
- * path: 'src/models/petStore.ts',
679
- * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })],
680
- * imports: [createImport({ name: ['z'], path: 'zod' })],
681
- * exports: [createExport({ name: ['Pet'], path: './petStore' })],
682
- * })
683
- * // file.id = SHA256 hash of the path
684
- * // file.name = 'petStore'
685
- * // file.extname = '.ts'
686
- * ```
687
- */
688
- type FileNode<TMeta extends object = object> = BaseNode & {
689
- kind: 'File';
634
+ title?: string;
690
635
  /**
691
- * Unique identifier derived from a SHA256 hash of the file path.
692
- * @default hash
636
+ * Schema description text.
693
637
  */
694
- id: string;
638
+ description?: string;
695
639
  /**
696
- * File name without extension, derived from `baseName`.
697
- * @link https://nodejs.org/api/path.html#pathformatpathobject
640
+ * Whether `null` is allowed.
698
641
  */
699
- name: string;
642
+ nullable?: boolean;
700
643
  /**
701
- * File base name, including extension.
702
- * Based on UNIX basename: `${name}${extname}`
703
- * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
644
+ * Whether the field is optional.
704
645
  */
705
- baseName: `${string}.${string}`;
646
+ optional?: boolean;
706
647
  /**
707
- * Full qualified path to the file.
648
+ * Both optional and nullable (`optional` + `nullable`).
708
649
  */
709
- path: string;
650
+ nullish?: boolean;
710
651
  /**
711
- * File extension extracted from `baseName`.
652
+ * Whether the schema is deprecated.
712
653
  */
713
- extname: Extname;
654
+ deprecated?: boolean;
714
655
  /**
715
- * Deduplicated list of source code fragments.
656
+ * Whether the schema is read-only.
716
657
  */
717
- sources: Array<SourceNode>;
658
+ readOnly?: boolean;
718
659
  /**
719
- * Deduplicated list of import declarations.
660
+ * Whether the schema is write-only.
720
661
  */
721
- imports: Array<ImportNode>;
662
+ writeOnly?: boolean;
722
663
  /**
723
- * Deduplicated list of export declarations.
664
+ * Default value.
724
665
  */
725
- exports: Array<ExportNode>;
666
+ default?: unknown;
726
667
  /**
727
- * Optional metadata attached to this file (used by plugins for barrel generation etc.).
668
+ * Example value.
728
669
  */
729
- meta?: TMeta;
670
+ example?: unknown;
730
671
  /**
731
- * Optional banner prepended to the generated file content.
672
+ * Base primitive type.
673
+ * For example, this is `'string'` for a `uuid` schema.
732
674
  */
733
- banner?: string;
675
+ primitive?: PrimitiveSchemaType;
734
676
  /**
735
- * Optional footer appended to the generated file content.
677
+ * Schema `format` value.
736
678
  */
737
- footer?: string;
679
+ format?: string;
738
680
  };
739
- //#endregion
740
- //#region src/nodes/function.d.ts
741
681
  /**
742
- * AST node representing a language-agnostic type expression used as a function parameter
743
- * type annotation. Each language printer renders the variant into its own syntax.
744
- *
745
- * - `struct` — an inline anonymous type grouping named fields.
746
- * TypeScript renders as `{ petId: string; name?: string }`.
747
- * - `member` — a single named field accessed from a named group type.
748
- * TypeScript renders as `PathParams['petId']`.
749
- *
750
- * @example Reference variant
751
- * ```ts
752
- * createParamsType({ variant: 'reference', name: 'QueryParams' })
753
- * // QueryParams
754
- * ```
755
- *
756
- * @example Struct variant
757
- * ```ts
758
- * createParamsType({ variant: 'struct', properties: [{ name: 'petId', optional: false, type: createParamsType({ variant: 'reference', name: 'string' }) }] })
759
- * // { petId: string }
760
- * ```
682
+ * Object schema with ordered properties.
761
683
  *
762
- * @example Member variant
684
+ * @example
763
685
  * ```ts
764
- * createParamsType({ variant: 'member', base: 'PathParams', key: 'petId' })
765
- * // PathParams['petId']
686
+ * const objectSchema: ObjectSchemaNode = {
687
+ * kind: 'Schema',
688
+ * type: 'object',
689
+ * properties: [],
690
+ * }
766
691
  * ```
767
692
  */
768
- type ParamsTypeNode = BaseNode & {
769
- /**
770
- * Node kind.
771
- */
772
- kind: 'ParamsType';
773
- } & ({
693
+ type ObjectSchemaNode = SchemaNodeBase & {
774
694
  /**
775
- * Reference variant — a plain type name or identifier.
776
- * TypeScript renders as-is, e.g. `string`, `QueryParams`, `Partial<Config>`.
695
+ * Schema type discriminator.
777
696
  */
778
- variant: 'reference';
697
+ type: 'object';
779
698
  /**
780
- * The full type name string, e.g. `'string'`, `'QueryParams'`, `'Partial<Config>'`.
699
+ * Primitive type always `'object'` for object schemas.
781
700
  */
782
- name: string;
783
- } | {
701
+ primitive: 'object';
784
702
  /**
785
- * Struct variant — an inline anonymous type grouping named fields.
786
- * TypeScript renders as `{ key: Type; other?: OtherType }`.
703
+ * Ordered object properties.
787
704
  */
788
- variant: 'struct';
705
+ properties: Array<PropertyNode>;
789
706
  /**
790
- * Properties of the struct type.
707
+ * Additional object properties behavior:
708
+ * - `true`: allow any value
709
+ * - `false`: reject unknown properties (maps to `.strict()` in Zod)
710
+ * - `SchemaNode`: allow values that match that schema
711
+ * - `undefined`: no additional properties constraint (open object)
791
712
  */
792
- properties: Array<{
793
- name: string;
794
- optional: boolean;
795
- type: ParamsTypeNode;
796
- }>;
797
- } | {
713
+ additionalProperties?: SchemaNode | boolean;
798
714
  /**
799
- * Member variant — a single named field accessed from a group type.
800
- * TypeScript renders as `Base['key']`.
715
+ * Pattern-based property schemas.
801
716
  */
802
- variant: 'member';
717
+ patternProperties?: Record<string, SchemaNode>;
803
718
  /**
804
- * Base type name, e.g. `'DeletePetPathParams'`.
719
+ * Minimum number of properties allowed.
805
720
  */
806
- base: string;
721
+ minProperties?: number;
807
722
  /**
808
- * The field name to access, e.g. `'petId'`.
723
+ * Maximum number of properties allowed.
809
724
  */
810
- key: string;
811
- });
725
+ maxProperties?: number;
726
+ };
812
727
  /**
813
- * AST node for one function parameter.
814
- *
815
- * @example Required parameter
816
- * `name: Type`
817
- *
818
- * @example Optional parameter
819
- * `name?: Type`
820
- *
821
- * @example Parameter with default value
822
- * `name: Type = defaultValue`
728
+ * Array-like schema (`array` or `tuple`).
823
729
  *
824
- * @example Rest parameter
825
- * `...name: Type[]`
730
+ * @example
731
+ * ```ts
732
+ * const arraySchema: ArraySchemaNode = {
733
+ * kind: 'Schema',
734
+ * type: 'array',
735
+ * items: [],
736
+ * }
737
+ * ```
826
738
  */
827
- type FunctionParameterNode = BaseNode & {
828
- /**
829
- * Node kind.
830
- */
831
- kind: 'FunctionParameter';
832
- /**
833
- * Parameter name in the generated signature.
834
- */
835
- name: string;
836
- /**
837
- * Type annotation as a structured {@link ParamsTypeNode}.
838
- * Omit for untyped output.
839
- *
840
- * @example Reference type node
841
- * `{ kind: 'ParamsType', variant: 'reference', name: 'string' }` → `petId: string`
842
- *
843
- * @example Struct type node
844
- * `{ kind: 'ParamsType', variant: 'struct', properties: [...] }` → `{ key: Type; other?: OtherType }`
845
- *
846
- * @example Member type node
847
- * `{ kind: 'ParamsType', variant: 'member', base: 'PathParams', key: 'petId' }` → `PathParams['petId']`
848
- */
849
- type?: ParamsTypeNode;
739
+ type ArraySchemaNode = SchemaNodeBase & {
850
740
  /**
851
- * When `true` the parameter is emitted as a rest parameter.
852
- *
853
- * @example Rest parameter
854
- * `...name: Type[]`
741
+ * Schema type discriminator (`array` or `tuple`).
855
742
  */
856
- rest?: boolean;
857
- }
858
- /**
859
- * Optional parameter — rendered with `?` and may be omitted by the caller.
860
- * Cannot be combined with `default` because a defaulted parameter is already optional.
861
- */
862
- & ({
863
- optional: true;
864
- default?: never;
865
- }
866
- /**
867
- * Required parameter, or a parameter with a default value.
868
- *
869
- * @example Required
870
- * `name: Type`
871
- *
872
- * @example With default
873
- * `name: Type = default`
874
- */
875
- | {
876
- optional?: false;
877
- default?: string;
878
- });
879
- /**
880
- * AST node for a group of related function parameters treated as a single unit.
881
- *
882
- * Each language printer decides how to render this group:
883
- * - TypeScript/JS: destructured object `{ key1, key2 }: { key1: Type1; key2: Type2 } = {}`
884
- * - Python: keyword-only args or a typed dict parameter
885
- * - C# / Kotlin: named record / data-class parameter
886
- *
887
- * When `inline` is `true`, the group is spread as individual top-level parameters
888
- * rather than wrapped in a single grouped construct.
889
- *
890
- * @example Grouped destructuring
891
- * `{ id, name }: { id: string; name: string } = {}`
892
- *
893
- * @example Inline (spread as individual parameters)
894
- * `id: string, name: string`
895
- */
896
- type ParameterGroupNode = BaseNode & {
743
+ type: 'array' | 'tuple';
897
744
  /**
898
- * Node kind.
745
+ * Item schemas.
899
746
  */
900
- kind: 'ParameterGroup';
747
+ items?: Array<SchemaNode>;
901
748
  /**
902
- * The individual parameters that form the group.
903
- * Rendered as a destructured object or spread inline when `inline` is `true`.
749
+ * Tuple rest-item schema for elements beyond positional `items`.
904
750
  */
905
- properties: Array<FunctionParameterNode>;
751
+ rest?: SchemaNode;
906
752
  /**
907
- * Optional explicit type annotation for the whole group.
908
- * When absent, printers auto-compute it from `properties`.
753
+ * Minimum item count (or tuple length).
909
754
  */
910
- type?: ParamsTypeNode;
755
+ min?: number;
911
756
  /**
912
- * When `true`, `properties` are emitted as individual top-level parameters instead of
913
- * being wrapped in a single grouped construct.
914
- *
915
- * @default false
757
+ * Maximum item count (or tuple length).
916
758
  */
917
- inline?: boolean;
759
+ max?: number;
918
760
  /**
919
- * Whether the group as a whole is optional.
920
- * If omitted, printers infer this from child properties.
761
+ * Whether all items must be unique.
921
762
  */
922
- optional?: boolean;
763
+ unique?: boolean;
764
+ };
765
+ /**
766
+ * Shared shape for union and intersection schemas.
767
+ */
768
+ type CompositeSchemaNodeBase = SchemaNodeBase & {
923
769
  /**
924
- * Default value for the group, written verbatim after `=`.
925
- * Commonly `'{}'` to allow omitting the argument entirely.
770
+ * Member schemas.
926
771
  */
927
- default?: string;
772
+ members?: Array<SchemaNode>;
928
773
  };
929
774
  /**
930
- * AST node for a complete function parameter list.
931
- *
932
- * Printers are responsible for sorting (`required` → `optional` → `defaulted`).
933
- * Nodes are plain immutable data.
775
+ * Union schema, often from `oneOf` or `anyOf`.
934
776
  *
935
- * Renders differently depending on the output mode:
936
- * - `declaration` → `(id: string, config: Config = {})` — function declaration parameters
937
- * - `call` → `(id, { method, url })` — function call arguments
938
- * - `keys` → `{ id, config }` — key names only (for destructuring)
939
- * - `values` → `{ id: id, config: config }` — key → value pairs
777
+ * @example
778
+ * ```ts
779
+ * const unionSchema: UnionSchemaNode = {
780
+ * kind: 'Schema',
781
+ * type: 'union',
782
+ * members: [],
783
+ * }
784
+ * ```
940
785
  */
941
- type FunctionParametersNode = BaseNode & {
786
+ type UnionSchemaNode = CompositeSchemaNodeBase & {
942
787
  /**
943
- * Node kind.
788
+ * Schema type discriminator.
944
789
  */
945
- kind: 'FunctionParameters';
790
+ type: 'union';
946
791
  /**
947
- * Ordered parameter nodes.
792
+ * Discriminator property name from OpenAPI `discriminator.propertyName`.
948
793
  */
949
- params: ReadonlyArray<FunctionParameterNode | ParameterGroupNode>;
794
+ discriminatorPropertyName?: string;
795
+ /**
796
+ * Logical strategy applied to union members: 'one' means exactly one member must be valid (from `oneOf`),
797
+ * 'any' means any number of members can be valid (from `anyOf`).
798
+ */
799
+ strategy?: 'one' | 'any';
950
800
  };
951
801
  /**
952
- * Union of all function-parameter AST node variants used by the function-parameter printer.
953
- */
954
- type FunctionParamNode = FunctionParameterNode | ParameterGroupNode | FunctionParametersNode | ParamsTypeNode;
955
- /**
956
- * Handler map keys — one per `FunctionParamNode` kind.
957
- */
958
- type FunctionNodeType = 'functionParameter' | 'parameterGroup' | 'functionParameters' | 'paramsType';
959
- //#endregion
960
- //#region src/nodes/property.d.ts
961
- /**
962
- * AST node representing one named object property.
802
+ * Intersection schema, often from `allOf`.
963
803
  *
964
804
  * @example
965
805
  * ```ts
966
- * const property: PropertyNode = {
967
- * kind: 'Property',
968
- * name: 'id',
969
- * schema: createSchema({ type: 'integer' }),
970
- * required: true,
806
+ * const intersectionSchema: IntersectionSchemaNode = {
807
+ * kind: 'Schema',
808
+ * type: 'intersection',
809
+ * members: [],
971
810
  * }
972
811
  * ```
973
812
  */
974
- type PropertyNode = BaseNode & {
813
+ type IntersectionSchemaNode = CompositeSchemaNodeBase & {
975
814
  /**
976
- * Node kind.
815
+ * Schema type discriminator.
977
816
  */
978
- kind: 'Property';
817
+ type: 'intersection';
818
+ };
819
+ /**
820
+ * One named enum item.
821
+ */
822
+ type EnumValueNode = {
979
823
  /**
980
- * Property key.
824
+ * Enum item name.
981
825
  */
982
826
  name: string;
983
827
  /**
984
- * Property schema.
828
+ * Enum item value.
985
829
  */
986
- schema: SchemaNode;
830
+ value: string | number | boolean;
987
831
  /**
988
- * Whether the property is required.
832
+ * Primitive type of the enum value.
989
833
  */
990
- required: boolean;
834
+ primitive: Extract<PrimitiveSchemaType, 'string' | 'number' | 'boolean'>;
991
835
  };
992
- //#endregion
993
- //#region src/nodes/schema.d.ts
994
- type PrimitiveSchemaType =
995
- /**
996
- * Text value.
997
- */
998
- 'string'
999
- /**
1000
- * Floating-point number.
1001
- */
1002
- | 'number'
1003
- /**
1004
- * Integer number.
1005
- */
1006
- | 'integer'
1007
- /**
1008
- * Big integer number.
1009
- */
1010
- | 'bigint'
1011
- /**
1012
- * Boolean value.
1013
- */
1014
- | 'boolean'
1015
- /**
1016
- * Null value.
1017
- */
1018
- | 'null'
1019
- /**
1020
- * Any value.
1021
- */
1022
- | 'any'
1023
- /**
1024
- * Unknown value.
1025
- */
1026
- | 'unknown'
1027
- /**
1028
- * No value (`void`).
1029
- */
1030
- | 'void'
1031
- /**
1032
- * Never value.
1033
- */
1034
- | 'never'
1035
- /**
1036
- * Object value.
1037
- */
1038
- | 'object'
1039
- /**
1040
- * Array value.
1041
- */
1042
- | 'array'
1043
- /**
1044
- * Date value.
1045
- */
1046
- | 'date';
1047
- /**
1048
- * Composite schema types.
1049
- */
1050
- type ComplexSchemaType = 'tuple' | 'union' | 'intersection' | 'enum';
1051
- /**
1052
- * Schema types that need special handling in generators.
1053
- */
1054
- type SpecialSchemaType = 'ref' | 'datetime' | 'time' | 'uuid' | 'email' | 'url' | 'ipv4' | 'ipv6' | 'blob';
1055
- /**
1056
- * All schema type strings.
1057
- */
1058
- type SchemaType = PrimitiveSchemaType | ComplexSchemaType | SpecialSchemaType;
1059
836
  /**
1060
- * Scalar schema types without extra object/array/ref structure.
837
+ * Enum schema node.
838
+ *
839
+ * @example
840
+ * ```ts
841
+ * const enumSchema: EnumSchemaNode = {
842
+ * kind: 'Schema',
843
+ * type: 'enum',
844
+ * enumValues: ['a', 'b'],
845
+ * }
846
+ * ```
1061
847
  */
1062
- type ScalarSchemaType = Exclude<SchemaType, 'object' | 'array' | 'tuple' | 'union' | 'intersection' | 'enum' | 'ref' | 'datetime' | 'date' | 'time' | 'string' | 'number' | 'integer' | 'bigint' | 'url' | 'uuid' | 'email'>;
848
+ type EnumSchemaNode = SchemaNodeBase & {
849
+ /**
850
+ * Schema type discriminator.
851
+ */
852
+ type: 'enum';
853
+ /**
854
+ * Enum values in simple form.
855
+ */
856
+ enumValues?: Array<string | number | boolean | null>;
857
+ /**
858
+ * Enum values in named form.
859
+ * If present, this is used instead of `enumValues`.
860
+ */
861
+ namedEnumValues?: Array<EnumValueNode>;
862
+ };
1063
863
  /**
1064
- * Fields shared by all schema nodes.
864
+ * Reference schema that points to another schema definition.
865
+ *
866
+ * @example
867
+ * ```ts
868
+ * const refSchema: RefSchemaNode = {
869
+ * kind: 'Schema',
870
+ * type: 'ref',
871
+ * ref: '#/components/schemas/Pet',
872
+ * }
873
+ * ```
1065
874
  */
1066
- type SchemaNodeBase = BaseNode & {
875
+ type RefSchemaNode = SchemaNodeBase & {
1067
876
  /**
1068
- * Node kind.
877
+ * Schema type discriminator.
1069
878
  */
1070
- kind: 'Schema';
879
+ type: 'ref';
1071
880
  /**
1072
- * Schema name for named definitions (for example, `"Pet"`).
1073
- * Inline schemas omit this field.
1074
- * `null` means kubb has processed this and determined there is no applicable name.
1075
- * `undefined` means the name has not been set yet.
881
+ * Referenced schema name.
882
+ * `null` means Kubb has processed this and determined there is no applicable name.
1076
883
  */
1077
884
  name?: string | null;
1078
885
  /**
1079
- * Short schema title.
886
+ * Original `$ref` path, for example, `#/components/schemas/Order`.
887
+ * Used to resolve names later.
1080
888
  */
1081
- title?: string;
889
+ ref?: string;
1082
890
  /**
1083
- * Schema description text.
891
+ * Pattern copied from a sibling `pattern` field.
1084
892
  */
1085
- description?: string;
893
+ pattern?: string;
1086
894
  /**
1087
- * Whether `null` is allowed.
895
+ * The fully-parsed schema that this ref resolves to.
896
+ * Populated during OAS parsing when the referenced definition can be resolved.
897
+ * `null` when the ref cannot be resolved or is part of a circular chain.
898
+ * `undefined` when resolution has not been attempted.
899
+ *
900
+ * Useful for inspecting the referenced schema's structure (e.g. `primitive`, `properties`)
901
+ * without following the reference manually.
1088
902
  */
1089
- nullable?: boolean;
903
+ schema?: SchemaNode | null;
904
+ };
905
+ /**
906
+ * Datetime schema.
907
+ *
908
+ * @example
909
+ * ```ts
910
+ * const datetimeSchema: DatetimeSchemaNode = { kind: 'Schema', type: 'datetime' }
911
+ * ```
912
+ */
913
+ type DatetimeSchemaNode = SchemaNodeBase & {
1090
914
  /**
1091
- * Whether the field is optional.
915
+ * Schema type discriminator.
1092
916
  */
1093
- optional?: boolean;
917
+ type: 'datetime';
1094
918
  /**
1095
- * Both optional and nullable (`optional` + `nullable`).
919
+ * Whether the datetime includes a timezone offset (`dateType: 'stringOffset'`).
1096
920
  */
1097
- nullish?: boolean;
921
+ offset?: boolean;
1098
922
  /**
1099
- * Whether the schema is deprecated.
923
+ * Whether the datetime is local (no timezone, `dateType: 'stringLocal'`).
1100
924
  */
1101
- deprecated?: boolean;
925
+ local?: boolean;
926
+ };
927
+ /**
928
+ * Shared base for `date` and `time` schemas.
929
+ */
930
+ type TemporalSchemaNodeBase<T extends 'date' | 'time'> = SchemaNodeBase & {
1102
931
  /**
1103
- * Whether the schema is read-only.
932
+ * Schema type discriminator.
1104
933
  */
1105
- readOnly?: boolean;
934
+ type: T;
935
+ /**
936
+ * Output representation in generated code.
937
+ */
938
+ representation: 'date' | 'string';
939
+ };
940
+ /**
941
+ * Date schema node.
942
+ *
943
+ * @example
944
+ * ```ts
945
+ * const dateSchema: DateSchemaNode = { kind: 'Schema', type: 'date', representation: 'string' }
946
+ * ```
947
+ */
948
+ type DateSchemaNode = TemporalSchemaNodeBase<'date'>;
949
+ /**
950
+ * Time schema node.
951
+ *
952
+ * @example
953
+ * ```ts
954
+ * const timeSchema: TimeSchemaNode = { kind: 'Schema', type: 'time', representation: 'string' }
955
+ * ```
956
+ */
957
+ type TimeSchemaNode = TemporalSchemaNodeBase<'time'>;
958
+ /**
959
+ * String schema node.
960
+ *
961
+ * @example
962
+ * ```ts
963
+ * const stringSchema: StringSchemaNode = { kind: 'Schema', type: 'string' }
964
+ * ```
965
+ */
966
+ type StringSchemaNode = SchemaNodeBase & {
1106
967
  /**
1107
- * Whether the schema is write-only.
968
+ * Schema type discriminator.
1108
969
  */
1109
- writeOnly?: boolean;
970
+ type: 'string';
1110
971
  /**
1111
- * Default value.
972
+ * Minimum string length.
1112
973
  */
1113
- default?: unknown;
974
+ min?: number;
1114
975
  /**
1115
- * Example value.
976
+ * Maximum string length.
1116
977
  */
1117
- example?: unknown;
978
+ max?: number;
1118
979
  /**
1119
- * Base primitive type.
1120
- * For example, this is `'string'` for a `uuid` schema.
980
+ * Regex pattern.
1121
981
  */
1122
- primitive?: PrimitiveSchemaType;
982
+ pattern?: string;
1123
983
  };
1124
984
  /**
1125
- * Object schema with ordered properties.
985
+ * Numeric schema (`number`, `integer`, or `bigint`).
1126
986
  *
1127
987
  * @example
1128
988
  * ```ts
1129
- * const objectSchema: ObjectSchemaNode = {
1130
- * kind: 'Schema',
1131
- * type: 'object',
1132
- * properties: [],
1133
- * }
989
+ * const numberSchema: NumberSchemaNode = { kind: 'Schema', type: 'number' }
1134
990
  * ```
1135
991
  */
1136
- type ObjectSchemaNode = SchemaNodeBase & {
992
+ type NumberSchemaNode = SchemaNodeBase & {
1137
993
  /**
1138
994
  * Schema type discriminator.
1139
995
  */
1140
- type: 'object';
996
+ type: 'number' | 'integer' | 'bigint';
1141
997
  /**
1142
- * Primitive type — always `'object'` for object schemas.
998
+ * Minimum value.
1143
999
  */
1144
- primitive: 'object';
1000
+ min?: number;
1145
1001
  /**
1146
- * Ordered object properties.
1002
+ * Maximum value.
1147
1003
  */
1148
- properties: Array<PropertyNode>;
1004
+ max?: number;
1149
1005
  /**
1150
- * Additional object properties behavior:
1151
- * - `true`: allow any value
1152
- * - `false`: reject unknown properties (maps to `.strict()` in Zod)
1153
- * - `SchemaNode`: allow values that match that schema
1154
- * - `undefined`: no additional properties constraint (open object)
1006
+ * Exclusive minimum value.
1155
1007
  */
1156
- additionalProperties?: SchemaNode | boolean;
1008
+ exclusiveMinimum?: number;
1157
1009
  /**
1158
- * Pattern-based property schemas.
1010
+ * Exclusive maximum value.
1159
1011
  */
1160
- patternProperties?: Record<string, SchemaNode>;
1012
+ exclusiveMaximum?: number;
1161
1013
  /**
1162
- * Minimum number of properties allowed.
1014
+ * The value must be a multiple of this number.
1163
1015
  */
1164
- minProperties?: number;
1016
+ multipleOf?: number;
1017
+ };
1018
+ /**
1019
+ * Scalar schema with no extra constraints.
1020
+ *
1021
+ * @example
1022
+ * ```ts
1023
+ * const anySchema: ScalarSchemaNode = { kind: 'Schema', type: 'any' }
1024
+ * ```
1025
+ */
1026
+ type ScalarSchemaNode = SchemaNodeBase & {
1165
1027
  /**
1166
- * Maximum number of properties allowed.
1028
+ * Schema type discriminator.
1167
1029
  */
1168
- maxProperties?: number;
1030
+ type: ScalarSchemaType;
1169
1031
  };
1170
1032
  /**
1171
- * Array-like schema (`array` or `tuple`).
1033
+ * URL schema node.
1034
+ * Can include an OpenAPI-style path template for template literal types.
1172
1035
  *
1173
1036
  * @example
1174
1037
  * ```ts
1175
- * const arraySchema: ArraySchemaNode = {
1176
- * kind: 'Schema',
1177
- * type: 'array',
1178
- * items: [],
1179
- * }
1038
+ * const urlSchema: UrlSchemaNode = { kind: 'Schema', type: 'url', path: '/pets/{petId}' }
1180
1039
  * ```
1181
1040
  */
1182
- type ArraySchemaNode = SchemaNodeBase & {
1041
+ type UrlSchemaNode = SchemaNodeBase & {
1183
1042
  /**
1184
- * Schema type discriminator (`array` or `tuple`).
1043
+ * Schema type discriminator.
1185
1044
  */
1186
- type: 'array' | 'tuple';
1045
+ type: 'url';
1187
1046
  /**
1188
- * Item schemas.
1047
+ * OpenAPI-style path template, for example, `'/pets/{petId}'`.
1189
1048
  */
1190
- items?: Array<SchemaNode>;
1049
+ path?: string;
1191
1050
  /**
1192
- * Tuple rest-item schema for elements beyond positional `items`.
1051
+ * Minimum string length.
1193
1052
  */
1194
- rest?: SchemaNode;
1053
+ min?: number;
1195
1054
  /**
1196
- * Minimum item count (or tuple length).
1055
+ * Maximum string length.
1056
+ */
1057
+ max?: number;
1058
+ };
1059
+ /**
1060
+ * Format-string schema for string-based formats that support length constraints.
1061
+ *
1062
+ * @example
1063
+ * ```ts
1064
+ * const uuidSchema: FormatStringSchemaNode = { kind: 'Schema', type: 'uuid', min: 36, max: 36 }
1065
+ * ```
1066
+ */
1067
+ type FormatStringSchemaNode = SchemaNodeBase & {
1068
+ /**
1069
+ * Schema type discriminator.
1070
+ */
1071
+ type: 'uuid' | 'email';
1072
+ /**
1073
+ * Minimum string length.
1197
1074
  */
1198
1075
  min?: number;
1199
1076
  /**
1200
- * Maximum item count (or tuple length).
1077
+ * Maximum string length.
1201
1078
  */
1202
1079
  max?: number;
1080
+ };
1081
+ /**
1082
+ * IPv4 address schema node.
1083
+ *
1084
+ * @example
1085
+ * ```ts
1086
+ * const ipv4Schema: Ipv4SchemaNode = { kind: 'Schema', type: 'ipv4' }
1087
+ * ```
1088
+ */
1089
+ type Ipv4SchemaNode = SchemaNodeBase & {
1203
1090
  /**
1204
- * Whether all items must be unique.
1091
+ * Schema type discriminator.
1205
1092
  */
1206
- unique?: boolean;
1093
+ type: 'ipv4';
1207
1094
  };
1208
1095
  /**
1209
- * Shared shape for union and intersection schemas.
1096
+ * IPv6 address schema node.
1097
+ *
1098
+ * @example
1099
+ * ```ts
1100
+ * const ipv6Schema: Ipv6SchemaNode = { kind: 'Schema', type: 'ipv6' }
1101
+ * ```
1210
1102
  */
1211
- type CompositeSchemaNodeBase = SchemaNodeBase & {
1103
+ type Ipv6SchemaNode = SchemaNodeBase & {
1212
1104
  /**
1213
- * Member schemas.
1105
+ * Schema type discriminator.
1214
1106
  */
1215
- members?: Array<SchemaNode>;
1107
+ type: 'ipv6';
1216
1108
  };
1217
1109
  /**
1218
- * Union schema, often from `oneOf` or `anyOf`.
1110
+ * Mapping from schema type literals to concrete schema node types.
1111
+ * Used by `narrowSchema`.
1112
+ */
1113
+ type SchemaNodeByType = {
1114
+ object: ObjectSchemaNode;
1115
+ array: ArraySchemaNode;
1116
+ tuple: ArraySchemaNode;
1117
+ union: UnionSchemaNode;
1118
+ intersection: IntersectionSchemaNode;
1119
+ enum: EnumSchemaNode;
1120
+ ref: RefSchemaNode;
1121
+ datetime: DatetimeSchemaNode;
1122
+ date: DateSchemaNode;
1123
+ time: TimeSchemaNode;
1124
+ string: StringSchemaNode;
1125
+ number: NumberSchemaNode;
1126
+ integer: NumberSchemaNode;
1127
+ bigint: NumberSchemaNode;
1128
+ boolean: ScalarSchemaNode;
1129
+ null: ScalarSchemaNode;
1130
+ any: ScalarSchemaNode;
1131
+ unknown: ScalarSchemaNode;
1132
+ void: ScalarSchemaNode;
1133
+ never: ScalarSchemaNode;
1134
+ uuid: FormatStringSchemaNode;
1135
+ email: FormatStringSchemaNode;
1136
+ url: UrlSchemaNode;
1137
+ ipv4: Ipv4SchemaNode;
1138
+ ipv6: Ipv6SchemaNode;
1139
+ blob: ScalarSchemaNode;
1140
+ };
1141
+ /**
1142
+ * Union of all schema node types.
1143
+ */
1144
+ type SchemaNode = ObjectSchemaNode | ArraySchemaNode | UnionSchemaNode | IntersectionSchemaNode | EnumSchemaNode | RefSchemaNode | DatetimeSchemaNode | DateSchemaNode | TimeSchemaNode | StringSchemaNode | NumberSchemaNode | UrlSchemaNode | FormatStringSchemaNode | Ipv4SchemaNode | Ipv6SchemaNode | ScalarSchemaNode;
1145
+ //#endregion
1146
+ //#region src/nodes/content.d.ts
1147
+ /**
1148
+ * AST node representing one content-type entry of a request body or response.
1149
+ *
1150
+ * One entry per content type declared in the spec (e.g. `application/json`,
1151
+ * `multipart/form-data`), each carrying its own body schema.
1219
1152
  *
1220
1153
  * @example
1221
1154
  * ```ts
1222
- * const unionSchema: UnionSchemaNode = {
1223
- * kind: 'Schema',
1224
- * type: 'union',
1225
- * members: [],
1155
+ * const content: ContentNode = {
1156
+ * kind: 'Content',
1157
+ * contentType: 'application/json',
1158
+ * schema: createSchema({ type: 'string' }),
1226
1159
  * }
1227
1160
  * ```
1228
1161
  */
1229
- type UnionSchemaNode = CompositeSchemaNodeBase & {
1162
+ type ContentNode = BaseNode & {
1230
1163
  /**
1231
- * Schema type discriminator.
1164
+ * Node kind.
1232
1165
  */
1233
- type: 'union';
1166
+ kind: 'Content';
1234
1167
  /**
1235
- * Discriminator property name from OpenAPI `discriminator.propertyName`.
1168
+ * The content type for this entry (e.g. `'application/json'`).
1236
1169
  */
1237
- discriminatorPropertyName?: string;
1170
+ contentType: string;
1238
1171
  /**
1239
- * Logical strategy applied to union members: 'one' means exactly one member must be valid (from `oneOf`),
1240
- * 'any' means any number of members can be valid (from `anyOf`).
1172
+ * Body schema for this content type.
1173
+ */
1174
+ schema?: SchemaNode;
1175
+ /**
1176
+ * Property keys to exclude from the generated type via `Omit<Type, Keys>`.
1177
+ * Set when a referenced schema has `readOnly`/`writeOnly` fields that should be omitted.
1178
+ */
1179
+ keysToOmit?: Array<string> | null;
1180
+ };
1181
+ //#endregion
1182
+ //#region src/nodes/file.d.ts
1183
+ /**
1184
+ * Supported file extensions.
1185
+ */
1186
+ type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`;
1187
+ type ImportName = string | Array<string | {
1188
+ propertyName: string;
1189
+ name?: string;
1190
+ }>;
1191
+ /**
1192
+ * Represents a language-agnostic import/dependency declaration.
1193
+ *
1194
+ * @example Named import (TypeScript: `import { useState } from 'react'`)
1195
+ * ```ts
1196
+ * createImport({ name: ['useState'], path: 'react' })
1197
+ * ```
1198
+ *
1199
+ * @example Default import (TypeScript: `import React from 'react'`)
1200
+ * ```ts
1201
+ * createImport({ name: 'React', path: 'react' })
1202
+ * ```
1203
+ *
1204
+ * @example Type-only import (TypeScript: `import type { FC } from 'react'`)
1205
+ * ```ts
1206
+ * createImport({ name: ['FC'], path: 'react', isTypeOnly: true })
1207
+ * ```
1208
+ *
1209
+ * @example Namespace import (TypeScript: `import * as React from 'react'`)
1210
+ * ```ts
1211
+ * createImport({ name: 'React', path: 'react', isNameSpace: true })
1212
+ * ```
1213
+ */
1214
+ type ImportNode = BaseNode & {
1215
+ kind: 'Import';
1216
+ /**
1217
+ * Import name(s) to be used.
1218
+ * @example ['useState']
1219
+ * @example 'React'
1220
+ */
1221
+ name: ImportName;
1222
+ /**
1223
+ * Path for the import.
1224
+ * @example '@kubb/core'
1225
+ */
1226
+ path: string;
1227
+ /**
1228
+ * Add type-only import prefix.
1229
+ * - `true` generates `import type { Type } from './path'`
1230
+ * - `false` generates `import { Type } from './path'`
1231
+ * @default false
1232
+ */
1233
+ isTypeOnly?: boolean | null;
1234
+ /**
1235
+ * Import entire module as namespace.
1236
+ * - `true` generates `import * as Name from './path'`
1237
+ * - `false` generates standard import
1238
+ * @default false
1239
+ */
1240
+ isNameSpace?: boolean | null;
1241
+ /**
1242
+ * When set, the import path is resolved relative to this root.
1241
1243
  */
1242
- strategy?: 'one' | 'any';
1244
+ root?: string | null;
1243
1245
  };
1244
1246
  /**
1245
- * Intersection schema, often from `allOf`.
1247
+ * Represents a language-agnostic export/public API declaration.
1246
1248
  *
1247
- * @example
1249
+ * @example Named export (TypeScript: `export { Pets } from './Pets'`)
1248
1250
  * ```ts
1249
- * const intersectionSchema: IntersectionSchemaNode = {
1250
- * kind: 'Schema',
1251
- * type: 'intersection',
1252
- * members: [],
1253
- * }
1251
+ * createExport({ name: ['Pets'], path: './Pets' })
1252
+ * ```
1253
+ *
1254
+ * @example Type-only export (TypeScript: `export type { Pet } from './Pet'`)
1255
+ * ```ts
1256
+ * createExport({ name: ['Pet'], path: './Pet', isTypeOnly: true })
1257
+ * ```
1258
+ *
1259
+ * @example Wildcard export (TypeScript: `export * from './utils'`)
1260
+ * ```ts
1261
+ * createExport({ path: './utils' })
1262
+ * ```
1263
+ *
1264
+ * @example Namespace alias (TypeScript: `export * as utils from './utils'`)
1265
+ * ```ts
1266
+ * createExport({ name: 'utils', path: './utils', asAlias: true })
1254
1267
  * ```
1255
1268
  */
1256
- type IntersectionSchemaNode = CompositeSchemaNodeBase & {
1269
+ type ExportNode = BaseNode & {
1270
+ kind: 'Export';
1257
1271
  /**
1258
- * Schema type discriminator.
1272
+ * Export name(s) to be used. When omitted, generates a wildcard export.
1273
+ * @example ['useState']
1274
+ * @example 'React'
1259
1275
  */
1260
- type: 'intersection';
1261
- };
1262
- /**
1263
- * One named enum item.
1264
- */
1265
- type EnumValueNode = {
1276
+ name?: string | Array<string> | null;
1266
1277
  /**
1267
- * Enum item name.
1278
+ * Path for the export.
1279
+ * @example '@kubb/core'
1268
1280
  */
1269
- name: string;
1281
+ path: string;
1270
1282
  /**
1271
- * Enum item value.
1283
+ * Add type-only export prefix.
1284
+ * - `true` generates `export type { Type } from './path'`
1285
+ * - `false` generates `export { Type } from './path'`
1286
+ * @default false
1272
1287
  */
1273
- value: string | number | boolean;
1288
+ isTypeOnly?: boolean | null;
1274
1289
  /**
1275
- * Primitive type of the enum value.
1290
+ * Export as an aliased namespace.
1291
+ * - `true` generates `export * as aliasName from './path'`
1292
+ * - `false` generates a standard export
1293
+ * @default false
1276
1294
  */
1277
- primitive: Extract<PrimitiveSchemaType, 'string' | 'number' | 'boolean'>;
1295
+ asAlias?: boolean | null;
1278
1296
  };
1279
1297
  /**
1280
- * Enum schema node.
1298
+ * Represents a fragment of source code within a file.
1281
1299
  *
1282
- * @example
1300
+ * @example Named exportable source
1283
1301
  * ```ts
1284
- * const enumSchema: EnumSchemaNode = {
1285
- * kind: 'Schema',
1286
- * type: 'enum',
1287
- * enumValues: ['a', 'b'],
1288
- * }
1302
+ * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true, isIndexable: true })
1303
+ * ```
1304
+ *
1305
+ * @example Inline unnamed code block
1306
+ * ```ts
1307
+ * createSource({ nodes: [createText('const x = 1')] })
1289
1308
  * ```
1290
1309
  */
1291
- type EnumSchemaNode = SchemaNodeBase & {
1310
+ type SourceNode = BaseNode & {
1311
+ kind: 'Source';
1292
1312
  /**
1293
- * Schema type discriminator.
1313
+ * Optional name identifying this source (used for deduplication and barrel generation).
1294
1314
  */
1295
- type: 'enum';
1315
+ name?: string | null;
1296
1316
  /**
1297
- * Enum values in simple form.
1317
+ * Mark this source as a type-only export.
1318
+ * @default false
1298
1319
  */
1299
- enumValues?: Array<string | number | boolean | null>;
1320
+ isTypeOnly?: boolean | null;
1300
1321
  /**
1301
- * Enum values in named form.
1302
- * If present, this is used instead of `enumValues`.
1322
+ * Include `export` keyword in the generated source.
1323
+ * @default false
1303
1324
  */
1304
- namedEnumValues?: Array<EnumValueNode>;
1325
+ isExportable?: boolean | null;
1326
+ /**
1327
+ * Include this source in barrel/index file generation.
1328
+ * @default false
1329
+ */
1330
+ isIndexable?: boolean | null;
1331
+ /**
1332
+ * Structured child nodes representing the content of this source fragment, in DOM order.
1333
+ * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
1334
+ */
1335
+ nodes?: Array<CodeNode>;
1305
1336
  };
1306
1337
  /**
1307
- * Reference schema that points to another schema definition.
1338
+ * Represents a fully resolved file in the AST.
1339
+ *
1340
+ * Created via `createFile()`, which computes the `id`, `name`, and `extname` from the input
1341
+ * and deduplicates `imports`, `exports`, and `sources`.
1308
1342
  *
1309
1343
  * @example
1310
1344
  * ```ts
1311
- * const refSchema: RefSchemaNode = {
1312
- * kind: 'Schema',
1313
- * type: 'ref',
1314
- * ref: '#/components/schemas/Pet',
1315
- * }
1345
+ * const file = createFile({
1346
+ * baseName: 'petStore.ts',
1347
+ * path: 'src/models/petStore.ts',
1348
+ * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })],
1349
+ * imports: [createImport({ name: ['z'], path: 'zod' })],
1350
+ * exports: [createExport({ name: ['Pet'], path: './petStore' })],
1351
+ * })
1352
+ * // file.id = SHA256 hash of the path
1353
+ * // file.name = 'petStore'
1354
+ * // file.extname = '.ts'
1316
1355
  * ```
1317
1356
  */
1318
- type RefSchemaNode = SchemaNodeBase & {
1357
+ type FileNode<TMeta extends object = object> = BaseNode & {
1358
+ kind: 'File';
1319
1359
  /**
1320
- * Schema type discriminator.
1360
+ * Unique identifier derived from a SHA256 hash of the file path. Computed
1361
+ * by `createFile`; callers do not need to provide it.
1321
1362
  */
1322
- type: 'ref';
1363
+ id: string;
1323
1364
  /**
1324
- * Referenced schema name.
1365
+ * File name without extension, derived from `baseName`.
1366
+ * @link https://nodejs.org/api/path.html#pathformatpathobject
1325
1367
  */
1326
- name?: string;
1368
+ name: string;
1327
1369
  /**
1328
- * Original `$ref` path, for example, `#/components/schemas/Order`.
1329
- * Used to resolve names later.
1370
+ * File base name, including extension.
1371
+ * Based on UNIX basename: `${name}${extname}`
1372
+ * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
1330
1373
  */
1331
- ref?: string;
1374
+ baseName: `${string}.${string}`;
1332
1375
  /**
1333
- * Pattern copied from a sibling `pattern` field.
1376
+ * Full qualified path to the file.
1334
1377
  */
1335
- pattern?: string;
1378
+ path: string;
1336
1379
  /**
1337
- * The fully-parsed schema that this ref resolves to.
1338
- * Populated during OAS parsing when the referenced definition can be resolved.
1339
- * `undefined` when the ref cannot be resolved or is part of a circular chain.
1340
- *
1341
- * Useful for inspecting the referenced schema's structure (e.g. `primitive`, `properties`)
1342
- * without following the reference manually.
1380
+ * File extension extracted from `baseName`.
1343
1381
  */
1344
- schema?: SchemaNode;
1345
- };
1346
- /**
1347
- * Datetime schema.
1348
- *
1349
- * @example
1350
- * ```ts
1351
- * const datetimeSchema: DatetimeSchemaNode = { kind: 'Schema', type: 'datetime' }
1352
- * ```
1353
- */
1354
- type DatetimeSchemaNode = SchemaNodeBase & {
1382
+ extname: Extname;
1355
1383
  /**
1356
- * Schema type discriminator.
1384
+ * Deduplicated list of source code fragments.
1357
1385
  */
1358
- type: 'datetime';
1386
+ sources: Array<SourceNode>;
1359
1387
  /**
1360
- * Whether the datetime includes a timezone offset (`dateType: 'stringOffset'`).
1388
+ * Deduplicated list of import declarations.
1361
1389
  */
1362
- offset?: boolean;
1390
+ imports: Array<ImportNode>;
1363
1391
  /**
1364
- * Whether the datetime is local (no timezone, `dateType: 'stringLocal'`).
1392
+ * Deduplicated list of export declarations.
1365
1393
  */
1366
- local?: boolean;
1367
- };
1368
- /**
1369
- * Shared base for `date` and `time` schemas.
1370
- */
1371
- type TemporalSchemaNodeBase<T extends 'date' | 'time'> = SchemaNodeBase & {
1394
+ exports: Array<ExportNode>;
1372
1395
  /**
1373
- * Schema type discriminator.
1396
+ * Optional metadata attached to this file (used by plugins for barrel generation etc.).
1374
1397
  */
1375
- type: T;
1398
+ meta?: TMeta;
1376
1399
  /**
1377
- * Output representation in generated code.
1400
+ * Optional banner prepended to the generated file content.
1401
+ * Accepts `null` so `resolver.resolveBanner()` results can be passed directly.
1378
1402
  */
1379
- representation: 'date' | 'string';
1403
+ banner?: string | null;
1404
+ /**
1405
+ * Optional footer appended to the generated file content.
1406
+ * Accepts `null` so `resolver.resolveFooter()` results can be passed directly.
1407
+ */
1408
+ footer?: string | null;
1380
1409
  };
1410
+ //#endregion
1411
+ //#region src/nodes/function.d.ts
1381
1412
  /**
1382
- * Date schema node.
1413
+ * AST node representing a language-agnostic type expression used as a function parameter
1414
+ * type annotation. Each language printer renders the variant into its own syntax.
1383
1415
  *
1384
- * @example
1416
+ * - `struct` — an inline anonymous type grouping named fields.
1417
+ * TypeScript renders as `{ petId: string; name?: string }`.
1418
+ * - `member` — a single named field accessed from a named group type.
1419
+ * TypeScript renders as `PathParams['petId']`.
1420
+ *
1421
+ * @example Reference variant
1385
1422
  * ```ts
1386
- * const dateSchema: DateSchemaNode = { kind: 'Schema', type: 'date', representation: 'string' }
1423
+ * createParamsType({ variant: 'reference', name: 'QueryParams' })
1424
+ * // QueryParams
1387
1425
  * ```
1388
- */
1389
- type DateSchemaNode = TemporalSchemaNodeBase<'date'>;
1390
- /**
1391
- * Time schema node.
1392
1426
  *
1393
- * @example
1427
+ * @example Struct variant
1394
1428
  * ```ts
1395
- * const timeSchema: TimeSchemaNode = { kind: 'Schema', type: 'time', representation: 'string' }
1429
+ * createParamsType({ variant: 'struct', properties: [{ name: 'petId', optional: false, type: createParamsType({ variant: 'reference', name: 'string' }) }] })
1430
+ * // { petId: string }
1396
1431
  * ```
1397
- */
1398
- type TimeSchemaNode = TemporalSchemaNodeBase<'time'>;
1399
- /**
1400
- * String schema node.
1401
1432
  *
1402
- * @example
1433
+ * @example Member variant
1403
1434
  * ```ts
1404
- * const stringSchema: StringSchemaNode = { kind: 'Schema', type: 'string' }
1435
+ * createParamsType({ variant: 'member', base: 'PathParams', key: 'petId' })
1436
+ * // PathParams['petId']
1405
1437
  * ```
1406
1438
  */
1407
- type StringSchemaNode = SchemaNodeBase & {
1439
+ type ParamsTypeNode = BaseNode & {
1408
1440
  /**
1409
- * Schema type discriminator.
1441
+ * Node kind.
1410
1442
  */
1411
- type: 'string';
1443
+ kind: 'ParamsType';
1444
+ } & ({
1412
1445
  /**
1413
- * Minimum string length.
1446
+ * Reference variant — a plain type name or identifier.
1447
+ * TypeScript renders as-is, e.g. `string`, `QueryParams`, `Partial<Config>`.
1414
1448
  */
1415
- min?: number;
1449
+ variant: 'reference';
1416
1450
  /**
1417
- * Maximum string length.
1451
+ * The full type name string, e.g. `'string'`, `'QueryParams'`, `'Partial<Config>'`.
1418
1452
  */
1419
- max?: number;
1453
+ name: string;
1454
+ } | {
1455
+ /**
1456
+ * Struct variant — an inline anonymous type grouping named fields.
1457
+ * TypeScript renders as `{ key: Type; other?: OtherType }`.
1458
+ */
1459
+ variant: 'struct';
1460
+ /**
1461
+ * Properties of the struct type.
1462
+ */
1463
+ properties: Array<{
1464
+ name: string;
1465
+ optional: boolean;
1466
+ type: ParamsTypeNode;
1467
+ }>;
1468
+ } | {
1469
+ /**
1470
+ * Member variant — a single named field accessed from a group type.
1471
+ * TypeScript renders as `Base['key']`.
1472
+ */
1473
+ variant: 'member';
1474
+ /**
1475
+ * Base type name, e.g. `'DeletePetPathParams'`.
1476
+ */
1477
+ base: string;
1420
1478
  /**
1421
- * Regex pattern.
1479
+ * The field name to access, e.g. `'petId'`.
1422
1480
  */
1423
- pattern?: string;
1424
- };
1481
+ key: string;
1482
+ });
1425
1483
  /**
1426
- * Numeric schema (`number`, `integer`, or `bigint`).
1484
+ * AST node for one function parameter.
1427
1485
  *
1428
- * @example
1429
- * ```ts
1430
- * const numberSchema: NumberSchemaNode = { kind: 'Schema', type: 'number' }
1431
- * ```
1486
+ * @example Required parameter
1487
+ * `name: Type`
1488
+ *
1489
+ * @example Optional parameter
1490
+ * `name?: Type`
1491
+ *
1492
+ * @example Parameter with default value
1493
+ * `name: Type = defaultValue`
1494
+ *
1495
+ * @example Rest parameter
1496
+ * `...name: Type[]`
1432
1497
  */
1433
- type NumberSchemaNode = SchemaNodeBase & {
1434
- /**
1435
- * Schema type discriminator.
1436
- */
1437
- type: 'number' | 'integer' | 'bigint';
1438
- /**
1439
- * Minimum value.
1440
- */
1441
- min?: number;
1498
+ type FunctionParameterNode = BaseNode & {
1442
1499
  /**
1443
- * Maximum value.
1500
+ * Node kind.
1444
1501
  */
1445
- max?: number;
1502
+ kind: 'FunctionParameter';
1446
1503
  /**
1447
- * Exclusive minimum value.
1504
+ * Parameter name in the generated signature.
1448
1505
  */
1449
- exclusiveMinimum?: number;
1506
+ name: string;
1450
1507
  /**
1451
- * Exclusive maximum value.
1508
+ * Type annotation as a structured {@link ParamsTypeNode}.
1509
+ * Omit for untyped output.
1510
+ *
1511
+ * @example Reference type node
1512
+ * `{ kind: 'ParamsType', variant: 'reference', name: 'string' }` → `petId: string`
1513
+ *
1514
+ * @example Struct type node
1515
+ * `{ kind: 'ParamsType', variant: 'struct', properties: [...] }` → `{ key: Type; other?: OtherType }`
1516
+ *
1517
+ * @example Member type node
1518
+ * `{ kind: 'ParamsType', variant: 'member', base: 'PathParams', key: 'petId' }` → `PathParams['petId']`
1452
1519
  */
1453
- exclusiveMaximum?: number;
1520
+ type?: ParamsTypeNode;
1454
1521
  /**
1455
- * The value must be a multiple of this number.
1522
+ * When `true` the parameter is emitted as a rest parameter.
1523
+ *
1524
+ * @example Rest parameter
1525
+ * `...name: Type[]`
1456
1526
  */
1457
- multipleOf?: number;
1458
- };
1527
+ rest?: boolean;
1528
+ }
1459
1529
  /**
1460
- * Scalar schema with no extra constraints.
1530
+ * Optional parameter — rendered with `?` and may be omitted by the caller.
1531
+ * Cannot be combined with `default` because a defaulted parameter is already optional.
1532
+ */
1533
+ & ({
1534
+ optional: true;
1535
+ default?: never;
1536
+ }
1537
+ /**
1538
+ * Required parameter, or a parameter with a default value.
1461
1539
  *
1462
- * @example
1463
- * ```ts
1464
- * const anySchema: ScalarSchemaNode = { kind: 'Schema', type: 'any' }
1465
- * ```
1540
+ * @example Required
1541
+ * `name: Type`
1542
+ *
1543
+ * @example With default
1544
+ * `name: Type = default`
1466
1545
  */
1467
- type ScalarSchemaNode = SchemaNodeBase & {
1468
- /**
1469
- * Schema type discriminator.
1470
- */
1471
- type: ScalarSchemaType;
1472
- };
1546
+ | {
1547
+ optional?: false;
1548
+ default?: string;
1549
+ });
1473
1550
  /**
1474
- * URL schema node.
1475
- * Can include an OpenAPI-style path template for template literal types.
1551
+ * AST node for a group of related function parameters treated as a single unit.
1476
1552
  *
1477
- * @example
1478
- * ```ts
1479
- * const urlSchema: UrlSchemaNode = { kind: 'Schema', type: 'url', path: '/pets/{petId}' }
1480
- * ```
1553
+ * Each language printer decides how to render this group:
1554
+ * - TypeScript/JS: destructured object `{ key1, key2 }: { key1: Type1; key2: Type2 } = {}`
1555
+ * - Python: keyword-only args or a typed dict parameter
1556
+ * - C# / Kotlin: named record / data-class parameter
1557
+ *
1558
+ * When `inline` is `true`, the group is spread as individual top-level parameters
1559
+ * rather than wrapped in a single grouped construct.
1560
+ *
1561
+ * @example Grouped destructuring
1562
+ * `{ id, name }: { id: string; name: string } = {}`
1563
+ *
1564
+ * @example Inline (spread as individual parameters)
1565
+ * `id: string, name: string`
1481
1566
  */
1482
- type UrlSchemaNode = SchemaNodeBase & {
1483
- /**
1484
- * Schema type discriminator.
1485
- */
1486
- type: 'url';
1567
+ type ParameterGroupNode = BaseNode & {
1487
1568
  /**
1488
- * OpenAPI-style path template, for example, `'/pets/{petId}'`.
1569
+ * Node kind.
1489
1570
  */
1490
- path?: string;
1571
+ kind: 'ParameterGroup';
1491
1572
  /**
1492
- * Minimum string length.
1573
+ * The individual parameters that form the group.
1574
+ * Rendered as a destructured object or spread inline when `inline` is `true`.
1493
1575
  */
1494
- min?: number;
1576
+ properties: Array<FunctionParameterNode>;
1495
1577
  /**
1496
- * Maximum string length.
1578
+ * Optional explicit type annotation for the whole group.
1579
+ * When absent, printers auto-compute it from `properties`.
1497
1580
  */
1498
- max?: number;
1499
- };
1500
- /**
1501
- * Format-string schema for string-based formats that support length constraints.
1502
- *
1503
- * @example
1504
- * ```ts
1505
- * const uuidSchema: FormatStringSchemaNode = { kind: 'Schema', type: 'uuid', min: 36, max: 36 }
1506
- * ```
1507
- */
1508
- type FormatStringSchemaNode = SchemaNodeBase & {
1581
+ type?: ParamsTypeNode;
1509
1582
  /**
1510
- * Schema type discriminator.
1583
+ * When `true`, `properties` are emitted as individual top-level parameters instead of
1584
+ * being wrapped in a single grouped construct.
1585
+ *
1586
+ * @default false
1511
1587
  */
1512
- type: 'uuid' | 'email';
1588
+ inline?: boolean;
1513
1589
  /**
1514
- * Minimum string length.
1590
+ * Whether the group as a whole is optional.
1591
+ * If omitted, printers infer this from child properties.
1515
1592
  */
1516
- min?: number;
1593
+ optional?: boolean;
1517
1594
  /**
1518
- * Maximum string length.
1595
+ * Default value for the group, written verbatim after `=`.
1596
+ * Commonly `'{}'` to allow omitting the argument entirely.
1519
1597
  */
1520
- max?: number;
1598
+ default?: string;
1521
1599
  };
1522
1600
  /**
1523
- * IPv4 address schema node.
1601
+ * AST node for a complete function parameter list.
1524
1602
  *
1525
- * @example
1526
- * ```ts
1527
- * const ipv4Schema: Ipv4SchemaNode = { kind: 'Schema', type: 'ipv4' }
1528
- * ```
1603
+ * Printers are responsible for sorting (`required` → `optional` → `defaulted`).
1604
+ * Nodes are plain immutable data.
1605
+ *
1606
+ * Renders differently depending on the output mode:
1607
+ * - `declaration` → `(id: string, config: Config = {})` — function declaration parameters
1608
+ * - `call` → `(id, { method, url })` — function call arguments
1609
+ * - `keys` → `{ id, config }` — key names only (for destructuring)
1610
+ * - `values` → `{ id: id, config: config }` — key → value pairs
1529
1611
  */
1530
- type Ipv4SchemaNode = SchemaNodeBase & {
1612
+ type FunctionParametersNode = BaseNode & {
1531
1613
  /**
1532
- * Schema type discriminator.
1614
+ * Node kind.
1533
1615
  */
1534
- type: 'ipv4';
1535
- };
1536
- /**
1537
- * IPv6 address schema node.
1538
- *
1539
- * @example
1540
- * ```ts
1541
- * const ipv6Schema: Ipv6SchemaNode = { kind: 'Schema', type: 'ipv6' }
1542
- * ```
1543
- */
1544
- type Ipv6SchemaNode = SchemaNodeBase & {
1616
+ kind: 'FunctionParameters';
1545
1617
  /**
1546
- * Schema type discriminator.
1618
+ * Ordered parameter nodes.
1547
1619
  */
1548
- type: 'ipv6';
1620
+ params: ReadonlyArray<FunctionParameterNode | ParameterGroupNode>;
1549
1621
  };
1550
1622
  /**
1551
- * Mapping from schema type literals to concrete schema node types.
1552
- * Used by `narrowSchema`.
1623
+ * Union of all function-parameter AST node variants used by the function-parameter printer.
1553
1624
  */
1554
- type SchemaNodeByType = {
1555
- object: ObjectSchemaNode;
1556
- array: ArraySchemaNode;
1557
- tuple: ArraySchemaNode;
1558
- union: UnionSchemaNode;
1559
- intersection: IntersectionSchemaNode;
1560
- enum: EnumSchemaNode;
1561
- ref: RefSchemaNode;
1562
- datetime: DatetimeSchemaNode;
1563
- date: DateSchemaNode;
1564
- time: TimeSchemaNode;
1565
- string: StringSchemaNode;
1566
- number: NumberSchemaNode;
1567
- integer: NumberSchemaNode;
1568
- bigint: NumberSchemaNode;
1569
- boolean: ScalarSchemaNode;
1570
- null: ScalarSchemaNode;
1571
- any: ScalarSchemaNode;
1572
- unknown: ScalarSchemaNode;
1573
- void: ScalarSchemaNode;
1574
- never: ScalarSchemaNode;
1575
- uuid: FormatStringSchemaNode;
1576
- email: FormatStringSchemaNode;
1577
- url: UrlSchemaNode;
1578
- ipv4: Ipv4SchemaNode;
1579
- ipv6: Ipv6SchemaNode;
1580
- blob: ScalarSchemaNode;
1581
- };
1625
+ type FunctionParamNode = FunctionParameterNode | ParameterGroupNode | FunctionParametersNode | ParamsTypeNode;
1582
1626
  /**
1583
- * Union of all schema node types.
1627
+ * Handler map keys one per `FunctionParamNode` kind.
1584
1628
  */
1585
- type SchemaNode = ObjectSchemaNode | ArraySchemaNode | UnionSchemaNode | IntersectionSchemaNode | EnumSchemaNode | RefSchemaNode | DatetimeSchemaNode | DateSchemaNode | TimeSchemaNode | StringSchemaNode | NumberSchemaNode | UrlSchemaNode | FormatStringSchemaNode | Ipv4SchemaNode | Ipv6SchemaNode | ScalarSchemaNode;
1629
+ type FunctionNodeType = 'functionParameter' | 'parameterGroup' | 'functionParameters' | 'paramsType';
1586
1630
  //#endregion
1587
1631
  //#region src/nodes/parameter.d.ts
1588
1632
  type ParameterLocation = 'path' | 'query' | 'header' | 'cookie';
@@ -1655,12 +1699,16 @@ type MediaType = 'application/json' | 'application/xml' | 'application/x-www-for
1655
1699
  /**
1656
1700
  * AST node representing one operation response variant.
1657
1701
  *
1702
+ * Mirrors {@link OperationNode.requestBody}: the response body schemas live exclusively inside
1703
+ * the `content` array (one entry per content type), so the same schema is never duplicated at the
1704
+ * node root and inside `content`.
1705
+ *
1658
1706
  * @example
1659
1707
  * ```ts
1660
1708
  * const response: ResponseNode = {
1661
1709
  * kind: 'Response',
1662
1710
  * statusCode: '200',
1663
- * schema: createSchema({ type: 'string' }),
1711
+ * content: [{ contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
1664
1712
  * }
1665
1713
  * ```
1666
1714
  */
@@ -1678,56 +1726,80 @@ type ResponseNode = BaseNode & {
1678
1726
  */
1679
1727
  description?: string;
1680
1728
  /**
1681
- * Response body schema.
1682
- */
1683
- schema: SchemaNode;
1684
- /**
1685
- * Response media type.
1686
- */
1687
- mediaType?: MediaType | null;
1688
- /**
1689
- * Property keys to exclude from the generated type via `Omit<Type, Keys>`.
1690
- * Set when a referenced schema has `writeOnly` fields that should not appear in response types.
1729
+ * All available content type entries for this response.
1730
+ *
1731
+ * When the adapter `contentType` option is set, this array contains exactly one entry for that
1732
+ * content type. Otherwise it contains one entry per content type declared in the spec, so that
1733
+ * plugins can generate a union of response types (e.g. `application/json` and `application/xml`).
1734
+ * Body-less responses keep a single entry whose `schema` is the empty/`void` placeholder.
1735
+ *
1736
+ * @example
1737
+ * ```ts
1738
+ * // spec response declares both application/json and application/xml
1739
+ * response.content[0].contentType // 'application/json'
1740
+ * response.content[1].contentType // 'application/xml'
1741
+ * ```
1691
1742
  */
1692
- keysToOmit?: Array<string>;
1743
+ content?: Array<ContentNode>;
1693
1744
  };
1694
1745
  //#endregion
1695
1746
  //#region src/nodes/operation.d.ts
1696
1747
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE';
1697
1748
  /**
1698
- * AST node representing one API operation.
1749
+ * Transport an operation belongs to.
1750
+ */
1751
+ type OperationProtocol = 'http';
1752
+ /**
1753
+ * AST node representing an operation request body.
1699
1754
  *
1700
- * @example
1701
- * ```ts
1702
- * const operation: OperationNode = {
1703
- * kind: 'Operation',
1704
- * operationId: 'listPets',
1705
- * method: 'GET',
1706
- * path: '/pets',
1707
- * tags: [],
1708
- * parameters: [],
1709
- * responses: [],
1755
+ * Body schemas live exclusively inside the `content` array (one entry per content type),
1756
+ * mirroring {@link ResponseNode}.
1757
+ *
1758
+ * @example
1759
+ * ```ts
1760
+ * const requestBody: RequestBodyNode = {
1761
+ * kind: 'RequestBody',
1762
+ * required: true,
1763
+ * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
1710
1764
  * }
1711
1765
  * ```
1712
1766
  */
1713
- type OperationNode = BaseNode & {
1767
+ type RequestBodyNode = BaseNode & {
1714
1768
  /**
1715
1769
  * Node kind.
1716
1770
  */
1717
- kind: 'Operation';
1771
+ kind: 'RequestBody';
1718
1772
  /**
1719
- * Operation identifier, usually from OpenAPI `operationId`.
1773
+ * Human-readable request body description.
1720
1774
  */
1721
- operationId: string;
1775
+ description?: string;
1722
1776
  /**
1723
- * HTTP Method like 'GET'
1777
+ * Whether the request body is required (`requestBody.required: true` in the spec).
1778
+ * When `false` or absent, the generated `data` parameter should be optional.
1724
1779
  */
1725
- method: HttpMethod;
1780
+ required?: boolean;
1726
1781
  /**
1727
- * OpenAPI-style path string, for example `/pets/{petId}`.
1728
- * Path parameters retain the `{param}` notation from the original spec.
1782
+ * All available content type entries for this request body.
1783
+ *
1784
+ * When the adapter `contentType` option is set, this array contains exactly one entry for
1785
+ * that content type. Otherwise it contains one entry per content type declared in the spec,
1786
+ * so that plugins can generate code for every variant (e.g. separate hooks for
1787
+ * `application/json` and `multipart/form-data`).
1729
1788
  */
1730
- path: string;
1789
+ content?: Array<ContentNode>;
1790
+ };
1791
+ /**
1792
+ * Fields shared by every operation, regardless of transport.
1793
+ */
1794
+ type OperationNodeBase = BaseNode & {
1795
+ /**
1796
+ * Node kind.
1797
+ */
1798
+ kind: 'Operation';
1799
+ /**
1800
+ * Operation identifier, usually from OpenAPI `operationId`.
1801
+ */
1802
+ operationId: string;
1731
1803
  /**
1732
1804
  * Group labels for the operation.
1733
1805
  * Usually copied from OpenAPI `tags`.
@@ -1750,54 +1822,64 @@ type OperationNode = BaseNode & {
1750
1822
  */
1751
1823
  parameters: Array<ParameterNode>;
1752
1824
  /**
1753
- * Request body metadata for the operation.
1825
+ * Request body for the operation.
1754
1826
  */
1755
- requestBody?: {
1756
- /**
1757
- * Human-readable request body description.
1758
- */
1759
- description?: string;
1760
- /**
1761
- * Whether the request body is required (`requestBody.required: true` in the spec).
1762
- * When `false` or absent, the generated `data` parameter should be optional.
1763
- */
1764
- required?: boolean;
1765
- /**
1766
- * All available content type entries for this request body.
1767
- *
1768
- * When the adapter `contentType` option is set, this array contains exactly one entry for
1769
- * that content type. Otherwise it contains one entry per content type declared in the spec,
1770
- * so that plugins can generate code for every variant (e.g. separate hooks for
1771
- * `application/json` and `multipart/form-data`).
1772
- *
1773
- * @example
1774
- * ```ts
1775
- * // spec has both application/json and multipart/form-data
1776
- * requestBody.content[0].contentType // 'application/json'
1777
- * requestBody.content[1].contentType // 'multipart/form-data'
1778
- * ```
1779
- */
1780
- content?: Array<{
1781
- /**
1782
- * The content type for this entry (e.g. `'application/json'`).
1783
- */
1784
- contentType: string;
1785
- /**
1786
- * Request body schema for this content type.
1787
- */
1788
- schema?: SchemaNode;
1789
- /**
1790
- * Property keys to exclude from the generated request body type via `Omit<Type, Keys>`.
1791
- * Set when a referenced schema has `readOnly` fields that should be omitted in request types.
1792
- */
1793
- keysToOmit?: Array<string>;
1794
- }>;
1795
- };
1827
+ requestBody?: RequestBodyNode;
1796
1828
  /**
1797
1829
  * Operation responses.
1798
1830
  */
1799
1831
  responses: Array<ResponseNode>;
1800
1832
  };
1833
+ /**
1834
+ * Operation served over HTTP/REST (OpenAPI). `method` and `path` are guaranteed.
1835
+ *
1836
+ * @example
1837
+ * ```ts
1838
+ * const operation: HttpOperationNode = {
1839
+ * kind: 'Operation',
1840
+ * operationId: 'listPets',
1841
+ * protocol: 'http',
1842
+ * method: 'GET',
1843
+ * path: '/pets',
1844
+ * tags: [],
1845
+ * parameters: [],
1846
+ * responses: [],
1847
+ * }
1848
+ * ```
1849
+ */
1850
+ type HttpOperationNode = OperationNodeBase & {
1851
+ /**
1852
+ * Transport the operation belongs to.
1853
+ */
1854
+ protocol?: 'http';
1855
+ /**
1856
+ * HTTP method like `'GET'`.
1857
+ */
1858
+ method: HttpMethod;
1859
+ /**
1860
+ * OpenAPI-style path string, for example `/pets/{petId}`, with `{param}` notation preserved.
1861
+ */
1862
+ path: string;
1863
+ };
1864
+ /**
1865
+ * Operation for a non-HTTP transport. HTTP-only fields are forbidden.
1866
+ */
1867
+ type GenericOperationNode = OperationNodeBase & {
1868
+ /**
1869
+ * Transport the operation belongs to.
1870
+ */
1871
+ protocol?: Exclude<OperationProtocol, 'http'>;
1872
+ method?: never;
1873
+ path?: never;
1874
+ };
1875
+ /**
1876
+ * AST node representing one API operation.
1877
+ *
1878
+ * Discriminated on `protocol`: an {@link HttpOperationNode} (`protocol: 'http'`) guarantees
1879
+ * `method` and `path`, while a {@link GenericOperationNode} omits them. Narrow with
1880
+ * `isHttpOperationNode(node)` or `node.protocol === 'http'` before reading `method`/`path`.
1881
+ */
1882
+ type OperationNode = HttpOperationNode | GenericOperationNode;
1801
1883
  //#endregion
1802
1884
  //#region src/nodes/output.d.ts
1803
1885
  /**
@@ -1826,32 +1908,62 @@ type OutputNode = BaseNode & {
1826
1908
  //#endregion
1827
1909
  //#region src/nodes/root.d.ts
1828
1910
  /**
1829
- * Basic metadata for an API document.
1830
- * Adapters fill fields that exist in their source format.
1911
+ * Metadata for an API document, populated by the adapter and available to every generator.
1912
+ *
1913
+ * All fields are plain JSON-serializable values — no `Set`, no `Map`, no class instances.
1914
+ * Computed fields (`circularNames`, `enumNames`) are pre-calculated once during the adapter
1915
+ * pre-scan so generators never need to iterate the full schema list themselves.
1831
1916
  *
1832
1917
  * @example
1833
1918
  * ```ts
1834
- * const meta: InputMeta = { title: 'Pet API', version: '1.0.0' }
1919
+ * const meta: InputMeta = { title: 'Pet Store', version: '1.0.0', baseURL: 'https://petstore.swagger.io/v2', circularNames: [], enumNames: [] }
1835
1920
  * ```
1836
1921
  */
1837
1922
  type InputMeta = {
1838
1923
  /**
1839
- * API title (from `info.title` in OAS/AsyncAPI).
1924
+ * API title from `info.title` in the source document.
1840
1925
  */
1841
1926
  title?: string;
1842
1927
  /**
1843
- * API description (from `info.description` in OAS/AsyncAPI).
1928
+ * API description from `info.description` in the source document.
1844
1929
  */
1845
1930
  description?: string;
1846
1931
  /**
1847
- * API version string (from `info.version` in OAS/AsyncAPI).
1932
+ * API version string from `info.version` in the source document.
1848
1933
  */
1849
1934
  version?: string;
1850
1935
  /**
1851
- * Resolved API base URL.
1852
- * For OpenAPI and AsyncAPI, this comes from the selected server URL.
1936
+ * Resolved base URL from the first matching server entry in the source document.
1937
+ */
1938
+ baseURL?: string | null;
1939
+ /**
1940
+ * Names of schemas that participate in a circular reference chain.
1941
+ * Computed once during the adapter pre-scan — use this instead of calling
1942
+ * `findCircularSchemas` per generator call.
1943
+ *
1944
+ * Convert to a `Set` once at the start of a generator, not per-schema,
1945
+ * to keep lookup O(1) without repeated allocations.
1946
+ *
1947
+ * @example Wrap a circular schema in z.lazy()
1948
+ * ```ts
1949
+ * const circular = new Set(meta.circularNames)
1950
+ * if (circular.has(schema.name)) { ... }
1951
+ * ```
1952
+ */
1953
+ circularNames: ReadonlyArray<string>;
1954
+ /**
1955
+ * Names of schemas whose type is `enum`.
1956
+ * Computed once during the adapter pre-scan — use this instead of filtering
1957
+ * schemas per generator call.
1958
+ *
1959
+ * Convert to a `Set` once at the start of a generator when you need repeated
1960
+ * membership checks, rather than calling `.includes()` per schema.
1961
+ *
1962
+ * @example Check if a referenced schema is an enum
1963
+ * `const enums = new Set(meta.enumNames)`
1964
+ * `const isEnum = enums.has(schemaName)`
1853
1965
  */
1854
- baseURL?: string;
1966
+ enumNames: ReadonlyArray<string>;
1855
1967
  };
1856
1968
  /**
1857
1969
  * Input AST node that contains all schemas and operations for one API document.
@@ -1880,7 +1992,38 @@ type InputNode = BaseNode & {
1880
1992
  */
1881
1993
  operations: Array<OperationNode>;
1882
1994
  /**
1883
- * Optional document metadata populated by the adapter.
1995
+ * Document metadata populated by the adapter.
1996
+ */
1997
+ meta: InputMeta;
1998
+ };
1999
+ /**
2000
+ * Streaming variant of `InputNode` for memory-efficient processing of large API specs.
2001
+ *
2002
+ * `schemas` and `operations` are `AsyncIterable` rather than arrays — each `for await`
2003
+ * loop creates a fresh parse pass from the cached in-memory document, so multiple
2004
+ * consumers (plugins) can iterate independently without keeping all nodes in memory.
2005
+ *
2006
+ * @example
2007
+ * ```ts
2008
+ * for await (const schema of inputStreamNode.schemas) {
2009
+ * // only this one SchemaNode is live here; previous ones are GC-eligible
2010
+ * }
2011
+ * ```
2012
+ */
2013
+ type InputStreamNode = {
2014
+ kind: 'Input';
2015
+ /**
2016
+ * Lazily parsed schema nodes. Each `for await` creates a fresh parse pass, so
2017
+ * multiple plugins can iterate independently without sharing state.
2018
+ */
2019
+ schemas: AsyncIterable<SchemaNode>;
2020
+ /**
2021
+ * Lazily parsed operation nodes. Each `for await` creates a fresh parse pass, so
2022
+ * multiple plugins can iterate independently without sharing state.
2023
+ */
2024
+ operations: AsyncIterable<OperationNode>;
2025
+ /**
2026
+ * Document metadata available immediately, before the first yielded node.
1884
2027
  */
1885
2028
  meta?: InputMeta;
1886
2029
  };
@@ -1905,7 +2048,198 @@ type InputNode = BaseNode & {
1905
2048
  * }
1906
2049
  * ```
1907
2050
  */
1908
- type Node = InputNode | OutputNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode | FunctionParamNode | FileNode | ImportNode | ExportNode | SourceNode | ConstNode | TypeNode | ParamsTypeNode | FunctionNode | ArrowFunctionNode;
2051
+ type Node = InputNode | OutputNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode | RequestBodyNode | ContentNode | FunctionParamNode | FileNode | ImportNode | ExportNode | SourceNode | ConstNode | TypeNode | ParamsTypeNode | FunctionNode | ArrowFunctionNode;
2052
+ //#endregion
2053
+ //#region src/dedupe.d.ts
2054
+ /**
2055
+ * A canonical destination for a deduplicated shape: the shared schema name and
2056
+ * the synthetic `$ref` path that points at it.
2057
+ */
2058
+ type DedupeCanonical = {
2059
+ /**
2060
+ * Canonical schema name every duplicate occurrence refers to.
2061
+ */
2062
+ name: string;
2063
+ /**
2064
+ * `$ref` path stored on the generated `ref` nodes (for example `#/components/schemas/Status`).
2065
+ */
2066
+ ref: string;
2067
+ };
2068
+ /**
2069
+ * The result of {@link buildDedupePlan}: a lookup from structural signature to its
2070
+ * canonical target, plus the freshly hoisted definitions that must be added to
2071
+ * the schema list.
2072
+ */
2073
+ type DedupePlan = {
2074
+ /**
2075
+ * Maps a structural signature to the canonical schema that represents it.
2076
+ */
2077
+ canonicalBySignature: Map<string, DedupeCanonical>;
2078
+ /**
2079
+ * New top-level schema definitions created for inline shapes that had no existing
2080
+ * named component. Nested duplicates inside each definition are already collapsed.
2081
+ */
2082
+ hoisted: Array<SchemaNode>;
2083
+ };
2084
+ /**
2085
+ * Options that inject the naming and candidate policy into {@link buildDedupePlan}.
2086
+ * The mechanics (grouping, counting, rewriting) live here; the policy lives in the caller.
2087
+ */
2088
+ type BuildDedupePlanOptions = {
2089
+ /**
2090
+ * Returns `true` when a node should be deduplicated. This is the only gate, so it must
2091
+ * reject both ineligible kinds (return `false` for anything other than, say, enums and
2092
+ * objects) and unsafe shapes (e.g. nodes that reference a circular schema).
2093
+ */
2094
+ isCandidate: (node: SchemaNode) => boolean;
2095
+ /**
2096
+ * Produces the canonical name for an inline shape with no existing named component.
2097
+ * Return `null` to leave the shape inline (for example when no contextual name exists).
2098
+ */
2099
+ nameFor: (node: SchemaNode, signature: string) => string | null;
2100
+ /**
2101
+ * Builds the `$ref` path for a canonical name.
2102
+ */
2103
+ refFor: (name: string) => string;
2104
+ /**
2105
+ * Minimum number of occurrences before a shape is deduplicated.
2106
+ *
2107
+ * @default 2
2108
+ */
2109
+ minOccurrences?: number;
2110
+ };
2111
+ /**
2112
+ * Rewrites a node, replacing every candidate sub-schema whose signature has a canonical
2113
+ * target with a `ref` to that target. Replacing a node with a `ref` prunes its subtree,
2114
+ * so nested duplicates inside a replaced shape are not visited again.
2115
+ *
2116
+ * Pass `skipRootMatch` when rewriting a canonical definition so its own root is not
2117
+ * turned into a reference to itself; nested duplicates are still collapsed.
2118
+ *
2119
+ * @example
2120
+ * ```ts
2121
+ * const next = applyDedupe(operationNode, plan.canonicalBySignature)
2122
+ * ```
2123
+ */
2124
+ declare function applyDedupe(node: SchemaNode, canonicalBySignature: ReadonlyMap<string, DedupeCanonical>, skipRootMatch?: boolean): SchemaNode;
2125
+ declare function applyDedupe(node: OperationNode, canonicalBySignature: ReadonlyMap<string, DedupeCanonical>, skipRootMatch?: boolean): OperationNode;
2126
+ /**
2127
+ * Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
2128
+ *
2129
+ * A shape that occurs at least `minOccurrences` times is deduplicated: if any occurrence
2130
+ * is a named top-level schema, that name becomes the canonical (so other top-level duplicates
2131
+ * and inline copies turn into references to it); otherwise a new definition is hoisted using
2132
+ * `nameFor`. The plan is then applied per node with {@link applyDedupe}.
2133
+ *
2134
+ * @example
2135
+ * ```ts
2136
+ * const plan = buildDedupePlan([...schemaNodes, ...operationNodes], {
2137
+ * isCandidate: (node) => node.type === 'enum' || node.type === 'object',
2138
+ * nameFor: (node) => node.name ?? null,
2139
+ * refFor: (name) => `#/components/schemas/${name}`,
2140
+ * })
2141
+ * ```
2142
+ */
2143
+ declare function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupePlanOptions): DedupePlan;
2144
+ //#endregion
2145
+ //#region src/dialect.d.ts
2146
+ /**
2147
+ * The spec-specific decisions a schema parser makes while converting a source
2148
+ * document's schemas into Kubb AST nodes.
2149
+ *
2150
+ * Everything else in an adapter's schema pipeline is generic JSON Schema shared
2151
+ * across specs; the dialect is the one seam where a spec differs — the
2152
+ * "dialect layer" analogue of a database driver targeting Postgres vs MySQL.
2153
+ * Pair it with {@link dispatch}: the rule table decides *which* converter runs,
2154
+ * the dialect answers the spec-specific questions inside them.
2155
+ *
2156
+ * The guard methods (`isReference`, `isDiscriminator`) are type predicates so
2157
+ * converters narrow the schema after a check; the type parameters carry those
2158
+ * narrowed types through.
2159
+ *
2160
+ * Scope: this is the seam for the **JSON Schema family** — OpenAPI, AsyncAPI, and
2161
+ * plain JSON Schema all share `$ref`, `allOf`/`oneOf`, `enum`, and `format`, and
2162
+ * differ only in these few decisions. A spec built on a different type system
2163
+ * (e.g. GraphQL, with non-null wrappers, interfaces, and named-type references
2164
+ * instead of `$ref`) does not implement a `SchemaDialect`; it reuses the universal
2165
+ * layer directly — the `Adapter` port, the AST factories, and {@link dispatch}
2166
+ * with its own rule table — to emit the same nodes.
2167
+ *
2168
+ * @typeParam TSchema - The adapter's schema object type (e.g. an OpenAPI `SchemaObject`).
2169
+ * @typeParam TRef - The narrowed `$ref` pointer type `isReference` proves.
2170
+ * @typeParam TDiscriminated - The narrowed discriminated-schema type `isDiscriminator` proves.
2171
+ * @typeParam TDocument - The source document `resolveRef` resolves against.
2172
+ */
2173
+ type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {
2174
+ /** Identifies the dialect in logs and while debugging dispatch. */name: string; /** Whether a schema should be treated as nullable. */
2175
+ isNullable: (schema?: TSchema) => boolean; /** Whether a value is a `$ref` pointer object. */
2176
+ isReference: (value?: unknown) => value is TRef; /** Whether a schema carries a structured discriminator (polymorphism). */
2177
+ isDiscriminator: (value?: unknown) => value is TDiscriminated; /** Whether a schema represents binary data (converted to a `blob` node). */
2178
+ isBinary: (schema: TSchema) => boolean; /** Resolves a local `$ref` pointer against the document, or nullish when it cannot. */
2179
+ resolveRef: <TResolved>(document: TDocument, ref: string) => TResolved | null | undefined;
2180
+ };
2181
+ /**
2182
+ * Identity helper that types a {@link SchemaDialect} for an adapter. Like
2183
+ * `defineParser`, it adds no runtime behavior — it pins the dialect's type for
2184
+ * inference and gives adapter authors a discoverable anchor.
2185
+ *
2186
+ * @example
2187
+ * ```ts
2188
+ * export const oasDialect = defineSchemaDialect({
2189
+ * name: 'oas',
2190
+ * isNullable,
2191
+ * isReference,
2192
+ * isDiscriminator,
2193
+ * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',
2194
+ * resolveRef,
2195
+ * })
2196
+ * ```
2197
+ */
2198
+ declare function defineSchemaDialect<TSchema, TRef, TDiscriminated, TDocument>(dialect: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>): SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>;
2199
+ //#endregion
2200
+ //#region src/dispatch.d.ts
2201
+ /**
2202
+ * One entry in an ordered dispatch table: a predicate paired with a converter.
2203
+ *
2204
+ * @typeParam TContext - Per-input context handed to every rule. A spec adapter typically
2205
+ * pre-computes this once per node (the source spec node plus derived fields like a
2206
+ * normalized type or resolved options) so individual rules stay cheap predicates.
2207
+ * @typeParam TNode - The node a rule produces, e.g. a Kubb AST `SchemaNode`.
2208
+ */
2209
+ type DispatchRule<TContext, TNode> = {
2210
+ /** Identifies the rule when reading the table or debugging which branch ran. */name: string; /** Returns `true` when this rule is responsible for the given context. */
2211
+ match: (context: TContext) => boolean;
2212
+ /**
2213
+ * Produces a node for the context, or `null` to fall through to the next rule.
2214
+ *
2215
+ * Returning `null` lets a broad `match` defer: e.g. "has a `format`" matches many schemas,
2216
+ * but only some formats are convertible — the rest fall through to plain `type` handling.
2217
+ */
2218
+ convert: (context: TContext) => TNode | null;
2219
+ };
2220
+ /**
2221
+ * Walks an ordered list of {@link DispatchRule}s and returns the first node produced.
2222
+ *
2223
+ * This is the shared backbone for spec adapters (OpenAPI today, AsyncAPI and others later).
2224
+ * The contract an adapter follows is intentionally minimal:
2225
+ *
2226
+ * context → [rule.match → rule.convert] → node
2227
+ *
2228
+ * An adapter derives a context from a source spec node, then declares an ordered table of
2229
+ * rules mapping spec shapes onto Kubb AST nodes. To add support for a new spec, write a new
2230
+ * context type and a new rules table — the traversal here is reused unchanged.
2231
+ *
2232
+ * Order is significant: earlier rules win, so list higher-precedence or more specific shapes
2233
+ * first (e.g. composition keywords before plain `type`). A rule whose `match` returns `true`
2234
+ * may still `convert` to `null` to defer to later rules. When no rule produces a node this
2235
+ * returns `null`, leaving the caller to apply its own fallback.
2236
+ *
2237
+ * @example
2238
+ * ```ts
2239
+ * const node = dispatch(schemaRules, schemaContext) ?? createSchema({ type: fallbackType })
2240
+ * ```
2241
+ */
2242
+ declare function dispatch<TContext, TNode>(rules: ReadonlyArray<DispatchRule<TContext, TNode>>, context: TContext): TNode | null;
1909
2243
  //#endregion
1910
2244
  //#region src/infer.d.ts
1911
2245
  /**
@@ -1913,15 +2247,25 @@ type Node = InputNode | OutputNode | OperationNode | SchemaNode | PropertyNode |
1913
2247
  */
1914
2248
  type ParserOptions = {
1915
2249
  /**
1916
- * How `format: 'date-time'` schemas are represented. `false` falls through to a plain string.
2250
+ * How `format: 'date-time'` schemas are represented downstream.
2251
+ * - `false` falls through to a plain `string` (no validation).
2252
+ * - `'string'` emits a datetime string node.
2253
+ * - `'stringOffset'` emits a datetime node with timezone offset.
2254
+ * - `'stringLocal'` emits a local datetime node.
2255
+ * - `'date'` emits a `date` node (JavaScript `Date` object).
1917
2256
  */
1918
2257
  dateType: false | 'string' | 'stringOffset' | 'stringLocal' | 'date';
1919
2258
  /**
1920
- * Whether `type: 'integer'` and `format: 'int64'` produce `number` or `bigint` nodes.
2259
+ * How `type: 'integer'` (and `format: 'int64'`) maps to TypeScript.
2260
+ * - `'number'` fits most JSON APIs; loses precision above `Number.MAX_SAFE_INTEGER`.
2261
+ * - `'bigint'` is exact for 64-bit IDs, but does not round-trip through JSON.
2262
+ *
2263
+ * @default 'number'
1921
2264
  */
1922
2265
  integerType?: 'number' | 'bigint';
1923
2266
  /**
1924
- * AST type used when no schema type can be inferred.
2267
+ * AST type used when a schema's type cannot be inferred from the spec
2268
+ * (`additionalProperties: true`, missing `type`, ...).
1925
2269
  */
1926
2270
  unknownType: 'any' | 'unknown' | 'void';
1927
2271
  /**
@@ -1929,7 +2273,8 @@ type ParserOptions = {
1929
2273
  */
1930
2274
  emptySchemaType: 'any' | 'unknown' | 'void';
1931
2275
  /**
1932
- * Suffix appended to derived enum names when building property schema names.
2276
+ * Suffix appended to derived enum names when Kubb has to invent one
2277
+ * (typically for inline enums on object properties).
1933
2278
  */
1934
2279
  enumSuffix: 'enum' | (string & {});
1935
2280
  };
@@ -1957,7 +2302,7 @@ type SchemaNodeMap<TDateType extends ParserOptions['dateType'] = 'string'> = [[{
1957
2302
  allOf: ReadonlyArray<unknown>;
1958
2303
  properties: object;
1959
2304
  }, IntersectionSchemaNode], [{
1960
- allOf: readonly [unknown, unknown, ...unknown[]];
2305
+ allOf: readonly [unknown, unknown, ...Array<unknown>];
1961
2306
  }, IntersectionSchemaNode], [{
1962
2307
  allOf: ReadonlyArray<unknown>;
1963
2308
  }, SchemaNode], [{
@@ -2050,10 +2395,13 @@ type InferSchema<TSchema extends object, TDateType extends ParserOptions['dateTy
2050
2395
  //#endregion
2051
2396
  //#region src/factory.d.ts
2052
2397
  /**
2053
- * Syncs property/parameter schema optionality flags from `required` and `schema.nullable`.
2398
+ * Updates a schema's `optional` and `nullish` flags from a parent's `required`
2399
+ * value and the schema's own `nullable`. Mirrors how OpenAPI parameters and
2400
+ * object properties combine "required" and "nullable" into a single AST.
2054
2401
  *
2055
- * - `optional` is set for non-required, non-nullable schemas.
2056
- * - `nullish` is set for non-required, nullable schemas.
2402
+ * - Non-required + non-nullable → `optional: true`.
2403
+ * - Non-required + nullable `nullish: true`.
2404
+ * - Required → both flags cleared.
2057
2405
  */
2058
2406
  declare function syncOptionality(schema: SchemaNode, required: boolean): SchemaNode;
2059
2407
  /**
@@ -2068,6 +2416,23 @@ declare function syncOptionality(schema: SchemaNode, required: boolean): SchemaN
2068
2416
  * ```
2069
2417
  */
2070
2418
  type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
2419
+ /**
2420
+ * Identity-preserving node update: returns `node` unchanged when every field in
2421
+ * `changes` already equals (by reference) the current value, otherwise a new node
2422
+ * with the changes applied.
2423
+ *
2424
+ * Mirrors the TypeScript compiler's `factory.updateX` contract — pair it with the
2425
+ * structural sharing in {@link transform} so a no-op rewrite doesn't allocate and
2426
+ * downstream passes can detect "nothing changed" by identity. Comparison is
2427
+ * shallow: a structurally-equal but newly-allocated array/object counts as a change.
2428
+ *
2429
+ * @example
2430
+ * ```ts
2431
+ * update(node, { name: node.name }) // -> same `node` reference
2432
+ * update(node, { name: 'renamed' }) // -> new node, `name` replaced
2433
+ * ```
2434
+ */
2435
+ declare function update<T extends Node>(node: T, changes: Partial<T>): T;
2071
2436
  type CreateSchemaObjectInput = Omit<ObjectSchemaNode, 'kind' | 'properties' | 'primitive'> & {
2072
2437
  properties?: Array<PropertyNode>;
2073
2438
  primitive?: 'object';
@@ -2092,6 +2457,15 @@ type CreateSchemaOutput<T extends CreateSchemaInput> = InferSchemaNode<T> & {
2092
2457
  * ```
2093
2458
  */
2094
2459
  declare function createInput(overrides?: Partial<Omit<InputNode, 'kind'>>): InputNode;
2460
+ /**
2461
+ * Creates an `InputStreamNode` from pre-built `AsyncIterable` sources.
2462
+ *
2463
+ * @example
2464
+ * ```ts
2465
+ * const node = createStreamInput(schemasIterable, operationsIterable, { title: 'My API' })
2466
+ * ```
2467
+ */
2468
+ declare function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta): InputStreamNode;
2095
2469
  /**
2096
2470
  * Creates an `OutputNode` with a stable default for `files`.
2097
2471
  *
@@ -2130,7 +2504,30 @@ declare function createOutput(overrides?: Partial<Omit<OutputNode, 'kind'>>): Ou
2130
2504
  * })
2131
2505
  * ```
2132
2506
  */
2133
- declare function createOperation(props: Pick<OperationNode, 'operationId' | 'method' | 'path'> & Partial<Omit<OperationNode, 'kind' | 'operationId' | 'method' | 'path'>>): OperationNode;
2507
+ /**
2508
+ * Loosely-typed content entry accepted by the builders, normalized into a {@link ContentNode}.
2509
+ */
2510
+ type UserContent = Omit<ContentNode, 'kind'>;
2511
+ /**
2512
+ * Creates a `ContentNode` for a single request-body or response content type.
2513
+ */
2514
+ declare function createContent(props: UserContent): ContentNode;
2515
+ /**
2516
+ * Loosely-typed request body accepted by `createOperation`, normalized into a {@link RequestBodyNode}.
2517
+ */
2518
+ type UserRequestBody = Omit<RequestBodyNode, 'kind' | 'content'> & {
2519
+ content?: Array<UserContent>;
2520
+ };
2521
+ /**
2522
+ * Creates a `RequestBodyNode`, normalizing each content entry into a `ContentNode`.
2523
+ */
2524
+ declare function createRequestBody(props: UserRequestBody): RequestBodyNode;
2525
+ declare function createOperation(props: Pick<HttpOperationNode, 'operationId' | 'method' | 'path'> & Partial<Omit<HttpOperationNode, 'kind' | 'operationId' | 'method' | 'path' | 'requestBody'>> & {
2526
+ requestBody?: UserRequestBody;
2527
+ }): HttpOperationNode;
2528
+ declare function createOperation(props: Pick<GenericOperationNode, 'operationId'> & Partial<Omit<GenericOperationNode, 'kind' | 'operationId' | 'requestBody'>> & {
2529
+ requestBody?: UserRequestBody;
2530
+ }): GenericOperationNode;
2134
2531
  /**
2135
2532
  * Creates a `SchemaNode`, narrowed to the variant of `props.type`.
2136
2533
  * For object schemas, `properties` defaults to an empty array.
@@ -2222,16 +2619,24 @@ declare function createParameter(props: Pick<ParameterNode, 'name' | 'in' | 'sch
2222
2619
  /**
2223
2620
  * Creates a `ResponseNode`.
2224
2621
  *
2622
+ * Response body schemas live inside `content`. For convenience a single legacy `schema`
2623
+ * (with optional `mediaType`/`keysToOmit`) is normalized into one `content` entry, so the same
2624
+ * schema is never stored both at the node root and inside `content`.
2625
+ *
2225
2626
  * @example
2226
2627
  * ```ts
2227
2628
  * const response = createResponse({
2228
2629
  * statusCode: '200',
2229
- * description: 'Success',
2230
- * schema: createSchema({ type: 'object', properties: [] }),
2630
+ * content: [{ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) }],
2231
2631
  * })
2232
2632
  * ```
2233
2633
  */
2234
- declare function createResponse(props: Pick<ResponseNode, 'statusCode' | 'schema'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'schema'>>): ResponseNode;
2634
+ declare function createResponse(props: Pick<ResponseNode, 'statusCode'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'content'>> & {
2635
+ content?: Array<UserContent>;
2636
+ schema?: SchemaNode;
2637
+ mediaType?: string | null;
2638
+ keysToOmit?: Array<string> | null;
2639
+ }): ResponseNode;
2235
2640
  /**
2236
2641
  * Creates a `FunctionParameterNode`.
2237
2642
  *
@@ -2583,10 +2988,10 @@ declare function createJsx(value: string): JsxNode;
2583
2988
  * @example
2584
2989
  * ```ts
2585
2990
  * const schema = createSchema({ type: 'string' })
2586
- * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | undefined
2991
+ * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | null
2587
2992
  * ```
2588
2993
  */
2589
- declare function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | undefined;
2994
+ declare function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | null;
2590
2995
  /**
2591
2996
  * Returns `true` when the input is an `InputNode`.
2592
2997
  *
@@ -2620,6 +3025,17 @@ declare const isOutputNode: (node: unknown) => node is OutputNode;
2620
3025
  * ```
2621
3026
  */
2622
3027
  declare const isOperationNode: (node: unknown) => node is OperationNode;
3028
+ /**
3029
+ * Narrows an `OperationNode` to an `HttpOperationNode`, guaranteeing `method` and `path`.
3030
+ *
3031
+ * @example
3032
+ * ```ts
3033
+ * if (isHttpOperationNode(node)) {
3034
+ * console.log(node.method, node.path)
3035
+ * }
3036
+ * ```
3037
+ */
3038
+ declare function isHttpOperationNode(node: OperationNode): node is HttpOperationNode;
2623
3039
  /**
2624
3040
  * Returns `true` when the input is a `SchemaNode`.
2625
3041
  *
@@ -2651,7 +3067,7 @@ type PrinterHandlerContext<TOutput, TOptions extends object> = {
2651
3067
  * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.
2652
3068
  * Use `this.transform` inside `nodes` handlers and inside the `print` override.
2653
3069
  */
2654
- transform: (node: SchemaNode) => TOutput | null | undefined;
3070
+ transform: (node: SchemaNode) => TOutput | null;
2655
3071
  /**
2656
3072
  * Options for this printer instance.
2657
3073
  */
@@ -2669,7 +3085,7 @@ type PrinterHandlerContext<TOutput, TOptions extends object> = {
2669
3085
  * }
2670
3086
  * ```
2671
3087
  */
2672
- type PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (this: PrinterHandlerContext<TOutput, TOptions>, node: SchemaNodeByType[T]) => TOutput | null | undefined;
3088
+ type PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (this: PrinterHandlerContext<TOutput, TOptions>, node: SchemaNodeByType[T]) => TOutput | null;
2673
3089
  /**
2674
3090
  * Partial map of per-node-type handler overrides for a printer.
2675
3091
  *
@@ -2732,13 +3148,13 @@ type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {
2732
3148
  * Always dispatches through the `nodes` map; never calls the `print` override.
2733
3149
  * Use this when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.
2734
3150
  */
2735
- transform: (node: SchemaNode) => T['output'] | null | undefined;
3151
+ transform: (node: SchemaNode) => T['output'] | null;
2736
3152
  /**
2737
3153
  * Public printer. If the builder provides a root-level `print`, this calls that
2738
3154
  * higher-level function (which may produce full declarations).
2739
3155
  * Otherwise, falls back to the node-level dispatcher.
2740
3156
  */
2741
- print: (node: SchemaNode) => T['printOutput'] | null | undefined;
3157
+ print: (node: SchemaNode) => T['printOutput'] | null;
2742
3158
  };
2743
3159
  /**
2744
3160
  * Builder function passed to `definePrinter`.
@@ -2769,22 +3185,27 @@ type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) =
2769
3185
  print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null;
2770
3186
  };
2771
3187
  /**
2772
- * Creates a schema printer factory.
2773
- *
2774
- * This function wraps a builder and makes options optional at call sites.
3188
+ * Defines a schema printer: a function that takes a `SchemaNode` and emits
3189
+ * code in your target language. Each plugin that produces code from schemas
3190
+ * (TypeScript types, Zod schemas, Faker factories) ships a printer built
3191
+ * with this helper.
2775
3192
  *
2776
3193
  * The builder receives resolved options and returns:
2777
- * - `name` — a unique identifier for the printer
2778
- * - `options` — options stored on the returned printer instance
2779
- * - `nodes` — a map of `SchemaType` → handler functions that convert a `SchemaNode` to `TOutput`
2780
- * - `print` _(optional)_ — top-level override exposed as `printer.print`
2781
- * - Inside this function, use `this.transform(node)` to dispatch to the `nodes` map
2782
- * - This keeps recursion safe and avoids self-calls
2783
3194
  *
2784
- * When no `print` override is provided, `printer.print` falls back to `printer.transform` (the node-level dispatcher).
3195
+ * - `name` unique identifier for the printer.
3196
+ * - `options` — stored on the returned printer instance.
3197
+ * - `nodes` — map of `SchemaType` → handler. Handlers return the rendered
3198
+ * output (a string, a TypeScript AST node, ...) for that schema type.
3199
+ * - `print` (optional) — top-level override exposed as `printer.print`.
3200
+ * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.
2785
3201
  *
2786
- * @example Basic usage Zod schema printer
3202
+ * Without a `print` override, `printer.print` falls back to `printer.transform`
3203
+ * (the node-level dispatcher).
3204
+ *
3205
+ * @example Tiny Zod printer
2787
3206
  * ```ts
3207
+ * import { definePrinter, type PrinterFactoryOptions } from '@kubb/ast'
3208
+ *
2788
3209
  * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>
2789
3210
  *
2790
3211
  * export const zodPrinter = definePrinter<PrinterZod>((options) => ({
@@ -2793,7 +3214,9 @@ type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) =
2793
3214
  * nodes: {
2794
3215
  * string: () => 'z.string()',
2795
3216
  * object(node) {
2796
- * const props = node.properties.map(p => `${p.name}: ${this.transform(p.schema)}`).join(', ')
3217
+ * const props = node.properties
3218
+ * .map((p) => `${p.name}: ${this.transform(p.schema)}`)
3219
+ * .join(', ')
2797
3220
  * return `z.object({ ${props} })`
2798
3221
  * },
2799
3222
  * },
@@ -2811,22 +3234,22 @@ declare function definePrinter<T extends PrinterFactoryOptions = PrinterFactoryO
2811
3234
  * )
2812
3235
  * ```
2813
3236
  */
2814
- declare function createPrinterFactory<TNode, TKey extends string, TNodeByKey extends Partial<Record<TKey, TNode>>>(getKey: (node: TNode) => TKey | undefined): <T extends PrinterFactoryOptions>(build: (options: T["options"]) => {
3237
+ declare function createPrinterFactory<TNode, TKey extends string, TNodeByKey extends Partial<Record<TKey, TNode>>>(getKey: (node: TNode) => TKey | null): <T extends PrinterFactoryOptions>(build: (options: T["options"]) => {
2815
3238
  name: T["name"];
2816
3239
  options: T["options"];
2817
3240
  nodes: Partial<{ [K in TKey]: (this: {
2818
- transform: (node: TNode) => T["output"] | null | undefined;
3241
+ transform: (node: TNode) => T["output"] | null;
2819
3242
  options: T["options"];
2820
- }, node: TNodeByKey[K]) => T["output"] | null | undefined }>;
3243
+ }, node: TNodeByKey[K]) => T["output"] | null }>;
2821
3244
  print?: (this: {
2822
- transform: (node: TNode) => T["output"] | null | undefined;
3245
+ transform: (node: TNode) => T["output"] | null;
2823
3246
  options: T["options"];
2824
- }, node: TNode) => T["printOutput"] | null | undefined;
3247
+ }, node: TNode) => T["printOutput"] | null;
2825
3248
  }) => (options?: T["options"]) => {
2826
3249
  name: T["name"];
2827
3250
  options: T["options"];
2828
- transform: (node: TNode) => T["output"] | null | undefined;
2829
- print: (node: TNode) => T["printOutput"] | null | undefined;
3251
+ transform: (node: TNode) => T["output"] | null;
3252
+ print: (node: TNode) => T["printOutput"] | null;
2830
3253
  };
2831
3254
  //#endregion
2832
3255
  //#region src/refs.d.ts
@@ -2860,9 +3283,36 @@ declare function collectImports<TImport>({
2860
3283
  }: {
2861
3284
  node: SchemaNode;
2862
3285
  nameMapping: Map<string, string>;
2863
- resolve: (schemaName: string) => TImport | undefined;
3286
+ resolve: (schemaName: string) => TImport | null;
2864
3287
  }): Array<TImport>;
2865
3288
  //#endregion
3289
+ //#region src/signature.d.ts
3290
+ /**
3291
+ * Computes a deterministic, shape-only signature (a fixed-length content hash) for a schema node.
3292
+ *
3293
+ * Two schemas share a signature when they are structurally identical, ignoring
3294
+ * documentation (`name`, `title`, `description`, `example`, `default`, `deprecated`)
3295
+ * and usage-slot flags (`optional`, `nullish`, `readOnly`, `writeOnly`). `nullable`
3296
+ * is kept because it changes the produced type. `ref` nodes compare by target name,
3297
+ * which also keeps the algorithm terminating on circular shapes.
3298
+ *
3299
+ * @example Two enums with different descriptions share a signature
3300
+ * ```ts
3301
+ * schemaSignature(createSchema({ type: 'enum', primitive: 'string', enumValues: ['a', 'b'], description: 'x' })) ===
3302
+ * schemaSignature(createSchema({ type: 'enum', primitive: 'string', enumValues: ['a', 'b'] }))
3303
+ * ```
3304
+ */
3305
+ declare function schemaSignature(node: SchemaNode): string;
3306
+ /**
3307
+ * Returns `true` when two schema nodes are structurally identical under shape-only equality.
3308
+ *
3309
+ * @example
3310
+ * ```ts
3311
+ * isSchemaEqual(a, b) // a and b produce the same TypeScript type
3312
+ * ```
3313
+ */
3314
+ declare function isSchemaEqual(a: SchemaNode, b: SchemaNode): boolean;
3315
+ //#endregion
2866
3316
  //#region src/transformers.d.ts
2867
3317
  /**
2868
3318
  * Replaces a discriminator property's schema with a string enum of allowed values.
@@ -2901,6 +3351,7 @@ declare function setDiscriminatorEnum({
2901
3351
  * ])
2902
3352
  * ```
2903
3353
  */
3354
+ declare function mergeAdjacentObjectsLazy(members: Iterable<SchemaNode>): Generator<SchemaNode, void, undefined>;
2904
3355
  declare function mergeAdjacentObjects(members: Array<SchemaNode>): Array<SchemaNode>;
2905
3356
  /**
2906
3357
  * Removes enum members that are covered by broader scalar primitives in the same union.
@@ -2923,7 +3374,7 @@ declare function setEnumName(propNode: SchemaNode, parentName: string | null | u
2923
3374
  *
2924
3375
  * `ParentOf` uses this map to find parent types.
2925
3376
  */
2926
- type ParentNodeMap = [[InputNode, undefined], [OutputNode, undefined], [OperationNode, InputNode], [SchemaNode, InputNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode], [PropertyNode, SchemaNode], [ParameterNode, OperationNode], [ResponseNode, OperationNode]];
3377
+ type ParentNodeMap = [[InputNode, undefined], [OutputNode, undefined], [OperationNode, InputNode], [RequestBodyNode, OperationNode], [ContentNode, RequestBodyNode | ResponseNode], [SchemaNode, InputNode | ContentNode | SchemaNode | PropertyNode | ParameterNode], [PropertyNode, SchemaNode], [ParameterNode, OperationNode], [ResponseNode, OperationNode]];
2927
3378
  /**
2928
3379
  * Resolves the parent node type for a given AST node type.
2929
3380
  *
@@ -2970,25 +3421,40 @@ type VisitorContext<T extends Node = Node> = {
2970
3421
  parent?: ParentOf<T>;
2971
3422
  };
2972
3423
  /**
2973
- * Synchronous visitor used by `transform`.
3424
+ * Synchronous visitor consumed by `transform`. Each optional callback runs
3425
+ * for the matching node type. Return a new node to replace it, or `undefined`
3426
+ * to leave it untouched.
2974
3427
  *
2975
- * @example
3428
+ * Plugins typically expose `transformer` so users can supply a `Visitor` that
3429
+ * rewrites operation IDs, drops descriptions, or otherwise tweaks the AST
3430
+ * before printing.
3431
+ *
3432
+ * @example Prefix every operationId
2976
3433
  * ```ts
2977
3434
  * const visitor: Visitor = {
2978
3435
  * operation(node) {
2979
- * return { ...node, operationId: `x_${node.operationId}` }
3436
+ * return { ...node, operationId: `api_${node.operationId}` }
3437
+ * },
3438
+ * }
3439
+ * ```
3440
+ *
3441
+ * @example Strip schema descriptions
3442
+ * ```ts
3443
+ * const visitor: Visitor = {
3444
+ * schema(node) {
3445
+ * return { ...node, description: undefined }
2980
3446
  * },
2981
3447
  * }
2982
3448
  * ```
2983
3449
  */
2984
3450
  type Visitor = {
2985
- input?(node: InputNode, context: VisitorContext<InputNode>): void | InputNode;
2986
- output?(node: OutputNode, context: VisitorContext<OutputNode>): void | OutputNode;
2987
- operation?(node: OperationNode, context: VisitorContext<OperationNode>): void | OperationNode;
2988
- schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): void | SchemaNode;
2989
- property?(node: PropertyNode, context: VisitorContext<PropertyNode>): void | PropertyNode;
2990
- parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): void | ParameterNode;
2991
- response?(node: ResponseNode, context: VisitorContext<ResponseNode>): void | ResponseNode;
3451
+ input?(node: InputNode, context: VisitorContext<InputNode>): undefined | null | InputNode;
3452
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): undefined | null | OutputNode;
3453
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): undefined | null | OperationNode;
3454
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): undefined | null | SchemaNode;
3455
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): undefined | null | PropertyNode;
3456
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): undefined | null | ParameterNode;
3457
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): undefined | null | ResponseNode;
2992
3458
  };
2993
3459
  /**
2994
3460
  * Utility type for values that can be returned directly or asynchronously.
@@ -3007,13 +3473,13 @@ type MaybePromise<T> = T | Promise<T>;
3007
3473
  * ```
3008
3474
  */
3009
3475
  type AsyncVisitor = {
3010
- input?(node: InputNode, context: VisitorContext<InputNode>): MaybePromise<void | InputNode>;
3011
- output?(node: OutputNode, context: VisitorContext<OutputNode>): MaybePromise<void | OutputNode>;
3012
- operation?(node: OperationNode, context: VisitorContext<OperationNode>): MaybePromise<void | OperationNode>;
3013
- schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): MaybePromise<void | SchemaNode>;
3014
- property?(node: PropertyNode, context: VisitorContext<PropertyNode>): MaybePromise<void | PropertyNode>;
3015
- parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): MaybePromise<void | ParameterNode>;
3016
- response?(node: ResponseNode, context: VisitorContext<ResponseNode>): MaybePromise<void | ResponseNode>;
3476
+ input?(node: InputNode, context: VisitorContext<InputNode>): MaybePromise<undefined | null | InputNode>;
3477
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): MaybePromise<undefined | null | OutputNode>;
3478
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): MaybePromise<undefined | null | OperationNode>;
3479
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): MaybePromise<undefined | null | SchemaNode>;
3480
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): MaybePromise<undefined | null | PropertyNode>;
3481
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): MaybePromise<undefined | null | ParameterNode>;
3482
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): MaybePromise<undefined | null | ResponseNode>;
3017
3483
  };
3018
3484
  /**
3019
3485
  * Visitor used by `collect`.
@@ -3028,13 +3494,13 @@ type AsyncVisitor = {
3028
3494
  * ```
3029
3495
  */
3030
3496
  type CollectVisitor<T> = {
3031
- input?(node: InputNode, context: VisitorContext<InputNode>): T | undefined;
3032
- output?(node: OutputNode, context: VisitorContext<OutputNode>): T | undefined;
3033
- operation?(node: OperationNode, context: VisitorContext<OperationNode>): T | undefined;
3034
- schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): T | undefined;
3035
- property?(node: PropertyNode, context: VisitorContext<PropertyNode>): T | undefined;
3036
- parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): T | undefined;
3037
- response?(node: ResponseNode, context: VisitorContext<ResponseNode>): T | undefined;
3497
+ input?(node: InputNode, context: VisitorContext<InputNode>): T | null | undefined;
3498
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): T | null | undefined;
3499
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): T | null | undefined;
3500
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): T | null | undefined;
3501
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): T | null | undefined;
3502
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): T | null | undefined;
3503
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): T | null | undefined;
3038
3504
  };
3039
3505
  /**
3040
3506
  * Options for `transform`.
@@ -3101,11 +3567,14 @@ type CollectOptions<T> = CollectVisitor<T> & {
3101
3567
  parent?: Node;
3102
3568
  };
3103
3569
  /**
3104
- * Depth-first traversal for side effects. Visitor return values are ignored.
3105
- * Sibling nodes at each level are visited concurrently up to `options.concurrency`
3106
- * (default: `WALK_CONCURRENCY`).
3570
+ * Async depth-first traversal for side effects. Visitor return values are
3571
+ * ignored. Use `transform` when you want to rewrite nodes.
3107
3572
  *
3108
- * @example
3573
+ * Sibling nodes at each depth run concurrently up to `options.concurrency`
3574
+ * (defaults to `WALK_CONCURRENCY`). Higher values overlap I/O-bound visitor
3575
+ * work; lower values reduce memory pressure.
3576
+ *
3577
+ * @example Log every operation
3109
3578
  * ```ts
3110
3579
  * await walk(root, {
3111
3580
  * operation(node) {
@@ -3114,20 +3583,20 @@ type CollectOptions<T> = CollectVisitor<T> & {
3114
3583
  * })
3115
3584
  * ```
3116
3585
  *
3117
- * @example
3586
+ * @example Only visit the root node
3118
3587
  * ```ts
3119
- * // Visit only the current node
3120
- * await walk(root, { depth: 'shallow', root: () => {} })
3588
+ * await walk(root, { depth: 'shallow', input: () => {} })
3121
3589
  * ```
3122
3590
  */
3123
3591
  declare function walk(node: Node, options: WalkOptions): Promise<void>;
3124
3592
  /**
3125
- * Runs a depth-first immutable transform.
3593
+ * Synchronous depth-first transform. Each visitor callback gets a chance to
3594
+ * return a replacement node; `undefined` keeps the original.
3126
3595
  *
3127
- * If a visitor returns a node, it replaces the current node.
3128
- * If it returns `undefined`, the current node stays the same.
3596
+ * The transform is immutable. The original tree is not mutated; a new tree
3597
+ * is returned. Use `depth: 'shallow'` to skip recursion into children.
3129
3598
  *
3130
- * @example
3599
+ * @example Prefix every operationId
3131
3600
  * ```ts
3132
3601
  * const next = transform(root, {
3133
3602
  * operation(node) {
@@ -3136,10 +3605,12 @@ declare function walk(node: Node, options: WalkOptions): Promise<void>;
3136
3605
  * })
3137
3606
  * ```
3138
3607
  *
3139
- * @example
3608
+ * @example Replace only the root node
3140
3609
  * ```ts
3141
- * // Shallow mode: only transform the input node
3142
- * const next = transform(root, { depth: 'shallow', root: (node) => node })
3610
+ * const next = transform(root, {
3611
+ * depth: 'shallow',
3612
+ * input: (node) => ({ ...node, meta: { ...node.meta, title: 'Rewritten' } }),
3613
+ * })
3143
3614
  * ```
3144
3615
  */
3145
3616
  declare function transform(node: InputNode, options: TransformOptions): InputNode;
@@ -3151,23 +3622,33 @@ declare function transform(node: ParameterNode, options: TransformOptions): Para
3151
3622
  declare function transform(node: ResponseNode, options: TransformOptions): ResponseNode;
3152
3623
  declare function transform(node: Node, options: TransformOptions): Node;
3153
3624
  /**
3154
- * Runs a depth-first synchronous collection pass.
3625
+ * Lazy depth-first collection pass. Yields every non-null value returned by
3626
+ * the visitor callbacks. Use `collect` for the eager array form.
3155
3627
  *
3156
- * Non-`undefined` values returned by visitor callbacks are appended to the result.
3157
- *
3158
- * @example
3628
+ * @example Collect every operationId
3159
3629
  * ```ts
3160
- * const ids = collect(root, {
3630
+ * const ids: string[] = []
3631
+ * for (const id of collectLazy<string>(root, {
3161
3632
  * operation(node) {
3162
3633
  * return node.operationId
3163
3634
  * },
3164
- * })
3635
+ * })) {
3636
+ * ids.push(id)
3637
+ * }
3165
3638
  * ```
3639
+ */
3640
+ declare function collectLazy<T>(node: Node, options: CollectOptions<T>): Generator<T, void, undefined>;
3641
+ /**
3642
+ * Eager depth-first collection pass. Returns an array of every non-null value
3643
+ * the visitor callbacks return.
3166
3644
  *
3167
- * @example
3645
+ * @example Collect every operationId
3168
3646
  * ```ts
3169
- * // Collect from only the current node
3170
- * const values = collect(root, { depth: 'shallow', root: () => 'root' })
3647
+ * const ids = collect<string>(root, {
3648
+ * operation(node) {
3649
+ * return node.operationId
3650
+ * },
3651
+ * })
3171
3652
  * ```
3172
3653
  */
3173
3654
  declare function collect<T>(node: Node, options: CollectOptions<T>): Array<T>;
@@ -3194,13 +3675,6 @@ declare function syncSchemaRef(node: SchemaNode): SchemaNode;
3194
3675
  * types, returns `true` only when `representation` is `'string'` rather than `'date'`.
3195
3676
  */
3196
3677
  declare function isStringType(node: SchemaNode): boolean;
3197
- /**
3198
- * Applies casing rules to parameter names and returns a new parameter array.
3199
- *
3200
- * Use this before passing parameters to schema builders so output property keys match
3201
- * the desired casing while preserving `OperationNode.parameters` for other consumers.
3202
- * The input array is not mutated. When `casing` is not set, the original array is returned unchanged.
3203
- */
3204
3678
  declare function caseParams(params: Array<ParameterNode>, casing: 'camelcase' | undefined): Array<ParameterNode>;
3205
3679
  /**
3206
3680
  * Creates a single-property object schema used as a discriminator literal.
@@ -3361,7 +3835,7 @@ declare function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): st
3361
3835
  /**
3362
3836
  * Resolves the schema name of a ref node, falling back through `ref` → `name` → nested `schema.name`.
3363
3837
  *
3364
- * Returns `undefined` for non-ref nodes or when no name can be resolved. Use this to get a schema's
3838
+ * Returns `null` for non-ref nodes or when no name can be resolved. Use this to get a schema's
3365
3839
  * identifier for type definitions or error messages.
3366
3840
  *
3367
3841
  * @example
@@ -3370,56 +3844,8 @@ declare function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): st
3370
3844
  * // => 'Pet'
3371
3845
  * ```
3372
3846
  */
3373
- declare function resolveRefName(node: SchemaNode | undefined): string | undefined;
3374
- /**
3375
- * Collects every named schema referenced (transitively) from a node via ref edges.
3376
- *
3377
- * Refs are followed by name only — the resolved `node.schema` is not traversed inline.
3378
- * Use this to determine schema dependencies, build reference graphs, or detect what schemas need to be emitted.
3379
- *
3380
- * @example Collect refs from a single schema
3381
- * ```ts
3382
- * const names = collectReferencedSchemaNames(petSchema)
3383
- * // → Set { 'Category', 'Tag' }
3384
- * ```
3385
- *
3386
- * @example Accumulate refs from multiple schemas into one set
3387
- * ```ts
3388
- * const out = new Set<string>()
3389
- * for (const schema of schemas) {
3390
- * collectReferencedSchemaNames(schema, out)
3391
- * }
3392
- * ```
3393
- */
3847
+ declare function resolveRefName(node: SchemaNode | undefined): string | null;
3394
3848
  declare function collectReferencedSchemaNames(node: SchemaNode | undefined, out?: Set<string>): Set<string>;
3395
- /**
3396
- * Collects the names of all top-level schemas transitively used by a set of operations.
3397
- *
3398
- * An operation uses a schema when any of its parameters, request body content, or responses
3399
- * reference it — directly or indirectly through other named schemas.
3400
- * The walk is iterative and safe against reference cycles.
3401
- *
3402
- * Use this together with `include` filters to determine which schemas from `components/schemas`
3403
- * are reachable from the allowed operations, so that schemas used only by excluded operations
3404
- * are not generated.
3405
- *
3406
- * @example Only generate schemas referenced by included operations
3407
- * ```ts
3408
- * const includedOps = inputNode.operations.filter(op => resolver.resolveOptions(op, { options, include }) !== null)
3409
- * const allowed = collectUsedSchemaNames(includedOps, inputNode.schemas)
3410
- *
3411
- * for (const schema of inputNode.schemas) {
3412
- * if (schema.name && !allowed.has(schema.name)) continue
3413
- * // … generate schema
3414
- * }
3415
- * ```
3416
- *
3417
- * @example Check whether a specific schema is needed
3418
- * ```ts
3419
- * const allowed = collectUsedSchemaNames(includedOps, inputNode.schemas)
3420
- * allowed.has('OrderStatus') // false when no included operation references OrderStatus
3421
- * ```
3422
- */
3423
3849
  declare function collectUsedSchemaNames(operations: ReadonlyArray<OperationNode>, schemas: ReadonlyArray<SchemaNode>): Set<string>;
3424
3850
  /**
3425
3851
  * Identifies all schemas that participate in circular dependency chains, including direct self-loops.
@@ -3447,5 +3873,5 @@ declare function containsCircularRef(node: SchemaNode | undefined, {
3447
3873
  excludeName?: string;
3448
3874
  }): boolean;
3449
3875
  //#endregion
3450
- export { type ArraySchemaNode, type ArrowFunctionNode, AsyncVisitor, type BaseNode, type BreakNode, type CodeNode, CollectOptions, CollectVisitor, type ComplexSchemaType, type ConstNode, type DateSchemaNode, type DatetimeSchemaNode, DistributiveOmit, type EnumSchemaNode, type EnumValueNode, type ExportNode, type FileNode, type FormatStringSchemaNode, type FunctionNode, type FunctionNodeType, type FunctionParamNode, type FunctionParameterNode, type FunctionParametersNode, type HttpMethod, type HttpStatusCode, type ImportNode, InferSchema, InferSchemaNode, type InputMeta, type InputNode, type IntersectionSchemaNode, type Ipv4SchemaNode, type Ipv6SchemaNode, type JSDocNode, type JsxNode, type MediaType, Node, type NodeKind, type NumberSchemaNode, type ObjectSchemaNode, type OperationNode, OperationParamsResolver, type OutputNode, type ParameterGroupNode, type ParameterLocation, type ParameterNode, type ParamsTypeNode, ParentOf, ParserOptions, type PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, type PropertyNode, RefMap, type RefSchemaNode, type ResponseNode, ScalarPrimitive, type ScalarSchemaNode, type ScalarSchemaType, type SchemaNode, type SchemaNodeByType, type SchemaType, type SourceNode, type SpecialSchemaType, type StatusCode, type StringSchemaNode, type TextNode, type TimeSchemaNode, TransformOptions, type TypeDeclarationNode, type TypeNode, type UnionSchemaNode, type UrlSchemaNode, UserFileNode, Visitor, VisitorContext, VisitorDepth, WalkOptions, caseParams, childName, collect, collectImports, collectReferencedSchemaNames, collectUsedSchemaNames, containsCircularRef, createArrowFunction, createBreak, createConst, createDiscriminantNode, createExport, createFile, createFunction, createFunctionParameter, createFunctionParameters, createImport, createInput, createJsx, createOperation, createOperationParams, createOutput, createParameter, createParameterGroup, createParamsType, createPrinterFactory, createProperty, createResponse, createSchema, createSource, createText, createType, definePrinter, enumPropName, extractRefName, extractStringsFromNodes, findCircularSchemas, findDiscriminator, httpMethods, isInputNode, isOperationNode, isOutputNode, isScalarPrimitive, isSchemaNode, isStringType, mediaTypes, mergeAdjacentObjects, narrowSchema, nodeKinds, resolveRefName, schemaTypes, setDiscriminatorEnum, setEnumName, simplifyUnion, syncOptionality, syncSchemaRef, transform, walk };
3876
+ export { type ArraySchemaNode, type ArrowFunctionNode, AsyncVisitor, type BaseNode, type BreakNode, BuildDedupePlanOptions, type CodeNode, CollectOptions, CollectVisitor, type ComplexSchemaType, type ConstNode, type DateSchemaNode, type DatetimeSchemaNode, DedupeCanonical, DedupePlan, DispatchRule, DistributiveOmit, type EnumSchemaNode, type EnumValueNode, type ExportNode, type FileNode, type FormatStringSchemaNode, type FunctionNode, type FunctionNodeType, type FunctionParamNode, type FunctionParameterNode, type FunctionParametersNode, type GenericOperationNode, type HttpMethod, type HttpOperationNode, type HttpStatusCode, type ImportNode, InferSchema, InferSchemaNode, type InputMeta, type InputNode, type InputStreamNode, type IntersectionSchemaNode, type Ipv4SchemaNode, type Ipv6SchemaNode, type JSDocNode, type JsxNode, type MediaType, Node, type NodeKind, type NumberSchemaNode, type ObjectSchemaNode, type OperationNode, type OperationNodeBase, OperationParamsResolver, type OperationProtocol, type OutputNode, type ParameterGroupNode, type ParameterLocation, type ParameterNode, type ParamsTypeNode, ParentOf, ParserOptions, type PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, type PropertyNode, RefMap, type RefSchemaNode, type ResponseNode, ScalarPrimitive, type ScalarSchemaNode, type ScalarSchemaType, SchemaDialect, type SchemaNode, type SchemaNodeByType, type SchemaType, type SourceNode, type SpecialSchemaType, type StatusCode, type StringSchemaNode, type TextNode, type TimeSchemaNode, TransformOptions, type TypeDeclarationNode, type TypeNode, type UnionSchemaNode, type UrlSchemaNode, UserFileNode, Visitor, VisitorContext, VisitorDepth, WalkOptions, applyDedupe, buildDedupePlan, caseParams, childName, collect, collectImports, collectLazy, collectReferencedSchemaNames, collectUsedSchemaNames, containsCircularRef, createArrowFunction, createBreak, createConst, createContent, createDiscriminantNode, createExport, createFile, createFunction, createFunctionParameter, createFunctionParameters, createImport, createInput, createJsx, createOperation, createOperationParams, createOutput, createParameter, createParameterGroup, createParamsType, createPrinterFactory, createProperty, createRequestBody, createResponse, createSchema, createSource, createStreamInput, createText, createType, definePrinter, defineSchemaDialect, dispatch, enumPropName, extractRefName, extractStringsFromNodes, findCircularSchemas, findDiscriminator, httpMethods, isHttpOperationNode, isInputNode, isOperationNode, isOutputNode, isScalarPrimitive, isSchemaEqual, isSchemaNode, isStringType, mediaTypes, mergeAdjacentObjects, mergeAdjacentObjectsLazy, narrowSchema, nodeKinds, resolveRefName, schemaSignature, schemaTypes, setDiscriminatorEnum, setEnumName, simplifyUnion, syncOptionality, syncSchemaRef, transform, update, walk };
3451
3877
  //# sourceMappingURL=index.d.ts.map