Full-featured PostgreSQL data provider for MemberJunction. This package implements DatabaseProviderBase from @memberjunction/core to provide a complete PostgreSQL backend for MemberJunction applications. It also includes a CodeGen provider for generating PostgreSQL-native database objects (views, PL/pgSQL functions, triggers, indexes, full-text search, and more).
Key capabilities:
pg.Pool with configurable min/max connections$1, $2, ... positional parametersGenericDatabaseProvider — default in-memory, with optional Redis support for shared, persistent cachingDatabaseProviderBase (@memberjunction/core)
└── PostgreSQLDataProvider
├── PGConnectionManager (connection pooling)
├── PGQueryParameterProcessor (type conversion)
└── PostgreSQLTransactionGroup (transaction support)
CodeGenDatabaseProvider (@memberjunction/codegen-lib)
└── PostgreSQLCodeGenProvider (DDL generation)
└── PostgreSQLCodeGenConnection (query execution)
| File | Purpose |
|---|---|
PostgreSQLDataProvider.ts |
Main provider: CRUD, queries, view execution (supports both OFFSET StartRow and keyset AfterKey pagination — see KEYSET_PAGINATION_GUIDE.md), dataset handling, caching |
pgConnectionManager.ts |
Connection pool lifecycle with pg.Pool, shared pool support |
queryParameterProcessor.ts |
Boolean, date, UUID, number, and binary type conversion |
types.ts |
PostgreSQLProviderConfigData and PostgreSQLProviderConfigOptions interfaces |
PostgreSQLTransactionGroup.ts |
BEGIN/COMMIT/ROLLBACK with variable dependencies between transaction items |
codegen/PostgreSQLCodeGenProvider.ts |
CodeGen: views, CRUD functions, triggers, indexes, FTS, permissions |
codegen/PostgreSQLCodeGenConnection.ts |
Translates @ParamName notation to $N positional parameters |
interface PGConnectionConfig {
Host: string;
Port?: number; // Default: 5432
Database: string;
User: string;
Password: string;
SSL?: boolean | pg.ConnectionConfig['ssl'];
MaxConnections?: number; // Default: 20
MinConnections?: number; // Default: 2
IdleTimeoutMillis?: number; // Default: 30000
ConnectionTimeoutMillis?: number; // Default: 30000
MJCoreSchemaName?: string; // Default: '__mj'
}
The PostgreSQLProviderConfigData class wraps the connection config and adds MemberJunction-specific options:
const configData = new PostgreSQLProviderConfigData(
connectionConfig, // PGConnectionConfig
'__mj', // MJCoreSchemaName (default: '__mj')
0, // CheckRefreshIntervalSeconds (0 = disabled)
['public', '__mj'], // includeSchemas (optional)
[], // excludeSchemas (optional)
true // ignoreExistingMetadata (default: true)
);
For CodeGen shell execution (psql):
PGHOST -- PostgreSQL server hostPGPORT -- PostgreSQL server portPGDATABASE -- Database namePGUSER -- UsernamePGPASSWORD -- Password (or use .pgpass file)import { PostgreSQLDataProvider } from '@memberjunction/postgresql-dataprovider';
const provider = new PostgreSQLDataProvider();
await provider.Config(new PostgreSQLProviderConfigData(
{
Host: 'localhost',
Port: 5432,
Database: 'memberjunction',
User: 'mj_user',
Password: 'secret',
MJCoreSchemaName: '__mj'
},
'__mj'
));
// Execute raw SQL with positional parameters
const result = await provider.ExecuteSQL<MyType>(
'SELECT * FROM __mj."User" WHERE "ID" = $1',
[$userId]
);
// Run views (MJ pattern)
const results = await provider.InternalRunView<UserEntity>({
EntityName: 'Users',
ExtraFilter: "Status='Active'",
OrderBy: 'Name',
MaxRows: 100
});
const txGroup = await provider.CreateTransactionGroup();
// Add operations to the transaction group...
await txGroup.Submit(); // Executes all items in a single BEGIN/COMMIT block
The PostgreSQLTransactionGroup supports variable dependencies between transaction items, allowing later items to reference values produced by earlier items in the same transaction.
BeginTransaction() / CommitTransaction() / RollbackTransaction() support arbitrary nesting that mirrors the SQLServerDataProvider's depth/savepoint-stack model:
| Depth | Begin emits | Commit emits | Rollback emits |
|---|---|---|---|
| 1 (outermost) | BEGIN on a fresh client |
COMMIT + release client |
ROLLBACK + release client |
| 2+ (nested) | SAVEPOINT mj_sp_<n> |
RELEASE SAVEPOINT mj_sp_<n> |
ROLLBACK TO SAVEPOINT mj_sp_<n> + RELEASE SAVEPOINT |
await provider.BeginTransaction(); // BEGIN; depth=1
await provider.BeginTransaction(); // SAVEPOINT mj_sp_1; depth=2
// ...do work...
await provider.RollbackTransaction(); // ROLLBACK TO + RELEASE mj_sp_1; depth=1
await provider.CommitTransaction(); // COMMIT; depth=0
Use provider.TransactionDepth to inspect the current nesting depth (0 = no active transaction). If COMMIT or ROLLBACK itself fails at depth 1, the provider force-releases the client to avoid leaking a poisoned connection back to the pool.
The PGConnectionManager supports shared pools for scenarios where multiple provider instances need to share a single connection pool (e.g., per-request providers):
// Primary provider creates the pool
const primary = new PGConnectionManager();
await primary.Initialize(config);
// Per-request providers share the pool (won't close it on Close())
const perRequest = new PGConnectionManager();
perRequest.InitializeWithExistingPool(primary.Pool, config);
The PostgreSQLCodeGenProvider generates PostgreSQL-native database objects during the MemberJunction code generation process:
CREATE OR REPLACE VIEW with joins and soft-delete filteringRETURNING clause__mj_UpdatedAt maintenanceCREATE INDEX IF NOT EXISTS with 63-character name limit enforcementDROP ... IF EXISTS ... CASCADE statements before object creationCREATE OR REPLACE FUNCTION instead of SQL Server stored proceduresRETURNS TABLE(...) or RETURNS SETOF$$...$$) for function bodiesLATERAL joins instead of SQL Server's OUTER APPLYtsvector/tsquery with GIN indexes (not CONTAINSTABLE)true/false instead of SQL Server's 1/0LIMIT/OFFSET for pagination instead of TOP/OFFSET-FETCH"double quotes" instead of SQL Server's [brackets]The CodeGen provider is registered via the MemberJunction class factory:
@RegisterClass(CodeGenDatabaseProvider, 'PostgreSQLCodeGenProvider')
export class PostgreSQLCodeGenProvider extends CodeGenDatabaseProvider { ... }
PostgreSQLDialect for identifier quoting, pagination syntax, and type mappingPostgreSQLDataProvider and PostgreSQLCodeGenProviderCodeGenDatabaseProvider abstract base class with ~55 methodsPostgreSQLCodeGenProvider implements all abstract methods with PostgreSQL-native SQLDatabaseProviderBase abstract class defining the full MJ data provider contractPostgreSQLDataProvider implements CRUD, view execution, dataset operations, and metadata access@RegisterClass for class factory registrationPostgreSQLCodeGenProvider registers itself so the CodeGen system can discover it at runtime| Package | Purpose |
|---|---|
@memberjunction/core |
Base provider interfaces and entity framework |
@memberjunction/codegen-lib |
CodeGen base class and orchestration types |
@memberjunction/sql-dialect |
SQL dialect abstraction (quoting, pagination, types) |
@memberjunction/global |
Class registration via @RegisterClass |
pg |
PostgreSQL Node.js driver (connection pooling, queries) |
cd packages/PostgreSQLDataProvider
npm run test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
Tests use Vitest with mocked database connections (no live database required).
The provider identifies itself with PlatformKey: 'postgresql', which is used throughout MemberJunction to select the correct SQL dialect, CodeGen templates, and runtime behavior for PostgreSQL deployments.