@kubb/ast 5.0.0-beta.57 → 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 (69) hide show
  1. package/README.md +21 -7
  2. package/dist/casing-BE2R1RXg.cjs +88 -0
  3. package/dist/casing-BE2R1RXg.cjs.map +1 -0
  4. package/dist/chunk-CNktS9qV.js +17 -0
  5. package/dist/extractStringsFromNodes-WMYJ8nQL.d.ts +82 -0
  6. package/dist/factory-BmcGBdeg.cjs +1251 -0
  7. package/dist/factory-BmcGBdeg.cjs.map +1 -0
  8. package/dist/factory-Du7nEP4B.js +282 -0
  9. package/dist/factory-Du7nEP4B.js.map +1 -0
  10. package/dist/factory.cjs +28 -0
  11. package/dist/factory.d.ts +62 -0
  12. package/dist/factory.js +3 -0
  13. package/dist/{types-C5aVnRE1.d.ts → index-BzjwdK2M.d.ts} +94 -1146
  14. package/dist/index.cjs +220 -1481
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +96 -58
  17. package/dist/index.js +182 -1920
  18. package/dist/index.js.map +1 -1
  19. package/dist/operationParams-BZ07xDm0.d.ts +204 -0
  20. package/dist/response-DKxTr522.js +683 -0
  21. package/dist/response-DKxTr522.js.map +1 -0
  22. package/dist/types-olVl9v5p.d.ts +764 -0
  23. package/dist/types.d.ts +5 -2
  24. package/dist/utils-BCtRXfhI.cjs +275 -0
  25. package/dist/utils-BCtRXfhI.cjs.map +1 -0
  26. package/dist/utils-SdZU0F3H.js +1336 -0
  27. package/dist/utils-SdZU0F3H.js.map +1 -0
  28. package/dist/utils.cjs +129 -13
  29. package/dist/utils.d.ts +127 -76
  30. package/dist/utils.js +3 -2
  31. package/package.json +5 -1
  32. package/src/constants.ts +8 -14
  33. package/src/dedupe.ts +8 -0
  34. package/src/factory.ts +18 -1
  35. package/src/guards.ts +1 -1
  36. package/src/index.ts +7 -50
  37. package/src/node.ts +1 -1
  38. package/src/nodes/base.ts +0 -10
  39. package/src/nodes/code.ts +29 -47
  40. package/src/nodes/content.ts +2 -2
  41. package/src/nodes/file.ts +28 -23
  42. package/src/nodes/function.ts +2 -17
  43. package/src/nodes/index.ts +1 -1
  44. package/src/nodes/input.ts +20 -19
  45. package/src/nodes/operation.ts +1 -1
  46. package/src/nodes/parameter.ts +0 -3
  47. package/src/nodes/property.ts +0 -3
  48. package/src/nodes/requestBody.ts +3 -6
  49. package/src/nodes/schema.ts +3 -2
  50. package/src/printer.ts +4 -4
  51. package/src/registry.ts +31 -26
  52. package/src/signature.ts +3 -3
  53. package/src/transformers.ts +28 -1
  54. package/src/types.ts +2 -53
  55. package/src/utils/codegen.ts +104 -0
  56. package/src/utils/extractStringsFromNodes.ts +34 -0
  57. package/src/utils/fileMerge.ts +184 -0
  58. package/src/utils/index.ts +8 -296
  59. package/src/utils/operationParams.ts +353 -0
  60. package/src/utils/refs.ts +112 -0
  61. package/src/utils/schemaGraph.ts +169 -0
  62. package/src/utils/strings.ts +139 -0
  63. package/src/visitor.ts +43 -19
  64. package/dist/chunk-C0LytTxp.js +0 -8
  65. package/dist/utils-0p8ZO287.js +0 -570
  66. package/dist/utils-0p8ZO287.js.map +0 -1
  67. package/dist/utils-cdQ6Pzyi.cjs +0 -726
  68. package/dist/utils-cdQ6Pzyi.cjs.map +0 -1
  69. package/src/utils/ast.ts +0 -879
@@ -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,8 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __defProp = Object.defineProperty;
3
- var __name = (target, value) => __defProp(target, "name", {
4
- value,
5
- configurable: true
6
- });
7
- //#endregion
8
- export { __name as t };