@app-connect/core 1.7.24 → 1.7.26
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 +441 -441
- package/connector/developerPortal.js +31 -42
- package/connector/mock.js +84 -77
- package/connector/proxy/engine.js +164 -163
- package/connector/proxy/index.js +500 -500
- package/connector/registry.js +252 -252
- package/docs/README.md +50 -50
- package/docs/architecture.md +93 -93
- package/docs/connectors.md +116 -117
- package/docs/handlers.md +125 -125
- package/docs/libraries.md +101 -101
- package/docs/models.md +144 -144
- package/docs/routes.md +115 -115
- package/docs/tests.md +73 -73
- package/handlers/admin.js +523 -523
- package/handlers/appointment.js +193 -0
- package/handlers/auth.js +296 -296
- package/handlers/calldown.js +99 -99
- package/handlers/contact.js +280 -280
- package/handlers/disposition.js +82 -80
- package/handlers/log.js +984 -973
- package/handlers/managedAuth.js +446 -446
- package/handlers/plugin.js +208 -208
- package/handlers/user.js +142 -142
- package/index.js +3140 -2652
- package/jest.config.js +56 -56
- package/lib/analytics.js +54 -54
- package/lib/authSession.js +109 -109
- package/lib/cacheCleanup.js +21 -0
- package/lib/callLogComposer.js +898 -898
- package/lib/callLogLookup.js +34 -0
- package/lib/constants.js +8 -8
- package/lib/debugTracer.js +177 -177
- package/lib/encode.js +30 -30
- package/lib/errorHandler.js +218 -206
- package/lib/generalErrorMessage.js +41 -41
- package/lib/jwt.js +18 -18
- package/lib/logger.js +190 -190
- package/lib/migrateCallLogsSchema.js +116 -0
- package/lib/ringcentral.js +266 -266
- package/lib/s3ErrorLogReport.js +65 -65
- package/lib/sharedSMSComposer.js +471 -471
- package/lib/util.js +67 -67
- package/mcp/README.md +412 -395
- package/mcp/lib/validator.js +91 -91
- package/mcp/mcpHandler.js +425 -425
- package/mcp/tools/cancelAppointment.js +101 -0
- package/mcp/tools/checkAuthStatus.js +105 -105
- package/mcp/tools/confirmAppointment.js +101 -0
- package/mcp/tools/createAppointment.js +157 -0
- package/mcp/tools/createCallLog.js +327 -316
- package/mcp/tools/createContact.js +117 -117
- package/mcp/tools/createMessageLog.js +287 -287
- package/mcp/tools/doAuth.js +60 -60
- package/mcp/tools/findContactByName.js +93 -93
- package/mcp/tools/findContactByPhone.js +101 -101
- package/mcp/tools/getCallLog.js +111 -102
- package/mcp/tools/getGoogleFilePicker.js +99 -99
- package/mcp/tools/getHelp.js +43 -43
- package/mcp/tools/getPublicConnectors.js +94 -94
- package/mcp/tools/getSessionInfo.js +90 -90
- package/mcp/tools/index.js +51 -41
- package/mcp/tools/listAppointments.js +163 -0
- package/mcp/tools/logout.js +96 -96
- package/mcp/tools/rcGetCallLogs.js +65 -65
- package/mcp/tools/updateAppointment.js +154 -0
- package/mcp/tools/updateCallLog.js +130 -126
- package/mcp/ui/App/App.tsx +358 -358
- package/mcp/ui/App/components/AuthInfoForm.tsx +113 -113
- package/mcp/ui/App/components/AuthSuccess.tsx +22 -22
- package/mcp/ui/App/components/ConnectorList.tsx +82 -82
- package/mcp/ui/App/components/DebugPanel.tsx +43 -43
- package/mcp/ui/App/components/OAuthConnect.tsx +270 -270
- package/mcp/ui/App/lib/callTool.ts +130 -130
- package/mcp/ui/App/lib/debugLog.ts +41 -41
- package/mcp/ui/App/lib/developerPortal.ts +111 -111
- package/mcp/ui/App/main.css +5 -5
- package/mcp/ui/App/root.tsx +13 -13
- package/mcp/ui/index.html +13 -13
- package/mcp/ui/package-lock.json +6356 -6356
- package/mcp/ui/package.json +25 -25
- package/mcp/ui/tsconfig.json +26 -26
- package/mcp/ui/vite.config.ts +16 -16
- package/models/accountDataModel.js +33 -33
- package/models/adminConfigModel.js +35 -35
- package/models/cacheModel.js +30 -26
- package/models/callDownListModel.js +34 -34
- package/models/callLogModel.js +33 -27
- package/models/dynamo/connectorSchema.js +146 -146
- package/models/dynamo/lockSchema.js +24 -24
- package/models/dynamo/noteCacheSchema.js +29 -29
- package/models/llmSessionModel.js +17 -17
- package/models/messageLogModel.js +25 -25
- package/models/sequelize.js +16 -16
- package/models/userModel.js +45 -45
- package/package.json +72 -72
- package/releaseNotes.json +1093 -1073
- package/test/connector/proxy/engine.test.js +126 -93
- package/test/connector/proxy/index.test.js +279 -279
- package/test/connector/proxy/sample.json +161 -161
- package/test/connector/registry.test.js +415 -415
- package/test/handlers/admin.test.js +616 -616
- package/test/handlers/auth.test.js +1018 -1015
- package/test/handlers/contact.test.js +1014 -1014
- package/test/handlers/log.test.js +1298 -1160
- package/test/handlers/managedAuth.test.js +458 -458
- package/test/handlers/plugin.test.js +380 -380
- package/test/index.test.js +105 -105
- package/test/lib/cacheCleanup.test.js +42 -0
- package/test/lib/callLogComposer.test.js +1231 -1231
- package/test/lib/debugTracer.test.js +328 -328
- package/test/lib/jwt.test.js +176 -176
- package/test/lib/logger.test.js +206 -206
- package/test/lib/oauth.test.js +359 -359
- package/test/lib/ringcentral.test.js +467 -467
- package/test/lib/sharedSMSComposer.test.js +1084 -1084
- package/test/lib/util.test.js +329 -329
- package/test/mcp/tools/checkAuthStatus.test.js +83 -82
- package/test/mcp/tools/createCallLog.test.js +436 -436
- package/test/mcp/tools/createContact.test.js +58 -58
- package/test/mcp/tools/createMessageLog.test.js +595 -595
- package/test/mcp/tools/doAuth.test.js +113 -113
- package/test/mcp/tools/findContactByName.test.js +275 -275
- package/test/mcp/tools/findContactByPhone.test.js +296 -296
- package/test/mcp/tools/getCallLog.test.js +298 -298
- package/test/mcp/tools/getGoogleFilePicker.test.js +281 -281
- package/test/mcp/tools/getPublicConnectors.test.js +107 -107
- package/test/mcp/tools/getSessionInfo.test.js +127 -127
- package/test/mcp/tools/logout.test.js +233 -233
- package/test/mcp/tools/rcGetCallLogs.test.js +56 -56
- package/test/mcp/tools/updateCallLog.test.js +360 -360
- package/test/models/accountDataModel.test.js +98 -98
- package/test/models/dynamo/connectorSchema.test.js +189 -189
- package/test/models/models.test.js +568 -539
- package/test/routes/managedAuthRoutes.test.js +104 -129
- package/test/setup.js +178 -178
package/connector/registry.js
CHANGED
|
@@ -1,252 +1,252 @@
|
|
|
1
|
-
// core/src/connector/registry.js
|
|
2
|
-
const logger = require('../lib/logger');
|
|
3
|
-
class ConnectorRegistry {
|
|
4
|
-
constructor() {
|
|
5
|
-
this.connectors = new Map();
|
|
6
|
-
this.manifests = new Map();
|
|
7
|
-
this.releaseNotes = {};
|
|
8
|
-
this.platformInterfaces = new Map(); // Store interface functions per platform
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
setDefaultManifest(manifest) {
|
|
12
|
-
this.manifests.set('default', manifest);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Register an interface function for a specific platform
|
|
17
|
-
* @param {string} platformName - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
18
|
-
* @param {string} interfaceName - Interface function name (e.g., 'createCallLog', 'findContact')
|
|
19
|
-
* @param {Function} interfaceFunction - The interface function to register
|
|
20
|
-
*/
|
|
21
|
-
registerConnectorInterface(platformName, interfaceName, interfaceFunction) {
|
|
22
|
-
if (typeof interfaceFunction !== 'function') {
|
|
23
|
-
throw new Error(`Interface function must be a function, got: ${typeof interfaceFunction}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!this.platformInterfaces.has(platformName)) {
|
|
27
|
-
this.platformInterfaces.set(platformName, new Map());
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
31
|
-
platformInterfaceMap.set(interfaceName, interfaceFunction);
|
|
32
|
-
|
|
33
|
-
logger.info(`Registered interface function: ${platformName}.${interfaceName}`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Get registered interface functions for a platform
|
|
38
|
-
* @param {string} platformName - Platform identifier
|
|
39
|
-
* @returns {Map} Map of interface functions
|
|
40
|
-
*/
|
|
41
|
-
getPlatformInterfaces(platformName) {
|
|
42
|
-
return this.platformInterfaces.get(platformName) || new Map();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Check if an interface function is registered for a platform
|
|
47
|
-
* @param {string} platformName - Platform identifier
|
|
48
|
-
* @param {string} interfaceName - Interface function name
|
|
49
|
-
* @returns {boolean} True if interface is registered
|
|
50
|
-
*/
|
|
51
|
-
hasPlatformInterface(platformName, interfaceName) {
|
|
52
|
-
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
53
|
-
return platformInterfaceMap ? platformInterfaceMap.has(interfaceName) : false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Unregister an interface function for a platform
|
|
58
|
-
* @param {string} platformName - Platform identifier
|
|
59
|
-
* @param {string} interfaceName - Interface function name
|
|
60
|
-
*/
|
|
61
|
-
unregisterConnectorInterface(platformName, interfaceName) {
|
|
62
|
-
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
63
|
-
if (platformInterfaceMap && platformInterfaceMap.has(interfaceName)) {
|
|
64
|
-
platformInterfaceMap.delete(interfaceName);
|
|
65
|
-
logger.info(`Unregistered interface function: ${platformName}.${interfaceName}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Register an connector with the core system
|
|
71
|
-
* @param {string} platform - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
72
|
-
* @param {Object} connector - Connector implementation
|
|
73
|
-
* @param {Object} manifest - Connector manifest configuration
|
|
74
|
-
*/
|
|
75
|
-
registerConnector(platform, connector, manifest = null) {
|
|
76
|
-
// Validate connector interface
|
|
77
|
-
this.validateConnectorInterface(platform, connector);
|
|
78
|
-
|
|
79
|
-
this.connectors.set(platform, connector);
|
|
80
|
-
if (manifest) {
|
|
81
|
-
this.manifests.set(platform, manifest);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
logger.info(`Registered connector: ${platform}`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Get connector by platform name with composed interfaces
|
|
89
|
-
* @param {string} platform - Platform identifier
|
|
90
|
-
* @returns {Object} Composed connector with interface functions
|
|
91
|
-
*/
|
|
92
|
-
getConnector(platform) {
|
|
93
|
-
let connector = this.connectors.get(platform);
|
|
94
|
-
const platformInterfaceMap = this.platformInterfaces.get(platform);
|
|
95
|
-
|
|
96
|
-
if (!connector && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
97
|
-
connector = this.connectors.get('proxy');
|
|
98
|
-
if (connector) {
|
|
99
|
-
return connector;
|
|
100
|
-
}
|
|
101
|
-
throw new Error(`Connector not found for platform: ${platform}`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// If no connector but interfaces exist, create a composed object with just interfaces
|
|
105
|
-
if (!connector && platformInterfaceMap && platformInterfaceMap.size > 0) {
|
|
106
|
-
const composedConnector = {};
|
|
107
|
-
|
|
108
|
-
// Add interface functions to the composed connector
|
|
109
|
-
for (const [interfaceName, interfaceFunction] of platformInterfaceMap) {
|
|
110
|
-
composedConnector[interfaceName] = interfaceFunction;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
logger.info(`Returning interface-only connector for platform: ${platform}`);
|
|
114
|
-
return composedConnector;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// If connector exists but no interfaces, return original connector
|
|
118
|
-
if (connector && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
119
|
-
return connector;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// If both connector and interfaces exist, create a composed object
|
|
123
|
-
const composedConnector = Object.create(connector);
|
|
124
|
-
|
|
125
|
-
// Add interface functions to the composed connector
|
|
126
|
-
for (const [interfaceName, interfaceFunction] of platformInterfaceMap) {
|
|
127
|
-
// Only add if the interface doesn't already exist in the connector
|
|
128
|
-
if (!Object.prototype.hasOwnProperty.call(connector, interfaceName)) {
|
|
129
|
-
composedConnector[interfaceName] = interfaceFunction;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return composedConnector;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Get the original connector without composed interfaces
|
|
138
|
-
* @param {string} platform - Platform identifier
|
|
139
|
-
* @returns {Object} Original connector implementation
|
|
140
|
-
*/
|
|
141
|
-
getOriginalConnector(platform) {
|
|
142
|
-
const connector = this.connectors.get(platform);
|
|
143
|
-
if (!connector) {
|
|
144
|
-
throw new Error(`Connector not found for platform: ${platform}`);
|
|
145
|
-
}
|
|
146
|
-
return connector;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Get manifest for a platform
|
|
151
|
-
* @param {string} platform - Platform identifier
|
|
152
|
-
* @returns {Object} Manifest configuration
|
|
153
|
-
*/
|
|
154
|
-
getManifest(platform, fallbackToDefault = false) {
|
|
155
|
-
let manifest = this.manifests.get(platform);
|
|
156
|
-
if (!manifest && fallbackToDefault) {
|
|
157
|
-
manifest = this.manifests.get('default');
|
|
158
|
-
}
|
|
159
|
-
if (!manifest) {
|
|
160
|
-
throw new Error(`Manifest not found for platform: ${platform}`);
|
|
161
|
-
}
|
|
162
|
-
return manifest;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Get all registered platforms
|
|
167
|
-
* @returns {Array<string>} Array of platform names
|
|
168
|
-
*/
|
|
169
|
-
getRegisteredPlatforms() {
|
|
170
|
-
return Array.from(this.connectors.keys());
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Check if platform is registered
|
|
175
|
-
* @param {string} platform - Platform identifier
|
|
176
|
-
* @returns {boolean} True if platform is registered
|
|
177
|
-
*/
|
|
178
|
-
isRegistered(platform) {
|
|
179
|
-
return this.connectors.has(platform);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Validate that connector implements required interface
|
|
184
|
-
* @param {Object} connector - Connector to validate
|
|
185
|
-
*/
|
|
186
|
-
validateConnectorInterface(platform, connector) {
|
|
187
|
-
const requiredMethods = [
|
|
188
|
-
'createCallLog',
|
|
189
|
-
'updateCallLog',
|
|
190
|
-
];
|
|
191
|
-
|
|
192
|
-
for (const method of requiredMethods) {
|
|
193
|
-
if (typeof connector[method] !== 'function') {
|
|
194
|
-
throw new Error(`Connector ${platform} missing required method: ${method}`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Unregister an connector
|
|
201
|
-
* @param {string} platform - Platform identifier
|
|
202
|
-
*/
|
|
203
|
-
unregisterConnector(platform) {
|
|
204
|
-
this.connectors.delete(platform);
|
|
205
|
-
this.manifests.delete(platform);
|
|
206
|
-
this.platformInterfaces.delete(platform);
|
|
207
|
-
logger.info(`Unregistered connector: ${platform}`);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
setReleaseNotes(releaseNotes) {
|
|
211
|
-
this.releaseNotes = releaseNotes;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
getReleaseNotes() {
|
|
215
|
-
return this.releaseNotes;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Get connector capabilities summary including composed interfaces
|
|
220
|
-
* @param {string} platform - Platform identifier
|
|
221
|
-
* @returns {Object} Connector capabilities
|
|
222
|
-
*/
|
|
223
|
-
async getConnectorCapabilities(platform) {
|
|
224
|
-
const originalConnector = this.getOriginalConnector(platform);
|
|
225
|
-
const composedConnector = this.getConnector(platform);
|
|
226
|
-
const platformInterfaceMap = this.getPlatformInterfaces(platform);
|
|
227
|
-
|
|
228
|
-
const capabilities = {
|
|
229
|
-
platform,
|
|
230
|
-
originalMethods: Object.keys(originalConnector),
|
|
231
|
-
composedMethods: Object.keys(composedConnector),
|
|
232
|
-
registeredInterfaces: Array.from(platformInterfaceMap.keys()),
|
|
233
|
-
authType: null
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
// Get auth type if available
|
|
237
|
-
if (typeof originalConnector.getAuthType === 'function') {
|
|
238
|
-
try {
|
|
239
|
-
capabilities.authType = await originalConnector.getAuthType();
|
|
240
|
-
} catch (error) {
|
|
241
|
-
logger.error('Error getting auth type', { stack: error.stack });
|
|
242
|
-
capabilities.authType = 'unknown';
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return capabilities;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Export singleton instance
|
|
251
|
-
const connectorRegistry = new ConnectorRegistry();
|
|
252
|
-
module.exports = connectorRegistry;
|
|
1
|
+
// core/src/connector/registry.js
|
|
2
|
+
const logger = require('../lib/logger');
|
|
3
|
+
class ConnectorRegistry {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.connectors = new Map();
|
|
6
|
+
this.manifests = new Map();
|
|
7
|
+
this.releaseNotes = {};
|
|
8
|
+
this.platformInterfaces = new Map(); // Store interface functions per platform
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
setDefaultManifest(manifest) {
|
|
12
|
+
this.manifests.set('default', manifest);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Register an interface function for a specific platform
|
|
17
|
+
* @param {string} platformName - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
18
|
+
* @param {string} interfaceName - Interface function name (e.g., 'createCallLog', 'findContact')
|
|
19
|
+
* @param {Function} interfaceFunction - The interface function to register
|
|
20
|
+
*/
|
|
21
|
+
registerConnectorInterface(platformName, interfaceName, interfaceFunction) {
|
|
22
|
+
if (typeof interfaceFunction !== 'function') {
|
|
23
|
+
throw new Error(`Interface function must be a function, got: ${typeof interfaceFunction}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!this.platformInterfaces.has(platformName)) {
|
|
27
|
+
this.platformInterfaces.set(platformName, new Map());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
31
|
+
platformInterfaceMap.set(interfaceName, interfaceFunction);
|
|
32
|
+
|
|
33
|
+
logger.info(`Registered interface function: ${platformName}.${interfaceName}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get registered interface functions for a platform
|
|
38
|
+
* @param {string} platformName - Platform identifier
|
|
39
|
+
* @returns {Map} Map of interface functions
|
|
40
|
+
*/
|
|
41
|
+
getPlatformInterfaces(platformName) {
|
|
42
|
+
return this.platformInterfaces.get(platformName) || new Map();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if an interface function is registered for a platform
|
|
47
|
+
* @param {string} platformName - Platform identifier
|
|
48
|
+
* @param {string} interfaceName - Interface function name
|
|
49
|
+
* @returns {boolean} True if interface is registered
|
|
50
|
+
*/
|
|
51
|
+
hasPlatformInterface(platformName, interfaceName) {
|
|
52
|
+
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
53
|
+
return platformInterfaceMap ? platformInterfaceMap.has(interfaceName) : false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Unregister an interface function for a platform
|
|
58
|
+
* @param {string} platformName - Platform identifier
|
|
59
|
+
* @param {string} interfaceName - Interface function name
|
|
60
|
+
*/
|
|
61
|
+
unregisterConnectorInterface(platformName, interfaceName) {
|
|
62
|
+
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
63
|
+
if (platformInterfaceMap && platformInterfaceMap.has(interfaceName)) {
|
|
64
|
+
platformInterfaceMap.delete(interfaceName);
|
|
65
|
+
logger.info(`Unregistered interface function: ${platformName}.${interfaceName}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Register an connector with the core system
|
|
71
|
+
* @param {string} platform - Platform identifier (e.g., 'pipedrive', 'salesforce')
|
|
72
|
+
* @param {Object} connector - Connector implementation
|
|
73
|
+
* @param {Object} manifest - Connector manifest configuration
|
|
74
|
+
*/
|
|
75
|
+
registerConnector(platform, connector, manifest = null) {
|
|
76
|
+
// Validate connector interface
|
|
77
|
+
this.validateConnectorInterface(platform, connector);
|
|
78
|
+
|
|
79
|
+
this.connectors.set(platform, connector);
|
|
80
|
+
if (manifest) {
|
|
81
|
+
this.manifests.set(platform, manifest);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
logger.info(`Registered connector: ${platform}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get connector by platform name with composed interfaces
|
|
89
|
+
* @param {string} platform - Platform identifier
|
|
90
|
+
* @returns {Object} Composed connector with interface functions
|
|
91
|
+
*/
|
|
92
|
+
getConnector(platform) {
|
|
93
|
+
let connector = this.connectors.get(platform);
|
|
94
|
+
const platformInterfaceMap = this.platformInterfaces.get(platform);
|
|
95
|
+
|
|
96
|
+
if (!connector && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
97
|
+
connector = this.connectors.get('proxy');
|
|
98
|
+
if (connector) {
|
|
99
|
+
return connector;
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`Connector not found for platform: ${platform}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// If no connector but interfaces exist, create a composed object with just interfaces
|
|
105
|
+
if (!connector && platformInterfaceMap && platformInterfaceMap.size > 0) {
|
|
106
|
+
const composedConnector = {};
|
|
107
|
+
|
|
108
|
+
// Add interface functions to the composed connector
|
|
109
|
+
for (const [interfaceName, interfaceFunction] of platformInterfaceMap) {
|
|
110
|
+
composedConnector[interfaceName] = interfaceFunction;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
logger.info(`Returning interface-only connector for platform: ${platform}`);
|
|
114
|
+
return composedConnector;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// If connector exists but no interfaces, return original connector
|
|
118
|
+
if (connector && (!platformInterfaceMap || platformInterfaceMap.size === 0)) {
|
|
119
|
+
return connector;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// If both connector and interfaces exist, create a composed object
|
|
123
|
+
const composedConnector = Object.create(connector);
|
|
124
|
+
|
|
125
|
+
// Add interface functions to the composed connector
|
|
126
|
+
for (const [interfaceName, interfaceFunction] of platformInterfaceMap) {
|
|
127
|
+
// Only add if the interface doesn't already exist in the connector
|
|
128
|
+
if (!Object.prototype.hasOwnProperty.call(connector, interfaceName)) {
|
|
129
|
+
composedConnector[interfaceName] = interfaceFunction;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return composedConnector;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get the original connector without composed interfaces
|
|
138
|
+
* @param {string} platform - Platform identifier
|
|
139
|
+
* @returns {Object} Original connector implementation
|
|
140
|
+
*/
|
|
141
|
+
getOriginalConnector(platform) {
|
|
142
|
+
const connector = this.connectors.get(platform);
|
|
143
|
+
if (!connector) {
|
|
144
|
+
throw new Error(`Connector not found for platform: ${platform}`);
|
|
145
|
+
}
|
|
146
|
+
return connector;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get manifest for a platform
|
|
151
|
+
* @param {string} platform - Platform identifier
|
|
152
|
+
* @returns {Object} Manifest configuration
|
|
153
|
+
*/
|
|
154
|
+
getManifest(platform, fallbackToDefault = false) {
|
|
155
|
+
let manifest = this.manifests.get(platform);
|
|
156
|
+
if (!manifest && fallbackToDefault) {
|
|
157
|
+
manifest = this.manifests.get('default');
|
|
158
|
+
}
|
|
159
|
+
if (!manifest) {
|
|
160
|
+
throw new Error(`Manifest not found for platform: ${platform}`);
|
|
161
|
+
}
|
|
162
|
+
return manifest;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get all registered platforms
|
|
167
|
+
* @returns {Array<string>} Array of platform names
|
|
168
|
+
*/
|
|
169
|
+
getRegisteredPlatforms() {
|
|
170
|
+
return Array.from(this.connectors.keys());
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Check if platform is registered
|
|
175
|
+
* @param {string} platform - Platform identifier
|
|
176
|
+
* @returns {boolean} True if platform is registered
|
|
177
|
+
*/
|
|
178
|
+
isRegistered(platform) {
|
|
179
|
+
return this.connectors.has(platform);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Validate that connector implements required interface
|
|
184
|
+
* @param {Object} connector - Connector to validate
|
|
185
|
+
*/
|
|
186
|
+
validateConnectorInterface(platform, connector) {
|
|
187
|
+
const requiredMethods = [
|
|
188
|
+
'createCallLog',
|
|
189
|
+
'updateCallLog',
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
for (const method of requiredMethods) {
|
|
193
|
+
if (typeof connector[method] !== 'function') {
|
|
194
|
+
throw new Error(`Connector ${platform} missing required method: ${method}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Unregister an connector
|
|
201
|
+
* @param {string} platform - Platform identifier
|
|
202
|
+
*/
|
|
203
|
+
unregisterConnector(platform) {
|
|
204
|
+
this.connectors.delete(platform);
|
|
205
|
+
this.manifests.delete(platform);
|
|
206
|
+
this.platformInterfaces.delete(platform);
|
|
207
|
+
logger.info(`Unregistered connector: ${platform}`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
setReleaseNotes(releaseNotes) {
|
|
211
|
+
this.releaseNotes = releaseNotes;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
getReleaseNotes() {
|
|
215
|
+
return this.releaseNotes;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get connector capabilities summary including composed interfaces
|
|
220
|
+
* @param {string} platform - Platform identifier
|
|
221
|
+
* @returns {Object} Connector capabilities
|
|
222
|
+
*/
|
|
223
|
+
async getConnectorCapabilities(platform) {
|
|
224
|
+
const originalConnector = this.getOriginalConnector(platform);
|
|
225
|
+
const composedConnector = this.getConnector(platform);
|
|
226
|
+
const platformInterfaceMap = this.getPlatformInterfaces(platform);
|
|
227
|
+
|
|
228
|
+
const capabilities = {
|
|
229
|
+
platform,
|
|
230
|
+
originalMethods: Object.keys(originalConnector),
|
|
231
|
+
composedMethods: Object.keys(composedConnector),
|
|
232
|
+
registeredInterfaces: Array.from(platformInterfaceMap.keys()),
|
|
233
|
+
authType: null
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// Get auth type if available
|
|
237
|
+
if (typeof originalConnector.getAuthType === 'function') {
|
|
238
|
+
try {
|
|
239
|
+
capabilities.authType = await originalConnector.getAuthType();
|
|
240
|
+
} catch (error) {
|
|
241
|
+
logger.error('Error getting auth type', { stack: error.stack });
|
|
242
|
+
capabilities.authType = 'unknown';
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return capabilities;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Export singleton instance
|
|
251
|
+
const connectorRegistry = new ConnectorRegistry();
|
|
252
|
+
module.exports = connectorRegistry;
|
package/docs/README.md
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
# App Connect Core Docs
|
|
2
|
-
|
|
3
|
-
This docs set explains the maintained code under `packages/core`, excluding the `mcp/` subsystem.
|
|
4
|
-
|
|
5
|
-
Use it when you need to change shared backend behavior, trace a request through the framework, or understand which module owns a feature.
|
|
6
|
-
|
|
7
|
-
## Scope
|
|
8
|
-
|
|
9
|
-
Included:
|
|
10
|
-
|
|
11
|
-
- root package entrypoints and route assembly
|
|
12
|
-
- connector infrastructure
|
|
13
|
-
- handlers
|
|
14
|
-
- models, including DynamoDB-backed schemas used outside MCP
|
|
15
|
-
- shared libraries
|
|
16
|
-
- tests that cover the non-MCP package surface
|
|
17
|
-
|
|
18
|
-
Excluded:
|
|
19
|
-
|
|
20
|
-
- `mcp/`
|
|
21
|
-
- generated output such as `coverage/`
|
|
22
|
-
- vendored dependencies such as `node_modules/`
|
|
23
|
-
|
|
24
|
-
## Reading Order
|
|
25
|
-
|
|
26
|
-
1. [Architecture](architecture.md) for the runtime shape and request flow
|
|
27
|
-
2. [Routes](routes.md) for the HTTP surface in `index.js`
|
|
28
|
-
3. [Handlers](handlers.md) for shared business logic
|
|
29
|
-
4. [Connectors](connectors.md) for registration, proxy behavior, and developer-portal helpers
|
|
30
|
-
5. [Models](models.md) for persistence
|
|
31
|
-
6. [Libraries](libraries.md) for shared helpers and infrastructure code
|
|
32
|
-
7. [Tests](tests.md) for current automated coverage
|
|
33
|
-
|
|
34
|
-
## File Map
|
|
35
|
-
|
|
36
|
-
| Area | Files |
|
|
37
|
-
| --- | --- |
|
|
38
|
-
| Package root | `index.js`, `package.json`, `README.md`, `releaseNotes.json`, `jest.config.js` |
|
|
39
|
-
| Connectors | `connector/registry.js`, `connector/developerPortal.js`, `connector/mock.js`, `connector/proxy/index.js`, `connector/proxy/engine.js` |
|
|
40
|
-
| Handlers | `handlers/admin.js`, `handlers/auth.js`, `handlers/calldown.js`, `handlers/contact.js`, `handlers/disposition.js`, `handlers/log.js`, `handlers/plugin.js`, `handlers/managedAuth.js`, `handlers/user.js` |
|
|
41
|
-
| Sequelize models | `models/accountDataModel.js`, `models/adminConfigModel.js`, `models/cacheModel.js`, `models/callDownListModel.js`, `models/callLogModel.js`, `models/llmSessionModel.js`, `models/messageLogModel.js`, `models/sequelize.js`, `models/userModel.js` |
|
|
42
|
-
| DynamoDB models | `models/dynamo/connectorSchema.js`, `models/dynamo/lockSchema.js`, `models/dynamo/noteCacheSchema.js` |
|
|
43
|
-
| Libraries | `lib/analytics.js`, `lib/authSession.js`, `lib/callLogComposer.js`, `lib/constants.js`, `lib/debugTracer.js`, `lib/encode.js`, `lib/errorHandler.js`, `lib/generalErrorMessage.js`, `lib/jwt.js`, `lib/logger.js`, `lib/oauth.js`, `lib/ringcentral.js`, `lib/s3ErrorLogReport.js`, `lib/sharedSMSComposer.js`, `lib/util.js` |
|
|
44
|
-
| Tests | `test/setup.js`, `test/connector/**`, `test/handlers/**`, `test/lib/**`, `test/models/**`, `test/routes/**` excluding `test/mcp/**` |
|
|
45
|
-
|
|
46
|
-
## Relationship To The Package README
|
|
47
|
-
|
|
48
|
-
The package [README.md](../README.md) is still the best public-facing quick start.
|
|
49
|
-
|
|
50
|
-
This docs set is the maintainer-oriented reference for the internals behind that API surface.
|
|
1
|
+
# App Connect Core Docs
|
|
2
|
+
|
|
3
|
+
This docs set explains the maintained code under `packages/core`, excluding the `mcp/` subsystem.
|
|
4
|
+
|
|
5
|
+
Use it when you need to change shared backend behavior, trace a request through the framework, or understand which module owns a feature.
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
|
|
9
|
+
Included:
|
|
10
|
+
|
|
11
|
+
- root package entrypoints and route assembly
|
|
12
|
+
- connector infrastructure
|
|
13
|
+
- handlers
|
|
14
|
+
- models, including DynamoDB-backed schemas used outside MCP
|
|
15
|
+
- shared libraries
|
|
16
|
+
- tests that cover the non-MCP package surface
|
|
17
|
+
|
|
18
|
+
Excluded:
|
|
19
|
+
|
|
20
|
+
- `mcp/`
|
|
21
|
+
- generated output such as `coverage/`
|
|
22
|
+
- vendored dependencies such as `node_modules/`
|
|
23
|
+
|
|
24
|
+
## Reading Order
|
|
25
|
+
|
|
26
|
+
1. [Architecture](architecture.md) for the runtime shape and request flow
|
|
27
|
+
2. [Routes](routes.md) for the HTTP surface in `index.js`
|
|
28
|
+
3. [Handlers](handlers.md) for shared business logic
|
|
29
|
+
4. [Connectors](connectors.md) for registration, proxy behavior, and developer-portal helpers
|
|
30
|
+
5. [Models](models.md) for persistence
|
|
31
|
+
6. [Libraries](libraries.md) for shared helpers and infrastructure code
|
|
32
|
+
7. [Tests](tests.md) for current automated coverage
|
|
33
|
+
|
|
34
|
+
## File Map
|
|
35
|
+
|
|
36
|
+
| Area | Files |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| Package root | `index.js`, `package.json`, `README.md`, `releaseNotes.json`, `jest.config.js` |
|
|
39
|
+
| Connectors | `connector/registry.js`, `connector/developerPortal.js`, `connector/mock.js`, `connector/proxy/index.js`, `connector/proxy/engine.js` |
|
|
40
|
+
| Handlers | `handlers/admin.js`, `handlers/auth.js`, `handlers/calldown.js`, `handlers/contact.js`, `handlers/disposition.js`, `handlers/log.js`, `handlers/plugin.js`, `handlers/managedAuth.js`, `handlers/user.js` |
|
|
41
|
+
| Sequelize models | `models/accountDataModel.js`, `models/adminConfigModel.js`, `models/cacheModel.js`, `models/callDownListModel.js`, `models/callLogModel.js`, `models/llmSessionModel.js`, `models/messageLogModel.js`, `models/sequelize.js`, `models/userModel.js` |
|
|
42
|
+
| DynamoDB models | `models/dynamo/connectorSchema.js`, `models/dynamo/lockSchema.js`, `models/dynamo/noteCacheSchema.js` |
|
|
43
|
+
| Libraries | `lib/analytics.js`, `lib/authSession.js`, `lib/callLogComposer.js`, `lib/constants.js`, `lib/debugTracer.js`, `lib/encode.js`, `lib/errorHandler.js`, `lib/generalErrorMessage.js`, `lib/jwt.js`, `lib/logger.js`, `lib/oauth.js`, `lib/ringcentral.js`, `lib/s3ErrorLogReport.js`, `lib/sharedSMSComposer.js`, `lib/util.js` |
|
|
44
|
+
| Tests | `test/setup.js`, `test/connector/**`, `test/handlers/**`, `test/lib/**`, `test/models/**`, `test/routes/**` excluding `test/mcp/**` |
|
|
45
|
+
|
|
46
|
+
## Relationship To The Package README
|
|
47
|
+
|
|
48
|
+
The package [README.md](../README.md) is still the best public-facing quick start.
|
|
49
|
+
|
|
50
|
+
This docs set is the maintainer-oriented reference for the internals behind that API surface.
|