upend/sdks/js/src/query.ts

92 lines
2.3 KiB
TypeScript

import type { Address } from "./types";
import { isAddress } from "./types";
export const Any = "?";
class Var {
constructor(public readonly name: string) {}
}
export function Variable(name: string): Var {
return new Var(name);
}
type QueryPart<T> = T | T[] | typeof Any | Var;
export class Query {
private _query: string | undefined;
public static matches(
entity: QueryPart<string>,
attribute: QueryPart<string>,
value: QueryPart<string | number | Address>
): Query {
const query = new Query();
let entityStr;
if (entity === Any) {
entityStr = "?";
} else if (entity instanceof Var) {
entityStr = `?${entity.name}`;
} else {
entityStr = Array.isArray(entity) ? `(in ${entity.join(" ")})` : entity;
}
let attributeStr;
if (attribute === Any) {
attributeStr = "?";
} else if (attribute instanceof Var) {
attributeStr = `?${attribute.name}`;
} else {
attributeStr = Array.isArray(attribute)
? `(in ${attribute.map((a) => `"${a}"`).join(" ")})`
: `"${attribute}"`;
}
let valueStr;
if (value === Any) {
valueStr = "?";
} else if (value instanceof Var) {
valueStr = `?${value.name}`;
} else {
valueStr = (Array.isArray(value) ? value : [value])
.map((v) => {
if (typeof v === "number") return v;
if (isAddress(v)) return v;
if (typeof v === "string") return `"${v}"`;
})
.join(" ");
valueStr = Array.isArray(value) ? `(in ${valueStr})` : valueStr;
}
query._query = `(matches ${entityStr} ${attributeStr} ${valueStr})`;
return query;
}
public static or(...queries: Query[]): Query {
const query = new Query();
query._query = `(or ${queries.join(" ")})`;
return query;
}
public static and(...queries: Query[]): Query {
const query = new Query();
query._query = `(and ${queries.join(" ")})`;
return query;
}
public static not(query: Query): Query {
const q = new Query();
q._query = `(not ${query})`;
return q;
}
public static join(...queries: Query[]): Query {
const query = new Query();
query._query = `(join ${queries.join(" ")})`;
return query;
}
public toString(): string {
if (!this._query) throw new Error("Query is not defined");
return this._query;
}
}