@m2k-5f/pgtx 1.4.12 → 2.0.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.
- 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 +2 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -18
- 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
|
@@ -2,7 +2,7 @@ import { Clause } from "./abstract.clause";
|
|
|
2
2
|
import { ClauseStrategyParams } from "../types";
|
|
3
3
|
export declare class WhereClause<T extends Record<string, any>> extends Clause {
|
|
4
4
|
private _value;
|
|
5
|
-
constructor(
|
|
5
|
+
private constructor();
|
|
6
6
|
static create<T extends Record<string, any>>(whereMap: T): WhereClause<T>;
|
|
7
7
|
mapIntoQuery(params: ClauseStrategyParams): void;
|
|
8
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"where.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/where.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE9D,OAAO,CAAC,MAAM;
|
|
1
|
+
{"version":3,"file":"where.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/where.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE9D,OAAO,CAAC,MAAM;IADlB,OAAO;WAIO,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;IAItD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAYrD"}
|
package/dist/connection.d.ts
CHANGED
|
@@ -1,51 +1,155 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PreparedStatement } from "./types";
|
|
1
|
+
import { ColumnDescription } from "./types";
|
|
3
2
|
import { Transaction } from "./transaction";
|
|
3
|
+
import { Queue } from "./queue";
|
|
4
|
+
type LogLevel = "none" | "error" | "notice" | "query";
|
|
5
|
+
export type ConnectionParams = {
|
|
6
|
+
user: string;
|
|
7
|
+
password?: string;
|
|
8
|
+
host: string;
|
|
9
|
+
port: number;
|
|
10
|
+
database: string;
|
|
11
|
+
logLevel?: LogLevel;
|
|
12
|
+
};
|
|
13
|
+
export type ConnectionQueryContext = {
|
|
14
|
+
columns: ColumnDescription[];
|
|
15
|
+
rows: (string | null)[][];
|
|
16
|
+
resolve: (value: any) => void;
|
|
17
|
+
reject: (err: Error) => void;
|
|
18
|
+
text: string;
|
|
19
|
+
statementName: string | null;
|
|
20
|
+
};
|
|
21
|
+
export declare class ConnectionQueryQueue extends Queue<ConnectionQueryContext> {
|
|
22
|
+
rejectAllNext(error: Error): void;
|
|
23
|
+
}
|
|
4
24
|
/**
|
|
5
|
-
* Represents a single dedicated connection to the database.
|
|
6
|
-
*
|
|
25
|
+
* Represents a single dedicated connection to the PostgreSQL database.
|
|
26
|
+
*
|
|
27
|
+
* Supports:
|
|
28
|
+
* - Tagged template queries with automatic parameter binding
|
|
29
|
+
* - Prepared statements with caching
|
|
30
|
+
* - Transaction management with savepoints
|
|
31
|
+
* - Pipeline execution for concurrent queries
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const conn = await Connection.new({
|
|
36
|
+
* host: 'localhost',
|
|
37
|
+
* user: 'postgres',
|
|
38
|
+
* password: 'postgres',
|
|
39
|
+
* database: 'test'
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* // Simple query
|
|
43
|
+
* const users = await conn.query`SELECT * FROM users WHERE id = ${1}`
|
|
44
|
+
*
|
|
45
|
+
* // Transaction
|
|
46
|
+
* await conn.begin(async tx => {
|
|
47
|
+
* await tx.query`INSERT INTO users ...`
|
|
48
|
+
* })
|
|
49
|
+
*
|
|
50
|
+
* // Close connection
|
|
51
|
+
* conn.close()
|
|
52
|
+
* ```
|
|
7
53
|
*/
|
|
8
54
|
export declare class Connection {
|
|
9
|
-
private
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
55
|
+
private _isFlushing;
|
|
56
|
+
private _isAlive;
|
|
57
|
+
private _socket;
|
|
58
|
+
private _writer;
|
|
59
|
+
private _queue;
|
|
60
|
+
private _statementDescriptions;
|
|
61
|
+
private _statements;
|
|
62
|
+
private _parsePending;
|
|
63
|
+
private _stmtCounter;
|
|
64
|
+
private _logLevel;
|
|
65
|
+
private _nextStatement;
|
|
66
|
+
private constructor();
|
|
17
67
|
/**
|
|
18
|
-
* Creates a
|
|
19
|
-
*
|
|
68
|
+
* Creates a new database connection.
|
|
69
|
+
*
|
|
70
|
+
* @param params - Connection parameters
|
|
71
|
+
* @returns A new Connection instance
|
|
72
|
+
* @throws {Error} If authentication fails or connection cannot be established
|
|
20
73
|
*
|
|
21
74
|
* @example
|
|
22
|
-
*
|
|
23
|
-
* const
|
|
75
|
+
* ```ts
|
|
76
|
+
* const conn = await Connection.new({
|
|
77
|
+
* host: 'localhost',
|
|
78
|
+
* port: 5432,
|
|
79
|
+
* user: 'postgres',
|
|
80
|
+
* password: 'secret',
|
|
81
|
+
* database: 'myapp'
|
|
82
|
+
* })
|
|
83
|
+
* ```
|
|
24
84
|
*/
|
|
25
|
-
|
|
85
|
+
static new(params: ConnectionParams): Promise<Connection>;
|
|
26
86
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
87
|
+
* Executes a query using tagged template literals.
|
|
88
|
+
*
|
|
89
|
+
* Parameters are automatically bound to `$1, $2, ...` placeholders.
|
|
90
|
+
* Queries with parameters use prepared statements for performance.
|
|
91
|
+
*
|
|
92
|
+
* @param templates - Tagged template string with SQL
|
|
93
|
+
* @param args - Query parameters
|
|
94
|
+
* @returns Array of rows with proper typing
|
|
95
|
+
* @throws {Error} If connection is dead or query fails
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* // Simple query
|
|
100
|
+
* const users = await conn.query`SELECT * FROM users`
|
|
101
|
+
*
|
|
102
|
+
* // With parameters
|
|
103
|
+
* const user = await conn.query`SELECT * FROM users WHERE id = ${1}`
|
|
104
|
+
*
|
|
105
|
+
* // With typed result
|
|
106
|
+
* type User = { id: number, name: string }
|
|
107
|
+
* const users = await conn.query<User>`SELECT * FROM users`
|
|
108
|
+
* ```
|
|
29
109
|
*/
|
|
30
|
-
|
|
31
|
-
private checkActive;
|
|
110
|
+
query<T extends Record<string, unknown>>(templates: TemplateStringsArray, ...args: any[]): Promise<T[]>;
|
|
32
111
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
112
|
+
* Starts a managed transaction on this connection.
|
|
113
|
+
*
|
|
114
|
+
* Automatically handles:
|
|
115
|
+
* - `BEGIN` before the callback
|
|
116
|
+
* - `COMMIT` on successful completion
|
|
117
|
+
* - `ROLLBACK` if an error is thrown
|
|
118
|
+
*
|
|
119
|
+
* @param txCallback - Async function that receives a `Transaction` instance
|
|
120
|
+
* @returns The value returned from the callback
|
|
121
|
+
* @throws {Error} If connection is dead or transaction fails
|
|
35
122
|
*
|
|
36
123
|
* @example
|
|
37
|
-
*
|
|
124
|
+
* ```ts
|
|
125
|
+
* const result = await conn.begin(async tx => {
|
|
126
|
+
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
127
|
+
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
128
|
+
* return { success: true }
|
|
129
|
+
* })
|
|
130
|
+
* ```
|
|
38
131
|
*/
|
|
39
|
-
|
|
132
|
+
begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Promise<T>;
|
|
133
|
+
private _registerFlush;
|
|
134
|
+
private _flush;
|
|
135
|
+
private _handlePacket;
|
|
136
|
+
private _handleError;
|
|
40
137
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
138
|
+
* Checks if the connection is still alive and usable.
|
|
139
|
+
* Returns `false` if the socket is destroyed or connection is dead.
|
|
140
|
+
*/
|
|
141
|
+
get isAlive(): boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Closes the connection immediately.
|
|
144
|
+
* All pending queries will be rejected with an error.
|
|
145
|
+
* The connection cannot be used after this call.
|
|
43
146
|
*
|
|
44
147
|
* @example
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
148
|
+
* ```ts
|
|
149
|
+
* conn.close()
|
|
150
|
+
* ```
|
|
48
151
|
*/
|
|
49
|
-
|
|
152
|
+
close(): void;
|
|
50
153
|
}
|
|
154
|
+
export {};
|
|
51
155
|
//# sourceMappingURL=connection.d.ts.map
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAE/B,KAAK,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;AAErD,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACtB,CAAA;AAKD,MAAM,MAAM,sBAAsB,GAAG;IACjC,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAA;IACzB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7B,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B,CAAA;AAGD,qBAAa,oBAAqB,SAAQ,KAAK,CAAC,sBAAsB,CAAC;IAEnE,aAAa,CAAC,KAAK,EAAE,KAAK;CAM7B;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAO;IACvB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,sBAAsB,CAAyC;IACvE,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,SAAS,CAAU;IAG3B,OAAO,CAAC,cAAc;IAItB,OAAO;IAcP;;;;;;;;;;;;;;;;;OAiBG;WACU,GAAG,CAAC,MAAM,EAAE,gBAAgB;IAQzC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;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;IA0DvG;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqBhF,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,aAAa;IAoFrB,OAAO,CAAC,YAAY;IAQpB;;;OAGG;IACH,IAAI,OAAO,YAEV;IAGD;;;;;;;;;OASG;IACH,KAAK;CAIR"}
|
package/dist/connection.js
CHANGED
|
@@ -1,89 +1,188 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Connection = void 0;
|
|
3
|
+
exports.Connection = exports.ConnectionQueryQueue = void 0;
|
|
4
|
+
const process_1 = require("process");
|
|
5
|
+
const connection_request_writer_1 = require("./protocol/connection-request-writer");
|
|
6
|
+
const socket_authorization_1 = require("./protocol/socket-authorization");
|
|
7
|
+
const constants_1 = require("./protocol/constants");
|
|
8
|
+
const value_parser_1 = require("./utils/value-parser");
|
|
9
|
+
const template_compiler_1 = require("./utils/template-compiler");
|
|
4
10
|
const transaction_1 = require("./transaction");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
11
|
+
const socket_connector_1 = require("./protocol/socket-connector");
|
|
12
|
+
const queue_1 = require("./queue");
|
|
13
|
+
const ErrConnectionDead = new Error("Connection is Dead");
|
|
14
|
+
class ConnectionQueryQueue extends queue_1.Queue {
|
|
15
|
+
rejectAllNext(error) {
|
|
16
|
+
while (!this.isFree) {
|
|
17
|
+
this.get().reject(error);
|
|
18
|
+
this.next();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.ConnectionQueryQueue = ConnectionQueryQueue;
|
|
8
23
|
/**
|
|
9
|
-
* Represents a single dedicated connection to the database.
|
|
10
|
-
*
|
|
24
|
+
* Represents a single dedicated connection to the PostgreSQL database.
|
|
25
|
+
*
|
|
26
|
+
* Supports:
|
|
27
|
+
* - Tagged template queries with automatic parameter binding
|
|
28
|
+
* - Prepared statements with caching
|
|
29
|
+
* - Transaction management with savepoints
|
|
30
|
+
* - Pipeline execution for concurrent queries
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const conn = await Connection.new({
|
|
35
|
+
* host: 'localhost',
|
|
36
|
+
* user: 'postgres',
|
|
37
|
+
* password: 'postgres',
|
|
38
|
+
* database: 'test'
|
|
39
|
+
* })
|
|
40
|
+
*
|
|
41
|
+
* // Simple query
|
|
42
|
+
* const users = await conn.query`SELECT * FROM users WHERE id = ${1}`
|
|
43
|
+
*
|
|
44
|
+
* // Transaction
|
|
45
|
+
* await conn.begin(async tx => {
|
|
46
|
+
* await tx.query`INSERT INTO users ...`
|
|
47
|
+
* })
|
|
48
|
+
*
|
|
49
|
+
* // Close connection
|
|
50
|
+
* conn.close()
|
|
51
|
+
* ```
|
|
11
52
|
*/
|
|
12
53
|
class Connection {
|
|
13
|
-
|
|
14
|
-
this.
|
|
15
|
-
this.enableLogs = enableLogs;
|
|
16
|
-
this.isReleased = false;
|
|
54
|
+
_nextStatement() {
|
|
55
|
+
return `s-${this._stmtCounter++}`;
|
|
17
56
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
57
|
+
constructor(socket, writer, logLevel) {
|
|
58
|
+
this._isFlushing = false;
|
|
59
|
+
this._isAlive = true;
|
|
60
|
+
this._queue = new ConnectionQueryQueue();
|
|
61
|
+
this._statementDescriptions = new Map();
|
|
62
|
+
this._statements = new Map();
|
|
63
|
+
this._parsePending = new Map();
|
|
64
|
+
this._stmtCounter = 0;
|
|
65
|
+
this._logLevel = logLevel;
|
|
66
|
+
this._socket = new socket_connector_1.SocketConnector(socket, (type, reader) => this._handlePacket(type, reader), error => this._handleError(error));
|
|
67
|
+
this._writer = writer;
|
|
23
68
|
}
|
|
24
69
|
/**
|
|
25
|
-
* Creates a
|
|
26
|
-
*
|
|
70
|
+
* Creates a new database connection.
|
|
71
|
+
*
|
|
72
|
+
* @param params - Connection parameters
|
|
73
|
+
* @returns A new Connection instance
|
|
74
|
+
* @throws {Error} If authentication fails or connection cannot be established
|
|
27
75
|
*
|
|
28
76
|
* @example
|
|
29
|
-
*
|
|
30
|
-
* const
|
|
77
|
+
* ```ts
|
|
78
|
+
* const conn = await Connection.new({
|
|
79
|
+
* host: 'localhost',
|
|
80
|
+
* port: 5432,
|
|
81
|
+
* user: 'postgres',
|
|
82
|
+
* password: 'secret',
|
|
83
|
+
* database: 'myapp'
|
|
84
|
+
* })
|
|
85
|
+
* ```
|
|
31
86
|
*/
|
|
32
|
-
async
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
return new
|
|
87
|
+
static async new(params) {
|
|
88
|
+
const writer = connection_request_writer_1.ConnectionRequestWriter.new();
|
|
89
|
+
const socket = await (0, socket_authorization_1.createAuthorizedSocket)(writer, params);
|
|
90
|
+
return new Connection(socket, writer, params.logLevel || 'error');
|
|
36
91
|
}
|
|
37
92
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
checkActive() {
|
|
48
|
-
if (this.isReleased) {
|
|
49
|
-
throw new Error("Connection has been released");
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Executes a tagged SQL query using structural caching.
|
|
54
|
-
* Supports recursive fragments and clauses.
|
|
93
|
+
* Executes a query using tagged template literals.
|
|
94
|
+
*
|
|
95
|
+
* Parameters are automatically bound to `$1, $2, ...` placeholders.
|
|
96
|
+
* Queries with parameters use prepared statements for performance.
|
|
97
|
+
*
|
|
98
|
+
* @param templates - Tagged template string with SQL
|
|
99
|
+
* @param args - Query parameters
|
|
100
|
+
* @returns Array of rows with proper typing
|
|
101
|
+
* @throws {Error} If connection is dead or query fails
|
|
55
102
|
*
|
|
56
103
|
* @example
|
|
57
|
-
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* // Simple query
|
|
106
|
+
* const users = await conn.query`SELECT * FROM users`
|
|
107
|
+
*
|
|
108
|
+
* // With parameters
|
|
109
|
+
* const user = await conn.query`SELECT * FROM users WHERE id = ${1}`
|
|
110
|
+
*
|
|
111
|
+
* // With typed result
|
|
112
|
+
* type User = { id: number, name: string }
|
|
113
|
+
* const users = await conn.query<User>`SELECT * FROM users`
|
|
114
|
+
* ```
|
|
58
115
|
*/
|
|
59
|
-
|
|
60
|
-
this.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
});
|
|
66
|
-
if (this.enableLogs) {
|
|
67
|
-
console.log(`\nQUERY: ${text}\n${args.length ? `ARGUMENTS: [${args}]\n` : ""}`);
|
|
116
|
+
query(templates, ...args) {
|
|
117
|
+
if (!this._isAlive)
|
|
118
|
+
throw ErrConnectionDead;
|
|
119
|
+
const query = (0, template_compiler_1.compileSqlTemplate)({ templates, args });
|
|
120
|
+
if (this._logLevel === 'query') {
|
|
121
|
+
console.log(`\nQUERY: ${query.text}\n${query.args.length !== 0 ? `ARGUMENTS: [${query.args}]\n` : ""}`);
|
|
68
122
|
}
|
|
69
|
-
|
|
70
|
-
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
this._registerFlush();
|
|
125
|
+
if (query.args.length === 0) {
|
|
126
|
+
this._writer.writeQuery(query.text);
|
|
127
|
+
this._queue.push({
|
|
128
|
+
resolve, reject, columns: [], rows: [], statementName: null, text: query.text
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
let rejectParsed = reject;
|
|
133
|
+
let statementName = '';
|
|
134
|
+
if (!this._statements.has(query.text) && !this._parsePending.has(query.text)) {
|
|
135
|
+
statementName = this._nextStatement();
|
|
136
|
+
this._parsePending.set(query.text, statementName);
|
|
137
|
+
rejectParsed = (error) => {
|
|
138
|
+
this._parsePending.delete(query.text);
|
|
139
|
+
reject(error);
|
|
140
|
+
};
|
|
141
|
+
this._writer
|
|
142
|
+
.writeParse(statementName, query.text);
|
|
143
|
+
console.log('parsed once', statementName, query.text);
|
|
144
|
+
}
|
|
145
|
+
statementName = this._statements.get(query.text) || this._parsePending.get(query.text);
|
|
146
|
+
if (!this._statementDescriptions.has(statementName)) {
|
|
147
|
+
this._writer.writeDescribe(statementName);
|
|
148
|
+
}
|
|
149
|
+
this._queue.push({
|
|
150
|
+
resolve, reject: rejectParsed, columns: [], rows: [], statementName: statementName, text: query.text
|
|
151
|
+
});
|
|
152
|
+
this._writer
|
|
153
|
+
.writeBind("", statementName, query.args)
|
|
154
|
+
.writeExecute("");
|
|
155
|
+
}
|
|
156
|
+
});
|
|
71
157
|
}
|
|
72
158
|
/**
|
|
73
159
|
* Starts a managed transaction on this connection.
|
|
74
|
-
*
|
|
160
|
+
*
|
|
161
|
+
* Automatically handles:
|
|
162
|
+
* - `BEGIN` before the callback
|
|
163
|
+
* - `COMMIT` on successful completion
|
|
164
|
+
* - `ROLLBACK` if an error is thrown
|
|
165
|
+
*
|
|
166
|
+
* @param txCallback - Async function that receives a `Transaction` instance
|
|
167
|
+
* @returns The value returned from the callback
|
|
168
|
+
* @throws {Error} If connection is dead or transaction fails
|
|
75
169
|
*
|
|
76
170
|
* @example
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
171
|
+
* ```ts
|
|
172
|
+
* const result = await conn.begin(async tx => {
|
|
173
|
+
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
174
|
+
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
175
|
+
* return { success: true }
|
|
176
|
+
* })
|
|
177
|
+
* ```
|
|
80
178
|
*/
|
|
81
|
-
async begin(
|
|
82
|
-
this.
|
|
179
|
+
async begin(txCallback) {
|
|
180
|
+
if (!this._isAlive)
|
|
181
|
+
throw ErrConnectionDead;
|
|
83
182
|
const tx = new transaction_1.Transaction(this);
|
|
84
183
|
try {
|
|
85
184
|
await tx.query `BEGIN`;
|
|
86
|
-
const result = await
|
|
185
|
+
const result = await txCallback(tx);
|
|
87
186
|
if (tx.isActive)
|
|
88
187
|
await tx.commit();
|
|
89
188
|
return result;
|
|
@@ -94,5 +193,137 @@ class Connection {
|
|
|
94
193
|
throw err;
|
|
95
194
|
}
|
|
96
195
|
}
|
|
196
|
+
_registerFlush() {
|
|
197
|
+
if (!this._isFlushing) {
|
|
198
|
+
this._isFlushing = true;
|
|
199
|
+
(0, process_1.nextTick)(() => this._flush());
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
_flush() {
|
|
203
|
+
if (!this._isAlive) {
|
|
204
|
+
this._queue.rejectAllNext(ErrConnectionDead);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
this._socket.write(this._writer.writeSync());
|
|
209
|
+
this._writer.clear();
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
this._isAlive = false;
|
|
213
|
+
this._socket.destroy();
|
|
214
|
+
this._queue.rejectAllNext(ErrConnectionDead);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
_handlePacket(type, reader) {
|
|
218
|
+
const context = this._queue.get();
|
|
219
|
+
switch (type) {
|
|
220
|
+
case constants_1.ResponseTypes.ParseComplete:
|
|
221
|
+
{
|
|
222
|
+
reader.readParseComplete();
|
|
223
|
+
this._statements.set(context.text, context.statementName);
|
|
224
|
+
this._parsePending.delete(context.text);
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
case constants_1.ResponseTypes.BindComplete:
|
|
228
|
+
{
|
|
229
|
+
reader.readBindComplete();
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
case constants_1.ResponseTypes.CloseComplete:
|
|
233
|
+
{
|
|
234
|
+
reader.readBindComplete();
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
case constants_1.ResponseTypes.ParameterDescription:
|
|
238
|
+
{
|
|
239
|
+
reader.readParameterDescription();
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
case constants_1.ResponseTypes.NoData:
|
|
243
|
+
{
|
|
244
|
+
reader.readNoData();
|
|
245
|
+
if (context.statementName) {
|
|
246
|
+
this._statementDescriptions.set(context.statementName, []);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
break;
|
|
250
|
+
case constants_1.ResponseTypes.RowDescription:
|
|
251
|
+
{
|
|
252
|
+
if (context.statementName) {
|
|
253
|
+
this._statementDescriptions.set(context.statementName, reader.readRowDescription());
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
context.columns = reader.readRowDescription();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
case constants_1.ResponseTypes.DataRow:
|
|
261
|
+
{
|
|
262
|
+
context.rows.push(reader.readDataRow());
|
|
263
|
+
}
|
|
264
|
+
break;
|
|
265
|
+
case constants_1.ResponseTypes.ComandComplete:
|
|
266
|
+
{
|
|
267
|
+
reader.readCommandComplete();
|
|
268
|
+
if (context.statementName) {
|
|
269
|
+
context.columns = this._statementDescriptions.get(context.statementName);
|
|
270
|
+
}
|
|
271
|
+
context.resolve((0, value_parser_1.parseRowValues)(context.columns, context.rows));
|
|
272
|
+
this._queue.next();
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
case constants_1.ResponseTypes.ErrorResponse:
|
|
276
|
+
{
|
|
277
|
+
const message = reader.readErrorResponse();
|
|
278
|
+
if (this._logLevel === 'error' || this._logLevel === 'notice' || this._logLevel === 'query') {
|
|
279
|
+
console.log(`\nError: ${message}\n`);
|
|
280
|
+
}
|
|
281
|
+
const error = new Error(message);
|
|
282
|
+
this._queue.rejectAllNext(error);
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
case constants_1.ResponseTypes.ReadyForQuery:
|
|
286
|
+
{
|
|
287
|
+
this._isFlushing = false;
|
|
288
|
+
reader.readReadyForQuery();
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
case constants_1.ResponseTypes.Notice:
|
|
292
|
+
{
|
|
293
|
+
const message = reader.readErrorResponse();
|
|
294
|
+
if (this._logLevel === 'notice' || this._logLevel === 'query') {
|
|
295
|
+
console.log(`\nError: ${message}\n`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
default: console.warn('Undeclared response type: ', type);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
_handleError(error) {
|
|
303
|
+
this._isAlive = false;
|
|
304
|
+
this._queue.rejectAllNext(error);
|
|
305
|
+
this._socket.destroy();
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Checks if the connection is still alive and usable.
|
|
309
|
+
* Returns `false` if the socket is destroyed or connection is dead.
|
|
310
|
+
*/
|
|
311
|
+
get isAlive() {
|
|
312
|
+
return this._isAlive && !this._socket.isDestroyed;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Closes the connection immediately.
|
|
316
|
+
* All pending queries will be rejected with an error.
|
|
317
|
+
* The connection cannot be used after this call.
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```ts
|
|
321
|
+
* conn.close()
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
close() {
|
|
325
|
+
this._isAlive = false;
|
|
326
|
+
this._socket.destroy();
|
|
327
|
+
}
|
|
97
328
|
}
|
|
98
329
|
exports.Connection = Connection;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import { Pool as PgtxPool } from "./pool";
|
|
2
|
-
import {
|
|
3
|
-
import { WhereClause } from "./clauses/where.clause";
|
|
4
|
-
import { InsertClause } from "./clauses/insert.clause";
|
|
5
|
-
import { UpdateClause } from "./clauses/update.clause";
|
|
6
|
-
import { ExcludeUpdateClause } from "./clauses/exclude.clause";
|
|
7
|
-
import { IdentifierClause } from "./clauses/iden.caluse";
|
|
8
|
-
import { LiteralClause } from "./clauses/literal.clause";
|
|
9
|
-
import { FragmentClause } from "./clauses/fragment.clause";
|
|
10
|
-
import { ArrayClause } from "./clauses/array.clause";
|
|
2
|
+
import { IdentifierClause, InsertClause, ArrayClause, UpdateClause, ExcludeUpdateClause, WhereClause, LiteralClause, FragmentClause } from './clauses';
|
|
11
3
|
import { Connection } from "./connection";
|
|
12
4
|
import { Transaction } from "./transaction";
|
|
13
5
|
/**
|
|
@@ -53,7 +45,7 @@ export declare const sql: {
|
|
|
53
45
|
* sql`SELECT * FROM users ${filters.length ? sql.fragment`WHERE ...` : sql.empty}`
|
|
54
46
|
* // Result: SELECT * FROM users
|
|
55
47
|
*/
|
|
56
|
-
empty: EmptyClause;
|
|
48
|
+
empty: import("./clauses").EmptyClause;
|
|
57
49
|
/**
|
|
58
50
|
* Generates a list of conditions for a WHERE clause from a JavaScript object.
|
|
59
51
|
* Works similarly to sql.update, but uses ' AND ' as a separator instead of a comma.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACX,aAAa,EACb,cAAc,EACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,GAAG;IACZ;;;;;;;;;;;OAWG;;IAGH;;;;;;OAMG;;IAGH;;;;;;OAMG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;KAWC;;IAGD;;;;;;;;;;OAUG;;IAGH;;;;;;;OAOG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;;;;;;;;;OAmBG;;CAEN,CAAA;AAGD;;;GAGG;AAEH,OAAO,EAAE,UAAU,IAAI,UAAU,EAAE,CAAA;AAEnC,OAAO,EAAE,WAAW,IAAI,WAAW,EAAE,CAAA;AAErC,OAAO,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAA"}
|