generator/processors/helpers.ts (59 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function replaceRefByName(schema: any, definitionName: string, replacement: any) {
transformSchemaRecursively(schema, val => {
if (val['$ref'] === `#/definitions/${definitionName}`) {
return replacement;
}
return val;
})
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function replaceCyclicRefByName(schema: any, definitionName: string, replacement: any) {
const refVertices: Record<string, Set<string>> = {};
for (const refName in schema.definitions) {
refVertices[refName] = new Set<string>();
transformSchemaRecursively(schema.definitions[refName], val => {
if (val['$ref'] && val['$ref'].startsWith('#/definitions/')) {
refVertices[refName].add(val['$ref'].substring('#/definitions/'.length));
}
return val;
});
}
const parentDefinitions = findCyclicReferencingDefinitions(refVertices, definitionName);
for (const parentDefinition of parentDefinitions) {
replaceRefByName(schema.definitions[parentDefinition], definitionName, replacement);
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function transformSchemaRecursively(schema: any, transformFunc: (input: any) => any) {
if (typeof schema === 'object') {
for (const key of Object.keys(schema)) {
schema[key] = transformSchemaRecursively(schema[key], transformFunc);
}
}
else if (Array.isArray(schema)) {
for (let i = 0; i < schema.length; i++) {
schema[i] = transformSchemaRecursively(schema[i], transformFunc);
}
}
return transformFunc(schema);
}
function findCyclicReferencingDefinitions(refVertices: Record<string, Set<string>>, definitionName: string) {
const visited = new Set<string>();
const queue = [definitionName];
const parentDefinitions = new Set<string>();
while (queue.length > 0) {
const current = queue.shift()!;
if (visited.has(current)) {
continue;
}
visited.add(current);
if (!refVertices[current]) {
continue;
}
for (const dependency of refVertices[current]) {
if (dependency === definitionName) {
parentDefinitions.add(current);
}
queue.push(dependency);
}
}
return parentDefinitions;
}