@app-connect/core 0.0.2 → 1.5.8
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/.env.test +5 -0
- package/README.md +175 -8
- package/adapter/registry.js +137 -5
- package/handlers/log.js +4 -3
- package/index.js +5 -3
- package/jest.config.js +57 -0
- package/lib/callLogComposer.js +98 -64
- package/lib/constants.js +9 -0
- package/lib/oauth.js +60 -23
- package/package.json +7 -1
- package/releaseNotes.json +28 -0
- package/test/adapter/registry.test.js +271 -0
- package/test/handlers/auth.test.js +231 -0
- package/test/lib/jwt.test.js +161 -0
- package/test/setup.js +176 -0
package/.env.test
ADDED
package/README.md
CHANGED
|
@@ -24,9 +24,14 @@ npm install @app-connect/core
|
|
|
24
24
|
|
|
25
25
|
```javascript
|
|
26
26
|
const { createCoreApp, adapterRegistry } = require('@app-connect/core');
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const myCRMAdapter = require('./adapters/myCRM');
|
|
28
|
+
const manifest = require('./adapters/manifest.json');
|
|
29
|
+
// Set the default manifest for the adapter registry. This ensures that all adapters
|
|
30
|
+
// have access to the necessary configuration and metadata before registration.
|
|
31
|
+
adapterRegistry.setDefaultManifest(manifest);
|
|
32
|
+
// Register your CRM adapters. The default manifest must be set before registration
|
|
33
|
+
// to ensure proper initialization of the adapter with the required settings.
|
|
34
|
+
adapterRegistry.registerAdapter('myCRM', myCRMAdapter, manifest);
|
|
30
35
|
|
|
31
36
|
// Create Express app with all core functionality
|
|
32
37
|
const app = createCoreApp();
|
|
@@ -39,6 +44,69 @@ app.get('/my-custom-route', (req, res) => {
|
|
|
39
44
|
exports.getServer = () => app;
|
|
40
45
|
```
|
|
41
46
|
|
|
47
|
+
### Adapter Interface Registration
|
|
48
|
+
|
|
49
|
+
The adapter registry supports dynamic interface registration, allowing you to extend adapter functionality without modifying the original adapter:
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
const { adapterRegistry } = require('@app-connect/core');
|
|
53
|
+
|
|
54
|
+
// Register interface functions for a platform
|
|
55
|
+
async function customCreateCallLog({ user, contactInfo, authHeader, callLog, note }) {
|
|
56
|
+
// Custom implementation
|
|
57
|
+
return {
|
|
58
|
+
logId: 'custom-log-id',
|
|
59
|
+
returnMessage: {
|
|
60
|
+
message: 'Call logged with custom implementation',
|
|
61
|
+
messageType: 'success',
|
|
62
|
+
ttl: 2000
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function customFindContact({ user, authHeader, phoneNumber }) {
|
|
68
|
+
// Custom implementation
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
id: 'custom-contact-id',
|
|
72
|
+
name: 'Custom Contact',
|
|
73
|
+
type: 'Contact',
|
|
74
|
+
phone: phoneNumber,
|
|
75
|
+
additionalInfo: null
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Register interface functions
|
|
81
|
+
adapterRegistry.registerAdapterInterface('myCRM', 'createCallLog', customCreateCallLog);
|
|
82
|
+
adapterRegistry.registerAdapterInterface('myCRM', 'findContact', customFindContact);
|
|
83
|
+
|
|
84
|
+
// Register the base adapter
|
|
85
|
+
adapterRegistry.registerAdapter('myCRM', myCRMAdapter);
|
|
86
|
+
|
|
87
|
+
// Get composed adapter with interfaces
|
|
88
|
+
const composedAdapter = adapterRegistry.getAdapter('myCRM');
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Interface-Only Adapters (No Base Adapter):**
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
// Register only interface functions, no base adapter
|
|
95
|
+
adapterRegistry.registerAdapterInterface('interfaceOnlyCRM', 'createCallLog', customCreateCallLog);
|
|
96
|
+
adapterRegistry.registerAdapterInterface('interfaceOnlyCRM', 'findContact', customFindContact);
|
|
97
|
+
|
|
98
|
+
// Get interface-only adapter
|
|
99
|
+
const interfaceOnlyAdapter = adapterRegistry.getAdapter('interfaceOnlyCRM');
|
|
100
|
+
console.log('Interface-only methods:', Object.keys(interfaceOnlyAdapter));
|
|
101
|
+
// Output: ['createCallLog', 'findContact']
|
|
102
|
+
|
|
103
|
+
// Later, you can add a base adapter
|
|
104
|
+
adapterRegistry.registerAdapter('interfaceOnlyCRM', myCRMAdapter);
|
|
105
|
+
const fullAdapter = adapterRegistry.getAdapter('interfaceOnlyCRM');
|
|
106
|
+
console.log('Full adapter methods:', Object.keys(fullAdapter));
|
|
107
|
+
// Output: ['getAuthType', 'getUserInfo', 'updateCallLog', 'unAuthorize', 'createContact', 'createCallLog', 'findContact']
|
|
108
|
+
```
|
|
109
|
+
|
|
42
110
|
### Advanced Usage with Custom Middleware
|
|
43
111
|
|
|
44
112
|
```javascript
|
|
@@ -50,8 +118,12 @@ const {
|
|
|
50
118
|
adapterRegistry
|
|
51
119
|
} = require('@app-connect/core');
|
|
52
120
|
|
|
121
|
+
const myCRMAdapter = require('./adapters/myCRM');
|
|
122
|
+
const manifest = require('./adapters/manifest.json');
|
|
123
|
+
// Set manifest
|
|
124
|
+
adapterRegistry.setDefaultManifest(manifest);
|
|
53
125
|
// Register adapters
|
|
54
|
-
adapterRegistry.registerAdapter('myCRM', myCRMAdapter);
|
|
126
|
+
adapterRegistry.registerAdapter('myCRM', myCRMAdapter, manifest);
|
|
55
127
|
|
|
56
128
|
// Initialize core services
|
|
57
129
|
initializeCore();
|
|
@@ -125,13 +197,84 @@ Registers a CRM adapter.
|
|
|
125
197
|
- `adapter` (Object): Adapter implementation
|
|
126
198
|
- `manifest` (Object, optional): Adapter manifest
|
|
127
199
|
|
|
200
|
+
#### `adapterRegistry.registerAdapterInterface(platformName, interfaceName, interfaceFunction)`
|
|
201
|
+
Registers an interface function for a specific platform that will be composed with the adapter at retrieval time.
|
|
202
|
+
|
|
203
|
+
**Parameters:**
|
|
204
|
+
- `platformName` (String): Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
205
|
+
- `interfaceName` (String): Interface function name (e.g., 'createCallLog', 'findContact')
|
|
206
|
+
- `interfaceFunction` (Function): The interface function to register
|
|
207
|
+
|
|
208
|
+
**Example:**
|
|
209
|
+
```javascript
|
|
210
|
+
async function customCreateCallLog({ user, contactInfo, authHeader, callLog, note }) {
|
|
211
|
+
// Custom implementation
|
|
212
|
+
return {
|
|
213
|
+
logId: 'custom-log-id',
|
|
214
|
+
returnMessage: {
|
|
215
|
+
message: 'Call logged with custom implementation',
|
|
216
|
+
messageType: 'success',
|
|
217
|
+
ttl: 2000
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
adapterRegistry.registerAdapterInterface('myCRM', 'createCallLog', customCreateCallLog);
|
|
223
|
+
```
|
|
224
|
+
|
|
128
225
|
#### `adapterRegistry.getAdapter(name)`
|
|
129
|
-
Retrieves a registered adapter.
|
|
226
|
+
Retrieves a registered adapter with composed interfaces.
|
|
130
227
|
|
|
131
228
|
**Parameters:**
|
|
132
229
|
- `name` (String): Adapter name
|
|
133
230
|
|
|
134
|
-
**Returns:**
|
|
231
|
+
**Returns:** Composed adapter object or interface-only object
|
|
232
|
+
|
|
233
|
+
**Behavior:**
|
|
234
|
+
- If adapter exists and interfaces exist: Returns composed adapter with both
|
|
235
|
+
- If adapter exists but no interfaces: Returns original adapter
|
|
236
|
+
- If no adapter but interfaces exist: Returns object with just interface functions
|
|
237
|
+
- If no adapter and no interfaces: Throws error
|
|
238
|
+
|
|
239
|
+
#### `adapterRegistry.getOriginalAdapter(name)`
|
|
240
|
+
Retrieves the original adapter without any composed interface functions.
|
|
241
|
+
|
|
242
|
+
**Parameters:**
|
|
243
|
+
- `name` (String): Adapter name
|
|
244
|
+
|
|
245
|
+
**Returns:** Original adapter object
|
|
246
|
+
|
|
247
|
+
#### `adapterRegistry.getPlatformInterfaces(platformName)`
|
|
248
|
+
Returns a Map of registered interface functions for a platform.
|
|
249
|
+
|
|
250
|
+
**Parameters:**
|
|
251
|
+
- `platformName` (String): Platform identifier
|
|
252
|
+
|
|
253
|
+
**Returns:** Map of interface functions
|
|
254
|
+
|
|
255
|
+
#### `adapterRegistry.hasPlatformInterface(platformName, interfaceName)`
|
|
256
|
+
Checks if a specific interface function is registered for a platform.
|
|
257
|
+
|
|
258
|
+
**Parameters:**
|
|
259
|
+
- `platformName` (String): Platform identifier
|
|
260
|
+
- `interfaceName` (String): Interface function name
|
|
261
|
+
|
|
262
|
+
**Returns:** Boolean indicating if interface exists
|
|
263
|
+
|
|
264
|
+
#### `adapterRegistry.unregisterAdapterInterface(platformName, interfaceName)`
|
|
265
|
+
Unregisters an interface function for a platform.
|
|
266
|
+
|
|
267
|
+
**Parameters:**
|
|
268
|
+
- `platformName` (String): Platform identifier
|
|
269
|
+
- `interfaceName` (String): Interface function name
|
|
270
|
+
|
|
271
|
+
#### `adapterRegistry.getAdapterCapabilities(platformName)`
|
|
272
|
+
Gets comprehensive information about an adapter including its capabilities and registered interfaces.
|
|
273
|
+
|
|
274
|
+
**Parameters:**
|
|
275
|
+
- `platformName` (String): Platform identifier
|
|
276
|
+
|
|
277
|
+
**Returns:** Object with adapter capabilities information
|
|
135
278
|
|
|
136
279
|
### Exported Components
|
|
137
280
|
|
|
@@ -234,9 +377,33 @@ The core package uses the following environment variables:
|
|
|
234
377
|
- `IS_PROD` - Production environment flag
|
|
235
378
|
- `DYNAMODB_LOCALHOST` - Local DynamoDB endpoint for development, used for lock cache
|
|
236
379
|
|
|
237
|
-
##
|
|
380
|
+
## Adapter Interface Registration Benefits
|
|
381
|
+
|
|
382
|
+
### Key Features
|
|
238
383
|
|
|
239
|
-
|
|
384
|
+
- **Composition over Mutation**: Interface functions are composed with adapters at retrieval time, preserving the original adapter
|
|
385
|
+
- **Dynamic Registration**: Register interface functions before or after adapter registration
|
|
386
|
+
- **Immutability**: Original adapter objects remain unchanged
|
|
387
|
+
- **Clean Separation**: Interface functions are kept separate from core adapter logic
|
|
388
|
+
- **Flexibility**: Support for interface-only adapters (no base adapter required)
|
|
389
|
+
|
|
390
|
+
### Best Practices
|
|
391
|
+
|
|
392
|
+
1. **Register Required Interfaces**: Register all required interface functions before using the adapter
|
|
393
|
+
2. **Use Descriptive Names**: Use clear, descriptive names for interface functions
|
|
394
|
+
3. **Handle Errors**: Implement proper error handling in interface functions
|
|
395
|
+
4. **Test Composed Adapters**: Test the final composed adapter to ensure interfaces work correctly
|
|
396
|
+
5. **Document Interfaces**: Document what each interface function does and expects
|
|
397
|
+
|
|
398
|
+
### Use Cases
|
|
399
|
+
|
|
400
|
+
- **Extending Existing Adapters**: Add new functionality to existing adapters without modification
|
|
401
|
+
- **Progressive Enhancement**: Start with interfaces, add base adapter later
|
|
402
|
+
- **Testing**: Test interface functions separately from base adapters
|
|
403
|
+
- **Modular Development**: Develop interface functions independently
|
|
404
|
+
- **Plugin Architecture**: Create pluggable interface functions for different scenarios
|
|
405
|
+
|
|
406
|
+
## Architecture
|
|
240
407
|
|
|
241
408
|
```
|
|
242
409
|
Core Package
|
package/adapter/registry.js
CHANGED
|
@@ -4,12 +4,67 @@ class AdapterRegistry {
|
|
|
4
4
|
this.adapters = new Map();
|
|
5
5
|
this.manifests = new Map();
|
|
6
6
|
this.releaseNotes = {};
|
|
7
|
+
this.platformInterfaces = new Map(); // Store interface functions per platform
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
setDefaultManifest(manifest) {
|
|
10
11
|
this.manifests.set('default', manifest);
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Register an interface function for a specific platform
|
|
16
|
+
* @param {string} platformName - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
17
|
+
* @param {string} interfaceName - Interface function name (e.g., 'createCallLog', 'findContact')
|
|
18
|
+
* @param {Function} interfaceFunction - The interface function to register
|
|
19
|
+
*/
|
|
20
|
+
registerAdapterInterface(platformName, interfaceName, interfaceFunction) {
|
|
21
|
+
if (typeof interfaceFunction !== 'function') {
|
|
22
|
+
throw new Error(`Interface function must be a function, got: ${typeof interfaceFunction}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!this.platformInterfaces.has(platformName)) {
|
|
26
|
+
this.platformInterfaces.set(platformName, new Map());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
30
|
+
platformInterfaceMap.set(interfaceName, interfaceFunction);
|
|
31
|
+
|
|
32
|
+
console.log(`Registered interface function: ${platformName}.${interfaceName}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get registered interface functions for a platform
|
|
37
|
+
* @param {string} platformName - Platform identifier
|
|
38
|
+
* @returns {Map} Map of interface functions
|
|
39
|
+
*/
|
|
40
|
+
getPlatformInterfaces(platformName) {
|
|
41
|
+
return this.platformInterfaces.get(platformName) || new Map();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Check if an interface function is registered for a platform
|
|
46
|
+
* @param {string} platformName - Platform identifier
|
|
47
|
+
* @param {string} interfaceName - Interface function name
|
|
48
|
+
* @returns {boolean} True if interface is registered
|
|
49
|
+
*/
|
|
50
|
+
hasPlatformInterface(platformName, interfaceName) {
|
|
51
|
+
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
52
|
+
return platformInterfaceMap ? platformInterfaceMap.has(interfaceName) : false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Unregister an interface function for a platform
|
|
57
|
+
* @param {string} platformName - Platform identifier
|
|
58
|
+
* @param {string} interfaceName - Interface function name
|
|
59
|
+
*/
|
|
60
|
+
unregisterAdapterInterface(platformName, interfaceName) {
|
|
61
|
+
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
62
|
+
if (platformInterfaceMap && platformInterfaceMap.has(interfaceName)) {
|
|
63
|
+
platformInterfaceMap.delete(interfaceName);
|
|
64
|
+
console.log(`Unregistered interface function: ${platformName}.${interfaceName}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
13
68
|
/**
|
|
14
69
|
* Register an adapter with the core system
|
|
15
70
|
* @param {string} platform - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
@@ -29,16 +84,62 @@ class AdapterRegistry {
|
|
|
29
84
|
}
|
|
30
85
|
|
|
31
86
|
/**
|
|
32
|
-
* Get adapter by platform name
|
|
87
|
+
* Get adapter by platform name with composed interfaces
|
|
33
88
|
* @param {string} platform - Platform identifier
|
|
34
|
-
* @returns {Object}
|
|
89
|
+
* @returns {Object} Composed adapter with interface functions
|
|
35
90
|
*/
|
|
36
91
|
getAdapter(platform) {
|
|
37
92
|
const adapter = this.adapters.get(platform);
|
|
38
|
-
|
|
93
|
+
const platformInterfaceMap = this.platformInterfaces.get(platform);
|
|
94
|
+
|
|
95
|
+
// If no adapter and no interfaces, throw error
|
|
96
|
+
if (!adapter && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
39
97
|
throw new Error(`Adapter not found for platform: ${platform}`);
|
|
40
98
|
}
|
|
41
|
-
|
|
99
|
+
|
|
100
|
+
// If no adapter but interfaces exist, create a composed object with just interfaces
|
|
101
|
+
if (!adapter && platformInterfaceMap && platformInterfaceMap.size > 0) {
|
|
102
|
+
const composedAdapter = {};
|
|
103
|
+
|
|
104
|
+
// Add interface functions to the composed adapter
|
|
105
|
+
for (const [interfaceName, interfaceFunction] of platformInterfaceMap) {
|
|
106
|
+
composedAdapter[interfaceName] = interfaceFunction;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log(`Returning interface-only adapter for platform: ${platform}`);
|
|
110
|
+
return composedAdapter;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// If adapter exists but no interfaces, return original adapter
|
|
114
|
+
if (adapter && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
115
|
+
return adapter;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// If both adapter and interfaces exist, create a composed object
|
|
119
|
+
const composedAdapter = Object.create(adapter);
|
|
120
|
+
|
|
121
|
+
// Add interface functions to the composed adapter
|
|
122
|
+
for (const [interfaceName, interfaceFunction] of platformInterfaceMap) {
|
|
123
|
+
// Only add if the interface doesn't already exist in the adapter
|
|
124
|
+
if (!Object.prototype.hasOwnProperty.call(adapter, interfaceName)) {
|
|
125
|
+
composedAdapter[interfaceName] = interfaceFunction;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return composedAdapter;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get the original adapter without composed interfaces
|
|
134
|
+
* @param {string} platform - Platform identifier
|
|
135
|
+
* @returns {Object} Original adapter implementation
|
|
136
|
+
*/
|
|
137
|
+
getOriginalAdapter(platform) {
|
|
138
|
+
const adapter = this.adapters.get(platform);
|
|
139
|
+
if (!adapter) {
|
|
140
|
+
throw new Error(`Adapter not found for platform: ${platform}`);
|
|
141
|
+
}
|
|
142
|
+
return adapter;
|
|
42
143
|
}
|
|
43
144
|
|
|
44
145
|
/**
|
|
@@ -98,6 +199,7 @@ class AdapterRegistry {
|
|
|
98
199
|
unregisterAdapter(platform) {
|
|
99
200
|
this.adapters.delete(platform);
|
|
100
201
|
this.manifests.delete(platform);
|
|
202
|
+
this.platformInterfaces.delete(platform);
|
|
101
203
|
console.log(`Unregistered adapter: ${platform}`);
|
|
102
204
|
}
|
|
103
205
|
|
|
@@ -108,8 +210,38 @@ class AdapterRegistry {
|
|
|
108
210
|
getReleaseNotes(platform) {
|
|
109
211
|
return this.releaseNotes;
|
|
110
212
|
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get adapter capabilities summary including composed interfaces
|
|
216
|
+
* @param {string} platform - Platform identifier
|
|
217
|
+
* @returns {Object} Adapter capabilities
|
|
218
|
+
*/
|
|
219
|
+
getAdapterCapabilities(platform) {
|
|
220
|
+
const originalAdapter = this.getOriginalAdapter(platform);
|
|
221
|
+
const composedAdapter = this.getAdapter(platform);
|
|
222
|
+
const platformInterfaceMap = this.getPlatformInterfaces(platform);
|
|
223
|
+
|
|
224
|
+
const capabilities = {
|
|
225
|
+
platform,
|
|
226
|
+
originalMethods: Object.keys(originalAdapter),
|
|
227
|
+
composedMethods: Object.keys(composedAdapter),
|
|
228
|
+
registeredInterfaces: Array.from(platformInterfaceMap.keys()),
|
|
229
|
+
authType: null
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Get auth type if available
|
|
233
|
+
if (typeof originalAdapter.getAuthType === 'function') {
|
|
234
|
+
try {
|
|
235
|
+
capabilities.authType = originalAdapter.getAuthType();
|
|
236
|
+
} catch (error) {
|
|
237
|
+
capabilities.authType = 'unknown';
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return capabilities;
|
|
242
|
+
}
|
|
111
243
|
}
|
|
112
244
|
|
|
113
245
|
// Export singleton instance
|
|
114
246
|
const adapterRegistry = new AdapterRegistry();
|
|
115
|
-
module.exports = adapterRegistry;
|
|
247
|
+
module.exports = adapterRegistry;
|
package/handlers/log.js
CHANGED
|
@@ -4,8 +4,9 @@ const { MessageLogModel } = require('../models/messageLogModel');
|
|
|
4
4
|
const { UserModel } = require('../models/userModel');
|
|
5
5
|
const oauth = require('../lib/oauth');
|
|
6
6
|
const errorMessage = require('../lib/generalErrorMessage');
|
|
7
|
-
const { composeCallLog, getLogFormatType
|
|
7
|
+
const { composeCallLog, getLogFormatType } = require('../lib/callLogComposer');
|
|
8
8
|
const adapterRegistry = require('../adapter/registry');
|
|
9
|
+
const { LOG_DETAILS_FORMAT_TYPE } = require('../lib/constants');
|
|
9
10
|
|
|
10
11
|
async function createCallLog({ platform, userId, incomingData }) {
|
|
11
12
|
try {
|
|
@@ -76,7 +77,7 @@ async function createCallLog({ platform, userId, incomingData }) {
|
|
|
76
77
|
// Compose call log details centrally
|
|
77
78
|
const logFormat = getLogFormatType(platform);
|
|
78
79
|
let composedLogDetails = '';
|
|
79
|
-
if (logFormat ===
|
|
80
|
+
if (logFormat === LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT || logFormat === LOG_DETAILS_FORMAT_TYPE.HTML || logFormat === LOG_DETAILS_FORMAT_TYPE.MARKDOWN) {
|
|
80
81
|
composedLogDetails = await composeCallLog({
|
|
81
82
|
logFormat,
|
|
82
83
|
callLog,
|
|
@@ -309,7 +310,7 @@ async function updateCallLog({ platform, userId, incomingData }) {
|
|
|
309
310
|
let existingCallLogDetails = null; // Compose updated call log details centrally
|
|
310
311
|
const logFormat = getLogFormatType(platform);
|
|
311
312
|
let composedLogDetails = '';
|
|
312
|
-
if (logFormat ===
|
|
313
|
+
if (logFormat === LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT || logFormat === LOG_DETAILS_FORMAT_TYPE.HTML || logFormat === LOG_DETAILS_FORMAT_TYPE.MARKDOWN) {
|
|
313
314
|
let existingBody = '';
|
|
314
315
|
try {
|
|
315
316
|
const getLogResult = await platformModule.getCallLog({
|
package/index.js
CHANGED
|
@@ -76,7 +76,7 @@ function createCoreRouter() {
|
|
|
76
76
|
const versions = Object.keys(adapterReleaseNotes);
|
|
77
77
|
for (const version of versions) {
|
|
78
78
|
mergedReleaseNotes[version] = {
|
|
79
|
-
global: globalReleaseNotes[version]
|
|
79
|
+
global: globalReleaseNotes[version]?.global ?? {},
|
|
80
80
|
...adapterReleaseNotes[version] ?? {}
|
|
81
81
|
};
|
|
82
82
|
}
|
|
@@ -229,7 +229,8 @@ function createCoreRouter() {
|
|
|
229
229
|
platformName = unAuthData?.platform ?? 'Unknown';
|
|
230
230
|
const user = await UserModel.findByPk(unAuthData?.id);
|
|
231
231
|
if (!user) {
|
|
232
|
-
res.status(400).send();
|
|
232
|
+
res.status(400).send('User not found');
|
|
233
|
+
return;
|
|
233
234
|
}
|
|
234
235
|
const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
|
|
235
236
|
const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
|
|
@@ -402,7 +403,8 @@ function createCoreRouter() {
|
|
|
402
403
|
platformName = unAuthData?.platform ?? 'Unknown';
|
|
403
404
|
const user = await UserModel.findByPk(unAuthData?.id);
|
|
404
405
|
if (!user) {
|
|
405
|
-
res.status(400).send();
|
|
406
|
+
res.status(400).send('User not found');
|
|
407
|
+
return;
|
|
406
408
|
}
|
|
407
409
|
else {
|
|
408
410
|
const rcAccessToken = req.query.rcAccessToken;
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
// Test environment
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
|
|
7
|
+
// Test file patterns
|
|
8
|
+
testMatch: [
|
|
9
|
+
'<rootDir>/test/**/*.test.js',
|
|
10
|
+
'<rootDir>/**/*.test.js'
|
|
11
|
+
],
|
|
12
|
+
|
|
13
|
+
// Setup files
|
|
14
|
+
setupFilesAfterEnv: [
|
|
15
|
+
'<rootDir>/test/setup.js'
|
|
16
|
+
],
|
|
17
|
+
|
|
18
|
+
// Coverage configuration
|
|
19
|
+
collectCoverage: true,
|
|
20
|
+
coverageDirectory: '<rootDir>/coverage',
|
|
21
|
+
coverageReporters: ['text', 'lcov', 'html'],
|
|
22
|
+
coveragePathIgnorePatterns: [
|
|
23
|
+
'/node_modules/',
|
|
24
|
+
'/test/',
|
|
25
|
+
'/coverage/',
|
|
26
|
+
'jest.config.js',
|
|
27
|
+
'setup.js'
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
// Module resolution
|
|
31
|
+
moduleDirectories: ['node_modules', '<rootDir>'],
|
|
32
|
+
moduleNameMapper: {
|
|
33
|
+
'^@app-connect/core/(.*)$': '<rootDir>/$1'
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
// Test timeout
|
|
37
|
+
testTimeout: 30000,
|
|
38
|
+
|
|
39
|
+
// Reporters
|
|
40
|
+
reporters: ['default'],
|
|
41
|
+
|
|
42
|
+
// Ignore patterns
|
|
43
|
+
modulePathIgnorePatterns: [
|
|
44
|
+
'<rootDir>/node_modules/',
|
|
45
|
+
'<rootDir>/coverage/',
|
|
46
|
+
'<rootDir>/test-results/'
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
// Clear mocks between tests
|
|
50
|
+
clearMocks: true,
|
|
51
|
+
|
|
52
|
+
// Restore mocks between tests
|
|
53
|
+
restoreMocks: true,
|
|
54
|
+
|
|
55
|
+
// Verbose output
|
|
56
|
+
verbose: true
|
|
57
|
+
};
|