@onlineapps/service-common 1.0.7 → 1.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/service-common",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Common utilities for both infrastructure services and business services",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/config.js CHANGED
@@ -23,16 +23,29 @@ const DEFAULTS = require('./defaults');
23
23
  const runtimeCfg = createRuntimeConfig({
24
24
  defaults: DEFAULTS,
25
25
  schema: {
26
- // Redis defaults
27
- redisHost: { env: 'REDIS_HOST', defaultKey: 'redisHost' },
28
- redisPort: { env: 'REDIS_PORT', defaultKey: 'redisPort' },
29
- redisUrl: { env: 'REDIS_URL', defaultKey: 'redisUrl' },
30
-
31
- // RabbitMQ defaults
32
- rabbitmqUrl: { env: 'RABBITMQ_URL', defaultKey: 'rabbitmqUrl' },
26
+ // Infrastructure topology (FAIL-FAST, no defaults)
27
+ redisUrl: { env: 'REDIS_URL', required: true },
28
+ rabbitmqUrl: { env: 'RABBITMQ_URL', required: true },
33
29
 
34
30
  // Infrastructure health
35
31
  infrastructureHealthQueueName: { env: 'INFRASTRUCTURE_HEALTH_QUEUE', defaultKey: 'infrastructureHealthQueueName' },
32
+ infrastructureHealthPublishIntervalMs: { env: 'INFRASTRUCTURE_HEALTH_PUBLISH_INTERVAL', defaultKey: 'infrastructureHealthPublishIntervalMs', type: 'number' },
33
+ infrastructureHealthWaitMaxTimeMs: { env: 'INFRASTRUCTURE_HEALTH_WAIT_MAX_TIME', defaultKey: 'infrastructureHealthWaitMaxTimeMs', type: 'number' },
34
+ infrastructureHealthWaitCheckIntervalMs: { env: 'INFRASTRUCTURE_HEALTH_WAIT_CHECK_INTERVAL', defaultKey: 'infrastructureHealthWaitCheckIntervalMs', type: 'number' },
35
+ infrastructureHealthTimeoutMs: { env: 'INFRASTRUCTURE_HEALTH_TIMEOUT', defaultKey: 'infrastructureHealthTimeoutMs', type: 'number' },
36
+ infrastructureHealthRedisTtlSeconds: { env: 'INFRASTRUCTURE_HEALTH_REDIS_TTL', defaultKey: 'infrastructureHealthRedisTtlSeconds', type: 'number' },
37
+ infrastructureHealthCleanupIntervalMs: { env: 'INFRASTRUCTURE_HEALTH_CLEANUP_INTERVAL', defaultKey: 'infrastructureHealthCleanupIntervalMs', type: 'number' },
38
+ infrastructureHealthQueueWaitMaxTimeMs: { env: 'INFRASTRUCTURE_HEALTH_QUEUE_WAIT_MAX_TIME', defaultKey: 'infrastructureHealthQueueWaitMaxTimeMs', type: 'number' },
39
+ infrastructureHealthQueueWaitCheckIntervalMs: { env: 'INFRASTRUCTURE_HEALTH_QUEUE_WAIT_CHECK_INTERVAL', defaultKey: 'infrastructureHealthQueueWaitCheckIntervalMs', type: 'number' },
40
+
41
+ // Optional reporting (no defaults; feature is disabled unless fully configured)
42
+ infraReportSmtpHost: { env: 'INFRA_REPORT_SMTP_HOST' },
43
+ infraReportSmtpPort: { env: 'INFRA_REPORT_SMTP_PORT', type: 'number' },
44
+ infraReportSmtpSecure: { env: 'INFRA_REPORT_SMTP_SECURE', type: 'boolean' },
45
+ infraReportSmtpUser: { env: 'INFRA_REPORT_SMTP_USER' },
46
+ infraReportSmtpPass: { env: 'INFRA_REPORT_SMTP_PASS' },
47
+ infraReportFrom: { env: 'INFRA_REPORT_FROM' },
48
+ infraReportTo: { env: 'INFRA_REPORT_TO' },
36
49
  }
37
50
  });
38
51
 
package/src/defaults.js CHANGED
@@ -10,12 +10,16 @@
10
10
  */
11
11
 
12
12
  module.exports = {
13
- redisHost: 'api_node_cache',
14
- redisPort: '6379',
15
- redisUrl: 'redis://api_node_cache:6379',
16
-
17
- rabbitmqUrl: 'amqp://guest:guest@api_services_queuer:5672',
18
13
  infrastructureHealthQueueName: 'infrastructure.health.checks',
14
+ infrastructureHealthPublishIntervalMs: 5000,
15
+ infrastructureHealthWaitMaxTimeMs: 300000,
16
+ infrastructureHealthWaitCheckIntervalMs: 5000,
17
+ infrastructureHealthTimeoutMs: 15000,
18
+ infrastructureHealthRedisTtlSeconds: 30,
19
+ infrastructureHealthCleanupIntervalMs: 10000,
20
+
21
+ infrastructureHealthQueueWaitMaxTimeMs: 60000,
22
+ infrastructureHealthQueueWaitCheckIntervalMs: 2000,
19
23
  };
20
24
 
21
25
 
package/src/index.js CHANGED
@@ -28,8 +28,6 @@ const {
28
28
  optionalNumberEnv,
29
29
  getCriticalConfig,
30
30
  getCriticalConfigWithFallbacks,
31
- getOptionalInfraConfig,
32
- getServiceConfig,
33
31
  getInfrastructureHealthConfig
34
32
  } = require('./runtime-config');
35
33
 
@@ -53,9 +51,7 @@ module.exports = {
53
51
  optionalEnv,
54
52
  optionalNumberEnv,
55
53
  getCriticalConfig,
56
- getCriticalConfigWithFallbacks, // EXCEPTION: Fallbacks allowed ONLY for infrastructure clients
57
- getOptionalInfraConfig,
58
- getServiceConfig,
54
+ getCriticalConfigWithFallbacks,
59
55
  getInfrastructureHealthConfig,
60
56
 
61
57
  // Reporting utilities
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { connectRedis, buildRedisUrl } = require('../redisClient');
4
+ const runtimeCfg = require('../config');
4
5
 
5
6
  /**
6
7
  * waitForHealthCheckQueueReady.js
@@ -33,11 +34,9 @@ const { connectRedis, buildRedisUrl } = require('../redisClient');
33
34
  * @throws {Error} - If timeout is reached
34
35
  */
35
36
  async function waitForHealthCheckQueueReady(options = {}) {
36
- const redisUrl =
37
- options.redisUrl ||
38
- buildRedisUrl({ env: process.env, defaults: { host: 'api_node_cache', port: '6379' } });
39
- const maxWait = options.maxWait || parseInt(process.env.INFRASTRUCTURE_HEALTH_QUEUE_WAIT_MAX_TIME) || 60000; // 1 minute
40
- const checkInterval = options.checkInterval || parseInt(process.env.INFRASTRUCTURE_HEALTH_QUEUE_WAIT_CHECK_INTERVAL) || 2000; // 2 seconds
37
+ const redisUrl = buildRedisUrl({ redisUrl: options.redisUrl });
38
+ const maxWait = runtimeCfg.get('infrastructureHealthQueueWaitMaxTimeMs', options.maxWait);
39
+ const checkInterval = runtimeCfg.get('infrastructureHealthQueueWaitCheckIntervalMs', options.checkInterval);
41
40
  const logger = options.logger || console;
42
41
 
43
42
  const log = (msg) => {
@@ -73,8 +72,7 @@ async function waitForHealthCheckQueueReady(options = {}) {
73
72
  }
74
73
  },
75
74
  timeoutMs: 10000,
76
- env: process.env,
77
- defaults: { host: 'api_node_cache', port: '6379' }
75
+ redisUrl
78
76
  });
79
77
  log('[HealthCheckQueueReady] Connected to Redis');
80
78
 
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { connectRedis, buildRedisUrl } = require('../redisClient');
4
+ const runtimeCfg = require('../config');
4
5
 
5
6
  /**
6
7
  * waitForInfrastructureReady.js
@@ -44,11 +45,9 @@ const { connectRedis, buildRedisUrl } = require('../redisClient');
44
45
  * Registry config (config.infrastructureHealth) is the source of truth for these defaults.
45
46
  */
46
47
  async function waitForInfrastructureReady(options = {}) {
47
- const redisUrl =
48
- options.redisUrl ||
49
- buildRedisUrl({ env: process.env, defaults: { host: 'api_node_cache', port: '6379' } });
50
- const maxWait = options.maxWait || parseInt(process.env.INFRASTRUCTURE_HEALTH_WAIT_MAX_TIME) || 300000; // 5 minutes
51
- const checkInterval = options.checkInterval || parseInt(process.env.INFRASTRUCTURE_HEALTH_WAIT_CHECK_INTERVAL) || 5000; // 5 seconds
48
+ const redisUrl = buildRedisUrl({ redisUrl: options.redisUrl });
49
+ const maxWait = runtimeCfg.get('infrastructureHealthWaitMaxTimeMs', options.maxWait);
50
+ const checkInterval = runtimeCfg.get('infrastructureHealthWaitCheckIntervalMs', options.checkInterval);
52
51
  const logger = options.logger || console;
53
52
 
54
53
  // Helper to log messages (compatible with both console and winston)
@@ -90,8 +89,7 @@ async function waitForInfrastructureReady(options = {}) {
90
89
  }
91
90
  },
92
91
  timeoutMs: 10000,
93
- env: process.env,
94
- defaults: { host: 'api_node_cache', port: '6379' }
92
+ redisUrl
95
93
  });
96
94
  log('[InfrastructureReady] Connected to Redis');
97
95
 
@@ -13,39 +13,38 @@
13
13
  */
14
14
 
15
15
  const { createClient } = require('redis');
16
- const DEFAULTS = require('./defaults');
16
+ const runtimeCfg = require('./config');
17
+ const { createRuntimeConfig } = require('@onlineapps/runtime-config');
17
18
 
18
19
  /**
19
20
  * Build a Redis connection URL from environment.
20
21
  *
21
- * EXCEPTION: Fallbacks are allowed ONLY for infrastructure client configuration.
22
- * This is the ONLY place where fallbacks are acceptable.
23
- *
24
- * Environment variable precedence (checked in order):
25
- * 1. REDIS_URL (full URL, e.g. redis://api_node_cache:6379) - ENV variable name
26
- * 2. REDIS_HOST + REDIS_PORT (if REDIS_URL not set)
27
- * 3. Fallback: redis://api_node_cache:6379 (docker-compose default)
22
+ * Strict rules:
23
+ * - No topology defaults (FAIL-FAST).
24
+ * - Priority: explicit redisUrl > env REDIS_URL.
28
25
  *
29
26
  * @param {Object} options - Options
30
- * @param {Object} [options.env=process.env] - Environment variables
31
- * @param {Object} [options.defaults] - Default host/port overrides
27
+ * @param {Object} [options.env] - Optional env override (tests/tools)
28
+ * @param {string} [options.redisUrl] - Explicit Redis URL override
32
29
  * @returns {string} Redis connection URL
33
30
  */
34
31
  function buildRedisUrl(options = {}) {
35
- const env = options.env || process.env || {};
36
- const defaults = options.defaults || {};
37
-
38
- // Priority 1: REDIS_URL from environment (ENV variable name: REDIS_URL)
39
- if (env.REDIS_URL && typeof env.REDIS_URL === 'string' && env.REDIS_URL.length > 0) {
40
- return env.REDIS_URL;
32
+ const { env, redisUrl } = options;
33
+
34
+ if (env) {
35
+ const cfg = createRuntimeConfig({
36
+ defaults: {},
37
+ env,
38
+ schema: {
39
+ redisUrl: { env: 'REDIS_URL', required: true },
40
+ },
41
+ });
42
+ return cfg.get('redisUrl', redisUrl);
41
43
  }
42
44
 
43
- // Priority 2: REDIS_HOST + REDIS_PORT (if REDIS_URL not set)
44
- // Fallback for docker-compose environment (defined in library, not in docker-compose.yml)
45
- const host = env.REDIS_HOST || defaults.host || DEFAULTS.redisHost;
46
- const port = env.REDIS_PORT || defaults.port || DEFAULTS.redisPort;
47
-
48
- return `redis://${host}:${port}`;
45
+ // Default env source is the runtime-config resolver's env (process.env),
46
+ // but we never access process.env directly here.
47
+ return runtimeCfg.get('redisUrl', redisUrl);
49
48
  }
50
49
 
51
50
  /**
@@ -65,10 +64,10 @@ function createRedisClient(options = {}) {
65
64
  forTests = false,
66
65
  logger = console,
67
66
  env,
68
- defaults
67
+ redisUrl
69
68
  } = options;
70
69
 
71
- const url = buildRedisUrl({ env, defaults });
70
+ const url = buildRedisUrl({ env, redisUrl });
72
71
 
73
72
  const socketOptions = forTests
74
73
  ? {
@@ -1,19 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  const nodemailer = require('nodemailer');
4
+ const runtimeCfg = require('../config');
4
5
 
5
6
  let transporter = null;
6
7
  let cachedConfigSignature = null;
7
8
 
8
9
  function loadConfig() {
9
10
  return {
10
- host: process.env.INFRA_REPORT_SMTP_HOST,
11
- port: process.env.INFRA_REPORT_SMTP_PORT ? parseInt(process.env.INFRA_REPORT_SMTP_PORT, 10) : undefined,
12
- secure: process.env.INFRA_REPORT_SMTP_SECURE === 'true',
13
- user: process.env.INFRA_REPORT_SMTP_USER,
14
- pass: process.env.INFRA_REPORT_SMTP_PASS,
15
- from: process.env.INFRA_REPORT_FROM,
16
- to: process.env.INFRA_REPORT_TO
11
+ host: runtimeCfg.get('infraReportSmtpHost'),
12
+ port: runtimeCfg.get('infraReportSmtpPort'),
13
+ secure: runtimeCfg.get('infraReportSmtpSecure'),
14
+ user: runtimeCfg.get('infraReportSmtpUser'),
15
+ pass: runtimeCfg.get('infraReportSmtpPass'),
16
+ from: runtimeCfg.get('infraReportFrom'),
17
+ to: runtimeCfg.get('infraReportTo')
17
18
  };
18
19
  }
19
20
 
@@ -2,35 +2,31 @@
2
2
 
3
3
  /**
4
4
  * Runtime Configuration Helper
5
- *
6
- * NO FALLBACKS for critical infrastructure connections.
7
- * Services must fail fast if critical config is missing.
8
- *
9
- * This ensures:
10
- * - Services don't silently connect to wrong infrastructure
11
- * - Configuration problems are detected immediately
12
- * - No hidden dependencies on hardcoded values
5
+ *
6
+ * Rules:
7
+ * - No inline process.env usage in implementation code (use runtime-config resolver).
8
+ * - No topology defaults (Redis/RabbitMQ URLs must be provided via explicit config or ENV).
9
+ * - Module-owned defaults are allowed only for non-topology behavior (intervals/timeouts).
13
10
  */
14
11
 
15
12
  const runtimeCfg = require('./config');
13
+ const { createRuntimeConfig } = require('@onlineapps/runtime-config');
16
14
 
17
15
  /**
18
- * Get required environment variable or throw error
19
- * @param {string} name - Environment variable name
20
- * @param {string} description - Description for error message
21
- * @returns {string} Environment variable value
22
- * @throws {Error} If variable is not set
16
+ * Resolve arbitrary environment variables through runtime-config (no direct process.env access).
17
+ * Note: Prefer module schema keys (runtimeCfg.get) over these generic helpers.
23
18
  */
24
19
  function requireEnv(name, description) {
25
- const value = process.env[name];
26
- if (!value || value.trim() === '') {
27
- throw new Error(
28
- `Service configuration error: ${name} is required but not set. ${description || ''}\n` +
29
- `Please set ${name} environment variable in .env file or environment.\n` +
30
- `Example: ${name}=value`
31
- );
20
+ const cfg = createRuntimeConfig({
21
+ defaults: {},
22
+ schema: { value: { env: name, required: true } },
23
+ });
24
+ try {
25
+ return cfg.get('value');
26
+ } catch (err) {
27
+ const hint = description ? ` ${description}` : '';
28
+ throw new Error(`[ServiceConfig] Missing environment variable - ${name} is required.${hint}`.trim());
32
29
  }
33
- return value;
34
30
  }
35
31
 
36
32
  /**
@@ -41,11 +37,11 @@ function requireEnv(name, description) {
41
37
  * @returns {any} Environment variable value or default
42
38
  */
43
39
  function optionalEnv(name, defaultValue) {
44
- const value = process.env[name];
45
- if (value === undefined || value === null || value === '') {
46
- return defaultValue;
47
- }
48
- return value;
40
+ const cfg = createRuntimeConfig({
41
+ defaults: {},
42
+ schema: { value: { env: name, default: defaultValue } },
43
+ });
44
+ return cfg.get('value');
49
45
  }
50
46
 
51
47
  /**
@@ -55,86 +51,36 @@ function optionalEnv(name, defaultValue) {
55
51
  * @returns {number} Parsed number or default
56
52
  */
57
53
  function optionalNumberEnv(name, defaultValue) {
58
- const value = process.env[name];
59
- if (!value || value.trim() === '') {
60
- return defaultValue;
61
- }
62
- const parsed = parseInt(value, 10);
63
- return Number.isFinite(parsed) ? parsed : defaultValue;
54
+ const cfg = createRuntimeConfig({
55
+ defaults: {},
56
+ schema: { value: { env: name, default: defaultValue, type: 'number' } },
57
+ });
58
+ return cfg.get('value');
64
59
  }
65
60
 
66
61
  /**
67
62
  * Get critical infrastructure configuration
68
- *
69
- * NOTE: This function is DEPRECATED - use getCriticalConfigWithFallbacks() instead.
70
- * This function requires ENV variables and fails fast (NO FALLBACKS).
71
- *
63
+ *
64
+ * This function is FAIL-FAST (NO FALLBACKS).
72
65
  * @returns {Object} Critical infrastructure config
73
66
  * @throws {Error} If REDIS_URL or RABBITMQ_URL are not set
74
67
  */
75
68
  function getCriticalConfig() {
76
69
  return {
77
- REDIS_URL: requireEnv('REDIS_URL', 'Redis connection URL (e.g., redis://api_node_cache:6379)'),
78
- RABBITMQ_URL: requireEnv('RABBITMQ_URL', 'RabbitMQ connection URL (e.g., amqp://guest:guest@api_services_queuer:5672)')
70
+ REDIS_URL: runtimeCfg.get('redisUrl'),
71
+ RABBITMQ_URL: runtimeCfg.get('rabbitmqUrl'),
79
72
  };
80
73
  }
81
74
 
82
75
  /**
83
76
  * Get critical infrastructure configuration with fallbacks
84
- *
85
- * EXCEPTION: Fallbacks are allowed ONLY for infrastructure client configuration.
86
- * This is the ONLY place where fallbacks are acceptable.
87
- *
88
- * Environment variables (checked in order):
89
- * - REDIS_URL: Full Redis URL (e.g., redis://api_node_cache:6379)
90
- * - RABBITMQ_URL: Full RabbitMQ URL (e.g., amqp://guest:guest@api_services_queuer:5672)
91
- *
92
- * Fallbacks (used only if ENV is not set):
93
- * - Redis: redis://api_node_cache:6379 (docker-compose default)
94
- * - RabbitMQ: amqp://guest:guest@api_services_queuer:5672 (docker-compose default)
95
- *
77
+ *
78
+ * Strict mode: This function is kept for compatibility but DOES NOT provide fallbacks.
79
+ * Topology is FAIL-FAST (no defaults).
96
80
  * @returns {Object} Critical infrastructure config with fallbacks
97
81
  */
98
82
  function getCriticalConfigWithFallbacks() {
99
- // Uses runtime-config for unified priority: ENV → owner defaults
100
- // Fallbacks are defined in ./defaults.js (module-owned)
101
- return {
102
- REDIS_URL: runtimeCfg.get('redisUrl'),
103
- RABBITMQ_URL: runtimeCfg.get('rabbitmqUrl')
104
- };
105
- }
106
-
107
- /**
108
- * Get optional infrastructure configuration
109
- * These have sensible defaults for development
110
- * @returns {Object} Optional infrastructure config
111
- */
112
- function getOptionalInfraConfig() {
113
- return {
114
- POSTGRES_URL: optionalEnv('POSTGRES_URL', null), // Optional - only for services that need it
115
- RABBITMQ_MGMT_URL: optionalEnv('RABBITMQ_MGMT_URL', null),
116
- RABBITMQ_DEFAULT_USER: optionalEnv('RABBITMQ_DEFAULT_USER', 'guest'),
117
- RABBITMQ_DEFAULT_PASS: optionalEnv('RABBITMQ_DEFAULT_PASS', 'guest'),
118
- RABBITMQ_VHOST: optionalEnv('RABBITMQ_VHOST', '/')
119
- };
120
- }
121
-
122
- /**
123
- * Get service configuration with defaults
124
- * @param {Object} options - Options
125
- * @param {string} [options.defaultPort] - Default port if PORT not set
126
- * @param {string} [options.defaultLogLevel] - Default log level
127
- * @returns {Object} Service config
128
- */
129
- function getServiceConfig(options = {}) {
130
- const { defaultPort = 3000, defaultLogLevel = 'info' } = options;
131
-
132
- return {
133
- PORT: optionalNumberEnv('PORT', defaultPort),
134
- LOG_LEVEL: optionalEnv('LOG_LEVEL', defaultLogLevel),
135
- SERVICE_NAME: optionalEnv('SERVICE_NAME', 'unknown-service'),
136
- NODE_ENV: optionalEnv('NODE_ENV', 'development')
137
- };
83
+ return getCriticalConfig();
138
84
  }
139
85
 
140
86
  /**
@@ -144,12 +90,14 @@ function getServiceConfig(options = {}) {
144
90
  function getInfrastructureHealthConfig() {
145
91
  return {
146
92
  queueName: runtimeCfg.get('infrastructureHealthQueueName'),
147
- publishInterval: optionalNumberEnv('INFRASTRUCTURE_HEALTH_PUBLISH_INTERVAL', 5000),
148
- waitMaxTime: optionalNumberEnv('INFRASTRUCTURE_HEALTH_WAIT_MAX_TIME', 300000),
149
- waitCheckInterval: optionalNumberEnv('INFRASTRUCTURE_HEALTH_WAIT_CHECK_INTERVAL', 5000),
150
- healthCheckTimeout: optionalNumberEnv('INFRASTRUCTURE_HEALTH_TIMEOUT', 15000),
151
- redisKeyTTL: optionalNumberEnv('INFRASTRUCTURE_HEALTH_REDIS_TTL', 30),
152
- cleanupInterval: optionalNumberEnv('INFRASTRUCTURE_HEALTH_CLEANUP_INTERVAL', 10000)
93
+ publishInterval: runtimeCfg.get('infrastructureHealthPublishIntervalMs'),
94
+ waitMaxTime: runtimeCfg.get('infrastructureHealthWaitMaxTimeMs'),
95
+ waitCheckInterval: runtimeCfg.get('infrastructureHealthWaitCheckIntervalMs'),
96
+ healthCheckTimeout: runtimeCfg.get('infrastructureHealthTimeoutMs'),
97
+ redisKeyTTL: runtimeCfg.get('infrastructureHealthRedisTtlSeconds'),
98
+ cleanupInterval: runtimeCfg.get('infrastructureHealthCleanupIntervalMs'),
99
+ queueWaitMaxTime: runtimeCfg.get('infrastructureHealthQueueWaitMaxTimeMs'),
100
+ queueWaitCheckInterval: runtimeCfg.get('infrastructureHealthQueueWaitCheckIntervalMs'),
153
101
  };
154
102
  }
155
103
 
@@ -159,8 +107,6 @@ module.exports = {
159
107
  optionalNumberEnv,
160
108
  getCriticalConfig,
161
109
  getCriticalConfigWithFallbacks,
162
- getOptionalInfraConfig,
163
- getServiceConfig,
164
110
  getInfrastructureHealthConfig
165
111
  };
166
112
 
@@ -6,20 +6,24 @@ const { buildRedisUrl } = require('../../src/redisClient');
6
6
 
7
7
  describe('@onlineapps/service-common defaults @unit', () => {
8
8
  test('should export stable module-owned defaults', () => {
9
- expect(defaults.redisUrl).toBe('redis://api_node_cache:6379');
10
- expect(defaults.rabbitmqUrl).toBe('amqp://guest:guest@api_services_queuer:5672');
11
9
  expect(defaults.infrastructureHealthQueueName).toBe('infrastructure.health.checks');
10
+ expect(defaults.infrastructureHealthPublishIntervalMs).toBe(5000);
11
+ expect(defaults.infrastructureHealthWaitMaxTimeMs).toBe(300000);
12
+ expect(defaults.infrastructureHealthWaitCheckIntervalMs).toBe(5000);
13
+ expect(defaults.infrastructureHealthTimeoutMs).toBe(15000);
14
+ expect(defaults.infrastructureHealthRedisTtlSeconds).toBe(30);
15
+ expect(defaults.infrastructureHealthCleanupIntervalMs).toBe(10000);
16
+ expect(defaults.infrastructureHealthQueueWaitMaxTimeMs).toBe(60000);
17
+ expect(defaults.infrastructureHealthQueueWaitCheckIntervalMs).toBe(2000);
12
18
  });
13
19
 
14
- test('getCriticalConfigWithFallbacks should use module defaults when env is missing', () => {
20
+ test('getCriticalConfigWithFallbacks should fail-fast when env is missing (no topology defaults)', () => {
15
21
  const oldRedis = process.env.REDIS_URL;
16
22
  const oldRabbit = process.env.RABBITMQ_URL;
17
23
  delete process.env.REDIS_URL;
18
24
  delete process.env.RABBITMQ_URL;
19
25
 
20
- const cfg = getCriticalConfigWithFallbacks();
21
- expect(cfg.REDIS_URL).toBe(defaults.redisUrl);
22
- expect(cfg.RABBITMQ_URL).toBe(defaults.rabbitmqUrl);
26
+ expect(() => getCriticalConfigWithFallbacks()).toThrow(/Missing required config/i);
23
27
 
24
28
  if (oldRedis !== undefined) process.env.REDIS_URL = oldRedis;
25
29
  if (oldRabbit !== undefined) process.env.RABBITMQ_URL = oldRabbit;
@@ -36,8 +40,7 @@ describe('@onlineapps/service-common defaults @unit', () => {
36
40
  });
37
41
 
38
42
  test('buildRedisUrl should fall back to module defaults host/port', () => {
39
- const url = buildRedisUrl({ env: {}, defaults: {} });
40
- expect(url).toBe(defaults.redisUrl);
43
+ expect(() => buildRedisUrl({ env: {}, defaults: {} })).toThrow(/Missing required config/i);
41
44
  });
42
45
  });
43
46
 
Binary file