@karkinos/query-builder
v1.0.2
Published
Una librería TypeScript flexible y type-safe para construir consultas complejas de manera fluida con drizzle ORM
Maintainers
Readme
@karkinos/query-builder
Una librería TypeScript flexible y type-safe para construir consultas complejas de manera fluida. Perfecta para aplicaciones que necesitan construir filtros dinámicos para APIs.
🚀 Características
- ✅ Type-safe: Completamente tipado con TypeScript
- 🔧 Fluent API: Sintaxis intuitiva y encadenable
- 🎯 Flexible: Soporta filtros complejos, ordenamiento y paginación
🏁 Instalación
npm install @karkinos/query-builder
# o
yarn add @karkinos/query-builder
# o
bun add @karkinos/query-builderUso
import { Q, F, Utils } from '@karkinos/query-builder';
// o importaciones específicas
import { FluentQueryBuilder, FilterFactory } from '@karkinos/query-builder';📚 Uso Básico
Query Builder Fluido
import { Q } from '@karkinos/query-builder';
// Crear una consulta simple
const query = Q.create()
.whereEquals('status', 'active')
.whereGreaterThan('age', 18)
.orderBy('createdAt', 'DESC')
.paginate(1, 20)
.build();
Resultado:
{
"filters": {
"operator": "AND",
"filters": [
{ "field": "status", "operator": "eq", "value": "active" },
{ "field": "age", "operator": "gt", "value": 18 }
]
},
"sort": { "createdAt": "DESC" },
"page": 1,
"limit": 20
}Factory de Filtros
import { F } from '@karkinos/query-builder';
// Crear filtros individuales
const activeUsers = F.equals('status', 'active');
const adults = F.greaterThanOrEqual('age', 18);
const nameSearch = F.ilike('name', '%john%');
const validEmails = F.isNotNull('email');
// Rangos y fechas
const thisWeek = F.between('createdAt', startDate, endDate);
const dateRange = F.dateRange('updatedAt', new Date('2024-01-01'), new Date());Filtros Complejos con Grupos
import { Q, F, FilterGroup } from '@karkinos/query-builder';
const query = Q.create()
.setFilterGroup(
FilterGroup.and(
F.equals('status', 'active'),
FilterGroup.or(
F.equals('role', 'admin'),
F.equals('role', 'moderator')
),
F.greaterThan('lastLogin', thirtyDaysAgo)
)
)
.build();📋 API Reference
FluentQueryBuilder (Q)
Métodos de Filtrado
whereEquals(field, value)- Filtro de igualdad exactawhereNotEquals(field, value)- Filtro de no igualdadwhereGreaterThan(field, value)- Mayor quewhereGreaterThanOrEqual(field, value)- Mayor o igual quewhereLessThan(field, value)- Menor quewhereLessThanOrEqual(field, value)- Menor o igual quewhereLike(field, value)- Búsqueda de texto (case-sensitive)whereILike(field, value)- Búsqueda de texto (case-insensitive)whereIn(field, values[])- Valor está en listawhereNotIn(field, values[])- Valor no está en listawhereNull(field)- Campo es nullwhereNotNull(field)- Campo no es nullwhereBetween(field, min, max)- Valor entre rangowhereDateRange(field, start, end)- Rango de fechaswhereTextSearch(fields[], term)- Búsqueda de texto en múltiples campos
Métodos de Ordenamiento
orderBy(field, direction)- Ordenar por campoorderByMultiple(sorts)- Múltiples ordenamientosclearOrderBy()- Limpiar ordenamiento
Métodos de Paginación
page(num)- Establecer páginalimit(num)- Establecer límite por páginapaginate(page, limit)- Paginación completaclearPagination()- Limpiar paginación
Métodos de Búsqueda
search(term)- Término de búsqueda globalclearSearch()- Limpiar búsqueda
Métodos de Utilidad
build()- Construir query finalclone()- Clonar builderreset()- Resetear a estado inicialisEmpty()- Verificar si está vacío
FilterFactory (F)
Métodos de Creación
create(field, operator, value)- Factory genéricoequals(field, value)- IgualdadnotEquals(field, value)- No igualdadgreaterThan(field, value)- Mayor quelessThan(field, value)- Menor quelike(field, pattern)- Pattern matchingin(field, values)- Valor en listaisNull(field)- Es nullisNotNull(field)- No es null
Métodos de Conveniencia
between(field, min, max)- Rango entre valoresdateRange(field, start, end)- Rango de fechastextSearch(fields, term)- Búsqueda en múltiples campos
QueryUtils (Utils)
Utilidades de Alto Nivel
import { Utils } from '@karkinos/query-builder';
// Query para tablas con paginación y búsqueda
const tableQuery = Utils.createTableQuery({
page: 1,
limit: 20,
search: 'john',
sortField: 'name',
sortDirection: 'ASC'
});
// Filtros de estado comunes
const statusFilters = Utils.createStatusFilters(['active', 'pending']);
// Filtros de fechas predefinidos
const todayFilters = Utils.createDateFilters({
field: 'createdAt',
today: true
});
const thisMonthFilters = Utils.createDateFilters({
field: 'updatedAt',
thisMonth: true
});🎯 Ejemplos Avanzados
Sistema de Usuarios Complejo
import { Q, F, Utils } from '@karkinos/query-builder';
// Buscar usuarios activos con roles específicos
const activeAdmins = Q.create()
.whereEquals('status', 'active')
.whereIn('role', ['admin', 'super_admin'])
.whereNotNull('lastLogin')
.whereDateRange('createdAt',
new Date('2024-01-01'),
new Date()
)
.orderBy('lastLogin', 'DESC')
.paginate(1, 50);
// Búsqueda de texto en múltiples campos
const userSearch = Q.create()
.whereTextSearch(['name', 'email', 'username'], 'john')
.whereEquals('status', 'active');
// Filtros de fecha usando utilidades
const recentUsers = Q.create()
.and(Utils.createDateFilters({
field: 'createdAt',
thisWeek: true
}))
.whereNotNull('profileImage');E-commerce: Productos
// Productos en stock con descuentos
const discountedProducts = Q.create()
.whereGreaterThan('stock', 0)
.whereBetween('discount', 10, 50)
.whereIn('category', ['electronics', 'clothing'])
.orderBy('discount', 'DESC')
.orderBy('price', 'ASC');
// Productos más vendidos del mes
const topProducts = Q.create()
.and(Utils.createDateFilters({
field: 'lastSale',
thisMonth: true
}))
.whereGreaterThan('salesCount', 10)
.orderBy('salesCount', 'DESC')
.limit(20);Reportes y Analytics
// Reportes de ventas por período
const salesReport = Q.create()
.whereDateRange('saleDate', startDate, endDate)
.whereIn('status', ['completed', 'shipped'])
.whereNotNull('customerId')
.orderBy('saleDate', 'DESC');
// Usuarios más activos
const activeUsers = Q.create()
.whereGreaterThan('loginCount', 5)
.and(Utils.createDateFilters({
field: 'lastActivity',
thisMonth: true
}))
.orderBy('loginCount', 'DESC')
.limit(100);🔧 Extensibilidad
Crear Filtros Personalizados
import { FilterBase } from '@karkinos/query-builder';
class CustomRangeFilter extends FilterBase {
constructor(field: string, min: any, max: any) {
super({
field,
operator: 'between' as any,
value: { min, max }
});
}
static create(field: string, min: any, max: any) {
return new CustomRangeFilter(field, min, max);
}
}Extender QueryBuilder
import { FluentQueryBuilder } from '@karkinos/query-builder';
class CustomQueryBuilder extends FluentQueryBuilder {
whereActive(): this {
return this.whereEquals('status', 'active');
}
whereUser(userId: string): this {
return this.whereEquals('userId', userId);
}
recent(): this {
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
return this.whereGreaterThan('createdAt', thirtyDaysAgo);
}
}🧪 Testing
import { Q, F } from '@karkinos/query-builder';
describe('QueryBuilder', () => {
it('should build basic query', () => {
const query = Q.create()
.whereEquals('status', 'active')
.build();
expect(query.filters).toEqual({
operator: 'AND',
filters: [
{ field: 'status', operator: 'eq', value: 'active' }
]
});
});
it('should handle complex filters', () => {
const query = Q.create()
.whereBetween('age', 18, 65)
.whereIn('role', ['user', 'admin'])
.build();
expect(query.filters.filters).toHaveLength(2);
});
});📝 Tipos TypeScript
// Tipos principales exportados
export type FilterOperatorType =
| 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte'
| 'like' | 'ilike' | 'in' | 'notIn'
| 'isNull' | 'isNotNull';
export type LogicalOperator = 'AND' | 'OR';
export type SortDirection = 'ASC' | 'DESC' | 'asc' | 'desc';
export interface IQueryParams {
filters?: IFilterGroup;
search?: string;
page?: number;
limit?: number;
sort?: Record<string, SortDirection>;
}🤝 Contribuir
- Mantén la estructura de carpetas organizada
- Agrega tests para nuevas características
- Documenta con JSDoc
- Usa TypeScript estricto
- Sigue los patrones existentes
