@pi-r/postgres 0.7.2 → 0.8.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/client/index.js +40 -74
- 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,50 +1,18 @@
|
|
|
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
17
|
const { user, password, host, port, database, application_name, ssl } = connectionString.parse(uri);
|
|
50
18
|
if (!credential.user) {
|
|
@@ -62,15 +30,6 @@ function fromConnectionString(credential, uri) {
|
|
|
62
30
|
}
|
|
63
31
|
return credential;
|
|
64
32
|
}
|
|
65
|
-
function getPoolKey(credential) {
|
|
66
|
-
if (credential.host && credential.user) {
|
|
67
|
-
if ('uuidKey' in credential) {
|
|
68
|
-
credential = { ...credential };
|
|
69
|
-
delete credential.uuidKey;
|
|
70
|
-
}
|
|
71
|
-
return JSON.stringify(credential);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
33
|
function setAuthentication(credential) {
|
|
75
34
|
const auth = (0, util_1.parseServerAuth)(credential);
|
|
76
35
|
credential.host ||= auth.hostname;
|
|
@@ -82,7 +41,6 @@ function setAuthentication(credential) {
|
|
|
82
41
|
this.readTLSConfig(credential.ssl);
|
|
83
42
|
}
|
|
84
43
|
}
|
|
85
|
-
exports.setAuthentication = setAuthentication;
|
|
86
44
|
function setCredential(item) {
|
|
87
45
|
let credential = this.getCredential(item);
|
|
88
46
|
if (credential) {
|
|
@@ -90,7 +48,7 @@ function setCredential(item) {
|
|
|
90
48
|
}
|
|
91
49
|
else {
|
|
92
50
|
credential = {};
|
|
93
|
-
if (
|
|
51
|
+
if (item.uri) {
|
|
94
52
|
item.credential = fromConnectionString(credential, item.uri);
|
|
95
53
|
}
|
|
96
54
|
}
|
|
@@ -102,10 +60,21 @@ function setCredential(item) {
|
|
|
102
60
|
if (!credential.user) {
|
|
103
61
|
errors.push('user');
|
|
104
62
|
}
|
|
105
|
-
if (errors.length) {
|
|
63
|
+
if (errors.length > 0) {
|
|
106
64
|
throw (0, types_1.errorMessage)("postgres", 'Not defined - ' + errors.join(' | '));
|
|
107
65
|
}
|
|
108
66
|
}
|
|
67
|
+
if (credential.host?.endsWith('.rds.amazonaws.com')) {
|
|
68
|
+
try {
|
|
69
|
+
const ssl = credential.ssl ||= {};
|
|
70
|
+
if ((0, types_1.isPlainObject)(ssl) && !ssl.ca) {
|
|
71
|
+
const bundle = require('aws-ssl-profiles');
|
|
72
|
+
ssl.ca = bundle.ca;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
109
78
|
const usePool = item.usePool;
|
|
110
79
|
if (!item.usePool || typeof credential.password === 'function') {
|
|
111
80
|
if ('usePool' in item) {
|
|
@@ -143,18 +112,19 @@ function setCredential(item) {
|
|
|
143
112
|
credential.connectionTimeoutMillis ??= timeout;
|
|
144
113
|
}
|
|
145
114
|
}
|
|
146
|
-
const poolKey =
|
|
115
|
+
const poolKey = DbPool.asString(credential);
|
|
147
116
|
if ((pool = POOL_STATE[poolKey]) && !pool.closed) {
|
|
148
117
|
pool.add(item);
|
|
149
118
|
return;
|
|
150
119
|
}
|
|
151
|
-
|
|
120
|
+
const client = new postgres.Pool(credential);
|
|
121
|
+
new DbPool(client, poolKey, username && password ? { username, password } : undefined)
|
|
122
|
+
.add(item)
|
|
123
|
+
.parent = POOL_STATE;
|
|
152
124
|
}
|
|
153
|
-
exports.setCredential = setCredential;
|
|
154
125
|
async function executeQuery(item, options) {
|
|
155
126
|
return (await executeBatchQuery.call(this, [item], options))[0] || [];
|
|
156
127
|
}
|
|
157
|
-
exports.executeQuery = executeQuery;
|
|
158
128
|
async function executeBatchQuery(batch, options = '', outResult) {
|
|
159
129
|
const length = batch.length;
|
|
160
130
|
if (length === 0) {
|
|
@@ -189,20 +159,18 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
189
159
|
item.transactionState = 64;
|
|
190
160
|
let client;
|
|
191
161
|
if (postgresPool) {
|
|
192
|
-
pools.push(client = await postgresPool.getConnection());
|
|
162
|
+
pools.push(client = await postgresPool.getConnection(credential));
|
|
193
163
|
item.transactionState &= ~64;
|
|
194
|
-
POOL_ACTIVE.add(credential);
|
|
195
164
|
return client;
|
|
196
165
|
}
|
|
197
|
-
const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool,
|
|
166
|
+
const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool, DbPool.asString(credential), ...connectOnce ? [item, batch[0]] : [item]);
|
|
198
167
|
if (pool) {
|
|
199
168
|
try {
|
|
200
|
-
pools.push(client = await pool.getConnection());
|
|
169
|
+
pools.push(client = await pool.getConnection(credential));
|
|
201
170
|
if (connectOnce) {
|
|
202
171
|
postgresPool = pool;
|
|
203
172
|
}
|
|
204
173
|
pool.connected = true;
|
|
205
|
-
POOL_ACTIVE.add(credential);
|
|
206
174
|
}
|
|
207
175
|
catch (err) {
|
|
208
176
|
let close;
|
|
@@ -267,7 +235,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
267
235
|
if (caching && ignoreCache !== true) {
|
|
268
236
|
queryString = Db.asString(query, true) + '_' + Db.asString(params, true);
|
|
269
237
|
if (ignoreCache !== 1) {
|
|
270
|
-
const result = this.getQueryResult(source,
|
|
238
|
+
const result = this.getQueryResult(source, DbPool.sanitize(credential), queryString, cacheValue);
|
|
271
239
|
if (result) {
|
|
272
240
|
if (parallel) {
|
|
273
241
|
tasks[i] = Promise.resolve(result);
|
|
@@ -303,7 +271,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
303
271
|
commandType = this.commandType.SELECT;
|
|
304
272
|
if (streamRow && (0, types_1.isString)(query)) {
|
|
305
273
|
const rows = [];
|
|
306
|
-
const processRow = typeof streamRow === 'function'
|
|
274
|
+
const processRow = typeof streamRow === 'function' ? streamRow : null;
|
|
307
275
|
const stream = client.query(new QueryStream(query, params));
|
|
308
276
|
stream
|
|
309
277
|
.on('data', row => {
|
|
@@ -326,7 +294,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
326
294
|
}
|
|
327
295
|
else {
|
|
328
296
|
this.add(item, 4);
|
|
329
|
-
resolve(!error ? this.setQueryResult(source,
|
|
297
|
+
resolve(!error ? this.setQueryResult(source, DbPool.sanitize(credential), queryString, rows, cacheValue) : rows);
|
|
330
298
|
}
|
|
331
299
|
})
|
|
332
300
|
.on('end', () => stream.destroy());
|
|
@@ -334,7 +302,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
334
302
|
else {
|
|
335
303
|
const { rows, command } = await client.query(query, params);
|
|
336
304
|
this.add(item, 4);
|
|
337
|
-
resolve(rows.length || command === 'SELECT' ? this.setQueryResult(source,
|
|
305
|
+
resolve(rows.length || command === 'SELECT' ? this.setQueryResult(source, DbPool.sanitize(credential), queryString, rows, cacheValue) : null);
|
|
338
306
|
}
|
|
339
307
|
}
|
|
340
308
|
catch (err) {
|
|
@@ -357,25 +325,23 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
357
325
|
}
|
|
358
326
|
}
|
|
359
327
|
return this.processRows(batch, tasks, {
|
|
328
|
+
parallel,
|
|
360
329
|
disconnect: () => {
|
|
361
|
-
|
|
330
|
+
for (const item of clients) {
|
|
362
331
|
item.end(err => {
|
|
363
332
|
if (err) {
|
|
364
333
|
this.writeFail(["Unable to close connnection", "postgres"], err, { type: 65536, fatal: false });
|
|
365
334
|
}
|
|
366
335
|
});
|
|
367
|
-
}
|
|
368
|
-
|
|
336
|
+
}
|
|
337
|
+
for (const item of pools) {
|
|
369
338
|
item.release();
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
parallel
|
|
339
|
+
}
|
|
340
|
+
}
|
|
373
341
|
}, outResult);
|
|
374
342
|
}
|
|
375
|
-
exports.executeBatchQuery = executeBatchQuery;
|
|
376
343
|
async function checkTimeout(value, limit = 0) {
|
|
377
344
|
return DbPool.checkTimeout(POOL_STATE, value, limit);
|
|
378
345
|
}
|
|
379
|
-
exports.checkTimeout = checkTimeout;
|
|
380
346
|
exports.DB_SOURCE_CLIENT = true;
|
|
381
347
|
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.0",
|
|
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;
|