UNPKG

@mintlify/common

Version:

Commonly shared code within Mintlify

181 lines (180 loc) 8.01 kB
import { getEnumValues } from '../getEnumValues.js'; const combinationKeys = ['oneOf', 'anyOf', 'allOf']; const getCombinationKey = (value) => { return combinationKeys.find((key) => key in value && Array.isArray(value[key])); }; const getTypeFromCombination = (value, combKey) => { var _a; // eslint-disable-next-line @typescript-eslint/no-explicit-any const schemas = value[combKey]; const types = [ ...new Set(schemas .map((s) => (typeof s === 'object' ? s.type : undefined)) .filter((t) => typeof t === 'string' && t !== 'null')), ]; if (types.length === 1) return (_a = types[0]) !== null && _a !== void 0 ? _a : combKey; return combKey; }; const getSchemaType = (value, keys) => { if ('type' in value) { return value.type; } const customTypeKey = keys.find((key) => /^x-.*type$/.test(key)); if (customTypeKey) { return value[customTypeKey]; } const enumValues = getEnumValues(value); if (enumValues === null || enumValues === void 0 ? void 0 : enumValues.length) { const firstValue = enumValues[0]; if (typeof firstValue === 'boolean') return 'boolean'; if (typeof firstValue === 'number') return 'number'; return 'string'; } return undefined; }; export const extractSchemaProperties = (schema) => { if (!schema) { return []; } const properties = []; const requiredFields = new Set(schema.required || []); for (const [key, value] of Object.entries(schema)) { const name = key; if (name === 'required' || name.includes('x-parser')) { continue; } if (name === 'oneOf' || name === 'anyOf' || name === 'allOf') { const descriptions = { oneOf: 'Must be one of these types', anyOf: 'Can be any of these types', allOf: 'Must contain all of these types', }; const prop = { name, type: name, description: descriptions[name], properties: value // eslint-disable-next-line @typescript-eslint/no-explicit-any .map((item) => { const schemaWithRequired = Object.assign(Object.assign({}, (item.properties || item)), { required: item.required }); const extracted = extractSchemaProperties(schemaWithRequired); return extracted; }) .flat(), }; properties.push(prop); continue; } if (value === null || value === undefined) { continue; } if (typeof value === 'object' && !Array.isArray(value)) { const keys = Object.keys(value); const type = getSchemaType(value, keys); if (type !== undefined) { const prop = { name: name, type, title: value.title, description: value.description || value['const'], enumValues: getEnumValues(value), examples: value.examples, deprecated: value.deprecated, required: requiredFields.has(name), }; if (value.properties) { prop.properties = extractSchemaProperties(Object.assign(Object.assign({}, value.properties), { required: value.required })); } else if (type === 'array' && value.items && typeof value.items === 'object' && !Array.isArray(value.items)) { if (value.items.properties) { const itemSchemaWithRequired = Object.assign(Object.assign({}, value.items.properties), { required: value.items.required }); prop.properties = extractSchemaProperties(itemSchemaWithRequired); } else { const itemProps = extractSchemaProperties({ item: value.items }); if (itemProps.length > 0) { prop.properties = itemProps; } } } properties.push(prop); } else { const combKey = getCombinationKey(value); if (combKey) { const inferredType = getTypeFromCombination(value, combKey); const prop = { name, type: inferredType, title: value.title, description: value.description, enumValues: getEnumValues(value), examples: value.examples, deprecated: value.deprecated, required: requiredFields.has(name), }; // Extract child properties from combination schemas // eslint-disable-next-line @typescript-eslint/no-explicit-any const combSchemas = value[combKey]; if (combKey === 'allOf') { // allOf: merge all sub-schema properties together const mergedProps = combSchemas.flatMap( // eslint-disable-next-line @typescript-eslint/no-explicit-any (item) => { if (item.properties) { const schemaWithRequired = Object.assign(Object.assign({}, item.properties), { required: item.required }); return extractSchemaProperties(schemaWithRequired); } return []; }); if (mergedProps.length > 0) { prop.properties = mergedProps; if (inferredType === 'allOf') prop.type = 'object'; } } else { // oneOf/anyOf: extract properties from sub-schemas that have them const subProps = combSchemas.flatMap( // eslint-disable-next-line @typescript-eslint/no-explicit-any (item) => { if (item.properties) { const schemaWithRequired = Object.assign(Object.assign({}, item.properties), { required: item.required }); return extractSchemaProperties(schemaWithRequired); } if (item.items && typeof item.items === 'object') { if (item.items.properties) { const schemaWithRequired = Object.assign(Object.assign({}, item.items.properties), { required: item.items.required }); return extractSchemaProperties(schemaWithRequired); } } return []; }); if (subProps.length > 0) { prop.properties = subProps; } } properties.push(prop); } else { properties.push(...extractSchemaProperties(value)); } } } else { properties.push({ name, type: Array.isArray(value) ? 'array' : typeof value, description: typeof value === 'string' ? value : undefined, required: requiredFields.has(name), }); } } return properties; };