Untitled
unknown
typescript
10 months ago
3.1 kB
14
Indexable
export type Operator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte";
export type Kind = "condition" | "group" | "not";
export type GroupType = "and" | "or";
export type Value = string | number | boolean | null;
export abstract class Expression {
abstract kind: Kind;
}
export class Conditon extends Expression {
kind: Kind = "condition";
constructor(
public column: string,
public operator: Operator,
public value: Value
) {
super();
}
}
export class Group extends Expression {
kind: Kind = "group";
constructor(public groupType: GroupType, public expressions: Expression[]) {
super();
}
}
export class Not extends Expression {
kind: Kind = "not";
constructor(public expr: Expression) {
super();
}
}
export const col = (column: string) => ({
eq: (value: Value) => new Conditon(column, "eq", value),
neq: (value: Value) => new Conditon(column, "neq", value),
gt: (value: Value) => new Conditon(column, "gt", value),
gte: (value: Value) => new Conditon(column, "gte", value),
lt: (value: Value) => new Conditon(column, "lt", value),
lte: (value: Value) => new Conditon(column, "lte", value),
});
export const and = (...expressions: Expression[]) =>
new Group("and", expressions);
export const or = (...expressions: Expression[]) =>
new Group("or", expressions);
export const not = (expr: Expression) => new Not(expr);
export const serialize = (value: unknown): string => {
if (Array.isArray(value)) {
return `(${value.map((v) => serialize(v)).join(", ")})`;
}
if (value === null) {
return "NULL";
}
if (typeof value === "boolean") {
return value ? "TRUE" : "FALSE";
}
if (typeof value === "number") {
return value.toString();
}
if (typeof value === "string") {
return `'${value.replace(/'/g, "''")}'`;
}
throw new Error(`Cannot serialize value: ${value}`);
};
export const serializeOperator = (operator: Operator): string => {
switch (operator) {
case "eq":
return "=";
case "neq":
return "<>";
case "gt":
return ">";
case "gte":
return ">=";
case "lt":
return "<";
case "lte":
return "<=";
}
throw new Error(`Cannot serialize operator: ${operator}`);
};
export const emitCondition = (condition: Conditon): string => {
return `${condition.column} ${serializeOperator(
condition.operator
)} ${serialize(condition.value)}`;
};
export const emitGroup = (group: Group): string => {
return `(${group.expressions
.map((expr) => emit(expr))
.join(` ${group.groupType.toUpperCase()} `)})`;
};
export const emitNot = (not: Not): string => {
return `(NOT ${emit(not.expr)})`;
};
export const emit = (expr: Expression): string => {
switch (expr.kind) {
case "condition":
return emitCondition(expr as Conditon);
case "group":
return emitGroup(expr as Group);
case "not":
return emitNot(expr as Not);
}
throw new Error(`Cannot emit expression: ${expr}`);
};
Editor is loading...
Leave a Comment