@jakub.knejzlik/ts-query
Version:
TypeScript implementation of SQL builder
233 lines (232 loc) • 8.15 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.OperationExpression = exports.FunctionExpression = exports.RawExpression = exports.ValueExpression = exports.Expression = exports.ExpressionBase = void 0;
const Condition_1 = require("./Condition");
class ExpressionBase {
static deserialize(value) {
if (value instanceof Date) {
return ValueExpression.deserialize(value);
}
const valueIsString = typeof value === "string";
if (valueIsString && RawExpression.isValueString(value)) {
return RawExpression.deserialize(value);
}
if (valueIsString && ValueExpression.isValueString(value)) {
return ValueExpression.deserialize(value);
}
if (valueIsString && FunctionExpression.isValidString(value)) {
return FunctionExpression.deserialize(value);
}
if (valueIsString && OperationExpression.isValidString(value)) {
return OperationExpression.deserialize(value);
}
if (value instanceof RawExpression) {
return value;
}
if (valueIsString ||
(value instanceof Expression && typeof value.value === "string")) {
const condition = Condition_1.Condition.deserialize(value instanceof Expression ? value.value : value);
if (condition !== null) {
return condition;
}
}
if (valueIsString ||
typeof value === "number" ||
typeof value === "bigint" ||
typeof value === "boolean") {
const expr = new Expression(value);
return expr;
}
if (value instanceof Condition_1.Condition) {
return Condition_1.Condition.deserialize(value);
}
return value;
}
static deserializeValue(value) {
if (value instanceof FunctionExpression) {
throw new Error("FunctionExpression cannot be used as a value");
}
if (value instanceof ValueExpression) {
return value;
}
if (value instanceof RawExpression) {
return value;
}
if (typeof value === "string" && RawExpression.isValueString(value)) {
return RawExpression.deserialize(value);
}
return ValueExpression.deserialize(value);
}
static deserializeRaw(value) {
return RawExpression.deserialize(value);
}
toSQL(_, __) {
throw new Error("Method not implemented.");
}
serialize() {
throw new Error("Method not implemented.");
}
}
exports.ExpressionBase = ExpressionBase;
class Expression extends ExpressionBase {
constructor(value) {
super();
this.value = value;
}
toSQL(flavor, options) {
if (this.value instanceof Expression) {
return this.value.toSQL(flavor, options);
}
let value = `${this.value}`;
const stringMatches = value.match(/&([^#]+)&/g);
if (stringMatches) {
for (const match of stringMatches) {
value = value.replace(match, flavor.escapeValue(match.substring(1, match.length - 1)));
}
}
const matches = value.match(/#([^#]+)#/g);
if (matches) {
for (const match of matches) {
value = value.replace(match, flavor.escapeColumn(match.substring(1, match.length - 1)));
}
}
return flavor.escapeColumn(value, true);
}
serialize() {
return `${this.value}`;
}
static escapeColumn(column) {
return `#${column}#`;
}
static escapeString(column) {
return `&${column}&`;
}
static escapeExpressionValue(column) {
if (typeof column === "string" || typeof column === "number") {
return this.escapeColumn(column);
}
if (column instanceof FunctionExpression) {
throw new Error("FunctionExpression cannot be used as a value");
}
if (column instanceof Expression) {
return `${column.value}`;
}
throw new Error(`Invalid expression value: ${column}`);
}
}
exports.Expression = Expression;
class ValueExpression extends Expression {
static isValueString(str) {
return str.startsWith("!!!") || this.isValueDateString(str);
}
static isValueDateString(str) {
return str.startsWith("!D!");
}
toSQL(flavor, options) {
if (typeof this.value === "number" ||
typeof this.value === "string" ||
typeof this.value === "bigint" ||
typeof this.value === "boolean" ||
this.value instanceof Date) {
return flavor.escapeValue(this.value);
}
return this.value.toSQL(flavor, options);
}
serialize() {
if (this.value instanceof Date) {
return `!D!` + this.value.valueOf() + "!!";
}
return `!!!` + JSON.stringify(this.value);
}
static deserialize(value) {
const isStringValue = typeof value === "string";
if (isStringValue && ValueExpression.isValueString(value)) {
if (ValueExpression.isValueDateString(value)) {
return new ValueExpression(new Date(parseInt(value.substring(3, value.length - 2), 10)));
}
const res = new ValueExpression(JSON.parse(value.substring(3)));
return res;
}
return new ValueExpression(value);
}
}
exports.ValueExpression = ValueExpression;
class RawExpression extends Expression {
static isValueString(str) {
return str.startsWith("!!") && str.endsWith("!!");
}
toSQL(flavor, _) {
return flavor.escapeRawValue(this.value);
}
serialize() {
return `!!` + JSON.stringify(this.value) + "!!";
}
static deserialize(value) {
if (typeof value === "string" &&
value.startsWith("!!") &&
value.endsWith("!!")) {
const res = new RawExpression(JSON.parse(value.substring(2, value.length - 2)));
return res;
}
throw new Error(`Invalid raw expression: '${value}'`);
}
}
exports.RawExpression = RawExpression;
class FunctionExpression extends Expression {
constructor(name, ...args) {
super(args);
this.name = name;
}
toSQL(flavor, _) {
return flavor.escapeFunction(this);
}
static isValidString(str) {
return str.startsWith("FN(") && str.endsWith(")");
}
static deserialize(value) {
if (typeof value === "string") {
const content = value.substring(3, value.length - 1);
const [name, ...args] = JSON.parse(content);
return new FunctionExpression(name, ...args.map(Expression.deserialize));
}
throw new Error(`Invalid function expression: '${value}'`);
}
serialize() {
return (`FN(` +
JSON.stringify([
this.name,
...this.value.map((v) => Expression.deserialize(v).serialize()),
]) +
`)`);
}
}
exports.FunctionExpression = FunctionExpression;
class OperationExpression extends Expression {
constructor(operation, ...args) {
super(args);
this.operation = operation;
}
toSQL(flavor, _) {
return flavor.escapeOperation(this);
}
static isValidString(str) {
return str.startsWith("OP(") && str.endsWith(")");
}
static deserialize(value) {
if (typeof value === "string") {
const content = value.substring(3, value.length - 1);
const [operation, ...args] = JSON.parse(content);
return new OperationExpression(operation, ...args.map(Expression.deserialize));
}
throw new Error(`Invalid function expression: '${value}'`);
}
serialize() {
return (`OP(` +
JSON.stringify([
this.operation,
...this.value.map((v) => Expression.deserialize(v).serialize()),
]) +
`)`);
}
}
exports.OperationExpression = OperationExpression;
;