PostgreSQL Database Structure Reverse Engineer

7.15.3 · active · verified Wed Apr 22

pg-structure is a TypeScript-first library designed to reverse engineer a PostgreSQL database schema into a detailed JavaScript object structure. It provides an API to programmatically access and navigate details about databases, schemas, tables, columns, foreign keys, relations, indexes, and custom types. The current stable version is 7.15.3. Releases are somewhat infrequent, with several bug fix releases in 2024 and feature additions in 2023 and prior years, indicating active maintenance. Its key differentiator is offering a comprehensive, introspected object model of the entire PostgreSQL schema, which is useful for ORM generators, database documentation tools, schema analysis scripts, or custom code generation, rather than just basic table listings. It handles complex PostgreSQL features like custom types and generated columns.

Common errors

Warnings

Install

Imports

Quickstart

This example connects to a PostgreSQL database, reverse engineers its structure, and demonstrates how to access specific tables, columns, their types, indexes, and relationships using the programmatic API.

import pgStructure from "pg-structure";
import type { Db, Table } from "pg-structure";

async function demo() {
  // It's highly recommended to use environment variables for sensitive credentials.
  // Example uses process.env for security best practices.
  const connectionConfig = {
    host: process.env.PG_HOST ?? "localhost",
    database: process.env.PG_DATABASE ?? "your_db_name",
    user: process.env.PG_USER ?? "your_username",
    password: process.env.PG_PASSWORD ?? "your_password",
    port: parseInt(process.env.PG_PORT ?? "5432", 10),
  };

  try {
    // Establish a connection and reverse engineer the database structure
    const db: Db = await pgStructure(connectionConfig, { includeSchemas: ["public"] });

    // Access a specific table by its name
    const contactTable: Table | undefined = db.get("contact");

    if (contactTable) {
      console.log(`Successfully introspected table: ${contactTable.name}`);

      // Get column names for the 'contact' table
      const columnNames = contactTable.columns.map((c) => c.name);
      console.log("Column Names for 'contact' table:", columnNames);

      // Get the type name of a specific column (e.g., 'options' column)
      const optionsColumn = contactTable.columns.get("options");
      if (optionsColumn) {
        console.log(`Type name of 'options' column: ${optionsColumn.type.name}`);
      }

      // Get columns involved in a specific index (e.g., 'ix_mail' index)
      const ixMailIndex = contactTable.indexes.get("ix_mail");
      if (ixMailIndex) {
        const indexColumnNames = ixMailIndex.columns.map(c => c.name);
        console.log("Columns in 'ix_mail' index:", indexColumnNames);
      }

      // Get tables related to 'contact' via hasMany relationship
      const relatedTables = contactTable.hasManyTables;
      console.log("Tables related to 'contact' via hasMany:", relatedTables.map(t => t.name));
    } else {
      console.log("Table 'contact' not found or not included in introspection.");
    }
  } catch (error) {
    console.error("Failed to connect or introspect database:", error);
  }
}

demo();

view raw JSON →