@onlineapps/infrastructure-tools 1.0.0 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/infrastructure-tools",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
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,24 @@ 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
+ const log = (message) => {
47
+ if (typeof logger.info === 'function') {
48
+ logger.info(message);
49
+ } else if (typeof logger.log === 'function') {
50
+ logger.log(message);
51
+ } else {
52
+ console.log(message);
53
+ }
54
+ };
55
+
45
56
  const startTime = Date.now();
46
57
  let attemptCount = 0;
47
58
  let redis = null;
48
59
 
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`);
60
+ log('[InfrastructureReady] Waiting for all infrastructure services to be ready...');
61
+ log(`[InfrastructureReady] Redis URL: ${redisUrl}`);
62
+ log(`[InfrastructureReady] Max wait: ${maxWait}ms, Check interval: ${checkInterval}ms`);
52
63
 
53
64
  try {
54
65
  // Connect to Redis
@@ -56,11 +67,11 @@ async function waitForInfrastructureReady(options = {}) {
56
67
  redis = createClient({ url: redisUrl });
57
68
 
58
69
  redis.on('error', (err) => {
59
- logger.log(`[InfrastructureReady] Redis error: ${err.message}`);
70
+ log(`[InfrastructureReady] Redis error: ${err.message}`);
60
71
  });
61
72
 
62
73
  await redis.connect();
63
- logger.log('[InfrastructureReady] Connected to Redis');
74
+ log('[InfrastructureReady] Connected to Redis');
64
75
 
65
76
  while (Date.now() - startTime < maxWait) {
66
77
  attemptCount++;
@@ -72,7 +83,7 @@ async function waitForInfrastructureReady(options = {}) {
72
83
  if (allHealthy === 'true') {
73
84
  // All services are UP, we can proceed
74
85
  const elapsed = Date.now() - startTime;
75
- logger.log(`[InfrastructureReady] ✓ All infrastructure services are ready (took ${elapsed}ms, ${attemptCount} attempts)`);
86
+ log(`[InfrastructureReady] ✓ All infrastructure services are ready (took ${elapsed}ms, ${attemptCount} attempts)`);
76
87
 
77
88
  // Optionally log individual service status
78
89
  // Note: Service names should match config.infrastructureServices in Registry
@@ -84,19 +95,19 @@ async function waitForInfrastructureReady(options = {}) {
84
95
  statuses[serviceName] = JSON.parse(status);
85
96
  }
86
97
  }
87
- logger.log(`[InfrastructureReady] Infrastructure status:`, JSON.stringify(statuses, null, 2));
98
+ log(`[InfrastructureReady] Infrastructure status: ${JSON.stringify(statuses, null, 2)}`);
88
99
 
89
100
  return true;
90
101
  }
91
102
 
92
103
  // 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...`);
104
+ log(`[InfrastructureReady] Attempt ${attemptCount}: Not all services ready (allHealthy: ${allHealthy || 'null'})`);
105
+ log(`[InfrastructureReady] Waiting ${checkInterval}ms before next check...`);
95
106
 
96
107
  } catch (error) {
97
108
  // 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...`);
109
+ log(`[InfrastructureReady] Attempt ${attemptCount}: Redis check failed (${error.message})`);
110
+ log(`[InfrastructureReady] Waiting ${checkInterval}ms before retry...`);
100
111
  }
101
112
 
102
113
  // Wait before next check
@@ -114,7 +125,7 @@ async function waitForInfrastructureReady(options = {}) {
114
125
  // Clean up Redis connection
115
126
  if (redis && redis.isReady) {
116
127
  await redis.quit();
117
- logger.log('[InfrastructureReady] Redis connection closed');
128
+ log('[InfrastructureReady] Redis connection closed');
118
129
  }
119
130
  }
120
131
  }
@@ -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
+