@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 CHANGED
@@ -1,52 +1,20 @@
1
1
  "use strict";
2
- exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT = exports.checkTimeout = exports.executeBatchQuery = exports.executeQuery = exports.setCredential = exports.setAuthentication = void 0;
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 Db = require("@e-mc/db");
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
- credential.database ||= database;
59
- credential.application_name ||= application_name;
60
- if (ssl) {
61
- credential.ssl ??= (0, types_1.isPlainObject)(ssl) ? ssl : true;
26
+ if (database) {
27
+ credential.database ||= database;
62
28
  }
63
- return credential;
64
- }
65
- function getPoolKey(credential) {
66
- if (credential.host && credential.user) {
67
- if ('uuidKey' in credential) {
68
- credential = { ...credential };
69
- delete credential.uuidKey;
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
- if ((0, types_1.isString)(item.uri)) {
94
- item.credential = fromConnectionString(credential, item.uri);
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 = getPoolKey(credential);
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
- new PostgresPool(new postgres.Pool(credential), poolKey, username && password ? { username, password } : undefined).add(item).parent = POOL_STATE;
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, getPoolKey(credential), ...connectOnce ? [item, batch[0]] : [item]);
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, removePoolProperties(credential), queryString, cacheValue);
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' && streamRow;
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, removePoolProperties(credential), queryString, rows, cacheValue) : rows);
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, removePoolProperties(credential), queryString, rows, cacheValue) : null);
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
- clients.forEach(item => {
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
- pools.forEach(item => {
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;
@@ -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.7.3",
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.9.6",
25
- "@e-mc/types": "^0.9.6",
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;