74 lines
2.1 KiB
JavaScript
74 lines
2.1 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
export default class SchemaFileLoader {
|
|
/**
|
|
* Load a schema JSON file and resolve all nested json_dtype references
|
|
*
|
|
* @param {string} filePath - Absolute or relative path to schema file
|
|
* @param {Set<string>} visited - Internal circular reference protection
|
|
* @returns {object} Fully resolved schema JSON
|
|
*/
|
|
static load(filePath, visited = new Set()) {
|
|
const absolutePath = path.resolve(filePath);
|
|
|
|
if (visited.has(absolutePath)) {
|
|
throw new Error(`Circular schema reference detected: ${absolutePath}`);
|
|
}
|
|
|
|
visited.add(absolutePath);
|
|
|
|
if (!fs.existsSync(absolutePath)) {
|
|
throw new Error(`Schema file not found: ${absolutePath}`);
|
|
}
|
|
|
|
const raw = fs.readFileSync(absolutePath, 'utf-8');
|
|
const schema = JSON.parse(raw);
|
|
|
|
const baseDir = path.dirname(absolutePath);
|
|
return this._resolveSchema(schema, baseDir, visited);
|
|
}
|
|
|
|
/**
|
|
* Recursively resolve json_dtype references
|
|
*/
|
|
static _resolveSchema(schema, baseDir, visited) {
|
|
if (typeof schema !== 'object' || schema === null) return schema;
|
|
|
|
for (const field in schema) {
|
|
const rule = schema[field];
|
|
|
|
if (!rule || typeof rule !== 'object') continue;
|
|
|
|
// Resolve nested JSON object schema
|
|
if (
|
|
rule.type === 'JSONObject' ||
|
|
rule.type === 'JSONArray'
|
|
) {
|
|
if (typeof rule.json_dtype === 'string') {
|
|
const nestedPath = path.join(baseDir, rule.json_dtype);
|
|
rule.json_dtype = this.load(nestedPath, visited);
|
|
} else if (typeof rule.json_dtype === 'object') {
|
|
rule.json_dtype = this._resolveSchema(
|
|
rule.json_dtype,
|
|
baseDir,
|
|
visited
|
|
);
|
|
}
|
|
}
|
|
|
|
// Resolve array of JSON objects
|
|
if (
|
|
rule.type === 'Array' &&
|
|
rule.array_dtype === 'JSONObject'
|
|
) {
|
|
if (typeof rule.json_dtype === 'string') {
|
|
const nestedPath = path.join(baseDir, rule.json_dtype);
|
|
rule.json_dtype = this.load(nestedPath, visited);
|
|
}
|
|
}
|
|
}
|
|
|
|
return schema;
|
|
}
|
|
} |