@kubb/ast 5.0.0-beta.22 → 5.0.0-beta.24

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.22",
3
+ "version": "5.0.0-beta.24",
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/factory.ts CHANGED
@@ -33,10 +33,13 @@ import type {
33
33
  import { combineExports, combineImports, combineSources, extractStringsFromNodes } from './utils.ts'
34
34
 
35
35
  /**
36
- * Syncs property/parameter schema optionality flags from `required` and `schema.nullable`.
36
+ * Updates a schema's `optional` and `nullish` flags from a parent's `required`
37
+ * value and the schema's own `nullable`. Mirrors how OpenAPI parameters and
38
+ * object properties combine "required" and "nullable" into a single AST.
37
39
  *
38
- * - `optional` is set for non-required, non-nullable schemas.
39
- * - `nullish` is set for non-required, nullable schemas.
40
+ * - Non-required + non-nullable → `optional: true`.
41
+ * - Non-required + nullable `nullish: true`.
42
+ * - Required → both flags cleared.
40
43
  */
41
44
  export function syncOptionality(schema: SchemaNode, required: boolean): SchemaNode {
42
45
  const nullable = schema.nullable ?? false
package/src/infer.ts CHANGED
@@ -20,15 +20,25 @@ import type {
20
20
  */
21
21
  export type ParserOptions = {
22
22
  /**
23
- * How `format: 'date-time'` schemas are represented. `false` falls through to a plain string.
23
+ * How `format: 'date-time'` schemas are represented downstream.
24
+ * - `false` falls through to a plain `string` (no validation).
25
+ * - `'string'` emits a datetime string node.
26
+ * - `'stringOffset'` emits a datetime node with timezone offset.
27
+ * - `'stringLocal'` emits a local datetime node.
28
+ * - `'date'` emits a `date` node (JavaScript `Date` object).
24
29
  */
25
30
  dateType: false | 'string' | 'stringOffset' | 'stringLocal' | 'date'
26
31
  /**
27
- * Whether `type: 'integer'` and `format: 'int64'` produce `number` or `bigint` nodes.
32
+ * How `type: 'integer'` (and `format: 'int64'`) maps to TypeScript.
33
+ * - `'number'` fits most JSON APIs; loses precision above `Number.MAX_SAFE_INTEGER`.
34
+ * - `'bigint'` is exact for 64-bit IDs, but does not round-trip through JSON.
35
+ *
36
+ * @default 'number'
28
37
  */
29
38
  integerType?: 'number' | 'bigint'
30
39
  /**
31
- * AST type used when no schema type can be inferred.
40
+ * AST type used when a schema's type cannot be inferred from the spec
41
+ * (`additionalProperties: true`, missing `type`, ...).
32
42
  */
33
43
  unknownType: 'any' | 'unknown' | 'void'
34
44
  /**
@@ -36,7 +46,8 @@ export type ParserOptions = {
36
46
  */
37
47
  emptySchemaType: 'any' | 'unknown' | 'void'
38
48
  /**
39
- * Suffix appended to derived enum names when building property schema names.
49
+ * Suffix appended to derived enum names when Kubb has to invent one
50
+ * (typically for inline enums on object properties).
40
51
  */
41
52
  enumSuffix: 'enum' | (string & {})
42
53
  }
package/src/nodes/code.ts CHANGED
@@ -36,21 +36,21 @@ export type ConstNode = BaseNode & {
36
36
  * Whether the declaration should be exported.
37
37
  * @default false
38
38
  */
39
- export?: boolean
39
+ export?: boolean | null
40
40
  /**
41
41
  * Optional explicit type annotation.
42
42
  * @example 'Pet'
43
43
  */
44
- type?: string
44
+ type?: string | null
45
45
  /**
46
46
  * JSDoc documentation metadata.
47
47
  */
48
- JSDoc?: JSDocNode
48
+ JSDoc?: JSDocNode | null
49
49
  /**
50
50
  * Whether to append `as const` to the declaration.
51
51
  * @default false
52
52
  */
53
- asConst?: boolean
53
+ asConst?: boolean | null
54
54
  /**
55
55
  * Child nodes representing the value of the constant (children of the `Const` component).
56
56
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -83,11 +83,11 @@ export type TypeNode = BaseNode & {
83
83
  * Whether the declaration should be exported.
84
84
  * @default false
85
85
  */
86
- export?: boolean
86
+ export?: boolean | null
87
87
  /**
88
88
  * JSDoc documentation metadata.
89
89
  */
90
- JSDoc?: JSDocNode
90
+ JSDoc?: JSDocNode | null
91
91
  /**
92
92
  * Child nodes representing the type body (children of the `Type` component).
93
93
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -126,35 +126,35 @@ export type FunctionNode = BaseNode & {
126
126
  * Whether the function is a default export.
127
127
  * @default false
128
128
  */
129
- default?: boolean
129
+ default?: boolean | null
130
130
  /**
131
131
  * Function parameter list rendered as a string (e.g. from `FunctionParams.toConstructor()`).
132
132
  */
133
- params?: string
133
+ params?: string | null
134
134
  /**
135
135
  * Whether the function should be exported.
136
136
  * @default false
137
137
  */
138
- export?: boolean
138
+ export?: boolean | null
139
139
  /**
140
140
  * Whether the function is async. When `true`, the return type is wrapped in `Promise<>`.
141
141
  * @default false
142
142
  */
143
- async?: boolean
143
+ async?: boolean | null
144
144
  /**
145
145
  * TypeScript generic type parameters.
146
146
  * @example ['T', 'U extends string']
147
147
  */
148
- generics?: string | string[]
148
+ generics?: string | string[] | null
149
149
  /**
150
150
  * Return type annotation.
151
151
  * @example 'Pet'
152
152
  */
153
- returnType?: string
153
+ returnType?: string | null
154
154
  /**
155
155
  * JSDoc documentation metadata.
156
156
  */
157
- JSDoc?: JSDocNode
157
+ JSDoc?: JSDocNode | null
158
158
  /**
159
159
  * Child nodes representing the function body (children of the `Function` component).
160
160
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -187,40 +187,40 @@ export type ArrowFunctionNode = BaseNode & {
187
187
  * Whether the function is a default export.
188
188
  * @default false
189
189
  */
190
- default?: boolean
190
+ default?: boolean | null
191
191
  /**
192
192
  * Function parameter list rendered as a string (e.g. from `FunctionParams.toConstructor()`).
193
193
  */
194
- params?: string
194
+ params?: string | null
195
195
  /**
196
196
  * Whether the arrow function should be exported.
197
197
  * @default false
198
198
  */
199
- export?: boolean
199
+ export?: boolean | null
200
200
  /**
201
201
  * Whether the arrow function is async. When `true`, the return type is wrapped in `Promise<>`.
202
202
  * @default false
203
203
  */
204
- async?: boolean
204
+ async?: boolean | null
205
205
  /**
206
206
  * TypeScript generic type parameters.
207
207
  * @example ['T', 'U extends string']
208
208
  */
209
- generics?: string | string[]
209
+ generics?: string | string[] | null
210
210
  /**
211
211
  * Return type annotation.
212
212
  * @example 'Pet'
213
213
  */
214
- returnType?: string
214
+ returnType?: string | null
215
215
  /**
216
216
  * JSDoc documentation metadata.
217
217
  */
218
- JSDoc?: JSDocNode
218
+ JSDoc?: JSDocNode | null
219
219
  /**
220
220
  * Render the arrow function body as a single-line expression.
221
221
  * @default false
222
222
  */
223
- singleLine?: boolean
223
+ singleLine?: boolean | null
224
224
  /**
225
225
  * Child nodes representing the function body (children of the `Function.Arrow` component).
226
226
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
package/src/nodes/file.ts CHANGED
@@ -50,18 +50,18 @@ export type ImportNode = BaseNode & {
50
50
  * - `false` generates `import { Type } from './path'`
51
51
  * @default false
52
52
  */
53
- isTypeOnly?: boolean
53
+ isTypeOnly?: boolean | null
54
54
  /**
55
55
  * Import entire module as namespace.
56
56
  * - `true` generates `import * as Name from './path'`
57
57
  * - `false` generates standard import
58
58
  * @default false
59
59
  */
60
- isNameSpace?: boolean
60
+ isNameSpace?: boolean | null
61
61
  /**
62
62
  * When set, the import path is resolved relative to this root.
63
63
  */
64
- root?: string
64
+ root?: string | null
65
65
  }
66
66
 
67
67
  /**
@@ -94,7 +94,7 @@ export type ExportNode = BaseNode & {
94
94
  * @example ['useState']
95
95
  * @example 'React'
96
96
  */
97
- name?: string | Array<string>
97
+ name?: string | Array<string> | null
98
98
  /**
99
99
  * Path for the export.
100
100
  * @example '@kubb/core'
@@ -106,14 +106,14 @@ export type ExportNode = BaseNode & {
106
106
  * - `false` generates `export { Type } from './path'`
107
107
  * @default false
108
108
  */
109
- isTypeOnly?: boolean
109
+ isTypeOnly?: boolean | null
110
110
  /**
111
111
  * Export as an aliased namespace.
112
112
  * - `true` generates `export * as aliasName from './path'`
113
113
  * - `false` generates a standard export
114
114
  * @default false
115
115
  */
116
- asAlias?: boolean
116
+ asAlias?: boolean | null
117
117
  }
118
118
 
119
119
  /**
@@ -134,22 +134,22 @@ export type SourceNode = BaseNode & {
134
134
  /**
135
135
  * Optional name identifying this source (used for deduplication and barrel generation).
136
136
  */
137
- name?: string
137
+ name?: string | null
138
138
  /**
139
139
  * Mark this source as a type-only export.
140
140
  * @default false
141
141
  */
142
- isTypeOnly?: boolean
142
+ isTypeOnly?: boolean | null
143
143
  /**
144
144
  * Include `export` keyword in the generated source.
145
145
  * @default false
146
146
  */
147
- isExportable?: boolean
147
+ isExportable?: boolean | null
148
148
  /**
149
149
  * Include this source in barrel/index file generation.
150
150
  * @default false
151
151
  */
152
- isIndexable?: boolean
152
+ isIndexable?: boolean | null
153
153
  /**
154
154
  * Structured child nodes representing the content of this source fragment, in DOM order.
155
155
  * Each entry is a {@link CodeNode}; use {@link TextNode} for raw string content.
@@ -180,8 +180,8 @@ export type SourceNode = BaseNode & {
180
180
  export type FileNode<TMeta extends object = object> = BaseNode & {
181
181
  kind: 'File'
182
182
  /**
183
- * Unique identifier derived from a SHA256 hash of the file path.
184
- * @default hash
183
+ * Unique identifier derived from a SHA256 hash of the file path. Computed
184
+ * by `createFile`; callers do not need to provide it.
185
185
  */
186
186
  id: string
187
187
  /**
package/src/printer.ts CHANGED
@@ -148,22 +148,27 @@ type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) =
148
148
  print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null
149
149
  }
150
150
  /**
151
- * Creates a schema printer factory.
152
- *
153
- * This function wraps a builder and makes options optional at call sites.
151
+ * Defines a schema printer: a function that takes a `SchemaNode` and emits
152
+ * code in your target language. Each plugin that produces code from schemas
153
+ * (TypeScript types, Zod schemas, Faker factories) ships a printer built
154
+ * with this helper.
154
155
  *
155
156
  * The builder receives resolved options and returns:
156
- * - `name` — a unique identifier for the printer
157
- * - `options` — options stored on the returned printer instance
158
- * - `nodes` — a map of `SchemaType` → handler functions that convert a `SchemaNode` to `TOutput`
159
- * - `print` _(optional)_ — top-level override exposed as `printer.print`
160
- * - Inside this function, use `this.transform(node)` to dispatch to the `nodes` map
161
- * - This keeps recursion safe and avoids self-calls
162
157
  *
163
- * When no `print` override is provided, `printer.print` falls back to `printer.transform` (the node-level dispatcher).
158
+ * - `name` unique identifier for the printer.
159
+ * - `options` — stored on the returned printer instance.
160
+ * - `nodes` — map of `SchemaType` → handler. Handlers return the rendered
161
+ * output (a string, a TypeScript AST node, ...) for that schema type.
162
+ * - `print` (optional) — top-level override exposed as `printer.print`.
163
+ * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.
164
+ *
165
+ * Without a `print` override, `printer.print` falls back to `printer.transform`
166
+ * (the node-level dispatcher).
164
167
  *
165
- * @example Basic usage — Zod schema printer
168
+ * @example Tiny Zod printer
166
169
  * ```ts
170
+ * import { definePrinter, type PrinterFactoryOptions } from '@kubb/ast'
171
+ *
167
172
  * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>
168
173
  *
169
174
  * export const zodPrinter = definePrinter<PrinterZod>((options) => ({
@@ -172,7 +177,9 @@ type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) =
172
177
  * nodes: {
173
178
  * string: () => 'z.string()',
174
179
  * object(node) {
175
- * const props = node.properties.map(p => `${p.name}: ${this.transform(p.schema)}`).join(', ')
180
+ * const props = node.properties
181
+ * .map((p) => `${p.name}: ${this.transform(p.schema)}`)
182
+ * .join(', ')
176
183
  * return `z.object({ ${props} })`
177
184
  * },
178
185
  * },
package/src/utils.ts CHANGED
@@ -556,15 +556,15 @@ function sourceKey(source: SourceNode): string {
556
556
  return `${nameKey}:${source.isExportable ?? false}:${source.isTypeOnly ?? false}`
557
557
  }
558
558
 
559
- function pathTypeKey(path: string, isTypeOnly: boolean | undefined): string {
559
+ function pathTypeKey(path: string, isTypeOnly: boolean | null | undefined): string {
560
560
  return `${path}:${isTypeOnly ?? false}`
561
561
  }
562
562
 
563
- function exportKey(path: string, name: string | undefined, isTypeOnly: boolean | undefined, asAlias: boolean | undefined): string {
563
+ function exportKey(path: string, name: string | null | undefined, isTypeOnly: boolean | null | undefined, asAlias: boolean | null | undefined): string {
564
564
  return `${path}:${name ?? ''}:${isTypeOnly ?? false}:${asAlias ?? ''}`
565
565
  }
566
566
 
567
- function importKey(path: string, name: string | undefined, isTypeOnly: boolean | undefined): string {
567
+ function importKey(path: string, name: string | null | undefined, isTypeOnly: boolean | null | undefined): string {
568
568
  return `${path}:${name ?? ''}:${isTypeOnly ?? false}`
569
569
  }
570
570
 
@@ -572,7 +572,7 @@ function importKey(path: string, name: string | undefined, isTypeOnly: boolean |
572
572
  * Computes a multi-level sort key for exports and imports:
573
573
  * non-array names first (wildcards/namespace aliases); type-only before value; alphabetical path; unnamed before named.
574
574
  */
575
- function sortKey(node: { name?: string | Array<unknown>; isTypeOnly?: boolean; path: string }): string {
575
+ function sortKey(node: { name?: string | Array<unknown> | null; isTypeOnly?: boolean | null; path: string }): string {
576
576
  const isArray = Array.isArray(node.name) ? '1' : '0'
577
577
  const typeOnly = node.isTypeOnly ? '0' : '1'
578
578
  const hasName = node.name != null ? '1' : '0'
package/src/visitor.ts CHANGED
@@ -115,25 +115,40 @@ export type VisitorContext<T extends Node = Node> = {
115
115
  }
116
116
 
117
117
  /**
118
- * Synchronous visitor used by `transform`.
118
+ * Synchronous visitor consumed by `transform`. Each optional callback runs
119
+ * for the matching node type. Return a new node to replace it, or `undefined`
120
+ * to leave it untouched.
119
121
  *
120
- * @example
122
+ * Plugins typically expose `transformer` so users can supply a `Visitor` that
123
+ * rewrites operation IDs, drops descriptions, or otherwise tweaks the AST
124
+ * before printing.
125
+ *
126
+ * @example Prefix every operationId
121
127
  * ```ts
122
128
  * const visitor: Visitor = {
123
129
  * operation(node) {
124
- * return { ...node, operationId: `x_${node.operationId}` }
130
+ * return { ...node, operationId: `api_${node.operationId}` }
131
+ * },
132
+ * }
133
+ * ```
134
+ *
135
+ * @example Strip schema descriptions
136
+ * ```ts
137
+ * const visitor: Visitor = {
138
+ * schema(node) {
139
+ * return { ...node, description: undefined }
125
140
  * },
126
141
  * }
127
142
  * ```
128
143
  */
129
144
  export type Visitor = {
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
145
+ input?(node: InputNode, context: VisitorContext<InputNode>): undefined | null | InputNode
146
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): undefined | null | OutputNode
147
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): undefined | null | OperationNode
148
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): undefined | null | SchemaNode
149
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): undefined | null | PropertyNode
150
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): undefined | null | ParameterNode
151
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): undefined | null | ResponseNode
137
152
  }
138
153
 
139
154
  /**
@@ -154,13 +169,13 @@ type MaybePromise<T> = T | Promise<T>
154
169
  * ```
155
170
  */
156
171
  export type AsyncVisitor = {
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>
172
+ input?(node: InputNode, context: VisitorContext<InputNode>): MaybePromise<undefined | null | InputNode>
173
+ output?(node: OutputNode, context: VisitorContext<OutputNode>): MaybePromise<undefined | null | OutputNode>
174
+ operation?(node: OperationNode, context: VisitorContext<OperationNode>): MaybePromise<undefined | null | OperationNode>
175
+ schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): MaybePromise<undefined | null | SchemaNode>
176
+ property?(node: PropertyNode, context: VisitorContext<PropertyNode>): MaybePromise<undefined | null | PropertyNode>
177
+ parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): MaybePromise<undefined | null | ParameterNode>
178
+ response?(node: ResponseNode, context: VisitorContext<ResponseNode>): MaybePromise<undefined | null | ResponseNode>
164
179
  }
165
180
 
166
181
  /**
@@ -310,11 +325,14 @@ function* getChildren(node: Node, recurse: boolean): Generator<Node, void, undef
310
325
  }
311
326
 
312
327
  /**
313
- * Depth-first traversal for side effects. Visitor return values are ignored.
314
- * Sibling nodes at each level are visited concurrently up to `options.concurrency`
315
- * (default: `WALK_CONCURRENCY`).
328
+ * Async depth-first traversal for side effects. Visitor return values are
329
+ * ignored. Use `transform` when you want to rewrite nodes.
316
330
  *
317
- * @example
331
+ * Sibling nodes at each depth run concurrently up to `options.concurrency`
332
+ * (defaults to `WALK_CONCURRENCY`). Higher values overlap I/O-bound visitor
333
+ * work; lower values reduce memory pressure.
334
+ *
335
+ * @example Log every operation
318
336
  * ```ts
319
337
  * await walk(root, {
320
338
  * operation(node) {
@@ -323,10 +341,9 @@ function* getChildren(node: Node, recurse: boolean): Generator<Node, void, undef
323
341
  * })
324
342
  * ```
325
343
  *
326
- * @example
344
+ * @example Only visit the root node
327
345
  * ```ts
328
- * // Visit only the current node
329
- * await walk(root, { depth: 'shallow', root: () => {} })
346
+ * await walk(root, { depth: 'shallow', input: () => {} })
330
347
  * ```
331
348
  */
332
349
  export async function walk(node: Node, options: WalkOptions): Promise<void> {
@@ -368,12 +385,13 @@ async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit:
368
385
  }
369
386
 
370
387
  /**
371
- * Runs a depth-first immutable transform.
388
+ * Synchronous depth-first transform. Each visitor callback gets a chance to
389
+ * return a replacement node; `undefined` keeps the original.
372
390
  *
373
- * If a visitor returns a node, it replaces the current node.
374
- * If it returns `undefined`, the current node stays the same.
391
+ * The transform is immutable. The original tree is not mutated; a new tree
392
+ * is returned. Use `depth: 'shallow'` to skip recursion into children.
375
393
  *
376
- * @example
394
+ * @example Prefix every operationId
377
395
  * ```ts
378
396
  * const next = transform(root, {
379
397
  * operation(node) {
@@ -382,10 +400,12 @@ async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit:
382
400
  * })
383
401
  * ```
384
402
  *
385
- * @example
403
+ * @example Replace only the root node
386
404
  * ```ts
387
- * // Shallow mode: only transform the input node
388
- * const next = transform(root, { depth: 'shallow', root: (node) => node })
405
+ * const next = transform(root, {
406
+ * depth: 'shallow',
407
+ * input: (node) => ({ ...node, meta: { ...node.meta, title: 'Rewritten' } }),
408
+ * })
389
409
  * ```
390
410
  */
391
411
  export function transform(node: InputNode, options: TransformOptions): InputNode
@@ -485,23 +505,19 @@ export function transform(node: Node, options: TransformOptions): Node {
485
505
  return node
486
506
  }
487
507
  /**
488
- * Runs a depth-first synchronous collection pass.
489
- *
490
- * Non-`null` values returned by visitor callbacks are appended to the result.
508
+ * Lazy depth-first collection pass. Yields every non-null value returned by
509
+ * the visitor callbacks. Use `collect` for the eager array form.
491
510
  *
492
- * @example
511
+ * @example Collect every operationId
493
512
  * ```ts
494
- * const ids = collect(root, {
513
+ * const ids: string[] = []
514
+ * for (const id of collectLazy<string>(root, {
495
515
  * operation(node) {
496
516
  * return node.operationId
497
517
  * },
498
- * })
499
- * ```
500
- *
501
- * @example
502
- * ```ts
503
- * // Collect from only the current node
504
- * const values = collect(root, { depth: 'shallow', root: () => 'root' })
518
+ * })) {
519
+ * ids.push(id)
520
+ * }
505
521
  * ```
506
522
  */
507
523
  export function* collectLazy<T>(node: Node, options: CollectOptions<T>): Generator<T, void, undefined> {
@@ -539,6 +555,19 @@ export function* collectLazy<T>(node: Node, options: CollectOptions<T>): Generat
539
555
  }
540
556
  }
541
557
 
558
+ /**
559
+ * Eager depth-first collection pass. Returns an array of every non-null value
560
+ * the visitor callbacks return.
561
+ *
562
+ * @example Collect every operationId
563
+ * ```ts
564
+ * const ids = collect<string>(root, {
565
+ * operation(node) {
566
+ * return node.operationId
567
+ * },
568
+ * })
569
+ * ```
570
+ */
542
571
  export function collect<T>(node: Node, options: CollectOptions<T>): Array<T> {
543
572
  return Array.from(collectLazy(node, options))
544
573
  }