Skip to content

Commit 6e61480

Browse files
committed
f
1 parent 8949b14 commit 6e61480

File tree

2 files changed

+236
-7
lines changed

2 files changed

+236
-7
lines changed

src/packages/dumbo/src/core/index.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import {
22
SQL,
3-
type PostgreSQLConnector,
43
type QueryResult,
54
type QueryResultRow,
65
type SQLCommandOptions,
76
type SQLExecutor,
87
type SQLQueryOptions,
9-
} from '../pg';
10-
import { SQLite3Connector, type SQLiteConnection } from '../sqlite3';
8+
} from '../core';
119
import type { Connection, ConnectionPool } from './connections';
1210
import type { ConnectorType } from './connectors';
1311

@@ -33,6 +31,17 @@ export type Dumbo<
3331

3432
export type PostgreSQLConnectionString = `postgresql://${string}`;
3533

34+
export const postgreSQLConnectionString = (
35+
connectionString: string,
36+
): PostgreSQLConnectionString => {
37+
if (!connectionString.startsWith('postgresql://')) {
38+
throw new Error(
39+
`Invalid PostgreSQL connection string: ${connectionString}. It should start with "postgresql://".`,
40+
);
41+
}
42+
return connectionString as PostgreSQLConnectionString;
43+
};
44+
3645
export type SQLiteConnectionString =
3746
| `file:${string}`
3847
| `:memory:`
@@ -42,17 +51,17 @@ export type SQLiteConnectionString =
4251
// Helper type to infer the connector type based on connection string
4352
export type InferConnector<T extends DatabaseConnectionString> =
4453
T extends PostgreSQLConnectionString
45-
? PostgreSQLConnector
54+
? ConnectorType<'PostgreSQL', 'pg'>
4655
: T extends SQLiteConnectionString
47-
? SQLite3Connector
56+
? ConnectorType<'SQLite', 'sqlite3'>
4857
: never;
4958

5059
// Helper type to infer the connection type based on connection string
5160
export type InferConnection<T extends DatabaseConnectionString> =
5261
T extends PostgreSQLConnectionString
53-
? PostgreSQLConnection<ConnectorType<'PostgreSQL', 'pg'>>
62+
? Connection<ConnectorType<'PostgreSQL', 'pg'>>
5463
: T extends SQLiteConnectionString
55-
? SQLiteConnection<ConnectorType<'SQLite', 'sqlite3'>>
64+
? Connection<ConnectorType<'SQLite', 'sqlite3'>>
5665
: never;
5766

5867
export type DatabaseConnectionString =
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import {
2+
PostgreSqlContainer,
3+
type StartedPostgreSqlContainer,
4+
} from '@testcontainers/postgresql';
5+
import { after, before, describe, it } from 'node:test';
6+
import pg from 'pg';
7+
import { nodePostgresPool } from '.';
8+
import {
9+
dumbo,
10+
postgreSQLConnectionString,
11+
rawSql,
12+
type PostgreSQLConnectionString,
13+
} from '../../../../core';
14+
import { endPool, getPool } from './pool';
15+
16+
void describe('Node Postgresql', () => {
17+
let postgres: StartedPostgreSqlContainer;
18+
let connectionString: PostgreSQLConnectionString;
19+
20+
before(async () => {
21+
postgres = await new PostgreSqlContainer().start();
22+
connectionString = postgreSQLConnectionString(postgres.getConnectionUri());
23+
});
24+
25+
after(async () => {
26+
await postgres.stop();
27+
});
28+
29+
void describe('nodePostgresPool', () => {
30+
void it('connects using default pool', async () => {
31+
const pool = dumbo({ connectionString });
32+
const connection = await pool.connection();
33+
34+
try {
35+
await connection.execute.query(rawSql('SELECT 1'));
36+
} catch (error) {
37+
console.log(error);
38+
} finally {
39+
await connection.close();
40+
await pool.close();
41+
}
42+
});
43+
44+
void it('connects using ambient pool', async () => {
45+
const nativePool = getPool(connectionString);
46+
const pool = nodePostgresPool({ connectionString, pool: nativePool });
47+
const connection = await pool.connection();
48+
49+
try {
50+
await connection.execute.query(rawSql('SELECT 1'));
51+
} finally {
52+
await connection.close();
53+
await pool.close();
54+
await endPool({ connectionString });
55+
}
56+
});
57+
58+
void it('connects using client', async () => {
59+
const pool = nodePostgresPool({
60+
connectionString,
61+
pooled: false,
62+
});
63+
const connection = await pool.connection();
64+
65+
try {
66+
await connection.execute.query(rawSql('SELECT 1'));
67+
} finally {
68+
await connection.close();
69+
await pool.close();
70+
}
71+
});
72+
73+
void it('connects using ambient client', async () => {
74+
const existingClient = new pg.Client({ connectionString });
75+
await existingClient.connect();
76+
77+
const pool = nodePostgresPool({
78+
connectionString,
79+
client: existingClient,
80+
});
81+
const connection = await pool.connection();
82+
83+
try {
84+
await connection.execute.query(rawSql('SELECT 1'));
85+
} finally {
86+
await connection.close();
87+
await pool.close();
88+
await existingClient.end();
89+
}
90+
});
91+
92+
void it('connects using connected ambient connected connection', async () => {
93+
const ambientPool = nodePostgresPool({ connectionString });
94+
const ambientConnection = await ambientPool.connection();
95+
await ambientConnection.open();
96+
97+
const pool = nodePostgresPool({
98+
connectionString,
99+
connection: ambientConnection,
100+
});
101+
102+
try {
103+
await pool.execute.query(rawSql('SELECT 1'));
104+
} finally {
105+
await pool.close();
106+
await ambientConnection.close();
107+
await ambientPool.close();
108+
}
109+
});
110+
111+
void it('connects using connected ambient not-connected connection', async () => {
112+
const ambientPool = nodePostgresPool({ connectionString });
113+
const ambientConnection = await ambientPool.connection();
114+
115+
const pool = nodePostgresPool({
116+
connectionString,
117+
connection: ambientConnection,
118+
});
119+
120+
try {
121+
await pool.execute.query(rawSql('SELECT 1'));
122+
} finally {
123+
await pool.close();
124+
await ambientConnection.close();
125+
await ambientPool.close();
126+
}
127+
});
128+
129+
void it('connects using ambient connected connection with transaction', async () => {
130+
const ambientPool = nodePostgresPool({ connectionString });
131+
const ambientConnection = await ambientPool.connection();
132+
await ambientConnection.open();
133+
134+
try {
135+
await ambientConnection.withTransaction<void>(async () => {
136+
const pool = nodePostgresPool({
137+
connectionString,
138+
connection: ambientConnection,
139+
});
140+
try {
141+
await pool.execute.query(rawSql('SELECT 1'));
142+
143+
return { success: true, result: undefined };
144+
} finally {
145+
await pool.close();
146+
}
147+
});
148+
} finally {
149+
await ambientConnection.close();
150+
await ambientPool.close();
151+
}
152+
});
153+
154+
void it('connects using ambient not-connected connection with transaction', async () => {
155+
const ambientPool = nodePostgresPool({ connectionString });
156+
const ambientConnection = await ambientPool.connection();
157+
158+
try {
159+
await ambientConnection.withTransaction<void>(async () => {
160+
const pool = nodePostgresPool({
161+
connectionString,
162+
connection: ambientConnection,
163+
});
164+
try {
165+
await pool.execute.query(rawSql('SELECT 1'));
166+
167+
return { success: true, result: undefined };
168+
} finally {
169+
await pool.close();
170+
}
171+
});
172+
} finally {
173+
await ambientConnection.close();
174+
await ambientPool.close();
175+
}
176+
});
177+
178+
void it('connects using ambient connection in withConnection scope', async () => {
179+
const ambientPool = nodePostgresPool({ connectionString });
180+
try {
181+
await ambientPool.withConnection(async (ambientConnection) => {
182+
const pool = nodePostgresPool({
183+
connectionString,
184+
connection: ambientConnection,
185+
});
186+
try {
187+
await pool.execute.query(rawSql('SELECT 1'));
188+
189+
return { success: true, result: undefined };
190+
} finally {
191+
await pool.close();
192+
}
193+
});
194+
} finally {
195+
await ambientPool.close();
196+
}
197+
});
198+
199+
void it('connects using ambient connection in withConnection and withTransaction scope', async () => {
200+
const ambientPool = nodePostgresPool({ connectionString });
201+
try {
202+
await ambientPool.withConnection((ambientConnection) =>
203+
ambientConnection.withTransaction<void>(async () => {
204+
const pool = nodePostgresPool({
205+
connectionString,
206+
connection: ambientConnection,
207+
});
208+
try {
209+
await pool.execute.query(rawSql('SELECT 1'));
210+
} finally {
211+
await pool.close();
212+
}
213+
}),
214+
);
215+
} finally {
216+
await ambientPool.close();
217+
}
218+
});
219+
});
220+
});

0 commit comments

Comments
 (0)