cesium-native/tools/generate-classes/SchemaCache.js

119 lines
2.8 KiB
JavaScript

const path = require("path");
const fs = require("fs");
const request = require("sync-request");
function readJsonStringFromFile(path) {
try {
const result = fs.readFileSync(path, "utf-8");
return result;
} catch (e) {
return undefined;
}
}
function readJsonStringFromUrl(url) {
try {
const res = request("GET", url);
return res.getBody("utf-8");
} catch (e) {
return undefined;
}
}
function readJsonString(pathOrUrl) {
if (pathOrUrl.startsWith("http")) {
return readJsonStringFromUrl(pathOrUrl);
}
return readJsonStringFromFile(pathOrUrl);
}
class SchemaCache {
constructor(schemaPaths, extensionPaths) {
this.schemaPaths = schemaPaths;
this.extensionSchemaPaths = extensionPaths;
this.cache = {};
this.contextStack = [];
}
load(name) {
// First search relative to the current context.
// If not found, search the schema paths.
const searchPaths = [
this.resolveRelativePath(name),
...this.schemaPaths.map((path) => this.resolvePath(path, name)),
];
return this.loadFromSearchPaths(name, searchPaths);
}
loadExtension(schemaName, extensionName) {
const searchPaths = this.extensionSchemaPaths.map((path) =>
this.resolvePath(path, schemaName)
);
// Prioritize paths that contain the extension name because multiple extensions may have the same schema name.
searchPaths.sort((pathA, pathB) => {
const resultA = pathA.indexOf(extensionName) === -1 ? 0 : 1;
const resultB = pathB.indexOf(extensionName) === -1 ? 0 : 1;
return resultB - resultA;
});
return this.loadFromSearchPaths(schemaName, searchPaths);
}
loadFromSearchPaths(name, paths) {
let jsonString;
let path;
for (path of paths) {
const existingSchema = this.cache[path];
if (existingSchema) {
return existingSchema;
}
jsonString = readJsonString(path);
if (jsonString) {
break;
}
}
if (jsonString === undefined) {
console.warn(
`Could not resolve ${name}. Tried:\n${paths
.map((path) => ` * ${path}`)
.join("\n")}`
);
return undefined;
}
const result = JSON.parse(jsonString);
result.sourcePath = path;
this.cache[path] = result;
return result;
}
pushContext(schema) {
this.contextStack.push(schema);
}
popContext() {
this.contextStack.pop();
}
resolveRelativePath(name) {
if (this.contextStack.length === 0) {
return name;
}
const base = this.contextStack[this.contextStack.length - 1].sourcePath;
return this.resolvePath(base, name);
}
resolvePath(base, name) {
if (base.startsWith("http")) {
return new URL(name, base).href;
} else {
return path.resolve(base, "..", name);
}
}
}
module.exports = SchemaCache;