@kubb/ast 5.0.0-beta.58 → 5.0.0-beta.59

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.
Files changed (67) hide show
  1. package/README.md +10 -0
  2. package/dist/casing-BE2R1RXg.cjs +88 -0
  3. package/dist/casing-BE2R1RXg.cjs.map +1 -0
  4. package/dist/extractStringsFromNodes-WMYJ8nQL.d.ts +82 -0
  5. package/dist/factory-BmcGBdeg.cjs +1251 -0
  6. package/dist/factory-BmcGBdeg.cjs.map +1 -0
  7. package/dist/factory-Du7nEP4B.js +282 -0
  8. package/dist/factory-Du7nEP4B.js.map +1 -0
  9. package/dist/factory.cjs +25 -28
  10. package/dist/factory.d.ts +3 -3
  11. package/dist/factory.js +3 -3
  12. package/dist/{ast-ClnJg9BN.d.ts → index-BzjwdK2M.d.ts} +74 -372
  13. package/dist/index.cjs +445 -46
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +94 -59
  16. package/dist/index.js +7 -113
  17. package/dist/index.js.map +1 -1
  18. package/dist/operationParams-BZ07xDm0.d.ts +204 -0
  19. package/dist/response-DKxTr522.js +683 -0
  20. package/dist/response-DKxTr522.js.map +1 -0
  21. package/dist/{types-CB2oY8Dw.d.ts → types-olVl9v5p.d.ts} +222 -227
  22. package/dist/types.d.ts +4 -3
  23. package/dist/utils-BCtRXfhI.cjs +275 -0
  24. package/dist/utils-BCtRXfhI.cjs.map +1 -0
  25. package/dist/{utils-DN4XLVqz.js → utils-SdZU0F3H.js} +472 -1235
  26. package/dist/utils-SdZU0F3H.js.map +1 -0
  27. package/dist/utils.cjs +127 -22
  28. package/dist/utils.d.ts +112 -80
  29. package/dist/utils.js +3 -2
  30. package/package.json +1 -1
  31. package/src/constants.ts +8 -14
  32. package/src/dedupe.ts +8 -0
  33. package/src/factory.ts +1 -2
  34. package/src/guards.ts +1 -1
  35. package/src/index.ts +4 -13
  36. package/src/nodes/code.ts +29 -47
  37. package/src/nodes/content.ts +2 -2
  38. package/src/nodes/file.ts +28 -23
  39. package/src/nodes/function.ts +0 -15
  40. package/src/nodes/input.ts +6 -6
  41. package/src/nodes/operation.ts +1 -1
  42. package/src/nodes/parameter.ts +0 -3
  43. package/src/nodes/property.ts +0 -3
  44. package/src/nodes/requestBody.ts +3 -6
  45. package/src/nodes/schema.ts +3 -2
  46. package/src/printer.ts +1 -1
  47. package/src/registry.ts +31 -26
  48. package/src/signature.ts +3 -3
  49. package/src/transformers.ts +28 -1
  50. package/src/types.ts +2 -53
  51. package/src/utils/codegen.ts +104 -0
  52. package/src/utils/fileMerge.ts +184 -0
  53. package/src/utils/index.ts +7 -339
  54. package/src/utils/operationParams.ts +353 -0
  55. package/src/utils/refs.ts +112 -0
  56. package/src/utils/schemaGraph.ts +169 -0
  57. package/src/utils/strings.ts +139 -0
  58. package/src/visitor.ts +43 -19
  59. package/dist/extractStringsFromNodes-Bn9cOos9.d.ts +0 -14
  60. package/dist/factory-C5gHvtLU.js +0 -138
  61. package/dist/factory-C5gHvtLU.js.map +0 -1
  62. package/dist/factory-JN-Ylfl6.cjs +0 -155
  63. package/dist/factory-JN-Ylfl6.cjs.map +0 -1
  64. package/dist/utils-C8bWAzhv.cjs +0 -2696
  65. package/dist/utils-C8bWAzhv.cjs.map +0 -1
  66. package/dist/utils-DN4XLVqz.js.map +0 -1
  67. package/src/utils/ast.ts +0 -816
@@ -0,0 +1,112 @@
1
+ import { pascalCase } from '@internals/utils'
2
+ import { narrowSchema } from '../guards.ts'
3
+ import type { OperationNode, ParameterNode, SchemaNode } from '../nodes/index.ts'
4
+ import type { SchemaType } from '../nodes/schema.ts'
5
+ import type { OperationParamsResolver, ParamGroupType } from './operationParams.ts'
6
+
7
+ const plainStringTypes = new Set<SchemaType>(['string', 'uuid', 'email', 'url', 'datetime'] as const)
8
+
9
+ /**
10
+ * Returns the last path segment of a reference string.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * extractRefName('#/components/schemas/Pet') // 'Pet'
15
+ * ```
16
+ */
17
+ export function extractRefName(ref: string): string {
18
+ return ref.split('/').at(-1) ?? ref
19
+ }
20
+
21
+ /**
22
+ * Resolves the schema name of a ref node, falling back through `ref` → `name` → nested `schema.name`.
23
+ *
24
+ * Returns `null` for non-ref nodes or when no name resolves.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * resolveRefName({ kind: 'Schema', type: 'ref', ref: '#/components/schemas/Pet' })
29
+ * // => 'Pet'
30
+ * ```
31
+ */
32
+ export function resolveRefName(node: SchemaNode | undefined): string | null {
33
+ if (!node || node.type !== 'ref') return null
34
+ if (node.ref) return extractRefName(node.ref) ?? node.name ?? node.schema?.name ?? null
35
+
36
+ return node.name ?? node.schema?.name ?? null
37
+ }
38
+
39
+ /**
40
+ * Builds a PascalCase child schema name by joining a parent name and property name.
41
+ * Returns `null` when there is no parent to nest under.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * childName('Order', 'shipping_address') // 'OrderShippingAddress'
46
+ * childName(undefined, 'params') // null
47
+ * ```
48
+ */
49
+ export function childName(parentName: string | null | undefined, propName: string): string | null {
50
+ return parentName ? pascalCase([parentName, propName].join(' ')) : null
51
+ }
52
+
53
+ /**
54
+ * Builds a PascalCase enum name from the parent name, property name, and a suffix, skipping any
55
+ * empty parts.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * enumPropName('Order', 'status', 'enum') // 'OrderStatusEnum'
60
+ * ```
61
+ */
62
+ export function enumPropName(parentName: string | null | undefined, propName: string, enumSuffix: string): string {
63
+ return pascalCase([parentName, propName, enumSuffix].filter(Boolean).join(' '))
64
+ }
65
+
66
+ /**
67
+ * Type guard that returns `true` when a schema emits as a plain `string` type.
68
+ *
69
+ * Covers `string`, `uuid`, `email`, `url`, and `datetime` types. For `date` and `time`
70
+ * types, returns `true` only when `representation` is `'string'` rather than `'date'`.
71
+ */
72
+ export function isStringType(node: SchemaNode): boolean {
73
+ if (plainStringTypes.has(node.type)) {
74
+ return true
75
+ }
76
+
77
+ const temporal = narrowSchema(node, 'date') ?? narrowSchema(node, 'time')
78
+ if (temporal) {
79
+ return temporal.representation !== 'date'
80
+ }
81
+
82
+ return false
83
+ }
84
+
85
+ /**
86
+ * Derives a {@link ParamGroupType} for a query or header group from the resolver.
87
+ *
88
+ * Returns `null` when there is no resolver, no params, or the group name equals the
89
+ * individual param name (so there is no real group to emit).
90
+ */
91
+ export function resolveGroupType({
92
+ node,
93
+ params,
94
+ group,
95
+ resolver,
96
+ }: {
97
+ node: OperationNode
98
+ params: Array<ParameterNode>
99
+ group: 'query' | 'header'
100
+ resolver: OperationParamsResolver | undefined
101
+ }): ParamGroupType | null {
102
+ if (!resolver || !params.length) {
103
+ return null
104
+ }
105
+ const firstParam = params[0]!
106
+ const groupMethod = group === 'query' ? resolver.resolveQueryParamsName : resolver.resolveHeaderParamsName
107
+ const groupName = groupMethod.call(resolver, node, firstParam)
108
+ if (groupName === resolver.resolveParamName(node, firstParam)) {
109
+ return null
110
+ }
111
+ return { type: groupName, optional: params.every((p) => !p.required) }
112
+ }
@@ -0,0 +1,169 @@
1
+ import { memoize } from '@internals/utils'
2
+ import type { OperationNode, SchemaNode } from '../nodes/index.ts'
3
+ import { collect, collectLazy } from '../visitor.ts'
4
+ import { resolveRefName } from './refs.ts'
5
+
6
+ /**
7
+ * Collects every named schema referenced transitively from a node through its ref edges.
8
+ *
9
+ * Refs are followed by name only, so the resolved `node.schema` is never traversed inline.
10
+ *
11
+ * @example Collect refs from a single schema
12
+ * ```ts
13
+ * const names = collectReferencedSchemaNames(petSchema)
14
+ * // → Set { 'Category', 'Tag' }
15
+ * ```
16
+ *
17
+ * @example Accumulate refs from multiple schemas into one set
18
+ * ```ts
19
+ * const out = new Set<string>()
20
+ * for (const schema of schemas) {
21
+ * collectReferencedSchemaNames(schema, out)
22
+ * }
23
+ * ```
24
+ */
25
+ const collectSchemaRefs = memoize(new WeakMap<SchemaNode, ReadonlySet<string>>(), (node: SchemaNode): ReadonlySet<string> => {
26
+ const refs = new Set<string>()
27
+ collect<void>(node, {
28
+ schema(child) {
29
+ if (child.type === 'ref') {
30
+ const name = resolveRefName(child)
31
+ if (name) refs.add(name)
32
+ }
33
+ },
34
+ })
35
+ return refs
36
+ })
37
+
38
+ export function collectReferencedSchemaNames(node: SchemaNode | undefined, out: Set<string> = new Set()): Set<string> {
39
+ if (!node) return out
40
+ for (const name of collectSchemaRefs(node)) out.add(name)
41
+ return out
42
+ }
43
+
44
+ /**
45
+ * Collects the names of all top-level schemas transitively used by a set of operations.
46
+ *
47
+ * An operation uses a schema when its parameters, request body, or responses reference it, directly
48
+ * or through other named schemas. The walk is iterative, so reference cycles are safe.
49
+ *
50
+ * Pair it with `include` filters so schemas reachable only from excluded operations stay ungenerated.
51
+ *
52
+ * @example Only generate schemas referenced by included operations
53
+ * ```ts
54
+ * const includedOps = operations.filter((op) => resolver.resolveOptions(op, { options, include }) !== null)
55
+ * const allowed = collectUsedSchemaNames(includedOps, schemas)
56
+ *
57
+ * for (const schema of schemas) {
58
+ * if (schema.name && !allowed.has(schema.name)) continue
59
+ * // … generate schema
60
+ * }
61
+ * ```
62
+ */
63
+ const collectUsedSchemaNamesMemo = memoize(new WeakMap<ReadonlyArray<OperationNode>, (schemas: ReadonlyArray<SchemaNode>) => Set<string>>(), (ops) =>
64
+ memoize(new WeakMap<ReadonlyArray<SchemaNode>, Set<string>>(), (schemas) => computeUsedSchemaNames(ops, schemas)),
65
+ )
66
+
67
+ function computeUsedSchemaNames(operations: ReadonlyArray<OperationNode>, schemas: ReadonlyArray<SchemaNode>): Set<string> {
68
+ const schemaMap = new Map<string, SchemaNode>()
69
+ for (const schema of schemas) {
70
+ if (schema.name) schemaMap.set(schema.name, schema)
71
+ }
72
+
73
+ const result = new Set<string>()
74
+
75
+ function visitSchema(schema: SchemaNode): void {
76
+ const directRefs = collectReferencedSchemaNames(schema)
77
+ for (const name of directRefs) {
78
+ if (!result.has(name)) {
79
+ result.add(name)
80
+ const namedSchema = schemaMap.get(name)
81
+ if (namedSchema) visitSchema(namedSchema)
82
+ }
83
+ }
84
+ }
85
+
86
+ for (const op of operations) {
87
+ for (const schema of collectLazy<SchemaNode>(op, { depth: 'shallow', schema: (node) => node })) {
88
+ visitSchema(schema)
89
+ }
90
+ }
91
+
92
+ return result
93
+ }
94
+
95
+ export function collectUsedSchemaNames(operations: ReadonlyArray<OperationNode>, schemas: ReadonlyArray<SchemaNode>): Set<string> {
96
+ return collectUsedSchemaNamesMemo(operations)(schemas)
97
+ }
98
+
99
+ const EMPTY_CIRCULAR_SET = new Set<string>()
100
+
101
+ const findCircularSchemasMemo = memoize(new WeakMap<ReadonlyArray<SchemaNode>, Set<string>>(), (schemas: ReadonlyArray<SchemaNode>): Set<string> => {
102
+ const graph = new Map<string, Set<string>>()
103
+
104
+ for (const schema of schemas) {
105
+ if (!schema.name) continue
106
+ graph.set(schema.name, collectReferencedSchemaNames(schema))
107
+ }
108
+
109
+ const circular = new Set<string>()
110
+ for (const start of graph.keys()) {
111
+ const visited = new Set<string>()
112
+ const stack: Array<string> = [...(graph.get(start) ?? [])]
113
+ while (stack.length > 0) {
114
+ const node = stack.pop()!
115
+ if (node === start) {
116
+ circular.add(start)
117
+ break
118
+ }
119
+ if (visited.has(node)) continue
120
+ visited.add(node)
121
+
122
+ const next = graph.get(node)
123
+ if (next) for (const r of next) stack.push(r)
124
+ }
125
+ }
126
+
127
+ return circular
128
+ })
129
+
130
+ /**
131
+ * Finds every schema that takes part in a circular dependency chain, including direct self-loops.
132
+ *
133
+ * Wrap the returned schema positions in a deferred construct (a lazy getter or `z.lazy(() => …)`) so
134
+ * the generated code does not recurse forever. Refs are followed by name only, so the walk stays
135
+ * linear in the size of the schema graph.
136
+ *
137
+ * @note Call this once on the full graph, then check individual schemas with `containsCircularRef()`.
138
+ */
139
+ export function findCircularSchemas(schemas: ReadonlyArray<SchemaNode>): Set<string> {
140
+ if (schemas.length === 0) return EMPTY_CIRCULAR_SET
141
+ return findCircularSchemasMemo(schemas)
142
+ }
143
+
144
+ /**
145
+ * Returns `true` when a schema, or anything nested inside it, references a circular schema.
146
+ *
147
+ * Pass `excludeName` to skip refs to a specific schema, which helps when self-references are handled
148
+ * on their own. Pair it with `findCircularSchemas()` to decide where lazy wrappers go.
149
+ *
150
+ * @note Stops at the first matching circular ref.
151
+ */
152
+ export function containsCircularRef(
153
+ node: SchemaNode | undefined,
154
+ { circularSchemas, excludeName }: { circularSchemas: ReadonlySet<string>; excludeName?: string },
155
+ ): boolean {
156
+ if (!node || circularSchemas.size === 0) return false
157
+
158
+ for (const _ of collectLazy<true>(node, {
159
+ schema(child) {
160
+ if (child.type !== 'ref') return null
161
+ const name = resolveRefName(child)
162
+ return name && name !== excludeName && circularSchemas.has(name) ? true : null
163
+ },
164
+ })) {
165
+ return true
166
+ }
167
+
168
+ return false
169
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`.
3
+ * Returns the string unchanged when no balanced quote pair is found.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * trimQuotes('"hello"') // 'hello'
8
+ * trimQuotes('hello') // 'hello'
9
+ * ```
10
+ */
11
+ export function trimQuotes(text: string): string {
12
+ if (text.length >= 2) {
13
+ const first = text[0]
14
+ const last = text[text.length - 1]
15
+ if ((first === '"' && last === '"') || (first === "'" && last === "'") || (first === '`' && last === '`')) {
16
+ return text.slice(1, -1)
17
+ }
18
+ }
19
+ return text
20
+ }
21
+
22
+ /**
23
+ * Serializes a primitive to a single-quoted string literal, stripping any surrounding quotes first.
24
+ *
25
+ * Escaping runs through `JSON.stringify`, then the result switches to single quotes so the generated
26
+ * code matches the repo style without a formatter.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * stringify('hello') // "'hello'"
31
+ * stringify('"hello"') // "'hello'"
32
+ * ```
33
+ */
34
+ export function stringify(value: string | number | boolean | undefined): string {
35
+ if (value === undefined || value === null) return "''"
36
+ const json = JSON.stringify(trimQuotes(value.toString()))
37
+ const inner = json.slice(1, -1).replace(/\\"/g, '"').replace(/'/g, "\\'")
38
+ return `'${inner}'`
39
+ }
40
+
41
+ /**
42
+ * Escapes characters that are not allowed inside JS string literals, covering quotes, backslashes,
43
+ * and the Unicode line terminators U+2028 and U+2029.
44
+ *
45
+ * @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * jsStringEscape('say "hi"\nbye') // 'say \\"hi\\"\\nbye'
50
+ * ```
51
+ */
52
+ export function jsStringEscape(input: unknown): string {
53
+ return `${input}`.replace(/["'\\\n\r\u2028\u2029]/g, (character) => {
54
+ switch (character) {
55
+ case '"':
56
+ case "'":
57
+ case '\\':
58
+ return `\\${character}`
59
+ case '\n':
60
+ return '\\n'
61
+ case '\r':
62
+ return '\\r'
63
+ case '\u2028':
64
+ return '\\u2028'
65
+ case '\u2029':
66
+ return '\\u2029'
67
+ default:
68
+ return ''
69
+ }
70
+ })
71
+ }
72
+
73
+ /**
74
+ * Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
75
+ * Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.
76
+ * Pass `null` as the second argument to emit a `/pattern/flags` literal instead.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * toRegExpString('^(?im)foo') // 'new RegExp("^foo", "im")'
81
+ * toRegExpString('^(?im)foo', null) // '/^foo/im'
82
+ * ```
83
+ */
84
+ export function toRegExpString(text: string, func: string | null = 'RegExp'): string {
85
+ const raw = trimQuotes(text)
86
+
87
+ const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i)
88
+ const replacementTarget = match?.[1] ?? ''
89
+ const matchedFlags = match?.[2]
90
+ const cleaned = raw
91
+ .replace(/^\\?\//, '')
92
+ .replace(/\\?\/$/, '')
93
+ .replace(replacementTarget, '')
94
+
95
+ const { source, flags } = new RegExp(cleaned, matchedFlags)
96
+
97
+ if (func === null) return `/${source}/${flags}`
98
+
99
+ return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ''})`
100
+ }
101
+
102
+ /**
103
+ * Renders a plain object as multi-line `key: value` source for embedding in generated code. Nested
104
+ * objects recurse with fixed indentation, so the result drops straight into an object literal
105
+ * without re-parsing.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * stringifyObject({ foo: 'bar', nested: { a: 1 } })
110
+ * // 'foo: bar,\nnested: {\n a: 1\n }'
111
+ * ```
112
+ */
113
+ export function stringifyObject(value: Record<string, unknown>): string {
114
+ const items = Object.entries(value)
115
+ .map(([key, val]) => {
116
+ if (val !== null && typeof val === 'object') {
117
+ return `${key}: {\n ${stringifyObject(val as Record<string, unknown>)}\n }`
118
+ }
119
+ return `${key}: ${val}`
120
+ })
121
+ .filter(Boolean)
122
+ return items.join(',\n')
123
+ }
124
+
125
+ /**
126
+ * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
127
+ * `accessor`. Returns `null` for an empty path.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * getNestedAccessor('pagination.next.id', 'lastPage')
132
+ * // "lastPage?.['pagination']?.['next']?.['id']"
133
+ * ```
134
+ */
135
+ export function getNestedAccessor(param: string | Array<string>, accessor: string): string | null {
136
+ const parts = Array.isArray(param) ? param : param.split('.')
137
+ if (parts.length === 0 || (parts.length === 1 && parts[0] === '')) return null
138
+ return `${accessor}?.['${`${parts.join("']?.['")}']`}`
139
+ }
package/src/visitor.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import type { VisitorDepth } from './constants.ts'
2
2
  import { visitorDepths, WALK_CONCURRENCY } from './constants.ts'
3
- import { nodeRebuilders, VISITOR_KEY_BY_KIND, VISITOR_KEYS } from './registry.ts'
3
+ import type { NodeDef } from './node.ts'
4
4
  import type {
5
5
  ContentNode,
6
6
  InputNode,
7
7
  Node,
8
+ NodeKind,
8
9
  OperationNode,
9
10
  OutputNode,
10
11
  ParameterNode,
@@ -13,6 +14,31 @@ import type {
13
14
  ResponseNode,
14
15
  SchemaNode,
15
16
  } from './nodes/index.ts'
17
+ import { nodeDefs } from './registry.ts'
18
+
19
+ /**
20
+ * Child node fields per node kind, in traversal order (Babel's `VISITOR_KEYS`).
21
+ * Derived from each definition's `children`.
22
+ */
23
+ const VISITOR_KEYS = Object.fromEntries(nodeDefs.flatMap((def) => (def.children ? [[def.kind, def.children] as const] : []))) as Partial<
24
+ Record<NodeKind, ReadonlyArray<string>>
25
+ >
26
+
27
+ /**
28
+ * Maps a node kind to the matching visitor callback name. Derived from each
29
+ * definition's `visitorKey`.
30
+ */
31
+ const VISITOR_KEY_BY_KIND = Object.fromEntries(nodeDefs.flatMap((def) => (def.visitorKey ? [[def.kind, def.visitorKey] as const] : []))) as Partial<
32
+ Record<NodeKind, NonNullable<NodeDef['visitorKey']>>
33
+ >
34
+
35
+ /**
36
+ * Per-kind builders rerun after children are rebuilt. Derived from each
37
+ * definition's `rebuild` flag.
38
+ */
39
+ const nodeRebuilders = Object.fromEntries(
40
+ nodeDefs.flatMap((def) => (def.rebuild ? [[def.kind, def.create as unknown as (node: Node) => Node] as const] : [])),
41
+ ) as Partial<Record<NodeKind, (node: Node) => Node>>
16
42
 
17
43
  /**
18
44
  * Creates a small async concurrency limiter.
@@ -76,8 +102,7 @@ type ParentNodeMap = [
76
102
  /**
77
103
  * Resolves the parent node type for a given AST node type.
78
104
  *
79
- * This is used by visitor context so `ctx.parent` is correctly typed
80
- * for each callback.
105
+ * Visitor context relies on this so `ctx.parent` is typed for each callback.
81
106
  *
82
107
  * @example
83
108
  * ```ts
@@ -133,8 +158,7 @@ export type VisitorContext<T extends Node = Node> = {
133
158
  * to leave it untouched.
134
159
  *
135
160
  * Plugins typically expose `transformer` so users can supply a `Visitor` that
136
- * rewrites operation IDs, drops descriptions, or otherwise tweaks the AST
137
- * before printing.
161
+ * rewrites the AST before printing.
138
162
  *
139
163
  * @example Prefix every operationId
140
164
  * ```ts
@@ -165,7 +189,7 @@ export type Visitor = {
165
189
  }
166
190
 
167
191
  /**
168
- * Utility type for values that can be returned directly or asynchronously.
192
+ * A visitor callback result that may be sync or async.
169
193
  */
170
194
  type MaybePromise<T> = T | Promise<T>
171
195
 
@@ -229,7 +253,7 @@ type CollectVisitor<T> = {
229
253
  */
230
254
  export type TransformOptions = Visitor & {
231
255
  /**
232
- * Traversal depth (`'deep'` by default).
256
+ * Traversal depth.
233
257
  * @default 'deep'
234
258
  */
235
259
  depth?: VisitorDepth
@@ -249,7 +273,7 @@ export type TransformOptions = Visitor & {
249
273
  */
250
274
  export type WalkOptions = AsyncVisitor & {
251
275
  /**
252
- * Traversal depth (`'deep'` by default).
276
+ * Traversal depth.
253
277
  * @default 'deep'
254
278
  */
255
279
  depth?: VisitorDepth
@@ -270,7 +294,7 @@ export type WalkOptions = AsyncVisitor & {
270
294
  */
271
295
  export type CollectOptions<T> = CollectVisitor<T> & {
272
296
  /**
273
- * Traversal depth (`'deep'` by default).
297
+ * Traversal depth.
274
298
  * @default 'deep'
275
299
  */
276
300
  depth?: VisitorDepth
@@ -318,9 +342,9 @@ function* getChildren(node: Node, recurse: boolean): Generator<Node, void, undef
318
342
  }
319
343
 
320
344
  /**
321
- * Invokes the visitor callback that matches `node.kind`, passing the traversal
322
- * context. Returns the callback's result (a replacement node, a collected
323
- * value, or `undefined` when no callback is registered for the kind).
345
+ * Runs the visitor callback that matches `node.kind` with the traversal
346
+ * context. The result is a replacement node, a collected value, or `undefined`
347
+ * when no callback is registered for the kind.
324
348
  *
325
349
  * Shared by `walk`, `transform`, and `collectLazy` so node-kind dispatch lives
326
350
  * in one place. `TResult` is the caller's expected return: the same node type
@@ -369,7 +393,7 @@ async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit:
369
393
 
370
394
  // Visit siblings concurrently and let the shared `limit` cap how many callbacks
371
395
  // run at once. Awaiting each child sequentially here would serialize the whole
372
- // traversal and make `concurrency` inert, every visitor callback would run one
396
+ // traversal and make `concurrency` inert. Every visitor callback would run one
373
397
  // at a time regardless of the limit.
374
398
  const children = Array.from(getChildren(node, recurse))
375
399
  if (children.length === 0) return
@@ -378,11 +402,11 @@ async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit:
378
402
  }
379
403
 
380
404
  /**
381
- * Synchronous depth-first transform. Each visitor callback gets a chance to
382
- * return a replacement node; `undefined` keeps the original.
405
+ * Synchronous depth-first transform. Each visitor callback can return a
406
+ * replacement node. Returning `undefined` keeps the original.
383
407
  *
384
- * The transform is immutable. The original tree is not mutated. A new tree
385
- * is returned. Use `depth: 'shallow'` to skip recursion into children.
408
+ * The original tree is never mutated, a new tree is returned. Pass
409
+ * `depth: 'shallow'` to skip recursion into children.
386
410
  *
387
411
  * @example Prefix every operationId
388
412
  * ```ts
@@ -489,8 +513,8 @@ export function* collectLazy<T>(node: Node, options: CollectOptions<T>): Generat
489
513
  }
490
514
 
491
515
  /**
492
- * Eager depth-first collection pass. Returns an array of every non-null value
493
- * the visitor callbacks return.
516
+ * Eager depth-first collection pass. Gathers every non-null value the visitor
517
+ * callbacks return into an array.
494
518
  *
495
519
  * @example Collect every operationId
496
520
  * ```ts
@@ -1,14 +0,0 @@
1
- import { n as __name } from "./chunk-CNktS9qV.js";
2
- import { Ht as CodeNode } from "./ast-ClnJg9BN.js";
3
-
4
- //#region src/utils/extractStringsFromNodes.d.ts
5
- /**
6
- * Extracts all string content from a `CodeNode` tree recursively.
7
- *
8
- * Collects text node values, identifier references in string fields (`params`, `generics`, `returnType`, `type`),
9
- * and nested node content. Used to build the full source string for import filtering.
10
- */
11
- declare function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): string;
12
- //#endregion
13
- export { extractStringsFromNodes as t };
14
- //# sourceMappingURL=extractStringsFromNodes-Bn9cOos9.d.ts.map