@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/handlers/calldown.js
CHANGED
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
const { UserModel } = require('../models/userModel');
|
|
2
|
-
const { CallDownListModel } = require('../models/callDownListModel');
|
|
3
|
-
const { Op } = require('sequelize');
|
|
4
|
-
const jwt = require('../lib/jwt');
|
|
5
|
-
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
6
|
-
|
|
7
|
-
async function schedule({ jwtToken, body }) {
|
|
8
|
-
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
9
|
-
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
10
|
-
const user = await UserModel.findByPk(unAuthData.id);
|
|
11
|
-
if (!user) throw new Error('User not found');
|
|
12
|
-
const crypto = require('crypto');
|
|
13
|
-
const recordId = crypto.randomBytes(16).toString('hex');
|
|
14
|
-
const payload = {
|
|
15
|
-
id: recordId,
|
|
16
|
-
userId: user.id,
|
|
17
|
-
contactId: body.contactId?.toString?.() ?? body.contactId,
|
|
18
|
-
contactType: body.contactType ?? 'contact',
|
|
19
|
-
contactName: body.contactName ?? '',
|
|
20
|
-
phoneNumber: body.phoneNumber ?? '',
|
|
21
|
-
status: 'scheduled',
|
|
22
|
-
scheduledAt: body.scheduledAt ? new Date(body.scheduledAt) : null,
|
|
23
|
-
lastCallAt: null
|
|
24
|
-
};
|
|
25
|
-
await CallDownListModel.create(payload);
|
|
26
|
-
return { id: recordId };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function list({ jwtToken, status }) {
|
|
30
|
-
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
31
|
-
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
32
|
-
const statusParam = (status || 'All').toString().toLowerCase();
|
|
33
|
-
const whereClause = { userId: unAuthData.id };
|
|
34
|
-
if (statusParam === 'called') whereClause.status = 'called';
|
|
35
|
-
else if (['not called', 'not_called', 'notcalled'].includes(statusParam)) whereClause.status = { [Op.ne]: 'called' };
|
|
36
|
-
const items = await CallDownListModel.findAll({ where: whereClause, order: [["scheduledAt", "ASC"]] });
|
|
37
|
-
return { items };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function remove({ jwtToken, id }) {
|
|
41
|
-
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
42
|
-
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
43
|
-
const deleted = await CallDownListModel.destroy({ where: { id, userId: unAuthData.id } });
|
|
44
|
-
if (!deleted) throw new Error('Not found');
|
|
45
|
-
return { successful: true };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function markCalled({ jwtToken, id, lastCallAt }) {
|
|
49
|
-
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
50
|
-
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
51
|
-
const when = lastCallAt ? new Date(lastCallAt) : new Date();
|
|
52
|
-
try {
|
|
53
|
-
const [affected] = await CallDownListModel.update({ status: 'called', lastCallAt: when }, { where: { id, userId: unAuthData.id } });
|
|
54
|
-
if (!affected) throw new Error('Not found');
|
|
55
|
-
return { successful: true };
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
return handleDatabaseError(error, 'Error marking call as called', { id, userId: unAuthData.id });
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function update({ jwtToken, id, updateData }) {
|
|
63
|
-
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
64
|
-
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
65
|
-
|
|
66
|
-
// Prepare the update object with only valid fields
|
|
67
|
-
const allowedFields = ['contactId', 'contactType', 'contactName', 'phoneNumber', 'status', 'scheduledAt', 'lastCallAt', 'note'];
|
|
68
|
-
const updateObject = {};
|
|
69
|
-
|
|
70
|
-
// Filter and prepare update data
|
|
71
|
-
Object.keys(updateData).forEach(key => {
|
|
72
|
-
if (allowedFields.includes(key)) {
|
|
73
|
-
let value = updateData[key];
|
|
74
|
-
|
|
75
|
-
// Handle date fields
|
|
76
|
-
if ((key === 'scheduledAt' || key === 'lastCallAt') && value) {
|
|
77
|
-
value = new Date(value);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
updateObject[key] = value;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// If no valid fields to update, throw error
|
|
85
|
-
if (Object.keys(updateObject).length === 0) {
|
|
86
|
-
throw new Error('No valid fields to update');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const [affected] = await CallDownListModel.update(updateObject, { where: { id, userId: unAuthData.id } });
|
|
90
|
-
if (!affected) throw new Error('Not found');
|
|
91
|
-
return { successful: true };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
exports.schedule = schedule;
|
|
95
|
-
exports.list = list;
|
|
96
|
-
exports.remove = remove;
|
|
97
|
-
exports.markCalled = markCalled;
|
|
98
|
-
exports.update = update;
|
|
99
|
-
|
|
1
|
+
const { UserModel } = require('../models/userModel');
|
|
2
|
+
const { CallDownListModel } = require('../models/callDownListModel');
|
|
3
|
+
const { Op } = require('sequelize');
|
|
4
|
+
const jwt = require('../lib/jwt');
|
|
5
|
+
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
6
|
+
|
|
7
|
+
async function schedule({ jwtToken, body }) {
|
|
8
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
9
|
+
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
10
|
+
const user = await UserModel.findByPk(unAuthData.id);
|
|
11
|
+
if (!user) throw new Error('User not found');
|
|
12
|
+
const crypto = require('crypto');
|
|
13
|
+
const recordId = crypto.randomBytes(16).toString('hex');
|
|
14
|
+
const payload = {
|
|
15
|
+
id: recordId,
|
|
16
|
+
userId: user.id,
|
|
17
|
+
contactId: body.contactId?.toString?.() ?? body.contactId,
|
|
18
|
+
contactType: body.contactType ?? 'contact',
|
|
19
|
+
contactName: body.contactName ?? '',
|
|
20
|
+
phoneNumber: body.phoneNumber ?? '',
|
|
21
|
+
status: 'scheduled',
|
|
22
|
+
scheduledAt: body.scheduledAt ? new Date(body.scheduledAt) : null,
|
|
23
|
+
lastCallAt: null
|
|
24
|
+
};
|
|
25
|
+
await CallDownListModel.create(payload);
|
|
26
|
+
return { id: recordId };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function list({ jwtToken, status }) {
|
|
30
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
31
|
+
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
32
|
+
const statusParam = (status || 'All').toString().toLowerCase();
|
|
33
|
+
const whereClause = { userId: unAuthData.id };
|
|
34
|
+
if (statusParam === 'called') whereClause.status = 'called';
|
|
35
|
+
else if (['not called', 'not_called', 'notcalled'].includes(statusParam)) whereClause.status = { [Op.ne]: 'called' };
|
|
36
|
+
const items = await CallDownListModel.findAll({ where: whereClause, order: [["scheduledAt", "ASC"]] });
|
|
37
|
+
return { items };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function remove({ jwtToken, id }) {
|
|
41
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
42
|
+
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
43
|
+
const deleted = await CallDownListModel.destroy({ where: { id, userId: unAuthData.id } });
|
|
44
|
+
if (!deleted) throw new Error('Not found');
|
|
45
|
+
return { successful: true };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function markCalled({ jwtToken, id, lastCallAt }) {
|
|
49
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
50
|
+
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
51
|
+
const when = lastCallAt ? new Date(lastCallAt) : new Date();
|
|
52
|
+
try {
|
|
53
|
+
const [affected] = await CallDownListModel.update({ status: 'called', lastCallAt: when }, { where: { id, userId: unAuthData.id } });
|
|
54
|
+
if (!affected) throw new Error('Not found');
|
|
55
|
+
return { successful: true };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return handleDatabaseError(error, 'Error marking call as called', { id, userId: unAuthData.id });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function update({ jwtToken, id, updateData }) {
|
|
63
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
64
|
+
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
65
|
+
|
|
66
|
+
// Prepare the update object with only valid fields
|
|
67
|
+
const allowedFields = ['contactId', 'contactType', 'contactName', 'phoneNumber', 'status', 'scheduledAt', 'lastCallAt', 'note'];
|
|
68
|
+
const updateObject = {};
|
|
69
|
+
|
|
70
|
+
// Filter and prepare update data
|
|
71
|
+
Object.keys(updateData).forEach(key => {
|
|
72
|
+
if (allowedFields.includes(key)) {
|
|
73
|
+
let value = updateData[key];
|
|
74
|
+
|
|
75
|
+
// Handle date fields
|
|
76
|
+
if ((key === 'scheduledAt' || key === 'lastCallAt') && value) {
|
|
77
|
+
value = new Date(value);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
updateObject[key] = value;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// If no valid fields to update, throw error
|
|
85
|
+
if (Object.keys(updateObject).length === 0) {
|
|
86
|
+
throw new Error('No valid fields to update');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const [affected] = await CallDownListModel.update(updateObject, { where: { id, userId: unAuthData.id } });
|
|
90
|
+
if (!affected) throw new Error('Not found');
|
|
91
|
+
return { successful: true };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
exports.schedule = schedule;
|
|
95
|
+
exports.list = list;
|
|
96
|
+
exports.remove = remove;
|
|
97
|
+
exports.markCalled = markCalled;
|
|
98
|
+
exports.update = update;
|
|
99
|
+
|