Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 21x 21x 21x 52x 47x 3x 3x 44x 44x 44x 44x 8x 8x 8x 44x 44x 21x 44x 21x 44x 737x 265x 152x 58x 207x 207x 8x 207x 541x 44x 44x 58x 58x | /**
* Detects circular $ref chains in OpenAPI schema definitions.
* Returns the set of schema names that participate in cycles.
* These should be wrapped in `lazy()` in the output .ck.
*/
export function detectCircularRefs(schemas: Record<string, unknown>): Set<string> {
const circular = new Set<string>();
const visiting = new Set<string>(); // current DFS path
const visited = new Set<string>(); // fully explored
function visit(name: string): void {
if (visited.has(name)) return;
if (visiting.has(name)) {
circular.add(name);
return;
}
visiting.add(name);
const schema = schemas[name];
Eif (schema && typeof schema === 'object') {
for (const ref of collectRefs(schema as Record<string, unknown>)) {
const refName = extractRefName(ref);
Eif (refName && schemas[refName]) {
visit(refName);
}
}
}
visiting.delete(name);
visited.add(name);
}
for (const name of Object.keys(schemas)) {
visit(name);
}
return circular;
}
/**
* Recursively collects all $ref strings from a schema object.
*/
function collectRefs(obj: Record<string, unknown>): string[] {
const refs: string[] = [];
function walk(val: unknown): void {
if (!val || typeof val !== 'object') return;
if (Array.isArray(val)) {
for (const item of val) walk(item);
return;
}
const record = val as Record<string, unknown>;
if (typeof record.$ref === 'string') {
refs.push(record.$ref);
}
for (const v of Object.values(record)) {
walk(v);
}
}
walk(obj);
return refs;
}
/**
* Extracts the schema name from a $ref like "#/components/schemas/Foo"
* or "#/definitions/Foo" (Swagger 2.0 after normalization still uses components).
*/
export function extractRefName(ref: string): string | undefined {
const match = ref.match(/^#\/(?:components\/schemas|definitions)\/(.+)$/);
return match?.[1];
}
|