@app-connect/core 0.0.3 → 1.6.4-beta.0
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 -5
- package/README.md +434 -425
- package/adapter/mock.js +76 -76
- package/adapter/registry.js +247 -247
- package/handlers/admin.js +62 -60
- package/handlers/auth.js +210 -156
- package/handlers/contact.js +274 -274
- package/handlers/disposition.js +193 -193
- package/handlers/log.js +612 -586
- package/handlers/user.js +101 -101
- package/index.js +1302 -1202
- package/jest.config.js +56 -56
- package/lib/analytics.js +52 -52
- package/lib/callLogComposer.js +550 -451
- package/lib/constants.js +9 -0
- package/lib/encode.js +30 -30
- package/lib/generalErrorMessage.js +41 -41
- package/lib/jwt.js +16 -16
- package/lib/oauth.js +79 -29
- package/lib/util.js +43 -40
- package/models/adminConfigModel.js +17 -17
- package/models/cacheModel.js +23 -23
- package/models/callLogModel.js +27 -27
- package/models/dynamo/lockSchema.js +24 -24
- package/models/dynamo/noteCacheSchema.js +30 -0
- package/models/messageLogModel.js +25 -25
- package/models/sequelize.js +16 -16
- package/models/userModel.js +41 -38
- package/package.json +67 -64
- package/releaseNotes.json +701 -577
- package/test/adapter/registry.test.js +270 -270
- package/test/handlers/auth.test.js +230 -230
- package/test/lib/jwt.test.js +161 -161
- package/test/setup.js +176 -176
package/adapter/mock.js
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
// This mock is to run high traffic tests on the server
|
|
2
|
-
|
|
3
|
-
const { UserModel } = require("../models/userModel");
|
|
4
|
-
const { CallLogModel } = require("../models/callLogModel");
|
|
5
|
-
const shortid = require("shortid");
|
|
6
|
-
const Op = require('sequelize').Op;
|
|
7
|
-
|
|
8
|
-
async function createUser() {
|
|
9
|
-
let mockUser = await UserModel.findByPk('mockUser');
|
|
10
|
-
if (!mockUser) {
|
|
11
|
-
mockUser = await UserModel.create({
|
|
12
|
-
id: 'mockUser'
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
return mockUser;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function deleteUser() {
|
|
19
|
-
let mockUser = await UserModel.findByPk('mockUser');
|
|
20
|
-
if (mockUser) {
|
|
21
|
-
await mockUser.destroy();
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async function getCallLog({ sessionIds }) {
|
|
28
|
-
const sessionIdsArray = sessionIds.split(',');
|
|
29
|
-
const callLogs = await CallLogModel.findAll({
|
|
30
|
-
where: {
|
|
31
|
-
sessionId: {
|
|
32
|
-
[Op.in]: sessionIdsArray
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
const logs = [];
|
|
37
|
-
for (const sId of sessionIdsArray) {
|
|
38
|
-
const callLog = callLogs.find(c => c.sessionId === sId);
|
|
39
|
-
if (!callLog) {
|
|
40
|
-
logs.push({ sessionId: sId, matched: false });
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
logs.push({ sessionId: callLog.sessionId, matched: true, logId: 'mockThirdPartyLogId' });
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return logs;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function createCallLog({ sessionId }) {
|
|
51
|
-
let callLog = await CallLogModel.findOne({
|
|
52
|
-
where: {
|
|
53
|
-
sessionId
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
if (!callLog) {
|
|
57
|
-
callLog = await CallLogModel.create({
|
|
58
|
-
id: shortid.generate(),
|
|
59
|
-
sessionId,
|
|
60
|
-
userId: 'mockUser'
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function cleanUpMockLogs() {
|
|
66
|
-
await CallLogModel.destroy({
|
|
67
|
-
where: {
|
|
68
|
-
userId: 'mockUser'
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
exports.createUser = createUser;
|
|
74
|
-
exports.deleteUser = deleteUser;
|
|
75
|
-
exports.getCallLog = getCallLog;
|
|
76
|
-
exports.createCallLog = createCallLog;
|
|
1
|
+
// This mock is to run high traffic tests on the server
|
|
2
|
+
|
|
3
|
+
const { UserModel } = require("../models/userModel");
|
|
4
|
+
const { CallLogModel } = require("../models/callLogModel");
|
|
5
|
+
const shortid = require("shortid");
|
|
6
|
+
const Op = require('sequelize').Op;
|
|
7
|
+
|
|
8
|
+
async function createUser() {
|
|
9
|
+
let mockUser = await UserModel.findByPk('mockUser');
|
|
10
|
+
if (!mockUser) {
|
|
11
|
+
mockUser = await UserModel.create({
|
|
12
|
+
id: 'mockUser'
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return mockUser;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function deleteUser() {
|
|
19
|
+
let mockUser = await UserModel.findByPk('mockUser');
|
|
20
|
+
if (mockUser) {
|
|
21
|
+
await mockUser.destroy();
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function getCallLog({ sessionIds }) {
|
|
28
|
+
const sessionIdsArray = sessionIds.split(',');
|
|
29
|
+
const callLogs = await CallLogModel.findAll({
|
|
30
|
+
where: {
|
|
31
|
+
sessionId: {
|
|
32
|
+
[Op.in]: sessionIdsArray
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const logs = [];
|
|
37
|
+
for (const sId of sessionIdsArray) {
|
|
38
|
+
const callLog = callLogs.find(c => c.sessionId === sId);
|
|
39
|
+
if (!callLog) {
|
|
40
|
+
logs.push({ sessionId: sId, matched: false });
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
logs.push({ sessionId: callLog.sessionId, matched: true, logId: 'mockThirdPartyLogId' });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return logs;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function createCallLog({ sessionId }) {
|
|
51
|
+
let callLog = await CallLogModel.findOne({
|
|
52
|
+
where: {
|
|
53
|
+
sessionId
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (!callLog) {
|
|
57
|
+
callLog = await CallLogModel.create({
|
|
58
|
+
id: shortid.generate(),
|
|
59
|
+
sessionId,
|
|
60
|
+
userId: 'mockUser'
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function cleanUpMockLogs() {
|
|
66
|
+
await CallLogModel.destroy({
|
|
67
|
+
where: {
|
|
68
|
+
userId: 'mockUser'
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
exports.createUser = createUser;
|
|
74
|
+
exports.deleteUser = deleteUser;
|
|
75
|
+
exports.getCallLog = getCallLog;
|
|
76
|
+
exports.createCallLog = createCallLog;
|
|
77
77
|
exports.cleanUpMockLogs = cleanUpMockLogs;
|
package/adapter/registry.js
CHANGED
|
@@ -1,247 +1,247 @@
|
|
|
1
|
-
// core/src/adapter/registry.js
|
|
2
|
-
class AdapterRegistry {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.adapters = new Map();
|
|
5
|
-
this.manifests = new Map();
|
|
6
|
-
this.releaseNotes = {};
|
|
7
|
-
this.platformInterfaces = new Map(); // Store interface functions per platform
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
setDefaultManifest(manifest) {
|
|
11
|
-
this.manifests.set('default', manifest);
|
|
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
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Register an adapter with the core system
|
|
70
|
-
* @param {string} platform - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
71
|
-
* @param {Object} adapter - Adapter implementation
|
|
72
|
-
* @param {Object} manifest - Adapter manifest configuration
|
|
73
|
-
*/
|
|
74
|
-
registerAdapter(platform, adapter, manifest = null) {
|
|
75
|
-
// Validate adapter interface
|
|
76
|
-
this.validateAdapterInterface(platform, adapter);
|
|
77
|
-
|
|
78
|
-
this.adapters.set(platform, adapter);
|
|
79
|
-
if (manifest) {
|
|
80
|
-
this.manifests.set(platform, manifest);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
console.log(`Registered adapter: ${platform}`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Get adapter by platform name with composed interfaces
|
|
88
|
-
* @param {string} platform - Platform identifier
|
|
89
|
-
* @returns {Object} Composed adapter with interface functions
|
|
90
|
-
*/
|
|
91
|
-
getAdapter(platform) {
|
|
92
|
-
const adapter = this.adapters.get(platform);
|
|
93
|
-
const platformInterfaceMap = this.platformInterfaces.get(platform);
|
|
94
|
-
|
|
95
|
-
// If no adapter and no interfaces, throw error
|
|
96
|
-
if (!adapter && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
97
|
-
throw new Error(`Adapter not found for platform: ${platform}`);
|
|
98
|
-
}
|
|
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;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Get manifest for a platform
|
|
147
|
-
* @param {string} platform - Platform identifier
|
|
148
|
-
* @returns {Object} Manifest configuration
|
|
149
|
-
*/
|
|
150
|
-
getManifest(platform, fallbackToDefault = false) {
|
|
151
|
-
let manifest = this.manifests.get(platform);
|
|
152
|
-
if (!manifest && fallbackToDefault) {
|
|
153
|
-
manifest = this.manifests.get('default');
|
|
154
|
-
}
|
|
155
|
-
if (!manifest) {
|
|
156
|
-
throw new Error(`Manifest not found for platform: ${platform}`);
|
|
157
|
-
}
|
|
158
|
-
return manifest;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Get all registered platforms
|
|
163
|
-
* @returns {Array<string>} Array of platform names
|
|
164
|
-
*/
|
|
165
|
-
getRegisteredPlatforms() {
|
|
166
|
-
return Array.from(this.adapters.keys());
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Check if platform is registered
|
|
171
|
-
* @param {string} platform - Platform identifier
|
|
172
|
-
* @returns {boolean} True if platform is registered
|
|
173
|
-
*/
|
|
174
|
-
isRegistered(platform) {
|
|
175
|
-
return this.adapters.has(platform);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Validate that adapter implements required interface
|
|
180
|
-
* @param {Object} adapter - Adapter to validate
|
|
181
|
-
*/
|
|
182
|
-
validateAdapterInterface(platform, adapter) {
|
|
183
|
-
const requiredMethods = [
|
|
184
|
-
'createCallLog',
|
|
185
|
-
'updateCallLog',
|
|
186
|
-
];
|
|
187
|
-
|
|
188
|
-
for (const method of requiredMethods) {
|
|
189
|
-
if (typeof adapter[method] !== 'function') {
|
|
190
|
-
throw new Error(`Adapter ${platform} missing required method: ${method}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Unregister an adapter
|
|
197
|
-
* @param {string} platform - Platform identifier
|
|
198
|
-
*/
|
|
199
|
-
unregisterAdapter(platform) {
|
|
200
|
-
this.adapters.delete(platform);
|
|
201
|
-
this.manifests.delete(platform);
|
|
202
|
-
this.platformInterfaces.delete(platform);
|
|
203
|
-
console.log(`Unregistered adapter: ${platform}`);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
setReleaseNotes(releaseNotes) {
|
|
207
|
-
this.releaseNotes = releaseNotes;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
getReleaseNotes(platform) {
|
|
211
|
-
return this.releaseNotes;
|
|
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
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Export singleton instance
|
|
246
|
-
const adapterRegistry = new AdapterRegistry();
|
|
247
|
-
module.exports = adapterRegistry;
|
|
1
|
+
// core/src/adapter/registry.js
|
|
2
|
+
class AdapterRegistry {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.adapters = new Map();
|
|
5
|
+
this.manifests = new Map();
|
|
6
|
+
this.releaseNotes = {};
|
|
7
|
+
this.platformInterfaces = new Map(); // Store interface functions per platform
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
setDefaultManifest(manifest) {
|
|
11
|
+
this.manifests.set('default', manifest);
|
|
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
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Register an adapter with the core system
|
|
70
|
+
* @param {string} platform - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
71
|
+
* @param {Object} adapter - Adapter implementation
|
|
72
|
+
* @param {Object} manifest - Adapter manifest configuration
|
|
73
|
+
*/
|
|
74
|
+
registerAdapter(platform, adapter, manifest = null) {
|
|
75
|
+
// Validate adapter interface
|
|
76
|
+
this.validateAdapterInterface(platform, adapter);
|
|
77
|
+
|
|
78
|
+
this.adapters.set(platform, adapter);
|
|
79
|
+
if (manifest) {
|
|
80
|
+
this.manifests.set(platform, manifest);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.log(`Registered adapter: ${platform}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get adapter by platform name with composed interfaces
|
|
88
|
+
* @param {string} platform - Platform identifier
|
|
89
|
+
* @returns {Object} Composed adapter with interface functions
|
|
90
|
+
*/
|
|
91
|
+
getAdapter(platform) {
|
|
92
|
+
const adapter = this.adapters.get(platform);
|
|
93
|
+
const platformInterfaceMap = this.platformInterfaces.get(platform);
|
|
94
|
+
|
|
95
|
+
// If no adapter and no interfaces, throw error
|
|
96
|
+
if (!adapter && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
97
|
+
throw new Error(`Adapter not found for platform: ${platform}`);
|
|
98
|
+
}
|
|
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;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get manifest for a platform
|
|
147
|
+
* @param {string} platform - Platform identifier
|
|
148
|
+
* @returns {Object} Manifest configuration
|
|
149
|
+
*/
|
|
150
|
+
getManifest(platform, fallbackToDefault = false) {
|
|
151
|
+
let manifest = this.manifests.get(platform);
|
|
152
|
+
if (!manifest && fallbackToDefault) {
|
|
153
|
+
manifest = this.manifests.get('default');
|
|
154
|
+
}
|
|
155
|
+
if (!manifest) {
|
|
156
|
+
throw new Error(`Manifest not found for platform: ${platform}`);
|
|
157
|
+
}
|
|
158
|
+
return manifest;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get all registered platforms
|
|
163
|
+
* @returns {Array<string>} Array of platform names
|
|
164
|
+
*/
|
|
165
|
+
getRegisteredPlatforms() {
|
|
166
|
+
return Array.from(this.adapters.keys());
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Check if platform is registered
|
|
171
|
+
* @param {string} platform - Platform identifier
|
|
172
|
+
* @returns {boolean} True if platform is registered
|
|
173
|
+
*/
|
|
174
|
+
isRegistered(platform) {
|
|
175
|
+
return this.adapters.has(platform);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Validate that adapter implements required interface
|
|
180
|
+
* @param {Object} adapter - Adapter to validate
|
|
181
|
+
*/
|
|
182
|
+
validateAdapterInterface(platform, adapter) {
|
|
183
|
+
const requiredMethods = [
|
|
184
|
+
'createCallLog',
|
|
185
|
+
'updateCallLog',
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
for (const method of requiredMethods) {
|
|
189
|
+
if (typeof adapter[method] !== 'function') {
|
|
190
|
+
throw new Error(`Adapter ${platform} missing required method: ${method}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Unregister an adapter
|
|
197
|
+
* @param {string} platform - Platform identifier
|
|
198
|
+
*/
|
|
199
|
+
unregisterAdapter(platform) {
|
|
200
|
+
this.adapters.delete(platform);
|
|
201
|
+
this.manifests.delete(platform);
|
|
202
|
+
this.platformInterfaces.delete(platform);
|
|
203
|
+
console.log(`Unregistered adapter: ${platform}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
setReleaseNotes(releaseNotes) {
|
|
207
|
+
this.releaseNotes = releaseNotes;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
getReleaseNotes(platform) {
|
|
211
|
+
return this.releaseNotes;
|
|
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
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Export singleton instance
|
|
246
|
+
const adapterRegistry = new AdapterRegistry();
|
|
247
|
+
module.exports = adapterRegistry;
|