npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@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

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-builder

Uso

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 exacta
  • whereNotEquals(field, value) - Filtro de no igualdad
  • whereGreaterThan(field, value) - Mayor que
  • whereGreaterThanOrEqual(field, value) - Mayor o igual que
  • whereLessThan(field, value) - Menor que
  • whereLessThanOrEqual(field, value) - Menor o igual que
  • whereLike(field, value) - Búsqueda de texto (case-sensitive)
  • whereILike(field, value) - Búsqueda de texto (case-insensitive)
  • whereIn(field, values[]) - Valor está en lista
  • whereNotIn(field, values[]) - Valor no está en lista
  • whereNull(field) - Campo es null
  • whereNotNull(field) - Campo no es null
  • whereBetween(field, min, max) - Valor entre rango
  • whereDateRange(field, start, end) - Rango de fechas
  • whereTextSearch(fields[], term) - Búsqueda de texto en múltiples campos

Métodos de Ordenamiento

  • orderBy(field, direction) - Ordenar por campo
  • orderByMultiple(sorts) - Múltiples ordenamientos
  • clearOrderBy() - Limpiar ordenamiento

Métodos de Paginación

  • page(num) - Establecer página
  • limit(num) - Establecer límite por página
  • paginate(page, limit) - Paginación completa
  • clearPagination() - Limpiar paginación

Métodos de Búsqueda

  • search(term) - Término de búsqueda global
  • clearSearch() - Limpiar búsqueda

Métodos de Utilidad

  • build() - Construir query final
  • clone() - Clonar builder
  • reset() - Resetear a estado inicial
  • isEmpty() - Verificar si está vacío

FilterFactory (F)

Métodos de Creación

  • create(field, operator, value) - Factory genérico
  • equals(field, value) - Igualdad
  • notEquals(field, value) - No igualdad
  • greaterThan(field, value) - Mayor que
  • lessThan(field, value) - Menor que
  • like(field, pattern) - Pattern matching
  • in(field, values) - Valor en lista
  • isNull(field) - Es null
  • isNotNull(field) - No es null

Métodos de Conveniencia

  • between(field, min, max) - Rango entre valores
  • dateRange(field, start, end) - Rango de fechas
  • textSearch(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

  1. Mantén la estructura de carpetas organizada
  2. Agrega tests para nuevas características
  3. Documenta con JSDoc
  4. Usa TypeScript estricto
  5. Sigue los patrones existentes

🔗 Links Útiles