@app-connect/core 1.7.37 → 1.7.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/README.md +17 -16
  2. package/dist/connector/developerPortal.d.ts +6 -0
  3. package/{connector → dist/connector}/developerPortal.js +29 -12
  4. package/dist/connector/mock.d.ts +1 -0
  5. package/{connector → dist/connector}/mock.js +33 -17
  6. package/dist/connector/proxy/engine.d.ts +10 -0
  7. package/dist/connector/proxy/engine.js +222 -0
  8. package/dist/connector/proxy/index.d.ts +5 -0
  9. package/dist/connector/proxy/index.js +511 -0
  10. package/dist/connector/registry.d.ts +1 -0
  11. package/dist/connector/registry.js +243 -0
  12. package/dist/handlers/admin.d.ts +1 -0
  13. package/{handlers → dist/handlers}/admin.js +137 -78
  14. package/dist/handlers/appointment.d.ts +9 -0
  15. package/{handlers → dist/handlers}/appointment.js +58 -29
  16. package/dist/handlers/auth.d.ts +9 -0
  17. package/{handlers → dist/handlers}/auth.js +68 -40
  18. package/dist/handlers/calldown.d.ts +10 -0
  19. package/dist/handlers/calldown.js +134 -0
  20. package/dist/handlers/contact.d.ts +1 -0
  21. package/{handlers → dist/handlers}/contact.js +61 -39
  22. package/dist/handlers/disposition.d.ts +1 -0
  23. package/{handlers → dist/handlers}/disposition.js +20 -10
  24. package/dist/handlers/log.d.ts +1 -0
  25. package/{handlers → dist/handlers}/log.js +91 -124
  26. package/dist/handlers/managedAuth.d.ts +1 -0
  27. package/{handlers → dist/handlers}/managedAuth.js +134 -61
  28. package/dist/handlers/managedOAuth.d.ts +13 -0
  29. package/{handlers → dist/handlers}/managedOAuth.js +102 -30
  30. package/dist/handlers/plugin.d.ts +1 -0
  31. package/{handlers → dist/handlers}/plugin.js +59 -27
  32. package/dist/handlers/user.d.ts +1 -0
  33. package/{handlers → dist/handlers}/user.js +45 -27
  34. package/dist/index.d.ts +1 -0
  35. package/{index.js → dist/index.js} +538 -449
  36. package/dist/jest.config.d.ts +1 -0
  37. package/dist/jest.config.js +65 -0
  38. package/dist/lib/analytics.d.ts +4 -0
  39. package/{lib → dist/lib}/analytics.js +8 -6
  40. package/dist/lib/authSession.d.ts +5 -0
  41. package/{lib → dist/lib}/authSession.js +15 -43
  42. package/dist/lib/cacheCleanup.d.ts +4 -0
  43. package/{lib → dist/lib}/cacheCleanup.js +5 -17
  44. package/dist/lib/callLogComposer.d.ts +109 -0
  45. package/{lib → dist/lib}/callLogComposer.js +157 -197
  46. package/dist/lib/callLogLookup.d.ts +6 -0
  47. package/{lib → dist/lib}/callLogLookup.js +12 -34
  48. package/dist/lib/constants.d.ts +6 -0
  49. package/dist/lib/constants.js +9 -0
  50. package/dist/lib/debugTracer.d.ts +17 -0
  51. package/{lib → dist/lib}/debugTracer.js +7 -83
  52. package/dist/lib/encode.d.ts +3 -0
  53. package/dist/lib/encode.js +50 -0
  54. package/dist/lib/errorHandler.d.ts +7 -0
  55. package/dist/lib/errorHandler.js +161 -0
  56. package/dist/lib/generalErrorMessage.d.ts +7 -0
  57. package/{lib → dist/lib}/generalErrorMessage.js +6 -6
  58. package/dist/lib/jwt.d.ts +4 -0
  59. package/dist/lib/jwt.js +18 -0
  60. package/dist/lib/logger.d.ts +24 -0
  61. package/dist/lib/logger.js +126 -0
  62. package/dist/lib/migrateCallLogsSchema.d.ts +32 -0
  63. package/{lib → dist/lib}/migrateCallLogsSchema.js +75 -160
  64. package/dist/lib/oauth.d.ts +4 -0
  65. package/{lib → dist/lib}/oauth.js +157 -160
  66. package/dist/lib/ringcentral.d.ts +24 -0
  67. package/dist/lib/ringcentral.js +226 -0
  68. package/dist/lib/s3ErrorLogReport.d.ts +4 -0
  69. package/{lib → dist/lib}/s3ErrorLogReport.js +11 -23
  70. package/dist/lib/sharedSMSComposer.d.ts +7 -0
  71. package/{lib → dist/lib}/sharedSMSComposer.js +21 -107
  72. package/dist/lib/util.d.ts +7 -0
  73. package/{lib → dist/lib}/util.js +9 -20
  74. package/dist/mcp/lib/oauthError.d.ts +1 -0
  75. package/dist/mcp/lib/oauthError.js +25 -0
  76. package/dist/mcp/lib/validator.d.ts +1 -0
  77. package/{mcp → dist/mcp}/lib/validator.js +16 -20
  78. package/dist/mcp/lib/widgetSessionToken.d.ts +1 -0
  79. package/dist/mcp/lib/widgetSessionToken.js +46 -0
  80. package/dist/mcp/mcpHandler.d.ts +8 -0
  81. package/{mcp → dist/mcp}/mcpHandler.js +98 -88
  82. package/dist/mcp/tools/cancelAppointment.d.ts +1 -0
  83. package/{mcp → dist/mcp}/tools/cancelAppointment.js +7 -16
  84. package/dist/mcp/tools/checkAuthStatus.d.ts +1 -0
  85. package/{mcp → dist/mcp}/tools/checkAuthStatus.js +21 -14
  86. package/dist/mcp/tools/confirmAppointment.d.ts +1 -0
  87. package/{mcp → dist/mcp}/tools/confirmAppointment.js +7 -16
  88. package/dist/mcp/tools/createAppointment.d.ts +1 -0
  89. package/{mcp → dist/mcp}/tools/createAppointment.js +7 -19
  90. package/dist/mcp/tools/createCallLog.d.ts +1 -0
  91. package/{mcp → dist/mcp}/tools/createCallLog.js +18 -29
  92. package/dist/mcp/tools/createContact.d.ts +1 -0
  93. package/{mcp → dist/mcp}/tools/createContact.js +8 -20
  94. package/dist/mcp/tools/createMessageLog.d.ts +1 -0
  95. package/{mcp → dist/mcp}/tools/createMessageLog.js +14 -26
  96. package/dist/mcp/tools/doAuth.d.ts +1 -0
  97. package/{mcp → dist/mcp}/tools/doAuth.js +17 -13
  98. package/dist/mcp/tools/findContactByName.d.ts +1 -0
  99. package/{mcp → dist/mcp}/tools/findContactByName.js +9 -15
  100. package/dist/mcp/tools/findContactByPhone.d.ts +1 -0
  101. package/{mcp → dist/mcp}/tools/findContactByPhone.js +8 -15
  102. package/dist/mcp/tools/getCallLog.d.ts +1 -0
  103. package/{mcp → dist/mcp}/tools/getCallLog.js +12 -21
  104. package/dist/mcp/tools/getGoogleFilePicker.d.ts +1 -0
  105. package/{mcp → dist/mcp}/tools/getGoogleFilePicker.js +9 -18
  106. package/dist/mcp/tools/getHelp.d.ts +1 -0
  107. package/{mcp → dist/mcp}/tools/getHelp.js +5 -6
  108. package/dist/mcp/tools/getPublicConnectors.d.ts +1 -0
  109. package/{mcp → dist/mcp}/tools/getPublicConnectors.js +19 -18
  110. package/dist/mcp/tools/getSessionInfo.d.ts +1 -0
  111. package/{mcp → dist/mcp}/tools/getSessionInfo.js +10 -16
  112. package/dist/mcp/tools/index.d.ts +8 -0
  113. package/dist/mcp/tools/index.js +50 -0
  114. package/dist/mcp/tools/listAppointments.d.ts +1 -0
  115. package/{mcp → dist/mcp}/tools/listAppointments.js +7 -19
  116. package/dist/mcp/tools/logout.d.ts +1 -0
  117. package/{mcp → dist/mcp}/tools/logout.js +16 -14
  118. package/dist/mcp/tools/rcGetCallLogs.d.ts +1 -0
  119. package/{mcp → dist/mcp}/tools/rcGetCallLogs.js +10 -8
  120. package/dist/mcp/tools/updateAppointment.d.ts +1 -0
  121. package/{mcp → dist/mcp}/tools/updateAppointment.js +17 -22
  122. package/dist/mcp/tools/updateCallLog.d.ts +1 -0
  123. package/{mcp → dist/mcp}/tools/updateCallLog.js +16 -26
  124. package/dist/models/accountDataModel.d.ts +3 -0
  125. package/dist/models/accountDataModel.js +39 -0
  126. package/dist/models/adminConfigModel.d.ts +2 -0
  127. package/dist/models/adminConfigModel.js +39 -0
  128. package/dist/models/cacheModel.d.ts +2 -0
  129. package/{models → dist/models}/cacheModel.js +7 -3
  130. package/dist/models/callDownListModel.d.ts +2 -0
  131. package/{models → dist/models}/callDownListModel.js +8 -4
  132. package/dist/models/callLogModel.d.ts +2 -0
  133. package/dist/models/callLogModel.js +43 -0
  134. package/dist/models/dynamo/connectorSchema.d.ts +2 -0
  135. package/dist/models/dynamo/connectorSchema.js +141 -0
  136. package/dist/models/dynamo/lockSchema.d.ts +2 -0
  137. package/{models → dist/models}/dynamo/lockSchema.js +5 -7
  138. package/dist/models/dynamo/noteCacheSchema.d.ts +2 -0
  139. package/{models → dist/models}/dynamo/noteCacheSchema.js +4 -6
  140. package/dist/models/llmSessionModel.d.ts +2 -0
  141. package/dist/models/llmSessionModel.js +21 -0
  142. package/dist/models/messageLogModel.d.ts +2 -0
  143. package/{models → dist/models}/messageLogModel.js +8 -4
  144. package/dist/models/sequelize.d.ts +2 -0
  145. package/dist/models/sequelize.js +68 -0
  146. package/dist/models/userModel.d.ts +2 -0
  147. package/dist/models/userModel.js +49 -0
  148. package/dist/package.json +100 -0
  149. package/dist/releaseNotes.json +1222 -0
  150. package/dist/tsconfig.json +14 -0
  151. package/dist/types/admin.d.ts +141 -0
  152. package/dist/types/analytics.d.ts +14 -0
  153. package/dist/types/appointment.d.ts +50 -0
  154. package/dist/types/auth.d.ts +137 -0
  155. package/dist/types/authSession.d.ts +35 -0
  156. package/dist/types/cacheCleanup.d.ts +12 -0
  157. package/dist/types/calldown.d.ts +54 -0
  158. package/dist/types/common.d.ts +46 -0
  159. package/dist/types/connector.d.ts +165 -0
  160. package/dist/types/contact.d.ts +125 -0
  161. package/dist/types/errorHandler.d.ts +60 -0
  162. package/dist/types/index.d.ts +76 -0
  163. package/dist/types/json.d.ts +9 -0
  164. package/dist/types/jwt.d.ts +8 -0
  165. package/dist/types/logging.d.ts +224 -0
  166. package/dist/types/managedAuth.d.ts +114 -0
  167. package/dist/types/managedOAuth.d.ts +59 -0
  168. package/dist/types/manifest.d.ts +120 -0
  169. package/dist/types/migration.d.ts +15 -0
  170. package/dist/types/plugin.d.ts +74 -0
  171. package/dist/types/ringcentral.d.ts +61 -0
  172. package/dist/types/s3ErrorLogReport.d.ts +16 -0
  173. package/dist/types/sharedSMSComposer.d.ts +105 -0
  174. package/dist/types/user.d.ts +46 -0
  175. package/dist/types/util.d.ts +7 -0
  176. package/package.json +34 -6
  177. package/releaseNotes.json +8 -0
  178. package/.env.test +0 -5
  179. package/connector/proxy/engine.js +0 -165
  180. package/connector/proxy/index.js +0 -500
  181. package/connector/registry.js +0 -252
  182. package/docs/README.md +0 -50
  183. package/docs/architecture.md +0 -94
  184. package/docs/connectors.md +0 -116
  185. package/docs/handlers.md +0 -128
  186. package/docs/libraries.md +0 -98
  187. package/docs/models.md +0 -146
  188. package/docs/routes.md +0 -119
  189. package/docs/tests.md +0 -73
  190. package/handlers/calldown.js +0 -99
  191. package/jest.config.js +0 -57
  192. package/lib/constants.js +0 -9
  193. package/lib/encode.js +0 -30
  194. package/lib/errorHandler.js +0 -218
  195. package/lib/jwt.js +0 -18
  196. package/lib/logger.js +0 -190
  197. package/lib/ringcentral.js +0 -267
  198. package/mcp/README.md +0 -420
  199. package/mcp/tools/index.js +0 -51
  200. package/mcp/ui/App/App.tsx +0 -358
  201. package/mcp/ui/App/components/AuthInfoForm.tsx +0 -113
  202. package/mcp/ui/App/components/AuthSuccess.tsx +0 -22
  203. package/mcp/ui/App/components/ConnectorList.tsx +0 -82
  204. package/mcp/ui/App/components/DebugPanel.tsx +0 -43
  205. package/mcp/ui/App/components/OAuthConnect.tsx +0 -270
  206. package/mcp/ui/App/lib/callTool.ts +0 -130
  207. package/mcp/ui/App/lib/debugLog.ts +0 -41
  208. package/mcp/ui/App/lib/developerPortal.ts +0 -111
  209. package/mcp/ui/App/main.css +0 -6
  210. package/mcp/ui/App/root.tsx +0 -13
  211. package/mcp/ui/dist/index.html +0 -53
  212. package/mcp/ui/vite.config.ts +0 -16
  213. package/models/accountDataModel.js +0 -34
  214. package/models/adminConfigModel.js +0 -35
  215. package/models/callLogModel.js +0 -39
  216. package/models/dynamo/connectorSchema.js +0 -146
  217. package/models/llmSessionModel.js +0 -17
  218. package/models/sequelize.js +0 -17
  219. package/models/userModel.js +0 -45
  220. package/test/connector/developerPortal.test.js +0 -166
  221. package/test/connector/mock.test.js +0 -131
  222. package/test/connector/proxy/engine.test.js +0 -211
  223. package/test/connector/proxy/index.test.js +0 -525
  224. package/test/connector/proxy/sample.json +0 -162
  225. package/test/connector/registry.test.js +0 -416
  226. package/test/handlers/admin.test.js +0 -960
  227. package/test/handlers/appointment.test.js +0 -260
  228. package/test/handlers/auth.test.js +0 -1096
  229. package/test/handlers/calldown.test.js +0 -310
  230. package/test/handlers/contact.test.js +0 -1014
  231. package/test/handlers/disposition.test.js +0 -396
  232. package/test/handlers/log.test.js +0 -1847
  233. package/test/handlers/managedAuth.test.js +0 -458
  234. package/test/handlers/managedOAuth.test.js +0 -262
  235. package/test/handlers/plugin.test.js +0 -429
  236. package/test/handlers/user.test.js +0 -381
  237. package/test/index.test.js +0 -301
  238. package/test/lib/analytics.test.js +0 -146
  239. package/test/lib/authSession.test.js +0 -173
  240. package/test/lib/cacheCleanup.test.js +0 -127
  241. package/test/lib/callLogComposer.test.js +0 -1231
  242. package/test/lib/debugTracer.test.js +0 -328
  243. package/test/lib/encode.test.js +0 -59
  244. package/test/lib/errorHandler.test.js +0 -246
  245. package/test/lib/generalErrorMessage.test.js +0 -82
  246. package/test/lib/jwt.test.js +0 -176
  247. package/test/lib/logger.test.js +0 -206
  248. package/test/lib/oauth.test.js +0 -359
  249. package/test/lib/ringcentral.test.js +0 -467
  250. package/test/lib/s3ErrorLogReport.test.js +0 -187
  251. package/test/lib/sharedSMSComposer.test.js +0 -1084
  252. package/test/lib/util.test.js +0 -329
  253. package/test/mcp/mcpHandler.test.js +0 -73
  254. package/test/mcp/mcpHandlerMore.test.js +0 -384
  255. package/test/mcp/tools/appointmentTools.test.js +0 -362
  256. package/test/mcp/tools/checkAuthStatus.test.js +0 -83
  257. package/test/mcp/tools/createCallLog.test.js +0 -436
  258. package/test/mcp/tools/createContact.test.js +0 -58
  259. package/test/mcp/tools/createMessageLog.test.js +0 -595
  260. package/test/mcp/tools/doAuth.test.js +0 -113
  261. package/test/mcp/tools/findContactByName.test.js +0 -275
  262. package/test/mcp/tools/findContactByPhone.test.js +0 -296
  263. package/test/mcp/tools/getCallLog.test.js +0 -298
  264. package/test/mcp/tools/getGoogleFilePicker.test.js +0 -281
  265. package/test/mcp/tools/getPublicConnectors.test.js +0 -107
  266. package/test/mcp/tools/getSessionInfo.test.js +0 -127
  267. package/test/mcp/tools/logout.test.js +0 -233
  268. package/test/mcp/tools/rcGetCallLogs.test.js +0 -56
  269. package/test/mcp/tools/updateCallLog.test.js +0 -360
  270. package/test/models/accountDataModel.test.js +0 -98
  271. package/test/models/callDownListModel.test.js +0 -125
  272. package/test/models/dynamo/connectorSchema.test.js +0 -189
  273. package/test/models/dynamo/lockSchema.test.js +0 -37
  274. package/test/models/dynamo/noteCacheSchema.test.js +0 -45
  275. package/test/models/llmSessionModel.test.js +0 -91
  276. package/test/models/models.test.js +0 -660
  277. package/test/routes/calldownRoutes.test.js +0 -224
  278. package/test/routes/coreRouterBroadRoutes.test.js +0 -855
  279. package/test/routes/dispositionRoutes.test.js +0 -192
  280. package/test/routes/managedAuthRoutes.test.js +0 -386
  281. package/test/routes/pluginRoutes.test.js +0 -262
  282. package/test/setup.js +0 -178
  283. /package/{mcp → dist/mcp}/ui/index.html +0 -0
  284. /package/{mcp → dist/mcp}/ui/package-lock.json +0 -0
  285. /package/{mcp → dist/mcp}/ui/package.json +0 -0
  286. /package/{mcp → dist/mcp}/ui/tsconfig.json +0 -0
@@ -1,54 +1,58 @@
1
- const express = require('express');
2
- const cors = require('cors')
3
- const bodyParser = require('body-parser');
1
+ "use strict";
2
+ // @ts-check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const express = /** @type {any} */ (require('express'));
5
+ const cors = /** @type {any} */ (require('cors'));
6
+ const bodyParser = /** @type {any} */ (require('body-parser'));
4
7
  require('body-parser-xml')(bodyParser);
5
- const dynamoose = require('dynamoose');
6
- const { DynamoDB } = require('@aws-sdk/client-dynamodb');
7
- const axios = require('axios');
8
- const { UserModel } = require('./models/userModel');
9
- const { LlmSessionModel } = require('./models/llmSessionModel');
10
- const { CallDownListModel } = require('./models/callDownListModel');
11
- const { CallLogModel } = require('./models/callLogModel');
12
- const { MessageLogModel } = require('./models/messageLogModel');
13
- const { AdminConfigModel } = require('./models/adminConfigModel');
14
- const { CacheModel } = require('./models/cacheModel');
15
- const { AccountDataModel } = require('./models/accountDataModel');
16
- const jwt = require('./lib/jwt');
17
- const logCore = require('./handlers/log');
18
- const contactCore = require('./handlers/contact');
19
- const appointmentCore = require('./handlers/appointment');
20
- const authCore = require('./handlers/auth');
21
- const adminCore = require('./handlers/admin');
22
- const userCore = require('./handlers/user');
23
- const dispositionCore = require('./handlers/disposition');
24
- const mock = require('./connector/mock');
25
- const proxyConnector = require('./connector/proxy');
8
+ const dynamoose = /** @type {any} */ (require('dynamoose'));
9
+ const { DynamoDB } = /** @type {any} */ (require('@aws-sdk/client-dynamodb'));
10
+ const axios = /** @type {any} */ (require('axios'));
11
+ const { UserModel } = /** @type {any} */ (require('./models/userModel'));
12
+ const { LlmSessionModel } = /** @type {any} */ (require('./models/llmSessionModel'));
13
+ const { CallDownListModel } = /** @type {any} */ (require('./models/callDownListModel'));
14
+ const { CallLogModel } = /** @type {any} */ (require('./models/callLogModel'));
15
+ const { MessageLogModel } = /** @type {any} */ (require('./models/messageLogModel'));
16
+ const { AdminConfigModel } = /** @type {any} */ (require('./models/adminConfigModel'));
17
+ const { CacheModel } = /** @type {any} */ (require('./models/cacheModel'));
18
+ const { AccountDataModel } = /** @type {any} */ (require('./models/accountDataModel'));
19
+ const jwt = /** @type {any} */ (require('./lib/jwt'));
20
+ const logCore = /** @type {any} */ (require('./handlers/log'));
21
+ const contactCore = /** @type {any} */ (require('./handlers/contact'));
22
+ const appointmentCore = /** @type {any} */ (require('./handlers/appointment'));
23
+ const authCore = /** @type {any} */ (require('./handlers/auth'));
24
+ const adminCore = /** @type {any} */ (require('./handlers/admin'));
25
+ const userCore = /** @type {any} */ (require('./handlers/user'));
26
+ const dispositionCore = /** @type {any} */ (require('./handlers/disposition'));
27
+ const mock = /** @type {any} */ (require('./connector/mock'));
28
+ const proxyConnector = /** @type {any} */ (require('./connector/proxy'));
26
29
  const releaseNotes = require('./releaseNotes.json');
27
- const analytics = require('./lib/analytics');
28
- const util = require('./lib/util');
29
- const connectorRegistry = require('./connector/registry');
30
- const calldown = require('./handlers/calldown');
31
- const mcpHandler = require('./mcp/mcpHandler');
32
- const logger = require('./lib/logger');
33
- const { DebugTracer } = require('./lib/debugTracer');
34
- const s3ErrorLogReport = require('./lib/s3ErrorLogReport');
35
- const pluginCore = require('./handlers/plugin');
36
- const { sequelize } = require('./models/sequelize');
37
- const { runCallLogsSchemaMigration } = require('./lib/migrateCallLogsSchema');
38
- const { handleDatabaseError } = require('./lib/errorHandler');
39
- const { updateAuthSession } = require('./lib/authSession');
40
- const managedAuthCore = require('./handlers/managedAuth');
41
- const managedOAuthCore = require('./handlers/managedOAuth');
42
-
30
+ const analytics = /** @type {any} */ (require('./lib/analytics'));
31
+ const util = /** @type {any} */ (require('./lib/util'));
32
+ const connectorRegistry = /** @type {any} */ (require('./connector/registry'));
33
+ const calldown = /** @type {any} */ (require('./handlers/calldown'));
34
+ const mcpHandler = /** @type {any} */ (require('./mcp/mcpHandler'));
35
+ const logger = /** @type {any} */ (require('./lib/logger'));
36
+ const { DebugTracer } = /** @type {any} */ (require('./lib/debugTracer'));
37
+ const s3ErrorLogReport = /** @type {any} */ (require('./lib/s3ErrorLogReport'));
38
+ const pluginCore = /** @type {any} */ (require('./handlers/plugin'));
39
+ const { sequelize } = /** @type {any} */ (require('./models/sequelize'));
40
+ const { runCallLogsSchemaMigration } = /** @type {any} */ (require('./lib/migrateCallLogsSchema'));
41
+ const { handleDatabaseError } = /** @type {any} */ (require('./lib/errorHandler'));
42
+ const { updateAuthSession } = /** @type {any} */ (require('./lib/authSession'));
43
+ const managedAuthCore = /** @type {any} */ (require('./handlers/managedAuth'));
44
+ const managedOAuthCore = /** @type {any} */ (require('./handlers/managedOAuth'));
45
+ const { MCP_OAUTH_REQUIRED_MESSAGE, MCP_OAUTH_STALE_CLIENT_MESSAGE, getMcpOAuthChallengeHeader, buildMcpOAuthError, } = /** @type {any} */ (require('./mcp/lib/oauthError'));
46
+ /** @type {any} */
43
47
  let packageJson = null;
44
48
  try {
45
49
  packageJson = require('./package.json');
46
50
  }
47
51
  catch (e) {
48
52
  logger.error('Error loading package.json', { stack: e.stack });
49
- packageJson = require('../package.json');
53
+ const fallbackPackageJsonPath = '../package.json';
54
+ packageJson = require(fallbackPackageJsonPath);
50
55
  }
51
-
52
56
  // For using dynamodb in local env
53
57
  // AWS SDK v3 requires a region even for local; ddb.local() omits it, so set manually.
54
58
  if (process.env.DYNAMODB_LOCALHOST) {
@@ -66,7 +70,6 @@ if (process.env.IS_PROD === 'false') {
66
70
  });
67
71
  }
68
72
  axios.defaults.headers.common['Unified-CRM-Extension-Version'] = packageJson.version;
69
-
70
73
  async function initDB() {
71
74
  if (!process.env.DISABLE_SYNC_DB_TABLE) {
72
75
  logger.info('creating db tables if not exist...');
@@ -80,7 +83,6 @@ async function initDB() {
80
83
  await AccountDataModel.sync();
81
84
  }
82
85
  }
83
-
84
86
  function getAnalyticsVariablesInReqHeaders({ headers }) {
85
87
  const hashedExtensionId = headers['rc-extension-id'];
86
88
  const hashedAccountId = headers['rc-account-id'];
@@ -95,12 +97,10 @@ function getAnalyticsVariablesInReqHeaders({ headers }) {
95
97
  userAgent,
96
98
  author,
97
99
  eventAddedVia
98
- }
100
+ };
99
101
  }
100
-
101
102
  const JWT_REFRESH_THRESHOLD_SECONDS = 7 * 24 * 60 * 60; // 1 week
102
103
  const JWT_LEGACY_LONG_LIVED_THRESHOLD_SECONDS = 365 * 24 * 60 * 60; // 1 year
103
-
104
104
  function getBearerTokenFromRequest(req) {
105
105
  const authHeader = req.headers?.authorization || req.headers?.Authorization;
106
106
  if (!authHeader || typeof authHeader !== 'string') {
@@ -112,7 +112,49 @@ function getBearerTokenFromRequest(req) {
112
112
  }
113
113
  return token;
114
114
  }
115
-
115
+ function normalizeTokenValue(value) {
116
+ const token = Array.isArray(value) ? value[0] : value;
117
+ if (typeof token !== 'string') {
118
+ return token || null;
119
+ }
120
+ const trimmedToken = token.trim();
121
+ return trimmedToken.toLowerCase().startsWith('bearer ')
122
+ ? trimmedToken.slice('bearer '.length).trim()
123
+ : trimmedToken;
124
+ }
125
+ function wrapDebugResponse(tracer, payload) {
126
+ if (tracer) {
127
+ return tracer.wrapResponse(payload);
128
+ }
129
+ return payload;
130
+ }
131
+ function getErrorResponse(e) {
132
+ if (e && e.message) {
133
+ return e.message;
134
+ }
135
+ return e;
136
+ }
137
+ function getRcAccessTokenFromRequest(req) {
138
+ return normalizeTokenValue(req.get?.('X-RC-Access-Token')
139
+ || req.headers?.['x-rc-access-token']
140
+ || req.body?.rcAccessToken
141
+ || req.query?.rcAccessToken);
142
+ }
143
+ function getFirstQueryValue(value) {
144
+ if (Array.isArray(value)) {
145
+ return value[0];
146
+ }
147
+ if (value === undefined || value === null) {
148
+ return undefined;
149
+ }
150
+ return value.toString();
151
+ }
152
+ function appendOAuthQueryParam(params, name, value) {
153
+ const normalizedValue = getFirstQueryValue(value);
154
+ if (normalizedValue) {
155
+ params.set(name, normalizedValue);
156
+ }
157
+ }
116
158
  function normalizeJwtFromRequest(req, res, next) {
117
159
  if (req.path?.startsWith('/mcp')) {
118
160
  return next();
@@ -121,19 +163,15 @@ function normalizeJwtFromRequest(req, res, next) {
121
163
  const queryToken = req.query?.jwtToken;
122
164
  let bearerToken = originalBearerToken;
123
165
  const isQueryAuth = !originalBearerToken && !!queryToken;
124
-
125
166
  // Backward compatibility: promote query jwtToken to Authorization Bearer.
126
167
  if (isQueryAuth) {
127
168
  req.headers.authorization = `Bearer ${queryToken}`;
128
169
  bearerToken = queryToken;
129
170
  }
130
-
131
171
  const token = bearerToken;
132
-
133
172
  if (!token) {
134
173
  return next();
135
174
  }
136
-
137
175
  const decodedToken = jwt.decodeJwt(token);
138
176
  if (!decodedToken?.id) {
139
177
  req.invalidJwtToken = true;
@@ -142,10 +180,8 @@ function normalizeJwtFromRequest(req, res, next) {
142
180
  }
143
181
  return next();
144
182
  }
145
-
146
183
  req.jwtToken = token;
147
184
  req.jwtAuth = decodedToken;
148
-
149
185
  if (typeof decodedToken.exp === 'number') {
150
186
  const now = Math.floor(Date.now() / 1000);
151
187
  const timeLeft = decodedToken.exp - now;
@@ -166,12 +202,10 @@ function normalizeJwtFromRequest(req, res, next) {
166
202
  }
167
203
  return next();
168
204
  }
169
-
170
205
  // Create a router with all core routes
171
206
  function createCoreRouter() {
172
207
  const router = express.Router();
173
208
  router.use(normalizeJwtFromRequest);
174
-
175
209
  // Move all app.get, app.post, etc. to router.get, router.post, etc.
176
210
  router.get('/releaseNotes', async function (req, res) {
177
211
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -186,7 +220,7 @@ function createCoreRouter() {
186
220
  ...connectorReleaseNotes[version] ?? {}
187
221
  };
188
222
  }
189
- res.json(tracer ? tracer.wrapResponse(mergedReleaseNotes ?? {}) : (mergedReleaseNotes ?? {}));
223
+ res.json(wrapDebugResponse(tracer, mergedReleaseNotes ?? {}));
190
224
  });
191
225
  // Obsolete
192
226
  router.get('/crmManifest', (req, res) => {
@@ -264,17 +298,17 @@ function createCoreRouter() {
264
298
  result.getLogFormatType = !!platformModule.getLogFormatType;
265
299
  result.refreshUserInfo = !!platformModule.refreshUserInfo;
266
300
  result.cacheCallNote = !!process.env.USE_CACHE;
267
- res.status(200).send(tracer ? tracer.wrapResponse(result) : result);
301
+ res.status(200).send(wrapDebugResponse(tracer, result));
268
302
  }
269
303
  else {
270
304
  tracer?.trace('implementedInterfaces:noPlatform', {});
271
- res.status(400).send(tracer ? tracer.wrapResponse('Please provide platform.') : 'Please provide platform.');
305
+ res.status(400).send(wrapDebugResponse(tracer, 'Please provide platform.'));
272
306
  return;
273
307
  }
274
308
  }
275
309
  catch (e) {
276
310
  tracer?.traceError('implementedInterfaces:error', e);
277
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
311
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
278
312
  }
279
313
  });
280
314
  router.get('/licenseStatus', async (req, res) => {
@@ -284,14 +318,14 @@ function createCoreRouter() {
284
318
  let platformName = null;
285
319
  let success = false;
286
320
  let extraData = {};
287
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
321
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
288
322
  try {
289
323
  const jwtToken = req.jwtToken || req.query.jwtToken;
290
324
  if (jwtToken) {
291
325
  const decodedToken = jwt.decodeJwt(jwtToken);
292
326
  if (!decodedToken) {
293
327
  tracer?.trace('licenseStatus:invalidJwtToken', {});
294
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid JWT token') : 'Invalid JWT token');
328
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid JWT token'));
295
329
  success = false;
296
330
  return;
297
331
  }
@@ -299,36 +333,28 @@ function createCoreRouter() {
299
333
  platformName = platform;
300
334
  if (!userId) {
301
335
  tracer?.trace('licenseStatus:noUserId', {});
302
- res.status(400).send(tracer ? tracer.wrapResponse('No user ID') : 'No user ID');
336
+ res.status(400).send(wrapDebugResponse(tracer, 'No user ID'));
303
337
  success = true;
304
338
  }
305
339
  const licenseStatus = await authCore.getLicenseStatus({ userId, platform });
306
- res.status(200).send(tracer ? tracer.wrapResponse(licenseStatus) : licenseStatus);
340
+ res.status(200).send(wrapDebugResponse(tracer, licenseStatus));
307
341
  success = true;
308
342
  }
309
343
  else {
310
- res.status(200).send(tracer ? tracer.wrapResponse({
311
- isLicenseValid: false,
312
- licenseStatus: 'Invalid (Invalid user session)',
313
- licenseStatusDescription: ''
314
- }) : {
344
+ res.status(200).send(wrapDebugResponse(tracer, {
315
345
  isLicenseValid: false,
316
346
  licenseStatus: 'Invalid (Invalid user session)',
317
347
  licenseStatusDescription: ''
318
- });
348
+ }));
319
349
  success = true;
320
350
  }
321
351
  }
322
352
  catch (e) {
323
- res.status(200).send(tracer ? tracer.wrapResponse({
353
+ res.status(200).send(wrapDebugResponse(tracer, {
324
354
  isLicenseValid: false,
325
355
  licenseStatus: 'Invalid (Connect to get license status)',
326
356
  licenseStatusDescription: ''
327
- }) : {
328
- isLicenseValid: false,
329
- licenseStatus: 'Invalid (Connect to get license status)',
330
- licenseStatusDescription: ''
331
- });
357
+ }));
332
358
  success = false;
333
359
  }
334
360
  const requestEndTime = new Date().getTime();
@@ -358,14 +384,14 @@ function createCoreRouter() {
358
384
  let validationPass = false;
359
385
  let reason = '';
360
386
  let statusCode = 200;
361
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
387
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
362
388
  try {
363
389
  const jwtToken = req.jwtToken || req.query.jwtToken;
364
390
  if (jwtToken) {
365
391
  const decodedToken = jwt.decodeJwt(jwtToken);
366
392
  if (!decodedToken) {
367
393
  tracer?.trace('authValidation:invalidJwtToken', {});
368
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid JWT token') : 'Invalid JWT token');
394
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid JWT token'));
369
395
  return;
370
396
  }
371
397
  const { id: userId, platform } = decodedToken;
@@ -375,11 +401,11 @@ function createCoreRouter() {
375
401
  validationPass = successful;
376
402
  reason = failReason;
377
403
  statusCode = status;
378
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
404
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage }));
379
405
  }
380
406
  else {
381
407
  tracer?.trace('authValidation:noToken', {});
382
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
408
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
383
409
  success = false;
384
410
  }
385
411
  }
@@ -387,7 +413,7 @@ function createCoreRouter() {
387
413
  logger.error('Auth validation failed', { platform: platformName, stack: e.stack });
388
414
  tracer?.traceError('authValidation:error', e);
389
415
  statusCode = e.response?.status ?? 'unknown';
390
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
416
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
391
417
  success = false;
392
418
  }
393
419
  const requestEndTime = new Date().getTime();
@@ -415,13 +441,13 @@ function createCoreRouter() {
415
441
  tracer?.trace('apiKeyManagedAuthState:start', { query: req.query });
416
442
  try {
417
443
  const platform = req.query.platform;
418
- const rcAccessToken = req.query.rcAccessToken;
444
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
419
445
  if (!platform) {
420
- res.status(400).send(tracer ? tracer.wrapResponse('Missing platform name') : 'Missing platform name');
446
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing platform name'));
421
447
  return;
422
448
  }
423
449
  if (!rcAccessToken) {
424
- res.status(400).send(tracer ? tracer.wrapResponse('Missing RingCentral access token') : 'Missing RingCentral access token');
450
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing RingCentral access token'));
425
451
  return;
426
452
  }
427
453
  const { rcAccountId, rcExtensionId } = await adminCore.validateRcUserToken({ rcAccessToken });
@@ -432,12 +458,12 @@ function createCoreRouter() {
432
458
  connectorId: req.query.connectorId,
433
459
  isPrivate: req.query.isPrivate === 'true'
434
460
  });
435
- res.status(200).send(tracer ? tracer.wrapResponse(managedAuthState) : managedAuthState);
461
+ res.status(200).send(wrapDebugResponse(tracer, managedAuthState));
436
462
  }
437
463
  catch (e) {
438
464
  logger.error('Get API key managed auth state failed', { stack: e.stack });
439
465
  tracer?.traceError('apiKeyManagedAuthState:error', e);
440
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
466
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
441
467
  }
442
468
  });
443
469
  router.get('/oauthManagedAuthState', async function (req, res) {
@@ -445,13 +471,13 @@ function createCoreRouter() {
445
471
  tracer?.trace('oauthManagedAuthState:start', { query: req.query });
446
472
  try {
447
473
  const platform = req.query.platform;
448
- const rcAccessToken = req.query.rcAccessToken;
474
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
449
475
  if (!platform) {
450
- res.status(400).send(tracer ? tracer.wrapResponse('Missing platform name') : 'Missing platform name');
476
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing platform name'));
451
477
  return;
452
478
  }
453
479
  if (!rcAccessToken) {
454
- res.status(400).send(tracer ? tracer.wrapResponse('Missing RingCentral access token') : 'Missing RingCentral access token');
480
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing RingCentral access token'));
455
481
  return;
456
482
  }
457
483
  const { rcAccountId } = await adminCore.validateRcUserToken({ rcAccessToken });
@@ -461,12 +487,12 @@ function createCoreRouter() {
461
487
  rcAccountId,
462
488
  isAdmin: !!adminValidation.isValidated
463
489
  });
464
- res.status(200).send(tracer ? tracer.wrapResponse(state) : state);
490
+ res.status(200).send(wrapDebugResponse(tracer, state));
465
491
  }
466
492
  catch (e) {
467
493
  logger.error('Get managed OAuth state failed', { stack: e.stack });
468
494
  tracer?.traceError('oauthManagedAuthState:error', e);
469
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
495
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
470
496
  }
471
497
  });
472
498
  // Obsolete
@@ -479,25 +505,25 @@ function createCoreRouter() {
479
505
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
480
506
  tracer?.trace('setAdminSettings:start', { body: req.body });
481
507
  let success = false;
482
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
508
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
483
509
  try {
484
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
510
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
485
511
  const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
486
512
  if (isValidated) {
487
513
  await adminCore.upsertAdminSettings({ hashedRcAccountId, adminSettings: req.body.adminSettings });
488
- res.status(200).send(tracer ? tracer.wrapResponse('Admin settings updated') : 'Admin settings updated');
514
+ res.status(200).send(wrapDebugResponse(tracer, 'Admin settings updated'));
489
515
  success = true;
490
516
  }
491
517
  else {
492
518
  tracer?.trace('setAdminSettings:adminValidationFailed', {});
493
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
519
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
494
520
  success = false;
495
521
  }
496
522
  }
497
523
  catch (e) {
498
524
  logger.error('Set admin settings failed', { stack: e.stack });
499
525
  tracer?.traceError('setAdminSettings:error', e);
500
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
526
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
501
527
  success = false;
502
528
  }
503
529
  const requestEndTime = new Date().getTime();
@@ -520,7 +546,7 @@ function createCoreRouter() {
520
546
  tracer?.trace('getAdminSettings:start', { query: req.query });
521
547
  let platformName = null;
522
548
  let success = false;
523
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
549
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
524
550
  try {
525
551
  const jwtToken = req.jwtToken || req.query.jwtToken;
526
552
  if (jwtToken) {
@@ -529,43 +555,40 @@ function createCoreRouter() {
529
555
  const user = await UserModel.findByPk(unAuthData?.id);
530
556
  if (!user) {
531
557
  tracer?.trace('getAdminSettings:userNotFound', {});
532
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
558
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
533
559
  return;
534
560
  }
535
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
561
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
536
562
  const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
537
563
  if (isValidated) {
538
564
  const adminSettings = await adminCore.getAdminSettings({ hashedRcAccountId });
539
565
  if (adminSettings) {
540
- res.status(200).send(tracer ? tracer.wrapResponse(adminSettings) : adminSettings);
566
+ res.status(200).send(wrapDebugResponse(tracer, adminSettings));
541
567
  }
542
568
  else {
543
- res.status(200).send(tracer ? tracer.wrapResponse({
569
+ res.status(200).send(wrapDebugResponse(tracer, {
544
570
  customConnector: null,
545
571
  userSettings: {}
546
- }) : {
547
- customConnector: null,
548
- userSettings: {}
549
- });
572
+ }));
550
573
  }
551
574
  success = true;
552
575
  }
553
576
  else {
554
577
  tracer?.trace('getAdminSettings:adminValidationFailed', {});
555
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
578
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
556
579
  success = true;
557
580
  }
558
581
  }
559
582
  else {
560
583
  tracer?.trace('getAdminSettings:noToken', {});
561
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
584
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
562
585
  success = false;
563
586
  }
564
587
  }
565
588
  catch (e) {
566
589
  console.log(`${e.stack}`);
567
590
  tracer?.traceError('getAdminSettings:error', e);
568
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
591
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
569
592
  }
570
593
  const requestEndTime = new Date().getTime();
571
594
  analytics.track({
@@ -588,18 +611,18 @@ function createCoreRouter() {
588
611
  try {
589
612
  const jwtToken = req.jwtToken || req.query.jwtToken;
590
613
  if (!jwtToken) {
591
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
614
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
592
615
  return;
593
616
  }
594
617
  const unAuthData = jwt.decodeJwt(jwtToken);
595
618
  const user = await UserModel.findByPk(unAuthData?.id);
596
619
  if (!user) {
597
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
620
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
598
621
  return;
599
622
  }
600
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
623
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
601
624
  if (!isValidated) {
602
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
625
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
603
626
  return;
604
627
  }
605
628
  const managedAuthSettings = await managedAuthCore.getManagedAuthAdminSettings({
@@ -608,12 +631,12 @@ function createCoreRouter() {
608
631
  connectorId: req.query.connectorId,
609
632
  isPrivate: req.query.isPrivate === 'true'
610
633
  });
611
- res.status(200).send(tracer ? tracer.wrapResponse(managedAuthSettings) : managedAuthSettings);
634
+ res.status(200).send(wrapDebugResponse(tracer, managedAuthSettings));
612
635
  }
613
636
  catch (e) {
614
637
  logger.error('Get managed auth settings failed', { stack: e.stack });
615
638
  tracer?.traceError('getAdminManagedAuth:error', e);
616
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
639
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
617
640
  }
618
641
  });
619
642
  router.post('/admin/managedAuth', async function (req, res) {
@@ -622,18 +645,18 @@ function createCoreRouter() {
622
645
  try {
623
646
  const jwtToken = req.jwtToken || req.query.jwtToken;
624
647
  if (!jwtToken) {
625
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
648
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
626
649
  return;
627
650
  }
628
651
  const unAuthData = jwt.decodeJwt(jwtToken);
629
652
  const user = await UserModel.findByPk(unAuthData?.id);
630
653
  if (!user) {
631
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
654
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
632
655
  return;
633
656
  }
634
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
657
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
635
658
  if (!isValidated) {
636
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
659
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
637
660
  return;
638
661
  }
639
662
  if (req.body?.scope === 'user') {
@@ -654,12 +677,12 @@ function createCoreRouter() {
654
677
  fieldsToRemove: req.body?.fieldsToRemove ?? []
655
678
  });
656
679
  }
657
- res.status(200).send(tracer ? tracer.wrapResponse('Shared authentication updated') : 'Shared authentication updated');
680
+ res.status(200).send(wrapDebugResponse(tracer, 'Shared authentication updated'));
658
681
  }
659
682
  catch (e) {
660
683
  logger.error('Set managed auth settings failed', { stack: e.stack });
661
684
  tracer?.traceError('setAdminManagedAuth:error', e);
662
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
685
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
663
686
  }
664
687
  });
665
688
  router.post('/admin/managedOAuth/cache', async function (req, res) {
@@ -671,64 +694,64 @@ function createCoreRouter() {
671
694
  }
672
695
  });
673
696
  try {
674
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
697
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
675
698
  if (!isValidated) {
676
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
699
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
677
700
  return;
678
701
  }
679
702
  await managedOAuthCore.upsertPendingManagedOAuth({
680
703
  rcAccountId: rcAccountId?.toString(),
681
704
  values: req.body?.values ?? {}
682
705
  });
683
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
706
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
684
707
  }
685
708
  catch (e) {
686
709
  logger.error('Set managed OAuth pending cache failed', { stack: e.stack });
687
710
  tracer?.traceError('setAdminManagedOAuthCache:error', e);
688
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
711
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
689
712
  }
690
713
  });
691
714
  router.delete('/admin/managedOAuth/cache', async function (req, res) {
692
715
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
693
716
  tracer?.trace('deleteAdminManagedOAuthCache:start', {});
694
717
  try {
695
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
718
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
696
719
  if (!isValidated) {
697
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
720
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
698
721
  return;
699
722
  }
700
723
  await managedOAuthCore.clearPendingManagedOAuth({ rcAccountId: rcAccountId?.toString() });
701
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
724
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
702
725
  }
703
726
  catch (e) {
704
727
  logger.error('Delete managed OAuth pending cache failed', { stack: e.stack });
705
728
  tracer?.traceError('deleteAdminManagedOAuthCache:error', e);
706
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
729
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
707
730
  }
708
731
  });
709
732
  router.delete('/admin/managedOAuth/account', async function (req, res) {
710
733
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
711
734
  tracer?.trace('deleteAdminManagedOAuthAccount:start', { query: req.query });
712
735
  try {
713
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
736
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
714
737
  if (!isValidated) {
715
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
738
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
716
739
  return;
717
740
  }
718
741
  if (!req.query.platform) {
719
- res.status(400).send(tracer ? tracer.wrapResponse('Missing platform name') : 'Missing platform name');
742
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing platform name'));
720
743
  return;
721
744
  }
722
745
  await managedOAuthCore.resetManagedOAuth({
723
746
  rcAccountId: rcAccountId?.toString(),
724
747
  platform: req.query.platform
725
748
  });
726
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
749
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
727
750
  }
728
751
  catch (e) {
729
752
  logger.error('Delete managed OAuth account failed', { stack: e.stack });
730
753
  tracer?.traceError('deleteAdminManagedOAuthAccount:error', e);
731
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
754
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
732
755
  }
733
756
  });
734
757
  router.post('/admin/userMapping', async function (req, res) {
@@ -737,7 +760,7 @@ function createCoreRouter() {
737
760
  tracer?.trace('getUserMapping:start', { query: req.query });
738
761
  let platformName = null;
739
762
  let success = false;
740
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
763
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
741
764
  try {
742
765
  const jwtToken = req.jwtToken || req.query.jwtToken;
743
766
  if (jwtToken) {
@@ -746,38 +769,38 @@ function createCoreRouter() {
746
769
  const user = await UserModel.findByPk(unAuthData?.id);
747
770
  if (!user) {
748
771
  tracer?.trace('getUserMapping:userNotFound', {});
749
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
772
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
750
773
  return;
751
774
  }
752
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
775
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
753
776
  const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
754
777
  if (isValidated) {
755
778
  const userMapping = await adminCore.getUserMapping({ user, hashedRcAccountId, rcExtensionList: req.body.rcExtensionList });
756
779
  if (userMapping?.isRevokeUserSession) {
757
- res.status(401).send(tracer ? tracer.wrapResponse(userMapping) : userMapping);
780
+ res.status(401).send(wrapDebugResponse(tracer, userMapping));
758
781
  success = false;
759
782
  }
760
783
  else {
761
- res.status(200).send(tracer ? tracer.wrapResponse(userMapping) : userMapping);
784
+ res.status(200).send(wrapDebugResponse(tracer, userMapping));
762
785
  success = true;
763
786
  }
764
787
  }
765
788
  else {
766
789
  tracer?.trace('getUserMapping:adminValidationFailed', {});
767
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
790
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
768
791
  success = true;
769
792
  }
770
793
  }
771
794
  else {
772
795
  tracer?.trace('getUserMapping:noToken', {});
773
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
796
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
774
797
  success = false;
775
798
  }
776
799
  }
777
800
  catch (e) {
778
801
  logger.error('Get user mapping failed', { stack: e.stack });
779
802
  tracer?.traceError('getUserMapping:error', e);
780
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
803
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
781
804
  }
782
805
  const requestEndTime = new Date().getTime();
783
806
  analytics.track({
@@ -800,7 +823,7 @@ function createCoreRouter() {
800
823
  tracer?.trace('reinitializeUserMapping:start', { body: req.body });
801
824
  let platformName = null;
802
825
  let success = false;
803
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
826
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
804
827
  try {
805
828
  const jwtToken = req.jwtToken || req.query.jwtToken;
806
829
  if (jwtToken) {
@@ -809,38 +832,38 @@ function createCoreRouter() {
809
832
  const user = await UserModel.findByPk(unAuthData?.id);
810
833
  if (!user) {
811
834
  tracer?.trace('reinitializeUserMapping:userNotFound', {});
812
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
835
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
813
836
  return;
814
837
  }
815
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
838
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: getRcAccessTokenFromRequest(req) });
816
839
  const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
817
840
  if (isValidated) {
818
841
  const userMapping = await adminCore.reinitializeUserMapping({ user, hashedRcAccountId, rcExtensionList: req.body.rcExtensionList });
819
842
  if (userMapping?.isRevokeUserSession) {
820
- res.status(401).send(tracer ? tracer.wrapResponse(userMapping) : userMapping);
843
+ res.status(401).send(wrapDebugResponse(tracer, userMapping));
821
844
  success = false;
822
845
  }
823
846
  else {
824
- res.status(200).send(tracer ? tracer.wrapResponse(userMapping) : userMapping);
847
+ res.status(200).send(wrapDebugResponse(tracer, userMapping));
825
848
  success = true;
826
849
  }
827
850
  }
828
851
  else {
829
852
  tracer?.trace('reinitializeUserMapping:adminValidationFailed', {});
830
- res.status(403).send(tracer ? tracer.wrapResponse('Admin validation failed') : 'Admin validation failed');
853
+ res.status(403).send(wrapDebugResponse(tracer, 'Admin validation failed'));
831
854
  success = true;
832
855
  }
833
856
  }
834
857
  else {
835
858
  tracer?.trace('reinitializeUserMapping:noToken', {});
836
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
859
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
837
860
  success = false;
838
861
  }
839
862
  }
840
863
  catch (e) {
841
864
  logger.error('Reinitialize user mapping failed', { stack: e.stack });
842
865
  tracer?.traceError('reinitializeUserMapping:error', e);
843
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
866
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
844
867
  }
845
868
  const requestEndTime = new Date().getTime();
846
869
  analytics.track({
@@ -866,32 +889,32 @@ function createCoreRouter() {
866
889
  const jwtToken = req.jwtToken || req.query.jwtToken;
867
890
  if (!jwtToken) {
868
891
  tracer?.trace('getServerLoggingSettings:noToken', {});
869
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
892
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
870
893
  return;
871
894
  }
872
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
895
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
873
896
  try {
874
897
  const unAuthData = jwt.decodeJwt(jwtToken);
875
898
  if (!unAuthData?.id) {
876
899
  tracer?.trace('getServerLoggingSettings:noToken', {});
877
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
900
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
878
901
  return;
879
902
  }
880
903
  platformName = unAuthData?.platform ?? 'Unknown';
881
904
  const user = await UserModel.findByPk(unAuthData?.id);
882
905
  if (!user) {
883
906
  tracer?.trace('getServerLoggingSettings:userNotFound', {});
884
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
907
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
885
908
  return;
886
909
  }
887
910
  const serverLoggingSettings = await adminCore.getServerLoggingSettings({ user });
888
- res.status(200).send(tracer ? tracer.wrapResponse(serverLoggingSettings) : serverLoggingSettings);
911
+ res.status(200).send(wrapDebugResponse(tracer, serverLoggingSettings));
889
912
  success = true;
890
913
  }
891
914
  catch (e) {
892
915
  logger.error('Get server logging settings failed', { stack: e.stack });
893
916
  tracer?.traceError('getServerLoggingSettings:error', e);
894
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
917
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
895
918
  }
896
919
  const requestEndTime = new Date().getTime();
897
920
  analytics.track({
@@ -917,37 +940,37 @@ function createCoreRouter() {
917
940
  const jwtToken = req.jwtToken || req.query.jwtToken;
918
941
  if (!jwtToken) {
919
942
  tracer?.trace('setServerLoggingSettings:noToken', {});
920
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
943
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
921
944
  return;
922
945
  }
923
946
  if (!req.body.additionalFieldValues) {
924
947
  tracer?.trace('setServerLoggingSettings:missingAdditionalFieldValues', {});
925
- res.status(400).send(tracer ? tracer.wrapResponse('Missing additionalFieldValues') : 'Missing additionalFieldValues');
948
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing additionalFieldValues'));
926
949
  return;
927
950
  }
928
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
951
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
929
952
  try {
930
953
  const unAuthData = jwt.decodeJwt(jwtToken);
931
954
  if (!unAuthData?.id) {
932
955
  tracer?.trace('setServerLoggingSettings:noToken', {});
933
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
956
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
934
957
  return;
935
958
  }
936
959
  platformName = unAuthData?.platform ?? 'Unknown';
937
960
  const user = await UserModel.findByPk(unAuthData?.id);
938
961
  if (!user) {
939
962
  tracer?.trace('setServerLoggingSettings:userNotFound', {});
940
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
963
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
941
964
  return;
942
965
  }
943
966
  const { successful, returnMessage } = await adminCore.updateServerLoggingSettings({ user, additionalFieldValues: req.body.additionalFieldValues });
944
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
967
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage }));
945
968
  success = true;
946
969
  }
947
970
  catch (e) {
948
971
  logger.error('Set server logging settings failed', { stack: e.stack });
949
972
  tracer?.traceError('setServerLoggingSettings:error', e);
950
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: { messageType: 'warning', message: 'Server logging settings update failed', ttl: 5000 } }) : { successful: false, returnMessage: { messageType: 'warning', message: 'Server logging settings update failed', ttl: 5000 } });
973
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: { messageType: 'warning', message: 'Server logging settings update failed', ttl: 5000 } }));
951
974
  success = false;
952
975
  }
953
976
  const requestEndTime = new Date().getTime();
@@ -964,36 +987,35 @@ function createCoreRouter() {
964
987
  author,
965
988
  eventAddedVia
966
989
  });
967
- })
990
+ });
968
991
  router.get('/user/preloadSettings', async function (req, res) {
969
992
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
970
993
  tracer?.trace('getUserSettingsByAdmin:start', { query: req.query });
971
994
  try {
972
- const rcAccessToken = req.query.rcAccessToken;
995
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
973
996
  const rcAccountId = req.query.rcAccountId;
974
997
  if (rcAccessToken || rcAccountId) {
975
998
  const userSettings = await userCore.getUserSettingsByAdmin({ rcAccessToken, rcAccountId });
976
- res.status(200).send(tracer ? tracer.wrapResponse(userSettings) : userSettings);
999
+ res.status(200).send(wrapDebugResponse(tracer, userSettings));
977
1000
  }
978
1001
  else {
979
1002
  tracer?.trace('getUserSettingsByAdmin:noRcAccessTokenOrRcAccountId', {});
980
- res.status(400).send(tracer ? tracer.wrapResponse('Cannot find rc user login') : 'Cannot find rc user login');
1003
+ res.status(400).send(wrapDebugResponse(tracer, 'Cannot find rc user login'));
981
1004
  }
982
1005
  }
983
1006
  catch (e) {
984
1007
  logger.error('Get user preload settings failed', { stack: e.stack });
985
1008
  tracer?.traceError('getUserSettingsByAdmin:error', e);
986
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1009
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
987
1010
  }
988
- }
989
- );
1011
+ });
990
1012
  router.post('/user/refreshInfo', async function (req, res) {
991
1013
  const requestStartTime = new Date().getTime();
992
1014
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
993
1015
  tracer?.trace('refreshUserInfo:start', { body: req.body });
994
1016
  let platformName = null;
995
1017
  let success = false;
996
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1018
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
997
1019
  try {
998
1020
  const jwtToken = req.jwtToken || req.query.jwtToken;
999
1021
  if (jwtToken) {
@@ -1001,19 +1023,19 @@ function createCoreRouter() {
1001
1023
  platformName = unAuthData?.platform ?? 'Unknown';
1002
1024
  const userId = unAuthData?.id;
1003
1025
  const { successful, returnMessage } = await userCore.refreshUserInfo({ platform: platformName, userId, tracer });
1004
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1026
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1005
1027
  success = true;
1006
1028
  }
1007
1029
  else {
1008
1030
  tracer?.trace('refreshUserInfo:noToken', {});
1009
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1031
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1010
1032
  success = false;
1011
1033
  }
1012
1034
  }
1013
1035
  catch (e) {
1014
1036
  logger.error('Refresh user info failed', { platform: platformName, stack: e.stack });
1015
1037
  tracer?.traceError('refreshUserInfo:error', e, { platform: platformName });
1016
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1038
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1017
1039
  }
1018
1040
  const requestEndTime = new Date().getTime();
1019
1041
  analytics.track({
@@ -1029,14 +1051,14 @@ function createCoreRouter() {
1029
1051
  author,
1030
1052
  eventAddedVia
1031
1053
  });
1032
- })
1054
+ });
1033
1055
  router.get('/user/settings', async function (req, res) {
1034
1056
  const requestStartTime = new Date().getTime();
1035
1057
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
1036
1058
  tracer?.trace('getUserSettings:start', { query: req.query });
1037
1059
  let platformName = null;
1038
1060
  let success = false;
1039
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1061
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1040
1062
  try {
1041
1063
  const jwtToken = req.jwtToken || req.query.jwtToken;
1042
1064
  if (jwtToken) {
@@ -1044,33 +1066,33 @@ function createCoreRouter() {
1044
1066
  platformName = unAuthData?.platform ?? 'Unknown';
1045
1067
  if (!unAuthData || !unAuthData?.id) {
1046
1068
  tracer?.trace('getUserSettings:noToken', {});
1047
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1069
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1048
1070
  return;
1049
1071
  }
1050
1072
  const user = await UserModel.findByPk(unAuthData?.id);
1051
1073
  if (!user) {
1052
1074
  tracer?.trace('getUserSettings:userNotFound', {});
1053
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
1075
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
1054
1076
  return;
1055
1077
  }
1056
1078
  else {
1057
- const rcAccessToken = req.query.rcAccessToken;
1079
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
1058
1080
  const rcAccountId = req.query.rcAccountId;
1059
1081
  const userSettings = await userCore.getUserSettings({ user, rcAccessToken, rcAccountId });
1060
1082
  success = true;
1061
- res.status(200).send(tracer ? tracer.wrapResponse(userSettings) : userSettings);
1083
+ res.status(200).send(wrapDebugResponse(tracer, userSettings));
1062
1084
  }
1063
1085
  }
1064
1086
  else {
1065
1087
  success = false;
1066
1088
  tracer?.trace('getUserSettings:noToken', {});
1067
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1089
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1068
1090
  }
1069
1091
  }
1070
1092
  catch (e) {
1071
1093
  logger.error('Get user settings failed', { platform: platformName, stack: e.stack });
1072
1094
  tracer?.traceError('getUserSettings:error', e, { platform: platformName });
1073
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1095
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1074
1096
  }
1075
1097
  const requestEndTime = new Date().getTime();
1076
1098
  analytics.track({
@@ -1093,7 +1115,7 @@ function createCoreRouter() {
1093
1115
  tracer?.trace('setUserSettings:start', { body: req.body });
1094
1116
  let platformName = null;
1095
1117
  let success = false;
1096
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1118
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1097
1119
  try {
1098
1120
  const jwtToken = req.jwtToken || req.query.jwtToken;
1099
1121
  if (jwtToken) {
@@ -1101,29 +1123,29 @@ function createCoreRouter() {
1101
1123
  platformName = unAuthData?.platform;
1102
1124
  if (!platformName) {
1103
1125
  tracer?.trace('setUserSettings:unknownPlatform', {});
1104
- res.status(400).send(tracer ? tracer.wrapResponse('Unknown platform') : 'Unknown platform');
1126
+ res.status(400).send(wrapDebugResponse(tracer, 'Unknown platform'));
1105
1127
  return;
1106
1128
  }
1107
1129
  const user = await UserModel.findByPk(unAuthData?.id);
1108
1130
  if (!user) {
1109
1131
  tracer?.trace('setUserSettings:userNotFound', {});
1110
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
1132
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
1111
1133
  return;
1112
1134
  }
1113
1135
  const { userSettings } = await userCore.updateUserSettings({ user, userSettings: req.body.userSettings, settingKeysToRemove: req.body.settingKeysToRemove || [], platformName });
1114
- res.status(200).send(tracer ? tracer.wrapResponse({ userSettings }) : { userSettings });
1136
+ res.status(200).send(wrapDebugResponse(tracer, { userSettings }));
1115
1137
  success = true;
1116
1138
  }
1117
1139
  else {
1118
1140
  tracer?.trace('setUserSettings:noToken', {});
1119
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1141
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1120
1142
  success = false;
1121
1143
  }
1122
1144
  }
1123
1145
  catch (e) {
1124
1146
  logger.error('Set user settings failed', { platform: platformName, stack: e.stack });
1125
1147
  tracer?.traceError('setUserSettings:error', e, { platform: platformName });
1126
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1148
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1127
1149
  }
1128
1150
  const requestEndTime = new Date().getTime();
1129
1151
  analytics.track({
@@ -1150,22 +1172,22 @@ function createCoreRouter() {
1150
1172
  const user = await UserModel.findByPk(unAuthData?.id);
1151
1173
  if (!user) {
1152
1174
  tracer?.trace('hostname:userNotFound', {});
1153
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
1175
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
1154
1176
  return;
1155
1177
  }
1156
- res.status(200).send(tracer ? tracer.wrapResponse(user.hostname) : user.hostname);
1178
+ res.status(200).send(wrapDebugResponse(tracer, user.hostname));
1157
1179
  }
1158
1180
  else {
1159
1181
  tracer?.trace('hostname:noToken', {});
1160
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1182
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1161
1183
  }
1162
1184
  }
1163
1185
  catch (e) {
1164
1186
  logger.error('Get hostname failed', { stack: e.stack });
1165
1187
  tracer?.traceError('hostname:error', e);
1166
- res.status(500).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1188
+ res.status(500).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1167
1189
  }
1168
- })
1190
+ });
1169
1191
  router.get('/oauth-callback', async function (req, res) {
1170
1192
  const requestStartTime = new Date().getTime();
1171
1193
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1173,7 +1195,7 @@ function createCoreRouter() {
1173
1195
  let platformName = null;
1174
1196
  let success = false;
1175
1197
  let sessionId = null;
1176
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1198
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1177
1199
  try {
1178
1200
  if (!req.query?.callbackUri || req.query.callbackUri === 'undefined') {
1179
1201
  // case: from mcp
@@ -1183,7 +1205,7 @@ function createCoreRouter() {
1183
1205
  }
1184
1206
  else {
1185
1207
  tracer?.trace('oauth-callback:missingCallbackUri', {});
1186
- res.status(400).send(tracer ? tracer.wrapResponse('Missing callbackUri') : 'Missing callbackUri');
1208
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing callbackUri'));
1187
1209
  return;
1188
1210
  }
1189
1211
  }
@@ -1201,7 +1223,7 @@ function createCoreRouter() {
1201
1223
  const tokenUrl = req.query.tokenUrl;
1202
1224
  if (!platformName) {
1203
1225
  tracer?.trace('oauth-callback:missingPlatformName', {});
1204
- res.status(400).send(tracer ? tracer.wrapResponse('Missing platform name') : 'Missing platform name');
1226
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing platform name'));
1205
1227
  return;
1206
1228
  }
1207
1229
  const hasAuthCodeInCallbackUri = req.query.callbackUri.includes('code=');
@@ -1237,12 +1259,12 @@ function createCoreRouter() {
1237
1259
  success = true;
1238
1260
  }
1239
1261
  else {
1240
- res.status(200).send(tracer ? tracer.wrapResponse({ jwtToken, name: userInfo.name, returnMessage }) : { jwtToken, name: userInfo.name, returnMessage });
1262
+ res.status(200).send(wrapDebugResponse(tracer, { jwtToken, name: userInfo.name, returnMessage }));
1241
1263
  success = true;
1242
1264
  }
1243
1265
  }
1244
1266
  else {
1245
- res.status(200).send(tracer ? tracer.wrapResponse({ returnMessage }) : { returnMessage });
1267
+ res.status(200).send(wrapDebugResponse(tracer, { returnMessage }));
1246
1268
  await updateAuthSession(sessionId, {
1247
1269
  status: 'failed',
1248
1270
  errorMessage: returnMessage?.message || 'Authentication failed'
@@ -1253,14 +1275,13 @@ function createCoreRouter() {
1253
1275
  catch (e) {
1254
1276
  logger.error('OAuth callback failed', { platform: platformName, stack: e.stack });
1255
1277
  tracer?.traceError('oauth-callback:error', e, { platform: platformName });
1256
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1278
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1257
1279
  if (sessionId) {
1258
1280
  await updateAuthSession(sessionId, {
1259
1281
  status: 'failed',
1260
- errorMessage: e.message || e.toString()
1282
+ errorMessage: getErrorResponse(e).toString()
1261
1283
  });
1262
1284
  }
1263
-
1264
1285
  success = false;
1265
1286
  }
1266
1287
  const requestEndTime = new Date().getTime();
@@ -1291,7 +1312,7 @@ function createCoreRouter() {
1291
1312
  });
1292
1313
  let platformName = null;
1293
1314
  let success = false;
1294
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1315
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1295
1316
  try {
1296
1317
  const platform = req.body.platform;
1297
1318
  platformName = platform;
@@ -1299,12 +1320,12 @@ function createCoreRouter() {
1299
1320
  const hostname = req.body.hostname;
1300
1321
  const proxyId = req.body.proxyId;
1301
1322
  const additionalInfo = req.body.additionalInfo;
1302
- const rcAccessToken = req.body.rcAccessToken;
1323
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
1303
1324
  const connectorId = req.body.connectorId;
1304
1325
  const isPrivate = !!req.body.isPrivate;
1305
1326
  if (!platform) {
1306
1327
  tracer?.trace('apiKeyLogin:missingPlatform', {});
1307
- res.status(400).send(tracer ? tracer.wrapResponse('Missing platform name') : 'Missing platform name');
1328
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing platform name'));
1308
1329
  return;
1309
1330
  }
1310
1331
  let rcAccountId = null;
@@ -1331,18 +1352,18 @@ function createCoreRouter() {
1331
1352
  id: userInfo.id.toString(),
1332
1353
  platform: platform
1333
1354
  });
1334
- res.status(200).send(tracer ? tracer.wrapResponse({ jwtToken, name: userInfo.name, returnMessage }) : { jwtToken, name: userInfo.name, returnMessage });
1355
+ res.status(200).send(wrapDebugResponse(tracer, { jwtToken, name: userInfo.name, returnMessage }));
1335
1356
  success = true;
1336
1357
  }
1337
1358
  else {
1338
- res.status(400).send(tracer ? tracer.wrapResponse({ returnMessage }) : { returnMessage });
1359
+ res.status(400).send(wrapDebugResponse(tracer, { returnMessage }));
1339
1360
  success = false;
1340
1361
  }
1341
1362
  }
1342
1363
  catch (e) {
1343
1364
  logger.error('API key login failed', { platform: platformName, stack: e.stack });
1344
1365
  tracer?.traceError('apiKeyLogin:error', e, { platform: platformName });
1345
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1366
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1346
1367
  success = false;
1347
1368
  }
1348
1369
  const requestEndTime = new Date().getTime();
@@ -1359,14 +1380,14 @@ function createCoreRouter() {
1359
1380
  author,
1360
1381
  eventAddedVia
1361
1382
  });
1362
- })
1383
+ });
1363
1384
  router.post('/unAuthorize', async function (req, res) {
1364
1385
  const requestStartTime = new Date().getTime();
1365
1386
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
1366
1387
  tracer?.trace('unAuthorize:start', { query: req.query });
1367
1388
  let platformName = null;
1368
1389
  let success = false;
1369
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1390
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1370
1391
  try {
1371
1392
  const jwtToken = req.jwtToken || req.query.jwtToken;
1372
1393
  if (jwtToken) {
@@ -1375,24 +1396,24 @@ function createCoreRouter() {
1375
1396
  const userToLogout = await UserModel.findByPk(unAuthData?.id);
1376
1397
  if (!userToLogout) {
1377
1398
  tracer?.trace('unAuthorize:userNotFound', {});
1378
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
1399
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
1379
1400
  return;
1380
1401
  }
1381
1402
  const platformModule = connectorRegistry.getConnector(unAuthData?.platform ?? 'Unknown');
1382
1403
  const { returnMessage } = await platformModule.unAuthorize({ user: userToLogout });
1383
- res.status(200).send(tracer ? tracer.wrapResponse(returnMessage) : returnMessage);
1404
+ res.status(200).send(wrapDebugResponse(tracer, returnMessage));
1384
1405
  success = true;
1385
1406
  }
1386
1407
  else {
1387
1408
  tracer?.trace('unAuthorize:noToken', {});
1388
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1409
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1389
1410
  success = false;
1390
1411
  }
1391
1412
  }
1392
1413
  catch (e) {
1393
1414
  logger.error('Unauthorize failed', { platform: platformName, stack: e.stack });
1394
1415
  tracer?.traceError('unAuthorize:error', e, { platform: platformName });
1395
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1416
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1396
1417
  success = false;
1397
1418
  }
1398
1419
  const requestEndTime = new Date().getTime();
@@ -1416,24 +1437,23 @@ function createCoreRouter() {
1416
1437
  tracer?.trace('userInfoHash:start', { query: req.query });
1417
1438
  const extensionId = util.getHashValue(req.query.extensionId, process.env.HASH_KEY);
1418
1439
  const accountId = util.getHashValue(req.query.accountId, process.env.HASH_KEY);
1419
- res.status(200).send(tracer ? tracer.wrapResponse({ extensionId, accountId }) : { extensionId, accountId });
1440
+ res.status(200).send(wrapDebugResponse(tracer, { extensionId, accountId }));
1420
1441
  }
1421
1442
  catch (e) {
1422
1443
  logger.error('Get user info hash failed', { stack: e.stack });
1423
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1444
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1424
1445
  tracer?.traceError('userInfoHash:error', e);
1425
1446
  }
1426
- })
1447
+ });
1427
1448
  router.get('/contact', async function (req, res) {
1428
1449
  const requestStartTime = new Date().getTime();
1429
1450
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
1430
1451
  tracer?.trace('findContact:start', { query: req.query });
1431
-
1432
1452
  let platformName = null;
1433
1453
  let success = false;
1434
1454
  let resultCount = 0;
1435
1455
  let extraData = {};
1436
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1456
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1437
1457
  try {
1438
1458
  const jwtToken = req.jwtToken || req.query.jwtToken;
1439
1459
  if (jwtToken) {
@@ -1441,7 +1461,7 @@ function createCoreRouter() {
1441
1461
  tracer?.trace('findContact:jwtDecoded', { decodedToken });
1442
1462
  if (!decodedToken) {
1443
1463
  tracer?.trace('findContact:invalidToken', {});
1444
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1464
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1445
1465
  return;
1446
1466
  }
1447
1467
  const { id: userId, platform } = decodedToken;
@@ -1456,12 +1476,12 @@ function createCoreRouter() {
1456
1476
  isForceRefreshAccountData: req.query?.isForceRefreshAccountData === 'true'
1457
1477
  });
1458
1478
  if (isRevokeUserSession) {
1459
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1479
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1460
1480
  success = false;
1461
1481
  }
1462
1482
  else {
1463
1483
  tracer?.trace('findContact:result', { successful, returnMessage, contact });
1464
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage, contact }) : { successful, returnMessage, contact });
1484
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage, contact }));
1465
1485
  if (successful) {
1466
1486
  const nonNewContact = contact?.filter(c => !c.isNewContact) ?? [];
1467
1487
  resultCount = nonNewContact.length;
@@ -1474,7 +1494,7 @@ function createCoreRouter() {
1474
1494
  }
1475
1495
  else {
1476
1496
  tracer?.trace('findContact:noToken', {});
1477
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1497
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1478
1498
  success = false;
1479
1499
  }
1480
1500
  }
@@ -1482,7 +1502,7 @@ function createCoreRouter() {
1482
1502
  logger.error('Find contact failed', { platform: platformName, stack: e.stack });
1483
1503
  tracer?.traceError('findContact:error', e, { platform: platformName });
1484
1504
  extraData.statusCode = e.response?.status ?? 'unknown';
1485
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1505
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1486
1506
  success = false;
1487
1507
  }
1488
1508
  const requestEndTime = new Date().getTime();
@@ -1511,25 +1531,25 @@ function createCoreRouter() {
1511
1531
  let platformName = null;
1512
1532
  let success = false;
1513
1533
  let extraData = {};
1514
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1534
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1515
1535
  try {
1516
1536
  const jwtToken = req.jwtToken || req.query.jwtToken;
1517
1537
  if (jwtToken) {
1518
1538
  const decodedToken = jwt.decodeJwt(jwtToken);
1519
1539
  if (!decodedToken) {
1520
1540
  tracer?.trace('createContact:invalidToken', {});
1521
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1541
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1522
1542
  return;
1523
1543
  }
1524
1544
  const { id: userId, platform } = decodedToken;
1525
1545
  platformName = platform;
1526
1546
  const { successful, returnMessage, contact, extraDataTracking, isRevokeUserSession } = await contactCore.createContact({ platform, userId, phoneNumber: req.body.phoneNumber, newContactName: req.body.newContactName, newContactType: req.body.newContactType, additionalSubmission: req.body.additionalSubmission });
1527
1547
  if (isRevokeUserSession) {
1528
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1548
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1529
1549
  success = false;
1530
1550
  }
1531
1551
  else {
1532
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage, contact }) : { successful, returnMessage, contact });
1552
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage, contact }));
1533
1553
  success = true;
1534
1554
  if (extraDataTracking) {
1535
1555
  extraData = extraDataTracking;
@@ -1538,7 +1558,7 @@ function createCoreRouter() {
1538
1558
  }
1539
1559
  else {
1540
1560
  tracer?.trace('createContact:noToken', {});
1541
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1561
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1542
1562
  success = false;
1543
1563
  }
1544
1564
  }
@@ -1546,7 +1566,7 @@ function createCoreRouter() {
1546
1566
  logger.error('Create contact failed', { platform: platformName, stack: e.stack });
1547
1567
  tracer?.traceError('createContact:error', e, { platform: platformName });
1548
1568
  extraData.statusCode = e.response?.status ?? 'unknown';
1549
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1569
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1550
1570
  success = false;
1551
1571
  }
1552
1572
  const requestEndTime = new Date().getTime();
@@ -1567,7 +1587,6 @@ function createCoreRouter() {
1567
1587
  eventAddedVia
1568
1588
  });
1569
1589
  });
1570
-
1571
1590
  router.get('/appointments', async function (req, res) {
1572
1591
  const requestStartTime = new Date().getTime();
1573
1592
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1575,14 +1594,14 @@ function createCoreRouter() {
1575
1594
  let platformName = null;
1576
1595
  let success = false;
1577
1596
  let extraData = {};
1578
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1597
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1579
1598
  try {
1580
- const jwtToken = req.query.jwtToken;
1599
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1581
1600
  if (jwtToken) {
1582
1601
  const decodedToken = jwt.decodeJwt(jwtToken);
1583
1602
  if (!decodedToken) {
1584
1603
  tracer?.trace('listAppointments:invalidToken', {});
1585
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1604
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1586
1605
  return;
1587
1606
  }
1588
1607
  const { id: userId, platform } = decodedToken;
@@ -1592,11 +1611,11 @@ function createCoreRouter() {
1592
1611
  const forceSync = req.query.forceSync === 'true';
1593
1612
  const { successful, appointments, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.listAppointments({ platform, userId, range, mineOnly, forceSync });
1594
1613
  if (isRevokeUserSession) {
1595
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1614
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1596
1615
  success = false;
1597
1616
  }
1598
1617
  else {
1599
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, appointments, returnMessage }) : { successful, appointments, returnMessage });
1618
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointments, returnMessage }));
1600
1619
  success = true;
1601
1620
  if (extraDataTracking) {
1602
1621
  extraData = extraDataTracking;
@@ -1609,7 +1628,7 @@ function createCoreRouter() {
1609
1628
  }
1610
1629
  else {
1611
1630
  tracer?.trace('listAppointments:noToken', {});
1612
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1631
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1613
1632
  success = false;
1614
1633
  }
1615
1634
  }
@@ -1617,7 +1636,7 @@ function createCoreRouter() {
1617
1636
  logger.error('List appointments failed', { platform: platformName, stack: e.stack });
1618
1637
  tracer?.traceError('listAppointments:error', e, { platform: platformName });
1619
1638
  extraData.statusCode = e.response?.status ?? 'unknown';
1620
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1639
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1621
1640
  success = false;
1622
1641
  }
1623
1642
  const requestEndTime = new Date().getTime();
@@ -1638,7 +1657,6 @@ function createCoreRouter() {
1638
1657
  eventAddedVia
1639
1658
  });
1640
1659
  });
1641
-
1642
1660
  router.post('/appointments', async function (req, res) {
1643
1661
  const requestStartTime = new Date().getTime();
1644
1662
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1646,14 +1664,14 @@ function createCoreRouter() {
1646
1664
  let platformName = null;
1647
1665
  let success = false;
1648
1666
  let extraData = {};
1649
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1667
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1650
1668
  try {
1651
- const jwtToken = req.query.jwtToken;
1669
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1652
1670
  if (jwtToken) {
1653
1671
  const decodedToken = jwt.decodeJwt(jwtToken);
1654
1672
  if (!decodedToken) {
1655
1673
  tracer?.trace('createAppointment:invalidToken', {});
1656
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1674
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1657
1675
  return;
1658
1676
  }
1659
1677
  const { id: userId, platform } = decodedToken;
@@ -1661,20 +1679,20 @@ function createCoreRouter() {
1661
1679
  const payload = req.body?.payload ?? req.body;
1662
1680
  const { successful, appointmentId, appointment, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.createAppointment({ platform, userId, payload });
1663
1681
  if (isRevokeUserSession) {
1664
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1682
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1665
1683
  success = false;
1666
1684
  }
1667
1685
  else {
1668
1686
  if (extraDataTracking) {
1669
1687
  extraData = extraDataTracking;
1670
1688
  }
1671
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, appointmentId, appointment, returnMessage }) : { successful, appointmentId, appointment, returnMessage });
1689
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointmentId, appointment, returnMessage }));
1672
1690
  success = true;
1673
1691
  }
1674
1692
  }
1675
1693
  else {
1676
1694
  tracer?.trace('createAppointment:noToken', {});
1677
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1695
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1678
1696
  success = false;
1679
1697
  }
1680
1698
  }
@@ -1682,7 +1700,7 @@ function createCoreRouter() {
1682
1700
  logger.error('Create appointment failed', { platform: platformName, stack: e.stack });
1683
1701
  tracer?.traceError('createAppointment:error', e, { platform: platformName });
1684
1702
  extraData.statusCode = e.response?.status ?? 'unknown';
1685
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1703
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1686
1704
  success = false;
1687
1705
  }
1688
1706
  const requestEndTime = new Date().getTime();
@@ -1703,7 +1721,6 @@ function createCoreRouter() {
1703
1721
  eventAddedVia
1704
1722
  });
1705
1723
  });
1706
-
1707
1724
  router.patch('/appointments/:appointmentId', async function (req, res) {
1708
1725
  const requestStartTime = new Date().getTime();
1709
1726
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1711,14 +1728,14 @@ function createCoreRouter() {
1711
1728
  let platformName = null;
1712
1729
  let success = false;
1713
1730
  let extraData = {};
1714
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1731
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1715
1732
  try {
1716
- const jwtToken = req.query.jwtToken;
1733
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1717
1734
  if (jwtToken) {
1718
1735
  const decodedToken = jwt.decodeJwt(jwtToken);
1719
1736
  if (!decodedToken) {
1720
1737
  tracer?.trace('updateAppointment:invalidToken', {});
1721
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1738
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1722
1739
  return;
1723
1740
  }
1724
1741
  const { id: userId, platform } = decodedToken;
@@ -1727,20 +1744,20 @@ function createCoreRouter() {
1727
1744
  const patchBody = req.body?.patch ?? req.body;
1728
1745
  const { successful, appointment, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.updateAppointment({ platform, userId, appointmentId, patchBody });
1729
1746
  if (isRevokeUserSession) {
1730
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1747
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1731
1748
  success = false;
1732
1749
  }
1733
1750
  else {
1734
1751
  if (extraDataTracking) {
1735
1752
  extraData = extraDataTracking;
1736
1753
  }
1737
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, appointmentId, appointment, returnMessage }) : { successful, appointmentId, appointment, returnMessage });
1754
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointmentId, appointment, returnMessage }));
1738
1755
  success = true;
1739
1756
  }
1740
1757
  }
1741
1758
  else {
1742
1759
  tracer?.trace('updateAppointment:noToken', {});
1743
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1760
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1744
1761
  success = false;
1745
1762
  }
1746
1763
  }
@@ -1748,7 +1765,7 @@ function createCoreRouter() {
1748
1765
  logger.error('Update appointment failed', { platform: platformName, stack: e.stack });
1749
1766
  tracer?.traceError('updateAppointment:error', e, { platform: platformName });
1750
1767
  extraData.statusCode = e.response?.status ?? 'unknown';
1751
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1768
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1752
1769
  success = false;
1753
1770
  }
1754
1771
  const requestEndTime = new Date().getTime();
@@ -1769,7 +1786,81 @@ function createCoreRouter() {
1769
1786
  eventAddedVia
1770
1787
  });
1771
1788
  });
1772
-
1789
+ router.post('/appointments/:appointmentId/status', async function (req, res) {
1790
+ const requestStartTime = new Date().getTime();
1791
+ const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
1792
+ tracer?.trace('updateAppointmentStatus:start', { query: req.query, params: req.params });
1793
+ let platformName = null;
1794
+ let success = false;
1795
+ let extraData = {};
1796
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1797
+ try {
1798
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1799
+ if (jwtToken) {
1800
+ const decodedToken = jwt.decodeJwt(jwtToken);
1801
+ if (!decodedToken) {
1802
+ tracer?.trace('updateAppointmentStatus:invalidToken', {});
1803
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1804
+ return;
1805
+ }
1806
+ const status = String(req.body?.status || '').trim().toLowerCase();
1807
+ if (!status) {
1808
+ tracer?.trace('updateAppointmentStatus:noStatus', {});
1809
+ res.status(400).send(wrapDebugResponse(tracer, 'Appointment status is required'));
1810
+ return;
1811
+ }
1812
+ const { id: userId, platform } = decodedToken;
1813
+ platformName = platform;
1814
+ const appointmentId = req.params.appointmentId;
1815
+ const { successful, appointment, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.updateAppointment({
1816
+ platform,
1817
+ userId,
1818
+ appointmentId,
1819
+ patchBody: { status }
1820
+ });
1821
+ if (isRevokeUserSession) {
1822
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1823
+ success = false;
1824
+ }
1825
+ else {
1826
+ if (extraDataTracking) {
1827
+ extraData = extraDataTracking;
1828
+ }
1829
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointmentId, appointment, returnMessage }));
1830
+ success = true;
1831
+ }
1832
+ }
1833
+ else {
1834
+ tracer?.trace('updateAppointmentStatus:noToken', {});
1835
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1836
+ success = false;
1837
+ }
1838
+ }
1839
+ catch (e) {
1840
+ logger.error('Update appointment status failed', { platform: platformName, stack: e.stack });
1841
+ tracer?.traceError('updateAppointmentStatus:error', e, { platform: platformName });
1842
+ extraData.statusCode = e.response?.status ?? 'unknown';
1843
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1844
+ success = false;
1845
+ }
1846
+ const requestEndTime = new Date().getTime();
1847
+ analytics.track({
1848
+ eventName: 'Update appointment status',
1849
+ interfaceName: 'updateAppointmentStatus',
1850
+ connectorName: platformName,
1851
+ accountId: hashedAccountId,
1852
+ extensionId: hashedExtensionId,
1853
+ success,
1854
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
1855
+ userAgent,
1856
+ ip,
1857
+ author,
1858
+ extras: {
1859
+ ...extraData
1860
+ },
1861
+ eventAddedVia
1862
+ });
1863
+ });
1773
1864
  router.get('/appointments/:appointmentId/refresh', async function (req, res) {
1774
1865
  const requestStartTime = new Date().getTime();
1775
1866
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1777,14 +1868,14 @@ function createCoreRouter() {
1777
1868
  let platformName = null;
1778
1869
  let success = false;
1779
1870
  let extraData = {};
1780
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1871
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1781
1872
  try {
1782
- const jwtToken = req.query.jwtToken;
1873
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1783
1874
  if (jwtToken) {
1784
1875
  const decodedToken = jwt.decodeJwt(jwtToken);
1785
1876
  if (!decodedToken) {
1786
1877
  tracer?.trace('refreshAppointment:invalidToken', {});
1787
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1878
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1788
1879
  return;
1789
1880
  }
1790
1881
  const { id: userId, platform } = decodedToken;
@@ -1792,20 +1883,20 @@ function createCoreRouter() {
1792
1883
  const appointmentId = req.params.appointmentId;
1793
1884
  const { successful, appointment, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.refreshAppointment({ platform, userId, appointmentId });
1794
1885
  if (isRevokeUserSession) {
1795
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1886
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1796
1887
  success = false;
1797
1888
  }
1798
1889
  else {
1799
1890
  if (extraDataTracking) {
1800
1891
  extraData = extraDataTracking;
1801
1892
  }
1802
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, appointmentId, appointment, returnMessage }) : { successful, appointmentId, appointment, returnMessage });
1893
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointmentId, appointment, returnMessage }));
1803
1894
  success = true;
1804
1895
  }
1805
1896
  }
1806
1897
  else {
1807
1898
  tracer?.trace('refreshAppointment:noToken', {});
1808
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1899
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1809
1900
  success = false;
1810
1901
  }
1811
1902
  }
@@ -1813,7 +1904,7 @@ function createCoreRouter() {
1813
1904
  logger.error('Refresh appointment failed', { platform: platformName, stack: e.stack });
1814
1905
  tracer?.traceError('refreshAppointment:error', e, { platform: platformName });
1815
1906
  extraData.statusCode = e.response?.status ?? 'unknown';
1816
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1907
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1817
1908
  success = false;
1818
1909
  }
1819
1910
  const requestEndTime = new Date().getTime();
@@ -1834,7 +1925,6 @@ function createCoreRouter() {
1834
1925
  eventAddedVia
1835
1926
  });
1836
1927
  });
1837
-
1838
1928
  router.post('/appointments/:appointmentId/confirm', async function (req, res) {
1839
1929
  const requestStartTime = new Date().getTime();
1840
1930
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1842,14 +1932,14 @@ function createCoreRouter() {
1842
1932
  let platformName = null;
1843
1933
  let success = false;
1844
1934
  let extraData = {};
1845
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1935
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1846
1936
  try {
1847
- const jwtToken = req.query.jwtToken;
1937
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1848
1938
  if (jwtToken) {
1849
1939
  const decodedToken = jwt.decodeJwt(jwtToken);
1850
1940
  if (!decodedToken) {
1851
1941
  tracer?.trace('confirmAppointment:invalidToken', {});
1852
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1942
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1853
1943
  return;
1854
1944
  }
1855
1945
  const { id: userId, platform } = decodedToken;
@@ -1857,20 +1947,20 @@ function createCoreRouter() {
1857
1947
  const appointmentId = req.params.appointmentId;
1858
1948
  const { successful, appointment, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.confirmAppointment({ platform, userId, appointmentId });
1859
1949
  if (isRevokeUserSession) {
1860
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
1950
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1861
1951
  success = false;
1862
1952
  }
1863
1953
  else {
1864
1954
  if (extraDataTracking) {
1865
1955
  extraData = extraDataTracking;
1866
1956
  }
1867
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, appointmentId, appointment, returnMessage }) : { successful, appointmentId, appointment, returnMessage });
1957
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointmentId, appointment, returnMessage }));
1868
1958
  success = true;
1869
1959
  }
1870
1960
  }
1871
1961
  else {
1872
1962
  tracer?.trace('confirmAppointment:noToken', {});
1873
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
1963
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1874
1964
  success = false;
1875
1965
  }
1876
1966
  }
@@ -1878,7 +1968,7 @@ function createCoreRouter() {
1878
1968
  logger.error('Confirm appointment failed', { platform: platformName, stack: e.stack });
1879
1969
  tracer?.traceError('confirmAppointment:error', e, { platform: platformName });
1880
1970
  extraData.statusCode = e.response?.status ?? 'unknown';
1881
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
1971
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1882
1972
  success = false;
1883
1973
  }
1884
1974
  const requestEndTime = new Date().getTime();
@@ -1899,7 +1989,6 @@ function createCoreRouter() {
1899
1989
  eventAddedVia
1900
1990
  });
1901
1991
  });
1902
-
1903
1992
  router.post('/appointments/:appointmentId/cancel', async function (req, res) {
1904
1993
  const requestStartTime = new Date().getTime();
1905
1994
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -1907,14 +1996,14 @@ function createCoreRouter() {
1907
1996
  let platformName = null;
1908
1997
  let success = false;
1909
1998
  let extraData = {};
1910
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1999
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1911
2000
  try {
1912
- const jwtToken = req.query.jwtToken;
2001
+ const jwtToken = req.jwtToken || req.query.jwtToken;
1913
2002
  if (jwtToken) {
1914
2003
  const decodedToken = jwt.decodeJwt(jwtToken);
1915
2004
  if (!decodedToken) {
1916
2005
  tracer?.trace('cancelAppointment:invalidToken', {});
1917
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2006
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1918
2007
  return;
1919
2008
  }
1920
2009
  const { id: userId, platform } = decodedToken;
@@ -1922,20 +2011,20 @@ function createCoreRouter() {
1922
2011
  const appointmentId = req.params.appointmentId;
1923
2012
  const { successful, appointment, returnMessage, extraDataTracking, isRevokeUserSession } = await appointmentCore.cancelAppointment({ platform, userId, appointmentId });
1924
2013
  if (isRevokeUserSession) {
1925
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2014
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1926
2015
  success = false;
1927
2016
  }
1928
2017
  else {
1929
2018
  if (extraDataTracking) {
1930
2019
  extraData = extraDataTracking;
1931
2020
  }
1932
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, appointmentId, appointment, returnMessage }) : { successful, appointmentId, appointment, returnMessage });
2021
+ res.status(200).send(wrapDebugResponse(tracer, { successful, appointmentId, appointment, returnMessage }));
1933
2022
  success = true;
1934
2023
  }
1935
2024
  }
1936
2025
  else {
1937
2026
  tracer?.trace('cancelAppointment:noToken', {});
1938
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2027
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1939
2028
  success = false;
1940
2029
  }
1941
2030
  }
@@ -1943,7 +2032,7 @@ function createCoreRouter() {
1943
2032
  logger.error('Cancel appointment failed', { platform: platformName, stack: e.stack });
1944
2033
  tracer?.traceError('cancelAppointment:error', e, { platform: platformName });
1945
2034
  extraData.statusCode = e.response?.status ?? 'unknown';
1946
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2035
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1947
2036
  success = false;
1948
2037
  }
1949
2038
  const requestEndTime = new Date().getTime();
@@ -1971,30 +2060,31 @@ function createCoreRouter() {
1971
2060
  let platformName = null;
1972
2061
  let success = false;
1973
2062
  let extraData = {};
1974
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2063
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
1975
2064
  try {
1976
2065
  const jwtToken = req.jwtToken || req.query.jwtToken;
1977
2066
  if (jwtToken) {
1978
2067
  const decodedToken = jwt.decodeJwt(jwtToken);
1979
2068
  if (!decodedToken) {
1980
2069
  tracer?.trace('saveNoteCache:invalidToken', {});
1981
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2070
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
1982
2071
  return;
1983
2072
  }
1984
2073
  const { id: userId, platform } = decodedToken;
1985
2074
  platformName = platform;
1986
2075
  const { successful, returnMessage, extraDataTracking } = await logCore.saveNoteCache({ platform, userId, sessionId: req.body.sessionId, note: req.body.note });
1987
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2076
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage }));
1988
2077
  success = true;
1989
2078
  if (extraDataTracking) {
1990
2079
  extraData = extraDataTracking;
1991
2080
  }
1992
2081
  }
1993
- } catch (e) {
2082
+ }
2083
+ catch (e) {
1994
2084
  logger.error('Save note cache failed', { platform: platformName, stack: e.stack });
1995
2085
  tracer?.traceError('saveNoteCache:error', e, { platform: platformName });
1996
2086
  extraData.statusCode = e.response?.status ?? 'unknown';
1997
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2087
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
1998
2088
  success = false;
1999
2089
  }
2000
2090
  const requestEndTime = new Date().getTime();
@@ -2014,7 +2104,7 @@ function createCoreRouter() {
2014
2104
  ...extraData
2015
2105
  }
2016
2106
  });
2017
- })
2107
+ });
2018
2108
  router.get('/callLog', async function (req, res) {
2019
2109
  const requestStartTime = new Date().getTime();
2020
2110
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
@@ -2022,14 +2112,14 @@ function createCoreRouter() {
2022
2112
  let platformName = null;
2023
2113
  let success = false;
2024
2114
  let extraData = {};
2025
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2115
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2026
2116
  try {
2027
2117
  const jwtToken = req.jwtToken || req.query.jwtToken;
2028
2118
  if (jwtToken) {
2029
2119
  const decodedToken = jwt.decodeJwt(jwtToken);
2030
2120
  if (!decodedToken) {
2031
2121
  tracer?.trace('getCallLog:invalidToken', {});
2032
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2122
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2033
2123
  return;
2034
2124
  }
2035
2125
  const { id: userId, platform } = decodedToken;
@@ -2043,11 +2133,11 @@ function createCoreRouter() {
2043
2133
  requireDetails: req.query.requireDetails === 'true'
2044
2134
  });
2045
2135
  if (isRevokeUserSession) {
2046
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2136
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
2047
2137
  success = false;
2048
2138
  }
2049
2139
  else {
2050
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, logs, returnMessage }) : { successful, logs, returnMessage });
2140
+ res.status(200).send(wrapDebugResponse(tracer, { successful, logs, returnMessage }));
2051
2141
  success = true;
2052
2142
  if (extraDataTracking) {
2053
2143
  extraData = extraDataTracking;
@@ -2057,14 +2147,14 @@ function createCoreRouter() {
2057
2147
  }
2058
2148
  else {
2059
2149
  tracer?.trace('getCallLog:noToken', {});
2060
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2150
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2061
2151
  success = false;
2062
2152
  }
2063
2153
  }
2064
2154
  catch (e) {
2065
2155
  logger.error('Get call log failed', { platform: platformName, stack: e.stack });
2066
2156
  extraData.statusCode = e.response?.status ?? 'unknown';
2067
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2157
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2068
2158
  tracer?.traceError('getCallLog:error', e, { platform: platformName });
2069
2159
  success = false;
2070
2160
  }
@@ -2093,41 +2183,41 @@ function createCoreRouter() {
2093
2183
  let platformName = null;
2094
2184
  let success = false;
2095
2185
  let extraData = {};
2096
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2186
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2097
2187
  try {
2098
2188
  const jwtToken = req.jwtToken || req.query.jwtToken;
2099
2189
  if (jwtToken) {
2100
2190
  const decodedToken = jwt.decodeJwt(jwtToken);
2101
2191
  if (!decodedToken) {
2102
2192
  tracer?.trace('createCallLog:invalidToken', {});
2103
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2193
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2104
2194
  return;
2105
2195
  }
2106
2196
  const { id: userId, platform } = decodedToken;
2107
2197
  platformName = platform;
2108
2198
  const { successful, logId, returnMessage, extraDataTracking, isRevokeUserSession } = await logCore.createCallLog({ jwtToken, platform, userId, incomingData: req.body, hashedAccountId: hashedAccountId ?? util.getHashValue(req.body.logInfo?.accountId, process.env.HASH_KEY), isFromSSCL: userAgent === 'SSCL' });
2109
2199
  if (isRevokeUserSession) {
2110
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2200
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
2111
2201
  success = false;
2112
2202
  }
2113
2203
  else {
2114
2204
  if (extraDataTracking) {
2115
2205
  extraData = extraDataTracking;
2116
2206
  }
2117
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, logId, returnMessage }) : { successful, logId, returnMessage });
2207
+ res.status(200).send(wrapDebugResponse(tracer, { successful, logId, returnMessage }));
2118
2208
  success = true;
2119
2209
  }
2120
2210
  }
2121
2211
  else {
2122
2212
  tracer?.trace('createCallLog:noToken', {});
2123
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2213
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2124
2214
  success = false;
2125
2215
  }
2126
2216
  }
2127
2217
  catch (e) {
2128
2218
  logger.error('Create call log failed', { platform: platformName, stack: e.stack });
2129
2219
  extraData.statusCode = e.response?.status ?? 'unknown';
2130
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2220
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2131
2221
  tracer?.traceError('createCallLog:error', e, { platform: platformName });
2132
2222
  success = false;
2133
2223
  }
@@ -2156,14 +2246,14 @@ function createCoreRouter() {
2156
2246
  let platformName = null;
2157
2247
  let success = false;
2158
2248
  let extraData = {};
2159
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2249
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2160
2250
  try {
2161
2251
  const jwtToken = req.jwtToken || req.query.jwtToken;
2162
2252
  if (jwtToken) {
2163
2253
  const decodedToken = jwt.decodeJwt(jwtToken);
2164
2254
  if (!decodedToken) {
2165
2255
  tracer?.trace('updateCallLog:invalidToken', {});
2166
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2256
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2167
2257
  return;
2168
2258
  }
2169
2259
  const { id: userId, platform } = decodedToken;
@@ -2172,19 +2262,19 @@ function createCoreRouter() {
2172
2262
  if (extraDataTracking) {
2173
2263
  extraData = extraDataTracking;
2174
2264
  }
2175
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, logId, updatedNote, returnMessage }) : { successful, logId, updatedNote, returnMessage });
2265
+ res.status(200).send(wrapDebugResponse(tracer, { successful, logId, updatedNote, returnMessage }));
2176
2266
  success = true;
2177
2267
  }
2178
2268
  else {
2179
2269
  tracer?.trace('updateCallLog:noToken', {});
2180
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2270
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2181
2271
  success = false;
2182
2272
  }
2183
2273
  }
2184
2274
  catch (e) {
2185
2275
  logger.error('Update call log failed', { platform: platformName, stack: e.stack });
2186
2276
  extraData.statusCode = e.response?.status ?? 'unknown';
2187
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2277
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2188
2278
  tracer?.traceError('updateCallLog:error', e, { platform: platformName });
2189
2279
  success = false;
2190
2280
  }
@@ -2213,21 +2303,21 @@ function createCoreRouter() {
2213
2303
  let platformName = null;
2214
2304
  let success = false;
2215
2305
  let extraData = {};
2216
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2306
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2217
2307
  try {
2218
2308
  const jwtToken = req.jwtToken || req.query.jwtToken;
2219
2309
  if (jwtToken) {
2220
2310
  const decodedToken = jwt.decodeJwt(jwtToken);
2221
2311
  if (!decodedToken) {
2222
2312
  tracer?.trace('upsertCallDisposition:invalidJwtToken', {});
2223
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid JWT token') : 'Invalid JWT token');
2313
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid JWT token'));
2224
2314
  return;
2225
2315
  }
2226
2316
  const { id: userId, platform } = decodedToken;
2227
2317
  platformName = platform;
2228
2318
  if (!userId) {
2229
2319
  tracer?.trace('upsertCallDisposition:invalidToken', {});
2230
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2320
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2231
2321
  return;
2232
2322
  }
2233
2323
  const { successful, returnMessage, extraDataTracking, isRevokeUserSession } = await dispositionCore.upsertCallDisposition({
@@ -2240,27 +2330,27 @@ function createCoreRouter() {
2240
2330
  additionalSubmission: req.body.additionalSubmission
2241
2331
  });
2242
2332
  if (isRevokeUserSession) {
2243
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2333
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
2244
2334
  success = false;
2245
2335
  }
2246
2336
  else {
2247
2337
  if (extraDataTracking) {
2248
2338
  extraData = extraDataTracking;
2249
2339
  }
2250
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2340
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage }));
2251
2341
  success = true;
2252
2342
  }
2253
2343
  }
2254
2344
  else {
2255
2345
  tracer?.trace('upsertCallDisposition:noToken', {});
2256
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2346
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2257
2347
  success = false;
2258
2348
  }
2259
2349
  }
2260
2350
  catch (e) {
2261
2351
  logger.error('Upsert call disposition failed', { platform: platformName, stack: e.stack });
2262
2352
  extraData.statusCode = e.response?.status ?? 'unknown';
2263
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2353
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2264
2354
  tracer?.traceError('upsertCallDisposition:error', e, { platform: platformName });
2265
2355
  success = false;
2266
2356
  }
@@ -2290,41 +2380,41 @@ function createCoreRouter() {
2290
2380
  let success = false;
2291
2381
  let statusCode = 200;
2292
2382
  let extraData = {};
2293
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2383
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2294
2384
  try {
2295
2385
  const jwtToken = req.jwtToken || req.query.jwtToken;
2296
2386
  if (jwtToken) {
2297
2387
  const decodedToken = jwt.decodeJwt(jwtToken);
2298
2388
  if (!decodedToken) {
2299
2389
  tracer?.trace('createMessageLog:invalidToken', {});
2300
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2390
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2301
2391
  return;
2302
2392
  }
2303
2393
  const { id: userId, platform } = decodedToken;
2304
2394
  platformName = platform;
2305
2395
  const { successful, returnMessage, logIds, extraDataTracking, isRevokeUserSession } = await logCore.createMessageLog({ platform, userId, incomingData: req.body });
2306
2396
  if (isRevokeUserSession) {
2307
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2397
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
2308
2398
  success = false;
2309
2399
  }
2310
2400
  else {
2311
2401
  if (extraDataTracking) {
2312
2402
  extraData = extraDataTracking;
2313
2403
  }
2314
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage, logIds }) : { successful, returnMessage, logIds });
2404
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage, logIds }));
2315
2405
  success = true;
2316
2406
  }
2317
2407
  }
2318
2408
  else {
2319
2409
  tracer?.trace('createMessageLog:noToken', {});
2320
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2410
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2321
2411
  success = false;
2322
2412
  }
2323
2413
  }
2324
2414
  catch (e) {
2325
2415
  logger.error('Create message log failed', { platform: platformName, stack: e.stack });
2326
2416
  statusCode = e.response?.status ?? 'unknown';
2327
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2417
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2328
2418
  tracer?.traceError('createMessageLog:error', e, { platform: platformName });
2329
2419
  success = false;
2330
2420
  }
@@ -2354,26 +2444,27 @@ function createCoreRouter() {
2354
2444
  let platformName = null;
2355
2445
  let success = false;
2356
2446
  let statusCode = 200;
2357
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2447
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2358
2448
  try {
2359
2449
  const jwtToken = req.jwtToken || req.query.jwtToken;
2360
2450
  if (!jwtToken) {
2361
2451
  tracer?.trace('scheduleCallDown:noToken', {});
2362
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2452
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2363
2453
  return;
2364
2454
  }
2365
2455
  try {
2366
- const { id } = await calldown.schedule({ jwtToken, rcAccessToken: req.query.rcAccessToken, body: req.body });
2456
+ const { id } = await calldown.schedule({ jwtToken, rcAccessToken: getRcAccessTokenFromRequest(req), body: req.body });
2367
2457
  success = true;
2368
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true, id }) : { successful: true, id });
2458
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true, id }));
2369
2459
  }
2370
2460
  catch (e) {
2371
2461
  return handleDatabaseError(e, 'Error scheduling call down');
2372
2462
  }
2373
- } catch (e) {
2463
+ }
2464
+ catch (e) {
2374
2465
  logger.error('Schedule call down failed', { platform: platformName, stack: e.stack });
2375
2466
  statusCode = e.response?.status ?? 'unknown';
2376
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2467
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2377
2468
  tracer?.traceError('scheduleCallDown:error', e, { platform: platformName });
2378
2469
  success = false;
2379
2470
  }
@@ -2402,21 +2493,22 @@ function createCoreRouter() {
2402
2493
  let platformName = null;
2403
2494
  let success = false;
2404
2495
  let statusCode = 200;
2405
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2496
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2406
2497
  try {
2407
2498
  const jwtToken = req.jwtToken || req.query.jwtToken;
2408
2499
  if (!jwtToken) {
2409
2500
  tracer?.trace('getCallDownList:noToken', {});
2410
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2501
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2411
2502
  return;
2412
2503
  }
2413
2504
  const { items } = await calldown.list({ jwtToken, status: req.query.status });
2414
2505
  success = true;
2415
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true, items }) : { successful: true, items });
2416
- } catch (e) {
2506
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true, items }));
2507
+ }
2508
+ catch (e) {
2417
2509
  logger.error('Get call down list failed', { platform: platformName, stack: e.stack });
2418
2510
  statusCode = e.response?.status ?? 'unknown';
2419
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2511
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2420
2512
  tracer?.traceError('getCallDownList:error', e, { platform: platformName });
2421
2513
  success = false;
2422
2514
  }
@@ -2443,28 +2535,29 @@ function createCoreRouter() {
2443
2535
  let platformName = null;
2444
2536
  let success = false;
2445
2537
  let statusCode = 200;
2446
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2538
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2447
2539
  try {
2448
2540
  const jwtToken = req.jwtToken || req.query.jwtToken;
2449
2541
  const id = req.query.id;
2450
2542
  if (!jwtToken) {
2451
2543
  tracer?.trace('deleteCallDownItem:noToken', {});
2452
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2544
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2453
2545
  return;
2454
2546
  }
2455
2547
  const rid = req.params.id || id;
2456
2548
  if (!rid) {
2457
2549
  tracer?.trace('deleteCallDownItem:missingId', {});
2458
- res.status(400).send(tracer ? tracer.wrapResponse('Missing id') : 'Missing id');
2550
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing id'));
2459
2551
  return;
2460
2552
  }
2461
2553
  await calldown.remove({ jwtToken, id: rid });
2462
2554
  success = true;
2463
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
2464
- } catch (e) {
2555
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
2556
+ }
2557
+ catch (e) {
2465
2558
  logger.error('Delete call down item failed', { platform: platformName, stack: e.stack });
2466
2559
  statusCode = e.response?.status ?? 'unknown';
2467
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2560
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2468
2561
  tracer?.traceError('deleteCallDownItem:error', e, { platform: platformName });
2469
2562
  success = false;
2470
2563
  }
@@ -2491,27 +2584,28 @@ function createCoreRouter() {
2491
2584
  let platformName = null;
2492
2585
  let success = false;
2493
2586
  let statusCode = 200;
2494
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2587
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2495
2588
  try {
2496
2589
  const jwtToken = req.jwtToken || req.query.jwtToken;
2497
2590
  if (!jwtToken) {
2498
2591
  tracer?.trace('markCallDownCalled:noToken', {});
2499
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2592
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2500
2593
  return;
2501
2594
  }
2502
2595
  const id = req.params.id || req.body?.id;
2503
2596
  if (!id) {
2504
2597
  tracer?.trace('markCallDownCalled:missingId', {});
2505
- res.status(400).send(tracer ? tracer.wrapResponse('Missing id') : 'Missing id');
2598
+ res.status(400).send(wrapDebugResponse(tracer, 'Missing id'));
2506
2599
  return;
2507
2600
  }
2508
2601
  await calldown.update({ jwtToken, id, updateData: req.body });
2509
2602
  success = true;
2510
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
2511
- } catch (e) {
2603
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
2604
+ }
2605
+ catch (e) {
2512
2606
  logger.error('Mark call down called failed', { platform: platformName, stack: e.stack });
2513
2607
  statusCode = e.response?.status ?? 'unknown';
2514
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2608
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2515
2609
  tracer?.traceError('markCallDownCalled:error', e, { platform: platformName });
2516
2610
  success = false;
2517
2611
  }
@@ -2538,14 +2632,14 @@ function createCoreRouter() {
2538
2632
  let platformName = null;
2539
2633
  let success = false;
2540
2634
  let statusCode = 200;
2541
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2635
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2542
2636
  try {
2543
2637
  const jwtToken = req.jwtToken || req.query.jwtToken;
2544
2638
  if (jwtToken) {
2545
2639
  const decodedToken = jwt.decodeJwt(jwtToken);
2546
2640
  if (!decodedToken) {
2547
2641
  tracer?.trace('findContactWithName:invalidJwtToken', {});
2548
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid JWT token') : 'Invalid JWT token');
2642
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid JWT token'));
2549
2643
  success = false;
2550
2644
  return;
2551
2645
  }
@@ -2553,25 +2647,24 @@ function createCoreRouter() {
2553
2647
  platformName = platform;
2554
2648
  const { successful, returnMessage, contact, isRevokeUserSession } = await contactCore.findContactWithName({ platform, userId, name: req.query.name });
2555
2649
  if (isRevokeUserSession) {
2556
- res.status(401).send(tracer ? tracer.wrapResponse({ successful, returnMessage }) : { successful, returnMessage });
2650
+ res.status(401).send(wrapDebugResponse(tracer, { successful, returnMessage }));
2557
2651
  success = false;
2558
2652
  }
2559
2653
  else {
2560
- res.status(200).send(tracer ? tracer.wrapResponse({ successful, returnMessage, contact }) : { successful, returnMessage, contact });
2654
+ res.status(200).send(wrapDebugResponse(tracer, { successful, returnMessage, contact }));
2561
2655
  success = successful;
2562
2656
  }
2563
2657
  }
2564
2658
  else {
2565
2659
  tracer?.trace('contactSearchByName:noToken', {});
2566
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2660
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2567
2661
  success = false;
2568
2662
  }
2569
-
2570
2663
  }
2571
2664
  catch (e) {
2572
2665
  logger.error('Contact search by name failed', { platform: platformName, stack: e.stack });
2573
2666
  statusCode = e.response?.status ?? 'unknown';
2574
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2667
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2575
2668
  tracer?.traceError('contactSearchByName:error', e, { platform: platformName });
2576
2669
  success = false;
2577
2670
  }
@@ -2598,7 +2691,7 @@ function createCoreRouter() {
2598
2691
  tracer?.trace('getAdminReport:start', { query: req.query });
2599
2692
  let platformName = null;
2600
2693
  let success = false;
2601
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2694
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2602
2695
  const jwtToken = req.jwtToken || req.query.jwtToken;
2603
2696
  try {
2604
2697
  if (jwtToken) {
@@ -2606,21 +2699,21 @@ function createCoreRouter() {
2606
2699
  const user = await UserModel.findByPk(unAuthData?.id);
2607
2700
  if (!user) {
2608
2701
  tracer?.trace('getAdminReport:userNotFound', {});
2609
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
2702
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
2610
2703
  return;
2611
2704
  }
2612
2705
  const report = await adminCore.getAdminReport({ rcAccountId: user.rcAccountId, timezone: req.query.timezone, timeFrom: req.query.timeFrom, timeTo: req.query.timeTo, groupBy: req.query.groupBy });
2613
- res.status(200).send(tracer ? tracer.wrapResponse(report) : report);
2706
+ res.status(200).send(wrapDebugResponse(tracer, report));
2614
2707
  success = true;
2615
2708
  return;
2616
2709
  }
2617
2710
  tracer?.trace('getAdminReport:invalidRequest', {});
2618
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid request') : 'Invalid request');
2711
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid request'));
2619
2712
  success = false;
2620
2713
  }
2621
2714
  catch (e) {
2622
2715
  logger.error('Get admin report failed', { stack: e.stack });
2623
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2716
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2624
2717
  tracer?.traceError('getAdminReport:error', e, { platform: platformName });
2625
2718
  }
2626
2719
  const requestEndTime = new Date().getTime();
@@ -2644,7 +2737,7 @@ function createCoreRouter() {
2644
2737
  tracer?.trace('getUserReport:start', { query: req.query });
2645
2738
  let platformName = null;
2646
2739
  let success = false;
2647
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2740
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2648
2741
  const jwtToken = req.jwtToken || req.query.jwtToken;
2649
2742
  try {
2650
2743
  if (jwtToken) {
@@ -2652,20 +2745,20 @@ function createCoreRouter() {
2652
2745
  const user = await UserModel.findByPk(unAuthData?.id);
2653
2746
  if (!user) {
2654
2747
  tracer?.trace('getUserReport:userNotFound', {});
2655
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
2748
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
2656
2749
  return;
2657
2750
  }
2658
2751
  const report = await adminCore.getUserReport({ rcAccountId: user.rcAccountId, rcExtensionId: req.query.rcExtensionId, timezone: req.query.timezone, timeFrom: req.query.timeFrom, timeTo: req.query.timeTo });
2659
- res.status(200).send(tracer ? tracer.wrapResponse(report) : report);
2752
+ res.status(200).send(wrapDebugResponse(tracer, report));
2660
2753
  return;
2661
2754
  }
2662
2755
  tracer?.trace('getUserReport:invalidRequest', {});
2663
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid request') : 'Invalid request');
2756
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid request'));
2664
2757
  success = false;
2665
2758
  }
2666
2759
  catch (e) {
2667
2760
  logger.error('Get user report failed', { stack: e.stack });
2668
- res.status(400).send(tracer ? tracer.wrapResponse({ error: e.message || e }) : { error: e.message || e });
2761
+ res.status(400).send(wrapDebugResponse(tracer, { error: getErrorResponse(e) }));
2669
2762
  tracer?.traceError('getUserReport:error', e, { platform: platformName });
2670
2763
  }
2671
2764
  const requestEndTime = new Date().getTime();
@@ -2693,15 +2786,15 @@ function createCoreRouter() {
2693
2786
  const user = await UserModel.findByPk(unAuthData?.id);
2694
2787
  if (!user) {
2695
2788
  tracer?.trace('onRingcentralOAuthCallback:userNotFound', {});
2696
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
2789
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
2697
2790
  return;
2698
2791
  }
2699
2792
  await authCore.onRingcentralOAuthCallback({ code, rcAccountId: user.rcAccountId });
2700
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
2793
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
2701
2794
  return;
2702
2795
  }
2703
2796
  tracer?.trace('onRingcentralOAuthCallback:invalidRequest', {});
2704
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid request') : 'Invalid request');
2797
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid request'));
2705
2798
  });
2706
2799
  router.get('/debug/report/url', async function (req, res) {
2707
2800
  const requestStartTime = new Date().getTime();
@@ -2709,17 +2802,17 @@ function createCoreRouter() {
2709
2802
  tracer?.trace('getErrorLogReportURL:start', { query: req.query });
2710
2803
  let platformName = null;
2711
2804
  let success = false;
2712
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2805
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2713
2806
  const jwtToken = req.jwtToken || req.query.jwtToken;
2714
2807
  if (jwtToken) {
2715
2808
  const unAuthData = jwt.decodeJwt(jwtToken);
2716
2809
  const uploadUrl = await s3ErrorLogReport.getUploadUrl({ userId: unAuthData?.id, platform: unAuthData?.platform });
2717
- res.status(200).send(tracer ? tracer.wrapResponse({ presignedUrl: uploadUrl }) : { presignedUrl: uploadUrl });
2810
+ res.status(200).send(wrapDebugResponse(tracer, { presignedUrl: uploadUrl }));
2718
2811
  success = true;
2719
2812
  }
2720
2813
  else {
2721
2814
  tracer?.trace('getErrorLogReportURL:invalidRequest', {});
2722
- res.status(400).send(tracer ? tracer.wrapResponse('Invalid request') : 'Invalid request');
2815
+ res.status(400).send(wrapDebugResponse(tracer, 'Invalid request'));
2723
2816
  success = false;
2724
2817
  }
2725
2818
  const requestEndTime = new Date().getTime();
@@ -2737,7 +2830,6 @@ function createCoreRouter() {
2737
2830
  eventAddedVia
2738
2831
  });
2739
2832
  });
2740
-
2741
2833
  router.post('/plugin/async-callback/:taskId', async function (req, res) {
2742
2834
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
2743
2835
  tracer?.trace('pluginAsyncCallback:start', { taskId: req.params.taskId, body: req.body });
@@ -2746,42 +2838,40 @@ function createCoreRouter() {
2746
2838
  taskId: req.params.taskId,
2747
2839
  body: req.body || {},
2748
2840
  });
2749
- res.status(result.statusCode).send(tracer ? tracer.wrapResponse(result.body) : result.body);
2841
+ res.status(result.statusCode).send(wrapDebugResponse(tracer, result.body));
2750
2842
  }
2751
2843
  catch (e) {
2752
2844
  logger.error('Plugin async callback failed', { taskId: req.params.taskId, stack: e.stack });
2753
2845
  tracer?.traceError('pluginAsyncCallback:error', e);
2754
- res.status(500).send(tracer ? tracer.wrapResponse({ successful: false, message: e.message || e }) : { successful: false, message: e.message || e });
2846
+ res.status(500).send(wrapDebugResponse(tracer, { successful: false, message: getErrorResponse(e) }));
2755
2847
  }
2756
2848
  });
2757
-
2758
2849
  router.post('/plugin/register', async function (req, res) {
2759
2850
  const requestStartTime = new Date().getTime();
2760
2851
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
2761
2852
  tracer?.trace('pluginRegister:start', { body: req.body });
2762
2853
  let success = false;
2763
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2854
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2764
2855
  try {
2765
2856
  const { pluginId, rcAccountId, pluginAccess, pluginName, ownerRcAccountId } = req.body || {};
2766
- const rcAccessToken = req.query?.rcAccessToken;
2857
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
2767
2858
  if (!pluginId || !rcAccountId) {
2768
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'pluginId and rcAccountId are required' }) : { successful: false, returnMessage: 'pluginId and rcAccountId are required' });
2859
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'pluginId and rcAccountId are required' }));
2769
2860
  return;
2770
2861
  }
2771
2862
  if (!rcAccessToken) {
2772
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'Missing RingCentral access token' }) : { successful: false, returnMessage: 'Missing RingCentral access token' });
2863
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'Missing RingCentral access token' }));
2773
2864
  return;
2774
2865
  }
2775
2866
  const { isValidated, rcAccountId: validatedRcAccountId } = await adminCore.validateAdminRole({ rcAccessToken });
2776
2867
  if (!isValidated) {
2777
- res.status(403).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'Admin validation failed' }) : { successful: false, returnMessage: 'Admin validation failed' });
2868
+ res.status(403).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'Admin validation failed' }));
2778
2869
  return;
2779
2870
  }
2780
2871
  if (validatedRcAccountId?.toString() !== rcAccountId?.toString()) {
2781
- res.status(403).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'rcAccountId mismatch' }) : { successful: false, returnMessage: 'rcAccountId mismatch' });
2872
+ res.status(403).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'rcAccountId mismatch' }));
2782
2873
  return;
2783
2874
  }
2784
-
2785
2875
  await pluginCore.registerPluginAccount({
2786
2876
  pluginId,
2787
2877
  rcAccessToken,
@@ -2790,15 +2880,15 @@ function createCoreRouter() {
2790
2880
  pluginAccess,
2791
2881
  pluginName,
2792
2882
  });
2793
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
2883
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
2794
2884
  success = true;
2795
- } catch (e) {
2885
+ }
2886
+ catch (e) {
2796
2887
  logger.error('Plugin register failed', { stack: e.stack });
2797
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: e.message || e }) : { successful: false, returnMessage: e.message || e });
2888
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: getErrorResponse(e) }));
2798
2889
  tracer?.traceError('pluginRegister:error', e);
2799
2890
  success = false;
2800
2891
  }
2801
-
2802
2892
  const requestEndTime = new Date().getTime();
2803
2893
  analytics.track({
2804
2894
  eventName: 'Plugin Register',
@@ -2813,44 +2903,43 @@ function createCoreRouter() {
2813
2903
  eventAddedVia
2814
2904
  });
2815
2905
  });
2816
-
2817
2906
  router.delete('/plugin/unregister', async function (req, res) {
2818
2907
  const requestStartTime = new Date().getTime();
2819
2908
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
2820
2909
  tracer?.trace('pluginUnregister:start', { query: req.query });
2821
2910
  let success = false;
2822
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
2911
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers });
2823
2912
  try {
2824
2913
  const { pluginId, rcAccountId, pluginName } = req.query || {};
2825
- const rcAccessToken = req.query?.rcAccessToken;
2914
+ const rcAccessToken = getRcAccessTokenFromRequest(req);
2826
2915
  if (!pluginId || !rcAccountId) {
2827
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'pluginId and rcAccountId are required' }) : { successful: false, returnMessage: 'pluginId and rcAccountId are required' });
2916
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'pluginId and rcAccountId are required' }));
2828
2917
  return;
2829
2918
  }
2830
2919
  if (!rcAccessToken) {
2831
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'Missing RingCentral access token' }) : { successful: false, returnMessage: 'Missing RingCentral access token' });
2920
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'Missing RingCentral access token' }));
2832
2921
  return;
2833
2922
  }
2834
2923
  const { isValidated, rcAccountId: validatedRcAccountId } = await adminCore.validateAdminRole({ rcAccessToken });
2835
2924
  if (!isValidated) {
2836
- res.status(403).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'Admin validation failed' }) : { successful: false, returnMessage: 'Admin validation failed' });
2925
+ res.status(403).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'Admin validation failed' }));
2837
2926
  return;
2838
2927
  }
2839
2928
  if (validatedRcAccountId?.toString() !== rcAccountId?.toString()) {
2840
- res.status(403).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: 'rcAccountId mismatch' }) : { successful: false, returnMessage: 'rcAccountId mismatch' });
2929
+ res.status(403).send(wrapDebugResponse(tracer, { successful: false, returnMessage: 'rcAccountId mismatch' }));
2841
2930
  return;
2842
2931
  }
2843
-
2844
2932
  await pluginCore.unregisterPluginAccount({
2845
2933
  pluginId,
2846
2934
  rcAccountId: rcAccountId?.toString(),
2847
2935
  pluginName,
2848
2936
  });
2849
- res.status(200).send(tracer ? tracer.wrapResponse({ successful: true }) : { successful: true });
2937
+ res.status(200).send(wrapDebugResponse(tracer, { successful: true }));
2850
2938
  success = true;
2851
- } catch (e) {
2939
+ }
2940
+ catch (e) {
2852
2941
  logger.error('Plugin unregister failed', { stack: e.stack });
2853
- res.status(400).send(tracer ? tracer.wrapResponse({ successful: false, returnMessage: e.message || e }) : { successful: false, returnMessage: e.message || e });
2942
+ res.status(400).send(wrapDebugResponse(tracer, { successful: false, returnMessage: getErrorResponse(e) }));
2854
2943
  tracer?.traceError('pluginUnregister:error', e);
2855
2944
  success = false;
2856
2945
  }
@@ -2868,7 +2957,6 @@ function createCoreRouter() {
2868
2957
  eventAddedVia
2869
2958
  });
2870
2959
  });
2871
-
2872
2960
  router.get('/plugin/licenseStatus', async function (req, res) {
2873
2961
  const tracer = req.headers['is-debug'] === 'true' ? DebugTracer.fromRequest(req) : null;
2874
2962
  tracer?.trace('getPluginLicenseStatus:start', { query: req.query });
@@ -2876,31 +2964,30 @@ function createCoreRouter() {
2876
2964
  const jwtToken = req.jwtToken || req.query.jwtToken;
2877
2965
  if (!jwtToken) {
2878
2966
  tracer?.trace('getPluginLicenseStatus:noToken', {});
2879
- res.status(400).send(tracer ? tracer.wrapResponse('Please go to Settings and authorize CRM platform') : 'Please go to Settings and authorize CRM platform');
2967
+ res.status(400).send(wrapDebugResponse(tracer, 'Please go to Settings and authorize CRM platform'));
2880
2968
  return;
2881
2969
  }
2882
2970
  const unAuthData = jwt.decodeJwt(jwtToken);
2883
2971
  const user = await UserModel.findByPk(unAuthData?.id);
2884
2972
  if (!user) {
2885
2973
  tracer?.trace('getPluginLicenseStatus:userNotFound', {});
2886
- res.status(400).send(tracer ? tracer.wrapResponse('User not found') : 'User not found');
2974
+ res.status(400).send(wrapDebugResponse(tracer, 'User not found'));
2887
2975
  return;
2888
2976
  }
2889
2977
  const { rcAccountId, pluginId } = req.query;
2890
2978
  if (!rcAccountId || !pluginId) {
2891
- res.status(400).send(tracer ? tracer.wrapResponse('rcAccountId and pluginId are required') : 'rcAccountId and pluginId are required');
2979
+ res.status(400).send(wrapDebugResponse(tracer, 'rcAccountId and pluginId are required'));
2892
2980
  return;
2893
2981
  }
2894
2982
  const licenseStatus = await pluginCore.getPluginLicenseStatus({ rcAccountId, pluginId });
2895
- res.status(200).send(tracer ? tracer.wrapResponse(licenseStatus) : licenseStatus);
2983
+ res.status(200).send(wrapDebugResponse(tracer, licenseStatus));
2896
2984
  }
2897
2985
  catch (e) {
2898
2986
  logger.error('Get plugin license status failed', { stack: e.stack });
2899
- res.status(200).send(tracer ? tracer.wrapResponse({ licenseStatus: false, licenseStatusDescription: e.message || e }) : { licenseStatus: false, licenseStatusDescription: e.message || e });
2987
+ res.status(200).send(wrapDebugResponse(tracer, { licenseStatus: false, licenseStatusDescription: getErrorResponse(e) }));
2900
2988
  tracer?.traceError('getPluginLicenseStatus:error', e);
2901
2989
  }
2902
2990
  });
2903
-
2904
2991
  if (process.env.IS_PROD === 'false') {
2905
2992
  router.post('/registerMockUser', async function (req, res) {
2906
2993
  const secretKey = req.query.secretKey;
@@ -2957,7 +3044,6 @@ function createCoreRouter() {
2957
3044
  router.get('/.well-known/openai-apps-challenge', (req, res) => {
2958
3045
  res.send(process.env.CHATGPT_VERIFICATION_CODE);
2959
3046
  });
2960
-
2961
3047
  // --- METADATA ENDPOINT 1: Resource Metadata ---
2962
3048
  // Tells the client "I am protected" and "Here is who protects me"
2963
3049
  router.get('/.well-known/oauth-protected-resource', (req, res) => {
@@ -2968,7 +3054,6 @@ function createCoreRouter() {
2968
3054
  scopes_supported: ["ReadAccounts"]
2969
3055
  });
2970
3056
  });
2971
-
2972
3057
  // --- METADATA ENDPOINT 2: Auth Server Metadata ---
2973
3058
  // Usually, you can redirect to your provider's configuration.
2974
3059
  // If your provider supports OIDC discovery, this is often sufficient.
@@ -2976,54 +3061,68 @@ function createCoreRouter() {
2976
3061
  res.json({
2977
3062
  issuer: process.env.APP_SERVER,
2978
3063
  registration_endpoint: `${process.env.APP_SERVER}/oauth/register`,
2979
-
2980
- // CHANGE THIS: Don't point to RingCentral. Point to your own Shim.
3064
+ // Keep the shim so unsupported metadata params are stripped before RingCentral.
2981
3065
  authorization_endpoint: `${process.env.APP_SERVER}/oauth/authorize_shim`,
2982
-
2983
- // Keep the token endpoint pointing to RingCentral (that usually works fine)
3066
+ // MCP clients exchange the authorization code with RingCentral directly using PKCE.
2984
3067
  token_endpoint: `${process.env.RINGCENTRAL_SERVER}/restapi/oauth/token`,
2985
- token_endpoint_auth_methods_supported: ["client_secret_basic"],
2986
- response_types_supported: ["code"]
3068
+ token_endpoint_auth_methods_supported: ["none"],
3069
+ response_types_supported: ["code"],
3070
+ grant_types_supported: ["authorization_code", "refresh_token"],
3071
+ code_challenge_methods_supported: ["S256"]
2987
3072
  });
2988
3073
  });
2989
-
2990
3074
  router.get('/oauth/authorize_shim', (req, res) => {
2991
- // 1. Get the parameters ChatGPT sent us
2992
- const { response_type, client_id, redirect_uri, state, scope } = req.query;
2993
-
2994
- // 2. Rebuild the query string for RingCentral
2995
- // We explicitly LEAVE OUT 'resource' and any other junk
2996
- const params = new URLSearchParams({
2997
- response_type,
2998
- client_id, // This will be your RC Client ID (since ChatGPT got it from /register)
2999
- redirect_uri,
3000
- state,
3001
- scope
3002
- });
3003
-
3004
- // 3. Redirect the user's browser to the REAL RingCentral URL
3075
+ const mcpClientId = process.env.RINGCENTRAL_MCP_CLIENT_ID;
3076
+ if (!mcpClientId) {
3077
+ return res.status(500).send('RINGCENTRAL_MCP_CLIENT_ID is not configured');
3078
+ }
3079
+ const { response_type, client_id, redirect_uri, state, scope, code_challenge, code_challenge_method, } = req.query;
3080
+ const requestedClientId = getFirstQueryValue(client_id);
3081
+ const requestedCodeChallenge = getFirstQueryValue(code_challenge);
3082
+ const requestedCodeChallengeMethod = getFirstQueryValue(code_challenge_method);
3083
+ if (requestedClientId && requestedClientId !== mcpClientId) {
3084
+ return res.status(400).send(buildMcpOAuthError({
3085
+ error: 'mcp_oauth_client_mismatch',
3086
+ message: MCP_OAUTH_STALE_CLIENT_MESSAGE,
3087
+ }));
3088
+ }
3089
+ if (!getFirstQueryValue(response_type) || !getFirstQueryValue(redirect_uri)) {
3090
+ return res.status(400).send('Missing OAuth authorization parameters');
3091
+ }
3092
+ if (!requestedCodeChallenge || requestedCodeChallengeMethod !== 'S256') {
3093
+ return res.status(400).send('PKCE S256 code_challenge is required');
3094
+ }
3095
+ const params = new URLSearchParams();
3096
+ appendOAuthQueryParam(params, 'response_type', response_type);
3097
+ params.set('client_id', mcpClientId);
3098
+ appendOAuthQueryParam(params, 'redirect_uri', redirect_uri);
3099
+ appendOAuthQueryParam(params, 'state', state);
3100
+ appendOAuthQueryParam(params, 'scope', scope);
3101
+ appendOAuthQueryParam(params, 'code_challenge', code_challenge);
3102
+ appendOAuthQueryParam(params, 'code_challenge_method', code_challenge_method);
3005
3103
  const rcUrl = `${process.env.RINGCENTRAL_SERVER}/restapi/oauth/authorize?${params.toString()}`;
3006
-
3007
3104
  console.log("Proxying OAuth request to:", rcUrl); // Helpful for debugging
3008
3105
  res.redirect(rcUrl);
3009
3106
  });
3010
-
3011
3107
  router.post('/oauth/register', (req, res) => {
3012
- // The MCP client calls this to get credentials.
3013
- // We simply return our hardcoded RingCentral app credentials.
3108
+ const mcpClientId = process.env.RINGCENTRAL_MCP_CLIENT_ID;
3109
+ if (!mcpClientId) {
3110
+ return res.status(500).send('RINGCENTRAL_MCP_CLIENT_ID is not configured');
3111
+ }
3112
+ // Dynamic registration for MCP public clients. No client secret is issued.
3014
3113
  res.json({
3015
- client_id: process.env.RINGCENTRAL_CLIENT_ID,
3016
- client_secret: process.env.RINGCENTRAL_CLIENT_SECRET
3114
+ client_id: mcpClientId,
3115
+ token_endpoint_auth_method: 'none',
3116
+ grant_types: ['authorization_code', 'refresh_token'],
3117
+ response_types: ['code']
3017
3118
  });
3018
3119
  });
3019
-
3020
3120
  router.use('/mcp', (req, res, next) => {
3021
3121
  // Widget tool calls are unauthenticated — they come from the iframe
3022
3122
  // which has no access to the RC bearer token.
3023
3123
  if (req.path === '/widget-tool-call') {
3024
3124
  return next();
3025
3125
  }
3026
-
3027
3126
  const authHeader = req.headers.authorization;
3028
3127
  const token = authHeader?.split(' ')[1]; // Remove "Bearer "
3029
3128
  // Allow GET and OPTIONS (CORS preflight) to pass freely.
@@ -3045,16 +3144,23 @@ function createCoreRouter() {
3045
3144
  }
3046
3145
  // SCENARIO 1: No Token provided. Kick off the OAuth flow.
3047
3146
  if (!token) {
3048
- res.setHeader('WWW-Authenticate', `Bearer realm="mcp", resource_metadata="${process.env.APP_SERVER}/.well-known/oauth-protected-resource"`);
3049
- return res.status(401).send();
3147
+ res.setHeader('WWW-Authenticate', getMcpOAuthChallengeHeader({
3148
+ appServer: process.env.APP_SERVER,
3149
+ errorDescription: MCP_OAUTH_REQUIRED_MESSAGE,
3150
+ }));
3151
+ return res.status(401).json(buildMcpOAuthError({
3152
+ message: MCP_OAUTH_REQUIRED_MESSAGE,
3153
+ }));
3050
3154
  }
3051
-
3052
3155
  // SCENARIO 2: Token provided. Verify it.
3053
3156
  try {
3054
3157
  next();
3055
- } catch {
3056
- res.setHeader('WWW-Authenticate', `Bearer realm="mcp", resource_metadata="${process.env.APP_SERVER}/.well-known/oauth-protected-resource"`);
3057
- return res.status(401).send();
3158
+ }
3159
+ catch {
3160
+ res.setHeader('WWW-Authenticate', getMcpOAuthChallengeHeader({
3161
+ appServer: process.env.APP_SERVER,
3162
+ }));
3163
+ return res.status(401).json(buildMcpOAuthError());
3058
3164
  }
3059
3165
  });
3060
3166
  // Handle OPTIONS for CORS preflight
@@ -3065,21 +3171,18 @@ function createCoreRouter() {
3065
3171
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
3066
3172
  res.status(200).end();
3067
3173
  });
3068
-
3069
3174
  // Dedicated endpoint for all MCP traffic
3070
3175
  router.post('/mcp', async (req, res) => {
3071
3176
  // Set CORS headers
3072
3177
  res.setHeader('Access-Control-Allow-Origin', '*');
3073
3178
  res.setHeader('Content-Type', 'application/json');
3074
-
3075
3179
  await mcpHandler.handleMcpRequest(req, res);
3076
3180
  });
3077
-
3078
3181
  // Lightweight endpoint for widget tool calls (bypasses MCP protocol)
3079
3182
  router.options('/mcp/widget-tool-call', (req, res) => {
3080
3183
  res.setHeader('Access-Control-Allow-Origin', '*');
3081
3184
  res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
3082
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
3185
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-App-Connect-Widget-Token');
3083
3186
  res.status(200).end();
3084
3187
  });
3085
3188
  router.post('/mcp/widget-tool-call', async (req, res) => {
@@ -3087,10 +3190,8 @@ function createCoreRouter() {
3087
3190
  res.setHeader('Content-Type', 'application/json');
3088
3191
  await mcpHandler.handleWidgetToolCall(req, res);
3089
3192
  });
3090
-
3091
3193
  return router;
3092
3194
  }
3093
-
3094
3195
  // Create middleware for core functionality
3095
3196
  function createCoreMiddleware() {
3096
3197
  return [
@@ -3110,18 +3211,12 @@ function createCoreMiddleware() {
3110
3211
  })
3111
3212
  ];
3112
3213
  }
3113
-
3114
3214
  // Initialize core services
3115
3215
  async function initializeCore(options = {}) {
3116
- const {
3117
- skipDatabaseInit = false,
3118
- skipAnalyticsInit = false,
3119
- } = options;
3120
-
3216
+ const { skipDatabaseInit = false, skipAnalyticsInit = false, } = options;
3121
3217
  if (!skipAnalyticsInit) {
3122
3218
  analytics.init();
3123
3219
  }
3124
-
3125
3220
  if (!skipDatabaseInit) {
3126
3221
  await initDB();
3127
3222
  // Run the heavy callLogs primary-key migration in the BACKGROUND, off the
@@ -3136,7 +3231,6 @@ async function initializeCore(options = {}) {
3136
3231
  }
3137
3232
  }
3138
3233
  }
3139
-
3140
3234
  // Create a complete app with core functionality
3141
3235
  function createCoreApp(options = {}) {
3142
3236
  const coreInit = initializeCore(options).catch((err) => {
@@ -3147,14 +3241,14 @@ function createCoreApp(options = {}) {
3147
3241
  throw err;
3148
3242
  });
3149
3243
  const app = express();
3150
-
3151
3244
  // Block routing until DB sync/migrations finish so traffic never hits a half-ready DB,
3152
3245
  // and ensure init failures are logged instead of only as unhandled rejections.
3153
3246
  app.use(async (req, res, next) => {
3154
3247
  try {
3155
3248
  await coreInit;
3156
3249
  next();
3157
- } catch (e) {
3250
+ }
3251
+ catch (e) {
3158
3252
  logger.error('Request rejected: core initialization failed', {
3159
3253
  message: e?.message,
3160
3254
  stack: e?.stack,
@@ -3164,22 +3258,17 @@ function createCoreApp(options = {}) {
3164
3258
  .json({ error: 'Service unavailable', detail: e?.message });
3165
3259
  }
3166
3260
  });
3167
-
3168
3261
  // Allow bigger POST body size
3169
3262
  app.use(express.json({ limit: '50mb' }));
3170
3263
  app.use(express.urlencoded({ limit: '50mb', extended: true }));
3171
-
3172
3264
  // Apply core middleware
3173
3265
  const coreMiddleware = createCoreMiddleware();
3174
3266
  coreMiddleware.forEach(middleware => app.use(middleware));
3175
-
3176
3267
  // Apply core routes
3177
3268
  const coreRouter = createCoreRouter();
3178
3269
  app.use('/', coreRouter);
3179
-
3180
3270
  return app;
3181
3271
  }
3182
-
3183
3272
  exports.createCoreRouter = createCoreRouter;
3184
3273
  exports.createCoreMiddleware = createCoreMiddleware;
3185
3274
  exports.createCoreApp = createCoreApp;