@kubb/ast 5.0.0-beta.1 → 5.0.0-beta.3

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
@@ -1180,6 +1180,13 @@ function combineExports(exports) {
1180
1180
  function combineImports(imports, exports, source) {
1181
1181
  const exportedNames = new Set(exports.flatMap((e) => Array.isArray(e.name) ? e.name : e.name ? [e.name] : []));
1182
1182
  const isUsed = (importName) => !source || source.includes(importName) || exportedNames.has(importName);
1183
+ const importNameMemo = /* @__PURE__ */ new Map();
1184
+ const canonicalizeName = (n) => {
1185
+ if (typeof n === "string") return n;
1186
+ const key = `${n.propertyName}:${n.name ?? ""}`;
1187
+ if (!importNameMemo.has(key)) importNameMemo.set(key, n);
1188
+ return importNameMemo.get(key);
1189
+ };
1183
1190
  const result = [];
1184
1191
  const namedByPath = /* @__PURE__ */ new Map();
1185
1192
  const seen = /* @__PURE__ */ new Set();
@@ -1193,7 +1200,7 @@ function combineImports(imports, exports, source) {
1193
1200
  const { path, isTypeOnly } = curr;
1194
1201
  let { name } = curr;
1195
1202
  if (Array.isArray(name)) {
1196
- name = [...new Set(name)].filter((item) => typeof item === "string" ? isUsed(item) : isUsed(item.propertyName));
1203
+ name = [...new Set(name.map(canonicalizeName))].filter((item) => typeof item === "string" ? isUsed(item) : isUsed(item.name ?? item.propertyName));
1197
1204
  if (!name.length) continue;
1198
1205
  const key = pathTypeKey(path, isTypeOnly);
1199
1206
  const existing = namedByPath.get(key);
@@ -1266,7 +1273,19 @@ function resolveRefName(node) {
1266
1273
  * Refs are followed by name only — the resolved `node.schema` is not traversed inline.
1267
1274
  * Use this to determine schema dependencies, build reference graphs, or detect what schemas need to be emitted.
1268
1275
  *
1269
- * @note Returns a Set of schema names for efficient membership testing.
1276
+ * @example Collect refs from a single schema
1277
+ * ```ts
1278
+ * const names = collectReferencedSchemaNames(petSchema)
1279
+ * // → Set { 'Category', 'Tag' }
1280
+ * ```
1281
+ *
1282
+ * @example Accumulate refs from multiple schemas into one set
1283
+ * ```ts
1284
+ * const out = new Set<string>()
1285
+ * for (const schema of schemas) {
1286
+ * collectReferencedSchemaNames(schema, out)
1287
+ * }
1288
+ * ```
1270
1289
  */
1271
1290
  function collectReferencedSchemaNames(node, out = /* @__PURE__ */ new Set()) {
1272
1291
  if (!node) return out;
@@ -1279,6 +1298,52 @@ function collectReferencedSchemaNames(node, out = /* @__PURE__ */ new Set()) {
1279
1298
  return out;
1280
1299
  }
1281
1300
  /**
1301
+ * Collects the names of all top-level schemas transitively used by a set of operations.
1302
+ *
1303
+ * An operation uses a schema when any of its parameters, request body content, or responses
1304
+ * reference it — directly or indirectly through other named schemas.
1305
+ * The walk is iterative and safe against reference cycles.
1306
+ *
1307
+ * Use this together with `include` filters to determine which schemas from `components/schemas`
1308
+ * are reachable from the allowed operations, so that schemas used only by excluded operations
1309
+ * are not generated.
1310
+ *
1311
+ * @example Only generate schemas referenced by included operations
1312
+ * ```ts
1313
+ * const includedOps = inputNode.operations.filter(op => resolver.resolveOptions(op, { options, include }) !== null)
1314
+ * const allowed = collectUsedSchemaNames(includedOps, inputNode.schemas)
1315
+ *
1316
+ * for (const schema of inputNode.schemas) {
1317
+ * if (schema.name && !allowed.has(schema.name)) continue
1318
+ * // … generate schema
1319
+ * }
1320
+ * ```
1321
+ *
1322
+ * @example Check whether a specific schema is needed
1323
+ * ```ts
1324
+ * const allowed = collectUsedSchemaNames(includedOps, inputNode.schemas)
1325
+ * allowed.has('OrderStatus') // false when no included operation references OrderStatus
1326
+ * ```
1327
+ */
1328
+ function collectUsedSchemaNames(operations, schemas) {
1329
+ const schemaMap = /* @__PURE__ */ new Map();
1330
+ for (const schema of schemas) if (schema.name) schemaMap.set(schema.name, schema);
1331
+ const result = /* @__PURE__ */ new Set();
1332
+ function visitSchema(schema) {
1333
+ const directRefs = collectReferencedSchemaNames(schema);
1334
+ for (const name of directRefs) if (!result.has(name)) {
1335
+ result.add(name);
1336
+ const namedSchema = schemaMap.get(name);
1337
+ if (namedSchema) visitSchema(namedSchema);
1338
+ }
1339
+ }
1340
+ for (const op of operations) for (const schema of collect(op, {
1341
+ depth: "shallow",
1342
+ schema: (node) => node
1343
+ })) visitSchema(schema);
1344
+ return result;
1345
+ }
1346
+ /**
1282
1347
  * Identifies all schemas that participate in circular dependency chains, including direct self-loops.
1283
1348
  *
1284
1349
  * Returns a Set of schema names with circular dependencies. Use this to wrap recursive schema positions
@@ -2161,6 +2226,7 @@ exports.childName = childName;
2161
2226
  exports.collect = collect;
2162
2227
  exports.collectImports = collectImports;
2163
2228
  exports.collectReferencedSchemaNames = collectReferencedSchemaNames;
2229
+ exports.collectUsedSchemaNames = collectUsedSchemaNames;
2164
2230
  exports.containsCircularRef = containsCircularRef;
2165
2231
  exports.createArrowFunction = createArrowFunction;
2166
2232
  exports.createBreak = createBreak;