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 🙏

© 2026 – Pkg Stats / Ryan Hefner

wilkques-database

v1.0.2

Published

Modern Node.js database query builder inspired by wilkques/database PHP package

Readme

Database Query Builder

Node.js Databases Tests License

Modern Node.js Database Query Builder
Supports MySQL, PostgreSQL, and SQLite

Quick StartAPI DocumentationExamplesFeatures

🌍 Language: English | 中文


🚀 Overview

A powerful, type-safe Node.js database query builder with fluent API and complete documentation. Supports complex queries, transaction handling, join operations, and conditional expressions, suitable for modern JavaScript/TypeScript projects.

✨ Features

🔧 Core Features

  • 🎯 Fluent API - Chainable method calls, intuitive and easy to use
  • 🔄 Multi-Database Support - Unified interface for MySQL, PostgreSQL, SQLite
  • ⚡ High Performance - Optimized query generation and connection management
  • 🔒 SQL Injection Protection - Automatic parameterized queries, safe and secure

📝 Query Features

  • 🔍 Complex Queries - SELECT, WHERE, ORDER BY, GROUP BY, HAVING
  • 🔗 JOIN Operations - INNER, LEFT, RIGHT, CROSS JOIN and subqueries
  • 📊 Aggregate Functions - COUNT, SUM, AVG, MAX, MIN
  • 🎛️ Conditional Expressions - Complete CASE WHEN and IF-ELSE support
  • 🔄 Transaction Handling - Complete transaction support and rollback mechanism

🛠️ Advanced Features

  • 📁 Subqueries - Nested queries in WHERE, FROM, JOIN
  • 🧮 Data Modification - INSERT, UPDATE, DELETE, UPSERT
  • 🔢 Atomic Operations - INCREMENT, DECREMENT atomic counters
  • 📋 Batch Operations - Optimized batch insert and update
  • 📊 Query Logging - Comprehensive query debugging and performance monitoring

📦 Installation

1. Install via npm

# Install the database query builder
npm install @wilkques/database

# Install the database driver you need
npm install mysql2          # For MySQL
npm install pg              # For PostgreSQL
npm install better-sqlite3  # For SQLite

2. Alternative: Install from Source

# Clone the repository
git clone https://github.com/wilkques/node-database.git database
cd database
npm install

🚀 Quick Start

Import and Basic Connection

// Default import (recommended)
import Database from "@wilkques/database";

// Named imports (alternative)
import { Database, Builder } from "@wilkques/database";

// CommonJS (if using require)
const Database = require("@wilkques/database").default;

// MySQL connection
const db = await Database.connect({
  driver: "mysql",
  host: "localhost",
  username: "user",
  password: "password",
  database: "mydb",
  port: 3306,
});

// PostgreSQL connection
const db = await Database.connect({
  driver: "postgres",
  host: "localhost",
  username: "user",
  password: "password",
  database: "mydb",
  port: 5432,
});

// SQLite connection
const db = await Database.connect({
  driver: "sqlite",
  database: "./database.db",
});

Basic Queries

// Simple query
const users = await db
  .table("users")
  .select("id", "name", "email")
  .where("active", true)
  .orderBy("created_at", "desc")
  .limit(10)
  .get();

// Conditional query
const posts = await db
  .table("posts")
  .select("title", "content", "author_id")
  .where("status", "published")
  .where("created_at", ">", "2024-01-01")
  .whereIn("category_id", [1, 2, 3])
  .get();

// JOIN query
const userPosts = await db
  .table("users", "u")
  .select("u.name", "p.title", "p.created_at")
  .leftJoin("posts p", "u.id", "p.author_id")
  .where("u.active", true)
  .orderBy("p.created_at", "desc")
  .get();

Conditional Expressions (CASE WHEN & IF-ELSE)

// Simple CASE statement
const users = await db
  .table("users")
  .select(
    "name",
    "email",
    db
      .case("status")
      .when("active", "Active")
      .when("inactive", "Inactive")
      .when("banned", "Banned")
      .else("Unknown")
      .end("status_text"),
  )
  .get();

// Complex conditional CASE
const orders = await db
  .table("orders")
  .select(
    "id",
    "total",
    db
      .case()
      .when((q) => q.where("total", ">", 1000), "Large Order")
      .when((q) => q.where("total", ">", 500), "Medium Order")
      .else("Small Order")
      .end("order_type"),
  )
  .get();

// Using CASE in UPDATE
await db.table("products").update({
  status: db
    .case("inventory")
    .when(0, "Out of Stock")
    .when((q) => q.where("inventory", "<", 10), "Low Stock")
    .else("In Stock")
    .end(),
});

IF-ELSE Expressions

// Simple IF expression
const users = await db
  .table("users")
  .select(
    "name",
    "email",
    db
      .if("status = 'active'", "Active User", "Inactive User")
      .as("user_status"),
  )
  .get();

// Function-based IF conditions
const products = await db
  .table("products")
  .select(
    "name",
    "price",
    db
      .if((q) => q.where("inventory", ">", 0), "In Stock", "Out of Stock")
      .as("availability"),
  )
  .get();

// Nested IF expressions
const orders = await db
  .table("orders")
  .select(
    "id",
    "total",
    db
      .if(
        "status = 'completed'",
        db.if("total > 100", "High Value", "Normal"),
        "Pending",
      )
      .as("order_category"),
  )
  .get();

// IF with subqueries
const userStats = await db
  .table("users")
  .select(
    "name",
    db
      .if(
        db.table("posts").count().whereRaw("posts.author_id = users.id"),
        "Has Posts",
        "No Posts",
      )
      .as("post_status"),
  )
  .get();

// Using IF in UPDATE
await db.table("products").update({
  status: db.if("inventory > 0", "available", "unavailable"),
  discount: db.if("price > 100", "10%", "0%"),
});

// IF in WHERE clauses
const filteredUsers = await db
  .table("users")
  .where(db.if("age >= 18", "status", "'minor'"), "active")
  .get();

Data Modification

// Insert data
const result = await db.table("users").insert({
  name: "John Doe",
  email: "[email protected]",
  created_at: new Date(),
});

// Batch insert
await db.table("users").insert([
  { name: "User 1", email: "[email protected]" },
  { name: "User 2", email: "[email protected]" },
]);

// Update data
await db.table("users").where("id", 1).update({
  name: "Jane Doe",
  updated_at: new Date(),
});

// Atomic operations
await db.table("posts").where("id", 1).increment("view_count", 1);

// Upsert operation
await db.table("settings").upsert({
  key: "theme",
  value: "dark",
});

Transaction Handling

const transaction = await db.transaction();

try {
  // Create order
  const orderId = await transaction.table("orders").insertGetId({
    user_id: userId,
    total: orderTotal,
    status: "pending",
  });

  // Add order items
  await transaction.table("order_items").insert(
    items.map((item) => ({
      order_id: orderId,
      product_id: item.product_id,
      quantity: item.quantity,
      price: item.price,
    })),
  );

  // Update inventory
  for (const item of items) {
    await transaction
      .table("products")
      .where("id", item.product_id)
      .decrement("stock", item.quantity);
  }

  await transaction.commit();
  console.log("Order created successfully");
} catch (error) {
  await transaction.rollback();
  console.error("Order creation failed:", error);
}

📚 API Documentation

Core Classes

Detailed Guides

System Documentation

💾 Supported Databases

| Database | Version Support | Driver | Feature Support | Query Logging | | -------------- | --------------- | -------------- | --------------- | ------------- | | MySQL | 5.7+ | mysql2 | ✅ Full Support | ✅ Enabled | | PostgreSQL | 9.6+ | pg | ✅ Full Support | ✅ Enabled | | SQLite | 3.x | better-sqlite3 | ✅ Full Support | ✅ Enabled |

Query Logging Support

All database drivers now support comprehensive query logging with:

  • 📝 SQL Statement Logging - Complete query text with proper syntax highlighting
  • ⚙️ Parameter Binding - All query parameters and their values
  • ⏱️ Execution Timing - Precise query execution duration in milliseconds
  • 🕐 Timestamp Tracking - Exact time when each query was executed
  • 🎛️ Log Management - Enable, disable, clear, and retrieve query logs

🧪 Testing

The project includes a complete test suite:

npm test

Test Coverage:

  • 156 tests all passed
  • 11 test suites covered
  • All core functionality verified

📁 Project Structure

lib/
├── Database.js              # Main database class
├── queries/                 # Query builder
│   ├── Builder.js          # Query builder main class
│   ├── grammar/            # SQL grammar compilers
│   └── processors/         # Result processors
├── connections/            # Database connection management
docs/                       # Complete documentation
├── api/                   # API reference
└── examples/              # Usage examples
tests/                     # Test suite
examples/                  # Example code

🔧 Advanced Usage

Custom Queries

// Raw SQL queries
const results = await db.raw(
  `
    SELECT u.*, COUNT(p.id) as post_count 
    FROM users u 
    LEFT JOIN posts p ON u.id = p.author_id 
    GROUP BY u.id
    HAVING post_count > ?
`,
  [5],
);

// Subqueries
const activeUsers = await db
  .table("users")
  .whereExists((query) => {
    query
      .table("posts")
      .whereRaw("posts.author_id = users.id")
      .where("posts.status", "published");
  })
  .get();

// Complex conditional queries with IF
const userAnalytics = await db
  .table("users")
  .select(
    "id",
    "name",
    db
      .if(
        db.table("orders").count().whereRaw("orders.user_id = users.id"),
        "Customer",
        "Prospect",
      )
      .as("customer_type"),
    db
      .if(
        (q) => q.whereRaw("created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)"),
        "New",
        "Existing",
      )
      .as("user_age"),
  )
  .get();

// Dynamic column selection with IF
const reportData = await db
  .table("products")
  .select(
    "name",
    "price",
    db.if("category = 'electronics'", "price * 0.9", "price").as("final_price"),
    db
      .if(
        db.raw("inventory > (SELECT AVG(inventory) FROM products)"),
        "High Stock",
        "Low Stock",
      )
      .as("stock_level"),
  )
  .get();

Query Logging & Debugging

// Enable query logging
db.connection.enableQueryLog();

// Execute some queries
await db.table("users").select("*").where("active", true).get();
await db.table("posts").select("title", "content").limit(10).get();
await db.raw("SELECT COUNT(*) as total FROM orders WHERE status = ?", [
  "completed",
]);

// Get query log with detailed information
const queryLog = db.connection.getQueryLog();

queryLog.forEach((entry, index) => {
  console.log(`Query ${index + 1}:`);
  console.log(`  SQL: ${entry.sql}`);
  console.log(`  Bindings: [${entry.bindings.join(", ")}]`);
  console.log(`  Timestamp: ${entry.timestamp.toISOString()}`);
  console.log(`  Duration: ${entry.duration}ms`);
  console.log("");
});

// Query log management
console.log(`Total queries logged: ${queryLog.length}`);
console.log(`Logging enabled: ${db.connection.isQueryLogEnabled()}`);

// Clear the log
db.connection.clearQueryLog();

// Disable logging
db.connection.disableQueryLog();

Query Log Features

  • 📊 Detailed Logging - Captures SQL, bindings, timestamps, and execution time
  • 🔍 Performance Monitoring - Track query execution duration for optimization
  • 🛠️ Debugging Support - Full query history for troubleshooting
  • 📈 Statistics - Analyze query patterns and performance metrics
  • 🎯 Universal Support - Available across all database drivers (MySQL, PostgreSQL, SQLite)

Database-Specific Logging

// All drivers support the same query logging API
const drivers = ['mysql', 'postgres', 'sqlite'];

for (const driver of drivers) {
  const db = await Database.connect({ driver, /* other config */ });

  // Enable logging - works on all drivers
  db.connection.enableQueryLog();

  // Execute queries - automatically logged with timing
  await db.table('users').select('*').get();

  // View logs with driver-specific SQL syntax
  const logs = db.connection.getQueryLog();
  console.log(`${driver.toUpperCase()} SQL:`, logs[0].sql);
  // MySQL:      SELECT `id`, `name` FROM `users`
  // PostgreSQL: SELECT "id", "name" FROM "users"
  // SQLite:     SELECT [id], [name] FROM [users]
}

```javascript
// Performance analysis example
db.connection.enableQueryLog();

// Execute your application queries
await executeApplicationQueries();

// Analyze performance
const logs = db.connection.getQueryLog();
const totalTime = logs.reduce((sum, entry) => sum + entry.duration, 0);
const avgTime = totalTime / logs.length;
const slowQueries = logs.filter(entry => entry.duration > 100); // > 100ms

console.log(`Total queries: ${logs.length}`);
console.log(`Total execution time: ${totalTime}ms`);
console.log(`Average query time: ${avgTime.toFixed(2)}ms`);
console.log(`Slow queries (>100ms): ${slowQueries.length}`);

// Log slow queries for optimization
slowQueries.forEach(query => {
  console.log(`SLOW: ${query.sql} (${query.duration}ms)`);
});

🤝 Contributing

Contributions and improvements are welcome!

📄 License

MIT License


🌟 If this project helps you, please give it a star!

Made with ❤️ for the Node.js community