@mfissehaye/string-to-drizzle-orm-filters
Version:
103 lines • 4.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilterGenerator = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const parser_1 = require("./parser");
/**
* The FilterGenerator class converts an AST (Abstract Syntax Tree) into
* Drizzle ORM filter expressions.
*/
class FilterGenerator {
columnMap;
drizzleOperators;
constructor(columnMap) {
this.columnMap = columnMap;
// Map string function names from the input to actual Drizzle ORM functions.
// Ensure all supported operators from the grammar are included here.
this.drizzleOperators = {
eq: drizzle_orm_1.eq,
and: drizzle_orm_1.and,
or: drizzle_orm_1.or,
like: drizzle_orm_1.like,
ilike: drizzle_orm_1.ilike,
gt: drizzle_orm_1.gt,
gte: drizzle_orm_1.gte,
lt: drizzle_orm_1.lt,
lte: drizzle_orm_1.lte,
isNull: drizzle_orm_1.isNull,
isNotNull: drizzle_orm_1.isNotNull,
not: drizzle_orm_1.not,
inArray: drizzle_orm_1.inArray,
between: drizzle_orm_1.between,
notBetween: drizzle_orm_1.notBetween,
// Add other Drizzle operators as needed (e.g., inArray, between)
};
}
/**
* Generates a Drizzle ORM filter expression from the given AST.
*
* @param ast The root of the AST (Program node) to convert.
* @returns A Drizzle ORM SQL expression (or undefined if the AST's expression is null).
*/
generate(ast) {
if (!ast.expression) {
return undefined; // Or throw an error if an empty expression is not allowed.
}
return this.traverseNode(ast.expression);
}
traverseNode(node) {
switch (node.kind) {
case 'CallExpression':
return this.handleCallExpression(node);
case 'StringLiteral':
// A StringLiteral itself is not a Drizzle filter, but it's used as an argument.
// If this is called at the top-level, it's a malformed AST for a filter.
// When called recursively for arguments, it should return its value.
// throw new ParserError(`Unexpected StringLiteral as a top-level filter ${node.value}`);
return node.value;
// NEW: Handle NumberLiteral
case 'NumberLiteral':
// A NumberLiteral is also an argument type, not a filter itself.
return node.value;
default:
// This should not happen if AST is well-formed
throw new parser_1.ParserError(`Unknown AST node kind: ${node.kind}`);
}
}
/**
* Handles CallExpression nodes, converting them into Drizzle ORM function calls.
*/
handleCallExpression(node) {
const drizzleFunction = this.drizzleOperators[node.functionName];
if (!drizzleFunction) {
throw new parser_1.ParserError(`Unsupported Drizzle ORM function: '${node.functionName}'.`);
}
// Process arguments: column references or literal values
const processedArgs = node.args.map((arg) => {
if (arg.kind === 'StringLiteral') {
const isComparisonOperator = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'like', 'ilike', 'isNull', 'isNotNull', 'inArray', 'between', 'notBetween'].includes(node.functionName);
if (isComparisonOperator && this.columnMap[arg.value]) {
return this.columnMap[arg.value];
}
else {
return arg.value;
}
}
else if (arg.kind === 'NumberLiteral') { // NEW: Handle NumberLiteral directly as its numeric value
return arg.value;
}
else if (arg.kind === 'CallExpression') {
return this.traverseNode(arg);
}
return undefined; // Should not happen with current AST types
}).filter(val => val !== undefined); // remove any undefined results from mapping
try {
return drizzleFunction(...processedArgs);
}
catch (e) {
throw new parser_1.ParserError(`Error calling Drizzle function '${node.functionName}' with arguments [${processedArgs.map(a => typeof a === 'object' && a !== null && 'getSQL' in a ? a.getSQL() : JSON.stringify(a)).join(', ')}]. Original error: ${e.message}`);
}
}
}
exports.FilterGenerator = FilterGenerator;
//# sourceMappingURL=generator.js.map