@kubb/ast 5.18.0 → 5.18.2

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/dist/index.cjs CHANGED
@@ -222,6 +222,15 @@ const VISITOR_KEYS = {
222
222
  Property: ["schema"],
223
223
  Parameter: ["schema"]
224
224
  };
225
+ /**
226
+ * Schema fields that hold checks rather than shape: the `conditionals` entries, `contains` and a string's `content`.
227
+ * `transform` and `collect` skip them, and `visitChildNodes` walks them with `checks: true`.
228
+ */
229
+ const schemaCheckKeys = [
230
+ "conditionals",
231
+ "contains",
232
+ "content"
233
+ ];
225
234
  /** Visitor callback names in traversal order, the keys of {@link Visitor}. */
226
235
  const visitorKeys = [
227
236
  "input",
@@ -272,28 +281,35 @@ function getChildren(node, recurse) {
272
281
  });
273
282
  return children;
274
283
  }
275
- /** Calls `visit` for each direct child node and stops at the first call that returns `true`. */
276
- function visitChildNodes(node, visit) {
277
- const keys = VISITOR_KEYS[node.kind];
284
+ /**
285
+ * Calls `visit` for each direct child node and stops at the first call that returns `true`.
286
+ * With `checks: true`, a schema's {@link schemaCheckKeys} fields are walked too.
287
+ */
288
+ function visitChildNodes(node, visit, { checks = false } = {}) {
289
+ const keys = checks && node.kind === nodeKinds.schema ? [...VISITOR_KEYS[node.kind] ?? [], ...schemaCheckKeys] : VISITOR_KEYS[node.kind];
278
290
  if (!keys) return false;
279
291
  const record = node;
280
292
  const seen = /* @__PURE__ */ new Set();
281
293
  const visitOnce = (child) => !seen.has(child) && (seen.add(child), visit(child));
294
+ const visitRecord = (value) => {
295
+ for (const name in value) {
296
+ if (!Object.hasOwn(value, name)) continue;
297
+ const item = value[name];
298
+ if (isNode(item) && visitOnce(item)) return true;
299
+ }
300
+ return false;
301
+ };
282
302
  for (const key of keys) {
283
303
  const value = record[key];
284
304
  if (Array.isArray(value)) {
285
- for (const item of value) if (isNode(item) && visitOnce(item)) return true;
305
+ for (const item of value) if (isNode(item) ? visitOnce(item) : isNodeRecord(item) && visitRecord(item)) return true;
286
306
  continue;
287
307
  }
288
308
  if (isNode(value)) {
289
309
  if (visitOnce(value)) return true;
290
310
  continue;
291
311
  }
292
- if (isNodeRecord(value)) for (const name in value) {
293
- if (!Object.hasOwn(value, name)) continue;
294
- const item = value[name];
295
- if (isNode(item) && visitOnce(item)) return true;
296
- }
312
+ if (isNodeRecord(value) && visitRecord(value)) return true;
297
313
  }
298
314
  return false;
299
315
  }
@@ -1202,23 +1218,33 @@ function memo(store, key, compute) {
1202
1218
  return value;
1203
1219
  }
1204
1220
  // src/utils/schemaGraph.ts
1205
- /**
1206
- * Walks a node's subtree once and lists every ref it holds, in traversal order, as the resolved
1207
- * name plus whether the ref carries a `$ref` pointer. Memoized by node identity, so
1208
- * `collectSchemaRefs` and `collectImportedRefNames` share one scan per schema.
1209
- */
1210
1221
  const refEntries = /* @__PURE__ */ new WeakMap();
1222
+ const checkRefEntries = /* @__PURE__ */ new WeakMap();
1211
1223
  const schemaRefs = /* @__PURE__ */ new WeakMap();
1212
1224
  const importedRefNames = /* @__PURE__ */ new WeakMap();
1213
- function collectRefEntries(node) {
1214
- return memo(refEntries, node, () => collectSync(node, { schema(child) {
1215
- if (child.type !== "ref") return void 0;
1216
- const name = resolveRefName(child);
1217
- return name ? {
1218
- name,
1219
- hasPointer: Boolean(child.ref)
1220
- } : void 0;
1221
- } }));
1225
+ const importedCheckRefNames = /* @__PURE__ */ new WeakMap();
1226
+ /**
1227
+ * Walks a node's subtree once and lists every ref it holds, in traversal order, as the resolved
1228
+ * name plus whether the ref carries a `$ref` pointer. Memoized per node and per `checks` mode, so
1229
+ * each helper below scans a schema once.
1230
+ */
1231
+ function collectRefEntries(node, { checks }) {
1232
+ return memo(checks ? checkRefEntries : refEntries, node, () => {
1233
+ const entries = [];
1234
+ const walk = (current) => {
1235
+ if (current.kind === nodeKinds.schema && current.type === "ref") {
1236
+ const name = resolveRefName(current);
1237
+ if (name) entries.push({
1238
+ name,
1239
+ hasPointer: Boolean(current.ref)
1240
+ });
1241
+ }
1242
+ visitChildNodes(current, walk, { checks });
1243
+ return false;
1244
+ };
1245
+ walk(node);
1246
+ return entries;
1247
+ });
1222
1248
  }
1223
1249
  /**
1224
1250
  * Collects the names of every schema a node's subtree references, resolved with `resolveRefName`.
@@ -1232,7 +1258,7 @@ function collectRefEntries(node) {
1232
1258
  * ```
1233
1259
  */
1234
1260
  function collectSchemaRefs(node) {
1235
- return memo(schemaRefs, node, () => new Set(collectRefEntries(node).map((entry) => entry.name)));
1261
+ return memo(schemaRefs, node, () => new Set(collectRefEntries(node, { checks: true }).map((entry) => entry.name)));
1236
1262
  }
1237
1263
  /**
1238
1264
  * Collects the de-duplicated target names of every pointer-carrying ref in a node's subtree, in
@@ -1241,7 +1267,8 @@ function collectSchemaRefs(node) {
1241
1267
  *
1242
1268
  * Only refs that carry a `$ref` pointer count, so a synthesized ref pointing at a sibling in the
1243
1269
  * same file (a union member created by name) is left out. That leaves exactly the set
1244
- * `resolver.imports` emits.
1270
+ * `resolver.imports` emits. Refs inside `conditionals`, `contains` and `content` count only with
1271
+ * `checks: true`, for a plugin that prints those checks.
1245
1272
  *
1246
1273
  * @example
1247
1274
  * ```ts
@@ -1249,8 +1276,8 @@ function collectSchemaRefs(node) {
1249
1276
  * // ['Category', 'Tag']
1250
1277
  * ```
1251
1278
  */
1252
- function collectImportedRefNames(node) {
1253
- return memo(importedRefNames, node, () => [...new Set(collectRefEntries(node).flatMap((entry) => entry.hasPointer ? [entry.name] : []))]);
1279
+ function collectImportedRefNames(node, { checks = false } = {}) {
1280
+ return memo(checks ? importedCheckRefNames : importedRefNames, node, () => [...new Set(collectRefEntries(node, { checks }).flatMap((entry) => entry.hasPointer ? [entry.name] : []))]);
1254
1281
  }
1255
1282
  /**
1256
1283
  * Collects the names of all top-level schemas transitively used by a set of operations.