UNPKG

@flavoai/fastfold

Version:

Zero-boilerplate backend for React apps with auto-generated CRUD and declarative security

194 lines 6.63 kB
import { eq, and, sql } from 'drizzle-orm'; export class DrizzleAdapter { db; schema; constructor(db, schema) { this.db = db; this.schema = schema; } /** * Get table schema object by name */ getTable(tableName) { const table = this.schema[tableName]; if (!table) { throw new Error(`Table '${tableName}' not found in schema`); } return table; } /** * Query records from a table */ async query(tableName, params = {}) { const table = this.getTable(tableName); let query = this.db.select().from(table); // Apply where conditions if (params.where) { const conditions = this.buildWhereConditions(table, params.where); if (conditions.length > 0) { query = query.where(and(...conditions)); } } // Apply ordering if (params.orderBy) { const orderConditions = Object.entries(params.orderBy).map(([field, direction]) => { const column = table[field]; if (!column) throw new Error(`Column '${field}' not found in table '${tableName}'`); return direction === 'desc' ? sql `${column} DESC` : sql `${column} ASC`; }); query = query.orderBy(...orderConditions); } // Apply pagination if (params.limit) { query = query.limit(params.limit); } if (params.offset) { query = query.offset(params.offset); } return await query; } /** * Create a new record */ async create(tableName, data) { const table = this.getTable(tableName); const result = await this.db.insert(table).values(data).returning(); return result[0]; } /** * Update a record by ID */ async update(tableName, id, data) { const table = this.getTable(tableName); const result = await this.db .update(table) .set(data) .where(eq(table.id, id)) .returning(); if (result.length === 0) { throw new Error(`Record with id '${id}' not found in table '${tableName}'`); } return result[0]; } /** * Delete a record by ID */ async delete(tableName, id) { const table = this.getTable(tableName); const result = await this.db .delete(table) .where(eq(table.id, id)) .returning(); return result.length > 0; } /** * Count records in a table */ async count(tableName, where) { const table = this.getTable(tableName); let query = this.db.select({ count: sql `count(*)` }).from(table); if (where) { const conditions = this.buildWhereConditions(table, where); if (conditions.length > 0) { query = query.where(and(...conditions)); } } const result = await query; return parseInt(result[0].count); } /** * Find a single record by ID */ async findById(tableName, id) { const table = this.getTable(tableName); const result = await this.db .select() .from(table) .where(eq(table.id, id)) .limit(1); return result[0] || null; } /** * Query with relations using Drizzle's relational query API */ async queryWithRelations(tableName, params = {}) { if (!this.db.query || !this.db.query[tableName]) { // Fallback to regular query if relational API not available return this.query(tableName, params); } let query = {}; // Apply where conditions if (params.where) { query.where = (table, { eq, and }) => { const conditions = Object.entries(params.where).map(([field, value]) => { return eq(table[field], value); }); return conditions.length === 1 ? conditions[0] : and(...conditions); }; } // Apply relations if (params.with) { query.with = params.with; } // Apply ordering if (params.orderBy) { query.orderBy = (table, { desc, asc }) => { return Object.entries(params.orderBy).map(([field, direction]) => { return direction === 'desc' ? desc(table[field]) : asc(table[field]); }); }; } // Apply pagination if (params.limit) { query.limit = params.limit; } if (params.offset) { query.offset = params.offset; } return await this.db.query[tableName].findMany(query); } /** * Build where conditions for Drizzle queries */ buildWhereConditions(table, where) { return Object.entries(where).map(([field, value]) => { const column = table[field]; if (!column) throw new Error(`Column '${field}' not found`); if (typeof value === 'object' && value !== null) { // Handle operators like { gte: 18 }, { in: [1, 2, 3] } const [operator, operatorValue] = Object.entries(value)[0]; switch (operator) { case 'gte': return sql `${column} >= ${operatorValue}`; case 'lte': return sql `${column} <= ${operatorValue}`; case 'gt': return sql `${column} > ${operatorValue}`; case 'lt': return sql `${column} < ${operatorValue}`; case 'in': return sql `${column} IN ${operatorValue}`; case 'notIn': return sql `${column} NOT IN ${operatorValue}`; case 'like': return sql `${column} LIKE ${operatorValue}`; default: return eq(column, value); } } return eq(column, value); }); } /** * Get available table names from schema */ getTableNames() { return Object.keys(this.schema).filter(key => { // Filter out relation definitions (they typically end with 'Relations') return !key.endsWith('Relations') && typeof this.schema[key] === 'object'; }); } } //# sourceMappingURL=drizzle.js.map