@mintlify/common
Version:
Commonly shared code within Mintlify
68 lines (67 loc) • 2.07 kB
JavaScript
import yaml from 'js-yaml';
export class ExternalRefError extends Error {
constructor(message, refs) {
super(message);
this.refs = refs;
this.name = 'ExternalRefError';
}
}
function tryParse(value) {
try {
return JSON.parse(value);
}
catch (_a) {
try {
const result = yaml.load(value);
return typeof result === 'object' ? result : null;
}
catch (_b) {
return null;
}
}
}
function validateParseable(input) {
try {
JSON.parse(input);
}
catch (_a) {
yaml.load(input);
}
}
function findExternalRefs(input, path = '', refs = [], visited = new WeakSet()) {
if (typeof input === 'string') {
const parsed = tryParse(input);
if (parsed)
findExternalRefs(parsed, path, refs, visited);
return refs;
}
if (!input || typeof input !== 'object' || visited.has(input))
return refs;
visited.add(input);
if (Array.isArray(input)) {
input.forEach((item, i) => findExternalRefs(item, `${path}[${i}]`, refs, visited));
}
else {
for (const [key, value] of Object.entries(input)) {
const newPath = path ? `${path}.${key}` : key;
if (key === '$ref' && typeof value === 'string' && !value.startsWith('#')) {
refs.push({ path: newPath, value });
}
else {
findExternalRefs(value, newPath, refs, visited);
}
}
}
return refs;
}
export function checkForExternalRefs(input) {
if (input == null || (typeof input !== 'string' && typeof input !== 'object'))
return;
if (typeof input === 'string')
validateParseable(input);
const refs = findExternalRefs(input);
if (refs.length > 0) {
const details = refs.map((r) => ` - ${r.path}: ${r.value}`).join('\n');
throw new ExternalRefError(`External $ref references are not allowed. Found ${refs.length} external reference(s):\n${details}`, refs);
}
}