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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lodestar-official/database

v2.0.0

Published

PostgreSQL database component with connection pooling, transactions, dependency management and TypeScript autocomplete

Readme

@lodestar-official/database

Componente de base de datos PostgreSQL con connection pooling, transacciones, gestión de dependencias y autocompletado de queries con TypeScript.

✨ Características

  • Autocompletado completo con createQueries()
  • ✅ Connection pooling automático
  • ✅ Transacciones ACID con dependencias entre queries
  • ✅ Soporte para queries planas, anidadas y mixtas
  • ✅ Raw SQL cuando lo necesites
  • ✅ Backward compatible con código existente
  • ✅ Logs configurables (4 niveles)
  • ✅ 100% TypeScript con tipos completos

📦 Instalación

npm install @lodestar-official/database

🚀 Inicio Rápido

Con createQueries() (Recomendado ⭐)

import Database, {
  createQueries,
  DatabaseConfig,
} from "@lodestar-official/database";

// 1. Crear queries con autocompletado
const queries = createQueries({
  users: {
    getById: "SELECT * FROM users WHERE id = $1",
    create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
    update: "UPDATE users SET name = $1 WHERE id = $2 RETURNING *",
    delete: "DELETE FROM users WHERE id = $1",
  },
  products: {
    getAll: "SELECT * FROM products",
    getById: "SELECT * FROM products WHERE id = $1",
  },
});

// 2. Configurar base de datos
const config: DatabaseConfig = {
  connectionString: process.env.DATABASE_URL!,
  ssl: { rejectUnauthorized: false },
  max: 10,
  logLevel: 2, // 0=NONE, 1=ERROR, 2=DEBUG, 3=ALL
};

// 3. Inicializar
const db = Database.getInstance(config, queries);

// 4. Usar con autocompletado! 🎉
const user = await db.query(queries.users.getById, [123]);
const newUser = await db.query(queries.users.create, [
  "John",
  "[email protected]",
]);
const products = await db.query(queries.products.getAll);

📚 Casos de Uso

1. Queries Planas (sin anidación)

const queries = createQueries({
  getUser: "SELECT * FROM users WHERE id = $1",
  createUser: "INSERT INTO users (name) VALUES ($1) RETURNING *",
  deleteUser: "DELETE FROM users WHERE id = $1",
});

const db = Database.getInstance(config, queries);

await db.query(queries.getUser, [123]);
await db.query(queries.createUser, ["Alice"]);
await db.query(queries.deleteUser, [456]);

2. Queries Anidadas (organizadas por dominio)

const queries = createQueries({
  users: {
    getById: "SELECT * FROM users WHERE id = $1",
    create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
    update: "UPDATE users SET name = $1 WHERE id = $2 RETURNING *",
  },
  products: {
    getAll: "SELECT * FROM products",
    getById: "SELECT * FROM products WHERE id = $1",
    create: "INSERT INTO products (name, price) VALUES ($1, $2) RETURNING *",
  },
});

const db = Database.getInstance(config, queries);

// Autocompletado funciona en todos los niveles!
await db.query(queries.users.getById, [123]);
await db.query(queries.products.create, ["Laptop", 999.99]);

3. Queries Mixtas (planas + anidadas)

const queries = createQueries({
  // Queries planas para cosas simples
  testConnection: "SELECT NOW() as time",
  checkHealth: "SELECT 1",

  // Queries anidadas para dominios complejos
  users: {
    getById: "SELECT * FROM users WHERE id = $1",
    create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
  },
  products: {
    getAll: "SELECT * FROM products",
  },
});

const db = Database.getInstance(config, queries);

// Planas
await db.query(queries.testConnection);
await db.query(queries.checkHealth);

// Anidadas
await db.query(queries.users.getById, [123]);
await db.query(queries.products.getAll);

4. Raw SQL (cuando lo necesites)

// Raw SQL sigue funcionando
const result = await db.query("SELECT COUNT(*) FROM users WHERE active = $1", [
  true,
]);
const count = result.rows[0].count;

5. Transacciones Simples

const results = await db.transaction(
  [queries.users.create, queries.users.create],
  [
    ["Alice", "[email protected]"],
    ["Bob", "[email protected]"],
  ]
);

console.log("Usuarios creados:", results.length);

6. Transacciones con Dependencias

import { Dependency } from "@lodestar-official/database";

const queries = createQueries({
  users: {
    create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
  },
  profiles: {
    create: "INSERT INTO profiles (user_id, bio) VALUES ($1, $2) RETURNING *",
  },
});

const db = Database.getInstance(config, queries);

// El ID del usuario se inyecta automáticamente en el perfil
const dependencies: Dependency[] = [
  { sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 },
];

const results = await db.transaction(
  [queries.users.create, queries.profiles.create],
  [
    ["John", "[email protected]"],
    [null, "John's bio"], // null será reemplazado por user.id
  ],
  dependencies
);

console.log("Usuario creado:", results[0].rows[0]);
console.log("Perfil creado:", results[1].rows[0]);

📊 Niveles de Log

export type LogLevel = 0 | 1 | 2 | 3;

// 0 = NONE   - Sin logs
// 1 = ERROR  - Solo errores
// 2 = DEBUG  - Errores + debug
// 3 = ALL    - Todos los logs (errores + debug + warnings + info)

const config: DatabaseConfig = {
  connectionString: process.env.DATABASE_URL!,
  logLevel: 2, // DEBUG
};

// Cambiar dinámicamente
db.setLogLevel(1); // Solo errores

🔄 Backward Compatibility

El paquete es 100% compatible con código existente:

// ✅ Forma antigua (sigue funcionando)
const db = Database.getInstance(config, {
  getUser: "SELECT * FROM users WHERE id = $1",
});
await db.query("getUser", [123]);

// ✅ Forma nueva (con autocompletado)
const queries = createQueries({
  users: {
    getById: "SELECT * FROM users WHERE id = $1",
  },
});
const db = Database.getInstance(config, queries);
await db.query(queries.users.getById, [123]);

🛡️ TypeScript

El paquete incluye definiciones de tipos completas:

import {
  Database,
  createQueries,
  QueryReference,
  DatabaseConfig,
  Dependency,
  Logger,
  LogLevel,
  QueryList,
} from "@lodestar-official/database";

📚 API Reference

createQueries(queries)

Crea un objeto de queries con autocompletado.

Parámetros:

  • queries: Record<string, any> - Objeto con queries (planas, anidadas o mixtas)

Retorna: Objeto con queries y __flatMap interno

Ejemplo:

const queries = createQueries({
  users: {
    getById: "SELECT * FROM users WHERE id = $1",
  },
});

Database.getInstance(config, queries)

Obtiene la instancia singleton de Database.

Parámetros:

  • config: DatabaseConfig - Configuración de conexión
  • queries?: any - Resultado de createQueries() o objeto plano

Retorna: Database

Ejemplo:

const db = Database.getInstance(config, queries);

db.query(query, params?)

Ejecuta una query (con QueryReference, string key o raw SQL).

Parámetros:

  • query: string | QueryReference - Query a ejecutar
  • params?: any[] - Parámetros de la query

Retorna: Promise<QueryResult>

Ejemplos:

// Con QueryReference
await db.query(queries.users.getById, [123]);

// Con string key
await db.query("users.getById", [123]);

// Raw SQL
await db.query("SELECT * FROM users WHERE id = $1", [123]);

db.transaction(queryArray, paramsArray, dependencies?)

Ejecuta múltiples queries en una transacción atómica.

Parámetros:

  • queryArray: (string | QueryReference)[] - Array de queries
  • paramsArray: any[][] - Parámetros para cada query
  • dependencies?: Dependency[] - Dependencias entre queries

Retorna: Promise<QueryResult[]>

Ejemplo:

await db.transaction(
  [queries.users.create, queries.profiles.create],
  [
    ["John", "[email protected]"],
    [null, "Bio"],
  ],
  [{ sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 }]
);

db.close()

Cierra todas las conexiones del pool.

Retorna: Promise<void>

Ejemplo:

await db.close();

db.setLogLevel(level)

Cambia el nivel de log dinámicamente.

Parámetros:

  • level: 0 | 1 | 2 | 3 - Nuevo nivel de log

Ejemplo:

db.setLogLevel(1); // Solo errores

🔒 Cerrar Conexiones

process.on("SIGTERM", async () => {
  const db = Database.getInstance(config);
  await db.close();
  process.exit(0);
});

🧪 Testing

npm test

📄 Licencia

MIT


🤝 Contribuir

Issues y Pull Requests son bienvenidos en: https://github.com/Lodestar/database


📝 Changelog

v2.0.0 (Actual)

  • NEW: createQueries() con autocompletado completo
  • NEW: Soporte para queries planas, anidadas y mixtas
  • NEW: QueryReference type para mejor DX
  • ✅ Backward compatible con v1.x.x
  • 📚 Documentación actualizada con ejemplos

v1.0.0

  • 🎉 Release inicial
  • Connection pooling
  • Transacciones con dependencias
  • Sistema de logs configurable