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

@takinprofit/sqlite-x

v1.2.3

Published

A modern node:sqlite wrapper for TypeScript

Readme

@takinprofit/sqlitex

A powerful, type-safe SQLite query builder and database wrapper for Node.js, featuring prepared statement caching, JSON column support, and SQL template literals.

MIT License npm version

Table of Contents

Features

  • 🔒 Type-safe SQL template literals
  • 🚀 Prepared statement caching
  • 📦 First-class JSON column support
  • 🛠️ Strong schema validation
  • 🔄 SQL query composition
  • ⚙️ Comprehensive PRAGMA configuration
  • 🌟 Modern async/iterator support

Installation

npm install @takinprofit/sqlitex

Quick Start

import { DB } from '@takinprofit/sqlitex';

// Create a database connection
const db = new DB({
  location: ':memory:',
  environment: 'development'
});

// Define your table type
interface User {
  id: number;
  name: string;
  age: number;
  metadata: {
    preferences: {
      theme: string;
      notifications: boolean;
    };
  };
}

// Create a table
db.exec(`
  CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    age INTEGER,
    metadata TEXT
  )
`);

// Insert with type safety and JSON support
const insert = db.sql<User>`
  INSERT INTO users (name, age, metadata)
  VALUES (${'$name'}, ${'$age'}, ${'$metadata->json'})
`;

insert.run({
  name: 'John Doe',
  age: 30,
  metadata: {
    preferences: {
      theme: 'dark',
      notifications: true
    }
  }
});

// Type-safe queries with automatic JSON parsing
const getUser = db.sql<{id: number}>`
  SELECT *, json_extract(metadata, '$') as metadata
  FROM users
  WHERE id = ${'$id'}
`;

const user = getUser.get({ id: 1 });
console.log(user.metadata.preferences.theme); // 'dark'

Core Concepts

Database Connection

SQLiteX provides comprehensive database configuration through the DBOptions interface:

interface DBOptions {
  // Database file path or ":memory:" for in-memory database
  location?: string | ":memory:"

  // Statement cache configuration - boolean for defaults or detailed options
  statementCache?: boolean | {
    maxSize: number
    maxAge?: number
  }

  // SQLite PRAGMA settings
  pragma?: {
    journalMode?: "DELETE" | "TRUNCATE" | "PERSIST" | "MEMORY" | "WAL" | "OFF"
    synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA"
    cacheSize?: number
    mmapSize?: number
    tempStore?: "DEFAULT" | "FILE" | "MEMORY"
    lockingMode?: "NORMAL" | "EXCLUSIVE"
    busyTimeout?: number
    foreignKeys?: boolean
    walAutocheckpoint?: number
    trustedSchema?: boolean
  }

  // Runtime environment affecting default PRAGMA settings
  environment?: "development" | "testing" | "production"

  // Custom logger implementation
  logger?: Logger

  // SQL formatting configuration
  format?: {
    indent?: string
    reservedWordCase?: "upper" | "lower"
    linesBetweenQueries?: number | "preserve"
  } | false
}

// Example usage with various options:
const db = new DB({
  location: 'path/to/db.sqlite',
  environment: 'production',
  statementCache: {
    maxSize: 100,
    maxAge: 3600000 // 1 hour
  },
  pragma: {
    journalMode: 'WAL',
    synchronous: 'NORMAL',
    foreignKeys: true,
    busyTimeout: 5000
  },
  format: {
    indent: '  ',
    reservedWordCase: 'upper',
    linesBetweenQueries: 1
  }
});

SQL Template Literals and SqlContext

SQLiteX provides a powerful SQL template literal system combined with the SqlContext interface for type-safe query building:

interface SqlContext<P extends DataRow> {
  // Column selection for SELECT statements
  cols?: (keyof P | FromJson<P> | ToJson<P>)[] | "*"

  // Values for INSERT statements
  values?: InsertOptions<P>

  // Column updates for UPDATE statements
  set?: SetOptions<P>

  // WHERE clause conditions
  where?: WhereClause<P>

  // ORDER BY configuration
  orderBy?: Partial<Record<keyof P, "ASC" | "DESC">>

  // LIMIT and OFFSET
  limit?: number
  offset?: number

  // RETURNING clause
  returning?: (keyof P)[] | "*"

  // Column definitions for CREATE TABLE
  columns?: Columns<P>
}

// Examples using SqlContext:

interface Post {
  id: number;
  title: string;
  userId: number;
  tags: string[];
  metadata: {
    views: number;
    lastModified: string;
  };
  status: 'draft' | 'published';
}

// INSERT with JSON and returning values
const createPost = db.sql<Post>`
  INSERT INTO posts
  ${{
    values: ['$title', '$userId', '$tags->json', '$metadata->json', '$status'],
    returning: ['id', 'created_at']
  }}
`;

// Complex SELECT with multiple conditions
const getPosts = db.sql<{
  userId: number,
  minViews: number,
  status: string
}>`
  SELECT ${{
    cols: ['id', 'title', 'metadata<-json', 'tags<-json']
  }}
  FROM posts
  ${{
    where: [
      'userId = $userId',
      'AND',
      'json_extract(metadata, "$.views") > $minViews',
      'AND',
      'status = $status'
    ],
    orderBy: {
      id: 'DESC'
    },
    limit: 10
  }}
`;

// Query Composition Examples

// Base query
let query = db.sql<{
  status: string,
  userId?: number,
  search?: string
}>`SELECT ${{
  cols: ['posts.*', 'metadata<-json', 'users.name as author']
}} FROM posts
LEFT JOIN users ON posts.userId = users.id`;

// Conditional WHERE clauses
if (params.status) {
  query = query.sql`${{
    where: 'status = $status'
  }}`;
}

// Add user filter if provided
if (params.userId) {
  query = query.sql`${{
    where: ['posts.userId = $userId']
  }}`;
}

// Add search condition if needed
if (params.search) {
  query = query.sql`${{
    where: ['title LIKE $search']
  }}`;
}

// Finalize with ordering and limits
query = query.sql`${{
  orderBy: {
    'posts.created_at': 'DESC'
  },
  limit: 20
}}`;

// UPDATE example with JSON modification
const updatePost = db.sql<Post & { newTags: string[] }>`
  UPDATE posts
  ${{
    set: [
      '$title',
      '$status',
      '$metadata->json',
      // Merge existing tags with new ones using JSON functions
      'tags = json_array(json_group_array(
        DISTINCT value)
      ) FROM (
        SELECT value FROM json_each($tags)
        UNION
        SELECT value FROM json_each($newTags)
      )'
    ],
    where: 'id = $id',
    returning: '*'
  }}
`;

Type Safety

SQLiteX provides comprehensive type safety:

interface Article {
  id: number;
  title: string;
  views: number;
  metadata: {
    authors: string[];
    categories: string[];
  };
}

// Column definitions are type-checked
const createTable = db.sql<Article>`
  CREATE TABLE articles ${
    columns: {
      id: 'INTEGER PRIMARY KEY',
      title: 'TEXT NOT NULL',
      views: 'INTEGER DEFAULT 0',
      metadata: 'TEXT'  // For JSON storage
    }
  }
`;

// Query parameters are type-checked
const updateViews = db.sql<Article>`
  UPDATE articles
  ${{
    set: ['$views'],
    where: 'id = $id',
    returning: ['views']
  }}
`;

// This will cause a type error
updateViews.run({
  id: 1,
  views: 'invalid'  // Type error: expected number
});

JSON Support

First-class JSON column support with type safety:

interface Product {
  id: number;
  name: string;
  specs: {
    dimensions: {
      width: number;
      height: number;
    };
    weight: number;
  };
  tags: string[];
}

// Store JSON data
const insertProduct = db.sql<Product>`
  INSERT INTO products
  ${{
    values: ['$name', '$specs->json', '$tags->json']
  }}
`;

// Query JSON data
const getProduct = db.sql<{id: number}>`
  SELECT
    name,
    json_extract(specs, '$.dimensions.width') as width,
    ${'$specs<-json'} as specs,
    ${'$tags<-json'} as tags
  FROM products
  WHERE id = ${'$id'}
`;

Advanced Usage

Query Building

SQLiteX provides a flexible query building API:

interface Comment {
  id: number;
  postId: number;
  userId: number;
  content: string;
  metadata: {
    ip: string;
    userAgent: string;
  };
}

// Complex query composition
const queryComments = db.sql<{
  postId: number;
  userId?: number;
  limit?: number;
}>`
  SELECT
    c.*,
    ${'$metadata<-json'} as metadata
  FROM comments c
  ${({
    where: [
      'c.postId = $postId',
      ...(params.userId ? ['AND', 'c.userId = $userId'] : [])
    ],
    orderBy: { id: 'DESC' },
    limit: params.limit
  })}
`;

PRAGMA Configuration

Fine-tune SQLite behavior with PRAGMA settings:

const db = new DB({
  pragma: {
    // Write-Ahead Logging
    journalMode: 'WAL',

    // Synchronization mode
    synchronous: 'NORMAL',

    // Cache settings
    cacheSize: -64000,  // 64MB

    // Memory-mapped I/O
    mmapSize: 268435456,  // 256MB

    // Busy handler timeout
    busyTimeout: 5000,

    // Enforce foreign key constraints
    foreignKeys: true
  }
});

Statement Caching

Optimize performance with statement caching:

const db = new DB({
  statementCache: {
    maxSize: 1000,    // Maximum number of cached statements
    maxAge: 3600000  // Maximum age in milliseconds (1 hour)
  }
});

// Get cache statistics
const stats = db.getCacheStats();
console.log(stats);  // { hits: 150, misses: 10, size: 100, ... }

// Clear the cache if needed
db.clearStatementCache();

Backup and Restore

Manage database backups:

// Create a backup
db.backup('backup.sqlite');

// Restore from backup
db.restore('backup.sqlite');

// Clean shutdown
db.close({
  optimize: true,
  shrinkMemory: true,
  walCheckpoint: 'TRUNCATE'
});

API Reference

For detailed API documentation, please visit API Docs.

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

This project is licensed under the BSD License - see the LICENSE file for details.


Made with ❤️ by Takin Profit