@kubb/ast 5.0.0-alpha.4 → 5.0.0-alpha.40

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/src/visitor.ts CHANGED
@@ -1,7 +1,22 @@
1
1
  import type { VisitorDepth } from './constants.ts'
2
2
  import { visitorDepths, WALK_CONCURRENCY } from './constants.ts'
3
- import type { Node, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode } from './nodes/index.ts'
3
+ import { createParameter, createProperty } from './factory.ts'
4
+ import type { InputNode, Node, OperationNode, OutputNode, ParameterNode, PropertyNode, ResponseNode, SchemaNode } from './nodes/index.ts'
4
5
 
6
+ /**
7
+ * Creates a small async concurrency limiter.
8
+ *
9
+ * At most `concurrency` tasks are in flight at once. Extra tasks are queued.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const limit = createLimit(2)
14
+ * for (const task of [taskA, taskB, taskC]) {
15
+ * await limit(() => task())
16
+ * }
17
+ * // only 2 tasks run at the same time
18
+ * ```
19
+ */
5
20
  function createLimit(concurrency: number) {
6
21
  let active = 0
7
22
  const queue: Array<() => void> = []
@@ -31,64 +46,233 @@ function createLimit(concurrency: number) {
31
46
  type LimitFn = ReturnType<typeof createLimit>
32
47
 
33
48
  /**
34
- * Shared options for `walk`, `transform`, and `collect`.
49
+ * Ordered mapping of `[NodeType, ParentType]` pairs.
50
+ *
51
+ * `ParentOf` uses this map to find parent types.
35
52
  */
36
- export type VisitorOptions = {
37
- depth?: VisitorDepth
53
+ type ParentNodeMap = [
54
+ [InputNode, undefined],
55
+ [OutputNode, undefined],
56
+ [OperationNode, InputNode],
57
+ [SchemaNode, InputNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode],
58
+ [PropertyNode, SchemaNode],
59
+ [ParameterNode, OperationNode],
60
+ [ResponseNode, OperationNode],
61
+ ]
62
+
63
+ /**
64
+ * Resolves the parent node type for a given AST node type.
65
+ *
66
+ * This is used by visitor context so `ctx.parent` is correctly typed
67
+ * for each callback.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * type InputParent = ParentOf<InputNode>
72
+ * // undefined
73
+ * ```
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * type PropertyParent = ParentOf<PropertyNode>
78
+ * // SchemaNode
79
+ * ```
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * type SchemaParent = ParentOf<SchemaNode>
84
+ * // InputNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode
85
+ * ```
86
+ */
87
+ export type ParentOf<T extends Node, TEntries extends ReadonlyArray<[Node, unknown]> = ParentNodeMap> = TEntries extends [
88
+ infer TEntry extends [Node, unknown],
89
+ ...infer TRest extends ReadonlyArray<[Node, unknown]>,
90
+ ]
91
+ ? T extends TEntry[0]
92
+ ? TEntry[1]
93
+ : ParentOf<T, TRest>
94
+ : Node
95
+
96
+ /**
97
+ * Traversal context passed as the second argument to every visitor callback.
98
+ * `parent` is typed from the current node type.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const visitor: Visitor = {
103
+ * schema(node, { parent }) {
104
+ * // parent type is narrowed by node kind
105
+ * },
106
+ * }
107
+ * ```
108
+ */
109
+ export type VisitorContext<T extends Node = Node> = {
38
110
  /**
39
- * Maximum number of sibling nodes visited concurrently inside `walk`.
40
- * @default 30
111
+ * Parent node of the currently visited node.
112
+ * For `InputNode`, this is `undefined`.
41
113
  */
42
- concurrency?: number
114
+ parent?: ParentOf<T>
43
115
  }
44
116
 
45
117
  /**
46
- * Synchronous visitor for `transform` and `walk`.
118
+ * Synchronous visitor used by `transform`.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * const visitor: Visitor = {
123
+ * operation(node) {
124
+ * return { ...node, operationId: `x_${node.operationId}` }
125
+ * },
126
+ * }
127
+ * ```
47
128
  */
48
129
  export type Visitor = {
49
- root?(node: RootNode): void | RootNode
50
- operation?(node: OperationNode): void | OperationNode
51
- schema?(node: SchemaNode): void | SchemaNode
52
- property?(node: PropertyNode): void | PropertyNode
53
- parameter?(node: ParameterNode): void | ParameterNode
54
- response?(node: ResponseNode): void | ResponseNode
130
+ input?(node: InputNode, context: VisitorContext<InputNode>): void | InputNode
131
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): void | OutputNode
132
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): void | OperationNode
133
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): void | SchemaNode
134
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): void | PropertyNode
135
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): void | ParameterNode
136
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): void | ResponseNode
55
137
  }
56
138
 
139
+ /**
140
+ * Utility type for values that can be returned directly or asynchronously.
141
+ */
57
142
  type MaybePromise<T> = T | Promise<T>
58
143
 
59
144
  /**
60
145
  * Async visitor for `walk`. Synchronous `Visitor` objects are compatible.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * const visitor: AsyncVisitor = {
150
+ * async operation(node) {
151
+ * await Promise.resolve(node.operationId)
152
+ * },
153
+ * }
154
+ * ```
61
155
  */
62
156
  export type AsyncVisitor = {
63
- root?(node: RootNode): MaybePromise<void | RootNode>
64
- operation?(node: OperationNode): MaybePromise<void | OperationNode>
65
- schema?(node: SchemaNode): MaybePromise<void | SchemaNode>
66
- property?(node: PropertyNode): MaybePromise<void | PropertyNode>
67
- parameter?(node: ParameterNode): MaybePromise<void | ParameterNode>
68
- response?(node: ResponseNode): MaybePromise<void | ResponseNode>
157
+ input?(node: InputNode, context: VisitorContext<InputNode>): MaybePromise<void | InputNode>
158
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): MaybePromise<void | OutputNode>
159
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): MaybePromise<void | OperationNode>
160
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): MaybePromise<void | SchemaNode>
161
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): MaybePromise<void | PropertyNode>
162
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): MaybePromise<void | ParameterNode>
163
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): MaybePromise<void | ResponseNode>
69
164
  }
70
165
 
71
166
  /**
72
- * Visitor for `collect`.
167
+ * Visitor used by `collect`.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * const visitor: CollectVisitor<string> = {
172
+ * operation(node) {
173
+ * return node.operationId
174
+ * },
175
+ * }
176
+ * ```
73
177
  */
74
178
  export type CollectVisitor<T> = {
75
- root?(node: RootNode): T | undefined
76
- operation?(node: OperationNode): T | undefined
77
- schema?(node: SchemaNode): T | undefined
78
- property?(node: PropertyNode): T | undefined
79
- parameter?(node: ParameterNode): T | undefined
80
- response?(node: ResponseNode): T | undefined
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
81
186
  }
82
187
 
83
188
  /**
84
- * Traversable children of `node`, respecting `recurse` for schema nodes.
189
+ * Options for `transform`.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * const options: TransformOptions = { depth: 'deep', schema: (node) => node }
194
+ * ```
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * // Only transform the current node, not nested children
199
+ * const options: TransformOptions = { depth: 'shallow', schema: (node) => node }
200
+ * ```
201
+ */
202
+ export type TransformOptions = Visitor & {
203
+ /**
204
+ * Traversal depth (`'deep'` by default).
205
+ * @default 'deep'
206
+ */
207
+ depth?: VisitorDepth
208
+ /**
209
+ * Internal parent override used during recursion.
210
+ */
211
+ parent?: Node
212
+ }
213
+
214
+ /**
215
+ * Options for `walk`.
216
+ *
217
+ * @example
218
+ * ```ts
219
+ * const options: WalkOptions = { depth: 'deep', concurrency: 10, root: () => {} }
220
+ * ```
221
+ */
222
+ export type WalkOptions = AsyncVisitor & {
223
+ /**
224
+ * Traversal depth (`'deep'` by default).
225
+ * @default 'deep'
226
+ */
227
+ depth?: VisitorDepth
228
+ /**
229
+ * Maximum number of sibling nodes visited concurrently.
230
+ * @default 30
231
+ */
232
+ concurrency?: number
233
+ }
234
+
235
+ /**
236
+ * Options for `collect`.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * const options: CollectOptions<string> = { depth: 'shallow', schema: () => undefined }
241
+ * ```
242
+ */
243
+ export type CollectOptions<T> = CollectVisitor<T> & {
244
+ /**
245
+ * Traversal depth (`'deep'` by default).
246
+ * @default 'deep'
247
+ */
248
+ depth?: VisitorDepth
249
+ /**
250
+ * Internal parent override used during recursion.
251
+ */
252
+ parent?: Node
253
+ }
254
+
255
+ /**
256
+ * Returns the immediate traversable children of `node`.
257
+ *
258
+ * For `Schema` nodes, children (`properties`, `items`, `members`, and non-boolean
259
+ * `additionalProperties`) are only included
260
+ * when `recurse` is `true`; shallow mode skips them.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * const children = getChildren(operationNode, true)
265
+ * // returns parameters, requestBody schema (if present), and responses
266
+ * ```
85
267
  */
86
268
  function getChildren(node: Node, recurse: boolean): Array<Node> {
87
269
  switch (node.kind) {
88
- case 'Root':
270
+ case 'Input':
89
271
  return [...node.schemas, ...node.operations]
272
+ case 'Output':
273
+ return []
90
274
  case 'Operation':
91
- return [...node.parameters, ...(node.requestBody ? [node.requestBody] : []), ...node.responses]
275
+ return [...node.parameters, ...(node.requestBody?.schema ? [node.requestBody.schema] : []), ...node.responses]
92
276
  case 'Schema': {
93
277
  const children: Array<Node> = []
94
278
 
@@ -97,6 +281,7 @@ function getChildren(node: Node, recurse: boolean): Array<Node> {
97
281
  if ('properties' in node && node.properties.length > 0) children.push(...node.properties)
98
282
  if ('items' in node && node.items) children.push(...node.items)
99
283
  if ('members' in node && node.members) children.push(...node.members)
284
+ if ('additionalProperties' in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties)
100
285
 
101
286
  return children
102
287
  }
@@ -106,159 +291,257 @@ function getChildren(node: Node, recurse: boolean): Array<Node> {
106
291
  return [node.schema]
107
292
  case 'Response':
108
293
  return node.schema ? [node.schema] : []
294
+ case 'FunctionParameter':
295
+ case 'ParameterGroup':
296
+ case 'FunctionParameters':
297
+ case 'Type':
298
+ return []
299
+ default:
300
+ return []
109
301
  }
110
302
  }
111
303
 
112
304
  /**
113
305
  * Depth-first traversal for side effects. Visitor return values are ignored.
114
- * Sibling nodes at each level are visited concurrently up to `options.concurrency` (default: 30).
306
+ * Sibling nodes at each level are visited concurrently up to `options.concurrency`
307
+ * (default: `WALK_CONCURRENCY`).
308
+ *
309
+ * @example
310
+ * ```ts
311
+ * await walk(root, {
312
+ * operation(node) {
313
+ * console.log(node.operationId)
314
+ * },
315
+ * })
316
+ * ```
317
+ *
318
+ * @example
319
+ * ```ts
320
+ * // Visit only the current node
321
+ * await walk(root, { depth: 'shallow', root: () => {} })
322
+ * ```
115
323
  */
116
- export async function walk(node: Node, visitor: AsyncVisitor, options: VisitorOptions = {}): Promise<void> {
324
+ export async function walk(node: Node, options: WalkOptions): Promise<void> {
117
325
  const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep
118
326
  const limit = createLimit(options.concurrency ?? WALK_CONCURRENCY)
119
- return _walk(node, visitor, recurse, limit)
327
+
328
+ return _walk(node, options, recurse, limit, undefined)
120
329
  }
121
330
 
122
- async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit: LimitFn): Promise<void> {
331
+ async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit: LimitFn, parent: Node | undefined): Promise<void> {
123
332
  switch (node.kind) {
124
- case 'Root':
125
- await limit(() => visitor.root?.(node))
333
+ case 'Input':
334
+ await limit(() => visitor.input?.(node, { parent: parent as ParentOf<InputNode> }))
335
+ break
336
+ case 'Output':
337
+ await limit(() => visitor.output?.(node, { parent: parent as ParentOf<OutputNode> }))
126
338
  break
127
339
  case 'Operation':
128
- await limit(() => visitor.operation?.(node))
340
+ await limit(() => visitor.operation?.(node, { parent: parent as ParentOf<OperationNode> }))
129
341
  break
130
342
  case 'Schema':
131
- await limit(() => visitor.schema?.(node))
343
+ await limit(() => visitor.schema?.(node, { parent: parent as ParentOf<SchemaNode> }))
132
344
  break
133
345
  case 'Property':
134
- await limit(() => visitor.property?.(node))
346
+ await limit(() => visitor.property?.(node, { parent: parent as ParentOf<PropertyNode> }))
135
347
  break
136
348
  case 'Parameter':
137
- await limit(() => visitor.parameter?.(node))
349
+ await limit(() => visitor.parameter?.(node, { parent: parent as ParentOf<ParameterNode> }))
138
350
  break
139
351
  case 'Response':
140
- await limit(() => visitor.response?.(node))
352
+ await limit(() => visitor.response?.(node, { parent: parent as ParentOf<ResponseNode> }))
353
+ break
354
+ case 'FunctionParameter':
355
+ case 'ParameterGroup':
356
+ case 'FunctionParameters':
141
357
  break
142
358
  }
143
359
 
144
360
  const children = getChildren(node, recurse)
145
- await Promise.all(children.map((child) => _walk(child, visitor, recurse, limit)))
361
+ for (const child of children) {
362
+ await _walk(child, visitor, recurse, limit, node)
363
+ }
146
364
  }
147
365
 
148
366
  /**
149
- * Depth-first immutable transformation. Visitor return values replace nodes; `undefined` keeps the original.
367
+ * Runs a depth-first immutable transform.
368
+ *
369
+ * If a visitor returns a node, it replaces the current node.
370
+ * If it returns `undefined`, the current node stays the same.
371
+ *
372
+ * @example
373
+ * ```ts
374
+ * const next = transform(root, {
375
+ * operation(node) {
376
+ * return { ...node, operationId: `prefixed_${node.operationId}` }
377
+ * },
378
+ * })
379
+ * ```
380
+ *
381
+ * @example
382
+ * ```ts
383
+ * // Shallow mode: only transform the input node
384
+ * const next = transform(root, { depth: 'shallow', root: (node) => node })
385
+ * ```
150
386
  */
151
- export function transform(node: RootNode, visitor: Visitor, options?: VisitorOptions): RootNode
152
- export function transform(node: OperationNode, visitor: Visitor, options?: VisitorOptions): OperationNode
153
- export function transform(node: SchemaNode, visitor: Visitor, options?: VisitorOptions): SchemaNode
154
- export function transform(node: PropertyNode, visitor: Visitor, options?: VisitorOptions): PropertyNode
155
- export function transform(node: ParameterNode, visitor: Visitor, options?: VisitorOptions): ParameterNode
156
- export function transform(node: ResponseNode, visitor: Visitor, options?: VisitorOptions): ResponseNode
157
- export function transform(node: Node, visitor: Visitor, options?: VisitorOptions): Node
158
- export function transform(node: Node, visitor: Visitor, options: VisitorOptions = {}): Node {
159
- const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep
387
+ export function transform(node: InputNode, options: TransformOptions): InputNode
388
+ export function transform(node: OutputNode, options: TransformOptions): OutputNode
389
+ export function transform(node: OperationNode, options: TransformOptions): OperationNode
390
+ export function transform(node: SchemaNode, options: TransformOptions): SchemaNode
391
+ export function transform(node: PropertyNode, options: TransformOptions): PropertyNode
392
+ export function transform(node: ParameterNode, options: TransformOptions): ParameterNode
393
+ export function transform(node: ResponseNode, options: TransformOptions): ResponseNode
394
+ export function transform(node: Node, options: TransformOptions): Node
395
+ export function transform(node: Node, options: TransformOptions): Node {
396
+ const { depth, parent, ...visitor } = options
397
+ const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep
160
398
 
161
399
  switch (node.kind) {
162
- case 'Root': {
163
- let root = node
164
- const replaced = visitor.root?.(root)
165
- if (replaced) root = replaced
400
+ case 'Input': {
401
+ let input = node
402
+ const replaced = visitor.input?.(input, { parent: parent as ParentOf<InputNode> })
403
+ if (replaced) input = replaced
166
404
 
167
405
  return {
168
- ...root,
169
- schemas: root.schemas.map((s) => transform(s, visitor, options)),
170
- operations: root.operations.map((op) => transform(op, visitor, options)),
406
+ ...input,
407
+ schemas: input.schemas.map((s) => transform(s, { ...options, parent: input })),
408
+ operations: input.operations.map((op) => transform(op, { ...options, parent: input })),
171
409
  }
172
410
  }
411
+ case 'Output': {
412
+ let output = node
413
+ const replaced = visitor.output?.(output, { parent: parent as ParentOf<OutputNode> })
414
+ if (replaced) output = replaced
415
+
416
+ return output
417
+ }
173
418
  case 'Operation': {
174
419
  let op = node
175
- const replaced = visitor.operation?.(op)
420
+ const replaced = visitor.operation?.(op, { parent: parent as ParentOf<OperationNode> })
176
421
  if (replaced) op = replaced
177
422
 
178
423
  return {
179
424
  ...op,
180
- parameters: op.parameters.map((p) => transform(p, visitor, options)),
181
- requestBody: op.requestBody ? transform(op.requestBody, visitor, options) : undefined,
182
- responses: op.responses.map((r) => transform(r, visitor, options)),
425
+ parameters: op.parameters.map((p) => transform(p, { ...options, parent: op })),
426
+ requestBody: op.requestBody
427
+ ? { ...op.requestBody, schema: op.requestBody.schema ? transform(op.requestBody.schema, { ...options, parent: op }) : undefined }
428
+ : undefined,
429
+ responses: op.responses.map((r) => transform(r, { ...options, parent: op })),
183
430
  }
184
431
  }
185
432
  case 'Schema': {
186
433
  let schema = node
187
- const replaced = visitor.schema?.(schema)
434
+ const replaced = visitor.schema?.(schema, { parent: parent as ParentOf<SchemaNode> })
188
435
  if (replaced) schema = replaced
189
436
 
437
+ const childOptions = { ...options, parent: schema }
438
+
190
439
  return {
191
440
  ...schema,
192
- ...('properties' in schema && recurse ? { properties: schema.properties.map((p) => transform(p, visitor, options)) } : {}),
193
- ...('items' in schema && recurse ? { items: schema.items?.map((i) => transform(i, visitor, options)) } : {}),
194
- ...('members' in schema && recurse ? { members: schema.members?.map((m) => transform(m, visitor, options)) } : {}),
195
- }
441
+ ...('properties' in schema && recurse ? { properties: schema.properties.map((p) => transform(p, childOptions)) } : {}),
442
+ ...('items' in schema && recurse ? { items: schema.items?.map((i) => transform(i, childOptions)) } : {}),
443
+ ...('members' in schema && recurse ? { members: schema.members?.map((m) => transform(m, childOptions)) } : {}),
444
+ ...('additionalProperties' in schema && recurse && schema.additionalProperties && schema.additionalProperties !== true
445
+ ? { additionalProperties: transform(schema.additionalProperties, childOptions) }
446
+ : {}),
447
+ } as SchemaNode
196
448
  }
197
449
  case 'Property': {
198
450
  let prop = node
199
- const replaced = visitor.property?.(prop)
451
+ const replaced = visitor.property?.(prop, { parent: parent as ParentOf<PropertyNode> })
200
452
  if (replaced) prop = replaced
201
453
 
202
- return {
454
+ return createProperty({
203
455
  ...prop,
204
- schema: transform(prop.schema, visitor, options),
205
- }
456
+ schema: transform(prop.schema, { ...options, parent: prop }),
457
+ })
206
458
  }
207
459
  case 'Parameter': {
208
460
  let param = node
209
- const replaced = visitor.parameter?.(param)
461
+ const replaced = visitor.parameter?.(param, { parent: parent as ParentOf<ParameterNode> })
210
462
  if (replaced) param = replaced
211
463
 
212
- return {
464
+ return createParameter({
213
465
  ...param,
214
- schema: transform(param.schema, visitor, options),
215
- }
466
+ schema: transform(param.schema, { ...options, parent: param }),
467
+ })
216
468
  }
217
469
  case 'Response': {
218
470
  let response = node
219
- const replaced = visitor.response?.(response)
471
+ const replaced = visitor.response?.(response, { parent: parent as ParentOf<ResponseNode> })
220
472
  if (replaced) response = replaced
221
473
 
222
474
  return {
223
475
  ...response,
224
- schema: response.schema ? transform(response.schema, visitor, options) : undefined,
476
+ schema: transform(response.schema, { ...options, parent: response }),
225
477
  }
226
478
  }
479
+ case 'FunctionParameter':
480
+ case 'ParameterGroup':
481
+ case 'FunctionParameters':
482
+ case 'Type':
483
+ return node
484
+ default:
485
+ return node
227
486
  }
228
487
  }
229
-
230
488
  /**
231
- * Depth-first synchronous reduction. Collects non-`undefined` visitor return values into an array.
489
+ * Runs a depth-first synchronous collection pass.
490
+ *
491
+ * Non-`undefined` values returned by visitor callbacks are appended to the result.
492
+ *
493
+ * @example
494
+ * ```ts
495
+ * const ids = collect(root, {
496
+ * operation(node) {
497
+ * return node.operationId
498
+ * },
499
+ * })
500
+ * ```
501
+ *
502
+ * @example
503
+ * ```ts
504
+ * // Collect from only the current node
505
+ * const values = collect(root, { depth: 'shallow', root: () => 'root' })
506
+ * ```
232
507
  */
233
- export function collect<T>(node: Node, visitor: CollectVisitor<T>, options: VisitorOptions = {}): Array<T> {
234
- const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep
508
+ export function collect<T>(node: Node, options: CollectOptions<T>): Array<T> {
509
+ const { depth, parent, ...visitor } = options
510
+ const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep
235
511
  const results: Array<T> = []
236
512
 
237
513
  let v: T | undefined
238
514
  switch (node.kind) {
239
- case 'Root':
240
- v = visitor.root?.(node)
515
+ case 'Input':
516
+ v = visitor.input?.(node, { parent: parent as ParentOf<InputNode> })
517
+ break
518
+ case 'Output':
519
+ v = visitor.output?.(node, { parent: parent as ParentOf<OutputNode> })
241
520
  break
242
521
  case 'Operation':
243
- v = visitor.operation?.(node)
522
+ v = visitor.operation?.(node, { parent: parent as ParentOf<OperationNode> })
244
523
  break
245
524
  case 'Schema':
246
- v = visitor.schema?.(node)
525
+ v = visitor.schema?.(node, { parent: parent as ParentOf<SchemaNode> })
247
526
  break
248
527
  case 'Property':
249
- v = visitor.property?.(node)
528
+ v = visitor.property?.(node, { parent: parent as ParentOf<PropertyNode> })
250
529
  break
251
530
  case 'Parameter':
252
- v = visitor.parameter?.(node)
531
+ v = visitor.parameter?.(node, { parent: parent as ParentOf<ParameterNode> })
253
532
  break
254
533
  case 'Response':
255
- v = visitor.response?.(node)
534
+ v = visitor.response?.(node, { parent: parent as ParentOf<ResponseNode> })
535
+ break
536
+ case 'FunctionParameter':
537
+ case 'ParameterGroup':
538
+ case 'FunctionParameters':
256
539
  break
257
540
  }
258
541
  if (v !== undefined) results.push(v)
259
542
 
260
543
  for (const child of getChildren(node, recurse)) {
261
- for (const item of collect(child, visitor, options)) {
544
+ for (const item of collect(child, { ...options, parent: node })) {
262
545
  results.push(item)
263
546
  }
264
547
  }
package/dist/types.cjs DELETED
File without changes
package/dist/types.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { $ as UnionSchemaNode, A as MediaType, B as IntersectionSchemaNode, C as Node, D as OperationNode, E as HttpMethod, F as ComplexSchemaType, G as ScalarSchemaNode, H as ObjectSchemaNode, I as DateSchemaNode, J as SchemaNodeByType, K as ScalarSchemaType, L as DatetimeSchemaNode, M as ParameterLocation, N as ParameterNode, O as ResponseNode, P as ArraySchemaNode, Q as TimeSchemaNode, R as EnumSchemaNode, T as RootNode, U as PrimitiveSchemaType, V as NumberSchemaNode, W as RefSchemaNode, X as SpecialSchemaType, Y as SchemaType, Z as StringSchemaNode, d as Printer, et as PropertyNode, f as PrinterFactoryOptions, g as DistributiveOmit, j as StatusCode, k as HttpStatusCode, m as PrinterHandlerContext, n as CollectVisitor, nt as NodeKind, p as PrinterHandler, q as SchemaNode, r as Visitor, rt as VisitorDepth, s as RefMap, t as AsyncVisitor, tt as BaseNode, w as RootMeta, z as EnumValueNode } from "./visitor-oFfdU8QA.js";
2
- export { type ArraySchemaNode, type AsyncVisitor, type BaseNode, type CollectVisitor, type ComplexSchemaType, type DateSchemaNode, type DatetimeSchemaNode, type DistributiveOmit, type EnumSchemaNode, type EnumValueNode, type HttpMethod, type HttpStatusCode, type IntersectionSchemaNode, type MediaType, type Node, type NodeKind, type NumberSchemaNode, type ObjectSchemaNode, type OperationNode, type ParameterLocation, type ParameterNode, type PrimitiveSchemaType, type Printer, type PrinterFactoryOptions, type PrinterHandler, type PrinterHandlerContext, type PropertyNode, type RefMap, type RefSchemaNode, type ResponseNode, type RootMeta, type RootNode, type ScalarSchemaNode, type ScalarSchemaType, type SchemaNode, type SchemaNodeByType, type SchemaType, type SpecialSchemaType, type StatusCode, type StringSchemaNode, type TimeSchemaNode, type UnionSchemaNode, type Visitor, type VisitorDepth };
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- export {};