relq 1.0.112 → 1.0.113

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.
@@ -257,15 +257,24 @@ class PgBase extends relq_base_1.RelqBase {
257
257
  return;
258
258
  this.poolErrorHandler = (err) => {
259
259
  const errorCode = err.code;
260
- const recoverableErrors = ['ETIMEDOUT', 'ECONNRESET', '57P02'];
261
- if (!recoverableErrors.includes(errorCode)) {
262
- throw err;
260
+ if (isPoolRecoverableError(errorCode)) {
261
+ const logLevel = this.config.logLevel ?? 'info';
262
+ if (logLevel !== 'silent') {
263
+ console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
264
+ code: errorCode,
265
+ message: err.message,
266
+ action: 'Connection removed from pool, will be replaced on next query'
267
+ });
268
+ }
269
+ return;
270
+ }
271
+ const logLevel = this.config.logLevel ?? 'info';
272
+ if (logLevel !== 'silent') {
273
+ console.error('[Relq Pool] Pool error:', {
274
+ code: errorCode,
275
+ message: err.message,
276
+ });
263
277
  }
264
- console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
265
- code: errorCode,
266
- message: err.message,
267
- action: 'Connection removed from pool, will be replaced on next query'
268
- });
269
278
  };
270
279
  this.poolConnectHandler = () => { };
271
280
  this.poolRemoveHandler = () => { };
@@ -349,3 +358,22 @@ class PgBase extends relq_base_1.RelqBase {
349
358
  }
350
359
  }
351
360
  exports.PgBase = PgBase;
361
+ const POOL_RECOVERABLE_NETWORK_CODES = new Set([
362
+ 'ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ESERVFAIL',
363
+ 'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
364
+ 'ECONNABORTED', 'ENETUNREACH', 'ENETRESET',
365
+ 'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
366
+ ]);
367
+ const POOL_RECOVERABLE_PG_CODES = new Set([
368
+ '57P01',
369
+ '57P02',
370
+ '57P03',
371
+ '08006',
372
+ '08001',
373
+ '08004',
374
+ ]);
375
+ function isPoolRecoverableError(code) {
376
+ if (!code)
377
+ return true;
378
+ return POOL_RECOVERABLE_NETWORK_CODES.has(code) || POOL_RECOVERABLE_PG_CODES.has(code);
379
+ }
@@ -14,6 +14,7 @@ class RelqBase {
14
14
  config;
15
15
  schema;
16
16
  emitter = new node_events_1.EventEmitter();
17
+ _defaultErrorHandler = () => { };
17
18
  columnMappings = new Map();
18
19
  initialized = false;
19
20
  initPromise;
@@ -21,6 +22,7 @@ class RelqBase {
21
22
  constructor(schema, config) {
22
23
  this.config = config;
23
24
  this.schema = schema;
25
+ this.emitter.on('error', this._defaultErrorHandler);
24
26
  if (schema) {
25
27
  const log = config.logLevel === 'debug'
26
28
  ? (...args) => (0, helpers_1.debugLog)(config, ...args)
@@ -312,7 +312,15 @@ function wrapError(error, context) {
312
312
  function parsePostgresError(error, sql) {
313
313
  const message = error.message || 'Database error';
314
314
  const code = error.code;
315
- if (code === 'ECONNREFUSED' || code === 'ENOTFOUND' || code === 'ETIMEDOUT') {
315
+ if (isNetworkErrorCode(code)) {
316
+ return new RelqConnectionError(message, {
317
+ cause: error,
318
+ code,
319
+ host: error.hostname || error.address,
320
+ port: error.port
321
+ });
322
+ }
323
+ if (code === '57P01' || code === '57P03' || code === '08006' || code === '08001' || code === '08004') {
316
324
  return new RelqConnectionError(message, {
317
325
  cause: error,
318
326
  code,
@@ -331,3 +339,11 @@ function parsePostgresError(error, sql) {
331
339
  hint: error.hint
332
340
  });
333
341
  }
342
+ const NETWORK_ERROR_CODES = new Set([
343
+ 'ECONNREFUSED', 'ECONNRESET', 'ENOTFOUND', 'ESERVFAIL',
344
+ 'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
345
+ 'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
346
+ ]);
347
+ function isNetworkErrorCode(code) {
348
+ return !!code && NETWORK_ERROR_CODES.has(code);
349
+ }
@@ -220,15 +220,24 @@ export class PgBase extends RelqBase {
220
220
  return;
221
221
  this.poolErrorHandler = (err) => {
222
222
  const errorCode = err.code;
223
- const recoverableErrors = ['ETIMEDOUT', 'ECONNRESET', '57P02'];
224
- if (!recoverableErrors.includes(errorCode)) {
225
- throw err;
223
+ if (isPoolRecoverableError(errorCode)) {
224
+ const logLevel = this.config.logLevel ?? 'info';
225
+ if (logLevel !== 'silent') {
226
+ console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
227
+ code: errorCode,
228
+ message: err.message,
229
+ action: 'Connection removed from pool, will be replaced on next query'
230
+ });
231
+ }
232
+ return;
233
+ }
234
+ const logLevel = this.config.logLevel ?? 'info';
235
+ if (logLevel !== 'silent') {
236
+ console.error('[Relq Pool] Pool error:', {
237
+ code: errorCode,
238
+ message: err.message,
239
+ });
226
240
  }
227
- console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
228
- code: errorCode,
229
- message: err.message,
230
- action: 'Connection removed from pool, will be replaced on next query'
231
- });
232
241
  };
233
242
  this.poolConnectHandler = () => { };
234
243
  this.poolRemoveHandler = () => { };
@@ -311,3 +320,22 @@ export class PgBase extends RelqBase {
311
320
  this.emitter.emit('connect', this.client);
312
321
  }
313
322
  }
323
+ const POOL_RECOVERABLE_NETWORK_CODES = new Set([
324
+ 'ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ESERVFAIL',
325
+ 'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
326
+ 'ECONNABORTED', 'ENETUNREACH', 'ENETRESET',
327
+ 'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
328
+ ]);
329
+ const POOL_RECOVERABLE_PG_CODES = new Set([
330
+ '57P01',
331
+ '57P02',
332
+ '57P03',
333
+ '08006',
334
+ '08001',
335
+ '08004',
336
+ ]);
337
+ function isPoolRecoverableError(code) {
338
+ if (!code)
339
+ return true;
340
+ return POOL_RECOVERABLE_NETWORK_CODES.has(code) || POOL_RECOVERABLE_PG_CODES.has(code);
341
+ }
@@ -11,6 +11,7 @@ export class RelqBase {
11
11
  config;
12
12
  schema;
13
13
  emitter = new EventEmitter();
14
+ _defaultErrorHandler = () => { };
14
15
  columnMappings = new Map();
15
16
  initialized = false;
16
17
  initPromise;
@@ -18,6 +19,7 @@ export class RelqBase {
18
19
  constructor(schema, config) {
19
20
  this.config = config;
20
21
  this.schema = schema;
22
+ this.emitter.on('error', this._defaultErrorHandler);
21
23
  if (schema) {
22
24
  const log = config.logLevel === 'debug'
23
25
  ? (...args) => debugLog(config, ...args)
@@ -290,7 +290,15 @@ export function wrapError(error, context) {
290
290
  export function parsePostgresError(error, sql) {
291
291
  const message = error.message || 'Database error';
292
292
  const code = error.code;
293
- if (code === 'ECONNREFUSED' || code === 'ENOTFOUND' || code === 'ETIMEDOUT') {
293
+ if (isNetworkErrorCode(code)) {
294
+ return new RelqConnectionError(message, {
295
+ cause: error,
296
+ code,
297
+ host: error.hostname || error.address,
298
+ port: error.port
299
+ });
300
+ }
301
+ if (code === '57P01' || code === '57P03' || code === '08006' || code === '08001' || code === '08004') {
294
302
  return new RelqConnectionError(message, {
295
303
  cause: error,
296
304
  code,
@@ -309,3 +317,11 @@ export function parsePostgresError(error, sql) {
309
317
  hint: error.hint
310
318
  });
311
319
  }
320
+ const NETWORK_ERROR_CODES = new Set([
321
+ 'ECONNREFUSED', 'ECONNRESET', 'ENOTFOUND', 'ESERVFAIL',
322
+ 'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
323
+ 'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
324
+ ]);
325
+ function isNetworkErrorCode(code) {
326
+ return !!code && NETWORK_ERROR_CODES.has(code);
327
+ }
package/dist/index.d.ts CHANGED
@@ -10023,6 +10023,7 @@ export declare abstract class RelqBase<TSchema = any> {
10023
10023
  protected config: RelqConfig;
10024
10024
  protected schema?: TSchema;
10025
10025
  protected readonly emitter: EventEmitter<any>;
10026
+ private readonly _defaultErrorHandler;
10026
10027
  protected columnMappings: ColumnMappings;
10027
10028
  protected initialized: boolean;
10028
10029
  protected initPromise?: Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relq",
3
- "version": "1.0.112",
3
+ "version": "1.0.113",
4
4
  "description": "The Fully-Typed PostgreSQL ORM for TypeScript",
5
5
  "author": "Olajide Mathew O. <olajide.mathew@yuniq.solutions>",
6
6
  "license": "MIT",