leonardocaldas/composable-query-builder

Installs: 2 704

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Open Issues: 0

Type:composer-plugin

pkg:composer/leonardocaldas/composable-query-builder

v1.0.29 2025-11-26 17:16 UTC

README

A composable, type-safe query builder for TypeScript and Prisma. Efficiently handles filtering, sorting, and pagination from request parameters.

Installation

npm install @arcanalabs/query-builder

Usage

Basic Usage

Import QueryBuilder and QueryBuilderParams to start transforming request objects into Prisma-compatible arguments.

import { QueryBuilder, QueryBuilderParams } from '@arcanalabs/query-builder';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// Assume 'request.query' comes from your API framework (Express, Fastify, etc.)
// e.g. ?filter[name]=Alice&page=2&perPage=10
async function getUsers(requestQuery: any) {
    const params = QueryBuilderParams.fromRequest(requestQuery);
    
    // Create params, applying logic like allowed filters
    params.setAllowedFilters(['name', 'email']);

    const qb = QueryBuilder.for(prisma.user, params);
    
    // Execute query
    const result = await qb.get();
    
    return result; 
    // Returns: { data: [...], meta: { total, page, per_page, last_page }, aggregates: {} }
}

Advanced Filtering

Name Mapping

Map public API parameters to different internal database fields.

const params = QueryBuilderParams.fromRequest(requestQuery)
    .filterNameMapping({
        'q': 'name', // ?filter[q]=Alice -> where: { name: 'Alice' }
        'active': 'status'
    });

Custom Behaviors

Define custom logic for specific fields, such as date ranges or complex lookups.

const params = QueryBuilderParams.fromRequest(requestQuery)
    .setFilterBehaviors({
        'created_at': (value) => {
             // ?filter[created_at]=2023-01-01
            return {
                gte: `${value}T00:00:00.000Z`,
                lte: `${value}T23:59:59.999Z`
            };
        }
    });

Where In

Pass comma-separated values or an array to automatically generate in clauses.

// ?filter[status]=active,pending
// OR ?filter[status][]=active&filter[status][]=pending
// Generates: where: { status: { in: ['active', 'pending'] } }

Relation Filtering

Use dot notation to filter by related records.

// ?filter[profile.age]=25
// Generates: where: { profile: { age: 25 } }

Pagination

Pagination is handled automatically.

  • Default page: 1
  • Default perPage: 15 (Configurable via params.setPerPage(20))

Supports both per_page (snake_case) and perPage (camelCase) in query parameters.

License

MIT