@kubb/ast 5.0.0-beta.61 → 5.0.0-beta.62

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 (86) hide show
  1. package/dist/{defineMacro-Bv9R_9a2.cjs → defineMacro-BryDiuQl.cjs} +12 -20
  2. package/dist/defineMacro-BryDiuQl.cjs.map +1 -0
  3. package/dist/{defineMacro-BTXvS8nI.js → defineMacro-CNkUpxia.js} +12 -19
  4. package/dist/defineMacro-CNkUpxia.js.map +1 -0
  5. package/dist/{defineMacro-BLIR6k-j.d.ts → defineMacro-Vw-xQvq7.d.ts} +9 -17
  6. package/dist/factory.cjs +64 -4
  7. package/dist/factory.cjs.map +1 -0
  8. package/dist/factory.d.ts +2 -37
  9. package/dist/factory.js +58 -3
  10. package/dist/factory.js.map +1 -0
  11. package/dist/{index-BzjwdK2M.d.ts → index-CTaN_ee_.d.ts} +235 -198
  12. package/dist/index.cjs +19 -20
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +36 -37
  15. package/dist/index.js +19 -17
  16. package/dist/index.js.map +1 -1
  17. package/dist/macros.cjs +33 -20
  18. package/dist/macros.cjs.map +1 -1
  19. package/dist/macros.d.ts +13 -11
  20. package/dist/macros.js +33 -20
  21. package/dist/macros.js.map +1 -1
  22. package/dist/{operationParams-BZ07xDm0.d.ts → operationParams-B44p6EQy.d.ts} +2 -2
  23. package/dist/{response-hnSw2NKE.cjs → response-BeG6hq2D.cjs} +394 -147
  24. package/dist/response-BeG6hq2D.cjs.map +1 -0
  25. package/dist/{response-KUdWiDWw.js → response-Rd1uisM1.js} +376 -136
  26. package/dist/response-Rd1uisM1.js.map +1 -0
  27. package/dist/{types-DyDzizSf.d.ts → types-DQTgVSwE.d.ts} +4 -54
  28. package/dist/types.d.ts +5 -6
  29. package/dist/{utils-BLJwyza-.cjs → utils-BDI3kXlb.cjs} +5 -5
  30. package/dist/{utils-BLJwyza-.cjs.map → utils-BDI3kXlb.cjs.map} +1 -1
  31. package/dist/{utils-CF_-Pn_c.js → utils-DW9rnfsD.js} +5 -5
  32. package/dist/{utils-CF_-Pn_c.js.map → utils-DW9rnfsD.js.map} +1 -1
  33. package/dist/utils.cjs +4 -4
  34. package/dist/utils.d.ts +11 -3
  35. package/dist/utils.js +3 -3
  36. package/dist/{visitor-DpKZ9Tk0.cjs → visitor-B7Zlnp4c.cjs} +3 -53
  37. package/dist/visitor-B7Zlnp4c.cjs.map +1 -0
  38. package/dist/{visitor-DJ6ZEJvq.js → visitor-DepQEKyp.js} +4 -42
  39. package/dist/visitor-DepQEKyp.js.map +1 -0
  40. package/package.json +1 -1
  41. package/src/constants.ts +0 -30
  42. package/src/dedupe.ts +1 -9
  43. package/src/defineMacro.ts +19 -12
  44. package/src/{node.ts → defineNode.ts} +19 -42
  45. package/src/dialect.ts +42 -19
  46. package/src/factory.ts +3 -90
  47. package/src/index.ts +6 -8
  48. package/src/macros/macroDiscriminatorEnum.ts +7 -1
  49. package/src/macros/macroEnumName.ts +9 -1
  50. package/src/macros/macroSimplifyUnion.ts +29 -19
  51. package/src/nodes/code.ts +32 -75
  52. package/src/nodes/content.ts +2 -7
  53. package/src/nodes/file.ts +102 -14
  54. package/src/nodes/function.ts +46 -46
  55. package/src/nodes/index.ts +2 -3
  56. package/src/nodes/input.ts +13 -9
  57. package/src/nodes/operation.ts +5 -5
  58. package/src/nodes/output.ts +1 -1
  59. package/src/nodes/parameter.ts +6 -6
  60. package/src/nodes/property.ts +6 -6
  61. package/src/nodes/requestBody.ts +6 -13
  62. package/src/nodes/response.ts +93 -8
  63. package/src/nodes/schema.ts +1 -1
  64. package/src/registry.ts +1 -1
  65. package/src/types.ts +4 -5
  66. package/src/utils/extractStringsFromNodes.ts +1 -0
  67. package/src/utils/operationParams.ts +1 -1
  68. package/src/visitor.ts +2 -13
  69. package/dist/defineMacro-BTXvS8nI.js.map +0 -1
  70. package/dist/defineMacro-Bv9R_9a2.cjs.map +0 -1
  71. package/dist/extractStringsFromNodes-Cja-xxx5.js +0 -29
  72. package/dist/extractStringsFromNodes-Cja-xxx5.js.map +0 -1
  73. package/dist/extractStringsFromNodes-DKgDjFO0.cjs +0 -34
  74. package/dist/extractStringsFromNodes-DKgDjFO0.cjs.map +0 -1
  75. package/dist/extractStringsFromNodes-p4mX1TQD.d.ts +0 -14
  76. package/dist/factory-CZNOGI-N.js +0 -283
  77. package/dist/factory-CZNOGI-N.js.map +0 -1
  78. package/dist/factory-DG1CVkEb.cjs +0 -300
  79. package/dist/factory-DG1CVkEb.cjs.map +0 -1
  80. package/dist/response-KUdWiDWw.js.map +0 -1
  81. package/dist/response-hnSw2NKE.cjs.map +0 -1
  82. package/dist/visitor-DJ6ZEJvq.js.map +0 -1
  83. package/dist/visitor-DpKZ9Tk0.cjs.map +0 -1
  84. package/src/mocks.ts +0 -56
  85. package/src/nodes/http.ts +0 -85
  86. /package/src/{printer.ts → definePrinter.ts} +0 -0
@@ -1,5 +1,20 @@
1
1
  import "./chunk-CNktS9qV.js";
2
- //#region src/node.ts
2
+ import { hash } from "node:crypto";
3
+ import path from "node:path";
4
+ //#region src/defineNode.ts
5
+ /**
6
+ * Visitor callback names, one per traversable node kind, in traversal order.
7
+ * Kept in sync with the keys of `Visitor` in `visitor.ts`.
8
+ */
9
+ const visitorKeys = [
10
+ "input",
11
+ "output",
12
+ "operation",
13
+ "schema",
14
+ "property",
15
+ "parameter",
16
+ "response"
17
+ ];
3
18
  /**
4
19
  * Builds a type guard that matches nodes of the given `kind`.
5
20
  */
@@ -7,52 +22,30 @@ function isKind(kind) {
7
22
  return (node) => node.kind === kind;
8
23
  }
9
24
  /**
10
- * Updates a schema's `optional` and `nullish` flags from a parent's `required`
11
- * value and the schema's own `nullable`. Mirrors how OpenAPI parameters and
12
- * object properties combine "required" and "nullable" into a single AST.
13
- *
14
- * - Non-required + non-nullable → `optional: true`.
15
- * - Non-required + nullable → `nullish: true`.
16
- * - Required → both flags cleared.
17
- */
18
- function syncOptionality(schema, required) {
19
- const nullable = schema.nullable ?? false;
20
- return {
21
- ...schema,
22
- optional: !required && !nullable ? true : void 0,
23
- nullish: !required && nullable ? true : void 0
24
- };
25
- }
26
- /**
27
25
  * Defines a node once and derives its `create` builder, `is` guard, and traversal
28
26
  * metadata. `create` merges `defaults`, the `build` hook (or the raw input), and the
29
27
  * `kind`, so node construction lives in one place without scattered `as` casts.
30
28
  *
31
- * Set `rebuild: true` when the `build` hook derives fields from children. After a
32
- * transform rewrites those children, the registry reruns `create` so the derived
33
- * fields stay correct.
34
- *
35
29
  * @example Simple node
36
30
  * ```ts
37
31
  * const importDef = defineNode<ImportNode>({ kind: 'Import' })
38
32
  * const createImport = importDef.create
39
33
  * ```
40
34
  *
41
- * @example Node with a build hook that is rerun on transform
35
+ * @example Node with a build hook
42
36
  * ```ts
43
37
  * const propertyDef = defineNode<PropertyNode, UserPropertyNode>({
44
38
  * kind: 'Property',
45
39
  * build: (props) => ({ ...props, required: props.required ?? false }),
46
40
  * children: ['schema'],
47
41
  * visitorKey: 'property',
48
- * rebuild: true,
49
42
  * })
50
43
  * ```
51
44
  */
52
45
  function defineNode(config) {
53
- const { kind, defaults, build, children, visitorKey, rebuild } = config;
54
- function create(input) {
55
- const base = build ? build(input) : input;
46
+ const { kind, defaults, build, children, visitorKey } = config;
47
+ function create(input, dialect) {
48
+ const base = build ? build(input, dialect) : input;
56
49
  return {
57
50
  ...defaults,
58
51
  ...base,
@@ -64,8 +57,7 @@ function defineNode(config) {
64
57
  create,
65
58
  is: isKind(kind),
66
59
  children,
67
- visitorKey,
68
- rebuild
60
+ visitorKey
69
61
  };
70
62
  }
71
63
  //#endregion
@@ -163,12 +155,87 @@ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
163
155
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
164
156
  }
165
157
  //#endregion
158
+ //#region ../../internals/utils/src/fs.ts
159
+ /**
160
+ * Strips the file extension from a path or file name.
161
+ * Only removes the last `.ext` segment when the dot is not part of a directory name.
162
+ *
163
+ * @example
164
+ * trimExtName('petStore.ts') // 'petStore'
165
+ * trimExtName('/src/models/pet.ts') // '/src/models/pet'
166
+ * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
167
+ * trimExtName('noExtension') // 'noExtension'
168
+ */
169
+ function trimExtName(text) {
170
+ const dotIndex = text.lastIndexOf(".");
171
+ if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
172
+ return text;
173
+ }
174
+ //#endregion
175
+ //#region src/utils/extractStringsFromNodes.ts
176
+ /**
177
+ * Extracts all string content from a `CodeNode` tree recursively.
178
+ *
179
+ * Collects text node values, identifier references in string fields (`params`, `generics`, `returnType`, `type`),
180
+ * and nested node content. Used to build the full source string for import filtering.
181
+ */
182
+ function extractStringsFromNodes(nodes) {
183
+ if (!nodes?.length) return "";
184
+ return nodes.map((node) => {
185
+ if (typeof node === "string") return node;
186
+ if (node.kind === "Text") return node.value;
187
+ if (node.kind === "Break") return "";
188
+ if (node.kind === "Jsx") return node.value;
189
+ const parts = [];
190
+ if ("params" in node && node.params) parts.push(node.params);
191
+ if ("generics" in node && node.generics) parts.push(Array.isArray(node.generics) ? node.generics.join(", ") : node.generics);
192
+ if ("returnType" in node && node.returnType) parts.push(node.returnType);
193
+ if ("type" in node && typeof node.type === "string") parts.push(node.type);
194
+ const nested = extractStringsFromNodes(node.nodes);
195
+ if (nested) parts.push(nested);
196
+ return parts.join("\n");
197
+ }).filter(Boolean).join("\n");
198
+ }
199
+ //#endregion
166
200
  //#region src/nodes/code.ts
167
201
  /**
168
202
  * Definition for the {@link ConstNode}.
169
203
  */
170
204
  const constDef = defineNode({ kind: "Const" });
171
205
  /**
206
+ * Definition for the {@link TypeNode}.
207
+ */
208
+ const typeDef = defineNode({ kind: "Type" });
209
+ /**
210
+ * Definition for the {@link FunctionNode}.
211
+ */
212
+ const functionDef = defineNode({ kind: "Function" });
213
+ /**
214
+ * Definition for the {@link ArrowFunctionNode}.
215
+ */
216
+ const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
217
+ /**
218
+ * Definition for the {@link TextNode}.
219
+ */
220
+ const textDef = defineNode({
221
+ kind: "Text",
222
+ build: (value) => ({ value })
223
+ });
224
+ /**
225
+ * Definition for the {@link BreakNode}.
226
+ */
227
+ const breakDef = defineNode({
228
+ kind: "Break",
229
+ build: () => ({})
230
+ });
231
+ /**
232
+ * Definition for the {@link JsxNode}.
233
+ */
234
+ const jsxDef = defineNode({
235
+ kind: "Jsx",
236
+ build: (value) => ({ value })
237
+ });
238
+ /**
172
239
  * Creates a `ConstNode` representing a TypeScript `const` declaration.
173
240
  *
174
241
  * @example Exported constant with type and `as const`
@@ -179,10 +246,6 @@ const constDef = defineNode({ kind: "Const" });
179
246
  */
180
247
  const createConst = constDef.create;
181
248
  /**
182
- * Definition for the {@link TypeNode}.
183
- */
184
- const typeDef = defineNode({ kind: "Type" });
185
- /**
186
249
  * Creates a `TypeNode` representing a TypeScript `type` alias declaration.
187
250
  *
188
251
  * @example
@@ -193,10 +256,6 @@ const typeDef = defineNode({ kind: "Type" });
193
256
  */
194
257
  const createType = typeDef.create;
195
258
  /**
196
- * Definition for the {@link FunctionNode}.
197
- */
198
- const functionDef = defineNode({ kind: "Function" });
199
- /**
200
259
  * Creates a `FunctionNode` representing a TypeScript `function` declaration.
201
260
  *
202
261
  * @example
@@ -207,10 +266,6 @@ const functionDef = defineNode({ kind: "Function" });
207
266
  */
208
267
  const createFunction = functionDef.create;
209
268
  /**
210
- * Definition for the {@link ArrowFunctionNode}.
211
- */
212
- const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
213
- /**
214
269
  * Creates an `ArrowFunctionNode` representing a TypeScript arrow function.
215
270
  *
216
271
  * @example
@@ -221,13 +276,6 @@ const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
221
276
  */
222
277
  const createArrowFunction = arrowFunctionDef.create;
223
278
  /**
224
- * Definition for the {@link TextNode}.
225
- */
226
- const textDef = defineNode({
227
- kind: "Text",
228
- build: (value) => ({ value })
229
- });
230
- /**
231
279
  * Creates a {@link TextNode} representing a raw string fragment in the source output.
232
280
  *
233
281
  * @example
@@ -238,13 +286,6 @@ const textDef = defineNode({
238
286
  */
239
287
  const createText = textDef.create;
240
288
  /**
241
- * Definition for the {@link BreakNode}.
242
- */
243
- const breakDef = defineNode({
244
- kind: "Break",
245
- build: () => ({})
246
- });
247
- /**
248
289
  * Creates a {@link BreakNode} representing a line break in the source output.
249
290
  *
250
291
  * @example
@@ -257,13 +298,6 @@ function createBreak() {
257
298
  return breakDef.create();
258
299
  }
259
300
  /**
260
- * Definition for the {@link JsxNode}.
261
- */
262
- const jsxDef = defineNode({
263
- kind: "Jsx",
264
- build: (value) => ({ value })
265
- });
266
- /**
267
301
  * Creates a {@link JsxNode} representing a raw JSX fragment in the source output.
268
302
  *
269
303
  * @example
@@ -287,12 +321,171 @@ const contentDef = defineNode({
287
321
  */
288
322
  const createContent = contentDef.create;
289
323
  //#endregion
324
+ //#region src/utils/fileMerge.ts
325
+ function sourceKey(source) {
326
+ return `${source.name ?? extractStringsFromNodes(source.nodes)}:${source.isExportable ?? false}:${source.isTypeOnly ?? false}`;
327
+ }
328
+ function pathTypeKey(path, isTypeOnly) {
329
+ return `${path}:${isTypeOnly ?? false}`;
330
+ }
331
+ function exportKey(path, name, isTypeOnly, asAlias) {
332
+ return `${path}:${name ?? ""}:${isTypeOnly ?? false}:${asAlias ?? ""}`;
333
+ }
334
+ function importKey(path, name, isTypeOnly) {
335
+ return `${path}:${name ?? ""}:${isTypeOnly ?? false}`;
336
+ }
337
+ /**
338
+ * Computes a multi-level sort key for exports and imports:
339
+ * non-array names first (wildcards/namespace aliases). Type-only before value. Alphabetical path. Unnamed before named.
340
+ */
341
+ function sortKey(node) {
342
+ const isArray = Array.isArray(node.name) ? "1" : "0";
343
+ const typeOnly = node.isTypeOnly ? "0" : "1";
344
+ const hasName = node.name != null ? "1" : "0";
345
+ const name = Array.isArray(node.name) ? node.name.toSorted().join("\0") : node.name ?? "";
346
+ return `${isArray}:${typeOnly}:${node.path}:${hasName}:${name}`;
347
+ }
348
+ /**
349
+ * Deduplicates and merges `SourceNode` objects by `name + isExportable + isTypeOnly`.
350
+ *
351
+ * Unnamed sources are deduplicated by object reference. Returns a deduplicated array in original order.
352
+ */
353
+ function combineSources(sources) {
354
+ const seen = /* @__PURE__ */ new Map();
355
+ for (const source of sources) {
356
+ const key = sourceKey(source);
357
+ if (!seen.has(key)) seen.set(key, source);
358
+ }
359
+ return [...seen.values()];
360
+ }
361
+ /**
362
+ * Merges `incoming` names into `existing`, preserving order and dropping duplicates.
363
+ *
364
+ * Shared by `combineExports` and `combineImports` for the same-path name-merge case.
365
+ */
366
+ function mergeNameArrays(existing, incoming) {
367
+ const merged = new Set(existing);
368
+ for (const name of incoming) merged.add(name);
369
+ return [...merged];
370
+ }
371
+ /**
372
+ * Deduplicates and merges `ExportNode` objects by path and type.
373
+ *
374
+ * Named exports with the same path and `isTypeOnly` flag have their names merged into a single export.
375
+ * Non-array exports are deduplicated by exact identity. Returns a sorted, deduplicated array.
376
+ */
377
+ function combineExports(exports) {
378
+ const result = [];
379
+ const namedByPath = /* @__PURE__ */ new Map();
380
+ const seen = /* @__PURE__ */ new Set();
381
+ const keyed = exports.map((node) => ({
382
+ node,
383
+ key: sortKey(node)
384
+ }));
385
+ keyed.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
386
+ for (const { node: curr } of keyed) {
387
+ const { name, path, isTypeOnly, asAlias } = curr;
388
+ if (Array.isArray(name)) {
389
+ if (!name.length) continue;
390
+ const key = pathTypeKey(path, isTypeOnly);
391
+ const existing = namedByPath.get(key);
392
+ if (existing && Array.isArray(existing.name)) existing.name = mergeNameArrays(existing.name, name);
393
+ else {
394
+ const newItem = {
395
+ ...curr,
396
+ name: [...new Set(name)]
397
+ };
398
+ result.push(newItem);
399
+ namedByPath.set(key, newItem);
400
+ }
401
+ } else {
402
+ const key = exportKey(path, name, isTypeOnly, asAlias);
403
+ if (!seen.has(key)) {
404
+ result.push(curr);
405
+ seen.add(key);
406
+ }
407
+ }
408
+ }
409
+ return result;
410
+ }
411
+ /**
412
+ * Deduplicates and merges `ImportNode` objects, filtering out unused imports.
413
+ *
414
+ * Retains imports that are referenced in `source` or re-exported. Imports with the same path and
415
+ * `isTypeOnly` flag have their names merged. Returns a sorted, deduplicated, filtered array.
416
+ */
417
+ function combineImports(imports, exports, source) {
418
+ const exportedNames = new Set(exports.flatMap((e) => Array.isArray(e.name) ? e.name : e.name ? [e.name] : []));
419
+ const isUsed = (importName) => !source || source.includes(importName) || exportedNames.has(importName);
420
+ const importNameMemo = /* @__PURE__ */ new Map();
421
+ const canonicalizeName = (n) => {
422
+ if (typeof n === "string") return n;
423
+ const key = `${n.propertyName}:${n.name ?? ""}`;
424
+ if (!importNameMemo.has(key)) importNameMemo.set(key, n);
425
+ return importNameMemo.get(key);
426
+ };
427
+ const pathsWithUsedNamedImport = /* @__PURE__ */ new Set();
428
+ for (const node of imports) {
429
+ if (!Array.isArray(node.name)) continue;
430
+ if (node.name.some((item) => typeof item === "string" ? isUsed(item) : isUsed(item.name ?? item.propertyName))) pathsWithUsedNamedImport.add(node.path);
431
+ }
432
+ const result = [];
433
+ const namedByPath = /* @__PURE__ */ new Map();
434
+ const seen = /* @__PURE__ */ new Set();
435
+ const keyed = imports.map((node) => ({
436
+ node,
437
+ key: sortKey(node)
438
+ }));
439
+ keyed.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
440
+ for (const { node: curr } of keyed) {
441
+ if (curr.path === curr.root) continue;
442
+ const { path, isTypeOnly } = curr;
443
+ let { name } = curr;
444
+ if (Array.isArray(name)) {
445
+ name = [...new Set(name.map(canonicalizeName))].filter((item) => typeof item === "string" ? isUsed(item) : isUsed(item.name ?? item.propertyName));
446
+ if (!name.length) continue;
447
+ const key = pathTypeKey(path, isTypeOnly);
448
+ const existing = namedByPath.get(key);
449
+ if (existing && Array.isArray(existing.name)) existing.name = mergeNameArrays(existing.name, name);
450
+ else {
451
+ const newItem = {
452
+ ...curr,
453
+ name
454
+ };
455
+ result.push(newItem);
456
+ namedByPath.set(key, newItem);
457
+ }
458
+ } else {
459
+ if (name && !isUsed(name) && !pathsWithUsedNamedImport.has(path)) continue;
460
+ const key = importKey(path, name, isTypeOnly);
461
+ if (!seen.has(key)) {
462
+ result.push(curr);
463
+ seen.add(key);
464
+ }
465
+ }
466
+ }
467
+ return result;
468
+ }
469
+ //#endregion
290
470
  //#region src/nodes/file.ts
291
471
  /**
292
472
  * Definition for the {@link ImportNode}.
293
473
  */
294
474
  const importDef = defineNode({ kind: "Import" });
295
475
  /**
476
+ * Definition for the {@link ExportNode}.
477
+ */
478
+ const exportDef = defineNode({ kind: "Export" });
479
+ /**
480
+ * Definition for the {@link SourceNode}.
481
+ */
482
+ const sourceDef = defineNode({ kind: "Source" });
483
+ /**
484
+ * Definition for the {@link FileNode}. The fully resolved builder lives in
485
+ * `createFile`, so this definition only supplies the guard.
486
+ */
487
+ const fileDef = defineNode({ kind: "File" });
488
+ /**
296
489
  * Creates an `ImportNode` representing a language-agnostic import/dependency declaration.
297
490
  *
298
491
  * @example Named import
@@ -303,10 +496,6 @@ const importDef = defineNode({ kind: "Import" });
303
496
  */
304
497
  const createImport = importDef.create;
305
498
  /**
306
- * Definition for the {@link ExportNode}.
307
- */
308
- const exportDef = defineNode({ kind: "Export" });
309
- /**
310
499
  * Creates an `ExportNode` representing a language-agnostic export/public API declaration.
311
500
  *
312
501
  * @example Named export
@@ -317,10 +506,6 @@ const exportDef = defineNode({ kind: "Export" });
317
506
  */
318
507
  const createExport = exportDef.create;
319
508
  /**
320
- * Definition for the {@link SourceNode}.
321
- */
322
- const sourceDef = defineNode({ kind: "Source" });
323
- /**
324
509
  * Creates a `SourceNode` representing a fragment of source code within a file.
325
510
  *
326
511
  * @example
@@ -330,10 +515,64 @@ const sourceDef = defineNode({ kind: "Source" });
330
515
  */
331
516
  const createSource = sourceDef.create;
332
517
  /**
333
- * Definition for the {@link FileNode}. The fully resolved builder lives in
334
- * `createFile`, so this definition only supplies the guard.
518
+ * Creates a fully resolved `FileNode` from a file input descriptor.
519
+ *
520
+ * Computes:
521
+ * - `id` SHA256 hash of the file path
522
+ * - `name` `baseName` without extension
523
+ * - `extname` extension extracted from `baseName`
524
+ *
525
+ * Deduplicates:
526
+ * - `sources` via `combineSources`
527
+ * - `exports` via `combineExports`
528
+ * - `imports` via `combineImports` (also filters unused imports)
529
+ *
530
+ * @throws {Error} when `baseName` has no extension.
531
+ *
532
+ * @example
533
+ * ```ts
534
+ * const file = createFile({
535
+ * baseName: 'petStore.ts',
536
+ * path: 'src/models/petStore.ts',
537
+ * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],
538
+ * imports: [createImport({ name: ['z'], path: 'zod' })],
539
+ * exports: [createExport({ name: ['Pet'], path: './petStore' })],
540
+ * })
541
+ * // file.id = SHA256 hash of 'src/models/petStore.ts'
542
+ * // file.name = 'petStore'
543
+ * // file.extname = '.ts'
544
+ * ```
335
545
  */
336
- const fileDef = defineNode({ kind: "File" });
546
+ function createFile(input) {
547
+ const extname = path.extname(input.baseName) || (input.baseName.startsWith(".") ? input.baseName : "");
548
+ if (!extname) throw new Error(`No extname found for ${input.baseName}`);
549
+ const source = (input.sources ?? []).flatMap((item) => item.nodes ?? []).map((node) => extractStringsFromNodes([node])).filter(Boolean).join("\n\n");
550
+ const resolvedExports = input.exports?.length ? combineExports(input.exports) : [];
551
+ const combinedImports = input.imports?.length ? combineImports(input.imports, resolvedExports, source || void 0) : [];
552
+ const localNames = new Set((input.sources ?? []).map((item) => item.name).filter((name) => Boolean(name)));
553
+ const nameOf = (item) => typeof item === "string" ? item : item.name ?? item.propertyName;
554
+ const resolvedImports = combinedImports.filter((imp) => imp.path !== input.path).flatMap((imp) => {
555
+ if (!Array.isArray(imp.name)) return typeof imp.name === "string" && localNames.has(imp.name) ? [] : [imp];
556
+ const kept = imp.name.filter((item) => !localNames.has(nameOf(item)));
557
+ if (!kept.length) return [];
558
+ return [kept.length === imp.name.length ? imp : {
559
+ ...imp,
560
+ name: kept
561
+ }];
562
+ });
563
+ const resolvedSources = input.sources?.length ? combineSources(input.sources) : [];
564
+ return {
565
+ kind: "File",
566
+ ...input,
567
+ id: hash("sha256", input.path, "hex"),
568
+ name: trimExtName(input.baseName),
569
+ extname,
570
+ imports: resolvedImports,
571
+ exports: resolvedExports,
572
+ sources: resolvedSources,
573
+ meta: input.meta ?? {}
574
+ };
575
+ }
337
576
  //#endregion
338
577
  //#region src/nodes/function.ts
339
578
  /**
@@ -341,44 +580,14 @@ const fileDef = defineNode({ kind: "File" });
341
580
  */
342
581
  const typeLiteralDef = defineNode({ kind: "TypeLiteral" });
343
582
  /**
344
- * Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
345
- *
346
- * @example
347
- * ```ts
348
- * createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
349
- * // { petId: string }
350
- * ```
351
- */
352
- const createTypeLiteral = typeLiteralDef.create;
353
- /**
354
583
  * Definition for the {@link IndexedAccessTypeNode}.
355
584
  */
356
585
  const indexedAccessTypeDef = defineNode({ kind: "IndexedAccessType" });
357
586
  /**
358
- * Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
359
- *
360
- * @example
361
- * ```ts
362
- * createIndexedAccessType({ objectType: 'DeletePetPathParams', indexType: 'petId' })
363
- * // DeletePetPathParams['petId']
364
- * ```
365
- */
366
- const createIndexedAccessType = indexedAccessTypeDef.create;
367
- /**
368
587
  * Definition for the {@link ObjectBindingPatternNode}.
369
588
  */
370
589
  const objectBindingPatternDef = defineNode({ kind: "ObjectBindingPattern" });
371
590
  /**
372
- * Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
373
- *
374
- * @example
375
- * ```ts
376
- * createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
377
- * // { id, name }
378
- * ```
379
- */
380
- const createObjectBindingPattern = objectBindingPatternDef.create;
381
- /**
382
591
  * Definition for the {@link FunctionParameterNode}. `optional` defaults to `false`.
383
592
  * Passing `properties` builds a destructured group: an {@link ObjectBindingPatternNode} name
384
593
  * paired with a {@link TypeLiteralNode} type.
@@ -403,6 +612,43 @@ const functionParameterDef = defineNode({
403
612
  }
404
613
  });
405
614
  /**
615
+ * Definition for the {@link FunctionParametersNode}.
616
+ */
617
+ const functionParametersDef = defineNode({
618
+ kind: "FunctionParameters",
619
+ defaults: { params: [] }
620
+ });
621
+ /**
622
+ * Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
623
+ *
624
+ * @example
625
+ * ```ts
626
+ * createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
627
+ * // { petId: string }
628
+ * ```
629
+ */
630
+ const createTypeLiteral = typeLiteralDef.create;
631
+ /**
632
+ * Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
633
+ *
634
+ * @example
635
+ * ```ts
636
+ * createIndexedAccessType({ target: 'DeletePetPathParams', key: 'petId' })
637
+ * // DeletePetPathParams['petId']
638
+ * ```
639
+ */
640
+ const createIndexedAccessType = indexedAccessTypeDef.create;
641
+ /**
642
+ * Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
643
+ *
644
+ * @example
645
+ * ```ts
646
+ * createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
647
+ * // { id, name }
648
+ * ```
649
+ */
650
+ const createObjectBindingPattern = objectBindingPatternDef.create;
651
+ /**
406
652
  * Creates a `FunctionParameterNode`. `optional` defaults to `false`.
407
653
  *
408
654
  * @example Optional param
@@ -419,13 +665,6 @@ const functionParameterDef = defineNode({
419
665
  */
420
666
  const createFunctionParameter = functionParameterDef.create;
421
667
  /**
422
- * Definition for the {@link FunctionParametersNode}.
423
- */
424
- const functionParametersDef = defineNode({
425
- kind: "FunctionParameters",
426
- defaults: { params: [] }
427
- });
428
- /**
429
668
  * Creates a `FunctionParametersNode` from an ordered list of parameters.
430
669
  *
431
670
  * @example
@@ -457,8 +696,8 @@ const inputDef = defineNode({
457
696
  });
458
697
  /**
459
698
  * Creates an `InputNode`. Pass `stream: true` for the streaming variant whose `schemas` and
460
- * `operations` are `AsyncIterable` sources and whose `meta` is optional. Otherwise it builds the
461
- * eager variant with array `schemas`/`operations` and the defaulted `meta`.
699
+ * `operations` are `AsyncIterable` sources. Otherwise it builds the eager variant with array
700
+ * `schemas`/`operations`. Both variants get the defaulted `meta`.
462
701
  *
463
702
  * @example Eager
464
703
  * ```ts
@@ -475,6 +714,10 @@ function createInput(options = {}) {
475
714
  const { stream, ...overrides } = options;
476
715
  if (stream) return {
477
716
  kind: "Input",
717
+ meta: {
718
+ circularNames: [],
719
+ enumNames: []
720
+ },
478
721
  ...overrides
479
722
  };
480
723
  return inputDef.create(overrides);
@@ -482,18 +725,15 @@ function createInput(options = {}) {
482
725
  //#endregion
483
726
  //#region src/nodes/requestBody.ts
484
727
  /**
485
- * Definition for the {@link RequestBodyNode}, normalizing each content entry into a `ContentNode`.
728
+ * Definition for the {@link RequestBodyNode}. Content entries are built upfront with
729
+ * {@link createContent}, mirroring how `parameters` and `responses` take prebuilt nodes.
486
730
  */
487
731
  const requestBodyDef = defineNode({
488
732
  kind: "RequestBody",
489
- build: (props) => ({
490
- ...props,
491
- content: props.content?.map(createContent)
492
- }),
493
733
  children: ["content"]
494
734
  });
495
735
  /**
496
- * Creates a `RequestBodyNode`, normalizing each content entry into a `ContentNode`.
736
+ * Creates a `RequestBodyNode`.
497
737
  */
498
738
  const createRequestBody = requestBodyDef.create;
499
739
  //#endregion
@@ -552,22 +792,22 @@ function createOutput(overrides = {}) {
552
792
  //#endregion
553
793
  //#region src/nodes/parameter.ts
554
794
  /**
555
- * Definition for the {@link ParameterNode}. `required` defaults to `false` and the
556
- * schema's `optional`/`nullish` flags are kept in sync with it.
795
+ * Definition for the {@link ParameterNode}. `required` defaults to `false`. When a `dialect` is
796
+ * passed to `create`, the schema's `optional`/`nullish` flags are derived through its
797
+ * `optionality`; without one, the schema is left as-is.
557
798
  */
558
799
  const parameterDef = defineNode({
559
800
  kind: "Parameter",
560
- build: (props) => {
801
+ build: (props, dialect) => {
561
802
  const required = props.required ?? false;
562
803
  return {
563
804
  ...props,
564
805
  required,
565
- schema: syncOptionality(props.schema, required)
806
+ schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema
566
807
  };
567
808
  },
568
809
  children: ["schema"],
569
- visitorKey: "parameter",
570
- rebuild: true
810
+ visitorKey: "parameter"
571
811
  });
572
812
  /**
573
813
  * Creates a `ParameterNode`.
@@ -586,22 +826,22 @@ const createParameter = parameterDef.create;
586
826
  //#endregion
587
827
  //#region src/nodes/property.ts
588
828
  /**
589
- * Definition for the {@link PropertyNode}. `required` defaults to `false` and the
590
- * schema's `optional`/`nullish` flags are kept in sync with it.
829
+ * Definition for the {@link PropertyNode}. `required` defaults to `false`. When a `dialect` is
830
+ * passed to `create`, the schema's `optional`/`nullish` flags are derived through its
831
+ * `optionality`; without one, the schema is left as-is.
591
832
  */
592
833
  const propertyDef = defineNode({
593
834
  kind: "Property",
594
- build: (props) => {
835
+ build: (props, dialect) => {
595
836
  const required = props.required ?? false;
596
837
  return {
597
838
  ...props,
598
839
  required,
599
- schema: syncOptionality(props.schema, required)
840
+ schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema
600
841
  };
601
842
  },
602
843
  children: ["schema"],
603
- visitorKey: "property",
604
- rebuild: true
844
+ visitorKey: "property"
605
845
  });
606
846
  /**
607
847
  * Creates a `PropertyNode`.
@@ -627,14 +867,14 @@ const responseDef = defineNode({
627
867
  kind: "Response",
628
868
  build: (props) => {
629
869
  const { schema, mediaType, keysToOmit, content, ...rest } = props;
630
- const entries = content ?? (schema ? [{
870
+ const entries = content ?? (schema ? [createContent({
631
871
  contentType: mediaType ?? "application/json",
632
872
  schema,
633
873
  keysToOmit: keysToOmit ?? null
634
- }] : void 0);
874
+ })] : void 0);
635
875
  return {
636
876
  ...rest,
637
- content: entries?.map(createContent)
877
+ content: entries
638
878
  };
639
879
  },
640
880
  children: ["content"],
@@ -647,12 +887,12 @@ const responseDef = defineNode({
647
887
  * ```ts
648
888
  * const response = createResponse({
649
889
  * statusCode: '200',
650
- * content: [{ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) }],
890
+ * content: [createContent({ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) })],
651
891
  * })
652
892
  * ```
653
893
  */
654
894
  const createResponse = responseDef.create;
655
895
  //#endregion
656
- export { syncOptionality as $, importDef as A, createFunction as B, objectBindingPatternDef as C, createSource as D, createImport as E, breakDef as F, jsxDef as G, createText as H, constDef as I, camelCase as J, textDef as K, createArrowFunction as L, contentDef as M, createContent as N, exportDef as O, arrowFunctionDef as P, defineNode as Q, createBreak as R, indexedAccessTypeDef as S, createExport as T, createType as U, createJsx as V, functionDef as W, createSchema as X, pascalCase as Y, schemaDef as Z, createIndexedAccessType as _, createParameter as a, functionParameterDef as b, outputDef as c, createRequestBody as d, requestBodyDef as f, createFunctionParameters as g, createFunctionParameter as h, propertyDef as i, sourceDef as j, fileDef as k, createOperation as l, inputDef as m, responseDef as n, parameterDef as o, createInput as p, typeDef as q, createProperty as r, createOutput as s, createResponse as t, operationDef as u, createObjectBindingPattern as v, typeLiteralDef as w, functionParametersDef as x, createTypeLiteral as y, createConst as z };
896
+ export { schemaDef as $, fileDef as A, createConst as B, objectBindingPatternDef as C, createImport as D, createFile as E, arrowFunctionDef as F, functionDef as G, createJsx as H, breakDef as I, typeDef as J, jsxDef as K, constDef as L, sourceDef as M, contentDef as N, createSource as O, createContent as P, createSchema as Q, createArrowFunction as R, indexedAccessTypeDef as S, createExport as T, createText as U, createFunction as V, createType as W, camelCase as X, extractStringsFromNodes as Y, pascalCase as Z, createIndexedAccessType as _, createParameter as a, functionParameterDef as b, outputDef as c, createRequestBody as d, defineNode as et, requestBodyDef as f, createFunctionParameters as g, createFunctionParameter as h, propertyDef as i, importDef as j, exportDef as k, createOperation as l, inputDef as m, responseDef as n, parameterDef as o, createInput as p, textDef as q, createProperty as r, createOutput as s, createResponse as t, visitorKeys as tt, operationDef as u, createObjectBindingPattern as v, typeLiteralDef as w, functionParametersDef as x, createTypeLiteral as y, createBreak as z };
657
897
 
658
- //# sourceMappingURL=response-KUdWiDWw.js.map
898
+ //# sourceMappingURL=response-Rd1uisM1.js.map