@onlineapps/service-common 1.0.12 → 1.0.14
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/README.md
CHANGED
|
@@ -53,10 +53,10 @@ await waitForInfrastructureReady({
|
|
|
53
53
|
Waits for all infrastructure services to be reported as healthy by Registry.
|
|
54
54
|
|
|
55
55
|
**Options:**
|
|
56
|
-
- `redisUrl` (string): Redis URL
|
|
56
|
+
- `redisUrl` (string): Redis URL
|
|
57
57
|
- `maxWait` (number): Maximum wait time in ms (default: 300000 = 5 minutes)
|
|
58
58
|
- `checkInterval` (number): Check interval in ms (default: 5000 = 5 seconds)
|
|
59
|
-
- `logger` (Object):
|
|
59
|
+
- `logger` (Object|Function): **Required** logger instance (or function). No implicit console fallback.
|
|
60
60
|
|
|
61
61
|
**Returns:** `Promise<boolean>` - True if all infrastructure services are ready
|
|
62
62
|
|
package/package.json
CHANGED
package/src/defaults.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
module.exports = {
|
|
13
13
|
infrastructureHealthQueueName: 'infrastructure.health.checks',
|
|
14
14
|
infrastructureHealthPublishIntervalMs: 5000,
|
|
15
|
-
infrastructureHealthWaitMaxTimeMs:
|
|
16
|
-
infrastructureHealthWaitCheckIntervalMs:
|
|
15
|
+
infrastructureHealthWaitMaxTimeMs: 60000,
|
|
16
|
+
infrastructureHealthWaitCheckIntervalMs: 2000,
|
|
17
17
|
infrastructureHealthTimeoutMs: 15000,
|
|
18
18
|
infrastructureHealthRedisTtlSeconds: 30,
|
|
19
19
|
infrastructureHealthCleanupIntervalMs: 10000,
|
|
@@ -37,15 +37,22 @@ async function waitForHealthCheckQueueReady(options = {}) {
|
|
|
37
37
|
const redisUrl = buildRedisUrl({ redisUrl: options.redisUrl });
|
|
38
38
|
const maxWait = runtimeCfg.get('infrastructureHealthQueueWaitMaxTimeMs', options.maxWait);
|
|
39
39
|
const checkInterval = runtimeCfg.get('infrastructureHealthQueueWaitCheckIntervalMs', options.checkInterval);
|
|
40
|
-
const logger = options.logger
|
|
40
|
+
const logger = options.logger;
|
|
41
|
+
if (!logger) {
|
|
42
|
+
throw new Error('[service-common][waitForHealthCheckQueueReady] Missing dependency - logger is required (no console fallback).');
|
|
43
|
+
}
|
|
41
44
|
|
|
42
45
|
const log = (msg) => {
|
|
43
46
|
if (logger && typeof logger.info === 'function') {
|
|
44
47
|
logger.info(msg);
|
|
45
48
|
} else if (logger && typeof logger.log === 'function') {
|
|
46
49
|
logger.log(msg);
|
|
50
|
+
} else if (logger && typeof logger === 'function') {
|
|
51
|
+
logger(msg);
|
|
47
52
|
} else {
|
|
48
|
-
|
|
53
|
+
throw new Error(
|
|
54
|
+
'[service-common][waitForHealthCheckQueueReady] Invalid logger - Expected logger.info(), logger.log(), or function logger(message).'
|
|
55
|
+
);
|
|
49
56
|
}
|
|
50
57
|
};
|
|
51
58
|
|
|
@@ -35,8 +35,8 @@ const runtimeCfg = require('../config');
|
|
|
35
35
|
* Wait for all infrastructure services to be ready
|
|
36
36
|
* @param {Object} options - Options
|
|
37
37
|
* @param {string} [options.redisUrl] - Redis URL (default: REDIS_URL env or redis://api_node_cache:6379)
|
|
38
|
-
* @param {number} [options.maxWait] - Maximum wait time in ms (default: INFRASTRUCTURE_HEALTH_WAIT_MAX_TIME env or
|
|
39
|
-
* @param {number} [options.checkInterval] - Check interval in ms (default: INFRASTRUCTURE_HEALTH_WAIT_CHECK_INTERVAL env or
|
|
38
|
+
* @param {number} [options.maxWait] - Maximum wait time in ms (default: INFRASTRUCTURE_HEALTH_WAIT_MAX_TIME env or 60000 = 1 minute)
|
|
39
|
+
* @param {number} [options.checkInterval] - Check interval in ms (default: INFRASTRUCTURE_HEALTH_WAIT_CHECK_INTERVAL env or 2000 = 2 seconds)
|
|
40
40
|
* @param {Object} [options.logger] - Logger instance (default: console)
|
|
41
41
|
* @returns {Promise<boolean>} - True if all infrastructure services are ready
|
|
42
42
|
* @throws {Error} - If timeout is reached
|
|
@@ -48,7 +48,10 @@ async function waitForInfrastructureReady(options = {}) {
|
|
|
48
48
|
const redisUrl = buildRedisUrl({ redisUrl: options.redisUrl });
|
|
49
49
|
const maxWait = runtimeCfg.get('infrastructureHealthWaitMaxTimeMs', options.maxWait);
|
|
50
50
|
const checkInterval = runtimeCfg.get('infrastructureHealthWaitCheckIntervalMs', options.checkInterval);
|
|
51
|
-
const logger = options.logger
|
|
51
|
+
const logger = options.logger;
|
|
52
|
+
if (!logger) {
|
|
53
|
+
throw new Error('[service-common][waitForInfrastructureReady] Missing dependency - logger is required (no console fallback).');
|
|
54
|
+
}
|
|
52
55
|
|
|
53
56
|
// Helper to log messages (compatible with both console and winston)
|
|
54
57
|
const log = (messageStr) => {
|
|
@@ -62,7 +65,9 @@ async function waitForInfrastructureReady(options = {}) {
|
|
|
62
65
|
// console.log or similar
|
|
63
66
|
logger(messageStr);
|
|
64
67
|
} else {
|
|
65
|
-
|
|
68
|
+
throw new Error(
|
|
69
|
+
'[service-common][waitForInfrastructureReady] Invalid logger - Expected logger.info(), logger.log(), or function logger(message).'
|
|
70
|
+
);
|
|
66
71
|
}
|
|
67
72
|
};
|
|
68
73
|
|
package/src/postgresClient.js
CHANGED
|
@@ -3,46 +3,52 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* PostgreSQL Client Utilities
|
|
5
5
|
*
|
|
6
|
-
* Provides helper functions for building PostgreSQL connection URLs
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* This is the ONLY place where fallbacks are acceptable.
|
|
6
|
+
* Provides helper functions for building PostgreSQL connection URLs.
|
|
7
|
+
*
|
|
8
|
+
* NO FALLBACKS: Topology must be explicit via ENV/config. This module must not
|
|
9
|
+
* embed docker-compose hostnames or credentials.
|
|
11
10
|
*/
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Build a PostgreSQL connection URL from environment.
|
|
15
14
|
*
|
|
16
|
-
* EXCEPTION: Fallbacks are allowed ONLY for infrastructure client configuration.
|
|
17
|
-
* This is the ONLY place where fallbacks are acceptable.
|
|
18
|
-
*
|
|
19
|
-
* Environment variable precedence (checked in order):
|
|
20
|
-
* 1. POSTGRES_URL (full URL, e.g. postgres://monitoring:monitoring_pass@api_monitoring_postgres:5432/monitoring) - ENV variable name
|
|
21
|
-
* 2. POSTGRES_HOST + POSTGRES_PORT + POSTGRES_USER + POSTGRES_PASSWORD + POSTGRES_DB (if POSTGRES_URL not set)
|
|
22
|
-
* 3. Fallback: postgres://monitoring:monitoring_pass@api_monitoring_postgres:5432/monitoring (docker-compose default)
|
|
23
|
-
*
|
|
24
15
|
* @param {Object} options - Options
|
|
25
16
|
* @param {Object} [options.env=process.env] - Environment variables
|
|
26
|
-
* @param {Object} [options.defaults] - Default host/port/user/password/db overrides
|
|
27
17
|
* @returns {string} PostgreSQL connection URL
|
|
28
18
|
*/
|
|
29
19
|
function buildPostgresUrl(options = {}) {
|
|
30
20
|
const env = options.env || process.env || {};
|
|
31
|
-
const defaults = options.defaults || {};
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
22
|
+
const url = env.POSTGRES_URL && typeof env.POSTGRES_URL === 'string' ? env.POSTGRES_URL.trim() : '';
|
|
23
|
+
if (url) return url;
|
|
24
|
+
|
|
25
|
+
const host = env.POSTGRES_HOST && typeof env.POSTGRES_HOST === 'string' ? env.POSTGRES_HOST.trim() : '';
|
|
26
|
+
const port = env.POSTGRES_PORT && typeof env.POSTGRES_PORT === 'string' ? env.POSTGRES_PORT.trim() : '';
|
|
27
|
+
const user = env.POSTGRES_USER && typeof env.POSTGRES_USER === 'string' ? env.POSTGRES_USER.trim() : '';
|
|
28
|
+
const password = env.POSTGRES_PASSWORD && typeof env.POSTGRES_PASSWORD === 'string' ? env.POSTGRES_PASSWORD.trim() : '';
|
|
29
|
+
const database = env.POSTGRES_DB && typeof env.POSTGRES_DB === 'string' ? env.POSTGRES_DB.trim() : '';
|
|
30
|
+
|
|
31
|
+
const anyPartsProvided = Boolean(host || port || user || password || database);
|
|
32
|
+
if (!anyPartsProvided) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
'[service-common][postgres] Missing configuration - POSTGRES_URL is required, or provide all: POSTGRES_HOST, POSTGRES_PORT, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB.'
|
|
35
|
+
);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
const missing = [];
|
|
39
|
+
if (!host) missing.push('POSTGRES_HOST');
|
|
40
|
+
if (!port) missing.push('POSTGRES_PORT');
|
|
41
|
+
if (!user) missing.push('POSTGRES_USER');
|
|
42
|
+
if (!password) missing.push('POSTGRES_PASSWORD');
|
|
43
|
+
if (!database) missing.push('POSTGRES_DB');
|
|
44
|
+
if (missing.length > 0) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`[service-common][postgres] Missing configuration - Partial PostgreSQL config provided. Missing: ${missing.join(', ')}. ` +
|
|
47
|
+
'Fix: set POSTGRES_URL or set all POSTGRES_* parts.'
|
|
48
|
+
);
|
|
49
|
+
}
|
|
45
50
|
|
|
51
|
+
// Do not attempt to do smart encoding here; POSTGRES_URL is the recommended option.
|
|
46
52
|
return `postgres://${user}:${password}@${host}:${port}/${database}`;
|
|
47
53
|
}
|
|
48
54
|
|
|
@@ -59,8 +65,7 @@ function createPostgresPool(options = {}) {
|
|
|
59
65
|
const { Pool } = require('pg');
|
|
60
66
|
|
|
61
67
|
const connectionString = buildPostgresUrl({
|
|
62
|
-
env: options.env
|
|
63
|
-
defaults: options.defaults
|
|
68
|
+
env: options.env
|
|
64
69
|
});
|
|
65
70
|
|
|
66
71
|
const poolConfig = {
|
|
@@ -81,7 +86,10 @@ function createPostgresPool(options = {}) {
|
|
|
81
86
|
* @param {Object} logger - Logger object with info/error methods
|
|
82
87
|
* @returns {Promise<void>}
|
|
83
88
|
*/
|
|
84
|
-
async function connectPostgres(pool, logger
|
|
89
|
+
async function connectPostgres(pool, logger) {
|
|
90
|
+
if (!logger) {
|
|
91
|
+
throw new Error('[service-common][postgres] Missing dependency - logger is required (no console fallback).');
|
|
92
|
+
}
|
|
85
93
|
try {
|
|
86
94
|
await pool.query('SELECT NOW()');
|
|
87
95
|
if (logger && logger.info) {
|
|
@@ -8,8 +8,8 @@ describe('@onlineapps/service-common defaults @unit', () => {
|
|
|
8
8
|
test('should export stable module-owned defaults', () => {
|
|
9
9
|
expect(defaults.infrastructureHealthQueueName).toBe('infrastructure.health.checks');
|
|
10
10
|
expect(defaults.infrastructureHealthPublishIntervalMs).toBe(5000);
|
|
11
|
-
expect(defaults.infrastructureHealthWaitMaxTimeMs).toBe(
|
|
12
|
-
expect(defaults.infrastructureHealthWaitCheckIntervalMs).toBe(
|
|
11
|
+
expect(defaults.infrastructureHealthWaitMaxTimeMs).toBe(60000);
|
|
12
|
+
expect(defaults.infrastructureHealthWaitCheckIntervalMs).toBe(2000);
|
|
13
13
|
expect(defaults.infrastructureHealthTimeoutMs).toBe(15000);
|
|
14
14
|
expect(defaults.infrastructureHealthRedisTtlSeconds).toBe(30);
|
|
15
15
|
expect(defaults.infrastructureHealthCleanupIntervalMs).toBe(10000);
|