@kubb/ast 4.36.1 → 5.0.0-alpha.10

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.
@@ -12,6 +12,9 @@ declare const nodeKinds: {
12
12
  readonly property: "Property";
13
13
  readonly parameter: "Parameter";
14
14
  readonly response: "Response";
15
+ readonly functionParameter: "FunctionParameter";
16
+ readonly objectBindingParameter: "ObjectBindingParameter";
17
+ readonly functionParameters: "FunctionParameters";
15
18
  };
16
19
  declare const schemaTypes: {
17
20
  readonly string: "string";
@@ -46,6 +49,7 @@ declare const schemaTypes: {
46
49
  readonly email: "email";
47
50
  readonly url: "url";
48
51
  readonly blob: "blob";
52
+ readonly never: "never";
49
53
  };
50
54
  declare const httpMethods: {
51
55
  readonly get: "GET";
@@ -83,7 +87,7 @@ declare const mediaTypes: {
83
87
  /**
84
88
  * Kind discriminant for every AST node.
85
89
  */
86
- type NodeKind = 'Root' | 'Operation' | 'Schema' | 'Property' | 'Parameter' | 'Response';
90
+ type NodeKind = 'Root' | 'Operation' | 'Schema' | 'Property' | 'Parameter' | 'Response' | 'FunctionParameter' | 'ObjectBindingParameter' | 'FunctionParameters';
87
91
  /**
88
92
  * Common base for all AST nodes.
89
93
  */
@@ -91,6 +95,127 @@ type BaseNode = {
91
95
  kind: NodeKind;
92
96
  };
93
97
  //#endregion
98
+ //#region src/nodes/function.d.ts
99
+ /**
100
+ * A single named function parameter.
101
+ *
102
+ * @example Simple required param
103
+ * `name: Type`
104
+ *
105
+ * @example Optional param
106
+ * `name?: Type`
107
+ *
108
+ * @example Param with default
109
+ * `name: Type = defaultValue`
110
+ *
111
+ * @example Rest / spread param
112
+ * `...name: Type[]`
113
+ */
114
+ type FunctionParameterNode = BaseNode & {
115
+ kind: 'FunctionParameter';
116
+ /**
117
+ * The parameter name as it appears in the function signature.
118
+ */
119
+ name: string;
120
+ /**
121
+ * TypeScript type annotation (raw string, e.g. `"string"`, `"Pet[]"`, `"Partial<Config>"`).
122
+ * Omit for untyped JavaScript output.
123
+ */
124
+ type?: string;
125
+ /**
126
+ * When `true` the parameter is emitted as a rest parameter (`...name`).
127
+ * @default false
128
+ */
129
+ rest?: boolean;
130
+ }
131
+ /**
132
+ * Explicitly optional parameter — rendered with `?` in the signature.
133
+ * Cannot be combined with `default`; a parameter with a default is implicitly optional.
134
+ * @example `name?: Type`
135
+ */
136
+ & ({
137
+ optional: true;
138
+ default?: never;
139
+ }
140
+ /**
141
+ * Required parameter, or a parameter with a default value (implicitly optional).
142
+ * @example Required: `name: Type`
143
+ * @example With default: `name: Type = default`
144
+ */
145
+ | {
146
+ optional?: false;
147
+ default?: string;
148
+ });
149
+ /**
150
+ * An object-destructured function parameter group.
151
+ *
152
+ * Renders as `{ key1, key2 }: { key1: Type1; key2: Type2 } = {}` in a declaration,
153
+ * or as individual top-level params when `inline` is `true`.
154
+ *
155
+ * Replaces `mode: 'object'` / `mode: 'inlineSpread'` from the legacy `FunctionParams` API.
156
+ *
157
+ * @example Object destructuring with auto-computed type (declaration)
158
+ * `{ id, name }: { id: string; name: string } = {}`
159
+ *
160
+ * @example Inline (spread) — children emitted as individual top-level params
161
+ * `id: string, name: string`
162
+ */
163
+ type ObjectBindingParameterNode = BaseNode & {
164
+ kind: 'ObjectBindingParameter';
165
+ /**
166
+ * The individual parameters that form the destructured object.
167
+ * Rendered as `{ key1, key2 }` in declarations, or spread inline when `inline` is `true`.
168
+ */
169
+ properties: Array<FunctionParameterNode>;
170
+ /**
171
+ * Explicit TypeScript type annotation for the whole object param.
172
+ * When absent the printer auto-computes `{ key1: Type1; key2: Type2 }` from `params`.
173
+ */
174
+ type?: string;
175
+ /**
176
+ * When `true` the `params` are emitted as individual top-level parameters instead of
177
+ * being wrapped in a destructuring pattern (`{ key1, key2 }`).
178
+ *
179
+ * Equivalent to `mode: 'inlineSpread'` in the legacy `FunctionParams` API.
180
+ * @default false
181
+ */
182
+ inline?: boolean;
183
+ /**
184
+ * Whether the whole object group is optional.
185
+ * When absent the printer auto-computes this: optional if every child param is optional.
186
+ */
187
+ optional?: boolean;
188
+ /**
189
+ * Default value for the object group, written verbatim after `=`.
190
+ * Commonly `'{}'` to allow omitting the argument entirely.
191
+ */
192
+ default?: string;
193
+ };
194
+ /**
195
+ * A complete ordered parameter list for a function.
196
+ *
197
+ * The printer is responsible for sorting (required → optional → has-default).
198
+ * Nodes themselves are treated as plain, immutable data.
199
+ *
200
+ * Renders differently depending on the output mode:
201
+ * - `declaration` → `(id: string, config: Config = {})` — typed function parameter list
202
+ * - `call` → `(id, { method, url })` — function call arguments
203
+ * - `keys` → `{ id, config }` — key names only (for destructuring)
204
+ * - `values` → `{ id: id, config: config }` — key → value pairs
205
+ */
206
+ type FunctionParametersNode = BaseNode & {
207
+ kind: 'FunctionParameters';
208
+ params: Array<FunctionParameterNode | ObjectBindingParameterNode>;
209
+ };
210
+ /**
211
+ * The three function-signature AST node variants.
212
+ */
213
+ type FunctionNode = FunctionParameterNode | ObjectBindingParameterNode | FunctionParametersNode;
214
+ /**
215
+ * Handler map keys — one per `FunctionNode` kind.
216
+ */
217
+ type FunctionNodeType = 'functionParameter' | 'objectBindingParameter' | 'functionParameters';
218
+ //#endregion
94
219
  //#region src/nodes/property.d.ts
95
220
  /**
96
221
  * A named property within an object schema.
@@ -103,14 +228,14 @@ type PropertyNode = BaseNode & {
103
228
  };
104
229
  //#endregion
105
230
  //#region src/nodes/schema.d.ts
106
- type PrimitiveSchemaType = 'string' | 'number' | 'integer' | 'bigint' | 'boolean' | 'null' | 'any' | 'unknown' | 'void' | 'object' | 'array' | 'date';
231
+ type PrimitiveSchemaType = 'string' | 'number' | 'integer' | 'bigint' | 'boolean' | 'null' | 'any' | 'unknown' | 'void' | 'never' | 'object' | 'array' | 'date';
107
232
  type ComplexSchemaType = 'tuple' | 'union' | 'intersection' | 'enum';
108
233
  /**
109
234
  * Semantic types requiring special handling in code generation (e.g. generating a `Date` object or a branded type).
110
235
  */
111
236
  type SpecialSchemaType = 'ref' | 'datetime' | 'time' | 'uuid' | 'email' | 'url' | 'blob';
112
237
  type SchemaType = PrimitiveSchemaType | ComplexSchemaType | SpecialSchemaType;
113
- type ScalarSchemaType = Exclude<SchemaType, 'object' | 'array' | 'tuple' | 'union' | 'intersection' | 'enum' | 'ref' | 'datetime' | 'date' | 'time' | 'string' | 'number' | 'integer' | 'bigint'>;
238
+ type ScalarSchemaType = Exclude<SchemaType, 'object' | 'array' | 'tuple' | 'union' | 'intersection' | 'enum' | 'ref' | 'datetime' | 'date' | 'time' | 'string' | 'number' | 'integer' | 'bigint' | 'url'>;
114
239
  /**
115
240
  * Base fields shared by every schema variant. Does not include spec-specific fields.
116
241
  */
@@ -284,6 +409,16 @@ type NumberSchemaNode = SchemaNodeBase & {
284
409
  type ScalarSchemaNode = SchemaNodeBase & {
285
410
  type: ScalarSchemaType;
286
411
  };
412
+ /**
413
+ * URL schema, optionally carrying an Express-style path template for template literal generation.
414
+ */
415
+ type UrlSchemaNode = SchemaNodeBase & {
416
+ type: 'url';
417
+ /**
418
+ * Express-style path (e.g. `'/pets/:petId'`). When set, printers may emit a template literal type.
419
+ */
420
+ path?: string;
421
+ };
287
422
  /**
288
423
  * Maps each schema type string to its `SchemaNode` variant. Used by `narrowSchema`.
289
424
  */
@@ -307,15 +442,16 @@ type SchemaNodeByType = {
307
442
  any: ScalarSchemaNode;
308
443
  unknown: ScalarSchemaNode;
309
444
  void: ScalarSchemaNode;
445
+ never: ScalarSchemaNode;
310
446
  uuid: ScalarSchemaNode;
311
447
  email: ScalarSchemaNode;
312
- url: ScalarSchemaNode;
448
+ url: UrlSchemaNode;
313
449
  blob: ScalarSchemaNode;
314
450
  };
315
451
  /**
316
452
  * Discriminated union of all schema variants.
317
453
  */
318
- type SchemaNode = ObjectSchemaNode | ArraySchemaNode | UnionSchemaNode | IntersectionSchemaNode | EnumSchemaNode | RefSchemaNode | DatetimeSchemaNode | DateSchemaNode | TimeSchemaNode | StringSchemaNode | NumberSchemaNode | ScalarSchemaNode;
454
+ type SchemaNode = ObjectSchemaNode | ArraySchemaNode | UnionSchemaNode | IntersectionSchemaNode | EnumSchemaNode | RefSchemaNode | DatetimeSchemaNode | DateSchemaNode | TimeSchemaNode | StringSchemaNode | NumberSchemaNode | UrlSchemaNode | ScalarSchemaNode;
319
455
  //#endregion
320
456
  //#region src/nodes/parameter.d.ts
321
457
  type ParameterLocation = 'path' | 'query' | 'header' | 'cookie';
@@ -357,7 +493,7 @@ type ResponseNode = BaseNode & {
357
493
  */
358
494
  statusCode: StatusCode;
359
495
  description?: string;
360
- schema?: SchemaNode;
496
+ schema: SchemaNode;
361
497
  mediaType?: MediaType;
362
498
  };
363
499
  //#endregion
@@ -373,6 +509,10 @@ type OperationNode = BaseNode & {
373
509
  */
374
510
  operationId: string;
375
511
  method: HttpMethod;
512
+ /**
513
+ * Express-style path string, e.g. `/pets/:petId`.
514
+ * Derived from the OpenAPI path by converting `{param}` tokens to `:param`.
515
+ */
376
516
  path: string;
377
517
  tags: Array<string>;
378
518
  summary?: string;
@@ -392,7 +532,17 @@ type OperationNode = BaseNode & {
392
532
  * Adapters populate whichever fields are available in their source format.
393
533
  */
394
534
  type RootMeta = {
395
- /** API title (from `info.title` in OAS/AsyncAPI). */title?: string; /** API version string (from `info.version` in OAS/AsyncAPI). */
535
+ /**
536
+ * API title (from `info.title` in OAS/AsyncAPI).
537
+ */
538
+ title?: string;
539
+ /**
540
+ * API description (from `info.description` in OAS/AsyncAPI).
541
+ */
542
+ description?: string;
543
+ /**
544
+ * API version string (from `info.version` in OAS/AsyncAPI).
545
+ */
396
546
  version?: string;
397
547
  /**
398
548
  * Resolved base URL for the API.
@@ -408,7 +558,10 @@ type RootMeta = {
408
558
  type RootNode = BaseNode & {
409
559
  kind: 'Root';
410
560
  schemas: Array<SchemaNode>;
411
- operations: Array<OperationNode>; /** Format-agnostic document metadata populated by the adapter. */
561
+ operations: Array<OperationNode>;
562
+ /**
563
+ * Format-agnostic document metadata populated by the adapter.
564
+ */
412
565
  meta?: RootMeta;
413
566
  };
414
567
  //#endregion
@@ -420,7 +573,7 @@ type RootNode = BaseNode & {
420
573
  * TypeScript narrow the type automatically inside `switch (node.kind)`
421
574
  * blocks, eliminating the need for manual `as TypeName` casts.
422
575
  */
423
- type Node = RootNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode;
576
+ type Node = RootNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode | FunctionNode;
424
577
  //#endregion
425
578
  //#region src/factory.d.ts
426
579
  /**
@@ -460,16 +613,90 @@ declare function createParameter(props: Pick<ParameterNode, 'name' | 'in' | 'sch
460
613
  /**
461
614
  * Creates a `ResponseNode`.
462
615
  */
463
- declare function createResponse(props: Pick<ResponseNode, 'statusCode'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode'>>): ResponseNode;
616
+ declare function createResponse(props: Pick<ResponseNode, 'statusCode' | 'schema'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'schema'>>): ResponseNode;
617
+ /**
618
+ * Creates a `FunctionParameterNode`. `optional` defaults to `false`.
619
+ *
620
+ * @example Required typed param
621
+ * ```ts
622
+ * createFunctionParameter({ name: 'petId', type: 'string' })
623
+ * // → petId: string
624
+ * ```
625
+ *
626
+ * @example Optional param
627
+ * ```ts
628
+ * createFunctionParameter({ name: 'params', type: 'QueryParams', optional: true })
629
+ * // → params?: QueryParams
630
+ * ```
631
+ *
632
+ * @example Param with default (implicitly optional — cannot combine with `optional: true`)
633
+ * ```ts
634
+ * createFunctionParameter({ name: 'config', type: 'RequestConfig', default: '{}' })
635
+ * // → config: RequestConfig = {}
636
+ * ```
637
+ */
638
+ declare function createFunctionParameter(props: {
639
+ name: string;
640
+ type?: string;
641
+ rest?: boolean;
642
+ } & ({
643
+ optional: true;
644
+ default?: never;
645
+ } | {
646
+ optional?: false;
647
+ default?: string;
648
+ })): FunctionParameterNode;
649
+ /**
650
+ * Creates an `ObjectBindingParameterNode` — an object-destructured parameter group.
651
+ *
652
+ * @example Destructured object param
653
+ * ```ts
654
+ * createObjectBindingParameter({
655
+ * properties: [
656
+ * createFunctionParameter({ name: 'id', type: 'string', optional: false }),
657
+ * createFunctionParameter({ name: 'name', type: 'string', optional: true }),
658
+ * ],
659
+ * default: '{}',
660
+ * })
661
+ * // declaration → { id, name? }: { id: string; name?: string } = {}
662
+ * // call → { id, name }
663
+ * ```
664
+ *
665
+ * @example Inline — children emitted as individual top-level params
666
+ * ```ts
667
+ * createObjectBindingParameter({
668
+ * properties: [createFunctionParameter({ name: 'petId', type: 'string', optional: false })],
669
+ * inline: true,
670
+ * })
671
+ * // declaration → petId: string
672
+ * // call → petId
673
+ * ```
674
+ */
675
+ declare function createObjectBindingParameter(props: Pick<ObjectBindingParameterNode, 'properties'> & Partial<Omit<ObjectBindingParameterNode, 'kind' | 'properties'>>): ObjectBindingParameterNode;
676
+ /**
677
+ * Creates a `FunctionParametersNode` from an ordered list of params.
678
+ *
679
+ * @example
680
+ * ```ts
681
+ * createFunctionParameters({
682
+ * params: [
683
+ * createFunctionParameter({ name: 'petId', type: 'string', optional: false }),
684
+ * createFunctionParameter({ name: 'config', type: 'RequestConfig', optional: false, default: '{}' }),
685
+ * ],
686
+ * })
687
+ * ```
688
+ */
689
+ declare function createFunctionParameters(props?: Partial<Omit<FunctionParametersNode, 'kind'>>): FunctionParametersNode;
464
690
  //#endregion
465
691
  //#region src/printer.d.ts
466
692
  /**
467
693
  * Handler context for `definePrinter` — mirrors `PluginContext` from `@kubb/core`.
468
- * Available as `this` inside each node handler.
694
+ * Available as `this` inside each node handler and the optional root-level `print`.
695
+ * `this.print` always dispatches to the `nodes` handlers (node-level printer).
469
696
  */
470
697
  type PrinterHandlerContext<TOutput, TOptions extends object> = {
471
698
  /**
472
- * Recursively print a nested `SchemaNode`.
699
+ * Recursively print a nested `SchemaNode` using the node-level handlers.
473
700
  */
474
701
  print: (node: SchemaNode) => TOutput | null | undefined;
475
702
  /**
@@ -486,18 +713,19 @@ type PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = Sch
486
713
  * Shape of the type parameter passed to `definePrinter`.
487
714
  * Mirrors `AdapterFactoryOptions` / `PluginFactoryOptions` from `@kubb/core`.
488
715
  *
489
- * - `TName` — unique string identifier (e.g. `'zod'`, `'ts'`)
490
- * - `TOptions` — options passed to and stored on the printer
491
- * - `TOutput` — the type emitted by `print` (typically `string`)
716
+ * - `TName` — unique string identifier (e.g. `'zod'`, `'ts'`)
717
+ * - `TOptions` — options passed to and stored on the printer
718
+ * - `TOutput` — the type emitted by node handlers
719
+ * - `TPrintOutput` — the type emitted by the public `print` override (defaults to `TOutput`)
492
720
  */
493
- type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown> = {
721
+ type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {
494
722
  name: TName;
495
723
  options: TOptions;
496
724
  output: TOutput;
725
+ printOutput: TPrintOutput;
497
726
  };
498
727
  /**
499
728
  * The object returned by calling a `definePrinter` instance.
500
- * Mirrors the shape of `Adapter` from `@kubb/core`.
501
729
  */
502
730
  type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {
503
731
  /**
@@ -509,14 +737,17 @@ type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {
509
737
  */
510
738
  options: T['options'];
511
739
  /**
512
- * Emits `TOutput` from a `SchemaNode`. Returns `null | undefined` when no handler matches.
513
- */
514
- print: (node: SchemaNode) => T['output'] | null | undefined;
515
- /**
516
- * Maps `print` over an array of `SchemaNode`s.
740
+ * Public printer. If the builder provides a root-level `print`, this calls that
741
+ * higher-level function (which may produce full declarations). Otherwise falls back
742
+ * to the node-level dispatcher
517
743
  */
518
- for: (nodes: Array<SchemaNode>) => Array<T['output'] | null | undefined>;
744
+ print: (node: SchemaNode) => T['printOutput'] | null | undefined;
519
745
  };
746
+ /**
747
+ * Builder function passed to `definePrinter`. Receives the resolved options and returns the
748
+ * printer configuration: a unique `name`, the stored `options`, node-level `nodes` handlers,
749
+ * and an optional root-level `print` override.
750
+ */
520
751
  type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {
521
752
  name: T['name'];
522
753
  /**
@@ -524,39 +755,58 @@ type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) =
524
755
  */
525
756
  options: T['options'];
526
757
  nodes: Partial<{ [K in SchemaType]: PrinterHandler<T['output'], T['options'], K> }>;
758
+ /**
759
+ * Optional root-level print override. When provided, becomes the public `printer.print`.
760
+ * `this.print(node)` inside this function calls the node-level dispatcher (`nodes` handlers),
761
+ * not the override itself — so recursion is safe.
762
+ */
763
+ print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null | undefined;
527
764
  };
528
765
  /**
529
- * Creates a named printer factory. Mirrors the `definePlugin` / `defineAdapter` pattern
766
+ * Creates a named printer factory. Mirrors the `createPlugin` / `createAdapter` pattern
530
767
  * from `@kubb/core` — wraps a builder to make options optional and separates raw options
531
768
  * from resolved options.
532
769
  *
533
- * @example
770
+ * The builder receives resolved options and returns:
771
+ * - `name` — a unique identifier for the printer
772
+ * - `options` — options stored on the returned printer instance
773
+ * - `nodes` — a map of `SchemaType` → handler functions that convert a `SchemaNode` to `TOutput`
774
+ * - `print` _(optional)_ — a root-level override that becomes the public `printer.print`.
775
+ * Inside it, `this.print(node)` still dispatches to the `nodes` map — safe recursion, no infinite loop.
776
+ *
777
+ * When no `print` override is provided, `printer.print` is the node-level dispatcher directly.
778
+ *
779
+ * @example Basic usage — Zod schema printer
534
780
  * ```ts
535
- * type ZodPrinter = PrinterFactoryOptions<'zod', { strict?: boolean }, { strict: boolean }, string>
781
+ * type ZodPrinter = PrinterFactoryOptions<'zod', { strict?: boolean }, string>
536
782
  *
537
- * export const zodPrinter = definePrinter<ZodPrinter>((options) => {
538
- * const { strict = true } = options
539
- * return {
540
- * name: 'zod',
541
- * options: { strict },
542
- * nodes: {
543
- * string(node) {
544
- * return `z.string()`
545
- * },
546
- * object(node) {
547
- * const props = node.properties
548
- * ?.map(p => `${p.name}: ${this.print(p)}`)
549
- * .join(', ') ?? ''
550
- * return `z.object({ ${props} })`
551
- * },
783
+ * export const zodPrinter = definePrinter<ZodPrinter>((options) => ({
784
+ * name: 'zod',
785
+ * options: { strict: options.strict ?? true },
786
+ * nodes: {
787
+ * string: () => 'z.string()',
788
+ * object(node) {
789
+ * const props = node.properties.map(p => `${p.name}: ${this.print(p.schema)}`).join(', ')
790
+ * return `z.object({ ${props} })`
552
791
  * },
553
- * }
554
- * })
792
+ * },
793
+ * }))
794
+ * ```
795
+ *
796
+ * @example With a root-level `print` override to wrap output in a full declaration
797
+ * ```ts
798
+ * type TsPrinter = PrinterFactoryOptions<'ts', { typeName?: string }, ts.TypeNode, ts.Node>
555
799
  *
556
- * const printer = zodPrinter({ strict: false })
557
- * printer.name // 'zod'
558
- * printer.options // { strict: false }
559
- * printer.print(node) // 'z.string()'
800
+ * export const printerTs = definePrinter<TsPrinter>((options) => ({
801
+ * name: 'ts',
802
+ * options,
803
+ * nodes: { string: () => factory.keywordTypeNodes.string },
804
+ * print(node) {
805
+ * const type = this.print(node) // calls the node-level dispatcher
806
+ * if (!type || !this.options.typeName) return type
807
+ * return factory.createTypeAliasDeclaration(this.options.typeName, type)
808
+ * },
809
+ * }))
560
810
  * ```
561
811
  */
562
812
  declare function definePrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T>;
@@ -645,5 +895,5 @@ declare function transform(node: Node, visitor: Visitor, options?: VisitorOption
645
895
  */
646
896
  declare function collect<T>(node: Node, visitor: CollectVisitor<T>, options?: VisitorOptions): Array<T>;
647
897
  //#endregion
648
- export { UnionSchemaNode as $, MediaType as A, IntersectionSchemaNode as B, Node as C, OperationNode as D, HttpMethod as E, ComplexSchemaType as F, ScalarSchemaNode as G, ObjectSchemaNode as H, DateSchemaNode as I, SchemaNodeByType as J, ScalarSchemaType as K, DatetimeSchemaNode as L, ParameterLocation as M, ParameterNode as N, ResponseNode as O, ArraySchemaNode as P, TimeSchemaNode as Q, EnumSchemaNode as R, createSchema as S, RootNode as T, PrimitiveSchemaType as U, NumberSchemaNode as V, RefSchemaNode as W, SpecialSchemaType as X, SchemaType as Y, StringSchemaNode as Z, createOperation as _, transform as a, mediaTypes as at, createResponse as b, buildRefMap as c, Printer as d, PropertyNode as et, PrinterFactoryOptions as f, DistributiveOmit as g, definePrinter as h, collect as i, httpMethods as it, StatusCode as j, HttpStatusCode as k, refMapToObject as l, PrinterHandlerContext as m, CollectVisitor as n, NodeKind as nt, walk as o, nodeKinds as ot, PrinterHandler as p, SchemaNode as q, Visitor as r, VisitorDepth as rt, RefMap as s, schemaTypes as st, AsyncVisitor as t, BaseNode as tt, resolveRef as u, createParameter as v, RootMeta as w, createRoot as x, createProperty as y, EnumValueNode as z };
649
- //# sourceMappingURL=visitor-CmsfJzro.d.ts.map
898
+ export { TimeSchemaNode as $, HttpStatusCode as A, EnumValueNode as B, createSchema as C, HttpMethod as D, RootNode as E, ArraySchemaNode as F, RefSchemaNode as G, NumberSchemaNode as H, ComplexSchemaType as I, SchemaNode as J, ScalarSchemaNode as K, DateSchemaNode as L, StatusCode as M, ParameterLocation as N, OperationNode as O, ParameterNode as P, StringSchemaNode as Q, DatetimeSchemaNode as R, createRoot as S, RootMeta as T, ObjectSchemaNode as U, IntersectionSchemaNode as V, PrimitiveSchemaType as W, SchemaType as X, SchemaNodeByType as Y, SpecialSchemaType as Z, createObjectBindingParameter as _, transform as a, FunctionParameterNode as at, createProperty as b, buildRefMap as c, BaseNode as ct, Printer as d, httpMethods as dt, UnionSchemaNode as et, PrinterFactoryOptions as f, mediaTypes as ft, createFunctionParameters as g, createFunctionParameter as h, collect as i, FunctionNodeType as it, MediaType as j, ResponseNode as k, refMapToObject as l, NodeKind as lt, DistributiveOmit as m, schemaTypes as mt, CollectVisitor as n, PropertyNode as nt, walk as o, FunctionParametersNode as ot, definePrinter as p, nodeKinds as pt, ScalarSchemaType as q, Visitor as r, FunctionNode as rt, RefMap as s, ObjectBindingParameterNode as st, AsyncVisitor as t, UrlSchemaNode as tt, resolveRef as u, VisitorDepth as ut, createOperation as v, Node as w, createResponse as x, createParameter as y, EnumSchemaNode as z };
899
+ //# sourceMappingURL=visitor-D-l3dMbN.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/ast",
3
- "version": "4.36.1",
3
+ "version": "5.0.0-alpha.10",
4
4
  "description": "Spec-agnostic AST layer for Kubb. Defines nodes, visitor pattern, and factory functions used across codegen plugins.",
5
5
  "keywords": [
6
6
  "kubb",
@@ -45,12 +45,13 @@
45
45
  "!/**/__snapshots__/**"
46
46
  ],
47
47
  "devDependencies": {
48
- "@types/node": "^20.19.37"
48
+ "@types/node": "^22.19.15",
49
+ "@internals/utils": "0.0.0"
49
50
  },
50
51
  "main": "./dist/index.cjs",
51
52
  "module": "./dist/index.js",
52
53
  "engines": {
53
- "node": ">=20"
54
+ "node": ">=22"
54
55
  },
55
56
  "publishConfig": {
56
57
  "access": "public",
package/src/constants.ts CHANGED
@@ -21,7 +21,10 @@ export const nodeKinds = {
21
21
  property: 'Property',
22
22
  parameter: 'Parameter',
23
23
  response: 'Response',
24
- } as const satisfies Record<Lowercase<NodeKind>, NodeKind>
24
+ functionParameter: 'FunctionParameter',
25
+ objectBindingParameter: 'ObjectBindingParameter',
26
+ functionParameters: 'FunctionParameters',
27
+ } as const satisfies Record<string, NodeKind>
25
28
 
26
29
  export const schemaTypes = {
27
30
  string: 'string',
@@ -56,6 +59,7 @@ export const schemaTypes = {
56
59
  email: 'email',
57
60
  url: 'url',
58
61
  blob: 'blob',
62
+ never: 'never',
59
63
  } as const satisfies Record<SchemaType, SchemaType>
60
64
 
61
65
  export const httpMethods = {
package/src/factory.ts CHANGED
@@ -1,4 +1,15 @@
1
- import type { ObjectSchemaNode, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode } from './nodes/index.ts'
1
+ import type {
2
+ FunctionParameterNode,
3
+ FunctionParametersNode,
4
+ ObjectBindingParameterNode,
5
+ ObjectSchemaNode,
6
+ OperationNode,
7
+ ParameterNode,
8
+ PropertyNode,
9
+ ResponseNode,
10
+ RootNode,
11
+ SchemaNode,
12
+ } from './nodes/index.ts'
2
13
 
3
14
  /**
4
15
  * Distributive variant of `Omit` that preserves union members.
@@ -76,9 +87,98 @@ export function createParameter(
76
87
  /**
77
88
  * Creates a `ResponseNode`.
78
89
  */
79
- export function createResponse(props: Pick<ResponseNode, 'statusCode'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode'>>): ResponseNode {
90
+ export function createResponse(
91
+ props: Pick<ResponseNode, 'statusCode' | 'schema'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'schema'>>,
92
+ ): ResponseNode {
80
93
  return {
81
94
  ...props,
82
95
  kind: 'Response',
83
96
  }
84
97
  }
98
+
99
+ /**
100
+ * Creates a `FunctionParameterNode`. `optional` defaults to `false`.
101
+ *
102
+ * @example Required typed param
103
+ * ```ts
104
+ * createFunctionParameter({ name: 'petId', type: 'string' })
105
+ * // → petId: string
106
+ * ```
107
+ *
108
+ * @example Optional param
109
+ * ```ts
110
+ * createFunctionParameter({ name: 'params', type: 'QueryParams', optional: true })
111
+ * // → params?: QueryParams
112
+ * ```
113
+ *
114
+ * @example Param with default (implicitly optional — cannot combine with `optional: true`)
115
+ * ```ts
116
+ * createFunctionParameter({ name: 'config', type: 'RequestConfig', default: '{}' })
117
+ * // → config: RequestConfig = {}
118
+ * ```
119
+ */
120
+ export function createFunctionParameter(
121
+ props: { name: string; type?: string; rest?: boolean } & ({ optional: true; default?: never } | { optional?: false; default?: string }),
122
+ ): FunctionParameterNode {
123
+ return {
124
+ optional: false,
125
+ ...props,
126
+ kind: 'FunctionParameter',
127
+ } as FunctionParameterNode
128
+ }
129
+
130
+ /**
131
+ * Creates an `ObjectBindingParameterNode` — an object-destructured parameter group.
132
+ *
133
+ * @example Destructured object param
134
+ * ```ts
135
+ * createObjectBindingParameter({
136
+ * properties: [
137
+ * createFunctionParameter({ name: 'id', type: 'string', optional: false }),
138
+ * createFunctionParameter({ name: 'name', type: 'string', optional: true }),
139
+ * ],
140
+ * default: '{}',
141
+ * })
142
+ * // declaration → { id, name? }: { id: string; name?: string } = {}
143
+ * // call → { id, name }
144
+ * ```
145
+ *
146
+ * @example Inline — children emitted as individual top-level params
147
+ * ```ts
148
+ * createObjectBindingParameter({
149
+ * properties: [createFunctionParameter({ name: 'petId', type: 'string', optional: false })],
150
+ * inline: true,
151
+ * })
152
+ * // declaration → petId: string
153
+ * // call → petId
154
+ * ```
155
+ */
156
+ export function createObjectBindingParameter(
157
+ props: Pick<ObjectBindingParameterNode, 'properties'> & Partial<Omit<ObjectBindingParameterNode, 'kind' | 'properties'>>,
158
+ ): ObjectBindingParameterNode {
159
+ return {
160
+ ...props,
161
+ kind: 'ObjectBindingParameter',
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Creates a `FunctionParametersNode` from an ordered list of params.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * createFunctionParameters({
171
+ * params: [
172
+ * createFunctionParameter({ name: 'petId', type: 'string', optional: false }),
173
+ * createFunctionParameter({ name: 'config', type: 'RequestConfig', optional: false, default: '{}' }),
174
+ * ],
175
+ * })
176
+ * ```
177
+ */
178
+ export function createFunctionParameters(props: Partial<Omit<FunctionParametersNode, 'kind'>> = {}): FunctionParametersNode {
179
+ return {
180
+ params: [],
181
+ ...props,
182
+ kind: 'FunctionParameters',
183
+ }
184
+ }