91 lines
2.3 KiB
TypeScript
91 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;
|
|
}
|
|
}
|