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

@bezql/query

v1.11.7

Published

Module for managing SQL connections, generating, and running queries

Downloads

47

Readme

@bezql/query

Query builder and executioner.

Supports MySQL and Postgresql.

Basic usage

Connect to Database

Connect to the database using one of the available drivers. Pass in an appropriate config for the driver being used.

The MySQL driver uses the mysql2 package under the hood, the PostGres driver uses pg.

A connection pool will be generated, with each query using a single connection from the pool.

import { Drivers } from @bezql/query;

//pass a mysql2 pool options object
const db = new Drivers.MySQL({
    host: "localhost",
    port: 3306,
    database: "myDb",
    user: "root",
    password: "MySecurePassword",
    connectionLimit: 100,
});

Build a Query

The inbuilt query builder is used to build a query step by step.

import { Query, Drivers } from @bezql/query;

const db = new Drivers.MySQL(config);

const query = db.query();

query.select("id", "name").from("User");

Execute Query

Use the appropriate function to execute a query.

Select

The fetch function accepts a generic type to define the structure of the items that will be returned.

query.select("id", "name").from("User");

const results = await query.fetch<{
  id: string;
  name: string;
}>();
results.rows.forEach((row) => {
  const { id, name } = row;
});
Sub Query Select

You can alternatively pass a query and alias to fetch from a sub query.

const subSelect = db.query();
subSelect.select("id", "name").from("User");

query.select("id", "name").from(subSelect, "SubUser");
Stream Select Results

Select results can be streamed to prevent holding too much data in memory at once.

query.select("id", "name").from("User");

await query.stream<{
  id: string;
  name: string;
}>(100, async (batch) => {
  batch.forEach((row) => {
    console.log(row.id, row.name);
  });

  //return false to exit the stream early
  return true;
});
Aggregate Results

Select results can be aggregated using the aggregate function, followed by the required aggregation.

query.select("id").from("userLogins");

query
  .aggregate()
  .count("*", "totalLogins")
  .max("loginDate", "lastLogin")
  .min("loginDate", "firstLogin")
  .avg("weekDay", "averageWeekday")
  .countDistinct("weekDay", "distinctWeekdays");

query.groupBy("id");

Insert

query
  .insert(
    {
      name: "Robert",
    },
    true
  )
  .into("User");

const result = await query.save();
console.log("INSERTED: ", result.rows_affected);
Insert multiple rows

Simply pass an array of values to insert multiple records.

query
  .insert(
    [
      {
        name: "Robert",
      },
      {
        name: "Tim",
      },
    ],
    true
  )
  .into("User");
Last Insert ID

For tables with an autogenerated ID, it is possible to return the ID of the first record inserted by the query.

This is done automatically for MySQL queries, with the first ID being returned in the results.

query
  .insert(
    [
      {
        name: "Robert",
      },
      {
        name: "Tim",
      },
    ],
    true
  )
  .into("User");

const result = await query.save();

const insertId = result.insert_id;
console.log(`FIRST INSERTED ID: ${insertId}`);

For Postgresql queries, you must first set the auto insert ID field.

query.setAutoInsertId("id");
query
  .insert(
    [
      {
        name: "Robert",
      },
      {
        name: "Tim",
      },
    ],
    true
  )
  .into("User");

const result = await query.save();

const insertId = result.insert_id;
console.log(`FIRST INSERTED ID: ${insertId}`);

Update

query.update("User").set(
  {
    name: "Bobby",
  },
  true
);

const constraints = query.constraint();
constraints.where("id", "=", 1, true);

const updateResult = await query.save();
console.log("UPDATED: ", updateResult.rows_changed);

Delete

query.delete().from("User");

const constraints = query.constraint();
constraints.where("id", "=", 1, true);

const updateResult = await query.save();
console.log("UPDATED: ", updateResult.rows_changed);

Constraints

Constraints can be used to restrict which records are returned when fetching, or which records are affected by an update or delete query.

To start adding constraints, the constraint manager must first be fetched from the query.

const query = db.query();
query.select("id", "name").from("User");

const constraints = query.constraints();

The constraint manager contains many constraining functions.

// basic where with parameterised and injected value
constraints.where("id", "=", 1, true);
//basic where with non parameterised value.
constraints.where("id", "=", 1, false);

// where in
constraints.whereIn("id", [1, 2], true);

// where not in
constraints.whereNotIn("id", [1, 2], true);

// where null
constraints.whereNull("isDeleted");

// where not null
constraints.whereNotNull("isDeleted");

Where logic

Logic can be applied to queries using the bracket and logic functions.

constraints
  .where("id", "=", 1, true)
  .and()
  .openBracket()
  .whereNull("isDeleted")
  .or()
  .where("isUnique", "=", 1, true)
  .closeBracket();

Joins

Two join functions are available for joining tables together, join and leftJoin.

query
  .select("User.id", "User.name", "UserType.type")
  .from("User")
  .join("UserType", "User.id", "UserType.id", "User.TypeId");

query
  .select("User.id", "User.name", "UserType.type")
  .from("User")
  .leftJoin("UserType", "User.id", "UserType.id", "User.TypeId");

More complex joins can also be handled by passing in a contraint function instead of the fields.

query
  .select("User.id", "User.name", "UserType.type")
  .from("User")
  .leftJoin("UserType", (contraints) => {
    constraints
      .on("UserType.id", "=", "User.id", false)
      .and()
      .on("UserType.type", "=", "member", true);
  });

Sub Query Joins

A query and alias can be passed into the join functions to join a sub query instead of a table name.

const joinQuery = db.query();
joinQuery.select("id", "group").from("UserGroup");

query.join(joinQuery, "groups", "User.groupId", "groups.id");

Disconnect

To disconnect, call the disconnect function on the database.

const db = new Drivers.MySQL({
  host: "localhost",
  port: 3306,
  database: "myDb",
  user: "root",
  password: "MySecurePassword",
  connectionLimit: 100,
});

db.disconnect();