@pi-r/postgres 0.7.3 → 0.8.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/client/index.js +58 -80
- package/client/pool.d.ts +9 -0
- package/client/pool.js +55 -0
- package/package.json +3 -3
- package/types/index.d.ts +3 -1
package/client/index.js
CHANGED
|
@@ -1,52 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT =
|
|
2
|
+
exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT = void 0;
|
|
3
|
+
exports.setAuthentication = setAuthentication;
|
|
4
|
+
exports.setCredential = setCredential;
|
|
5
|
+
exports.executeQuery = executeQuery;
|
|
6
|
+
exports.executeBatchQuery = executeBatchQuery;
|
|
7
|
+
exports.checkTimeout = checkTimeout;
|
|
3
8
|
const postgres = require("pg");
|
|
4
9
|
const connectionString = require("pg-connection-string");
|
|
10
|
+
const QueryStream = require("pg-query-stream");
|
|
11
|
+
const Db = require("@e-mc/db");
|
|
5
12
|
const util_1 = require("@e-mc/db/util");
|
|
6
13
|
const types_1 = require("@e-mc/types");
|
|
7
|
-
const
|
|
8
|
-
const QueryStream = require("pg-query-stream");
|
|
9
|
-
const DbPool = require('@e-mc/db/pool');
|
|
10
|
-
class PostgresPool extends DbPool {
|
|
11
|
-
async getConnection() {
|
|
12
|
-
return this.client.connect();
|
|
13
|
-
}
|
|
14
|
-
async close() {
|
|
15
|
-
return this.client.end();
|
|
16
|
-
}
|
|
17
|
-
isEmpty() {
|
|
18
|
-
return this.closed || this.client.totalCount === 0 && this.client.waitingCount === 0;
|
|
19
|
-
}
|
|
20
|
-
get closed() {
|
|
21
|
-
return this.client.ended;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
14
|
+
const DbPool = require("@pi-r/postgres/client/pool");
|
|
24
15
|
const POOL_STATE = {};
|
|
25
|
-
const POOL_UNUSED = ['ssl', 'keepAlive', 'statement_timeout', 'query_timeout', 'keepAliveInitialDelayMillis', 'idle_in_transaction_session_timeout', 'connectionTimeoutMillis', 'max', 'min', 'idleTimeoutMillis', 'log', 'allowExitOnIdle', 'maxUses'];
|
|
26
|
-
const POOL_ACTIVE = new WeakSet();
|
|
27
|
-
function removePoolProperties(credential) {
|
|
28
|
-
if (!credential.uuidKey && POOL_ACTIVE.has(credential)) {
|
|
29
|
-
let result;
|
|
30
|
-
for (let i = 0, length = POOL_UNUSED.length; i < length; ++i) {
|
|
31
|
-
const attr = POOL_UNUSED[i];
|
|
32
|
-
if (attr in credential) {
|
|
33
|
-
result ||= { ...credential };
|
|
34
|
-
if (attr === 'ssl' && (0, types_1.isObject)(result[attr])) {
|
|
35
|
-
result[attr] = true;
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
delete result[attr];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (result) {
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return credential;
|
|
47
|
-
}
|
|
48
16
|
function fromConnectionString(credential, uri) {
|
|
49
|
-
const { user, password, host, port, database, application_name, ssl } = connectionString.parse(uri);
|
|
17
|
+
const { user, password, host, port, database, application_name, ssl, options } = connectionString.parse(uri);
|
|
50
18
|
if (!credential.user) {
|
|
51
19
|
credential.user = user;
|
|
52
20
|
credential.password = password;
|
|
@@ -55,21 +23,24 @@ function fromConnectionString(credential, uri) {
|
|
|
55
23
|
if (port) {
|
|
56
24
|
credential.port ||= parseInt(port);
|
|
57
25
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (ssl) {
|
|
61
|
-
credential.ssl ??= (0, types_1.isPlainObject)(ssl) ? ssl : true;
|
|
26
|
+
if (database) {
|
|
27
|
+
credential.database ||= database;
|
|
62
28
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
29
|
+
if (application_name) {
|
|
30
|
+
credential.application_name ||= application_name;
|
|
31
|
+
}
|
|
32
|
+
if (options) {
|
|
33
|
+
credential.options ||= options;
|
|
34
|
+
}
|
|
35
|
+
if (ssl) {
|
|
36
|
+
if (!(0, types_1.isPlainObject)(ssl)) {
|
|
37
|
+
credential.ssl ??= true;
|
|
38
|
+
}
|
|
39
|
+
else if (!(0, types_1.isPlainObject)(credential.ssl)) {
|
|
40
|
+
credential.ssl = ssl;
|
|
70
41
|
}
|
|
71
|
-
return JSON.stringify(credential);
|
|
72
42
|
}
|
|
43
|
+
return credential;
|
|
73
44
|
}
|
|
74
45
|
function setAuthentication(credential) {
|
|
75
46
|
const auth = (0, util_1.parseServerAuth)(credential);
|
|
@@ -82,7 +53,6 @@ function setAuthentication(credential) {
|
|
|
82
53
|
this.readTLSConfig(credential.ssl);
|
|
83
54
|
}
|
|
84
55
|
}
|
|
85
|
-
exports.setAuthentication = setAuthentication;
|
|
86
56
|
function setCredential(item) {
|
|
87
57
|
let credential = this.getCredential(item);
|
|
88
58
|
if (credential) {
|
|
@@ -90,9 +60,9 @@ function setCredential(item) {
|
|
|
90
60
|
}
|
|
91
61
|
else {
|
|
92
62
|
credential = {};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
}
|
|
64
|
+
if (item.uri) {
|
|
65
|
+
item.credential = fromConnectionString(credential, item.uri);
|
|
96
66
|
}
|
|
97
67
|
if (!credential.connectionString) {
|
|
98
68
|
const errors = [];
|
|
@@ -102,10 +72,21 @@ function setCredential(item) {
|
|
|
102
72
|
if (!credential.user) {
|
|
103
73
|
errors.push('user');
|
|
104
74
|
}
|
|
105
|
-
if (errors.length) {
|
|
75
|
+
if (errors.length > 0) {
|
|
106
76
|
throw (0, types_1.errorMessage)("postgres", 'Not defined - ' + errors.join(' | '));
|
|
107
77
|
}
|
|
108
78
|
}
|
|
79
|
+
if (credential.host?.endsWith('.rds.amazonaws.com')) {
|
|
80
|
+
try {
|
|
81
|
+
const ssl = credential.ssl ||= {};
|
|
82
|
+
if ((0, types_1.isPlainObject)(ssl) && !ssl.ca) {
|
|
83
|
+
const bundle = require('aws-ssl-profiles');
|
|
84
|
+
ssl.ca = bundle.ca;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
109
90
|
const usePool = item.usePool;
|
|
110
91
|
if (!item.usePool || typeof credential.password === 'function') {
|
|
111
92
|
if ('usePool' in item) {
|
|
@@ -143,18 +124,19 @@ function setCredential(item) {
|
|
|
143
124
|
credential.connectionTimeoutMillis ??= timeout;
|
|
144
125
|
}
|
|
145
126
|
}
|
|
146
|
-
const poolKey =
|
|
127
|
+
const poolKey = DbPool.asString(credential);
|
|
147
128
|
if ((pool = POOL_STATE[poolKey]) && !pool.closed) {
|
|
148
129
|
pool.add(item);
|
|
149
130
|
return;
|
|
150
131
|
}
|
|
151
|
-
|
|
132
|
+
const client = new postgres.Pool(credential);
|
|
133
|
+
new DbPool(client, poolKey, username && password ? { username, password } : undefined)
|
|
134
|
+
.add(item)
|
|
135
|
+
.parent = POOL_STATE;
|
|
152
136
|
}
|
|
153
|
-
exports.setCredential = setCredential;
|
|
154
137
|
async function executeQuery(item, options) {
|
|
155
138
|
return (await executeBatchQuery.call(this, [item], options))[0] || [];
|
|
156
139
|
}
|
|
157
|
-
exports.executeQuery = executeQuery;
|
|
158
140
|
async function executeBatchQuery(batch, options = '', outResult) {
|
|
159
141
|
const length = batch.length;
|
|
160
142
|
if (length === 0) {
|
|
@@ -189,20 +171,18 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
189
171
|
item.transactionState = 64;
|
|
190
172
|
let client;
|
|
191
173
|
if (postgresPool) {
|
|
192
|
-
pools.push(client = await postgresPool.getConnection());
|
|
174
|
+
pools.push(client = await postgresPool.getConnection(credential));
|
|
193
175
|
item.transactionState &= ~64;
|
|
194
|
-
POOL_ACTIVE.add(credential);
|
|
195
176
|
return client;
|
|
196
177
|
}
|
|
197
|
-
const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool,
|
|
178
|
+
const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool, DbPool.asString(credential), ...connectOnce ? [item, batch[0]] : [item]);
|
|
198
179
|
if (pool) {
|
|
199
180
|
try {
|
|
200
|
-
pools.push(client = await pool.getConnection());
|
|
181
|
+
pools.push(client = await pool.getConnection(credential));
|
|
201
182
|
if (connectOnce) {
|
|
202
183
|
postgresPool = pool;
|
|
203
184
|
}
|
|
204
185
|
pool.connected = true;
|
|
205
|
-
POOL_ACTIVE.add(credential);
|
|
206
186
|
}
|
|
207
187
|
catch (err) {
|
|
208
188
|
let close;
|
|
@@ -267,7 +247,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
267
247
|
if (caching && ignoreCache !== true) {
|
|
268
248
|
queryString = Db.asString(query, true) + '_' + Db.asString(params, true);
|
|
269
249
|
if (ignoreCache !== 1) {
|
|
270
|
-
const result = this.getQueryResult(source,
|
|
250
|
+
const result = this.getQueryResult(source, DbPool.sanitize(credential), queryString, cacheValue);
|
|
271
251
|
if (result) {
|
|
272
252
|
if (parallel) {
|
|
273
253
|
tasks[i] = Promise.resolve(result);
|
|
@@ -303,7 +283,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
303
283
|
commandType = this.commandType.SELECT;
|
|
304
284
|
if (streamRow && (0, types_1.isString)(query)) {
|
|
305
285
|
const rows = [];
|
|
306
|
-
const processRow = typeof streamRow === 'function'
|
|
286
|
+
const processRow = typeof streamRow === 'function' ? streamRow : null;
|
|
307
287
|
const stream = client.query(new QueryStream(query, params));
|
|
308
288
|
stream
|
|
309
289
|
.on('data', row => {
|
|
@@ -326,7 +306,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
326
306
|
}
|
|
327
307
|
else {
|
|
328
308
|
this.add(item, 4);
|
|
329
|
-
resolve(!error ? this.setQueryResult(source,
|
|
309
|
+
resolve(!error ? this.setQueryResult(source, DbPool.sanitize(credential), queryString, rows, cacheValue) : rows);
|
|
330
310
|
}
|
|
331
311
|
})
|
|
332
312
|
.on('end', () => stream.destroy());
|
|
@@ -334,7 +314,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
334
314
|
else {
|
|
335
315
|
const { rows, command } = await client.query(query, params);
|
|
336
316
|
this.add(item, 4);
|
|
337
|
-
resolve(rows.length || command === 'SELECT' ? this.setQueryResult(source,
|
|
317
|
+
resolve(rows.length || command === 'SELECT' ? this.setQueryResult(source, DbPool.sanitize(credential), queryString, rows, cacheValue) : null);
|
|
338
318
|
}
|
|
339
319
|
}
|
|
340
320
|
catch (err) {
|
|
@@ -357,25 +337,23 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
357
337
|
}
|
|
358
338
|
}
|
|
359
339
|
return this.processRows(batch, tasks, {
|
|
340
|
+
parallel,
|
|
360
341
|
disconnect: () => {
|
|
361
|
-
|
|
342
|
+
for (const item of clients) {
|
|
362
343
|
item.end(err => {
|
|
363
344
|
if (err) {
|
|
364
345
|
this.writeFail(["Unable to close connnection", "postgres"], err, { type: 65536, fatal: false });
|
|
365
346
|
}
|
|
366
347
|
});
|
|
367
|
-
}
|
|
368
|
-
|
|
348
|
+
}
|
|
349
|
+
for (const item of pools) {
|
|
369
350
|
item.release();
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
parallel
|
|
351
|
+
}
|
|
352
|
+
}
|
|
373
353
|
}, outResult);
|
|
374
354
|
}
|
|
375
|
-
exports.executeBatchQuery = executeBatchQuery;
|
|
376
355
|
async function checkTimeout(value, limit = 0) {
|
|
377
356
|
return DbPool.checkTimeout(POOL_STATE, value, limit);
|
|
378
357
|
}
|
|
379
|
-
exports.checkTimeout = checkTimeout;
|
|
380
358
|
exports.DB_SOURCE_CLIENT = true;
|
|
381
359
|
exports.DB_SOURCE_TYPE = types_1.DB_TYPE.SQL;
|
package/client/pool.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DbPoolConstructor } from '@e-mc/types/lib/db';
|
|
2
|
+
|
|
3
|
+
import type { DbPoolCredential, PostgresDataSource } from '../types';
|
|
4
|
+
|
|
5
|
+
import type { Pool, PoolClient } from 'pg';
|
|
6
|
+
|
|
7
|
+
declare const PostgresPool: DbPoolConstructor<PostgresDataSource, Pool, PoolClient, DbPoolCredential>;
|
|
8
|
+
|
|
9
|
+
export = PostgresPool;
|
package/client/pool.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const types_1 = require("@e-mc/types");
|
|
3
|
+
const DbPool = require('@e-mc/db/pool');
|
|
4
|
+
const POOL_ACTIVE = new WeakSet();
|
|
5
|
+
class PostgresPool extends DbPool {
|
|
6
|
+
static CACHE_UNUSED = ['keepAlive', 'statement_timeout', 'query_timeout', 'keepAliveInitialDelayMillis', 'idle_in_transaction_session_timeout', 'connectionTimeoutMillis', 'max', 'min', 'idleTimeoutMillis', 'log', 'allowExitOnIdle', 'maxUses'];
|
|
7
|
+
static asString(credential) {
|
|
8
|
+
if (credential.host && credential.user) {
|
|
9
|
+
return JSON.stringify(this.removeUUIDKey(credential));
|
|
10
|
+
}
|
|
11
|
+
return super.asString(credential);
|
|
12
|
+
}
|
|
13
|
+
static sanitize(credential) {
|
|
14
|
+
if (!POOL_ACTIVE.has(credential) || credential.uuidKey) {
|
|
15
|
+
return credential;
|
|
16
|
+
}
|
|
17
|
+
const ssl = credential.ssl;
|
|
18
|
+
let result = super.sanitize(credential);
|
|
19
|
+
if ((0, types_1.isObject)(ssl)) {
|
|
20
|
+
if (result === credential) {
|
|
21
|
+
result = { ...credential };
|
|
22
|
+
}
|
|
23
|
+
const cert = ssl.cert;
|
|
24
|
+
if ((0, types_1.isString)(cert)) {
|
|
25
|
+
result.ssl = { cert };
|
|
26
|
+
}
|
|
27
|
+
else if (Buffer.isBuffer(cert)) {
|
|
28
|
+
result.ssl = { cert: cert.toString('utf-8') };
|
|
29
|
+
}
|
|
30
|
+
else if ((0, types_1.isArray)(cert)) {
|
|
31
|
+
result.ssl = { cert: cert.reduce((a, b) => a + (Buffer.isBuffer(b) ? b.toString('utf-8') : b), '') };
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
result.ssl = { cert: "Unknown" };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
async getConnection(credential) {
|
|
40
|
+
if (credential) {
|
|
41
|
+
POOL_ACTIVE.add(credential);
|
|
42
|
+
}
|
|
43
|
+
return this.client.connect();
|
|
44
|
+
}
|
|
45
|
+
async close() {
|
|
46
|
+
return this.client.end();
|
|
47
|
+
}
|
|
48
|
+
isEmpty() {
|
|
49
|
+
return this.closed || this.client.totalCount === 0 && this.client.waitingCount === 0;
|
|
50
|
+
}
|
|
51
|
+
get closed() {
|
|
52
|
+
return this.client.ended;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
module.exports = PostgresPool;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-r/postgres",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "PostgreSQL client driver for E-mc.",
|
|
5
5
|
"main": "client/index.js",
|
|
6
6
|
"types": "client/index.d.ts",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"homepage": "https://github.com/anpham6/pi-r#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@e-mc/db": "^0.
|
|
25
|
-
"@e-mc/types": "^0.
|
|
24
|
+
"@e-mc/db": "^0.10.0",
|
|
25
|
+
"@e-mc/types": "^0.10.0",
|
|
26
26
|
"pg": "^8.12.0",
|
|
27
27
|
"pg-connection-string": "^2.6.4",
|
|
28
28
|
"pg-query-stream": "^4.6.0"
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DbDataSource } from '@e-mc/types/lib/squared';
|
|
2
2
|
|
|
3
|
+
import type { IdentifierAction } from '@e-mc/types/lib/core';
|
|
3
4
|
import type { ExecuteAction, ServerAuth } from '@e-mc/types/lib/db';
|
|
4
5
|
|
|
5
6
|
// @ts-ignore
|
|
@@ -9,4 +10,5 @@ export interface PostgresDataSource<T = unknown[]> extends DbDataSource<string |
|
|
|
9
10
|
source: "postgres";
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export interface PostgresCredential extends Omit<ServerAuth, "password">, PoolConfig {}
|
|
13
|
+
export interface PostgresCredential extends Omit<ServerAuth, "password">, PoolConfig {}
|
|
14
|
+
export type DbPoolCredential = PoolConfig & IdentifierAction;
|