in lib/generator/swaggerMocker.ts [188:299]
private mockCachedObj(
objName: string,
schema: any,
example: any,
visited: Set<string>,
isRequest: boolean,
discriminatorValue: string | undefined = undefined
) {
if (!schema || typeof schema !== "object") {
log.warn(`invalid schema.`);
return undefined;
}
// use visited set to avoid circular dependency
if ("$ref" in schema && visited.has(schema.$ref)) {
return undefined;
}
const cache = this.getCache(schema);
if (cache) {
return cache;
}
const definitionSpec = this.getDefSpec(schema, visited);
if (util.isObject(definitionSpec)) {
// circular inherit will not be handled
const properties = this.getProperties(definitionSpec, visited);
example = example || {};
const discriminator = this.getDiscriminator(definitionSpec, visited);
if (
discriminator &&
!discriminatorValue &&
properties &&
Object.keys(properties).includes(discriminator)
) {
return (
this.mockForDiscriminator(definitionSpec, example, discriminator, isRequest, visited) ||
undefined
);
} else {
Object.keys(properties).forEach((key: string) => {
// the objName is the discriminator when discriminatorValue is specified.
if (key === objName && discriminatorValue) {
example[key] = createLeafItem(discriminatorValue, buildItemOption(properties[key]));
} else {
example[key] = this.mockCachedObj(
key,
properties[key],
example[key],
visited,
isRequest,
discriminatorValue
);
}
});
}
if ("additionalProperties" in definitionSpec && definitionSpec.additionalProperties) {
const newKey = util.randomKey();
if (newKey in properties) {
console.error(`generate additionalProperties for ${objName} fail`);
} else {
example[newKey] = this.mockCachedObj(
newKey,
definitionSpec.additionalProperties,
undefined,
visited,
isRequest,
discriminatorValue
);
}
}
} else if (definitionSpec.type === "array") {
example = example || [];
const arrItem: any = this.mockCachedObj(
`${objName}'s item`,
definitionSpec.items,
example[0],
visited,
isRequest
);
example = this.mocker.mock(definitionSpec, objName, arrItem);
} else {
/** type === number or integer */
example = example ? example : this.mocker.mock(definitionSpec, objName);
}
// return value for primary type: string, number, integer, boolean
// "aaaa"
// removeFromSet: once we try all roads started from present node, we should remove it and backtrack
this.removeFromSet(schema, visited);
let cacheItem: CacheItem;
if (Array.isArray(example)) {
const cacheChild: CacheItem[] = [];
for (const item of example) {
cacheChild.push(item);
}
cacheItem = createTrunkItem(cacheChild, buildItemOption(definitionSpec));
} else if (typeof example === "object") {
const cacheChild: { [index: string]: CacheItem } = {};
for (const [key, item] of Object.entries(example)) {
cacheChild[key] = item as CacheItem;
}
cacheItem = createTrunkItem(cacheChild, buildItemOption(definitionSpec));
} else {
cacheItem = createLeafItem(example, buildItemOption(definitionSpec));
}
cacheItem.isMocked = true;
const requiredProperties = this.getRequiredProperties(definitionSpec);
if (requiredProperties && requiredProperties.length > 0) {
cacheItem.required = requiredProperties;
}
this.mockCache.checkAndCache(schema, cacheItem);
return cacheItem;
}