@onlineapps/infrastructure-tools 1.0.0 → 1.0.2

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/infrastructure-tools",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Infrastructure orchestration utilities for OA Drive infrastructure services (health tracking, queue initialization, service discovery)",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -42,13 +42,30 @@ async function waitForInfrastructureReady(options = {}) {
42
42
  const checkInterval = options.checkInterval || parseInt(process.env.INFRASTRUCTURE_HEALTH_WAIT_CHECK_INTERVAL) || 5000; // 5 seconds
43
43
  const logger = options.logger || console;
44
44
 
45
+ // Universal logger adapter (supports both console and winston)
46
+ // Winston logger expects object with message property, console.log accepts string
47
+ const log = (message) => {
48
+ if (typeof logger.info === 'function' && typeof logger.log !== 'function') {
49
+ // Likely winston logger - use object format
50
+ logger.info({ message: String(message) });
51
+ } else if (typeof logger.log === 'function') {
52
+ // console.log or similar
53
+ logger.log(message);
54
+ } else if (typeof logger.info === 'function') {
55
+ // Fallback for other loggers
56
+ logger.info(message);
57
+ } else {
58
+ console.log(message);
59
+ }
60
+ };
61
+
45
62
  const startTime = Date.now();
46
63
  let attemptCount = 0;
47
64
  let redis = null;
48
65
 
49
- logger.log('[InfrastructureReady] Waiting for all infrastructure services to be ready...');
50
- logger.log(`[InfrastructureReady] Redis URL: ${redisUrl}`);
51
- logger.log(`[InfrastructureReady] Max wait: ${maxWait}ms, Check interval: ${checkInterval}ms`);
66
+ log('[InfrastructureReady] Waiting for all infrastructure services to be ready...');
67
+ log(`[InfrastructureReady] Redis URL: ${redisUrl}`);
68
+ log(`[InfrastructureReady] Max wait: ${maxWait}ms, Check interval: ${checkInterval}ms`);
52
69
 
53
70
  try {
54
71
  // Connect to Redis
@@ -56,11 +73,11 @@ async function waitForInfrastructureReady(options = {}) {
56
73
  redis = createClient({ url: redisUrl });
57
74
 
58
75
  redis.on('error', (err) => {
59
- logger.log(`[InfrastructureReady] Redis error: ${err.message}`);
76
+ log(`[InfrastructureReady] Redis error: ${err.message}`);
60
77
  });
61
78
 
62
79
  await redis.connect();
63
- logger.log('[InfrastructureReady] Connected to Redis');
80
+ log('[InfrastructureReady] Connected to Redis');
64
81
 
65
82
  while (Date.now() - startTime < maxWait) {
66
83
  attemptCount++;
@@ -72,7 +89,7 @@ async function waitForInfrastructureReady(options = {}) {
72
89
  if (allHealthy === 'true') {
73
90
  // All services are UP, we can proceed
74
91
  const elapsed = Date.now() - startTime;
75
- logger.log(`[InfrastructureReady] ✓ All infrastructure services are ready (took ${elapsed}ms, ${attemptCount} attempts)`);
92
+ log(`[InfrastructureReady] ✓ All infrastructure services are ready (took ${elapsed}ms, ${attemptCount} attempts)`);
76
93
 
77
94
  // Optionally log individual service status
78
95
  // Note: Service names should match config.infrastructureServices in Registry
@@ -84,19 +101,19 @@ async function waitForInfrastructureReady(options = {}) {
84
101
  statuses[serviceName] = JSON.parse(status);
85
102
  }
86
103
  }
87
- logger.log(`[InfrastructureReady] Infrastructure status:`, JSON.stringify(statuses, null, 2));
104
+ log(`[InfrastructureReady] Infrastructure status: ${JSON.stringify(statuses, null, 2)}`);
88
105
 
89
106
  return true;
90
107
  }
91
108
 
92
109
  // Not all services ready yet
93
- logger.log(`[InfrastructureReady] Attempt ${attemptCount}: Not all services ready (allHealthy: ${allHealthy || 'null'})`);
94
- logger.log(`[InfrastructureReady] Waiting ${checkInterval}ms before next check...`);
110
+ log(`[InfrastructureReady] Attempt ${attemptCount}: Not all services ready (allHealthy: ${allHealthy || 'null'})`);
111
+ log(`[InfrastructureReady] Waiting ${checkInterval}ms before next check...`);
95
112
 
96
113
  } catch (error) {
97
114
  // Redis might not be ready yet, or connection issue
98
- logger.log(`[InfrastructureReady] Attempt ${attemptCount}: Redis check failed (${error.message})`);
99
- logger.log(`[InfrastructureReady] Waiting ${checkInterval}ms before retry...`);
115
+ log(`[InfrastructureReady] Attempt ${attemptCount}: Redis check failed (${error.message})`);
116
+ log(`[InfrastructureReady] Waiting ${checkInterval}ms before retry...`);
100
117
  }
101
118
 
102
119
  // Wait before next check
@@ -114,7 +131,7 @@ async function waitForInfrastructureReady(options = {}) {
114
131
  // Clean up Redis connection
115
132
  if (redis && redis.isReady) {
116
133
  await redis.quit();
117
- logger.log('[InfrastructureReady] Redis connection closed');
134
+ log('[InfrastructureReady] Redis connection closed');
118
135
  }
119
136
  }
120
137
  }
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Integration test for infrastructure-tools
6
+ * Tests all components: healthPublisher, waitForInfrastructureReady, initInfrastructureQueues
7
+ */
8
+
9
+ const {
10
+ createHealthPublisher,
11
+ createBaseClientAdapter,
12
+ createAmqplibAdapter,
13
+ waitForInfrastructureReady,
14
+ initInfrastructureQueues
15
+ } = require('./src/index');
16
+
17
+ console.log('🧪 Testing @onlineapps/infrastructure-tools\n');
18
+
19
+ // Test 1: Check exports
20
+ console.log('Test 1: Checking exports...');
21
+ const exportTypes = {
22
+ createHealthPublisher: typeof createHealthPublisher,
23
+ createBaseClientAdapter: typeof createBaseClientAdapter,
24
+ createAmqplibAdapter: typeof createAmqplibAdapter,
25
+ waitForInfrastructureReady: typeof waitForInfrastructureReady,
26
+ initInfrastructureQueues: typeof initInfrastructureQueues
27
+ };
28
+
29
+ let allExportsOk = true;
30
+ for (const [name, type] of Object.entries(exportTypes)) {
31
+ if (type !== 'function') {
32
+ console.error(` ✗ ${name} is not a function (got ${type})`);
33
+ allExportsOk = false;
34
+ } else {
35
+ console.log(` ✓ ${name} is a function`);
36
+ }
37
+ }
38
+
39
+ if (!allExportsOk) {
40
+ console.error('\n❌ Export test failed');
41
+ process.exit(1);
42
+ }
43
+
44
+ console.log('✓ All exports are functions\n');
45
+
46
+ // Test 2: Test createHealthPublisher with mock
47
+ async function testHealthPublisher() {
48
+ console.log('Test 2: Testing createHealthPublisher with mock publish function...');
49
+ let publishedMessages = [];
50
+ const mockPublish = async (queueName, data) => {
51
+ publishedMessages.push({ queueName, data, timestamp: new Date().toISOString() });
52
+ };
53
+
54
+ const mockGetHealthData = () => ({
55
+ mq: 'healthy',
56
+ redis: 'healthy',
57
+ http: 'healthy'
58
+ });
59
+
60
+ try {
61
+ const publisher = createHealthPublisher({
62
+ serviceName: 'test-service',
63
+ version: '1.0.0',
64
+ publishFunction: mockPublish,
65
+ getHealthData: mockGetHealthData,
66
+ config: {
67
+ queueName: 'test.health.checks',
68
+ publishInterval: 100
69
+ },
70
+ logger: {
71
+ log: () => {},
72
+ warn: () => {},
73
+ error: () => {},
74
+ debug: () => {},
75
+ info: () => {}
76
+ }
77
+ });
78
+
79
+ // Test immediate publish
80
+ await publisher.publishNow();
81
+ if (publishedMessages.length !== 1) {
82
+ throw new Error(`Expected 1 published message, got ${publishedMessages.length}`);
83
+ }
84
+ if (publishedMessages[0].data.serviceName !== 'test-service') {
85
+ throw new Error(`Expected serviceName 'test-service', got '${publishedMessages[0].data.serviceName}'`);
86
+ }
87
+ console.log(' ✓ publishNow() works');
88
+
89
+ // Test start/stop
90
+ await publisher.start();
91
+ await new Promise(resolve => setTimeout(resolve, 250)); // Wait for 2 intervals
92
+ publisher.stop();
93
+
94
+ if (publishedMessages.length < 2) {
95
+ throw new Error(`Expected at least 2 published messages, got ${publishedMessages.length}`);
96
+ }
97
+ console.log(' ✓ start/stop works');
98
+ console.log(` ✓ Published ${publishedMessages.length} messages total`);
99
+
100
+ console.log('✓ createHealthPublisher test passed\n');
101
+ } catch (error) {
102
+ console.error(` ✗ createHealthPublisher test failed: ${error.message}`);
103
+ throw error;
104
+ }
105
+ }
106
+
107
+ // Test 3: Test waitForInfrastructureReady (mock Redis)
108
+ console.log('Test 3: Testing waitForInfrastructureReady with mock Redis...');
109
+ // This test would require Redis connection, so we'll just check that function exists
110
+ if (typeof waitForInfrastructureReady === 'function') {
111
+ console.log(' ✓ waitForInfrastructureReady is a function');
112
+ } else {
113
+ console.error(` ✗ waitForInfrastructureReady is not a function`);
114
+ process.exit(1);
115
+ }
116
+ console.log(' ⚠ Skipping actual Redis test (requires Redis connection)\n');
117
+
118
+ // Test 4: Test initInfrastructureQueues (mock channel)
119
+ console.log('Test 4: Testing initInfrastructureQueues with mock channel...');
120
+ // This test would require RabbitMQ connection, so we'll just check that function exists
121
+ if (typeof initInfrastructureQueues === 'function') {
122
+ console.log(' ✓ initInfrastructureQueues is a function');
123
+ } else {
124
+ console.error(` ✗ initInfrastructureQueues is not a function`);
125
+ process.exit(1);
126
+ }
127
+ console.log(' ⚠ Skipping actual RabbitMQ test (requires RabbitMQ connection)\n');
128
+
129
+ // Run async tests
130
+ (async () => {
131
+ try {
132
+ await testHealthPublisher();
133
+
134
+ console.log('✅ All tests passed!');
135
+ console.log('\nNote: Full integration tests require:');
136
+ console.log(' - Redis connection (for waitForInfrastructureReady)');
137
+ console.log(' - RabbitMQ connection (for initInfrastructureQueues)');
138
+ console.log(' - Running infrastructure services (for end-to-end testing)');
139
+ } catch (error) {
140
+ console.error('\n❌ Tests failed:', error.message);
141
+ process.exit(1);
142
+ }
143
+ })();
144
+