@kubb/ast 5.9.3 → 5.9.5

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/README.md CHANGED
@@ -32,15 +32,14 @@ Defines the node tree, visitor pattern, factory functions, and type guards used
32
32
  | ------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
33
33
  | `@kubb/ast` | Runtime: node definitions, guards, visitor, macro engine, constants |
34
34
  | `ast.factory` (via `@kubb/ast`) | Node constructors (`createSchema`, `createFile`, and friends), the `ts.factory` analogue |
35
- | `@kubb/ast/types` | Types only: all node interfaces, type aliases, visitor types |
36
35
  | `kubb/kit` | Re-exports the `ast` and `factory` namespaces, the way most Kubb code reaches the AST without a direct dependency |
37
36
 
38
- `@kubb/ast` is an internal library. Inside the Kubb ecosystem the whole surface travels on the `ast` namespace from `kubb/kit`, so plugins and generators reach it there instead of depending on this package directly. The examples below import from `@kubb/ast` for clarity; through `kubb/kit` the same calls read as `ast.walk`, `ast.factory.createSchema`, and so on.
37
+ `@kubb/ast` is an internal library. Inside the Kubb ecosystem the whole surface travels on the `ast` namespace from `kubb/kit`, so plugins and generators reach it there instead of depending on this package directly. The examples below import from `@kubb/ast` for clarity; through `kubb/kit` the same calls read as `ast.transform`, `ast.factory.createSchema`, and so on.
39
38
 
40
39
  ## Node tree
41
40
 
42
41
  ```
43
- RootNode
42
+ InputNode
44
43
  ├── schemas: SchemaNode[]
45
44
  └── operations: OperationNode[]
46
45
  ├── parameters: ParameterNode[] → SchemaNode
@@ -113,7 +112,7 @@ const types = collectSync<string>(root, {
113
112
 
114
113
  ```ts
115
114
  import { narrowSchema } from '@kubb/ast'
116
- import type { Node } from '@kubb/ast/types'
115
+ import type { Node } from '@kubb/ast'
117
116
 
118
117
  function process(node: Node) {
119
118
  if (node.kind === 'Schema') {
@@ -133,12 +132,11 @@ resolveRefName({ kind: 'Schema', type: 'ref', ref: '#/components/schemas/Pet' })
133
132
 
134
133
  ## Adding a node
135
134
 
136
- Adding a node touches four files.
135
+ Adding a node touches three files.
137
136
 
138
137
  1. Define the node type and its `createFoo` function in its own `src/nodes/*.ts` file, and add the kind to `NodeKind` in `src/nodes/base.ts`.
139
- 2. Add the type to the `Node` union in `src/nodes/index.ts` and export it from `src/types.ts`.
140
- 3. Re-export `createFoo` from `src/factory.ts`.
141
- 4. When the node has children or a visitor callback, add it to `VISITOR_KEYS` and `VISITOR_KEY_BY_KIND` in `src/visitor.ts`.
138
+ 2. Add the type to the `Node` union and re-export `createFoo` in `src/nodes/index.ts`, and export the type from `src/types.ts`.
139
+ 3. When the node has children or a visitor callback, add it to `VISITOR_KEYS` and `VISITOR_KEY_BY_KIND` in `src/visitor.ts`.
142
140
 
143
141
  ## Supporting Kubb
144
142
 
package/dist/index.cjs CHANGED
@@ -34,10 +34,6 @@ let node_path = require("node:path");
34
34
  node_path = __toESM(node_path, 1);
35
35
  let node_crypto = require("node:crypto");
36
36
  //#region src/constants.ts
37
- const visitorDepths = {
38
- shallow: "shallow",
39
- deep: "deep"
40
- };
41
37
  /**
42
38
  * Schema type discriminators used by all AST schema nodes.
43
39
  *
@@ -205,7 +201,6 @@ const VISITOR_KEYS = {
205
201
  /** Visitor callback names in traversal order, the keys of {@link Visitor}. */
206
202
  const visitorKeys = [
207
203
  "input",
208
- "output",
209
204
  "operation",
210
205
  "schema",
211
206
  "property",
@@ -217,14 +212,12 @@ const visitorKeys = [
217
212
  */
218
213
  const VISITOR_KEY_BY_KIND = {
219
214
  Input: "input",
220
- Output: "output",
221
215
  Operation: "operation",
222
216
  Schema: "schema",
223
217
  Property: "property",
224
218
  Parameter: "parameter",
225
219
  Response: "response"
226
220
  };
227
- const visitorKeysByKind = VISITOR_KEYS;
228
221
  /**
229
222
  * Returns `true` when `value` is an AST node (an object carrying a `kind`).
230
223
  */
@@ -238,14 +231,6 @@ function isNodeRecord(value) {
238
231
  return typeof value === "object" && value !== null && !Array.isArray(value);
239
232
  }
240
233
  /**
241
- * Returns the child fields of `node` to walk, from {@link VISITOR_KEYS}, or `undefined` when there
242
- * is nothing to walk. `Schema` children are only walked when `recurse` is `true`.
243
- */
244
- function childKeys(node, recurse) {
245
- if (node.kind === "Schema" && !recurse) return void 0;
246
- return visitorKeysByKind[node.kind];
247
- }
248
- /**
249
234
  * Returns the immediate traversable children of `node`.
250
235
  *
251
236
  * @example
@@ -255,7 +240,7 @@ function childKeys(node, recurse) {
255
240
  * ```
256
241
  */
257
242
  function* getChildren(node, recurse) {
258
- const keys = childKeys(node, recurse);
243
+ const keys = node.kind === "Schema" && !recurse ? void 0 : VISITOR_KEYS[node.kind];
259
244
  if (!keys) return;
260
245
  const record = node;
261
246
  for (const key of keys) {
@@ -314,7 +299,7 @@ function applyVisitor(node, visitor, parent) {
314
299
  */
315
300
  function transform(node, options) {
316
301
  const { depth, parent, ...visitor } = options;
317
- return transformNode(node, visitor, (depth ?? visitorDepths.deep) === visitorDepths.deep, parent);
302
+ return transformNode(node, visitor, (depth ?? "deep") === "deep", parent);
318
303
  }
319
304
  /**
320
305
  * Visits a single node, then immutably rebuilds its children. Returns the original
@@ -329,7 +314,7 @@ function transformNode(node, visitor, recurse, parent) {
329
314
  * (e.g. `additionalProperties: true`) intact.
330
315
  */
331
316
  function transformChildren(node, visitor, recurse) {
332
- const keys = childKeys(node, recurse);
317
+ const keys = node.kind === "Schema" && !recurse ? void 0 : VISITOR_KEYS[node.kind];
333
318
  if (!keys) return node;
334
319
  const record = node;
335
320
  let updates;
@@ -387,7 +372,7 @@ function transformChildren(node, visitor, recurse) {
387
372
  */
388
373
  function* collect(node, options) {
389
374
  const { depth, parent, ...visitor } = options;
390
- yield* collectNode(node, visitor, (depth ?? visitorDepths.deep) === visitorDepths.deep, parent);
375
+ yield* collectNode(node, visitor, (depth ?? "deep") === "deep", parent);
391
376
  }
392
377
  function* collectNode(node, visitor, recurse, parent) {
393
378
  const v = applyVisitor(node, visitor, parent);
@@ -517,18 +502,6 @@ function optionality(schema, required) {
517
502
  nullish: !required && nullable ? true : void 0
518
503
  };
519
504
  }
520
- /**
521
- * Defaults `required` to `false` and derives the schema's `optional`/`nullish` flags from it.
522
- * Shared build step of `createProperty` and `createParameter`.
523
- */
524
- function withRequired(props) {
525
- const required = props.required ?? false;
526
- return {
527
- ...props,
528
- required,
529
- schema: optionality(props.schema, required)
530
- };
531
- }
532
505
  //#endregion
533
506
  //#region src/createPrinter.ts
534
507
  /**
@@ -636,6 +609,10 @@ function extractStringsFromNodes(nodes) {
636
609
  }
637
610
  //#endregion
638
611
  //#region src/utils/refs.ts
612
+ /** Returns the last segment of a `$ref` pointer, for example `'Pet'` for `#/components/schemas/Pet`. */
613
+ function refName(ref) {
614
+ return ref.split("/").at(-1) ?? ref;
615
+ }
639
616
  /**
640
617
  * Resolves the emitted name of the schema a ref node points at. Prefers `targetName` (set when
641
618
  * the referenced schema was renamed, e.g. to break a collision), then the last segment of `ref`,
@@ -652,7 +629,7 @@ function extractStringsFromNodes(nodes) {
652
629
  function resolveRefName(node) {
653
630
  if (!node || node.type !== "ref") return null;
654
631
  if (node.targetName) return node.targetName;
655
- if (node.ref) return node.ref.split("/").at(-1) ?? node.ref;
632
+ if (node.ref) return refName(node.ref);
656
633
  return node.name ?? node.schema?.name ?? null;
657
634
  }
658
635
  /**
@@ -987,6 +964,17 @@ function inferDiscriminatorPropertyName(members) {
987
964
  }
988
965
  }
989
966
  //#endregion
967
+ //#region src/nodes/base.ts
968
+ /** Builds a `createX` factory for a node whose only computed field is `kind`. */
969
+ function nodeFactory(kind) {
970
+ return (input) => {
971
+ return {
972
+ ...input,
973
+ kind
974
+ };
975
+ };
976
+ }
977
+ //#endregion
990
978
  //#region src/nodes/code.ts
991
979
  /**
992
980
  * Creates a `ConstNode` representing a TypeScript `const` declaration.
@@ -997,12 +985,7 @@ function inferDiscriminatorPropertyName(members) {
997
985
  * // export const pets: Pet[] = ... as const
998
986
  * ```
999
987
  */
1000
- function createConst(input) {
1001
- return {
1002
- ...input,
1003
- kind: "Const"
1004
- };
1005
- }
988
+ const createConst = nodeFactory("Const");
1006
989
  /**
1007
990
  * Creates a `TypeNode` representing a TypeScript `type` alias declaration.
1008
991
  *
@@ -1012,12 +995,7 @@ function createConst(input) {
1012
995
  * // export type Pet = ...
1013
996
  * ```
1014
997
  */
1015
- function createType(input) {
1016
- return {
1017
- ...input,
1018
- kind: "Type"
1019
- };
1020
- }
998
+ const createType = nodeFactory("Type");
1021
999
  /**
1022
1000
  * Creates a `FunctionNode` representing a TypeScript `function` declaration.
1023
1001
  *
@@ -1027,12 +1005,7 @@ function createType(input) {
1027
1005
  * // export async function fetchPet(): Promise<Pet> { ... }
1028
1006
  * ```
1029
1007
  */
1030
- function createFunction(input) {
1031
- return {
1032
- ...input,
1033
- kind: "Function"
1034
- };
1035
- }
1008
+ const createFunction = nodeFactory("Function");
1036
1009
  /**
1037
1010
  * Creates an `ArrowFunctionNode` representing a TypeScript arrow function.
1038
1011
  *
@@ -1042,12 +1015,7 @@ function createFunction(input) {
1042
1015
  * // export const double = (n: number) => ...
1043
1016
  * ```
1044
1017
  */
1045
- function createArrowFunction(input) {
1046
- return {
1047
- ...input,
1048
- kind: "ArrowFunction"
1049
- };
1050
- }
1018
+ const createArrowFunction = nodeFactory("ArrowFunction");
1051
1019
  /**
1052
1020
  * Creates a {@link TextNode} representing a raw string fragment in the source output.
1053
1021
  *
@@ -1095,12 +1063,7 @@ function createJsx(value) {
1095
1063
  /**
1096
1064
  * Creates a `ContentNode` for a single request-body or response content type.
1097
1065
  */
1098
- function createContent(input) {
1099
- return {
1100
- ...input,
1101
- kind: "Content"
1102
- };
1103
- }
1066
+ const createContent = nodeFactory("Content");
1104
1067
  //#endregion
1105
1068
  //#region src/utils/combineFileMembers.ts
1106
1069
  const IDENTIFIER_RUN = /[\w$]+/g;
@@ -1249,12 +1212,7 @@ function combineImports(imports, exports, source) {
1249
1212
  * // import { useState } from 'react'
1250
1213
  * ```
1251
1214
  */
1252
- function createImport(input) {
1253
- return {
1254
- ...input,
1255
- kind: "Import"
1256
- };
1257
- }
1215
+ const createImport = nodeFactory("Import");
1258
1216
  /**
1259
1217
  * Creates an `ExportNode` representing a language-agnostic export/public API declaration.
1260
1218
  *
@@ -1264,12 +1222,7 @@ function createImport(input) {
1264
1222
  * // export { Pet } from './Pet'
1265
1223
  * ```
1266
1224
  */
1267
- function createExport(input) {
1268
- return {
1269
- ...input,
1270
- kind: "Export"
1271
- };
1272
- }
1225
+ const createExport = nodeFactory("Export");
1273
1226
  /**
1274
1227
  * Creates a `SourceNode` representing a fragment of source code within a file.
1275
1228
  *
@@ -1278,12 +1231,7 @@ function createExport(input) {
1278
1231
  * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })
1279
1232
  * ```
1280
1233
  */
1281
- function createSource(input) {
1282
- return {
1283
- ...input,
1284
- kind: "Source"
1285
- };
1286
- }
1234
+ const createSource = nodeFactory("Source");
1287
1235
  /**
1288
1236
  * Creates a fully resolved `FileNode` from a file input descriptor.
1289
1237
  *
@@ -1389,12 +1337,7 @@ function createInput(overrides = {}) {
1389
1337
  /**
1390
1338
  * Creates a `RequestBodyNode`.
1391
1339
  */
1392
- function createRequestBody(input) {
1393
- return {
1394
- ...input,
1395
- kind: "RequestBody"
1396
- };
1397
- }
1340
+ const createRequestBody = nodeFactory("RequestBody");
1398
1341
  //#endregion
1399
1342
  //#region src/nodes/operation.ts
1400
1343
  function createOperation(props) {
@@ -1411,28 +1354,10 @@ function createOperation(props) {
1411
1354
  };
1412
1355
  }
1413
1356
  //#endregion
1414
- //#region src/nodes/output.ts
1415
- /**
1416
- * Creates an `OutputNode` with a stable default for `files`.
1417
- *
1418
- * @example
1419
- * ```ts
1420
- * const output = createOutput()
1421
- * // { kind: 'Output', files: [] }
1422
- * ```
1423
- */
1424
- function createOutput(overrides = {}) {
1425
- return {
1426
- files: [],
1427
- ...overrides,
1428
- kind: "Output"
1429
- };
1430
- }
1431
- //#endregion
1432
1357
  //#region src/nodes/parameter.ts
1433
1358
  /**
1434
1359
  * Creates a `ParameterNode`. `required` defaults to `false`, and the schema's
1435
- * `optional`/`nullish` flags are derived from it through {@link withRequired}.
1360
+ * `optional`/`nullish` flags are derived from it.
1436
1361
  *
1437
1362
  * @example
1438
1363
  * ```ts
@@ -1445,8 +1370,11 @@ function createOutput(overrides = {}) {
1445
1370
  * ```
1446
1371
  */
1447
1372
  function createParameter(input) {
1373
+ const required = input.required ?? false;
1448
1374
  return {
1449
- ...withRequired(input),
1375
+ ...input,
1376
+ required,
1377
+ schema: optionality(input.schema, required),
1450
1378
  kind: "Parameter"
1451
1379
  };
1452
1380
  }
@@ -1454,7 +1382,7 @@ function createParameter(input) {
1454
1382
  //#region src/nodes/property.ts
1455
1383
  /**
1456
1384
  * Creates a `PropertyNode`. `required` defaults to `false`, and the schema's
1457
- * `optional`/`nullish` flags are derived from it through {@link withRequired}.
1385
+ * `optional`/`nullish` flags are derived from it.
1458
1386
  *
1459
1387
  * @example
1460
1388
  * ```ts
@@ -1467,8 +1395,11 @@ function createParameter(input) {
1467
1395
  * ```
1468
1396
  */
1469
1397
  function createProperty(input) {
1398
+ const required = input.required ?? false;
1470
1399
  return {
1471
- ...withRequired(input),
1400
+ ...input,
1401
+ required,
1402
+ schema: optionality(input.schema, required),
1472
1403
  kind: "Property"
1473
1404
  };
1474
1405
  }
@@ -1540,8 +1471,8 @@ function createSchema(props) {
1540
1471
  };
1541
1472
  }
1542
1473
  //#endregion
1543
- //#region src/factory.ts
1544
- var factory_exports = /* @__PURE__ */ __exportAll({
1474
+ //#region src/nodes/index.ts
1475
+ var nodes_exports = /* @__PURE__ */ __exportAll({
1545
1476
  createArrowFunction: () => createArrowFunction,
1546
1477
  createBreak: () => createBreak,
1547
1478
  createConst: () => createConst,
@@ -1553,7 +1484,6 @@ var factory_exports = /* @__PURE__ */ __exportAll({
1553
1484
  createInput: () => createInput,
1554
1485
  createJsx: () => createJsx,
1555
1486
  createOperation: () => createOperation,
1556
- createOutput: () => createOutput,
1557
1487
  createParameter: () => createParameter,
1558
1488
  createProperty: () => createProperty,
1559
1489
  createRequestBody: () => createRequestBody,
@@ -1561,32 +1491,8 @@ var factory_exports = /* @__PURE__ */ __exportAll({
1561
1491
  createSchema: () => createSchema,
1562
1492
  createSource: () => createSource,
1563
1493
  createText: () => createText,
1564
- createType: () => createType,
1565
- update: () => update
1494
+ createType: () => createType
1566
1495
  });
1567
- /**
1568
- * Identity-preserving node update: returns `node` unchanged when every field in
1569
- * `changes` already equals (by reference) the current value, otherwise a new node
1570
- * with the changes applied.
1571
- *
1572
- * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the
1573
- * structural sharing in {@link transform} so a no-op rewrite does not allocate and
1574
- * downstream passes can detect "nothing changed" by identity. Comparison is shallow,
1575
- * so a structurally equal but newly allocated array or object counts as a change.
1576
- *
1577
- * @example
1578
- * ```ts
1579
- * update(node, { name: node.name }) // -> same `node` reference
1580
- * update(node, { name: 'renamed' }) // -> new node, `name` replaced
1581
- * ```
1582
- */
1583
- function update(node, changes) {
1584
- for (const key in changes) if (changes[key] !== node[key]) return {
1585
- ...node,
1586
- ...changes
1587
- };
1588
- return node;
1589
- }
1590
1496
  //#endregion
1591
1497
  //#region src/index.ts
1592
1498
  var src_exports = /* @__PURE__ */ __exportAll({
@@ -1601,7 +1507,7 @@ var src_exports = /* @__PURE__ */ __exportAll({
1601
1507
  createPrinter: () => createPrinter,
1602
1508
  defineMacro: () => defineMacro,
1603
1509
  extractStringsFromNodes: () => extractStringsFromNodes,
1604
- factory: () => factory_exports,
1510
+ factory: () => nodes_exports,
1605
1511
  findCircularSchemas: () => findCircularSchemas,
1606
1512
  findCircularSchemasFromGraph: () => findCircularSchemasFromGraph,
1607
1513
  getSchemaLiteralValues: () => getSchemaLiteralValues,
@@ -1611,6 +1517,7 @@ var src_exports = /* @__PURE__ */ __exportAll({
1611
1517
  mergeRefWithSchema: () => mergeRefWithSchema,
1612
1518
  narrowSchema: () => narrowSchema,
1613
1519
  optionality: () => optionality,
1520
+ refName: () => refName,
1614
1521
  resolveRefName: () => resolveRefName,
1615
1522
  resolveSchemaProperties: () => resolveSchemaProperties,
1616
1523
  schemaTypes: () => schemaTypes,
@@ -1636,7 +1543,7 @@ exports.extractStringsFromNodes = extractStringsFromNodes;
1636
1543
  Object.defineProperty(exports, "factory", {
1637
1544
  enumerable: true,
1638
1545
  get: function() {
1639
- return factory_exports;
1546
+ return nodes_exports;
1640
1547
  }
1641
1548
  });
1642
1549
  exports.findCircularSchemas = findCircularSchemas;
@@ -1648,6 +1555,7 @@ exports.isHttpOperationNode = isHttpOperationNode;
1648
1555
  exports.mergeRefWithSchema = mergeRefWithSchema;
1649
1556
  exports.narrowSchema = narrowSchema;
1650
1557
  exports.optionality = optionality;
1558
+ exports.refName = refName;
1651
1559
  exports.resolveRefName = resolveRefName;
1652
1560
  exports.resolveSchemaProperties = resolveSchemaProperties;
1653
1561
  exports.schemaTypes = schemaTypes;