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

nuxt-pg

v0.2.0

Published

Seamless Nuxt 'pg' integration with event context-aware transaction handling.

Readme

nuxt-pg

PostgreSQL database module for Nuxt with automatic transaction management

npm version License

nuxt-pg provides a clean, type-safe PostgreSQL integration for Nuxt with automatic transaction context tracking. Write cleaner code by eliminating transaction parameter passing throughout your application.

Features

  • Automatic Transaction Context - No need to pass transaction objects through function calls
  • Lazy Initialization - Database initializes on first getPg() call, giving you full control over startup order
  • DevTools Integration - Switch between database connections in Nuxt DevTools during development
  • Connection Hooks - Listen for connection switch events via Nitro hooks
  • Type-Safe - Full TypeScript support with proper type inference
  • Connection Pooling - Built-in connection pool management with node-postgres
  • Flexible Pool Configuration - Customize pool settings globally or per-connection
  • Request Isolation - Transactions are automatically scoped per-request
  • Graceful Shutdown - Properly closes connections on server shutdown

Installation

npm install nuxt-pg pg

Quick Start

1. Add to your nuxt.config.ts

export default defineNuxtConfig({
    modules: ['nuxt-pg'],

    nuxtPg: {
        connectionString: process.env.DATABASE_URL || '',
    },
})

2. Use in your API routes

// server/api/users/[id].get.ts
export default defineEventHandler(async (event) => {
    const db = getPg()
    const id = getRouterParam(event, 'id')

    const users = await db.query(
        'SELECT * FROM users WHERE id = $1',
        [id]
    )

    return users[0]
})

getPg() is auto-imported in all server code. The first call initializes the database connection; subsequent calls return the existing singleton.

Usage

Basic Queries

const db = getPg()

// Simple query
const users = await db.query('SELECT * FROM users')

// With parameters
const user = await db.query(
    'SELECT * FROM users WHERE email = $1',
    ['[email protected]']
)

// With TypeScript types
interface User {
    id: string
    name: string
    email: string
}

const users = await db.query<User>(
    'SELECT * FROM users WHERE active = $1',
    [true]
)

Transactions

Automatic (Recommended)

export default defineEventHandler(async (event) => {
    const db = getPg()

    return await db.transactional(async (txn) => {
        await txn.query('INSERT INTO users (name) VALUES ($1)', ['Alice'])
        await txn.query('INSERT INTO profiles (user_id) VALUES ($1)', [userId])

        // Automatically commits on success, rolls back on error
        return { success: true }
    })
})

Manual Control

export default defineEventHandler(async (event) => {
    const db = getPg()

    await db.createTransaction()

    try {
        await db.query('INSERT INTO users ...')
        await db.query('UPDATE profiles ...')

        await db.commitTransaction()
        return { success: true }
    } catch (error) {
        await db.rollbackTransaction()
        throw error
    }
})

Context-Aware Queries

Transactions are tracked per-request — no need to pass transaction objects through your call stack:

// user.repo.ts
export class UserRepository {
    static async create(data: CreateUserData) {
        // Automatically uses the active transaction if one exists
        return getPg().query('INSERT INTO users ...', [...])
    }
}

// handler.ts
export default defineEventHandler(async (event) => {
    const db = getPg()

    return await db.transactional(async () => {
        // Both use the same transaction automatically
        await UserRepository.create({ name: 'Alice' })
        await ProfileRepository.create(userId, { bio: 'Hello' })
    })
})

Configuration

Module Options

Configure nuxt-pg under the nuxtPg key in your nuxt.config.ts:

export default defineNuxtConfig({
    modules: ['nuxt-pg'],

    nuxtPg: {
        enabled: true,                    // default: true
        connectionString: '',             // production connection string
        pool: {                           // global pool settings
            maxConnections: 30,
            minConnections: 2,
            idleTimeoutMs: 30000,
            connectionTimeoutMs: 2000,
            ssl: true,
        },
        dev: {                            // dev-only settings
            connections: {                // named connections for switching
                local: {
                    connectionString: process.env.DATABASE_URL_DEV || '',
                    pool: { ssl: false },
                },
                staging: {
                    connectionString: process.env.DATABASE_URL_STAGING || '',
                },
            },
            defaultConnection: 'local',   // which connection to use initially
        },
        devtools: {                       // devtools panel settings
            apiUrl: '',                   // remote API URL (see DevTools section)
        },
    },
})

When enabled is false, the module is entirely stripped — no aliases, runtime config, server imports, or hooks are registered. The only exception is the DevTools tab when devtools.apiUrl is set.

Pool Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | maxConnections | number | 30 | Maximum number of clients in the pool | | minConnections | number | 2 | Minimum number of clients to maintain | | idleTimeoutMs | number | 30000 | Time (ms) a client can be idle before being closed | | connectionTimeoutMs | number | 2000 | Time (ms) to wait for a connection before timing out | | ssl | boolean | true | Enable SSL connection |

Pool settings defined per-connection in dev.connections are merged with (and override) the global pool settings.

DevTools Integration

In dev mode, nuxt-pg adds a NuxtPG tab to Nuxt DevTools that lets you switch between named database connections on the fly.

Setup

Define multiple connections under dev.connections:

nuxtPg: {
    connectionString: process.env.DATABASE_URL || '',
    dev: {
        connections: {
            local: {
                connectionString: process.env.DATABASE_URL_DEV || '',
                pool: { ssl: false },
            },
            staging: {
                connectionString: process.env.DATABASE_URL_STAGING || '',
            },
            production: {
                connectionString: process.env.DATABASE_URL || '',
            },
        },
        defaultConnection: 'local',
    },
}

The DevTools panel appears automatically. Click any connection to switch — the module waits for active transactions to complete, swaps the connection pool, and resumes.

Remote DevTools (Monorepo)

In a monorepo where multiple Nuxt apps share a single API project, you can show the connection switcher in all apps without initializing a database in each one:

// main-app/nuxt.config.ts, dashboard/nuxt.config.ts, etc.
export default defineNuxtConfig({
    modules: ['nuxt-pg'],

    nuxtPg: {
        enabled: false,
        devtools: {
            apiUrl: 'http://localhost:3000',  // your API project's dev URL
        },
    },
})

With enabled: false and devtools.apiUrl set, the module only registers the DevTools tab pointing at the remote API — nothing else is loaded.

Connection Switch Hooks

When a database connection is switched (via DevTools or programmatically), nuxt-pg emits Nitro hooks you can listen to:

| Hook | Payload | When | |------|---------|------| | nuxtpg:connection:before-switch | { from, to } | Before the pool shutdown begins | | nuxtpg:connection:switched | { from, to } | After a successful switch | | nuxtpg:connection:switch-error | { from, to, error } | On switch failure |

Listening to Hooks

// server/plugins/on-db-switch.ts
export default defineNitroPlugin((nitroApp) => {
    nitroApp.hooks.hook('nuxtpg:connection:switched', ({ from, to }) => {
        console.log(`Database switched from "${from}" to "${to}"`)
        // Invalidate caches, re-seed data, notify services, etc.
    })

    nitroApp.hooks.hook('nuxtpg:connection:switch-error', ({ from, to, error }) => {
        console.error(`Failed to switch from "${from}" to "${to}":`, error.message)
    })
})

Hook Payload Types

import type {
    NuxtPgConnectionSwitchPayload,
    NuxtPgConnectionSwitchErrorPayload,
    NuxtPgHooks,
} from 'nuxt-pg'

API Reference

getPg()

Returns the database service singleton. Auto-imported in all server code.

On first call, reads runtime config, initializes the connection pool, and registers a shutdown hook. Subsequent calls return the existing instance.

| Method | Description | |--------|-------------| | query<T>(sql, params?) | Execute a SQL query. Uses the active transaction if one exists. | | createTransaction(timeoutMs?) | Start a new transaction in the current request context. | | commitTransaction() | Commit the active transaction. | | rollbackTransaction() | Rollback the active transaction. | | transactional<T>(fn, timeoutMs?) | Execute a function within a transaction with automatic commit/rollback. | | isHealthy() | Check if the connection pool is healthy. | | shutdown() | Gracefully shutdown the database service. |

How It Works

nuxt-pg automatically enables Nitro's asyncContext to track database transactions across async boundaries. When you start a transaction, it's stored in the request context and automatically used by all subsequent queries in that request:

// Without nuxt-pg (manual transaction passing)
await userService.create(data, transaction)
await profileService.create(profileData, transaction)

// With nuxt-pg (automatic context tracking)
await userService.create(data)
await profileService.create(profileData)

Requirements

  • Nuxt 3.0+
  • Node.js 18+
  • PostgreSQL 12+
  • pg as a peer dependency

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License

Credits

Built with: