@onlineapps/service-wrapper 2.0.21 → 2.0.22

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.
Files changed (33) hide show
  1. package/API.md +0 -0
  2. package/README.md +0 -0
  3. package/docs/CONFIGURATION_GUIDE.md +0 -0
  4. package/docs/FINAL_ARCHITECTURE.md +0 -0
  5. package/docs/MIGRATION_FROM_OPENAPI.md +0 -0
  6. package/docs/STANDARDS_OVERVIEW.md +0 -0
  7. package/docs/archived-2025-09-29/API_STRUCTURE_STANDARD.md +0 -0
  8. package/docs/archived-2025-09-29/ARCHITECTURE_DECISION.md +0 -0
  9. package/docs/archived-2025-09-29/HANDLER_VS_HTTP_COMPARISON.md +0 -0
  10. package/docs/archived-2025-09-29/INSTALLATION_GUIDE.md +0 -0
  11. package/docs/archived-2025-09-29/OPERATIONS_SCHEMA.md +0 -0
  12. package/docs/archived-2025-09-29/PERFORMANCE.md +0 -0
  13. package/docs/archived-2025-09-29/PROCESS_FLOWS.md +0 -0
  14. package/docs/archived-2025-09-29/SERVICE_TESTING_STANDARD.md +0 -0
  15. package/docs/archived-2025-09-29/WRAPPER_ARCHITECTURE.md +0 -0
  16. package/examples/README.md +0 -0
  17. package/examples/cookbook-file-output.json +0 -0
  18. package/examples/cookbook-multi-step.json +0 -0
  19. package/examples/cookbook-single-operation.json +0 -0
  20. package/jest.config.js +0 -0
  21. package/jsdoc.json +0 -0
  22. package/package.json +1 -1
  23. package/src/ServiceWrapper.js +110 -24
  24. package/src/index.js +0 -0
  25. package/tests/component/ServiceWrapper.component.test.js +0 -407
  26. package/tests/component/connector-integration.test.js +0 -293
  27. package/tests/e2e/full-flow.test.js +0 -293
  28. package/tests/integration/orchestrator-integration.test.js +0 -170
  29. package/tests/mocks/connectors.js +0 -304
  30. package/tests/monitoring-integration.test.js +0 -150
  31. package/tests/run-tests.js +0 -135
  32. package/tests/setup.js +0 -31
  33. package/tests/unit/ServiceWrapper.test.js +0 -372
@@ -1,293 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * End-to-End Integration Tests for ServiceWrapper
5
- * Tests the complete flow: MQ → ServiceWrapper → HTTP Service → Response
6
- */
7
-
8
- const ServiceWrapper = require('../../src/ServiceWrapper');
9
- const MQConnector = require('@onlineapps/conn-infra-mq');
10
- const express = require('express');
11
- const http = require('http');
12
-
13
- describe('ServiceWrapper E2E Tests @e2e', () => {
14
- let testService;
15
- let testServer;
16
- let serviceWrapper;
17
- let mqClient;
18
- let servicePort;
19
- const serviceName = 'test-service';
20
- const rabbitUrl = process.env.RABBITMQ_URL || 'amqp://guest:guest@localhost:33023';
21
-
22
- beforeAll(async () => {
23
- // 1. Create test HTTP service
24
- testService = express();
25
- testService.use(express.json());
26
-
27
- // Add test endpoints
28
- testService.post('/test/hello', (req, res) => {
29
- res.json({
30
- message: `Hello ${req.body.name}`,
31
- timestamp: new Date().toISOString()
32
- });
33
- });
34
-
35
- testService.post('/test/error', (req, res) => {
36
- res.status(500).json({ error: 'Test error' });
37
- });
38
-
39
- testService.get('/health', (req, res) => {
40
- res.json({ status: 'ok' });
41
- });
42
-
43
- // Start test service
44
- servicePort = 40000 + Math.floor(Math.random() * 1000);
45
- testServer = http.createServer(testService);
46
- await new Promise(resolve => {
47
- testServer.listen(servicePort, resolve);
48
- });
49
-
50
- // 2. Create OpenAPI spec
51
- const openApiSpec = {
52
- openapi: '3.0.0',
53
- info: {
54
- title: 'Test Service',
55
- version: '1.0.0'
56
- },
57
- paths: {
58
- '/test/hello': {
59
- post: {
60
- operationId: 'sayHello',
61
- requestBody: {
62
- content: {
63
- 'application/json': {
64
- schema: {
65
- type: 'object',
66
- properties: {
67
- name: { type: 'string' }
68
- }
69
- }
70
- }
71
- }
72
- }
73
- }
74
- },
75
- '/test/error': {
76
- post: {
77
- operationId: 'triggerError'
78
- }
79
- }
80
- }
81
- };
82
-
83
- // 3. Initialize ServiceWrapper
84
- serviceWrapper = new ServiceWrapper({
85
- serviceUrl: `http://localhost:${servicePort}`,
86
- serviceName,
87
- openApiSpec,
88
- config: {
89
- rabbitmq: rabbitUrl,
90
- heartbeatInterval: 60000, // Long interval for tests
91
- directCall: false // Force HTTP calls
92
- }
93
- });
94
-
95
- // 4. Initialize MQ client for sending test messages
96
- mqClient = new MQConnector({
97
- type: 'rabbitmq',
98
- host: rabbitUrl,
99
- queue: `${serviceName}.workflow`,
100
- durable: true
101
- });
102
- await mqClient.connect();
103
-
104
- // 5. Start wrapper (with timeout for registration)
105
- await serviceWrapper.start();
106
- }, 60000); // 60s timeout for setup
107
-
108
- afterAll(async () => {
109
- // Cleanup
110
- if (serviceWrapper) {
111
- await serviceWrapper.stop();
112
- }
113
- if (mqClient) {
114
- await mqClient.disconnect();
115
- }
116
- if (testServer) {
117
- await new Promise(resolve => testServer.close(resolve));
118
- }
119
- });
120
-
121
- describe('Basic Message Flow', () => {
122
- test('should process simple workflow message', async () => {
123
- const testMessage = {
124
- workflow_id: 'test-workflow-1',
125
- current_step: {
126
- service: serviceName,
127
- operation: 'sayHello',
128
- input: {
129
- name: 'World'
130
- }
131
- }
132
- };
133
-
134
- // Send message to queue
135
- await mqClient.publish(testMessage);
136
-
137
- // Wait for processing
138
- await new Promise(resolve => setTimeout(resolve, 2000));
139
-
140
- // Verify by checking service logs or response queue
141
- // Note: In real test, we'd capture response through response queue
142
- expect(true).toBe(true); // Placeholder
143
- });
144
-
145
- test('should handle error responses', async () => {
146
- const testMessage = {
147
- workflow_id: 'test-workflow-2',
148
- current_step: {
149
- service: serviceName,
150
- operation: 'triggerError',
151
- input: {}
152
- }
153
- };
154
-
155
- await mqClient.publish(testMessage);
156
- await new Promise(resolve => setTimeout(resolve, 2000));
157
-
158
- // Verify error handling
159
- expect(true).toBe(true); // Placeholder
160
- });
161
- });
162
-
163
- describe('Workflow Orchestration', () => {
164
- test('should process multi-step workflow', async () => {
165
- const workflow = {
166
- workflow_id: 'multi-step-1',
167
- steps: [
168
- {
169
- service: serviceName,
170
- operation: 'sayHello',
171
- input: { name: 'Step1' }
172
- },
173
- {
174
- service: serviceName,
175
- operation: 'sayHello',
176
- input: { name: 'Step2' }
177
- }
178
- ],
179
- current_step: {
180
- service: serviceName,
181
- operation: 'sayHello',
182
- input: { name: 'Step1' }
183
- }
184
- };
185
-
186
- await mqClient.publish(workflow);
187
- await new Promise(resolve => setTimeout(resolve, 3000));
188
-
189
- expect(true).toBe(true); // Placeholder
190
- });
191
- });
192
-
193
- describe('Error Handling & Recovery', () => {
194
- test('should retry on transient failures', async () => {
195
- // Test retry logic
196
- const testMessage = {
197
- workflow_id: 'retry-test-1',
198
- current_step: {
199
- service: serviceName,
200
- operation: 'triggerError',
201
- input: {},
202
- retry_count: 0,
203
- max_retries: 3
204
- }
205
- };
206
-
207
- await mqClient.publish(testMessage);
208
- await new Promise(resolve => setTimeout(resolve, 5000));
209
-
210
- // Verify retries occurred
211
- expect(true).toBe(true); // Placeholder
212
- });
213
-
214
- test('should handle circuit breaker', async () => {
215
- // Send multiple failing requests to trigger circuit breaker
216
- for (let i = 0; i < 5; i++) {
217
- await mqClient.publish({
218
- workflow_id: `circuit-test-${i}`,
219
- current_step: {
220
- service: serviceName,
221
- operation: 'triggerError',
222
- input: {}
223
- }
224
- });
225
- }
226
-
227
- await new Promise(resolve => setTimeout(resolve, 3000));
228
-
229
- // Verify circuit breaker activated
230
- expect(true).toBe(true); // Placeholder
231
- });
232
- });
233
-
234
- describe('Performance & Load Testing', () => {
235
- test('should handle concurrent messages', async () => {
236
- const messages = [];
237
- for (let i = 0; i < 10; i++) {
238
- messages.push({
239
- workflow_id: `concurrent-${i}`,
240
- current_step: {
241
- service: serviceName,
242
- operation: 'sayHello',
243
- input: { name: `User${i}` }
244
- }
245
- });
246
- }
247
-
248
- // Send all messages concurrently
249
- await Promise.all(messages.map(msg => mqClient.publish(msg)));
250
-
251
- // Wait for all to process
252
- await new Promise(resolve => setTimeout(resolve, 5000));
253
-
254
- expect(true).toBe(true); // Placeholder
255
- });
256
-
257
- test('should respect prefetch limit', async () => {
258
- // Send more messages than prefetch limit
259
- const messages = [];
260
- for (let i = 0; i < 20; i++) {
261
- messages.push({
262
- workflow_id: `prefetch-${i}`,
263
- current_step: {
264
- service: serviceName,
265
- operation: 'sayHello',
266
- input: { name: `Batch${i}` }
267
- }
268
- });
269
- }
270
-
271
- await Promise.all(messages.map(msg => mqClient.publish(msg)));
272
- await new Promise(resolve => setTimeout(resolve, 10000));
273
-
274
- // Verify prefetch was respected
275
- expect(true).toBe(true); // Placeholder
276
- });
277
- });
278
-
279
- describe('Registry Integration', () => {
280
- test('should register service on startup', () => {
281
- // Verify service was registered
282
- expect(serviceWrapper.isRunning).toBe(true);
283
- });
284
-
285
- test('should send heartbeats', async () => {
286
- // Wait for at least one heartbeat
287
- await new Promise(resolve => setTimeout(resolve, 5000));
288
-
289
- // Verify heartbeat was sent (check logs or registry)
290
- expect(true).toBe(true); // Placeholder
291
- });
292
- });
293
- });
@@ -1,170 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * Integration test for ServiceWrapper with OrchestratorConnector
6
- * Tests that the thin orchestration layer properly delegates to orchestrator
7
- */
8
-
9
- const path = require('path');
10
-
11
- // Mock setup
12
- const Module = require('module');
13
- const originalRequire = Module.prototype.require;
14
-
15
- // Create test doubles
16
- const testDoubles = {
17
- processWorkflowMessage: null,
18
- lastMessage: null,
19
- lastServiceName: null
20
- };
21
-
22
- Module.prototype.require = function(id) {
23
- switch(id) {
24
- case '@onlineapps/conn-infra-mq':
25
- return class MockMQ {
26
- constructor() { this.connected = false; }
27
- async connect() { this.connected = true; }
28
- async disconnect() { this.connected = false; }
29
- async consume(handler) { this.handler = handler; }
30
- isConnected() { return this.connected; }
31
- };
32
-
33
- case '@onlineapps/conn-orch-registry':
34
- return {
35
- ServiceRegistryClient: class {
36
- async register() { return true; }
37
- async unregister() { return true; }
38
- async sendHeartbeat() { return true; }
39
- isConnected() { return true; }
40
- }
41
- };
42
-
43
- case '@onlineapps/conn-base-logger':
44
- return {
45
- create: () => ({
46
- info: () => {},
47
- error: () => {},
48
- warn: () => {},
49
- debug: () => {}
50
- })
51
- };
52
-
53
- case '@onlineapps/conn-orch-orchestrator':
54
- return {
55
- create: (options) => ({
56
- processWorkflowMessage: async (message, serviceName) => {
57
- testDoubles.lastMessage = message;
58
- testDoubles.lastServiceName = serviceName;
59
- testDoubles.processWorkflowMessage = true;
60
- return { processed: true };
61
- }
62
- })
63
- };
64
-
65
- case '@onlineapps/conn-orch-api-mapper':
66
- return { create: () => ({ map: () => {} }) };
67
-
68
- case '@onlineapps/conn-orch-cookbook':
69
- return { validateCookbook: () => true };
70
-
71
- case '@onlineapps/conn-base-cache':
72
- return class {
73
- async connect() {}
74
- async disconnect() {}
75
- };
76
-
77
- case '@onlineapps/conn-infra-error-handler':
78
- return class {
79
- constructor() {}
80
- };
81
-
82
- default:
83
- return originalRequire.apply(this, arguments);
84
- }
85
- };
86
-
87
- // Run test
88
- async function testOrchestratorIntegration() {
89
- console.log('=== Orchestrator Integration Test ===\n');
90
-
91
- try {
92
- // Load ServiceWrapper with mocked dependencies
93
- const ServiceWrapper = require('../../src/ServiceWrapper');
94
-
95
- // Create instance
96
- const wrapper = new ServiceWrapper({
97
- service: function expressApp() {},
98
- serviceName: 'test-service',
99
- openApiSpec: {
100
- openapi: '3.0.0',
101
- info: { version: '1.0.0' },
102
- paths: {}
103
- },
104
- config: {}
105
- });
106
-
107
- // Start wrapper
108
- await wrapper.start();
109
- console.log('✓ ServiceWrapper started');
110
-
111
- // Get MQ client handler
112
- const mqClient = wrapper.mqClient;
113
- if (!mqClient.handler) {
114
- throw new Error('No message handler registered');
115
- }
116
-
117
- // Simulate workflow message
118
- const testMessage = {
119
- workflow_id: 'wf-123',
120
- current_step: {
121
- id: 'step-1',
122
- service: 'test-service',
123
- operation: 'testOp',
124
- input: { data: 'test' }
125
- },
126
- context: {
127
- variables: {},
128
- results: {}
129
- }
130
- };
131
-
132
- // Process message through the handler
133
- console.log('Sending test message to handler...');
134
- await mqClient.handler(testMessage);
135
-
136
- // Verify orchestrator was called
137
- if (testDoubles.processWorkflowMessage) {
138
- console.log('✓ Orchestrator.processWorkflowMessage was called');
139
- console.log('✓ Message passed:', JSON.stringify(testDoubles.lastMessage, null, 2));
140
- console.log('✓ Service name passed:', testDoubles.lastServiceName);
141
-
142
- // Verify correct delegation
143
- if (testDoubles.lastMessage === testMessage &&
144
- testDoubles.lastServiceName === 'test-service') {
145
- console.log('✓ Message and service name correctly delegated');
146
- } else {
147
- console.log('✗ Incorrect delegation parameters');
148
- }
149
- } else {
150
- console.log('✗ Orchestrator.processWorkflowMessage was NOT called');
151
- }
152
-
153
- // Stop wrapper
154
- await wrapper.stop();
155
- console.log('✓ ServiceWrapper stopped');
156
-
157
- console.log('\n=== Test Result ===');
158
- console.log('✅ Orchestrator integration working correctly!');
159
- console.log('ServiceWrapper properly delegates workflow messages to orchestrator.');
160
-
161
- } catch (error) {
162
- console.error('\n=== Test Failed ===');
163
- console.error('✗ Error:', error.message);
164
- console.error('Stack:', error.stack);
165
- process.exit(1);
166
- }
167
- }
168
-
169
- // Run the test
170
- testOrchestratorIntegration();