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

musqrat

v0.3.1

Published

A lightweight, strongly typed wrapper for using MySQL in Node.js

Readme

musqrat

A lightweight, strongly typed wrapper for using MySQL in Node.JS.

Inspired by using mongoose, I wanted something with a similar chaining behaviour for MySQL plus the benefits of TypeScript while building queries.

Dependencies

  • mysql2
  • TypeScript

Currently Supports

Examples

Connecting to a MySQL database

import musqrat from "musqrat";

// Uses the mysql.Pool type: https://github.com/mysqljs/mysql#pool-options
musqrat.connect({
    username: "username",
    password: "password",
    host: "localhost",
    database: "testDB",
});

if (musqrat.connected) {
    console.log("Woohoo!");
}

await musqrat.disconnect();

Defining a table

interface TableSchema = {
    tableId: number;
    column: string;
    nullableColumn?: string;
}

const Table = musqrat.initTable<TableSchema>('TableName');

Building Queries vs Executing Queries

// Each query operation can be used to build a prepared statement or execute against the database if the
// connection object is given.
console.log(Table.delete().query);
await Table.delete().exec();

Deleting

// Deletes everything, no conditions. Use limit/orderBy/where to be more specific.
await Table.delete().exec();

Inserting

// Insert accepts a single object or array of objects.
// INSERT INTO TableName (tableId, column) VALUES (1, 'value');
await Table.insert({tableId: 1, column: 'value'}).exec();
// INSERT INTO TableName (tableId, column) VALUES (1, 'value'), (2, 'another');
await Table.insert([{tableId: 1, column: 'value'}, {tableId: 2, column: 'another'}]).exec();

// You can also identify primary keys when creating the table that can be excluded from insertion
// (i.e. if they are AUTO_INCREMENT)
const Table = musqrat.initTable<TableSchema, 'tableId'>('TableName');
// Now this is invalid
await Table.insert({tableId: 1, column: 'value'}).exec();
// This is valid
await Table.insert({column: 'value'}).exec();

Selecting

// SELECT tableId, column FROM TableName;
await Table.select("tableId", "column").exec();

// SELECT * FROM TableName;
await Table.select().exec();

Updating

// Update accepts a single object or array of objects
// UPDATE TableName SET column = 'new value';
await Table.update({ field: "column", value: "new value" }).exec();

// UPDATE TableName SET column = 'new value', nullableColumn = NULL;
await Table.update([
    { field: "column", value: "new value" },
    { field: "nullableColumn", value: null },
]).exec();

Group By

// Available on select only
// SELECT * FROM TableName GROUP BY column;
await Table.select().groupBy("column").exec();

Inner Join

// Available on select only
interface JoinSchema = {
    joinId: number;
    tableId: number;
}
// SELECT tableId, joinId FROM TableName INNER JOIN JoinTable ON tableId = tableId;
await Table.select<[JoinSchema]>('tableId', 'joinId').innerJoin('JoinTable', 'tableId', 'tableId').exec();

Limit

// Available on select, update, delete
// SELECT * FROM TableName LIMIT 1;
await Table.select().limit(1).exec();

Order By

// Available on select, update, delete
// SELECT * FROM TableName ORDER BY column ASC;
await Table.select().orderBy("column").exec();

// SELECT * FROM TableName ORDER BY column DESC;
await Table.select().orderBy("column", "DESC").exec();

Where

// Available on select, update, delete
// SELECT * FROM TableName WHERE tableId IN (1, 2, 3);
await Table.select().where("tableId", "in", [1, 2, 3]).exec();

// UPDATE TableName SET nullableColumn = NULL WHERE (column = 'specific' AND nullableColumn IS NOT NULL);
await Table.update({ field: "nullableColumn", value: null })
    .where({
        AND: [
            { field: "column", operator: "=", value: "specific" },
            { field: "nullableColumn", operator: "IS NOT", value: null },
        ],
    })
    .exec();

// WHERE conditions can be built using either a single where condition or an 'aggregation'
// which is an object like you see in the second example that looks like this: {AND?: <>, OR?: <>}
// You can nest those as far down as you need to.

TODO

  • Bugs
    • groupBy can't be called in a 'logical' (to me) order. where is usually first, groupBy isn't on QueryStatment
  • Improvements
    • Don't allow duplicates on select statement fields
    • Overload for inner join that accepts just 1 parameter that is a key on both types and uses the USING syntax?
  • Options to calls
  • Advanced uses
    • Views
    • Unions
    • Sub queries
    • Function calls/stored procs?