Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

query-builder

npm install @ferrow/query-builder

CI

A chainable SQL query builder for TypeScript/Node. Builds parameterized SELECT/INSERT/UPDATE/DELETE statements with nested AND/OR WHERE conditions, joins, ordering, and limit/offset. Produces plain { sql, params } — there is no database driver dependency; hand the output to pg, mysql2, better-sqlite3, or whatever client you use.

Install

Copy src/index.ts into your project, or build this repo (npm run build) and depend on the compiled dist/.

Quickstart

import { QueryBuilder } from 'query-builder';

const { sql, params } = new QueryBuilder()
  .select(['id', 'name'])
  .from('users')
  .where({ column: 'active', op: '=', value: true })
  .orderBy('name')
  .limit(10)
  .build();
// sql:    SELECT "id", "name" FROM "users" WHERE "active" = $1 ORDER BY "name" ASC LIMIT 10
// params: [true]

Nested WHERE

.where({
  and: [
    { column: 'active', op: '=', value: true },
    { or: [
      { column: 'total', op: '>', value: 100 },
      { column: 'status', op: 'in', value: ['paid', 'shipped'] },
    ]},
  ],
})

Joins

new QueryBuilder()
  .select(['users.id', 'orders.total'])
  .from('users')
  .join('orders', 'users.id = orders.user_id', 'left') // or 'inner' (default)
  .build();

Insert / Update / Delete

new QueryBuilder().insert('users', { name: 'Ada', active: true }).build();
new QueryBuilder().update('users', { active: false }).where({ column: 'id', op: '=', value: 42 }).build();
new QueryBuilder().delete_('sessions').where({ column: 'expires_at', op: '<', value: Date.now() }).build();

Placeholder style

new QueryBuilder({ paramStyle: 'question' }); // ? instead of $1, $2, ...

API

  • new QueryBuilder({ paramStyle?: 'dollar' | 'question' })'dollar' ($1, $2, ...) is the default; 'question' (?) for MySQL/SQLite-style drivers.
  • .select(columns?), .from(table), .join(table, on, type?)type is 'inner' (default) or 'left'; on is a raw SQL condition string (e.g. 'a.id = b.a_id'), not identifier-escaped.
  • .insert(table, row), .update(table, set), .delete_(table) — note the trailing underscore on delete_ (delete is a reserved word).
  • .where(node) — a WhereCondition ({ column, op, value? }, ops: = != > < >= <= in like "is null" "is not null") or a nested { and: WhereNode[] } / { or: WhereNode[] }.
  • .orderBy(column, direction?), .limit(n), .offset(n).
  • .build(): { sql: string; params: unknown[] }.
  • escapeIdentifier(id) — double-quotes a column/table identifier (supports table.column), throwing on anything that isn't [A-Za-z_][A-Za-z0-9_]* (dot-separated).

Scope and limits

  • No database driver, connection, or execution — this only builds SQL strings and parameter arrays.
  • No SQL dialect abstraction beyond identifier quoting and placeholder style — e.g. LIMIT/OFFSET syntax is Postgres/MySQL/SQLite-compatible but not validated against a specific dialect's full grammar.
  • join()'s on clause is raw SQL you provide — it is not parsed or escaped, so don't interpolate untrusted input into it.
  • No subqueries, GROUP BY/HAVING, UNION, or CTEs.

Sponsored by Ferrow


Part of the ferrow-toolkit collection · Sponsored by Ferrow

About

Chainable SQL query builder for SELECT/INSERT/UPDATE/DELETE with nested AND/OR WHERE, joins, ordering, limit/offset, and safe identifier escaping. Produces { sql, params } — no DB driver dependency.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages