UNPKG

@mfissehaye/string-to-drizzle-orm-filters

Version:
103 lines 4.6 kB
"use strict"; 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