@useorbis/db-sdk
Version:
Orbis' Typescript SDK for building open-data experiences.
150 lines (149 loc) • 4.39 kB
JavaScript
import { OrbisError } from "../util/results.js";
function buildUrl(node, route) {
const _route = route.startsWith("/") ? route : "/" + route;
return node.gateway + _route;
}
async function apiFetch(node, route, opts) {
if (node.key) {
if (opts) {
opts.headers = {
...(opts.headers || {}),
"x-orbis-api-key": node.key,
};
}
}
const url = buildUrl(node, route);
return fetch(url, opts);
}
async function ping(node) {
const response = await apiFetch(node, "/api/ping");
const text = await response.text();
if (text === "pong") {
return true;
}
return false;
}
async function fetchMetadata(node) {
const response = await apiFetch(node, "/api/metadata");
return (await response.json());
}
export async function queryDatabase(node, jsonQuery, env) {
const environment = env || node.env;
const response = await apiFetch(node, "/api/db/query/json", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ jsonQuery, env: environment }),
});
if (![200, 404].includes(response.status)) {
throw new OrbisError(`Error querying database. Status code: ${response.status || "Unknown"} (${response.statusText || response.status || ""})`, { node, query: jsonQuery, environment });
}
const { data = [] } = await response.json();
return {
columns: data.length ? Object.keys(data[0]) : [],
rows: data,
};
}
export class OrbisNode {
node;
constructor(node) {
this.node = node;
}
get env() {
return this.node.env;
}
async query(jsonQuery, env) {
return queryDatabase(this.node, jsonQuery, env);
}
async fetch(route, opts) {
return apiFetch(this.node, route, opts);
}
async ping() {
return {
pong: await ping(this.node),
node: this.node,
};
}
async metadata(forceRefresh = false) {
if (this.node.metadata && !forceRefresh) {
const { metadata, ...node } = this.node;
return {
metadata,
node,
};
}
try {
const result = await fetchMetadata(this.node);
this.node.metadata = result;
const { metadata, ...node } = this.node;
return {
metadata,
node,
};
}
catch (e) {
console.log("Couldn't retrieve metadata for this OrbisDB instance.");
return {
metadata: null,
node: this.node,
};
}
}
async models() {
const { metadata, ...node } = await this.metadata();
return {
models: metadata?.models,
node,
};
}
async plugins() {
const { metadata, ...node } = await this.metadata();
return {
plugins: metadata?.plugins,
node,
};
}
// Add a method to get the human-readable table name for a model ID
async getTableName(id) {
const { metadata, ...node } = await this.metadata();
return {
tableName: metadata?.models_mapping[id],
node,
};
}
// Add a method to get the model ID for a human-readable table name
async getTableModelId(tableName) {
const { metadata, ...node } = this.node;
const modelsMapping = metadata?.models_mapping;
const modelId = Object.keys(modelsMapping || {}).find((key) => {
return modelsMapping && tableName === modelsMapping[key];
});
return {
modelId,
node,
};
}
}
export class OrbisNodeManager {
#nodes;
#currentNode;
constructor(nodes) {
if (!nodes.length) {
throw "[OrbisNodeManager] You must provide at least one (1) OrbisNode configuration.";
}
this.#nodes = nodes.map(({ gateway, key, env }, index) => new OrbisNode({
gateway: gateway.replace(/\/$/, ""),
isPrimary: index === 0,
key,
env,
}));
this.#currentNode = this.#nodes[0];
}
get nodes() {
return this.#nodes;
}
get active() {
return this.#currentNode;
}
}