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

140 lines
3.2 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(schemaPath, extensionPath) {
this.schemaPath = schemaPath;
this.extensionPath = extensionPath;
this.cache = {};
this.contextStack = [];
this.byTitle = {};
}
load(name) {
// First try loading relative to the current context
let path = this.resolveRelativePath(name);
const existing = this.cache[path];
if (existing) {
return existing;
}
let jsonString = readJsonString(path);
if (jsonString === undefined) {
// Next try resolving relative to the base URL
const pathFromBase = this.resolvePathFromBase(name);
const existingFromBase = this.cache[pathFromBase];
if (existingFromBase) {
return existingFromBase;
}
jsonString = readJsonString(pathFromBase);
if (jsonString === undefined) {
console.warn(
`Could not resolve ${name}. Tried:\n * ${path}\n *${pathFromBase}`
);
return undefined;
}
path = pathFromBase;
}
const result = JSON.parse(jsonString);
result.sourcePath = path;
this.cache[path] = result;
const upperTitle = result.title.toUpperCase();
if (this.byTitle[upperTitle]) {
console.warn(
`*** Two schema files share the same title, things will be broken:\n ${this.byTitle[upperTitle].sourcePath}\n ${path}`
);
}
this.byTitle[upperTitle] = result;
return result;
}
loadExtension(name) {
const path = this.resolvePath(this.extensionPath, name);
const existing = this.cache[path];
if (existing) {
return existing;
}
const jsonString = readJsonString(path);
const result = JSON.parse(jsonString, "utf-8");
result.sourcePath = path;
this.cache[name] = result;
const upperTitle = result.title.toUpperCase();
if (this.byTitle[upperTitle]) {
console.warn(
`*** Two schema files share the same title, things will be broken:\n ${this.byTitle[upperTitle].sourcePath}\n ${path}`
);
}
this.byTitle[result.title.toUpperCase()] = 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);
}
resolvePathFromBase(name) {
return this.resolvePath(this.schemaPath, name);
}
resolvePath(base, name) {
if (base.startsWith("http")) {
return new URL(name, base).href;
} else {
return path.resolve(base, "..", name);
}
}
}
module.exports = SchemaCache;