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

vulcyn

v0.0.7

Published

An ergonomic Postgres query builder for TypeScript.

Readme

Vulcyn

An ergonomic Postgres query builder for TypeScript.

Build Status

A Work in Progress

This project is still very much under construction. It was inspired by (and some of the API was shamelessly stolen from) the mammoth library.

This is mostly meant to be a fun project for me to work on in my spare time. It is missing many features and should not be incorporated into any other project at this point.

Goals

Embrace SQL

I love SQL and this project does too. Importantly, Vulcyn is not an ORM and its usage should make sense to someone who has never seen the library but who knows SQL.

Painless Client Typing

You shouldn't need to declare interfaces that are not well-typed in order to marshall your data into and out of SQL. The appropriate db.select call in Vulcyn should return the correct interface with all of the known types.

Examples

Declaring Tables

Simply write your tables as a class that extends Table using the various Column classes. Pass an object with all of your tables into the Database call.

import { Client } from "pg";
import { Database, IntColumn, SerialColumn, Table, TextColumn } from "Vulcyn";

class UserTable extends Table {
  id = new SerialColumn();
  name = new TextColumn();
  age = new IntColumn();
  address = new TextColumn().nullable();
}

const pg = new Client();
await pg.connect();
const db = Database(pg, {
  users: new UserTable(),
});
await db.createTables();

There's currently no support for migrations or anything similar. db.createTables simply issues a CREATE TABLE statement for every table that you've defined.

Querying Data

// Has type Array<{ id: number; name: string; address: string | null }>
const users = db.select(db.users, "id", "name", "address");

You can also add WHERE clauses. The and and or functions provide a syntactically nice way to do this.

const teenagers = db
  .select(db.users, "id", "name", "address")
  .where(and(db.users.age.gte(13), db.users.age.lte(19)));

If you try do do bad things™, you'll get type errors.

// TS2345: Argument of type '"foo"' is not assignable to parameter of type '"id" | "name" | "address"
db.select(db.users, "foo");

db.select(db.users, "address").then((users) => {
  users.forEach(({address}) => {
    // TS2531: Object is possibly 'null'.
    console.log(address.toUpperCase());
  })
);

Inserting Data

Single-row insertion is super simply (and statically typed!). Columns with defaults (including nullable columns) need not be specified.

await db
  .insertInto(db.users)
  .values({,
    name: "Sylvia The Cat",
  });

If you try do do bad things™, you'll get type errors.

// TS2322: Type 'string' is not assignable to type 'number'.
await db.insertInto(db.users).values({
  name: "Sylvia The Cat",
});

Updating Data

await db
  .update(db.users)
  .set({
    name: "Sylvia, Queen of Cats",
  })
  .where(db.users.name.eq("Sylvia The Cat"));

SQL Safety

All parameters passed into queries are forwarded to Postgres via parameter values ($1, $2, ...). You can inspect the SQL generated as well.

console.log(
  db
    .insertInto(db.users)
    .values({
      id: 123,
      name: "Sylvia The Cat",
    })
    .$toSQL(),
);
// INSERT INTO users (id, name) VALUES ($1, $2);

Warts

  • There is some inconsistency about what things should be constructed with new and which things are constructed just with function calls. The reason for this is because classes can't implement interfaces with generics.