postgrejs 2.12.0 → 2.15.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/CHANGELOG.md +231 -191
- package/README.md +112 -96
- package/cjs/connection/connection.js +10 -5
- package/cjs/connection/cursor.js +2 -4
- package/cjs/connection/intl-connection.js +19 -12
- package/cjs/connection/pool.js +12 -6
- package/cjs/connection/prepared-statement.js +6 -3
- package/cjs/data-types/bytea-type.js +2 -4
- package/cjs/data-types/numeric-type.js +2 -2
- package/cjs/data-types/time-type.js +2 -1
- package/cjs/data-types/timestamp-type.js +2 -1
- package/cjs/data-types/timestamptz-type.js +2 -1
- package/cjs/index.js +26 -39
- package/cjs/protocol/frontend.js +8 -5
- package/cjs/protocol/pg-socket.js +33 -31
- package/cjs/protocol/sasl.js +14 -14
- package/cjs/protocol/smart-buffer.js +2 -24
- package/cjs/util/array-calculatedim.js +1 -2
- package/cjs/util/bigint-methods.js +2 -3
- package/cjs/util/config-from-env.js +1 -2
- package/cjs/util/connection-config.js +8 -11
- package/cjs/util/convert-row-to-object.js +1 -2
- package/cjs/util/decode-binaryarray.js +1 -2
- package/cjs/util/encode-binaryarray.js +1 -2
- package/cjs/util/escape-literal.js +1 -2
- package/cjs/util/fast-parseint.js +1 -2
- package/cjs/util/get-parsers.js +1 -2
- package/cjs/util/parse-array.js +1 -2
- package/cjs/util/parse-datetime.js +1 -2
- package/cjs/util/parse-row.js +1 -2
- package/cjs/util/parse-time.js +2 -2
- package/cjs/util/stringify-arrayliteral.js +1 -2
- package/cjs/util/stringify-for-sql.js +2 -3
- package/cjs/util/wrap-row-description.js +1 -2
- package/esm/connection/connection.js +10 -5
- package/esm/connection/intl-connection.js +17 -10
- package/esm/connection/pool.js +12 -6
- package/esm/connection/prepared-statement.js +6 -3
- package/esm/data-types/time-type.js +2 -1
- package/esm/data-types/timestamp-type.js +2 -1
- package/esm/data-types/timestamptz-type.js +2 -1
- package/esm/index.js +5 -5
- package/esm/protocol/frontend.js +8 -5
- package/esm/protocol/pg-socket.js +28 -24
- package/esm/protocol/sasl.js +12 -10
- package/esm/util/connection-config.js +4 -4
- package/package.json +5 -5
- package/typings/connection/connection.d.ts +0 -1
- package/typings/connection/cursor.d.ts +0 -1
- package/typings/connection/prepared-statement.d.ts +0 -1
- package/typings/index.d.ts +5 -5
- package/typings/interfaces/database-connection-params.d.ts +1 -1
- package/typings/protocol/backend.d.ts +0 -1
- package/typings/protocol/buffer-reader.d.ts +0 -1
- package/typings/protocol/frontend.d.ts +0 -1
- package/typings/protocol/pg-socket.d.ts +0 -1
- package/typings/protocol/protocol.d.ts +0 -1
- package/typings/protocol/smart-buffer.d.ts +0 -1
- package/typings/safe-event-emitter.d.ts +0 -1
- package/typings/types.d.ts +0 -1
- package/typings/util/bigint-methods.d.ts +0 -1
- package/typings/util/decode-binaryarray.d.ts +0 -1
|
@@ -83,34 +83,37 @@ export class Connection extends SafeEventEmitter {
|
|
|
83
83
|
if (this.state === ConnectionState.CLOSED || this._closing)
|
|
84
84
|
return;
|
|
85
85
|
/* istanbul ignore next */
|
|
86
|
-
if (this.listenerCount('debug'))
|
|
86
|
+
if (this.listenerCount('debug')) {
|
|
87
87
|
this.emit('debug', {
|
|
88
88
|
location: 'Connection.close',
|
|
89
89
|
connection: this,
|
|
90
90
|
message: `[${this.processID}] closing`,
|
|
91
91
|
});
|
|
92
|
+
}
|
|
92
93
|
this._closing = true;
|
|
93
94
|
if (this._intlCon.refCount > 0 && typeof terminateWait === 'number' && terminateWait > 0) {
|
|
94
95
|
const startTime = Date.now();
|
|
95
96
|
return this._captureErrorStack(new Promise((resolve, reject) => {
|
|
96
97
|
/* istanbul ignore next */
|
|
97
|
-
if (this.listenerCount('debug'))
|
|
98
|
+
if (this.listenerCount('debug')) {
|
|
98
99
|
this.emit('debug', {
|
|
99
100
|
location: 'Connection.close',
|
|
100
101
|
connection: this,
|
|
101
102
|
message: `[${this.processID}] waiting active queries`,
|
|
102
103
|
});
|
|
104
|
+
}
|
|
103
105
|
const timer = setInterval(() => {
|
|
104
106
|
if (this._intlCon.refCount <= 0 || Date.now() > startTime + terminateWait) {
|
|
105
107
|
clearInterval(timer);
|
|
106
108
|
if (this._intlCon.refCount > 0) {
|
|
107
109
|
/* istanbul ignore next */
|
|
108
|
-
if (this.listenerCount('debug'))
|
|
110
|
+
if (this.listenerCount('debug')) {
|
|
109
111
|
this.emit('debug', {
|
|
110
112
|
location: 'Connection.close',
|
|
111
113
|
connection: this,
|
|
112
114
|
message: `[${this.processID}] terminate`,
|
|
113
115
|
});
|
|
116
|
+
}
|
|
114
117
|
this.emit('terminate');
|
|
115
118
|
}
|
|
116
119
|
this._close().then(resolve).catch(reject);
|
|
@@ -134,13 +137,14 @@ export class Connection extends SafeEventEmitter {
|
|
|
134
137
|
async query(sql, options) {
|
|
135
138
|
this._intlCon.assertConnected();
|
|
136
139
|
/* istanbul ignore next */
|
|
137
|
-
if (this.listenerCount('debug'))
|
|
140
|
+
if (this.listenerCount('debug')) {
|
|
138
141
|
this.emit('debug', {
|
|
139
142
|
location: 'Connection.query',
|
|
140
143
|
connection: this,
|
|
141
144
|
message: `[${this.processID}] query | ${sql}`,
|
|
142
145
|
sql,
|
|
143
146
|
});
|
|
147
|
+
}
|
|
144
148
|
const typeMap = options?.typeMap || GlobalTypeMap;
|
|
145
149
|
const paramTypes = options?.params?.map(prm => prm instanceof BindParam ? prm.oid : typeMap.determine(prm));
|
|
146
150
|
const statement = await this.prepare(sql, { paramTypes, typeMap }).catch((e) => {
|
|
@@ -161,13 +165,14 @@ export class Connection extends SafeEventEmitter {
|
|
|
161
165
|
*/
|
|
162
166
|
async prepare(sql, options) {
|
|
163
167
|
/* istanbul ignore next */
|
|
164
|
-
if (this.listenerCount('debug'))
|
|
168
|
+
if (this.listenerCount('debug')) {
|
|
165
169
|
this.emit('debug', {
|
|
166
170
|
location: 'Connection.prepare',
|
|
167
171
|
connection: this,
|
|
168
172
|
message: `[${this.processID}] prepare | ${sql}`,
|
|
169
173
|
sql,
|
|
170
174
|
});
|
|
175
|
+
}
|
|
171
176
|
return await this._captureErrorStack(PreparedStatement.prepare(this, sql, options));
|
|
172
177
|
}
|
|
173
178
|
/**
|
|
@@ -109,8 +109,9 @@ export class IntlConnection extends SafeEventEmitter {
|
|
|
109
109
|
const result = await this._execute(sql, options, cb);
|
|
110
110
|
if (commitLast)
|
|
111
111
|
await this._execute('COMMIT');
|
|
112
|
-
else if (this.inTransaction && rollbackOnError)
|
|
112
|
+
else if (this.inTransaction && rollbackOnError) {
|
|
113
113
|
await this._execute('RELEASE ' + this._onErrorSavePoint + ';');
|
|
114
|
+
}
|
|
114
115
|
return result;
|
|
115
116
|
}
|
|
116
117
|
catch (e) {
|
|
@@ -191,20 +192,23 @@ export class IntlConnection extends SafeEventEmitter {
|
|
|
191
192
|
current.rows = [];
|
|
192
193
|
break;
|
|
193
194
|
case Protocol.BackendMessageCode.DataRow:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
cb
|
|
200
|
-
|
|
201
|
-
|
|
195
|
+
{
|
|
196
|
+
let row = msg.columns.map((x) => x.toString('utf8'));
|
|
197
|
+
parseRow(parsers, row, opts);
|
|
198
|
+
if (opts.objectRows && current.fields)
|
|
199
|
+
row = convertRowToObject(current.fields, row);
|
|
200
|
+
if (cb)
|
|
201
|
+
cb('row', row);
|
|
202
|
+
current.rows = current.rows || [];
|
|
203
|
+
current.rows.push(row);
|
|
204
|
+
}
|
|
202
205
|
break;
|
|
203
206
|
case Protocol.BackendMessageCode.CommandComplete:
|
|
204
207
|
// Ignore BEGIN command that we added to sql
|
|
205
208
|
current.command = msg.command;
|
|
206
|
-
if (current.command === 'DELETE' || current.command === 'INSERT' || current.command === 'UPDATE')
|
|
209
|
+
if (current.command === 'DELETE' || current.command === 'INSERT' || current.command === 'UPDATE') {
|
|
207
210
|
current.rowsAffected = msg.rowCount;
|
|
211
|
+
}
|
|
208
212
|
current.executeTime = Date.now() - currentStart;
|
|
209
213
|
if (current.rows)
|
|
210
214
|
current.rowType = opts.objectRows && current.fields ? 'object' : 'array';
|
|
@@ -220,6 +224,9 @@ export class IntlConnection extends SafeEventEmitter {
|
|
|
220
224
|
// Ignore COMMIT command that we added to sql
|
|
221
225
|
result.totalCommands = result.results.length;
|
|
222
226
|
done(undefined, result);
|
|
227
|
+
break;
|
|
228
|
+
default:
|
|
229
|
+
break;
|
|
223
230
|
}
|
|
224
231
|
});
|
|
225
232
|
}
|
package/esm/connection/pool.js
CHANGED
|
@@ -25,42 +25,46 @@ export class Pool extends SafeEventEmitter {
|
|
|
25
25
|
const poolFactory = {
|
|
26
26
|
create: async () => {
|
|
27
27
|
/* istanbul ignore next */
|
|
28
|
-
if (this.listenerCount('debug'))
|
|
28
|
+
if (this.listenerCount('debug')) {
|
|
29
29
|
this.emit('debug', {
|
|
30
30
|
location: 'Pool.factory.create',
|
|
31
31
|
pool: this,
|
|
32
32
|
message: `new connection creating`,
|
|
33
33
|
});
|
|
34
|
+
}
|
|
34
35
|
const intlCon = new IntlConnection(cfg);
|
|
35
36
|
await intlCon.connect();
|
|
36
37
|
intlCon.on('close', () => this._pool.destroy(intlCon));
|
|
37
38
|
/* istanbul ignore next */
|
|
38
|
-
if (this.listenerCount('debug'))
|
|
39
|
+
if (this.listenerCount('debug')) {
|
|
39
40
|
this.emit('debug', {
|
|
40
41
|
location: 'Pool.factory.create',
|
|
41
42
|
pool: this,
|
|
42
43
|
message: `[${intlCon.processID}] connection created`,
|
|
43
44
|
});
|
|
45
|
+
}
|
|
44
46
|
return intlCon;
|
|
45
47
|
},
|
|
46
48
|
destroy: intlCon => {
|
|
47
49
|
/* istanbul ignore next */
|
|
48
|
-
if (this.listenerCount('debug'))
|
|
50
|
+
if (this.listenerCount('debug')) {
|
|
49
51
|
this.emit('debug', {
|
|
50
52
|
location: 'Pool.factory.destroy',
|
|
51
53
|
pool: this,
|
|
52
54
|
message: `[${intlCon.processID}] connection destroy`,
|
|
53
55
|
});
|
|
56
|
+
}
|
|
54
57
|
return intlCon.close();
|
|
55
58
|
},
|
|
56
59
|
reset: async (intlCon) => {
|
|
57
60
|
/* istanbul ignore next */
|
|
58
|
-
if (this.listenerCount('debug'))
|
|
61
|
+
if (this.listenerCount('debug')) {
|
|
59
62
|
this.emit('debug', {
|
|
60
63
|
location: 'Pool.factory.reset',
|
|
61
64
|
pool: this,
|
|
62
65
|
message: `[${intlCon.processID}] connection reset`,
|
|
63
66
|
});
|
|
67
|
+
}
|
|
64
68
|
try {
|
|
65
69
|
if (intlCon.state === ConnectionState.READY) {
|
|
66
70
|
await intlCon.execute('ROLLBACK;UNLISTEN *');
|
|
@@ -74,12 +78,13 @@ export class Pool extends SafeEventEmitter {
|
|
|
74
78
|
},
|
|
75
79
|
validate: async (intlCon) => {
|
|
76
80
|
/* istanbul ignore next */
|
|
77
|
-
if (this.listenerCount('debug'))
|
|
81
|
+
if (this.listenerCount('debug')) {
|
|
78
82
|
this.emit('debug', {
|
|
79
83
|
location: 'Pool.factory.validate',
|
|
80
84
|
pool: this,
|
|
81
85
|
message: `[${intlCon.processID}] connection validate`,
|
|
82
86
|
});
|
|
87
|
+
}
|
|
83
88
|
if (intlCon.state !== ConnectionState.READY)
|
|
84
89
|
throw new Error('Connection is not active');
|
|
85
90
|
await intlCon.execute('select 1;');
|
|
@@ -116,12 +121,13 @@ export class Pool extends SafeEventEmitter {
|
|
|
116
121
|
async acquire() {
|
|
117
122
|
const intlCon = await this._pool.acquire();
|
|
118
123
|
/* istanbul ignore next */
|
|
119
|
-
if (this.listenerCount('debug'))
|
|
124
|
+
if (this.listenerCount('debug')) {
|
|
120
125
|
this.emit('debug', {
|
|
121
126
|
location: 'Pool.acquire',
|
|
122
127
|
pool: this,
|
|
123
128
|
message: `[${intlCon.processID}] acquired`,
|
|
124
129
|
});
|
|
130
|
+
}
|
|
125
131
|
const connection = new Connection(this, intlCon);
|
|
126
132
|
/* istanbul ignore next */
|
|
127
133
|
if (this.listenerCount('debug'))
|
|
@@ -100,13 +100,15 @@ export class PreparedStatement extends SafeEventEmitter {
|
|
|
100
100
|
const result = await intlCon.statementQueue.enqueue(() => this._execute(options)).toPromise();
|
|
101
101
|
if (commitLast)
|
|
102
102
|
await intlCon.execute('COMMIT');
|
|
103
|
-
else if (intlCon.inTransaction && rollbackOnError)
|
|
103
|
+
else if (intlCon.inTransaction && rollbackOnError) {
|
|
104
104
|
await intlCon.execute('RELEASE ' + this._onErrorSavePoint + ';');
|
|
105
|
+
}
|
|
105
106
|
return result;
|
|
106
107
|
}
|
|
107
108
|
catch (e) {
|
|
108
|
-
if (intlCon.inTransaction && rollbackOnError)
|
|
109
|
+
if (intlCon.inTransaction && rollbackOnError) {
|
|
109
110
|
await intlCon.execute('ROLLBACK TO ' + this._onErrorSavePoint + ';');
|
|
111
|
+
}
|
|
110
112
|
throw e;
|
|
111
113
|
}
|
|
112
114
|
}
|
|
@@ -166,8 +168,9 @@ export class PreparedStatement extends SafeEventEmitter {
|
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
|
-
if (result.command === 'DELETE' || result.command === 'INSERT' || result.command === 'UPDATE')
|
|
171
|
+
if (result.command === 'DELETE' || result.command === 'INSERT' || result.command === 'UPDATE') {
|
|
170
172
|
result.rowsAffected = executeResult.rowCount;
|
|
173
|
+
}
|
|
171
174
|
result.executeTime = Date.now() - startTime;
|
|
172
175
|
return result;
|
|
173
176
|
}
|
|
@@ -10,8 +10,9 @@ export const TimeType = {
|
|
|
10
10
|
const hi = v.readInt32BE();
|
|
11
11
|
const lo = v.readUInt32BE(4);
|
|
12
12
|
let d = new Date((lo + hi * timeMul) / 1000);
|
|
13
|
-
if (fetchAsString || !options.utcDates)
|
|
13
|
+
if (fetchAsString || !options.utcDates) {
|
|
14
14
|
d = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
|
|
15
|
+
}
|
|
15
16
|
return fetchAsString ? dateToTimeString(d) : d;
|
|
16
17
|
},
|
|
17
18
|
encodeBinary(buf, v, options) {
|
|
@@ -16,8 +16,9 @@ export const TimestampType = {
|
|
|
16
16
|
return fetchAsString ? '-infinity' : -Infinity;
|
|
17
17
|
// Shift from 2000 to 1970
|
|
18
18
|
let d = new Date((lo + hi * timeMul) / 1000 + timeShift);
|
|
19
|
-
if (fetchAsString || !options.utcDates)
|
|
19
|
+
if (fetchAsString || !options.utcDates) {
|
|
20
20
|
d = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
|
|
21
|
+
}
|
|
21
22
|
return fetchAsString ? dateToTimestampString(d) : d;
|
|
22
23
|
},
|
|
23
24
|
encodeBinary(buf, v, options) {
|
|
@@ -16,8 +16,9 @@ export const TimestamptzType = {
|
|
|
16
16
|
return fetchAsString ? '-infinity' : -Infinity;
|
|
17
17
|
// Shift from 2000 to 1970
|
|
18
18
|
let d = new Date((lo + hi * timeMul) / 1000 + timeShift);
|
|
19
|
-
if (fetchAsString || !options.utcDates)
|
|
19
|
+
if (fetchAsString || !options.utcDates) {
|
|
20
20
|
d = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
|
|
21
|
+
}
|
|
21
22
|
return fetchAsString ? dateToTimestamptzString(d) : d;
|
|
22
23
|
},
|
|
23
24
|
encodeBinary(buf, v, options) {
|
package/esm/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
export * from './constants.js';
|
|
2
|
-
export * from './data-type-map.js';
|
|
3
|
-
export * from './types.js';
|
|
4
1
|
export * from './connection/bind-param.js';
|
|
5
2
|
export * from './connection/connection.js';
|
|
6
3
|
export * from './connection/cursor.js';
|
|
7
4
|
export * from './connection/pool.js';
|
|
8
5
|
export * from './connection/prepared-statement.js';
|
|
6
|
+
export * from './constants.js';
|
|
7
|
+
export * from './data-type-map.js';
|
|
9
8
|
export * from './interfaces/command-result.js';
|
|
10
9
|
export * from './interfaces/data-mapping-options.js';
|
|
11
10
|
export * from './interfaces/data-type.js';
|
|
@@ -16,10 +15,11 @@ export * from './interfaces/query-result.js';
|
|
|
16
15
|
export * from './interfaces/script-execute-options.js';
|
|
17
16
|
export * from './interfaces/script-result.js';
|
|
18
17
|
export * from './interfaces/statement-prepare-options.js';
|
|
18
|
+
export * from './protocol/database-error.js';
|
|
19
|
+
export * from './protocol/smart-buffer.js';
|
|
20
|
+
export * from './types.js';
|
|
19
21
|
export * from './util/connection-config.js';
|
|
20
22
|
export * from './util/escape-literal.js';
|
|
21
23
|
export * from './util/parse-datetime.js';
|
|
22
24
|
export * from './util/stringify-arrayliteral.js';
|
|
23
25
|
export * from './util/stringify-for-sql.js';
|
|
24
|
-
export * from './protocol/smart-buffer.js';
|
|
25
|
-
export * from './protocol/database-error.js';
|
package/esm/protocol/frontend.js
CHANGED
|
@@ -158,8 +158,9 @@ export class Frontend {
|
|
|
158
158
|
return setLengthAndFlush(io, 1);
|
|
159
159
|
}
|
|
160
160
|
getDescribeMessage(args) {
|
|
161
|
-
if (args.name && args.name.length > 63)
|
|
162
|
-
throw new Error(args.type === 'P' ? 'Portal' : 'Statement
|
|
161
|
+
if (args.name && args.name.length > 63) {
|
|
162
|
+
throw new Error(args.type === 'P' ? 'Portal' : 'Statement name length must be lower than 63');
|
|
163
|
+
}
|
|
163
164
|
const io = this._io
|
|
164
165
|
.start()
|
|
165
166
|
.writeInt8(Protocol.FrontendMessageCode.Describe)
|
|
@@ -169,8 +170,9 @@ export class Frontend {
|
|
|
169
170
|
return setLengthAndFlush(io, 1);
|
|
170
171
|
}
|
|
171
172
|
getExecuteMessage(args) {
|
|
172
|
-
if (args.fetchCount && (args.fetchCount < 0 || args.fetchCount > 4294967295))
|
|
173
|
+
if (args.fetchCount && (args.fetchCount < 0 || args.fetchCount > 4294967295)) {
|
|
173
174
|
throw new Error('fetchCount can be between 0 and 4294967295');
|
|
175
|
+
}
|
|
174
176
|
const io = this._io
|
|
175
177
|
.start()
|
|
176
178
|
.writeInt8(Protocol.FrontendMessageCode.Execute)
|
|
@@ -180,8 +182,9 @@ export class Frontend {
|
|
|
180
182
|
return setLengthAndFlush(io, 1);
|
|
181
183
|
}
|
|
182
184
|
getCloseMessage(args) {
|
|
183
|
-
if (args.name && args.name.length > 63)
|
|
184
|
-
throw new Error(args.type === 'P' ? 'Portal' : 'Statement
|
|
185
|
+
if (args.name && args.name.length > 63) {
|
|
186
|
+
throw new Error(args.type === 'P' ? 'Portal' : 'Statement name length must be lower than 63');
|
|
187
|
+
}
|
|
185
188
|
const io = this._io
|
|
186
189
|
.start()
|
|
187
190
|
.writeInt8(Protocol.FrontendMessageCode.Close)
|
|
@@ -53,30 +53,31 @@ export class PgSocket extends SafeEventEmitter {
|
|
|
53
53
|
socket.setTimeout(0);
|
|
54
54
|
if (this.options.keepAlive || this.options.keepAlive == null)
|
|
55
55
|
socket.setKeepAlive(true);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (
|
|
56
|
+
socket.write(this._frontend.getSSLRequestMessage());
|
|
57
|
+
socket.once('data', x => {
|
|
58
|
+
this._removeListeners();
|
|
59
|
+
if (x.toString() === 'S') {
|
|
60
|
+
const tslOptions = { ...options.ssl, socket };
|
|
61
|
+
if (options.host && net.isIP(options.host) === 0)
|
|
62
|
+
tslOptions.servername = options.host;
|
|
63
|
+
const tlsSocket = (this._socket = tls.connect(tslOptions));
|
|
64
|
+
tlsSocket.once('error', errorHandler);
|
|
65
|
+
tlsSocket.once('secureConnect', () => {
|
|
66
|
+
this._removeListeners();
|
|
67
|
+
this._handleConnect();
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (x.toString() === 'N') {
|
|
72
|
+
if (options.requireSSL) {
|
|
73
73
|
return errorHandler(new Error('Server does not support SSL connections'));
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
}
|
|
75
|
+
this._removeListeners();
|
|
76
|
+
this._handleConnect();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
return errorHandler(new Error('There was an error establishing an SSL connection'));
|
|
80
|
+
});
|
|
80
81
|
};
|
|
81
82
|
socket.setNoDelay(true);
|
|
82
83
|
socket.setTimeout(options.connectTimeoutMs || 30000, () => errorHandler(new Error('Connection timed out')));
|
|
@@ -283,8 +284,9 @@ export class PgSocket extends SafeEventEmitter {
|
|
|
283
284
|
});
|
|
284
285
|
break;
|
|
285
286
|
case Protocol.AuthenticationMessageKind.SASL: {
|
|
286
|
-
if (!msg.mechanisms.includes('SCRAM-SHA-256'))
|
|
287
|
+
if (!msg.mechanisms.includes('SCRAM-SHA-256')) {
|
|
287
288
|
throw new Error('SASL: Only mechanism SCRAM-SHA-256 is currently supported');
|
|
289
|
+
}
|
|
288
290
|
const saslSession = (this._saslSession = SASL.createSession(this.options.user || '', 'SCRAM-SHA-256'));
|
|
289
291
|
this._send(this._frontend.getSASLMessage(saslSession));
|
|
290
292
|
break;
|
|
@@ -308,6 +310,8 @@ export class PgSocket extends SafeEventEmitter {
|
|
|
308
310
|
this._saslSession = undefined;
|
|
309
311
|
break;
|
|
310
312
|
}
|
|
313
|
+
default:
|
|
314
|
+
break;
|
|
311
315
|
}
|
|
312
316
|
}
|
|
313
317
|
_handleParameterStatus(msg) {
|
package/esm/protocol/sasl.js
CHANGED
|
@@ -33,6 +33,8 @@ export var SASL;
|
|
|
33
33
|
case 'i':
|
|
34
34
|
iteration = parseInt(i.substring(2), 10);
|
|
35
35
|
break;
|
|
36
|
+
default:
|
|
37
|
+
break;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
if (!nonce)
|
|
@@ -69,25 +71,25 @@ export var SASL;
|
|
|
69
71
|
throw new Error('SASL: Server signature does not match');
|
|
70
72
|
}
|
|
71
73
|
SASL.finalizeSession = finalizeSession;
|
|
72
|
-
function
|
|
74
|
+
const firstMessageBare = function (username, nonce) {
|
|
73
75
|
return `n=${username},r=${nonce}`;
|
|
74
|
-
}
|
|
76
|
+
};
|
|
75
77
|
/**
|
|
76
78
|
* Hi() is, essentially, PBKDF2 [RFC2898] with HMAC() as the
|
|
77
79
|
* pseudorandom function (PRF) and with dkLen == output length of
|
|
78
80
|
* HMAC() == output length of H()
|
|
79
81
|
*/
|
|
80
|
-
function
|
|
82
|
+
const hi = function (text, salt, iterations) {
|
|
81
83
|
return crypto.pbkdf2Sync(text, Buffer.from(salt, 'base64'), iterations, 32, 'sha256');
|
|
82
|
-
}
|
|
84
|
+
};
|
|
83
85
|
const encode64 = str => Buffer.from(str).toString('base64');
|
|
84
|
-
function
|
|
86
|
+
const hmac = function (key, msg) {
|
|
85
87
|
return crypto.createHmac('sha256', key).update(msg).digest();
|
|
86
|
-
}
|
|
87
|
-
function
|
|
88
|
+
};
|
|
89
|
+
const hash = function (data) {
|
|
88
90
|
return crypto.createHash('sha256').update(data).digest();
|
|
89
|
-
}
|
|
90
|
-
function
|
|
91
|
+
};
|
|
92
|
+
const xor = function (a, b) {
|
|
91
93
|
a = Buffer.isBuffer(a) ? a : Buffer.from(a);
|
|
92
94
|
b = Buffer.isBuffer(b) ? b : Buffer.from(b);
|
|
93
95
|
if (a.length !== b.length)
|
|
@@ -98,5 +100,5 @@ export var SASL;
|
|
|
98
100
|
out[i] = a[i] ^ b[i];
|
|
99
101
|
}
|
|
100
102
|
return out;
|
|
101
|
-
}
|
|
103
|
+
};
|
|
102
104
|
})(SASL || (SASL = {}));
|
|
@@ -23,9 +23,7 @@ export function parseConnectionString(str) {
|
|
|
23
23
|
if (!str.includes('://'))
|
|
24
24
|
str = 'postgres://' + str;
|
|
25
25
|
const parsed = new URL(str);
|
|
26
|
-
const getFirst = (v) =>
|
|
27
|
-
return typeof v === 'string' ? v : Array.isArray(v) ? v[0] : '';
|
|
28
|
-
};
|
|
26
|
+
const getFirst = (v) => (typeof v === 'string' ? v : Array.isArray(v) ? v[0] : '');
|
|
29
27
|
const cfg = {};
|
|
30
28
|
cfg.host = decodeURI(parsed.hostname || '');
|
|
31
29
|
if (parsed.port)
|
|
@@ -47,11 +45,13 @@ export function parseConnectionString(str) {
|
|
|
47
45
|
cfg.database = decodeURI(getFirst(parsed.searchParams.get('db')));
|
|
48
46
|
if (parsed.searchParams.get('schema'))
|
|
49
47
|
cfg.schema = decodeURI(getFirst(parsed.searchParams.get('schema')));
|
|
50
|
-
if (parsed.searchParams.get('application_name'))
|
|
48
|
+
if (parsed.searchParams.get('application_name')) {
|
|
51
49
|
cfg.applicationName = decodeURI(getFirst(parsed.searchParams.get('application_name')));
|
|
50
|
+
}
|
|
52
51
|
if (parsed.username)
|
|
53
52
|
cfg.user = parsed.username;
|
|
54
53
|
if (parsed.password)
|
|
55
54
|
cfg.password = parsed.password;
|
|
55
|
+
cfg.requireSSL = parsed.searchParams.get('sslmode') === 'require';
|
|
56
56
|
return cfg;
|
|
57
57
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postgrejs",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "2.
|
|
3
|
+
"description": "Professional PostgreSQL client NodeJS",
|
|
4
|
+
"version": "2.15.1",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Eray Hanoglu <e.hanoglu@panates.com>"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/panates/
|
|
12
|
+
"url": "https://github.com/panates/postgrejs.git"
|
|
13
13
|
},
|
|
14
14
|
"type": "module",
|
|
15
15
|
"main": "./cjs/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"doublylinked": "^2.5.4",
|
|
20
20
|
"lightning-pool": "^4.2.2",
|
|
21
21
|
"postgres-bytea": "^3.0.0",
|
|
22
|
-
"power-tasks": "^1.7.
|
|
22
|
+
"power-tasks": "^1.7.4",
|
|
23
23
|
"putil-merge": "^3.12.1",
|
|
24
24
|
"putil-promisify": "^1.10.1",
|
|
25
25
|
"putil-varhelpers": "^1.6.5"
|
|
@@ -51,4 +51,4 @@
|
|
|
51
51
|
"ts",
|
|
52
52
|
"esm"
|
|
53
53
|
]
|
|
54
|
-
}
|
|
54
|
+
}
|
package/typings/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
export * from './constants.js';
|
|
2
|
-
export * from './data-type-map.js';
|
|
3
|
-
export * from './types.js';
|
|
4
1
|
export * from './connection/bind-param.js';
|
|
5
2
|
export * from './connection/connection.js';
|
|
6
3
|
export * from './connection/cursor.js';
|
|
7
4
|
export * from './connection/pool.js';
|
|
8
5
|
export * from './connection/prepared-statement.js';
|
|
6
|
+
export * from './constants.js';
|
|
7
|
+
export * from './data-type-map.js';
|
|
9
8
|
export * from './interfaces/command-result.js';
|
|
10
9
|
export * from './interfaces/data-mapping-options.js';
|
|
11
10
|
export * from './interfaces/data-type.js';
|
|
@@ -16,10 +15,11 @@ export * from './interfaces/query-result.js';
|
|
|
16
15
|
export * from './interfaces/script-execute-options.js';
|
|
17
16
|
export * from './interfaces/script-result.js';
|
|
18
17
|
export * from './interfaces/statement-prepare-options.js';
|
|
18
|
+
export * from './protocol/database-error.js';
|
|
19
|
+
export * from './protocol/smart-buffer.js';
|
|
20
|
+
export * from './types.js';
|
|
19
21
|
export * from './util/connection-config.js';
|
|
20
22
|
export * from './util/escape-literal.js';
|
|
21
23
|
export * from './util/parse-datetime.js';
|
|
22
24
|
export * from './util/stringify-arrayliteral.js';
|
|
23
25
|
export * from './util/stringify-for-sql.js';
|
|
24
|
-
export * from './protocol/smart-buffer.js';
|
|
25
|
-
export * from './protocol/database-error.js';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import type { PoolConfiguration as LPoolConfiguration } from 'lightning-pool';
|
|
3
2
|
import type { ConnectionOptions as TlsConnectionOptions } from 'tls';
|
|
4
3
|
import type { SmartBufferConfig } from '../protocol/smart-buffer.js';
|
|
@@ -10,6 +9,7 @@ export interface DatabaseConnectionParams {
|
|
|
10
9
|
password?: string | (() => string | Promise<string>);
|
|
11
10
|
database?: string;
|
|
12
11
|
applicationName?: string;
|
|
12
|
+
requireSSL?: boolean;
|
|
13
13
|
ssl?: TlsConnectionOptions;
|
|
14
14
|
timezone?: string;
|
|
15
15
|
schema?: string;
|
package/typings/types.d.ts
CHANGED