@m2k-5f/pgtx 1.4.12 → 2.0.1
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.
- package/README.md +225 -128
- package/dist/clauses/array.clause.js +1 -1
- package/dist/clauses/empty.clause.d.ts +1 -1
- package/dist/clauses/empty.clause.d.ts.map +1 -1
- package/dist/clauses/empty.clause.js +2 -2
- package/dist/clauses/fragment.clause.d.ts +1 -1
- package/dist/clauses/fragment.clause.d.ts.map +1 -1
- package/dist/clauses/fragment.clause.js +3 -5
- package/dist/clauses/iden.caluse.d.ts +1 -1
- package/dist/clauses/iden.caluse.d.ts.map +1 -1
- package/dist/clauses/index.d.ts +10 -0
- package/dist/clauses/index.d.ts.map +1 -0
- package/dist/clauses/index.js +25 -0
- package/dist/clauses/insert.clause.d.ts +1 -1
- package/dist/clauses/insert.clause.d.ts.map +1 -1
- package/dist/clauses/insert.clause.js +1 -1
- package/dist/clauses/literal.clause.d.ts +1 -1
- package/dist/clauses/literal.clause.d.ts.map +1 -1
- package/dist/clauses/update.clause.d.ts +1 -1
- package/dist/clauses/update.clause.d.ts.map +1 -1
- package/dist/clauses/update.clause.js +1 -1
- package/dist/clauses/where.clause.d.ts +1 -1
- package/dist/clauses/where.clause.d.ts.map +1 -1
- package/dist/clauses/where.clause.js +1 -1
- package/dist/connection.d.ts +135 -31
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +290 -59
- package/dist/index.d.ts +4 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -19
- package/dist/pool.d.ts +126 -32
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +203 -54
- package/dist/protocol/connection-request-writer.d.ts +38 -0
- package/dist/protocol/connection-request-writer.d.ts.map +1 -0
- package/dist/protocol/connection-request-writer.js +175 -0
- package/dist/protocol/connection-response-reader.d.ts +49 -0
- package/dist/protocol/connection-response-reader.d.ts.map +1 -0
- package/dist/protocol/connection-response-reader.js +185 -0
- package/dist/protocol/constants.d.ts +46 -0
- package/dist/protocol/constants.d.ts.map +1 -0
- package/dist/protocol/constants.js +43 -0
- package/dist/protocol/socket-authorization.d.ts +11 -0
- package/dist/protocol/socket-authorization.d.ts.map +1 -0
- package/dist/protocol/socket-authorization.js +95 -0
- package/dist/protocol/socket-connector.d.ts +17 -0
- package/dist/protocol/socket-connector.d.ts.map +1 -0
- package/dist/protocol/socket-connector.js +48 -0
- package/dist/queue.d.ts +10 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +27 -0
- package/dist/security/md5.d.ts +2 -0
- package/dist/security/md5.d.ts.map +1 -0
- package/dist/security/md5.js +12 -0
- package/dist/security/sasl.d.ts +6 -0
- package/dist/security/sasl.d.ts.map +1 -0
- package/dist/security/sasl.js +29 -0
- package/dist/transaction.d.ts +1 -2
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +4 -4
- package/dist/types.d.ts +6 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/template-compiler.d.ts +3 -0
- package/dist/utils/template-compiler.d.ts.map +1 -0
- package/dist/utils/template-compiler.js +64 -0
- package/dist/utils/value-parser.d.ts +6 -0
- package/dist/utils/value-parser.d.ts.map +1 -0
- package/dist/utils/value-parser.js +101 -0
- package/package.json +8 -9
package/dist/index.js
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Pool = exports.Transaction = exports.Connection = exports.sql = void 0;
|
|
3
|
+
exports.setTypeParser = exports.Pool = exports.Transaction = exports.Connection = exports.sql = void 0;
|
|
4
4
|
const pool_1 = require("./pool");
|
|
5
5
|
Object.defineProperty(exports, "Pool", { enumerable: true, get: function () { return pool_1.Pool; } });
|
|
6
|
-
const
|
|
7
|
-
const where_clause_1 = require("./clauses/where.clause");
|
|
8
|
-
const insert_clause_1 = require("./clauses/insert.clause");
|
|
9
|
-
const update_clause_1 = require("./clauses/update.clause");
|
|
10
|
-
const exclude_clause_1 = require("./clauses/exclude.clause");
|
|
11
|
-
const iden_caluse_1 = require("./clauses/iden.caluse");
|
|
12
|
-
const literal_clause_1 = require("./clauses/literal.clause");
|
|
13
|
-
const fragment_clause_1 = require("./clauses/fragment.clause");
|
|
14
|
-
const array_clause_1 = require("./clauses/array.clause");
|
|
6
|
+
const clauses_1 = require("./clauses");
|
|
15
7
|
const connection_1 = require("./connection");
|
|
16
8
|
Object.defineProperty(exports, "Connection", { enumerable: true, get: function () { return connection_1.Connection; } });
|
|
17
9
|
const transaction_1 = require("./transaction");
|
|
18
10
|
Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_1.Transaction; } });
|
|
11
|
+
const value_parser_1 = require("./utils/value-parser");
|
|
12
|
+
Object.defineProperty(exports, "setTypeParser", { enumerable: true, get: function () { return value_parser_1.setTypeParser; } });
|
|
19
13
|
/**
|
|
20
14
|
* Core SQL tagging utility for Pgtx.
|
|
21
15
|
* Provides type-safe helpers for building dynamic queries with recursive support.
|
|
@@ -33,7 +27,7 @@ exports.sql = {
|
|
|
33
27
|
* sql.insert([{ id: 1 }, { id: 2 }])
|
|
34
28
|
* // Result: (id) VALUES ($1), ($2)
|
|
35
29
|
*/
|
|
36
|
-
insert:
|
|
30
|
+
insert: clauses_1.InsertClause.create,
|
|
37
31
|
/**
|
|
38
32
|
* Generates a SET clause for UPDATE queries from a JavaScript object.
|
|
39
33
|
*
|
|
@@ -41,7 +35,7 @@ exports.sql = {
|
|
|
41
35
|
* sql.update({ status: 'active', updated_at: new Date() })
|
|
42
36
|
* // Result: status = $1, updated_at = $2
|
|
43
37
|
*/
|
|
44
|
-
update:
|
|
38
|
+
update: clauses_1.UpdateClause.create,
|
|
45
39
|
/**
|
|
46
40
|
* Generates an assignment list for ON CONFLICT DO UPDATE using the EXCLUDED table.
|
|
47
41
|
*
|
|
@@ -49,7 +43,7 @@ exports.sql = {
|
|
|
49
43
|
* sql`INSERT INTO users ${sql.insert(data)} ON CONFLICT (id) DO UPDATE SET ${sql.excluded(['name', 'email'])}`
|
|
50
44
|
* // Result: name = EXCLUDED.name, email = EXCLUDED.email
|
|
51
45
|
*/
|
|
52
|
-
excluded:
|
|
46
|
+
excluded: clauses_1.ExcludeUpdateClause.create,
|
|
53
47
|
/**
|
|
54
48
|
* Represents a safe empty SQL fragment.
|
|
55
49
|
* Useful for dynamic query building when a condition or list might be optional.
|
|
@@ -59,7 +53,7 @@ exports.sql = {
|
|
|
59
53
|
* sql`SELECT * FROM users ${filters.length ? sql.fragment`WHERE ...` : sql.empty}`
|
|
60
54
|
* // Result: SELECT * FROM users
|
|
61
55
|
*/
|
|
62
|
-
empty:
|
|
56
|
+
empty: clauses_1.emptyClause,
|
|
63
57
|
/**
|
|
64
58
|
* Generates a list of conditions for a WHERE clause from a JavaScript object.
|
|
65
59
|
* Works similarly to sql.update, but uses ' AND ' as a separator instead of a comma.
|
|
@@ -72,7 +66,7 @@ exports.sql = {
|
|
|
72
66
|
* sql`DELETE FROM tasks WHERE ${sql.where({ id: 10, user_id: 5 })}`
|
|
73
67
|
* // Result: id = $1 AND user_id = $2
|
|
74
68
|
*/
|
|
75
|
-
where:
|
|
69
|
+
where: clauses_1.WhereClause.create,
|
|
76
70
|
/**
|
|
77
71
|
* Safely escapes SQL identifiers (table or column names) using double quotes.
|
|
78
72
|
*
|
|
@@ -84,7 +78,7 @@ exports.sql = {
|
|
|
84
78
|
* sql.ident('table.column')
|
|
85
79
|
* // Result: "table.column"
|
|
86
80
|
*/
|
|
87
|
-
ident:
|
|
81
|
+
ident: clauses_1.IdentifierClause.create,
|
|
88
82
|
/**
|
|
89
83
|
* Injects raw, unescaped SQL strings.
|
|
90
84
|
* ⚠️ Use with caution to prevent SQL injection!
|
|
@@ -93,7 +87,7 @@ exports.sql = {
|
|
|
93
87
|
* sql.literal('DESC')
|
|
94
88
|
* // Result: DESC
|
|
95
89
|
*/
|
|
96
|
-
literal:
|
|
90
|
+
literal: clauses_1.LiteralClause.create,
|
|
97
91
|
/**
|
|
98
92
|
* Creates a reusable, recursive SQL fragment.
|
|
99
93
|
* Fragments can be nested within each other; argument numbering is handled automatically.
|
|
@@ -103,7 +97,7 @@ exports.sql = {
|
|
|
103
97
|
* sql`SELECT * FROM users WHERE ${filter} AND status = ${'active'}`
|
|
104
98
|
* // Result: SELECT * FROM users WHERE age > $1 AND status = $2
|
|
105
99
|
*/
|
|
106
|
-
fragment:
|
|
100
|
+
fragment: clauses_1.FragmentClause.create,
|
|
107
101
|
/**
|
|
108
102
|
* Formats an array for dynamic lists (IN clauses, column lists, or joined conditions).
|
|
109
103
|
* Supports recursive Clauses (fragments, idents) within the array.
|
|
@@ -124,5 +118,5 @@ exports.sql = {
|
|
|
124
118
|
* sql`SELECT ${sql.array([sql.ident('id'), sql.ident('name')])}`
|
|
125
119
|
* // Result: SELECT "id", "name"
|
|
126
120
|
*/
|
|
127
|
-
array:
|
|
121
|
+
array: clauses_1.ArrayClause.create,
|
|
128
122
|
};
|
package/dist/pool.d.ts
CHANGED
|
@@ -1,60 +1,154 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PoolConfig, PreparedStatement } from "./types";
|
|
3
|
-
import { Connection } from "./connection";
|
|
1
|
+
import { Connection, ConnectionParams } from "./connection";
|
|
4
2
|
import { Transaction } from "./transaction";
|
|
3
|
+
type PoolParams = ConnectionParams & {
|
|
4
|
+
max?: number;
|
|
5
|
+
};
|
|
5
6
|
/**
|
|
6
7
|
* The main entry point for Pgtx.
|
|
7
8
|
* Manages a connection pool and provides high-level API for queries and transactions.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const pool = new Pool({
|
|
13
|
+
* host: 'localhost',
|
|
14
|
+
* user: 'postgres',
|
|
15
|
+
* password: 'postgres',
|
|
16
|
+
* database: 'test',
|
|
17
|
+
* max: 10
|
|
18
|
+
* })
|
|
19
|
+
*
|
|
20
|
+
* // Simple query
|
|
21
|
+
* const users = await pool.query`SELECT * FROM users WHERE id = ${1}`
|
|
22
|
+
*
|
|
23
|
+
* // Transaction
|
|
24
|
+
* const result = await pool.begin(async tx => {
|
|
25
|
+
* await tx.query`INSERT INTO users ...`
|
|
26
|
+
* return 'success'
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* // Manual acquire/release
|
|
30
|
+
* const conn = await pool.acquire()
|
|
31
|
+
* try {
|
|
32
|
+
* await conn.query`SELECT 1`
|
|
33
|
+
* } finally {
|
|
34
|
+
* pool.release(conn)
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* // Clean up
|
|
38
|
+
* await pool.close()
|
|
39
|
+
* ```
|
|
8
40
|
*/
|
|
9
41
|
export declare class Pool {
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
|
|
42
|
+
private _available;
|
|
43
|
+
private _config;
|
|
44
|
+
private _max;
|
|
45
|
+
private _total;
|
|
46
|
+
private _waiting;
|
|
47
|
+
private _isClosed;
|
|
48
|
+
private _checkClosed;
|
|
49
|
+
constructor(params: PoolParams);
|
|
13
50
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
51
|
+
* Acquires a dedicated connection from the pool.
|
|
52
|
+
*
|
|
53
|
+
* **Note:** You must call `pool.release(conn)` manually when finished.
|
|
54
|
+
* For most cases, prefer using `pool.query()` or `pool.begin()` which handle this automatically.
|
|
55
|
+
*
|
|
56
|
+
* @returns A connection from the pool or a new one if available.
|
|
16
57
|
*
|
|
17
58
|
* @example
|
|
18
|
-
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* const conn = await pool.acquire()
|
|
61
|
+
* try {
|
|
62
|
+
* await conn.query`SELECT 1`
|
|
63
|
+
* } finally {
|
|
64
|
+
* pool.release(conn)
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
19
67
|
*/
|
|
20
|
-
|
|
68
|
+
acquire(): Promise<Connection>;
|
|
21
69
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
70
|
+
* Releases the connection back to the pool.
|
|
71
|
+
*
|
|
72
|
+
* If there are pending `acquire()` calls, the connection is passed directly to the next waiter.
|
|
73
|
+
* Otherwise, it's added to the available connections queue.
|
|
74
|
+
*
|
|
75
|
+
* @param conn - The connection to release.
|
|
25
76
|
*
|
|
26
77
|
* @example
|
|
27
|
-
*
|
|
28
|
-
* const
|
|
78
|
+
* ```ts
|
|
79
|
+
* const conn = await pool.acquire()
|
|
80
|
+
* try {
|
|
81
|
+
* await conn.query`SELECT 1`
|
|
82
|
+
* } finally {
|
|
83
|
+
* pool.release(conn)
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
29
86
|
*/
|
|
30
|
-
|
|
87
|
+
release(conn: Connection): void;
|
|
31
88
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
89
|
+
* Starts a managed transaction.
|
|
90
|
+
*
|
|
91
|
+
* Automatically acquires a connection and handles `BEGIN`, `COMMIT`, and `ROLLBACK`.
|
|
92
|
+
* If the callback throws an error, the transaction is rolled back.
|
|
93
|
+
*
|
|
94
|
+
* @param txCallback - Async function that receives a `Transaction` instance.
|
|
95
|
+
* @returns The value returned from the callback.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* const result = await pool.begin(async tx => {
|
|
100
|
+
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
101
|
+
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
102
|
+
* return { success: true }
|
|
103
|
+
* })
|
|
104
|
+
* ```
|
|
34
105
|
*/
|
|
35
|
-
|
|
106
|
+
begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Promise<T>;
|
|
36
107
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
108
|
+
* Executes a one-off query using pipeline.
|
|
109
|
+
*
|
|
110
|
+
* Automatically acquires and releases a connection from the pool.
|
|
111
|
+
* For optimal performance, multiple queries can be pipelined through the same connection.
|
|
112
|
+
*
|
|
113
|
+
* @param templates - Tagged template string with SQL.
|
|
114
|
+
* @param args - Query parameters.
|
|
115
|
+
* @returns Array of rows with proper typing.
|
|
39
116
|
*
|
|
40
117
|
* @example
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
118
|
+
* ```ts
|
|
119
|
+
* // Simple query
|
|
120
|
+
* const users = await pool.query`SELECT * FROM users`
|
|
121
|
+
*
|
|
122
|
+
* // With parameters
|
|
123
|
+
* const user = await pool.query`SELECT * FROM users WHERE id = ${1}`
|
|
124
|
+
*
|
|
125
|
+
* // With typed result
|
|
126
|
+
* type User = { id: number, name: string }
|
|
127
|
+
* const users = await pool.query<User>`SELECT * FROM users`
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
query<T extends Record<string, unknown>>(templates: TemplateStringsArray, ...args: any[]): Promise<T[]>;
|
|
131
|
+
/**
|
|
132
|
+
* Number of available (idle) connections in the pool.
|
|
45
133
|
*/
|
|
46
|
-
|
|
134
|
+
get size(): number;
|
|
47
135
|
/**
|
|
48
|
-
*
|
|
136
|
+
* Total number of connections currently managed by the pool
|
|
137
|
+
* (available + in use).
|
|
49
138
|
*/
|
|
50
|
-
get
|
|
51
|
-
total: number;
|
|
52
|
-
idle: number;
|
|
53
|
-
waiting: number;
|
|
54
|
-
};
|
|
139
|
+
get total(): number;
|
|
55
140
|
/**
|
|
56
141
|
* Shuts down the pool and closes all active connections.
|
|
142
|
+
*
|
|
143
|
+
* All pending `acquire()` calls will be rejected with an error.
|
|
144
|
+
* The pool cannot be used after calling `close()`.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* await pool.close()
|
|
149
|
+
* ```
|
|
57
150
|
*/
|
|
58
151
|
close(): Promise<void>;
|
|
59
152
|
}
|
|
153
|
+
export {};
|
|
60
154
|
//# sourceMappingURL=pool.d.ts.map
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAI3C,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,IAAI;IACb,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,YAAY;gBAIR,MAAM,EAAE,UAAU;IAM9B;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IA6BpC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU;IAoBxB;;;;;;;;;;;;;;;;;OAiBG;IACG,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYhF;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAmCvG;;OAEG;IACH,IAAI,IAAI,WAEP;IAGD;;;OAGG;IACH,IAAI,KAAK,WAER;IAGD;;;;;;;;;;OAUG;IACG,KAAK;CAed"}
|
package/dist/pool.js
CHANGED
|
@@ -1,96 +1,245 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Pool = void 0;
|
|
4
|
-
const pg_1 = require("pg");
|
|
5
4
|
const connection_1 = require("./connection");
|
|
6
|
-
const
|
|
5
|
+
const queue_1 = require("./queue");
|
|
7
6
|
/**
|
|
8
7
|
* The main entry point for Pgtx.
|
|
9
8
|
* Manages a connection pool and provides high-level API for queries and transactions.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const pool = new Pool({
|
|
13
|
+
* host: 'localhost',
|
|
14
|
+
* user: 'postgres',
|
|
15
|
+
* password: 'postgres',
|
|
16
|
+
* database: 'test',
|
|
17
|
+
* max: 10
|
|
18
|
+
* })
|
|
19
|
+
*
|
|
20
|
+
* // Simple query
|
|
21
|
+
* const users = await pool.query`SELECT * FROM users WHERE id = ${1}`
|
|
22
|
+
*
|
|
23
|
+
* // Transaction
|
|
24
|
+
* const result = await pool.begin(async tx => {
|
|
25
|
+
* await tx.query`INSERT INTO users ...`
|
|
26
|
+
* return 'success'
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* // Manual acquire/release
|
|
30
|
+
* const conn = await pool.acquire()
|
|
31
|
+
* try {
|
|
32
|
+
* await conn.query`SELECT 1`
|
|
33
|
+
* } finally {
|
|
34
|
+
* pool.release(conn)
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* // Clean up
|
|
38
|
+
* await pool.close()
|
|
39
|
+
* ```
|
|
10
40
|
*/
|
|
11
41
|
class Pool {
|
|
12
|
-
|
|
13
|
-
this.
|
|
14
|
-
|
|
42
|
+
_checkClosed() {
|
|
43
|
+
if (this._isClosed)
|
|
44
|
+
throw new Error('Pool closed');
|
|
45
|
+
}
|
|
46
|
+
constructor(params) {
|
|
47
|
+
this._available = new queue_1.Queue();
|
|
48
|
+
this._total = 0;
|
|
49
|
+
this._waiting = new queue_1.Queue();
|
|
50
|
+
this._isClosed = false;
|
|
51
|
+
this._config = params;
|
|
52
|
+
this._max = params.max || 20;
|
|
15
53
|
}
|
|
16
54
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
55
|
+
* Acquires a dedicated connection from the pool.
|
|
56
|
+
*
|
|
57
|
+
* **Note:** You must call `pool.release(conn)` manually when finished.
|
|
58
|
+
* For most cases, prefer using `pool.query()` or `pool.begin()` which handle this automatically.
|
|
59
|
+
*
|
|
60
|
+
* @returns A connection from the pool or a new one if available.
|
|
19
61
|
*
|
|
20
62
|
* @example
|
|
21
|
-
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* const conn = await pool.acquire()
|
|
65
|
+
* try {
|
|
66
|
+
* await conn.query`SELECT 1`
|
|
67
|
+
* } finally {
|
|
68
|
+
* pool.release(conn)
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
22
71
|
*/
|
|
23
|
-
async
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
72
|
+
async acquire() {
|
|
73
|
+
this._checkClosed();
|
|
74
|
+
while (!this._available.isFree) {
|
|
75
|
+
const conn = this._available.get();
|
|
76
|
+
this._available.next();
|
|
77
|
+
if (conn.isAlive) {
|
|
78
|
+
return conn;
|
|
79
|
+
}
|
|
80
|
+
this._total--;
|
|
27
81
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
82
|
+
if (this._total < this._max) {
|
|
83
|
+
this._total++;
|
|
84
|
+
try {
|
|
85
|
+
return await connection_1.Connection.new(this._config);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
this._total--;
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
33
91
|
}
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
this._waiting.push({ resolve, reject });
|
|
94
|
+
});
|
|
34
95
|
}
|
|
35
96
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
97
|
+
* Releases the connection back to the pool.
|
|
98
|
+
*
|
|
99
|
+
* If there are pending `acquire()` calls, the connection is passed directly to the next waiter.
|
|
100
|
+
* Otherwise, it's added to the available connections queue.
|
|
101
|
+
*
|
|
102
|
+
* @param conn - The connection to release.
|
|
39
103
|
*
|
|
40
104
|
* @example
|
|
41
|
-
*
|
|
42
|
-
* const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Acquires a dedicated connection from the pool.
|
|
51
|
-
* **Note:** You must call `connection.release()` manually when finished.
|
|
105
|
+
* ```ts
|
|
106
|
+
* const conn = await pool.acquire()
|
|
107
|
+
* try {
|
|
108
|
+
* await conn.query`SELECT 1`
|
|
109
|
+
* } finally {
|
|
110
|
+
* pool.release(conn)
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
52
113
|
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
114
|
+
release(conn) {
|
|
115
|
+
this._checkClosed();
|
|
116
|
+
if (!conn.isAlive) {
|
|
117
|
+
this._total--;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!this._waiting.isFree) {
|
|
121
|
+
const waiter = this._waiting.get();
|
|
122
|
+
this._waiting.next();
|
|
123
|
+
waiter.resolve(conn);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this._available.push(conn);
|
|
56
127
|
}
|
|
57
128
|
/**
|
|
58
129
|
* Starts a managed transaction.
|
|
59
|
-
*
|
|
130
|
+
*
|
|
131
|
+
* Automatically acquires a connection and handles `BEGIN`, `COMMIT`, and `ROLLBACK`.
|
|
132
|
+
* If the callback throws an error, the transaction is rolled back.
|
|
133
|
+
*
|
|
134
|
+
* @param txCallback - Async function that receives a `Transaction` instance.
|
|
135
|
+
* @returns The value returned from the callback.
|
|
60
136
|
*
|
|
61
137
|
* @example
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* const result = await pool.begin(async tx => {
|
|
140
|
+
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
141
|
+
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
142
|
+
* return { success: true }
|
|
143
|
+
* })
|
|
144
|
+
* ```
|
|
66
145
|
*/
|
|
67
|
-
async begin(
|
|
146
|
+
async begin(txCallback) {
|
|
147
|
+
this._checkClosed();
|
|
68
148
|
const conn = await this.acquire();
|
|
69
149
|
try {
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
throw err;
|
|
150
|
+
return conn.begin(txCallback);
|
|
74
151
|
}
|
|
75
152
|
finally {
|
|
76
|
-
|
|
153
|
+
this.release(conn);
|
|
77
154
|
}
|
|
78
155
|
}
|
|
79
156
|
/**
|
|
80
|
-
*
|
|
157
|
+
* Executes a one-off query using pipeline.
|
|
158
|
+
*
|
|
159
|
+
* Automatically acquires and releases a connection from the pool.
|
|
160
|
+
* For optimal performance, multiple queries can be pipelined through the same connection.
|
|
161
|
+
*
|
|
162
|
+
* @param templates - Tagged template string with SQL.
|
|
163
|
+
* @param args - Query parameters.
|
|
164
|
+
* @returns Array of rows with proper typing.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* // Simple query
|
|
169
|
+
* const users = await pool.query`SELECT * FROM users`
|
|
170
|
+
*
|
|
171
|
+
* // With parameters
|
|
172
|
+
* const user = await pool.query`SELECT * FROM users WHERE id = ${1}`
|
|
173
|
+
*
|
|
174
|
+
* // With typed result
|
|
175
|
+
* type User = { id: number, name: string }
|
|
176
|
+
* const users = await pool.query<User>`SELECT * FROM users`
|
|
177
|
+
* ```
|
|
81
178
|
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
179
|
+
query(templates, ...args) {
|
|
180
|
+
this._checkClosed();
|
|
181
|
+
while (!this._available.isFree) {
|
|
182
|
+
const conn = this._available.get();
|
|
183
|
+
if (conn.isAlive) {
|
|
184
|
+
return conn.query(templates, ...args);
|
|
185
|
+
}
|
|
186
|
+
this._available.next();
|
|
187
|
+
this._total--;
|
|
188
|
+
}
|
|
189
|
+
if (this._total < this._max) {
|
|
190
|
+
this._total++;
|
|
191
|
+
return connection_1.Connection.new(this._config)
|
|
192
|
+
.catch(err => {
|
|
193
|
+
this._total--;
|
|
194
|
+
throw err;
|
|
195
|
+
})
|
|
196
|
+
.then(conn => {
|
|
197
|
+
this.release(conn);
|
|
198
|
+
return conn.query(templates, ...args);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return this.acquire()
|
|
202
|
+
.then(conn => {
|
|
203
|
+
this.release(conn);
|
|
204
|
+
return conn.query(templates, ...args);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Number of available (idle) connections in the pool.
|
|
209
|
+
*/
|
|
210
|
+
get size() {
|
|
211
|
+
return this._available.size;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Total number of connections currently managed by the pool
|
|
215
|
+
* (available + in use).
|
|
216
|
+
*/
|
|
217
|
+
get total() {
|
|
218
|
+
return this._total;
|
|
88
219
|
}
|
|
89
220
|
/**
|
|
90
221
|
* Shuts down the pool and closes all active connections.
|
|
222
|
+
*
|
|
223
|
+
* All pending `acquire()` calls will be rejected with an error.
|
|
224
|
+
* The pool cannot be used after calling `close()`.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* await pool.close()
|
|
229
|
+
* ```
|
|
91
230
|
*/
|
|
92
|
-
close() {
|
|
93
|
-
|
|
231
|
+
async close() {
|
|
232
|
+
while (!this._available.isFree) {
|
|
233
|
+
const conn = this._available.get();
|
|
234
|
+
this._available.next();
|
|
235
|
+
conn.close();
|
|
236
|
+
}
|
|
237
|
+
while (!this._waiting.isFree) {
|
|
238
|
+
const waiter = this._waiting.get();
|
|
239
|
+
this._waiting.next();
|
|
240
|
+
waiter.reject(new Error('Pool closed'));
|
|
241
|
+
}
|
|
242
|
+
this._total = 0;
|
|
94
243
|
}
|
|
95
244
|
}
|
|
96
245
|
exports.Pool = Pool;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { RequestType } from "./constants";
|
|
2
|
+
export declare class ConnectionRequestBuffer {
|
|
3
|
+
private buffer;
|
|
4
|
+
private offset;
|
|
5
|
+
private lastRequestLenByteOffset;
|
|
6
|
+
private constructor();
|
|
7
|
+
static new(capacity: number): ConnectionRequestBuffer;
|
|
8
|
+
private ensureCapacity;
|
|
9
|
+
writeCString(string: string): this;
|
|
10
|
+
writeString(string: string): this;
|
|
11
|
+
writeInt32(number: number): this;
|
|
12
|
+
writeInt16(number: number): this;
|
|
13
|
+
writeChar(char: string): this;
|
|
14
|
+
startRequest(requestType: RequestType): this;
|
|
15
|
+
startMessage(): this;
|
|
16
|
+
endRequest(): this;
|
|
17
|
+
asBuffer(): Buffer<ArrayBufferLike>;
|
|
18
|
+
clear(): void;
|
|
19
|
+
}
|
|
20
|
+
export declare class ConnectionRequestWriter {
|
|
21
|
+
private buffer;
|
|
22
|
+
private constructor();
|
|
23
|
+
static new(): ConnectionRequestWriter;
|
|
24
|
+
writeQuery(text: string): this;
|
|
25
|
+
writeParse(name: string | "", text: string): this;
|
|
26
|
+
writeDescribe(statementName: string | ""): this;
|
|
27
|
+
writeBind(portName: string | "", statementName: string | "", params: (string | null)[]): this;
|
|
28
|
+
writeClose(name: string): this;
|
|
29
|
+
writeStartup(user: string, database: string): this;
|
|
30
|
+
writeExecute(portName: string | ""): this;
|
|
31
|
+
writeSync(): this;
|
|
32
|
+
writePassword(password: string): this;
|
|
33
|
+
writeSaslInitial(mechanism: string, clientFirstMessage: string): this;
|
|
34
|
+
writeSaslResponse(clientFinalMessage: string): this;
|
|
35
|
+
asBuffer(): Buffer<ArrayBufferLike>;
|
|
36
|
+
clear(): this;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=connection-request-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-request-writer.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-request-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAA;AAGvD,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,wBAAwB;IAHpC,OAAO;IAOP,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAK3B,OAAO,CAAC,cAAc;IAmBtB,YAAY,CAAC,MAAM,EAAE,MAAM;IAY3B,WAAW,CAAC,MAAM,EAAE,MAAM;IAS1B,UAAU,CAAC,MAAM,EAAE,MAAM;IAUzB,UAAU,CAAC,MAAM,EAAE,MAAM;IAUzB,SAAS,CAAC,IAAI,EAAE,MAAM;IAStB,YAAY,CAAC,WAAW,EAAE,WAAW;IAQrC,YAAY;IAMZ,UAAU;IAUV,QAAQ;IAKR,KAAK;CAIR;AAGD,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,MAAM;IADlB,OAAO;IAIP,MAAM,CAAC,GAAG;IAMV,UAAU,CAAC,IAAI,EAAE,MAAM;IASvB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM;IAW1C,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,EAAE;IAUxC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE;IAmBtF,UAAU,CAAC,IAAI,EAAE,MAAM;IAUvB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAY3C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,EAAE;IAUlC,SAAS;IAOT,aAAa,CAAC,QAAQ,EAAE,MAAM;IAS9B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM;IAW9D,iBAAiB,CAAC,kBAAkB,EAAE,MAAM;IAS5C,QAAQ;IAKR,KAAK;CAKR"}
|