@anysoftinc/anydb-sdk
Version:
AnyDB TypeScript SDK for querying and transacting with Datomic databases
114 lines (113 loc) • 4.32 kB
JavaScript
import { stringifyEdn } from "./client";
// Load the DataScript backend if available
let datascriptBackend = null;
try {
// Try to load the compiled DataScript module (shipped alongside dist output)
datascriptBackend =
globalThis.anydbDatascript ||
require("./anydb.datascript.core.js");
}
catch (e) {
console.warn("DataScript backend not available. Run `npx shadow-cljs compile datascript` to enable client-only development mode.");
}
export class DataScriptBackend {
constructor(storageAlias, dbName) {
this.dbAlias = `${storageAlias}/${dbName}`;
if (!datascriptBackend) {
throw new Error("DataScript backend not loaded. Please compile ClojureScript modules first.");
}
}
// Database management
async listDatabases() {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
return datascriptBackend.listDatabases();
}
async createDatabase() {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
return datascriptBackend.createDatabase(this.dbAlias);
}
async deleteDatabase() {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
return datascriptBackend.deleteDatabase(this.dbAlias);
}
// Transaction operations
async transact(txData) {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
const txDataEdn = stringifyEdn(txData);
const result = datascriptBackend.transactData(this.dbAlias, txDataEdn);
// Convert to match Datomic API format
return {
"db-before": { "basis-t": -1, "db/alias": this.dbAlias },
"db-after": { "basis-t": -1, "db/alias": this.dbAlias },
"tx-data": result["tx-data"] || [],
tempids: result.tempids || {},
};
}
// Query operations
async query(query, ...args) {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
const queryEdn = stringifyEdn(query);
const argsEdn = args.map((arg) => stringifyEdn(arg));
return datascriptBackend.queryData(queryEdn, this.dbAlias, ...argsEdn);
}
// Entity operations
async entity(entityId) {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
const entity = datascriptBackend.getEntity(this.dbAlias, entityId);
// Ensure db/id is present
if (entity && !entity["db/id"]) {
entity["db/id"] = entityId;
}
return entity;
}
// Datoms operations
async datoms(index, options = {}) {
if (!datascriptBackend)
throw new Error("DataScript backend not available");
const components = [];
if (options.e !== undefined)
components.push(options.e);
if (options.a !== undefined)
components.push(options.a);
if (options.v !== undefined)
components.push(options.v);
let datoms = datascriptBackend.getDatoms(this.dbAlias, index, ...components);
// Apply client-side limit/offset since DataScript doesn't have built-in pagination
if (options.offset) {
datoms = datoms.slice(options.offset);
}
if (options.limit) {
datoms = datoms.slice(0, options.limit);
}
// Convert to Datomic datom format
return datoms.map((d) => ({
e: d.e || d[0],
a: d.a || d[1],
v: d.v || d[2],
tx: d.tx || d[3],
added: d.added !== false, // Default to true
}));
}
// Database info (mock for compatibility)
async databaseInfo() {
return {
"basis-t": -1, // DataScript doesn't have basis-t concept
"db/alias": this.dbAlias,
};
}
}
// Utility to check if DataScript backend is available
export function isDataScriptAvailable() {
return datascriptBackend !== null;
}
// Utility to detect if we should use DataScript backend
export function shouldUseDataScript(storageAlias) {
// Explicit opt-in: use DataScript when storage alias is exactly "datascript"
return storageAlias === "datascript";
}