@onlineapps/service-wrapper 2.0.20 → 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 +120 -25
  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,304 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Mock connectors for unit testing
5
- * These mocks allow us to test ServiceWrapper in isolation
6
- */
7
-
8
- // Mock MQ Connector
9
- class MockMQConnector {
10
- constructor(config) {
11
- this.config = config;
12
- this.connected = false;
13
- this.consumers = new Map();
14
- this.publishedMessages = [];
15
- }
16
-
17
- async connect() {
18
- this.connected = true;
19
- return Promise.resolve();
20
- }
21
-
22
- async disconnect() {
23
- this.connected = false;
24
- return Promise.resolve();
25
- }
26
-
27
- isConnected() {
28
- return this.connected;
29
- }
30
-
31
- async consume(handler, options) {
32
- this.consumers.set(options.queue, handler);
33
- return Promise.resolve();
34
- }
35
-
36
- async publish(queue, message) {
37
- this.publishedMessages.push({ queue, message });
38
- return Promise.resolve();
39
- }
40
-
41
- // Test helper - simulate message arrival
42
- async simulateMessage(queue, message) {
43
- const handler = this.consumers.get(queue);
44
- if (handler) {
45
- await handler(message);
46
- }
47
- }
48
- }
49
-
50
- // Mock Registry Connector
51
- class MockServiceRegistryClient {
52
- constructor(config) {
53
- this.config = config;
54
- this.registeredServices = new Map();
55
- this.heartbeats = [];
56
- this.connected = true;
57
- }
58
-
59
- async register(serviceInfo) {
60
- this.registeredServices.set(serviceInfo.name, serviceInfo);
61
- return Promise.resolve();
62
- }
63
-
64
- async unregister(serviceName) {
65
- this.registeredServices.delete(serviceName);
66
- return Promise.resolve();
67
- }
68
-
69
- async sendHeartbeat(serviceName) {
70
- this.heartbeats.push({ service: serviceName, timestamp: Date.now() });
71
- return Promise.resolve();
72
- }
73
-
74
- isConnected() {
75
- return this.connected;
76
- }
77
- }
78
-
79
- // Mock Logger Connector
80
- class MockLogger {
81
- constructor(serviceName) {
82
- this.serviceName = serviceName;
83
- this.logs = [];
84
- }
85
-
86
- _log(level, message, meta) {
87
- this.logs.push({ level, message, meta, timestamp: Date.now() });
88
- }
89
-
90
- info(message, meta) {
91
- this._log('info', message, meta);
92
- }
93
-
94
- warn(message, meta) {
95
- this._log('warn', message, meta);
96
- }
97
-
98
- error(message, meta) {
99
- this._log('error', message, meta);
100
- }
101
-
102
- debug(message, meta) {
103
- this._log('debug', message, meta);
104
- }
105
-
106
- // Test helper
107
- getLogsByLevel(level) {
108
- return this.logs.filter(log => log.level === level);
109
- }
110
- }
111
-
112
- // Add static create method to the class itself and as a property
113
- MockLogger.create = function(serviceName) {
114
- return new MockLogger(serviceName);
115
- };
116
-
117
- // Mock Orchestrator Connector
118
- class MockWorkflowOrchestrator {
119
- constructor(config) {
120
- this.config = config;
121
- this.processedMessages = [];
122
- this.shouldFail = false;
123
- }
124
-
125
- async processWorkflowMessage(message, serviceName) {
126
- this.processedMessages.push({ message, serviceName });
127
-
128
- if (this.shouldFail) {
129
- throw new Error('Mock processing failure');
130
- }
131
-
132
- return {
133
- success: true,
134
- workflow_id: message.workflow_id,
135
- step_id: message.current_step,
136
- result: { mocked: true }
137
- };
138
- }
139
-
140
- // Test helper - make next processing fail
141
- setNextProcessingToFail(shouldFail = true) {
142
- this.shouldFail = shouldFail;
143
- }
144
- }
145
-
146
- const MockOrchestratorConnector = {
147
- create: (config) => new MockWorkflowOrchestrator(config)
148
- };
149
-
150
- // Mock API Mapper Connector
151
- class MockApiMapper {
152
- constructor(config) {
153
- this.config = config;
154
- this.operations = new Map();
155
- }
156
-
157
- async callOperation(operationId, input, context) {
158
- return {
159
- operationId,
160
- input,
161
- context,
162
- result: 'mocked'
163
- };
164
- }
165
- }
166
-
167
- const MockApiMapperConnector = {
168
- create: (config) => new MockApiMapper(config)
169
- };
170
-
171
- // Mock Cookbook Connector
172
- const MockCookbookConnector = {
173
- validateCookbook: (cookbook) => {
174
- if (!cookbook || !cookbook.steps) {
175
- throw new Error('Invalid cookbook');
176
- }
177
- return true;
178
- },
179
-
180
- createRouter: (mqClient, registryClient, options) => {
181
- return {
182
- routeToService: async (service, message) => {
183
- return Promise.resolve();
184
- },
185
- routeToDLQ: async (cookbook, context, error, service) => {
186
- return Promise.resolve();
187
- }
188
- };
189
- },
190
-
191
- CookbookExecutor: class {
192
- constructor(cookbook, options) {
193
- this.cookbook = cookbook;
194
- this.options = options;
195
- this.context = {
196
- setInput: (input) => {},
197
- data: { steps: {} }
198
- };
199
- }
200
-
201
- async executeStep(step) {
202
- return { executed: step.id };
203
- }
204
- },
205
-
206
- CookbookGenerator: class {
207
- constructor(options) {
208
- this.options = options;
209
- }
210
-
211
- generate(openApiSpec) {
212
- return { generated: true };
213
- }
214
- },
215
-
216
- ResponseMapper: class {
217
- mapResponse(response, mapping) {
218
- return response;
219
- }
220
- }
221
- };
222
-
223
- /**
224
- * MockCacheConnector - Simulates cache connector
225
- */
226
- class MockCacheConnector {
227
- constructor(options = {}) {
228
- this.options = options;
229
- this.connected = false;
230
- }
231
-
232
- async connect() {
233
- this.connected = true;
234
- return Promise.resolve();
235
- }
236
-
237
- async disconnect() {
238
- this.connected = false;
239
- return Promise.resolve();
240
- }
241
-
242
- async get(key) {
243
- return null;
244
- }
245
-
246
- async set(key, value, ttl) {
247
- return 'OK';
248
- }
249
-
250
- async del(key) {
251
- return 1;
252
- }
253
-
254
- isConnected() {
255
- return this.connected;
256
- }
257
- }
258
-
259
- /**
260
- * MockErrorHandlerConnector - Simulates error handler
261
- */
262
- class MockErrorHandlerConnector {
263
- constructor(options = {}) {
264
- this.maxRetries = options.maxRetries || 3;
265
- this.retryDelay = options.retryDelay || 1000;
266
- this.logger = options.logger;
267
- }
268
-
269
- async executeWithRetry(fn, context = {}) {
270
- try {
271
- return await fn();
272
- } catch (error) {
273
- if (this.logger) {
274
- this.logger.error('Error in executeWithRetry', { error: error.message });
275
- }
276
- throw error;
277
- }
278
- }
279
-
280
- handleError(error, context = {}) {
281
- if (this.logger) {
282
- this.logger.error('Handling error', { error: error.message, context });
283
- }
284
- return {
285
- error: error.message,
286
- retry: false
287
- };
288
- }
289
-
290
- isRetryableError(error) {
291
- return error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT';
292
- }
293
- }
294
-
295
- module.exports = {
296
- MockMQConnector,
297
- MockServiceRegistryClient,
298
- MockLogger,
299
- MockOrchestratorConnector,
300
- MockApiMapperConnector,
301
- MockCookbookConnector,
302
- MockCacheConnector,
303
- MockErrorHandlerConnector
304
- };
@@ -1,150 +0,0 @@
1
- /**
2
- * Test monitoring integration in service-wrapper
3
- */
4
-
5
- describe('ServiceWrapper Monitoring Integration @integration', () => {
6
- let ServiceWrapper;
7
- let express;
8
-
9
- beforeEach(() => {
10
- // Reset modules
11
- jest.resetModules();
12
-
13
- // Mock dependencies
14
- jest.mock('@onlineapps/conn-infra-mq', () => {
15
- return jest.fn().mockImplementation(() => ({
16
- connect: jest.fn().mockResolvedValue(true),
17
- disconnect: jest.fn().mockResolvedValue(true),
18
- consume: jest.fn().mockResolvedValue(true),
19
- isConnected: jest.fn().mockReturnValue(true)
20
- }));
21
- });
22
-
23
- jest.mock('@onlineapps/conn-orch-registry', () => ({
24
- ServiceRegistryClient: jest.fn().mockImplementation(() => ({
25
- register: jest.fn().mockResolvedValue(true),
26
- unregister: jest.fn().mockResolvedValue(true),
27
- sendHeartbeat: jest.fn().mockResolvedValue(true),
28
- isConnected: jest.fn().mockReturnValue(true)
29
- }))
30
- }));
31
-
32
- jest.mock('@onlineapps/conn-base-monitoring', () => ({
33
- init: jest.fn().mockResolvedValue({
34
- info: jest.fn(),
35
- warn: jest.fn(),
36
- error: jest.fn(),
37
- debug: jest.fn()
38
- }),
39
- info: jest.fn(),
40
- warn: jest.fn(),
41
- error: jest.fn(),
42
- debug: jest.fn()
43
- }));
44
-
45
- jest.mock('@onlineapps/conn-orch-orchestrator', () => ({
46
- create: jest.fn().mockReturnValue({
47
- processWorkflowMessage: jest.fn().mockResolvedValue({ success: true })
48
- })
49
- }));
50
-
51
- jest.mock('@onlineapps/conn-orch-api-mapper', () => ({
52
- create: jest.fn().mockReturnValue({})
53
- }));
54
-
55
- jest.mock('@onlineapps/conn-orch-cookbook', () => ({}));
56
- jest.mock('@onlineapps/conn-base-cache', () => jest.fn());
57
- jest.mock('@onlineapps/conn-infra-error-handler', () => jest.fn());
58
-
59
- ServiceWrapper = require('../src/ServiceWrapper');
60
- express = require('express');
61
- });
62
-
63
- test('should initialize monitoring on start', async () => {
64
- const app = express();
65
- const monitoring = require('@onlineapps/conn-base-monitoring');
66
-
67
- const wrapper = new ServiceWrapper({
68
- service: app,
69
- serviceName: 'test-service',
70
- openApiSpec: { info: { version: '1.0.0' } },
71
- config: {}
72
- });
73
-
74
- await wrapper.start();
75
-
76
- expect(monitoring.init).toHaveBeenCalledWith({
77
- serviceName: 'test-service'
78
- });
79
-
80
- expect(wrapper.logger).toBeDefined();
81
- expect(wrapper.monitoring).toBeDefined();
82
- });
83
-
84
- test('should use monitoring for logging', async () => {
85
- const app = express();
86
- const wrapper = new ServiceWrapper({
87
- service: app,
88
- serviceName: 'test-service',
89
- openApiSpec: { info: { version: '1.0.0' } },
90
- config: {}
91
- });
92
-
93
- await wrapper.start();
94
-
95
- // Test logger methods are available
96
- expect(wrapper.logger.info).toBeDefined();
97
- expect(wrapper.logger.error).toBeDefined();
98
- expect(wrapper.logger.warn).toBeDefined();
99
- expect(wrapper.logger.debug).toBeDefined();
100
-
101
- // Test logger is used
102
- wrapper.logger.info('Test message', { data: 'test' });
103
- wrapper.logger.error('Error message', { error: 'test' });
104
- });
105
-
106
- test('should pass monitoring to orchestrator', async () => {
107
- const app = express();
108
- const OrchestratorConnector = require('@onlineapps/conn-orch-orchestrator');
109
-
110
- const wrapper = new ServiceWrapper({
111
- service: app,
112
- serviceName: 'test-service',
113
- openApiSpec: { info: { version: '1.0.0' } },
114
- config: {}
115
- });
116
-
117
- await wrapper.start();
118
-
119
- expect(OrchestratorConnector.create).toHaveBeenCalledWith(
120
- expect.objectContaining({
121
- logger: expect.objectContaining({
122
- info: expect.any(Function),
123
- error: expect.any(Function),
124
- warn: expect.any(Function),
125
- debug: expect.any(Function)
126
- })
127
- })
128
- );
129
- });
130
-
131
- test('should handle monitoring mode from config', async () => {
132
- const app = express();
133
- const monitoring = require('@onlineapps/conn-base-monitoring');
134
-
135
- const wrapper = new ServiceWrapper({
136
- service: app,
137
- serviceName: 'test-service',
138
- openApiSpec: { info: { version: '1.0.0' } },
139
- config: {
140
- monitoringMode: 'debug'
141
- }
142
- });
143
-
144
- await wrapper.start();
145
-
146
- // Monitoring should be initialized but mode is not passed
147
- // because ServiceWrapper doesn't pass it through yet
148
- expect(monitoring.init).toHaveBeenCalled();
149
- });
150
- });
@@ -1,135 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * Test runner that uses mocked dependencies
6
- * Allows us to test service-wrapper without actual connectors
7
- */
8
-
9
- const path = require('path');
10
-
11
- // Setup module aliases for mocked connectors
12
- const mocks = require('./mocks/connectors');
13
-
14
- const Module = require('module');
15
- const originalRequire = Module.prototype.require;
16
-
17
- Module.prototype.require = function(id) {
18
- // Intercept connector imports and return appropriate mocks
19
- switch(id) {
20
- case '@onlineapps/conn-infra-mq':
21
- return mocks.MockMQConnector;
22
- case '@onlineapps/conn-orch-registry':
23
- return { ServiceRegistryClient: mocks.MockServiceRegistryClient };
24
- case '@onlineapps/conn-base-logger':
25
- return mocks.MockLogger;
26
- case '@onlineapps/conn-orch-orchestrator':
27
- return mocks.MockOrchestratorConnector;
28
- case '@onlineapps/conn-orch-api-mapper':
29
- return mocks.MockApiMapperConnector;
30
- case '@onlineapps/conn-orch-cookbook':
31
- return mocks.MockCookbookConnector;
32
- case '@onlineapps/conn-base-cache':
33
- return mocks.MockCacheConnector;
34
- case '@onlineapps/conn-infra-error-handler':
35
- return mocks.MockErrorHandlerConnector;
36
- default:
37
- return originalRequire.apply(this, arguments);
38
- }
39
- };
40
-
41
- // Now we can test the ServiceWrapper with mocked dependencies
42
- console.log('Testing ServiceWrapper with mocked connectors...\n');
43
-
44
- // Test 1: Basic instantiation
45
- try {
46
- const ServiceWrapper = require('../src/ServiceWrapper');
47
- const wrapper = new ServiceWrapper({
48
- service: function() {},
49
- serviceName: 'test-service',
50
- openApiSpec: { openapi: '3.0.0', paths: {} }
51
- });
52
- console.log('✓ ServiceWrapper instantiation works');
53
- } catch (error) {
54
- console.log('✗ ServiceWrapper instantiation failed:', error.message);
55
- }
56
-
57
- // Test 2: Check what connectors are imported
58
- try {
59
- const ServiceWrapper = require('../src/ServiceWrapper');
60
- console.log('✓ All connector imports resolved');
61
- } catch (error) {
62
- console.log('✗ Failed to import connectors:', error.message);
63
- }
64
-
65
- // Test 3: Test start/stop lifecycle
66
- async function testLifecycle() {
67
- try {
68
- const ServiceWrapper = require('../src/ServiceWrapper');
69
- const wrapper = new ServiceWrapper({
70
- service: function() {},
71
- serviceName: 'test-service',
72
- openApiSpec: { openapi: '3.0.0', paths: {} }
73
- });
74
-
75
- await wrapper.start();
76
- console.log('✓ ServiceWrapper.start() works');
77
-
78
- const status = wrapper.getStatus();
79
- console.log('✓ ServiceWrapper.getStatus() returns:', status);
80
-
81
- await wrapper.stop();
82
- console.log('✓ ServiceWrapper.stop() works');
83
- } catch (error) {
84
- console.log('✗ Lifecycle test failed:', error.message);
85
- }
86
- }
87
-
88
- // Test 4: Check for missing functionality
89
- function checkMissingFunctionality() {
90
- console.log('\n=== Missing Functionality Check ===');
91
-
92
- const missing = [];
93
-
94
- // Check for cache connector
95
- try {
96
- require('@onlineapps/conn-base-cache');
97
- } catch (e) {
98
- missing.push('conn-base-cache');
99
- }
100
-
101
- // Check for error handler
102
- try {
103
- require('@onlineapps/conn-infra-error-handler');
104
- } catch (e) {
105
- missing.push('conn-infra-error-handler');
106
- }
107
-
108
- // Check cookbook connector exports
109
- const cookbook = require('./mocks/connectors').MockCookbookConnector;
110
- const requiredExports = ['validateCookbook', 'createRouter', 'CookbookExecutor', 'CookbookGenerator', 'ResponseMapper'];
111
- const missingExports = requiredExports.filter(exp => !cookbook[exp]);
112
-
113
- if (missingExports.length > 0) {
114
- missing.push(`cookbook missing: ${missingExports.join(', ')}`);
115
- }
116
-
117
- if (missing.length > 0) {
118
- console.log('Missing connectors/functionality:');
119
- missing.forEach(m => console.log(` - ${m}`));
120
- } else {
121
- console.log('All required functionality is available (mocked)');
122
- }
123
- }
124
-
125
- // Run tests
126
- testLifecycle().then(() => {
127
- checkMissingFunctionality();
128
- console.log('\n=== Test Summary ===');
129
- console.log('Service-wrapper is working as a thin orchestration layer!');
130
- console.log('Next steps:');
131
- console.log('1. Implement conn-base-cache connector');
132
- console.log('2. Implement conn-infra-error-handler connector');
133
- console.log('3. Fix cookbook connector exports');
134
- console.log('4. Test with real connectors');
135
- });
package/tests/setup.js DELETED
@@ -1,31 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Jest setup file
5
- * Configure test environment
6
- */
7
-
8
- // Set test environment variables
9
- process.env.NODE_ENV = 'test';
10
- process.env.LOG_LEVEL = 'error'; // Reduce noise during tests
11
-
12
- // Global test timeout
13
- jest.setTimeout(10000);
14
-
15
- // Mock timers for tests that need them
16
- global.mockTimers = () => {
17
- jest.useFakeTimers();
18
- };
19
-
20
- global.restoreTimers = () => {
21
- jest.useRealTimers();
22
- };
23
-
24
- // Helper to wait for async operations
25
- global.waitForAsync = () => new Promise(resolve => setImmediate(resolve));
26
-
27
- // Suppress console errors in tests unless debugging
28
- if (!process.env.DEBUG_TESTS) {
29
- global.console.error = jest.fn();
30
- global.console.warn = jest.fn();
31
- }