@kubb/ast 5.0.0-beta.20 → 5.0.0-beta.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/ast",
3
- "version": "5.0.0-beta.20",
3
+ "version": "5.0.0-beta.21",
4
4
  "description": "Spec-agnostic AST layer for Kubb. Defines the node tree, visitor pattern, factory functions, and type guards used across all code generation plugins.",
5
5
  "keywords": [
6
6
  "ast",
package/src/guards.ts CHANGED
@@ -20,11 +20,11 @@ import type {
20
20
  * @example
21
21
  * ```ts
22
22
  * const schema = createSchema({ type: 'string' })
23
- * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | undefined
23
+ * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | null
24
24
  * ```
25
25
  */
26
- export function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | undefined {
27
- return node?.type === type ? (node as SchemaNodeByType[T]) : undefined
26
+ export function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | null {
27
+ return node?.type === type ? (node as SchemaNodeByType[T]) : null
28
28
  }
29
29
 
30
30
  function isKind<T extends Node>(kind: NodeKind) {
@@ -101,7 +101,7 @@ export type OperationNode = BaseNode & {
101
101
  * Property keys to exclude from the generated request body type via `Omit<Type, Keys>`.
102
102
  * Set when a referenced schema has `readOnly` fields that should be omitted in request types.
103
103
  */
104
- keysToOmit?: Array<string>
104
+ keysToOmit?: Array<string> | null
105
105
  }>
106
106
  }
107
107
  /**
@@ -39,5 +39,5 @@ export type ResponseNode = BaseNode & {
39
39
  * Property keys to exclude from the generated type via `Omit<Type, Keys>`.
40
40
  * Set when a referenced schema has `writeOnly` fields that should not appear in response types.
41
41
  */
42
- keysToOmit?: Array<string>
42
+ keysToOmit?: Array<string> | null
43
43
  }
package/src/nodes/root.ts CHANGED
@@ -30,7 +30,7 @@ export type InputMeta = {
30
30
  /**
31
31
  * Resolved base URL from the first matching server entry in the source document.
32
32
  */
33
- baseURL?: string
33
+ baseURL?: string | null
34
34
  /**
35
35
  * Names of schemas that participate in a circular reference chain.
36
36
  * Computed once during the adapter pre-scan — use this instead of calling
@@ -368,8 +368,9 @@ export type RefSchemaNode = SchemaNodeBase & {
368
368
  type: 'ref'
369
369
  /**
370
370
  * Referenced schema name.
371
+ * `null` means Kubb has processed this and determined there is no applicable name.
371
372
  */
372
- name?: string
373
+ name?: string | null
373
374
  /**
374
375
  * Original `$ref` path, for example, `#/components/schemas/Order`.
375
376
  * Used to resolve names later.
@@ -382,12 +383,13 @@ export type RefSchemaNode = SchemaNodeBase & {
382
383
  /**
383
384
  * The fully-parsed schema that this ref resolves to.
384
385
  * Populated during OAS parsing when the referenced definition can be resolved.
385
- * `undefined` when the ref cannot be resolved or is part of a circular chain.
386
+ * `null` when the ref cannot be resolved or is part of a circular chain.
387
+ * `undefined` when resolution has not been attempted.
386
388
  *
387
389
  * Useful for inspecting the referenced schema's structure (e.g. `primitive`, `properties`)
388
390
  * without following the reference manually.
389
391
  */
390
- schema?: SchemaNode
392
+ schema?: SchemaNode | null
391
393
  }
392
394
 
393
395
  /**
package/src/printer.ts CHANGED
@@ -18,7 +18,7 @@ export type PrinterHandlerContext<TOutput, TOptions extends object> = {
18
18
  * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.
19
19
  * Use `this.transform` inside `nodes` handlers and inside the `print` override.
20
20
  */
21
- transform: (node: SchemaNode) => TOutput | null | undefined
21
+ transform: (node: SchemaNode) => TOutput | null
22
22
  /**
23
23
  * Options for this printer instance.
24
24
  */
@@ -40,7 +40,7 @@ export type PrinterHandlerContext<TOutput, TOptions extends object> = {
40
40
  export type PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (
41
41
  this: PrinterHandlerContext<TOutput, TOptions>,
42
42
  node: SchemaNodeByType[T],
43
- ) => TOutput | null | undefined
43
+ ) => TOutput | null
44
44
 
45
45
  /**
46
46
  * Partial map of per-node-type handler overrides for a printer.
@@ -108,13 +108,13 @@ export type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {
108
108
  * Always dispatches through the `nodes` map; never calls the `print` override.
109
109
  * Use this when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.
110
110
  */
111
- transform: (node: SchemaNode) => T['output'] | null | undefined
111
+ transform: (node: SchemaNode) => T['output'] | null
112
112
  /**
113
113
  * Public printer. If the builder provides a root-level `print`, this calls that
114
114
  * higher-level function (which may produce full declarations).
115
115
  * Otherwise, falls back to the node-level dispatcher.
116
116
  */
117
- print: (node: SchemaNode) => T['printOutput'] | null | undefined
117
+ print: (node: SchemaNode) => T['printOutput'] | null
118
118
  }
119
119
 
120
120
  /**
@@ -147,7 +147,6 @@ type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) =
147
147
  */
148
148
  print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null
149
149
  }
150
-
151
150
  /**
152
151
  * Creates a schema printer factory.
153
152
  *
@@ -194,7 +193,7 @@ export function definePrinter<T extends PrinterFactoryOptions = PrinterFactoryOp
194
193
  * )
195
194
  * ```
196
195
  */
197
- export function createPrinterFactory<TNode, TKey extends string, TNodeByKey extends Partial<Record<TKey, TNode>>>(getKey: (node: TNode) => TKey | undefined) {
196
+ export function createPrinterFactory<TNode, TKey extends string, TNodeByKey extends Partial<Record<TKey, TNode>>>(getKey: (node: TNode) => TKey | null) {
198
197
  return function <T extends PrinterFactoryOptions>(
199
198
  build: (options: T['options']) => {
200
199
  name: T['name']
@@ -202,40 +201,40 @@ export function createPrinterFactory<TNode, TKey extends string, TNodeByKey exte
202
201
  nodes: Partial<{
203
202
  [K in TKey]: (
204
203
  this: {
205
- transform: (node: TNode) => T['output'] | null | undefined
204
+ transform: (node: TNode) => T['output'] | null
206
205
  options: T['options']
207
206
  },
208
207
  node: TNodeByKey[K],
209
- ) => T['output'] | null | undefined
208
+ ) => T['output'] | null
210
209
  }>
211
210
  print?: (
212
211
  this: {
213
- transform: (node: TNode) => T['output'] | null | undefined
212
+ transform: (node: TNode) => T['output'] | null
214
213
  options: T['options']
215
214
  },
216
215
  node: TNode,
217
- ) => T['printOutput'] | null | undefined
216
+ ) => T['printOutput'] | null
218
217
  },
219
218
  ): (options?: T['options']) => {
220
219
  name: T['name']
221
220
  options: T['options']
222
- transform: (node: TNode) => T['output'] | null | undefined
223
- print: (node: TNode) => T['printOutput'] | null | undefined
221
+ transform: (node: TNode) => T['output'] | null
222
+ print: (node: TNode) => T['printOutput'] | null
224
223
  } {
225
224
  return (options) => {
226
225
  const { name, options: resolvedOptions, nodes, print: printOverride } = build(options ?? ({} as T['options']))
227
226
 
228
227
  const context = {
229
228
  options: resolvedOptions,
230
- transform: (node: TNode): T['output'] | null | undefined => {
229
+ transform: (node: TNode): T['output'] | null => {
231
230
  const key = getKey(node)
232
- if (key === undefined) return null
231
+ if (key === null) return null
233
232
 
234
233
  const handler = nodes[key]
235
234
 
236
235
  if (!handler) return null
237
236
 
238
- return (handler as (this: typeof context, node: TNode) => T['output'] | null | undefined).call(context, node)
237
+ return (handler as (this: typeof context, node: TNode) => T['output'] | null).call(context, node)
239
238
  },
240
239
  }
241
240
 
@@ -243,7 +242,7 @@ export function createPrinterFactory<TNode, TKey extends string, TNodeByKey exte
243
242
  name,
244
243
  options: resolvedOptions,
245
244
  transform: context.transform,
246
- print: (printOverride ? printOverride.bind(context) : context.transform) as (node: TNode) => T['printOutput'] | null | undefined,
245
+ print: (printOverride ? printOverride.bind(context) : context.transform) as (node: TNode) => T['printOutput'] | null,
247
246
  }
248
247
  }
249
248
  }
package/src/refs.ts CHANGED
@@ -45,13 +45,15 @@ export function buildRefMap(input: InputNode): RefMap {
45
45
  /**
46
46
  * Resolves a schema by name from a `RefMap`.
47
47
  *
48
+ * Returns `null` when the ref is not found.
49
+ *
48
50
  * @example
49
51
  * ```ts
50
52
  * const petSchema = resolveRef(refMap, 'Pet')
51
53
  * ```
52
54
  */
53
- export function resolveRef(refMap: RefMap, ref: string): SchemaNode | undefined {
54
- return refMap.get(ref)
55
+ export function resolveRef(refMap: RefMap, ref: string): SchemaNode | null {
56
+ return refMap.get(ref) ?? null
55
57
  }
56
58
 
57
59
  /**
package/src/resolvers.ts CHANGED
@@ -27,17 +27,17 @@ export function collectImports<TImport>({
27
27
  }: {
28
28
  node: SchemaNode
29
29
  nameMapping: Map<string, string>
30
- resolve: (schemaName: string) => TImport | undefined
30
+ resolve: (schemaName: string) => TImport | null
31
31
  }): Array<TImport> {
32
32
  return collect<TImport>(node, {
33
- schema(schemaNode): TImport | undefined {
33
+ schema(schemaNode): TImport | null {
34
34
  const schemaRef = narrowSchema(schemaNode, 'ref')
35
- if (!schemaRef?.ref) return
35
+ if (!schemaRef?.ref) return null
36
36
 
37
37
  const rawName = extractRefName(schemaRef.ref)
38
38
  const schemaName = nameMapping.get(rawName) ?? rawName
39
39
  const result = resolve(schemaName)
40
- if (!result) return
40
+ if (!result) return null
41
41
 
42
42
  return result
43
43
  },
@@ -150,7 +150,7 @@ export function setEnumName(propNode: SchemaNode, parentName: string | null | un
150
150
  const enumNode = narrowSchema(propNode, 'enum')
151
151
 
152
152
  if (enumNode?.primitive === 'boolean') {
153
- return { ...propNode, name: undefined }
153
+ return { ...propNode, name: null }
154
154
  }
155
155
 
156
156
  if (enumNode) {
package/src/utils.ts CHANGED
@@ -394,7 +394,7 @@ export function createOperationParams(node: OperationNode, options: CreateOperat
394
394
  } else {
395
395
  if (pathParams.length) {
396
396
  if (pathParamsType === 'inlineSpread') {
397
- const spreadType = resolver?.resolvePathParamsName(node, pathParams[0]!) ?? undefined
397
+ const spreadType = resolver?.resolvePathParamsName(node, pathParams[0]!)
398
398
  params.push(
399
399
  createFunctionParameter({
400
400
  name: pathName,
@@ -476,7 +476,7 @@ function buildGroupParam({
476
476
  name: string
477
477
  node: OperationNode
478
478
  params: Array<ParameterNode>
479
- groupType: ParamGroupType | undefined
479
+ groupType: ParamGroupType | null | undefined
480
480
  resolver: OperationParamsResolver | undefined
481
481
  wrapType: (type: string) => ParamsTypeNode
482
482
  }): Array<FunctionParameterNode> {
@@ -498,7 +498,7 @@ function buildGroupParam({
498
498
 
499
499
  /**
500
500
  * Derives a {@link ParamGroupType} from the resolver's group method.
501
- * Returns `undefined` when the group name equals the individual param name (no real group).
501
+ * Returns `null` when the group name equals the individual param name (no real group).
502
502
  */
503
503
  function resolveGroupType({
504
504
  node,
@@ -510,14 +510,14 @@ function resolveGroupType({
510
510
  params: Array<ParameterNode>
511
511
  groupMethod: (_node: OperationNode, _param: ParameterNode) => string
512
512
  resolver: OperationParamsResolver
513
- }): ParamGroupType | undefined {
513
+ }): ParamGroupType | null {
514
514
  if (!params.length) {
515
- return undefined
515
+ return null
516
516
  }
517
517
  const firstParam = params[0]!
518
518
  const groupName = groupMethod.call(resolver, node, firstParam)
519
519
  if (groupName === resolver.resolveParamName(node, firstParam)) {
520
- return undefined
520
+ return null
521
521
  }
522
522
  const allOptional = params.every((p) => !p.required)
523
523
  return {
@@ -746,7 +746,7 @@ export function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): str
746
746
  /**
747
747
  * Resolves the schema name of a ref node, falling back through `ref` → `name` → nested `schema.name`.
748
748
  *
749
- * Returns `undefined` for non-ref nodes or when no name can be resolved. Use this to get a schema's
749
+ * Returns `null` for non-ref nodes or when no name can be resolved. Use this to get a schema's
750
750
  * identifier for type definitions or error messages.
751
751
  *
752
752
  * @example
@@ -755,11 +755,11 @@ export function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): str
755
755
  * // => 'Pet'
756
756
  * ```
757
757
  */
758
- export function resolveRefName(node: SchemaNode | undefined): string | undefined {
759
- if (!node || node.type !== 'ref') return undefined
760
- if (node.ref) return extractRefName(node.ref) ?? node.name ?? node.schema?.name ?? undefined
758
+ export function resolveRefName(node: SchemaNode | undefined): string | null {
759
+ if (!node || node.type !== 'ref') return null
760
+ if (node.ref) return extractRefName(node.ref) ?? node.name ?? node.schema?.name ?? null
761
761
 
762
- return node.name ?? node.schema?.name ?? undefined
762
+ return node.name ?? node.schema?.name ?? null
763
763
  }
764
764
 
765
765
  /**
@@ -926,9 +926,9 @@ export function containsCircularRef(
926
926
 
927
927
  for (const _ of collectLazy<true>(node, {
928
928
  schema(child) {
929
- if (child.type !== 'ref') return undefined
929
+ if (child.type !== 'ref') return null
930
930
  const name = resolveRefName(child)
931
- return name && name !== excludeName && circularSchemas.has(name) ? true : undefined
931
+ return name && name !== excludeName && circularSchemas.has(name) ? true : null
932
932
  },
933
933
  })) {
934
934
  return true
package/src/visitor.ts CHANGED
@@ -176,13 +176,13 @@ export type AsyncVisitor = {
176
176
  * ```
177
177
  */
178
178
  export type CollectVisitor<T> = {
179
- input?(node: InputNode, context: VisitorContext<InputNode>): T | undefined
180
- output?(node: OutputNode, context: VisitorContext<OutputNode>): T | undefined
181
- operation?(node: OperationNode, context: VisitorContext<OperationNode>): T | undefined
182
- schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): T | undefined
183
- property?(node: PropertyNode, context: VisitorContext<PropertyNode>): T | undefined
184
- parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): T | undefined
185
- response?(node: ResponseNode, context: VisitorContext<ResponseNode>): T | undefined
179
+ input?(node: InputNode, context: VisitorContext<InputNode>): T | null | undefined
180
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): T | null | undefined
181
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): T | null | undefined
182
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): T | null | undefined
183
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): T | null | undefined
184
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): T | null | undefined
185
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): T | null | undefined
186
186
  }
187
187
 
188
188
  /**
@@ -487,7 +487,7 @@ export function transform(node: Node, options: TransformOptions): Node {
487
487
  /**
488
488
  * Runs a depth-first synchronous collection pass.
489
489
  *
490
- * Non-`undefined` values returned by visitor callbacks are appended to the result.
490
+ * Non-`null` values returned by visitor callbacks are appended to the result.
491
491
  *
492
492
  * @example
493
493
  * ```ts
@@ -508,7 +508,7 @@ export function* collectLazy<T>(node: Node, options: CollectOptions<T>): Generat
508
508
  const { depth, parent, ...visitor } = options
509
509
  const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep
510
510
 
511
- let v: T | undefined
511
+ let v: T | null | undefined
512
512
  switch (node.kind) {
513
513
  case 'Input':
514
514
  v = visitor.input?.(node, { parent: parent as ParentOf<InputNode> })
@@ -532,7 +532,7 @@ export function* collectLazy<T>(node: Node, options: CollectOptions<T>): Generat
532
532
  v = visitor.response?.(node, { parent: parent as ParentOf<ResponseNode> })
533
533
  break
534
534
  }
535
- if (v !== undefined) yield v
535
+ if (v != null) yield v
536
536
 
537
537
  for (const child of getChildren(node, recurse)) {
538
538
  yield* collectLazy(child, { ...options, parent: node })