
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
PostgreSQL database module for Nuxt with automatic transaction management
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.
getPg() call, giving you full control over startup ordernode-postgresnpm install nuxt-pg pg
nuxt.config.tsexport default defineNuxtConfig({
modules: ['nuxt-pg'],
nuxtPg: {
connectionString: process.env.DATABASE_URL || '',
},
})
// 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.
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',
['user@example.com']
)
// With TypeScript types
interface User {
id: string
name: string
email: string
}
const users = await db.query<User>(
'SELECT * FROM users WHERE active = $1',
[true]
)
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 }
})
})
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
}
})
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' })
})
})
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.
| 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.
In dev mode, nuxt-pg adds a NuxtPG tab to Nuxt DevTools that lets you switch between named database connections on the fly.
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.
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.
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 |
// 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)
})
})
import type {
NuxtPgConnectionSwitchPayload,
NuxtPgConnectionSwitchErrorPayload,
NuxtPgHooks,
} from 'nuxt-pg'
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. |
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)
pg as a peer dependencyContributions are welcome! Please feel free to submit a Pull Request.
Built with:
FAQs
Seamless Nuxt 'pg' integration with event context-aware transaction handling.
We found that nuxt-pg demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.