api-v1/db/queryHelper/API_REFERENCE.md

6.4 KiB

Query Helper API Reference

This document provides a complete reference for the JSON-based database query helper.

Method Overview

Method Description Notes
select(options) Retrieve records from database JSON-based query builder
insert(options) Insert new record(s) Single or batch insert
update(options) Update existing records Requires WHERE clause
deleteRecord(options) Delete records Requires WHERE clause
execute(options) Execute transactions or custom queries Transactions or raw builder

Detailed Method Reference

SELECT

Retrieve records from database with filtering, sorting, and pagination.

const users = await select({
    table: 'users',
    where: { deleted: false, status: 'active' },
    orderBy: { column: 'created_at', direction: 'desc' },
    limit: 20
});

Options:

  • table (string, required): Table name (must be in whitelist)
  • columns (string[] | '', optional): Columns to select (default: '')
  • where (object, optional): WHERE conditions
  • orderBy (object, optional): { column: string, direction: 'asc'|'desc' }
  • limit (number, optional): Max records (capped at 100)
  • offset (number, optional): Skip records
  • joins (array, optional): Join configurations

INSERT

Insert new record(s) into database.

const user = await insert({
    table: 'users',
    data: { name: 'John', phone: '+1234567890' },
    returning: ['id', 'name']
});

Options:

  • table (string, required): Table name
  • data (object | object[], required): Data to insert (single object or array for batch)
  • returning (string[] | '*', optional): Columns to return (PostgreSQL)

UPDATE

Update existing records in database.

const updated = await update({
    table: 'users',
    data: { name: 'Jane' },
    where: { id: userId }
});

Options:

  • table (string, required): Table name
  • data (object, required): Data to update
  • where (object, required): WHERE conditions (required for safety)
  • returning (string[] | '*', optional): Columns to return

DELETE

Delete records from database.

await deleteRecord({
    table: 'users',
    where: { id: userId }
});

Options:

  • table (string, required): Table name
  • where (object, required): WHERE conditions (required for safety)
  • returning (string[] | '*', optional): Columns to return

EXECUTE (Transaction)

Execute transactions or custom query builder logic.

await execute({
    type: 'transaction',
    handler: async (trx) => {
        await trx('animals').insert(animalData);
        await trx('listings').insert(listingData);
    }
});

Options:

  • type (string, required): 'transaction' or 'raw-builder'
  • handler (function, required): Handler function receiving knex/trx instance

WHERE Clause Operators

Operator Description Example
Equality Simple key-value match where: { status: 'active' }
> Greater than where: { price: { op: '>', value: 100 } }
< Less than where: { age: { op: '<', value: 18 } }
>= Greater than or equal where: { price: { op: '>=', value: 100 } }
<= Less than or equal where: { age: { op: '<=', value: 65 } }
!= or <> Not equal where: { status: { op: '!=', value: 'deleted' } }
in In array where: { id: { op: 'in', value: [1, 2, 3] } }
notIn Not in array where: { id: { op: 'notIn', value: [1, 2, 3] } }
like Case-sensitive LIKE where: { name: { op: 'like', value: '%John%' } }
ilike Case-insensitive LIKE where: { name: { op: 'ilike', value: '%john%' } }
between Between two values where: { age: { op: 'between', value: [18, 65] } }
isNull IS NULL where: { deleted_at: { op: 'isNull' } }
isNotNull IS NOT NULL where: { deleted_at: { op: 'isNotNull' } }

Supported Operators

Operator Description Example
> Greater than { op: '>', value: 100 }
< Less than { op: '<', value: 100 }
>= Greater than or equal { op: '>=', value: 100 }
<= Less than or equal { op: '<=', value: 100 }
!= or <> Not equal { op: '!=', value: 'deleted' }
in In array { op: 'in', value: [1, 2, 3] }
notIn Not in array { op: 'notIn', value: [1, 2, 3] }
like Case-sensitive LIKE { op: 'like', value: '%test%' }
ilike Case-insensitive LIKE { op: 'ilike', value: '%test%' }
between Between two values { op: 'between', value: [10, 20] }
isNull IS NULL { op: 'isNull' }
isNotNull IS NOT NULL { op: 'isNotNull' }

Naming Conventions

  • Table names: lowercase, snake_case (e.g., users, listing_media)
  • Column names: lowercase, snake_case (e.g., created_at, user_id)
  • Options: camelCase (e.g., orderBy, returning)
  • Operators: lowercase (e.g., op: '>')

Type System

  • JavaScript: JSON objects with runtime validation
  • Runtime Validation: Descriptive errors for invalid inputs
  • Type Safety: Structured JSON prevents SQL injection

Error Handling

  • Runtime Validation: All inputs validated at runtime
  • Descriptive Errors: Clear error messages for debugging
  • Database Errors: Propagated with context

Transactions

await execute({
    type: 'transaction',
    handler: async (trx) => {
        await trx('users').insert(userData);
        await trx('listings').insert(listingData);
    }
});

Migration Checklist

When migrating from raw SQL to queryHelper:

  • Replace pool.query() with select(), insert(), update(), or deleteRecord()
  • Convert SQL WHERE clauses to JSON objects
  • Replace string concatenation with structured options
  • Convert transactions to execute({ type: 'transaction' })
  • Update JOINs to use joins array
  • Replace parameterized queries with JSON where conditions
  • Test all queries to ensure same results
  • Remove all raw SQL strings from service layer

Benefits

  1. Type Safety: Structured JSON prevents SQL injection
  2. Readability: Clear, self-documenting queries
  3. Maintainability: Easy to modify and extend
  4. Security: Table whitelist prevents unauthorized access
  5. Consistency: Uniform query interface across codebase
  6. Testing: Easier to mock and test