singulio-postgres 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @singulio/postgres - PostgreSQL Client
3
+ * Thin wrapper around bun:postgres native client
4
+ */
5
+ import type { PostgresConfig, QueryResult, QueryRow, Logger } from './types.js';
6
+ /**
7
+ * PostgreSQL client wrapping Bun's native postgres driver
8
+ */
9
+ export declare class PostgresClient {
10
+ private connectionString;
11
+ private logger?;
12
+ private connected;
13
+ constructor(config: PostgresConfig | string, logger?: Logger);
14
+ private buildConnectionString;
15
+ /**
16
+ * Execute a SQL query with parameters
17
+ */
18
+ query<T = QueryRow>(queryText: string, params?: unknown[]): Promise<QueryResult<T>>;
19
+ /**
20
+ * Execute a query and return the first row or null
21
+ */
22
+ queryOne<T = QueryRow>(queryText: string, params?: unknown[]): Promise<T | null>;
23
+ /**
24
+ * Execute a query and return all rows
25
+ */
26
+ queryAll<T = QueryRow>(queryText: string, params?: unknown[]): Promise<T[]>;
27
+ /**
28
+ * Execute a command (INSERT/UPDATE/DELETE) and return affected row count
29
+ */
30
+ execute(queryText: string, params?: unknown[]): Promise<number>;
31
+ /**
32
+ * Check if connected and working
33
+ */
34
+ ping(): Promise<boolean>;
35
+ /**
36
+ * Get server version
37
+ */
38
+ version(): Promise<string>;
39
+ /**
40
+ * Close all connections (for bun:postgres this is mostly a no-op as it manages connections)
41
+ */
42
+ close(): Promise<void>;
43
+ /**
44
+ * Get connection string (for debugging, sensitive parts masked)
45
+ */
46
+ get maskedConnectionString(): string;
47
+ }
48
+ /**
49
+ * Create a new PostgresClient instance
50
+ */
51
+ export declare function createClient(config: PostgresConfig | string, logger?: Logger): PostgresClient;
52
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEhF;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAM5D,OAAO,CAAC,qBAAqB;IAgC7B;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA8BzF;;OAEG;IACG,QAAQ,CAAC,CAAC,GAAG,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKtF;;OAEG;IACG,QAAQ,CAAC,CAAC,GAAG,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKjF;;OAEG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAKrE;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAS9B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAKhC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACH,IAAI,sBAAsB,IAAI,MAAM,CAEnC;CACF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAE7F"}
package/dist/client.js ADDED
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @singulio/postgres - PostgreSQL Client
3
+ * Thin wrapper around bun:postgres native client
4
+ */
5
+ import { sql } from 'bun';
6
+ /**
7
+ * PostgreSQL client wrapping Bun's native postgres driver
8
+ */
9
+ export class PostgresClient {
10
+ connectionString;
11
+ logger;
12
+ connected = false;
13
+ constructor(config, logger) {
14
+ this.connectionString =
15
+ typeof config === 'string' ? config : this.buildConnectionString(config);
16
+ this.logger = logger;
17
+ }
18
+ buildConnectionString(config) {
19
+ if (config.connectionString)
20
+ return config.connectionString;
21
+ const { host = 'localhost', port = 5432, database = 'postgres', user = 'postgres', password = '', ssl, applicationName, } = config;
22
+ let connStr = `postgres://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
23
+ const params = [];
24
+ if (ssl === true || ssl === 'require') {
25
+ params.push('sslmode=require');
26
+ }
27
+ else if (ssl === 'prefer') {
28
+ params.push('sslmode=prefer');
29
+ }
30
+ if (applicationName) {
31
+ params.push(`application_name=${encodeURIComponent(applicationName)}`);
32
+ }
33
+ if (params.length > 0) {
34
+ connStr += '?' + params.join('&');
35
+ }
36
+ return connStr;
37
+ }
38
+ /**
39
+ * Execute a SQL query with parameters
40
+ */
41
+ async query(queryText, params) {
42
+ const start = performance.now();
43
+ try {
44
+ // Use Bun's sql tagged template for parameterized queries
45
+ const result = await sql.unsafe(queryText, params ?? []);
46
+ const latency = performance.now() - start;
47
+ this.logger?.debug('Query executed', {
48
+ query: queryText.substring(0, 100),
49
+ params: params?.length ?? 0,
50
+ rows: result.length,
51
+ latencyMs: latency.toFixed(2),
52
+ });
53
+ return {
54
+ rows: result,
55
+ rowCount: result.length,
56
+ };
57
+ }
58
+ catch (error) {
59
+ const latency = performance.now() - start;
60
+ this.logger?.error('Query failed', {
61
+ query: queryText.substring(0, 100),
62
+ error: error instanceof Error ? error.message : String(error),
63
+ latencyMs: latency.toFixed(2),
64
+ });
65
+ throw error;
66
+ }
67
+ }
68
+ /**
69
+ * Execute a query and return the first row or null
70
+ */
71
+ async queryOne(queryText, params) {
72
+ const result = await this.query(queryText, params);
73
+ return result.rows[0] ?? null;
74
+ }
75
+ /**
76
+ * Execute a query and return all rows
77
+ */
78
+ async queryAll(queryText, params) {
79
+ const result = await this.query(queryText, params);
80
+ return result.rows;
81
+ }
82
+ /**
83
+ * Execute a command (INSERT/UPDATE/DELETE) and return affected row count
84
+ */
85
+ async execute(queryText, params) {
86
+ const result = await this.query(queryText, params);
87
+ return result.rowCount;
88
+ }
89
+ /**
90
+ * Check if connected and working
91
+ */
92
+ async ping() {
93
+ try {
94
+ const result = await sql `SELECT 1 as ok`;
95
+ return result.length > 0;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ /**
102
+ * Get server version
103
+ */
104
+ async version() {
105
+ const result = await sql `SELECT version()`;
106
+ return result[0]?.version ?? 'unknown';
107
+ }
108
+ /**
109
+ * Close all connections (for bun:postgres this is mostly a no-op as it manages connections)
110
+ */
111
+ async close() {
112
+ this.connected = false;
113
+ this.logger?.info('PostgresClient closed');
114
+ }
115
+ /**
116
+ * Get connection string (for debugging, sensitive parts masked)
117
+ */
118
+ get maskedConnectionString() {
119
+ return this.connectionString.replace(/:([^@]+)@/, ':***@');
120
+ }
121
+ }
122
+ /**
123
+ * Create a new PostgresClient instance
124
+ */
125
+ export function createClient(config, logger) {
126
+ return new PostgresClient(config, logger);
127
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @singulio/postgres - Health Check Utilities
3
+ * Kubernetes readiness/liveness probes for PostgreSQL
4
+ */
5
+ import type { HealthCheckResult, Logger } from './types.js';
6
+ import type { PostgresPool } from './pool.js';
7
+ /**
8
+ * Simple health check - verifies database connectivity
9
+ */
10
+ export declare function healthCheck(logger?: Logger): Promise<HealthCheckResult>;
11
+ /**
12
+ * Extended health check with pool statistics
13
+ */
14
+ export declare function healthCheckWithPool(pool: PostgresPool, logger?: Logger): Promise<HealthCheckResult>;
15
+ /**
16
+ * Deep health check - verifies database is accepting writes
17
+ */
18
+ export declare function deepHealthCheck(logger?: Logger): Promise<HealthCheckResult>;
19
+ /**
20
+ * Check PostgreSQL version
21
+ */
22
+ export declare function getVersion(): Promise<string>;
23
+ /**
24
+ * Check if database is in recovery mode (replica)
25
+ */
26
+ export declare function isInRecovery(): Promise<boolean>;
27
+ /**
28
+ * Get database size
29
+ */
30
+ export declare function getDatabaseSize(dbName?: string): Promise<string>;
31
+ /**
32
+ * Get connection count
33
+ */
34
+ export declare function getConnectionCount(): Promise<{
35
+ active: number;
36
+ idle: number;
37
+ total: number;
38
+ maxConnections: number;
39
+ }>;
40
+ /**
41
+ * Create an HTTP health check handler for Bun.serve
42
+ */
43
+ export declare function createHealthHandler(pool?: PostgresPool): (req: Request) => Promise<Response>;
44
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2B7E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAwC5B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkDjF;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAGlD;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAGrD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAiBD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,CAAC,EAAE,YAAY,IACvC,KAAK,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAuB/C"}
package/dist/health.js ADDED
@@ -0,0 +1,182 @@
1
+ /**
2
+ * @singulio/postgres - Health Check Utilities
3
+ * Kubernetes readiness/liveness probes for PostgreSQL
4
+ */
5
+ import { sql } from 'bun';
6
+ /**
7
+ * Simple health check - verifies database connectivity
8
+ */
9
+ export async function healthCheck(logger) {
10
+ const start = performance.now();
11
+ try {
12
+ const result = await sql `SELECT 1 as ok`;
13
+ const latencyMs = performance.now() - start;
14
+ const healthy = result.length > 0 && result[0].ok === 1;
15
+ logger?.debug('Health check completed', { healthy, latencyMs: latencyMs.toFixed(2) });
16
+ return {
17
+ healthy,
18
+ latencyMs,
19
+ };
20
+ }
21
+ catch (error) {
22
+ const latencyMs = performance.now() - start;
23
+ const errorMessage = error instanceof Error ? error.message : String(error);
24
+ logger?.error('Health check failed', { error: errorMessage, latencyMs: latencyMs.toFixed(2) });
25
+ return {
26
+ healthy: false,
27
+ latencyMs,
28
+ error: errorMessage,
29
+ };
30
+ }
31
+ }
32
+ /**
33
+ * Extended health check with pool statistics
34
+ */
35
+ export async function healthCheckWithPool(pool, logger) {
36
+ const start = performance.now();
37
+ try {
38
+ // Query through pool
39
+ const result = await pool.query('SELECT 1 as ok');
40
+ const latencyMs = performance.now() - start;
41
+ const healthy = result.rows.length > 0 && result.rows[0].ok === 1;
42
+ const poolStats = pool.stats();
43
+ logger?.debug('Pool health check completed', {
44
+ healthy,
45
+ latencyMs: latencyMs.toFixed(2),
46
+ ...poolStats,
47
+ });
48
+ return {
49
+ healthy,
50
+ latencyMs,
51
+ poolStats,
52
+ };
53
+ }
54
+ catch (error) {
55
+ const latencyMs = performance.now() - start;
56
+ const errorMessage = error instanceof Error ? error.message : String(error);
57
+ const poolStats = pool.stats();
58
+ logger?.error('Pool health check failed', {
59
+ error: errorMessage,
60
+ latencyMs: latencyMs.toFixed(2),
61
+ ...poolStats,
62
+ });
63
+ return {
64
+ healthy: false,
65
+ latencyMs,
66
+ poolStats,
67
+ error: errorMessage,
68
+ };
69
+ }
70
+ }
71
+ /**
72
+ * Deep health check - verifies database is accepting writes
73
+ */
74
+ export async function deepHealthCheck(logger) {
75
+ const start = performance.now();
76
+ try {
77
+ // Check we can read and write
78
+ await sql `
79
+ CREATE TEMP TABLE IF NOT EXISTS _health_check (
80
+ id serial PRIMARY KEY,
81
+ ts timestamptz DEFAULT NOW()
82
+ )
83
+ `;
84
+ await sql `INSERT INTO _health_check DEFAULT VALUES`;
85
+ const result = await sql `SELECT COUNT(*) as count FROM _health_check`;
86
+ await sql `DROP TABLE IF EXISTS _health_check`;
87
+ const latencyMs = performance.now() - start;
88
+ const healthy = result.length > 0 && result[0].count > 0;
89
+ logger?.debug('Deep health check completed', {
90
+ healthy,
91
+ latencyMs: latencyMs.toFixed(2),
92
+ });
93
+ return {
94
+ healthy,
95
+ latencyMs,
96
+ };
97
+ }
98
+ catch (error) {
99
+ const latencyMs = performance.now() - start;
100
+ const errorMessage = error instanceof Error ? error.message : String(error);
101
+ // Cleanup on error
102
+ try {
103
+ await sql `DROP TABLE IF EXISTS _health_check`;
104
+ }
105
+ catch {
106
+ // Ignore cleanup errors
107
+ }
108
+ logger?.error('Deep health check failed', {
109
+ error: errorMessage,
110
+ latencyMs: latencyMs.toFixed(2),
111
+ });
112
+ return {
113
+ healthy: false,
114
+ latencyMs,
115
+ error: errorMessage,
116
+ };
117
+ }
118
+ }
119
+ /**
120
+ * Check PostgreSQL version
121
+ */
122
+ export async function getVersion() {
123
+ const result = await sql `SELECT version()`;
124
+ return result[0]?.version ?? 'unknown';
125
+ }
126
+ /**
127
+ * Check if database is in recovery mode (replica)
128
+ */
129
+ export async function isInRecovery() {
130
+ const result = await sql `SELECT pg_is_in_recovery() as in_recovery`;
131
+ return result[0]?.in_recovery === true;
132
+ }
133
+ /**
134
+ * Get database size
135
+ */
136
+ export async function getDatabaseSize(dbName) {
137
+ const result = await sql.unsafe(`SELECT pg_size_pretty(pg_database_size(${dbName ? '$1' : 'current_database()'}))::text as size`, dbName ? [dbName] : []);
138
+ return result[0]?.size ?? 'unknown';
139
+ }
140
+ /**
141
+ * Get connection count
142
+ */
143
+ export async function getConnectionCount() {
144
+ const result = await sql `
145
+ SELECT
146
+ COUNT(*) FILTER (WHERE state = 'active') as active,
147
+ COUNT(*) FILTER (WHERE state = 'idle') as idle,
148
+ COUNT(*) as total,
149
+ (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') as max_connections
150
+ FROM pg_stat_activity
151
+ WHERE datname = current_database()
152
+ `;
153
+ return {
154
+ active: Number(result[0]?.active) || 0,
155
+ idle: Number(result[0]?.idle) || 0,
156
+ total: Number(result[0]?.total) || 0,
157
+ maxConnections: Number(result[0]?.max_connections) || 100,
158
+ };
159
+ }
160
+ /**
161
+ * Create an HTTP health check handler for Bun.serve
162
+ */
163
+ export function createHealthHandler(pool) {
164
+ return async (req) => {
165
+ const url = new URL(req.url);
166
+ if (url.pathname === '/health' || url.pathname === '/healthz') {
167
+ const result = pool ? await healthCheckWithPool(pool) : await healthCheck();
168
+ return new Response(JSON.stringify(result), {
169
+ status: result.healthy ? 200 : 503,
170
+ headers: { 'Content-Type': 'application/json' },
171
+ });
172
+ }
173
+ if (url.pathname === '/ready' || url.pathname === '/readyz') {
174
+ const result = await deepHealthCheck();
175
+ return new Response(JSON.stringify(result), {
176
+ status: result.healthy ? 200 : 503,
177
+ headers: { 'Content-Type': 'application/json' },
178
+ });
179
+ }
180
+ return new Response('Not Found', { status: 404 });
181
+ };
182
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @singulio/postgres
3
+ * PostgreSQL 18.x client for Bun with RLS, pooling, transactions, and pgvector support
4
+ *
5
+ * A thin wrapper around bun:postgres native client providing:
6
+ * - Connection pooling with configurable limits
7
+ * - Row-Level Security (RLS) helpers for multi-tenant isolation
8
+ * - Transaction support with auto-rollback
9
+ * - pgvector extension for AI/ML embeddings
10
+ * - Kubernetes health check utilities
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createClient, createPool, withTenant, vectorSearch } from '@singulio/postgres';
15
+ *
16
+ * // Simple client
17
+ * const client = createClient(process.env.DATABASE_URL);
18
+ * const users = await client.queryAll('SELECT * FROM users');
19
+ *
20
+ * // With RLS tenant context
21
+ * const tenantData = await withTenant({ tenantId: 'tenant-123' }, async () => {
22
+ * return client.queryAll('SELECT * FROM contacts'); // RLS filters by tenant
23
+ * });
24
+ *
25
+ * // Vector similarity search
26
+ * const similar = await vectorSearch('documents', 'embedding', queryVector, {
27
+ * operator: '<=>', // Cosine similarity
28
+ * limit: 10,
29
+ * });
30
+ * ```
31
+ */
32
+ export type { PostgresConfig, PoolConfig, RLSContext, QueryResult, QueryRow, FieldInfo, IsolationLevel, TransactionOptions, HealthCheckResult, PoolStats, VectorDistanceOperator, VectorIndexType, VectorSearchOptions, Logger, } from './types.js';
33
+ export { PostgresClient, createClient } from './client.js';
34
+ export { PostgresPool, createPool } from './pool.js';
35
+ export { setRLSContext, clearRLSContext, getRLSContext, withTenant, queryWithTenant, RLSClient, createRLSClient, } from './rls.js';
36
+ export { transaction, serializableTransaction, readOnlyTransaction, savepoint, rollbackToSavepoint, releaseSavepoint, type TransactionQuery, } from './transaction.js';
37
+ export { formatVector, parseVector, vectorDimension, normalizeVector, getDistanceOperator, getDistanceOperatorName, ensureVectorExtension, createVectorColumn, createVectorIndex, vectorSearch, insertWithVector, updateVector, batchInsertWithVectors, type Vector, } from './vector.js';
38
+ export { healthCheck, healthCheckWithPool, deepHealthCheck, getVersion, isInRecovery, getDatabaseSize, getConnectionCount, createHealthHandler, } from './health.js';
39
+ export { sql } from 'bun';
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,YAAY,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,EACT,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,MAAM,GACP,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EACL,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,eAAe,EACf,SAAS,EACT,eAAe,GAChB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,KAAK,MAAM,GACZ,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @singulio/postgres
3
+ * PostgreSQL 18.x client for Bun with RLS, pooling, transactions, and pgvector support
4
+ *
5
+ * A thin wrapper around bun:postgres native client providing:
6
+ * - Connection pooling with configurable limits
7
+ * - Row-Level Security (RLS) helpers for multi-tenant isolation
8
+ * - Transaction support with auto-rollback
9
+ * - pgvector extension for AI/ML embeddings
10
+ * - Kubernetes health check utilities
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createClient, createPool, withTenant, vectorSearch } from '@singulio/postgres';
15
+ *
16
+ * // Simple client
17
+ * const client = createClient(process.env.DATABASE_URL);
18
+ * const users = await client.queryAll('SELECT * FROM users');
19
+ *
20
+ * // With RLS tenant context
21
+ * const tenantData = await withTenant({ tenantId: 'tenant-123' }, async () => {
22
+ * return client.queryAll('SELECT * FROM contacts'); // RLS filters by tenant
23
+ * });
24
+ *
25
+ * // Vector similarity search
26
+ * const similar = await vectorSearch('documents', 'embedding', queryVector, {
27
+ * operator: '<=>', // Cosine similarity
28
+ * limit: 10,
29
+ * });
30
+ * ```
31
+ */
32
+ // Client
33
+ export { PostgresClient, createClient } from './client.js';
34
+ // Pool
35
+ export { PostgresPool, createPool } from './pool.js';
36
+ // RLS
37
+ export { setRLSContext, clearRLSContext, getRLSContext, withTenant, queryWithTenant, RLSClient, createRLSClient, } from './rls.js';
38
+ // Transactions
39
+ export { transaction, serializableTransaction, readOnlyTransaction, savepoint, rollbackToSavepoint, releaseSavepoint, } from './transaction.js';
40
+ // Vector (pgvector)
41
+ export { formatVector, parseVector, vectorDimension, normalizeVector, getDistanceOperator, getDistanceOperatorName, ensureVectorExtension, createVectorColumn, createVectorIndex, vectorSearch, insertWithVector, updateVector, batchInsertWithVectors, } from './vector.js';
42
+ // Health
43
+ export { healthCheck, healthCheckWithPool, deepHealthCheck, getVersion, isInRecovery, getDatabaseSize, getConnectionCount, createHealthHandler, } from './health.js';
44
+ // Re-export bun:postgres sql for direct usage
45
+ export { sql } from 'bun';
package/dist/pool.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @singulio/postgres - Connection Pool Manager
3
+ * Manages PostgreSQL connections with configurable pooling
4
+ *
5
+ * Note: Bun's native sql driver handles connection pooling internally.
6
+ * This module provides a higher-level API with explicit pool management
7
+ * for scenarios requiring fine-grained control.
8
+ */
9
+ import type { PoolConfig, PoolStats, QueryResult, QueryRow, Logger } from './types.js';
10
+ /**
11
+ * Connection pool manager for PostgreSQL
12
+ */
13
+ export declare class PostgresPool {
14
+ private config;
15
+ private logger?;
16
+ private connections;
17
+ private nextId;
18
+ private waitQueue;
19
+ private closed;
20
+ private idleCheckTimer?;
21
+ constructor(config: PoolConfig, logger?: Logger);
22
+ /**
23
+ * Initialize the pool with minimum connections
24
+ */
25
+ initialize(): Promise<void>;
26
+ private createConnection;
27
+ private acquireConnection;
28
+ private releaseConnection;
29
+ private destroyConnection;
30
+ private checkIdleConnections;
31
+ /**
32
+ * Execute a query using a pooled connection
33
+ */
34
+ query<T = QueryRow>(queryText: string, params?: unknown[]): Promise<QueryResult<T>>;
35
+ /**
36
+ * Execute with exclusive connection for multi-statement operations
37
+ */
38
+ withConnection<T>(fn: (query: (sql: string, params?: unknown[]) => Promise<QueryResult>) => Promise<T>): Promise<T>;
39
+ /**
40
+ * Get current pool statistics
41
+ */
42
+ stats(): PoolStats;
43
+ /**
44
+ * Close the pool and all connections
45
+ */
46
+ close(): Promise<void>;
47
+ }
48
+ /**
49
+ * Create and initialize a connection pool
50
+ */
51
+ export declare function createPool(config: PoolConfig, logger?: Logger): Promise<PostgresPool>;
52
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAkBvF;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAIT;IACR,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAC,CAAQ;gBAEnB,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM;IAe/C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAgBnB,gBAAgB;YAWhB,iBAAiB;IAkC/B,OAAO,CAAC,iBAAiB;YAaX,iBAAiB;YAKjB,oBAAoB;IAclC;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA4BzF;;OAEG;IACG,cAAc,CAAC,CAAC,EACpB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACnF,OAAO,CAAC,CAAC,CAAC;IAoBb;;OAEG;IACH,KAAK,IAAI,SAAS;IAoBlB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAqB7B;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAI3F"}