@kubb/ast 5.0.0-alpha.3 → 5.0.0-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/ast",
3
- "version": "5.0.0-alpha.3",
3
+ "version": "5.0.0-alpha.31",
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,7 +45,8 @@
45
45
  "!/**/__snapshots__/**"
46
46
  ],
47
47
  "devDependencies": {
48
- "@types/node": "^22.19.15"
48
+ "@types/node": "^22.19.17",
49
+ "@internals/utils": "0.0.0"
49
50
  },
50
51
  "main": "./dist/index.cjs",
51
52
  "module": "./dist/index.js",
package/src/constants.ts CHANGED
@@ -5,7 +5,7 @@ import type { ParameterLocation } from './nodes/parameter.ts'
5
5
  import type { SchemaType } from './nodes/schema.ts'
6
6
 
7
7
  /**
8
- * Depth for schema traversal in visitor functions.
8
+ * Traversal depth used by AST visitor utilities.
9
9
  */
10
10
  export type VisitorDepth = 'shallow' | 'deep'
11
11
 
@@ -21,9 +21,26 @@ 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
+ parameterGroup: 'ParameterGroup',
26
+ functionParameters: 'FunctionParameters',
27
+ } as const satisfies Record<string, NodeKind>
25
28
 
29
+ /**
30
+ * Canonical schema type strings used by AST schema nodes.
31
+ *
32
+ * These values are used across the AST as stable discriminators
33
+ * (for example `schema.type === schemaTypes.object`).
34
+ *
35
+ * The map is grouped by intent:
36
+ * - primitives (`string`, `number`, `boolean`, ...)
37
+ * - structural/composite (`object`, `array`, `union`, ...)
38
+ * - special OpenAPI-oriented types (`ref`, `datetime`, `uuid`, ...)
39
+ */
26
40
  export const schemaTypes = {
41
+ /**
42
+ * Text value.
43
+ */
27
44
  string: 'string',
28
45
  /**
29
46
  * Floating-point number (`float`, `double`).
@@ -37,27 +54,110 @@ export const schemaTypes = {
37
54
  * 64-bit integer (`int64`). Only used when `integerType` is set to `'bigint'`.
38
55
  */
39
56
  bigint: 'bigint',
57
+ /**
58
+ * Boolean value
59
+ */
40
60
  boolean: 'boolean',
61
+ /**
62
+ * Explicit null value.
63
+ */
41
64
  null: 'null',
65
+ /**
66
+ * Any value (no type restriction).
67
+ */
42
68
  any: 'any',
69
+ /**
70
+ * Unknown value (must be narrowed before usage).
71
+ */
43
72
  unknown: 'unknown',
73
+ /**
74
+ * No return value (`void`).
75
+ */
44
76
  void: 'void',
77
+ /**
78
+ * Object with named properties.
79
+ */
45
80
  object: 'object',
81
+ /**
82
+ * Sequential list of items.
83
+ */
46
84
  array: 'array',
85
+ /**
86
+ * Fixed-length list with position-specific items.
87
+ */
47
88
  tuple: 'tuple',
89
+ /**
90
+ * "One of" multiple schema members.
91
+ */
48
92
  union: 'union',
93
+ /**
94
+ * "All of" multiple schema members.
95
+ */
49
96
  intersection: 'intersection',
97
+ /**
98
+ * Enum schema.
99
+ */
50
100
  enum: 'enum',
101
+ /**
102
+ * Reference to another schema.
103
+ */
51
104
  ref: 'ref',
105
+ /**
106
+ * Calendar date (for example `2026-03-24`).
107
+ */
52
108
  date: 'date',
109
+ /**
110
+ * Date-time value (for example `2026-03-24T09:00:00Z`).
111
+ */
53
112
  datetime: 'datetime',
113
+ /**
114
+ * Time-only value (for example `09:00:00`).
115
+ */
54
116
  time: 'time',
117
+ /**
118
+ * UUID value.
119
+ */
55
120
  uuid: 'uuid',
121
+ /**
122
+ * Email address value.
123
+ */
56
124
  email: 'email',
125
+ /**
126
+ * URL value.
127
+ */
57
128
  url: 'url',
129
+ /**
130
+ * IPv4 address value.
131
+ */
132
+ ipv4: 'ipv4',
133
+ /**
134
+ * IPv6 address value.
135
+ */
136
+ ipv6: 'ipv6',
137
+ /**
138
+ * Binary/blob value.
139
+ */
58
140
  blob: 'blob',
141
+ /**
142
+ * Impossible value (`never`).
143
+ */
144
+ never: 'never',
59
145
  } as const satisfies Record<SchemaType, SchemaType>
60
146
 
147
+ export type ScalarPrimitive = 'string' | 'number' | 'integer' | 'bigint' | 'boolean'
148
+
149
+ /**
150
+ * Primitive scalar schema types used when simplifying union members.
151
+ */
152
+ export const SCALAR_PRIMITIVE_TYPES = new Set<ScalarPrimitive>(['string', 'number', 'integer', 'bigint', 'boolean'])
153
+
154
+ /**
155
+ * Returns `true` when `type` is a scalar primitive schema type.
156
+ */
157
+ export function isScalarPrimitive(type: string): type is ScalarPrimitive {
158
+ return SCALAR_PRIMITIVE_TYPES.has(type as ScalarPrimitive)
159
+ }
160
+
61
161
  export const httpMethods = {
62
162
  get: 'GET',
63
163
  post: 'POST',
@@ -77,12 +177,26 @@ export const parameterLocations = {
77
177
  } as const satisfies Record<ParameterLocation, ParameterLocation>
78
178
 
79
179
  /**
80
- * Default max concurrent visitor calls in `walk`.
180
+ * Default maximum number of concurrent callbacks used by `walk`.
181
+ *
182
+ * 30 is chosen to allow enough parallelism to overlap I/O-bound resolver calls
183
+ * without overwhelming the event loop or causing excessive memory pressure during
184
+ * large spec traversals.
185
+ *
186
+ * @example
187
+ * ```ts
188
+ * walk(root, { concurrency: WALK_CONCURRENCY, root: () => {} })
189
+ * ```
81
190
  */
82
191
  export const WALK_CONCURRENCY = 30
83
192
 
84
193
  /**
85
- * Fallback status code string for API spec responses.
194
+ * Fallback response status code used for catch-all responses.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * const status = DEFAULT_STATUS_CODE // 'default'
199
+ * ```
86
200
  */
87
201
  export const DEFAULT_STATUS_CODE = 'default' as const
88
202
 
package/src/factory.ts CHANGED
@@ -1,12 +1,66 @@
1
- import type { ObjectSchemaNode, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode } from './nodes/index.ts'
1
+ import type { InferSchemaNode } from './infer.ts'
2
+ import type {
3
+ FunctionParameterNode,
4
+ FunctionParametersNode,
5
+ ObjectSchemaNode,
6
+ OperationNode,
7
+ ParameterGroupNode,
8
+ ParameterNode,
9
+ PrimitiveSchemaType,
10
+ PropertyNode,
11
+ ResponseNode,
12
+ RootNode,
13
+ SchemaNode,
14
+ TypeNode,
15
+ } from './nodes/index.ts'
2
16
 
3
17
  /**
4
- * Distributive variant of `Omit` that preserves union members.
18
+ * Syncs property/parameter schema optionality flags from `required` and `schema.nullable`.
19
+ *
20
+ * - `optional` is set for non-required, non-nullable schemas.
21
+ * - `nullish` is set for non-required, nullable schemas.
22
+ */
23
+ export function syncOptionality(schema: SchemaNode, required: boolean): SchemaNode {
24
+ const nullable = schema.nullable ?? false
25
+
26
+ return {
27
+ ...schema,
28
+ optional: !required && !nullable ? true : undefined,
29
+ nullish: !required && nullable ? true : undefined,
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Distributive `Omit` that preserves each member of a union.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * type A = { kind: 'a'; keep: string; drop: number }
39
+ * type B = { kind: 'b'; keep: boolean; drop: number }
40
+ * type Result = DistributiveOmit<A | B, 'drop'>
41
+ * // -> { kind: 'a'; keep: string } | { kind: 'b'; keep: boolean }
42
+ * ```
5
43
  */
6
44
  export type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never
7
45
 
46
+ type CreateSchemaObjectInput = Omit<ObjectSchemaNode, 'kind' | 'properties' | 'primitive'> & { properties?: Array<PropertyNode>; primitive?: 'object' }
47
+ type CreateSchemaInput = CreateSchemaObjectInput | DistributiveOmit<Exclude<SchemaNode, ObjectSchemaNode>, 'kind'>
48
+ type CreateSchemaOutput<T extends CreateSchemaInput> = InferSchemaNode<T> & { kind: 'Schema' }
49
+
8
50
  /**
9
- * Creates a `RootNode`.
51
+ * Creates a `RootNode` with stable defaults for `schemas` and `operations`.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const root = createRoot()
56
+ * // { kind: 'Root', schemas: [], operations: [] }
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const root = createRoot({ schemas: [petSchema] })
62
+ * // keeps default operations: []
63
+ * ```
10
64
  */
11
65
  export function createRoot(overrides: Partial<Omit<RootNode, 'kind'>> = {}): RootNode {
12
66
  return {
@@ -18,7 +72,27 @@ export function createRoot(overrides: Partial<Omit<RootNode, 'kind'>> = {}): Roo
18
72
  }
19
73
 
20
74
  /**
21
- * Creates an `OperationNode`.
75
+ * Creates an `OperationNode` with default empty arrays for `tags`, `parameters`, and `responses`.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const operation = createOperation({
80
+ * operationId: 'getPetById',
81
+ * method: 'GET',
82
+ * path: '/pet/{petId}',
83
+ * })
84
+ * // tags, parameters, and responses are []
85
+ * ```
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const operation = createOperation({
90
+ * operationId: 'findPets',
91
+ * method: 'GET',
92
+ * path: '/pet/findByStatus',
93
+ * tags: ['pet'],
94
+ * })
95
+ * ```
22
96
  */
23
97
  export function createOperation(
24
98
  props: Pick<OperationNode, 'operationId' | 'method' | 'path'> & Partial<Omit<OperationNode, 'kind' | 'operationId' | 'method' | 'path'>>,
@@ -32,53 +106,293 @@ export function createOperation(
32
106
  }
33
107
  }
34
108
 
109
+ /**
110
+ * Maps schema `type` to its underlying `primitive`.
111
+ * Primitive types map to themselves; special string formats map to `'string'`.
112
+ * Complex types (`ref`, `enum`, `union`, `intersection`, `tuple`, `blob`) are left unset.
113
+ */
114
+ const TYPE_TO_PRIMITIVE: Partial<Record<SchemaNode['type'], PrimitiveSchemaType>> = {
115
+ string: 'string',
116
+ number: 'number',
117
+ integer: 'integer',
118
+ bigint: 'bigint',
119
+ boolean: 'boolean',
120
+ null: 'null',
121
+ any: 'any',
122
+ unknown: 'unknown',
123
+ void: 'void',
124
+ never: 'never',
125
+ object: 'object',
126
+ array: 'array',
127
+ date: 'date',
128
+ uuid: 'string',
129
+ email: 'string',
130
+ url: 'string',
131
+ datetime: 'string',
132
+ time: 'string',
133
+ }
134
+
35
135
  /**
36
136
  * Creates a `SchemaNode`, narrowed to the variant of `props.type`.
37
- * For object schemas, `properties` defaults to `[]` when not provided.
137
+ * For object schemas, `properties` defaults to an empty array.
138
+ * `primitive` is automatically inferred from `type` when not explicitly provided.
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * const scalar = createSchema({ type: 'string' })
143
+ * // { kind: 'Schema', type: 'string', primitive: 'string' }
144
+ * ```
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * const uuid = createSchema({ type: 'uuid' })
149
+ * // { kind: 'Schema', type: 'uuid', primitive: 'string' }
150
+ * ```
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * const object = createSchema({ type: 'object' })
155
+ * // { kind: 'Schema', type: 'object', primitive: 'object', properties: [] }
156
+ * ```
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * const enumSchema = createSchema({
161
+ * type: 'enum',
162
+ * primitive: 'string',
163
+ * enumValues: ['available', 'pending'],
164
+ * })
165
+ * ```
38
166
  */
39
- export function createSchema<T extends Omit<ObjectSchemaNode, 'kind' | 'properties'> & { properties?: Array<PropertyNode> }>(
40
- props: T,
41
- ): Omit<T, 'properties'> & { properties: Array<PropertyNode>; kind: 'Schema' }
42
- export function createSchema<T extends DistributiveOmit<Exclude<SchemaNode, ObjectSchemaNode>, 'kind'>>(props: T): T & { kind: 'Schema' }
43
- export function createSchema(props: DistributiveOmit<SchemaNode, 'kind'>): SchemaNode
44
- export function createSchema(props: Record<string, unknown>): Record<string, unknown> {
167
+ export function createSchema<T extends CreateSchemaInput>(props: T): CreateSchemaOutput<T>
168
+ export function createSchema(props: CreateSchemaInput): SchemaNode
169
+ export function createSchema(props: CreateSchemaInput): SchemaNode {
170
+ const inferredPrimitive = TYPE_TO_PRIMITIVE[props.type as keyof typeof TYPE_TO_PRIMITIVE]
171
+
45
172
  if (props['type'] === 'object') {
46
- return { properties: [], ...props, kind: 'Schema' }
173
+ return { properties: [], primitive: 'object', ...props, kind: 'Schema' } as CreateSchemaOutput<typeof props>
47
174
  }
48
175
 
49
- return { ...props, kind: 'Schema' }
176
+ return { primitive: inferredPrimitive, ...props, kind: 'Schema' } as CreateSchemaOutput<typeof props>
50
177
  }
51
178
 
52
179
  /**
53
- * Creates a `PropertyNode`. `required` defaults to `false`.
180
+ * Creates a `PropertyNode`.
181
+ *
182
+ * `required` defaults to `false`.
183
+ * `schema.optional` and `schema.nullish` are derived from `required` and `schema.nullable`.
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * const property = createProperty({
188
+ * name: 'status',
189
+ * schema: createSchema({ type: 'string' }),
190
+ * })
191
+ * // required=false, schema.optional=true
192
+ * ```
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * const property = createProperty({
197
+ * name: 'status',
198
+ * required: true,
199
+ * schema: createSchema({ type: 'string', nullable: true }),
200
+ * })
201
+ * // required=true, no optional/nullish
202
+ * ```
54
203
  */
55
204
  export function createProperty(props: Pick<PropertyNode, 'name' | 'schema'> & Partial<Omit<PropertyNode, 'kind' | 'name' | 'schema'>>): PropertyNode {
205
+ const required = props.required ?? false
206
+
56
207
  return {
57
- required: false,
58
208
  ...props,
59
209
  kind: 'Property',
210
+ required,
211
+ schema: syncOptionality(props.schema, required),
60
212
  }
61
213
  }
62
214
 
63
215
  /**
64
- * Creates a `ParameterNode`. `required` defaults to `false`.
216
+ * Creates a `ParameterNode`.
217
+ *
218
+ * `required` defaults to `false`.
219
+ * Nested schema flags are set from `required` and `schema.nullable`.
220
+ *
221
+ * @example
222
+ * ```ts
223
+ * const param = createParameter({
224
+ * name: 'petId',
225
+ * in: 'path',
226
+ * required: true,
227
+ * schema: createSchema({ type: 'string' }),
228
+ * })
229
+ * ```
230
+ *
231
+ * @example
232
+ * ```ts
233
+ * const param = createParameter({
234
+ * name: 'status',
235
+ * in: 'query',
236
+ * schema: createSchema({ type: 'string', nullable: true }),
237
+ * })
238
+ * // required=false, schema.nullish=true
239
+ * ```
65
240
  */
66
241
  export function createParameter(
67
242
  props: Pick<ParameterNode, 'name' | 'in' | 'schema'> & Partial<Omit<ParameterNode, 'kind' | 'name' | 'in' | 'schema'>>,
68
243
  ): ParameterNode {
244
+ const required = props.required ?? false
69
245
  return {
70
- required: false,
71
246
  ...props,
72
247
  kind: 'Parameter',
248
+ required,
249
+ schema: syncOptionality(props.schema, required),
73
250
  }
74
251
  }
75
252
 
76
253
  /**
77
254
  * Creates a `ResponseNode`.
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * const response = createResponse({
259
+ * statusCode: '200',
260
+ * description: 'Success',
261
+ * schema: createSchema({ type: 'object', properties: [] }),
262
+ * })
263
+ * ```
78
264
  */
79
- export function createResponse(props: Pick<ResponseNode, 'statusCode'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode'>>): ResponseNode {
265
+ export function createResponse(
266
+ props: Pick<ResponseNode, 'statusCode' | 'schema'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'schema'>>,
267
+ ): ResponseNode {
80
268
  return {
81
269
  ...props,
82
270
  kind: 'Response',
83
271
  }
84
272
  }
273
+
274
+ /**
275
+ * Creates a `FunctionParameterNode`.
276
+ *
277
+ * `optional` defaults to `false`.
278
+ *
279
+ * @example Required typed param
280
+ * ```ts
281
+ * createFunctionParameter({ name: 'petId', type: createTypeNode({ variant: 'reference', name: 'string' }) })
282
+ * // → petId: string
283
+ * ```
284
+ *
285
+ * @example Optional param
286
+ * ```ts
287
+ * createFunctionParameter({ name: 'params', type: createTypeNode({ variant: 'reference', name: 'QueryParams' }), optional: true })
288
+ * // → params?: QueryParams
289
+ * ```
290
+ *
291
+ * @example Param with default (implicitly optional; cannot combine with `optional: true`)
292
+ * ```ts
293
+ * createFunctionParameter({ name: 'config', type: createTypeNode({ variant: 'reference', name: 'RequestConfig' }), default: '{}' })
294
+ * // → config: RequestConfig = {}
295
+ * ```
296
+ */
297
+ export function createFunctionParameter(
298
+ props: { name: string; type?: TypeNode; rest?: boolean } & ({ optional: true; default?: never } | { optional?: false; default?: string }),
299
+ ): FunctionParameterNode {
300
+ return {
301
+ optional: false,
302
+ ...props,
303
+ kind: 'FunctionParameter',
304
+ } as FunctionParameterNode
305
+ }
306
+
307
+ /**
308
+ * Creates a {@link TypeNode} representing a language-agnostic structured type expression.
309
+ *
310
+ * Use `variant: 'struct'` for inline anonymous types and `variant: 'member'` for a single
311
+ * named field accessed from a group type. Each language's printer renders the variant
312
+ * into its own syntax (TypeScript, Python, C#, Kotlin, …).
313
+ *
314
+ * @example Reference type (TypeScript: `QueryParams`)
315
+ * ```ts
316
+ * createTypeNode({ variant: 'reference', name: 'QueryParams' })
317
+ * ```
318
+ *
319
+ * @example Struct type (TypeScript: `{ petId: string }`)
320
+ * ```ts
321
+ * createTypeNode({ variant: 'struct', properties: [{ name: 'petId', optional: false, type: createTypeNode({ variant: 'reference', name: 'string' }) }] })
322
+ * ```
323
+ *
324
+ * @example Member type (TypeScript: `DeletePetPathParams['petId']`)
325
+ * ```ts
326
+ * createTypeNode({ variant: 'member', base: 'DeletePetPathParams', key: 'petId' })
327
+ * ```
328
+ */
329
+ export function createTypeNode(
330
+ props:
331
+ | { variant: 'reference'; name: string }
332
+ | { variant: 'struct'; properties: Array<{ name: string; optional: boolean; type: TypeNode }> }
333
+ | { variant: 'member'; base: string; key: string },
334
+ ): TypeNode {
335
+ return { ...props, kind: 'Type' } as TypeNode
336
+ }
337
+
338
+ /**
339
+ * Creates a `ParameterGroupNode` representing a group of related parameters treated as a unit.
340
+ *
341
+ * @example Grouped param (TypeScript declaration)
342
+ * ```ts
343
+ * createParameterGroup({
344
+ * properties: [
345
+ * createFunctionParameter({ name: 'id', type: createTypeNode({ variant: 'reference', name: 'string' }), optional: false }),
346
+ * createFunctionParameter({ name: 'name', type: createTypeNode({ variant: 'reference', name: 'string' }), optional: true }),
347
+ * ],
348
+ * default: '{}',
349
+ * })
350
+ * // declaration → { id, name? }: { id: string; name?: string } = {}
351
+ * // call → { id, name }
352
+ * ```
353
+ *
354
+ * @example Inline (spread) — children emitted as individual top-level parameters
355
+ * ```ts
356
+ * createParameterGroup({
357
+ * properties: [createFunctionParameter({ name: 'petId', type: createTypeNode({ variant: 'reference', name: 'string' }), optional: false })],
358
+ * inline: true,
359
+ * })
360
+ * // declaration → petId: string
361
+ * // call → petId
362
+ * ```
363
+ */
364
+ export function createParameterGroup(
365
+ props: Pick<ParameterGroupNode, 'properties'> & Partial<Omit<ParameterGroupNode, 'kind' | 'properties'>>,
366
+ ): ParameterGroupNode {
367
+ return {
368
+ ...props,
369
+ kind: 'ParameterGroup',
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Creates a `FunctionParametersNode` from an ordered list of parameters.
375
+ *
376
+ * @example
377
+ * ```ts
378
+ * createFunctionParameters({
379
+ * params: [
380
+ * createFunctionParameter({ name: 'petId', type: createTypeNode({ variant: 'reference', name: 'string' }), optional: false }),
381
+ * createFunctionParameter({ name: 'config', type: createTypeNode({ variant: 'reference', name: 'RequestConfig' }), optional: false, default: '{}' }),
382
+ * ],
383
+ * })
384
+ * ```
385
+ *
386
+ * @example
387
+ * ```ts
388
+ * const empty = createFunctionParameters()
389
+ * // { kind: 'FunctionParameters', params: [] }
390
+ * ```
391
+ */
392
+ export function createFunctionParameters(props: Partial<Omit<FunctionParametersNode, 'kind'>> = {}): FunctionParametersNode {
393
+ return {
394
+ params: [],
395
+ ...props,
396
+ kind: 'FunctionParameters',
397
+ }
398
+ }
package/src/guards.ts CHANGED
@@ -1,7 +1,26 @@
1
- import type { Node, NodeKind, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode, SchemaNodeByType } from './nodes/index.ts'
1
+ import type {
2
+ FunctionParameterNode,
3
+ FunctionParametersNode,
4
+ Node,
5
+ NodeKind,
6
+ OperationNode,
7
+ ParameterGroupNode,
8
+ ParameterNode,
9
+ PropertyNode,
10
+ ResponseNode,
11
+ RootNode,
12
+ SchemaNode,
13
+ SchemaNodeByType,
14
+ } from './nodes/index.ts'
2
15
 
3
16
  /**
4
- * Narrows a `SchemaNode` to the specific variant matching `type`.
17
+ * Narrows a `SchemaNode` to the variant that matches `type`.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const schema = createSchema({ type: 'string' })
22
+ * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | undefined
23
+ * ```
5
24
  */
6
25
  export function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | undefined {
7
26
  return node?.type === type ? (node as SchemaNodeByType[T]) : undefined
@@ -12,31 +31,67 @@ function isKind<T extends Node>(kind: NodeKind) {
12
31
  }
13
32
 
14
33
  /**
15
- * Type guard for `RootNode`.
34
+ * Returns `true` when the input is a `RootNode`.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * if (isRootNode(node)) {
39
+ * console.log(node.schemas.length)
40
+ * }
41
+ * ```
16
42
  */
17
43
  export const isRootNode = isKind<RootNode>('Root')
18
44
 
19
45
  /**
20
- * Type guard for `OperationNode`.
46
+ * Returns `true` when the input is an `OperationNode`.
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * if (isOperationNode(node)) {
51
+ * console.log(node.operationId)
52
+ * }
53
+ * ```
21
54
  */
22
55
  export const isOperationNode = isKind<OperationNode>('Operation')
23
56
 
24
57
  /**
25
- * Type guard for `SchemaNode`.
58
+ * Returns `true` when the input is a `SchemaNode`.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * if (isSchemaNode(node)) {
63
+ * console.log(node.type)
64
+ * }
65
+ * ```
26
66
  */
27
67
  export const isSchemaNode = isKind<SchemaNode>('Schema')
28
68
 
29
69
  /**
30
- * Type guard for `PropertyNode`.
70
+ * Returns `true` when the input is a `PropertyNode`.
31
71
  */
32
72
  export const isPropertyNode = isKind<PropertyNode>('Property')
33
73
 
34
74
  /**
35
- * Type guard for `ParameterNode`.
75
+ * Returns `true` when the input is a `ParameterNode`.
36
76
  */
37
77
  export const isParameterNode = isKind<ParameterNode>('Parameter')
38
78
 
39
79
  /**
40
- * Type guard for `ResponseNode`.
80
+ * Returns `true` when the input is a `ResponseNode`.
41
81
  */
42
82
  export const isResponseNode = isKind<ResponseNode>('Response')
83
+
84
+ /**
85
+ * Returns `true` when the input is a `FunctionParameterNode`.
86
+ */
87
+ export const isFunctionParameterNode = isKind<FunctionParameterNode>('FunctionParameter')
88
+
89
+ /**
90
+ * Returns `true` when the input is a `ParameterGroupNode`.
91
+ */
92
+ export const isParameterGroupNode = isKind<ParameterGroupNode>('ParameterGroup')
93
+
94
+ /**
95
+ * Returns `true` when the input is a `FunctionParametersNode`.
96
+ */
97
+ export const isFunctionParametersNode = isKind<FunctionParametersNode>('FunctionParameters')