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

kysforge

v0.3.5

Published

Codegen for Kysely + PostgreSQL/SQLite projects.

Readme

kysforge

Database introspection + Kysely type generation for PostgreSQL and SQLite.

A small, programmatic codegen library. No CLI, no env-var magic, you import a function, pass a config object, and get a fully-typed Database interface written to disk.

Features

  • PostgreSQL codegen: tables, views, enums, generated columns, configurable overrides
  • SQLite codegen: tables, views, generated (STORED/VIRTUAL) columns, configurable overrides
  • Programmatic API: no CLI, no env vars; call from your own script or build step
  • Kysely-native output: emits ColumnType, Generated, Selectable, Insertable, Updateable

Requirements

  • Node >=22, SQLite codegen uses the built-in node:sqlite module:
    • On Node 22–23, run your script with --experimental-sqlite
    • On Node 24+, node:sqlite is stable and no flag is needed
  • kysely >= 0.27 as a peer dep
  • For PostgreSQL: one of the following drivers as a peer dep (install only the one you use):
    • pg >=8.00.0, or
    • postgres >=3.4.9 (postgres.js) together with kysely-postgres-js >=3.0.0

Installation

npm install kysforge
# peer deps
npm install kysely

# PostgreSQL — pick ONE driver:
npm install pg                            # node-postgres, or
npm install postgres kysely-postgres-js   # postgres.js

PostgreSQL

import { pgCodegen } from "kysforge/pg";

const result = await pgCodegen({
  connection: {
    host: "localhost",
    port: 5432,          // optional, defaults to 5432
    database: "my_db",
    user: "dev",
    password: "password",
  },

  // Optional: which driver to use ("pg" or "postgres"). When omitted, the
  // driver is auto-detected at runtime ("pg" preferred, then "postgres").
  driver: "pg",

  // Optional: schemas to introspect. Defaults to ["public"].
  schemas: ["public", "auth"],

  output: {
    database: "./src/database.generated.ts",
    // Optional: write enums to a separate file.
    enums: "./src/enums.generated.ts",
    // Optional: module specifier used to import enums inside the database file.
    // If omitted, a relative path is derived automatically.
    enumsImportPath: "@my-app/shared",
  },

  // Optional: include views as read-only types in the Database interface.
  views: true,

  // Optional: override the inferred TS type for specific columns.
  overrides: {
    columns: {
      "books.type": '"book"',
      "movies.type": '"movie"',
    },
  },
});

// `result` is a PgCodegenResult, log it, print warnings, exit non-zero
// on unknown types, etc. kysforge itself does not log or call process.exit.
console.info(
  `Generated ${result.tables} table(s), ${result.enums} enum(s), ${result.views} view(s)`,
);
for (const w of result.warnings) console.warn(w);

The function returns a PgCodegenResult with the counts, the resolved databasePath / enumsPath, the schemas that were introspected, and a warnings array (e.g. unknown data types). On failure it throws, wrap the call in try/catch if you need custom error handling.

How you load the connection settings is up to you, read a .env file in your own script, pull from a secret manager, hard-code in dev, etc. kysforge itself does not touch process.env.

Choosing a driver

PostgreSQL codegen works with either pg (node-postgres) or postgres (postgres.js). These are optional peer dependencies — install only the one you use, and kysforge imports it lazily at runtime.

  • Leave driver unset to auto-detect the installed package (pg is preferred, then postgres).
  • Set driver: "pg" or driver: "postgres" explicitly to disambiguate when both packages are installed.

Using postgres.js also requires the kysely-postgres-js dialect package. If the configured (or detected) driver isn't installed, pgCodegen throws with an install hint.

Generated output (example)

import type {
  ColumnType,
  Generated,
  Insertable,
  Selectable,
  Updateable,
} from "kysely";

export interface UsersTable {
  id: Generated<string>;
  email: string;
  created_at: ColumnType<Date, string | Date | undefined, never>;
  updated_at: ColumnType<Date, string | Date | undefined, string | Date>;
}

export type User = Selectable<UsersTable>;
export type NewUser = Insertable<UsersTable>;
export type UserUpdate = Updateable<UsersTable>;

// Views are read-only: Selectable only, no Insertable / Updateable.
export interface ActiveUsersView {
  id: string | null;
  email: string | null;
}

export type ActiveUser = Selectable<ActiveUsersView>;

export interface Database {
  users: UsersTable;
  active_users: ActiveUsersView;
}

SQLite

Uses Node's built-in node:sqlite, no native dependency required.

Node 22–23: run your script with node --experimental-sqlite .... Node 24+: no flag needed.

import { sqliteCodegen } from "kysforge/sqlite";

const result = await sqliteCodegen({
  databasePath: "./data/app.db",

  output: {
    database: "./src/database.generated.ts",
  },

  // Optional: include views as read-only types in the Database interface.
  views: true,

  // Optional: override the inferred TS type for specific columns.
  overrides: {
    columns: {
      "users.metadata": "Record<string, unknown>",
    },
  },
});

// `result` is a SqliteCodegenResult with `tables`, `views`, `databasePath`,
// and a `warnings` array. Errors are thrown rather than logged.
console.info(
  `Generated ${result.tables} table(s) and ${result.views} view(s)`,
);
for (const w of result.warnings) console.warn(w);

Type mapping notes

SQLite stores values under five storage classes (INTEGER, REAL, TEXT, BLOB, NULL) but accepts arbitrary declared type names. kysforge maps only declared types that correspond to a real storage class:

  • INTEGER, INT, BIGINT, INT2, … → number
  • REAL, DOUBLE, FLOAT, NUMERIC, DECIMALnumber
  • TEXT, VARCHAR(n), CHAR, CLOBstring
  • BLOBBuffer

Anything else (e.g. BOOLEAN, DATETIME, JSONB, custom names) is recorded in the result's warnings array and resolves to unknown. Use the overrides map to plug in the type you actually want for those columns.

INTEGER PRIMARY KEY columns are detected as auto-assigned and emitted as Generated<number>. STORED and VIRTUAL generated columns are emitted as ColumnType<T, never, never>.


Resources