@app-connect/core 1.7.36 → 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 (287) 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} +548 -450
  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/dist/lib/migrateCallLogsSchema.js +339 -0
  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 +13 -1
  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/migrateCallLogsSchema.js +0 -237
  198. package/lib/ringcentral.js +0 -267
  199. package/mcp/README.md +0 -420
  200. package/mcp/tools/index.js +0 -51
  201. package/mcp/ui/App/App.tsx +0 -358
  202. package/mcp/ui/App/components/AuthInfoForm.tsx +0 -113
  203. package/mcp/ui/App/components/AuthSuccess.tsx +0 -22
  204. package/mcp/ui/App/components/ConnectorList.tsx +0 -82
  205. package/mcp/ui/App/components/DebugPanel.tsx +0 -43
  206. package/mcp/ui/App/components/OAuthConnect.tsx +0 -270
  207. package/mcp/ui/App/lib/callTool.ts +0 -130
  208. package/mcp/ui/App/lib/debugLog.ts +0 -41
  209. package/mcp/ui/App/lib/developerPortal.ts +0 -111
  210. package/mcp/ui/App/main.css +0 -6
  211. package/mcp/ui/App/root.tsx +0 -13
  212. package/mcp/ui/dist/index.html +0 -53
  213. package/mcp/ui/vite.config.ts +0 -16
  214. package/models/accountDataModel.js +0 -34
  215. package/models/adminConfigModel.js +0 -35
  216. package/models/callLogModel.js +0 -39
  217. package/models/dynamo/connectorSchema.js +0 -146
  218. package/models/llmSessionModel.js +0 -17
  219. package/models/sequelize.js +0 -17
  220. package/models/userModel.js +0 -45
  221. package/test/connector/developerPortal.test.js +0 -166
  222. package/test/connector/mock.test.js +0 -131
  223. package/test/connector/proxy/engine.test.js +0 -211
  224. package/test/connector/proxy/index.test.js +0 -525
  225. package/test/connector/proxy/sample.json +0 -162
  226. package/test/connector/registry.test.js +0 -416
  227. package/test/handlers/admin.test.js +0 -960
  228. package/test/handlers/appointment.test.js +0 -260
  229. package/test/handlers/auth.test.js +0 -1096
  230. package/test/handlers/calldown.test.js +0 -310
  231. package/test/handlers/contact.test.js +0 -1014
  232. package/test/handlers/disposition.test.js +0 -396
  233. package/test/handlers/log.test.js +0 -1847
  234. package/test/handlers/managedAuth.test.js +0 -458
  235. package/test/handlers/managedOAuth.test.js +0 -262
  236. package/test/handlers/plugin.test.js +0 -429
  237. package/test/handlers/user.test.js +0 -381
  238. package/test/index.test.js +0 -301
  239. package/test/lib/analytics.test.js +0 -146
  240. package/test/lib/authSession.test.js +0 -173
  241. package/test/lib/cacheCleanup.test.js +0 -127
  242. package/test/lib/callLogComposer.test.js +0 -1231
  243. package/test/lib/debugTracer.test.js +0 -328
  244. package/test/lib/encode.test.js +0 -59
  245. package/test/lib/errorHandler.test.js +0 -246
  246. package/test/lib/generalErrorMessage.test.js +0 -82
  247. package/test/lib/jwt.test.js +0 -176
  248. package/test/lib/logger.test.js +0 -206
  249. package/test/lib/oauth.test.js +0 -359
  250. package/test/lib/ringcentral.test.js +0 -467
  251. package/test/lib/s3ErrorLogReport.test.js +0 -187
  252. package/test/lib/sharedSMSComposer.test.js +0 -1084
  253. package/test/lib/util.test.js +0 -329
  254. package/test/mcp/mcpHandler.test.js +0 -73
  255. package/test/mcp/mcpHandlerMore.test.js +0 -384
  256. package/test/mcp/tools/appointmentTools.test.js +0 -362
  257. package/test/mcp/tools/checkAuthStatus.test.js +0 -83
  258. package/test/mcp/tools/createCallLog.test.js +0 -436
  259. package/test/mcp/tools/createContact.test.js +0 -58
  260. package/test/mcp/tools/createMessageLog.test.js +0 -595
  261. package/test/mcp/tools/doAuth.test.js +0 -113
  262. package/test/mcp/tools/findContactByName.test.js +0 -275
  263. package/test/mcp/tools/findContactByPhone.test.js +0 -296
  264. package/test/mcp/tools/getCallLog.test.js +0 -298
  265. package/test/mcp/tools/getGoogleFilePicker.test.js +0 -281
  266. package/test/mcp/tools/getPublicConnectors.test.js +0 -107
  267. package/test/mcp/tools/getSessionInfo.test.js +0 -127
  268. package/test/mcp/tools/logout.test.js +0 -233
  269. package/test/mcp/tools/rcGetCallLogs.test.js +0 -56
  270. package/test/mcp/tools/updateCallLog.test.js +0 -360
  271. package/test/models/accountDataModel.test.js +0 -98
  272. package/test/models/callDownListModel.test.js +0 -125
  273. package/test/models/dynamo/connectorSchema.test.js +0 -189
  274. package/test/models/dynamo/lockSchema.test.js +0 -37
  275. package/test/models/dynamo/noteCacheSchema.test.js +0 -45
  276. package/test/models/llmSessionModel.test.js +0 -91
  277. package/test/models/models.test.js +0 -660
  278. package/test/routes/calldownRoutes.test.js +0 -224
  279. package/test/routes/coreRouterBroadRoutes.test.js +0 -855
  280. package/test/routes/dispositionRoutes.test.js +0 -192
  281. package/test/routes/managedAuthRoutes.test.js +0 -386
  282. package/test/routes/pluginRoutes.test.js +0 -262
  283. package/test/setup.js +0 -178
  284. /package/{mcp → dist/mcp}/ui/index.html +0 -0
  285. /package/{mcp → dist/mcp}/ui/package-lock.json +0 -0
  286. /package/{mcp → dist/mcp}/ui/package.json +0 -0
  287. /package/{mcp → dist/mcp}/ui/tsconfig.json +0 -0
@@ -1,15 +1,32 @@
1
- const oauth = require('../lib/oauth');
2
- const { UserModel } = require('../models/userModel');
3
- const connectorRegistry = require('../connector/registry');
4
- const Op = require('sequelize').Op;
5
- const { RingCentral } = require('../lib/ringcentral');
6
- const adminCore = require('./admin');
7
- const { Connector } = require('../models/dynamo/connectorSchema');
1
+ "use strict";
2
+ // @ts-check
3
+ /** @typedef {import('../types').ApiKeyLoginParams} ApiKeyLoginParams */
4
+ /** @typedef {import('../types').AuthHandlerResult} AuthHandlerResult */
5
+ /** @typedef {import('../types').AuthValidationParams} AuthValidationParams */
6
+ /** @typedef {import('../types').AuthValidationResult} AuthValidationResult */
7
+ /** @typedef {import('../types').LicenseStatusParams} LicenseStatusParams */
8
+ /** @typedef {import('../types').OAuthCallbackParams} OAuthCallbackParams */
9
+ /** @typedef {import('../types').RingcentralOAuthCallbackParams} RingcentralOAuthCallbackParams */
10
+ /** @typedef {import('../types').SaveUserInfoParams} SaveUserInfoParams */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const oauth = /** @type {any} */ (require('../lib/oauth'));
13
+ const { UserModel: UserModelImport } = require('../models/userModel');
14
+ const UserModel = /** @type {any} */ (UserModelImport);
15
+ const connectorRegistry = /** @type {any} */ (require('../connector/registry'));
16
+ const Op = /** @type {any} */ (require('sequelize').Op);
17
+ const { RingCentral: RingCentralImport } = require('../lib/ringcentral');
18
+ const RingCentral = /** @type {any} */ (RingCentralImport);
19
+ const adminCore = /** @type {any} */ (require('./admin'));
20
+ const { Connector: ConnectorImport } = require('../models/dynamo/connectorSchema');
21
+ const Connector = /** @type {any} */ (ConnectorImport);
8
22
  const { handleDatabaseError } = require('../lib/errorHandler');
9
- const managedAuthCore = require('./managedAuth');
10
- const managedOAuthCore = require('./managedOAuth');
23
+ const managedAuthCore = /** @type {any} */ (require('./managedAuth'));
24
+ const managedOAuthCore = /** @type {any} */ (require('./managedOAuth'));
11
25
  const { getHashValue } = require('../lib/util');
12
-
26
+ /**
27
+ * @param {OAuthCallbackParams} params
28
+ * @returns {Promise<AuthHandlerResult>}
29
+ */
13
30
  async function onOAuthCallback({ platform, hostname, tokenUrl, query, hashedRcExtensionId, isFromMCP = false }) {
14
31
  const callbackUri = query.callbackUri;
15
32
  const apiUrl = query.apiUrl;
@@ -43,9 +60,8 @@ async function onOAuthCallback({ platform, hostname, tokenUrl, query, hashedRcEx
43
60
  messageType: 'danger',
44
61
  message: oauthInfo.failMessage
45
62
  }
46
- }
63
+ };
47
64
  }
48
-
49
65
  // Some platforms require different oauth queries, this won't affect normal OAuth process unless CRM module implements getOverridingOAuthOption() method
50
66
  let overridingOAuthOption = null;
51
67
  if (platformModule.getOverridingOAuthOption != null) {
@@ -56,7 +72,6 @@ async function onOAuthCallback({ platform, hostname, tokenUrl, query, hashedRcEx
56
72
  const { accessToken, refreshToken, expires, data } = await oauthApp.code.getToken(callbackUri, overridingOAuthOption);
57
73
  const authHeader = `Bearer ${accessToken}`;
58
74
  const { successful, platformUserInfo, returnMessage } = await platformModule.getUserInfo({ authHeader, tokenUrl: resolvedTokenUrl, apiUrl, hostname: resolvedHostname, platform, username, callbackUri, query, proxyId, proxyConfig, userEmail, data });
59
-
60
75
  if (successful) {
61
76
  let userInfo = null;
62
77
  try {
@@ -96,10 +111,13 @@ async function onOAuthCallback({ platform, hostname, tokenUrl, query, hashedRcEx
96
111
  return {
97
112
  userInfo: null,
98
113
  returnMessage
99
- }
114
+ };
100
115
  }
101
116
  }
102
-
117
+ /**
118
+ * @param {ApiKeyLoginParams} params
119
+ * @returns {Promise<AuthHandlerResult>}
120
+ */
103
121
  async function onApiKeyLogin({ platform, hostname, apiKey, proxyId, rcAccountId, rcExtensionId, connectorId, isPrivate, hashedRcExtensionId, additionalInfo }) {
104
122
  const platformModule = connectorRegistry.getConnector(platform);
105
123
  let resolvedAdditionalInfo = {
@@ -109,6 +127,7 @@ async function onApiKeyLogin({ platform, hostname, apiKey, proxyId, rcAccountId,
109
127
  resolvedAdditionalInfo.apiKey = apiKey;
110
128
  }
111
129
  let resolvedApiKey = apiKey;
130
+ /** @type {Array<Record<string, unknown>>} */
112
131
  let managedFieldDefinitions = [];
113
132
  if (rcAccountId) {
114
133
  managedFieldDefinitions = await managedAuthCore.getManagedFieldDefinitions({ rcAccountId, platform, connectorId, isPrivate });
@@ -179,9 +198,12 @@ async function onApiKeyLogin({ platform, hostname, apiKey, proxyId, rcAccountId,
179
198
  return {
180
199
  userInfo: null,
181
200
  returnMessage
182
- }
201
+ };
183
202
  }
184
-
203
+ /**
204
+ * @param {SaveUserInfoParams} params
205
+ * @returns {Promise<unknown>}
206
+ */
185
207
  async function saveUserInfo({ platformUserInfo, platform, hostname, accessToken, refreshToken, tokenExpiry, rcAccountId, hashedRcExtensionId, proxyId }) {
186
208
  const id = platformUserInfo.id;
187
209
  const name = platformUserInfo.name;
@@ -192,23 +214,21 @@ async function saveUserInfo({ platformUserInfo, platform, hostname, accessToken,
192
214
  platformAdditionalInfo.proxyId = proxyId;
193
215
  if (existingUser) {
194
216
  try {
195
- await existingUser.update(
196
- {
197
- platform,
198
- hostname,
199
- timezoneName,
200
- timezoneOffset,
201
- accessToken,
202
- refreshToken,
203
- tokenExpiry,
204
- rcAccountId,
205
- hashedRcExtensionId,
206
- platformAdditionalInfo: {
207
- ...existingUser.platformAdditionalInfo, // keep existing platformAdditionalInfo
208
- ...platformAdditionalInfo,
209
- }
217
+ await existingUser.update({
218
+ platform,
219
+ hostname,
220
+ timezoneName,
221
+ timezoneOffset,
222
+ accessToken,
223
+ refreshToken,
224
+ tokenExpiry,
225
+ rcAccountId,
226
+ hashedRcExtensionId,
227
+ platformAdditionalInfo: {
228
+ ...existingUser.platformAdditionalInfo, // keep existing platformAdditionalInfo
229
+ ...platformAdditionalInfo,
210
230
  }
211
- );
231
+ });
212
232
  }
213
233
  catch (error) {
214
234
  return handleDatabaseError(error, 'Error saving user info');
@@ -240,7 +260,10 @@ async function saveUserInfo({ platformUserInfo, platform, hostname, accessToken,
240
260
  name
241
261
  };
242
262
  }
243
-
263
+ /**
264
+ * @param {LicenseStatusParams} params
265
+ * @returns {Promise<unknown>}
266
+ */
244
267
  async function getLicenseStatus({ userId, platform }) {
245
268
  const user = await UserModel.findByPk(userId);
246
269
  if (!user) {
@@ -248,14 +271,17 @@ async function getLicenseStatus({ userId, platform }) {
248
271
  isLicenseValid: false,
249
272
  licenseStatus: 'Invalid (User not found)',
250
273
  licenseStatusDescription: ''
251
- }
274
+ };
252
275
  }
253
276
  const platformModule = connectorRegistry.getConnector(platform);
254
277
  const licenseStatus = await platformModule.getLicenseStatus({ userId, platform, user });
255
278
  return licenseStatus;
256
279
  }
257
-
258
280
  // Just for oauth ATM
281
+ /**
282
+ * @param {AuthValidationParams} params
283
+ * @returns {Promise<AuthValidationResult>}
284
+ */
259
285
  async function authValidation({ platform, userId }) {
260
286
  let existingUser = await UserModel.findOne({
261
287
  where: {
@@ -283,18 +309,21 @@ async function authValidation({ platform, userId }) {
283
309
  returnMessage,
284
310
  status,
285
311
  failReason: successful ? '' : 'CRM. API failed'
286
- }
312
+ };
287
313
  }
288
314
  else {
289
315
  return {
290
316
  successful: false,
291
317
  status: 404,
292
318
  failReason: 'App Connect. User not found in database'
293
- }
319
+ };
294
320
  }
295
321
  }
296
-
297
322
  // Ringcentral
323
+ /**
324
+ * @param {RingcentralOAuthCallbackParams} params
325
+ * @returns {Promise<void>}
326
+ */
298
327
  async function onRingcentralOAuthCallback({ code, rcAccountId }) {
299
328
  if (!process.env.RINGCENTRAL_SERVER || !process.env.RINGCENTRAL_CLIENT_ID || !process.env.RINGCENTRAL_CLIENT_SECRET) {
300
329
  return;
@@ -314,7 +343,6 @@ async function onRingcentralOAuthCallback({ code, rcAccountId }) {
314
343
  adminTokenExpiry: expire_time
315
344
  });
316
345
  }
317
-
318
346
  exports.onOAuthCallback = onOAuthCallback;
319
347
  exports.onApiKeyLogin = onApiKeyLogin;
320
348
  exports.authValidation = authValidation;
@@ -0,0 +1,10 @@
1
+ /** @typedef {import('../types').CallDownJwtData} CallDownJwtData */
2
+ /** @typedef {import('../types').CallDownListParams} CallDownListParams */
3
+ /** @typedef {import('../types').CallDownListResult} CallDownListResult */
4
+ /** @typedef {import('../types').CallDownMarkCalledParams} CallDownMarkCalledParams */
5
+ /** @typedef {import('../types').CallDownOperationResult} CallDownOperationResult */
6
+ /** @typedef {import('../types').CallDownRecordParams} CallDownRecordParams */
7
+ /** @typedef {import('../types').CallDownScheduleParams} CallDownScheduleParams */
8
+ /** @typedef {import('../types').CallDownScheduleResult} CallDownScheduleResult */
9
+ /** @typedef {import('../types').CallDownUpdateParams} CallDownUpdateParams */
10
+ export {};
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ // @ts-check
3
+ /** @typedef {import('../types').CallDownJwtData} CallDownJwtData */
4
+ /** @typedef {import('../types').CallDownListParams} CallDownListParams */
5
+ /** @typedef {import('../types').CallDownListResult} CallDownListResult */
6
+ /** @typedef {import('../types').CallDownMarkCalledParams} CallDownMarkCalledParams */
7
+ /** @typedef {import('../types').CallDownOperationResult} CallDownOperationResult */
8
+ /** @typedef {import('../types').CallDownRecordParams} CallDownRecordParams */
9
+ /** @typedef {import('../types').CallDownScheduleParams} CallDownScheduleParams */
10
+ /** @typedef {import('../types').CallDownScheduleResult} CallDownScheduleResult */
11
+ /** @typedef {import('../types').CallDownUpdateParams} CallDownUpdateParams */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const { UserModel: UserModelImport } = require('../models/userModel');
14
+ const UserModel = /** @type {any} */ (UserModelImport);
15
+ const { CallDownListModel: CallDownListModelImport } = require('../models/callDownListModel');
16
+ const CallDownListModel = /** @type {any} */ (CallDownListModelImport);
17
+ const { Op: OpImport } = require('sequelize');
18
+ const Op = /** @type {any} */ (OpImport);
19
+ const jwt = /** @type {any} */ (require('../lib/jwt'));
20
+ const { handleDatabaseError } = require('../lib/errorHandler');
21
+ /**
22
+ * @param {CallDownScheduleParams} params
23
+ * @returns {Promise<CallDownScheduleResult>}
24
+ */
25
+ async function schedule({ jwtToken, body }) {
26
+ const unAuthData = /** @type {CallDownJwtData | null} */ (jwt.decodeJwt(jwtToken));
27
+ if (!unAuthData?.id)
28
+ throw new Error('Unauthorized');
29
+ const user = await UserModel.findByPk(unAuthData.id);
30
+ if (!user)
31
+ throw new Error('User not found');
32
+ const crypto = require('crypto');
33
+ const recordId = crypto.randomBytes(16).toString('hex');
34
+ const payload = {
35
+ id: recordId,
36
+ userId: user.id,
37
+ contactId: body.contactId?.toString?.() ?? body.contactId,
38
+ contactType: body.contactType ?? 'contact',
39
+ contactName: body.contactName ?? '',
40
+ phoneNumber: body.phoneNumber ?? '',
41
+ status: 'scheduled',
42
+ scheduledAt: body.scheduledAt ? new Date(body.scheduledAt) : null,
43
+ lastCallAt: null
44
+ };
45
+ await CallDownListModel.create(payload);
46
+ return { id: recordId };
47
+ }
48
+ /**
49
+ * @param {CallDownListParams} params
50
+ * @returns {Promise<CallDownListResult>}
51
+ */
52
+ async function list({ jwtToken, status }) {
53
+ const unAuthData = /** @type {CallDownJwtData | null} */ (jwt.decodeJwt(jwtToken));
54
+ if (!unAuthData?.id)
55
+ throw new Error('Unauthorized');
56
+ const statusParam = (status || 'All').toString().toLowerCase();
57
+ /** @type {{ userId: string | number, status?: unknown }} */
58
+ const whereClause = { userId: unAuthData.id };
59
+ if (statusParam === 'called')
60
+ whereClause.status = 'called';
61
+ else if (['not called', 'not_called', 'notcalled'].includes(statusParam))
62
+ whereClause.status = { [Op.ne]: 'called' };
63
+ const items = await CallDownListModel.findAll({ where: whereClause, order: [["scheduledAt", "ASC"]] });
64
+ return { items };
65
+ }
66
+ /**
67
+ * @param {CallDownRecordParams} params
68
+ * @returns {Promise<CallDownOperationResult>}
69
+ */
70
+ async function remove({ jwtToken, id }) {
71
+ const unAuthData = /** @type {CallDownJwtData | null} */ (jwt.decodeJwt(jwtToken));
72
+ if (!unAuthData?.id)
73
+ throw new Error('Unauthorized');
74
+ const deleted = await CallDownListModel.destroy({ where: { id, userId: unAuthData.id } });
75
+ if (!deleted)
76
+ throw new Error('Not found');
77
+ return { successful: true };
78
+ }
79
+ /**
80
+ * @param {CallDownMarkCalledParams} params
81
+ * @returns {Promise<CallDownOperationResult>}
82
+ */
83
+ async function markCalled({ jwtToken, id, lastCallAt }) {
84
+ const unAuthData = /** @type {CallDownJwtData | null} */ (jwt.decodeJwt(jwtToken));
85
+ if (!unAuthData?.id)
86
+ throw new Error('Unauthorized');
87
+ const when = lastCallAt ? new Date(/** @type {any} */ (lastCallAt)) : new Date();
88
+ try {
89
+ const [affected] = await CallDownListModel.update({ status: 'called', lastCallAt: when }, { where: { id, userId: unAuthData.id } });
90
+ if (!affected)
91
+ throw new Error('Not found');
92
+ return { successful: true };
93
+ }
94
+ catch (error) {
95
+ return handleDatabaseError(error, 'Error marking call as called', { id, userId: unAuthData.id });
96
+ }
97
+ }
98
+ /**
99
+ * @param {CallDownUpdateParams} params
100
+ * @returns {Promise<CallDownOperationResult>}
101
+ */
102
+ async function update({ jwtToken, id, updateData }) {
103
+ const unAuthData = /** @type {CallDownJwtData | null} */ (jwt.decodeJwt(jwtToken));
104
+ if (!unAuthData?.id)
105
+ throw new Error('Unauthorized');
106
+ // Prepare the update object with only valid fields
107
+ const allowedFields = ['contactId', 'contactType', 'contactName', 'phoneNumber', 'status', 'scheduledAt', 'lastCallAt', 'note'];
108
+ /** @type {Record<string, unknown>} */
109
+ const updateObject = {};
110
+ // Filter and prepare update data
111
+ Object.keys(updateData).forEach(key => {
112
+ if (allowedFields.includes(key)) {
113
+ let value = updateData[key];
114
+ // Handle date fields
115
+ if ((key === 'scheduledAt' || key === 'lastCallAt') && value) {
116
+ value = new Date(/** @type {any} */ (value));
117
+ }
118
+ updateObject[key] = value;
119
+ }
120
+ });
121
+ // If no valid fields to update, throw error
122
+ if (Object.keys(updateObject).length === 0) {
123
+ throw new Error('No valid fields to update');
124
+ }
125
+ const [affected] = await CallDownListModel.update(updateObject, { where: { id, userId: unAuthData.id } });
126
+ if (!affected)
127
+ throw new Error('Not found');
128
+ return { successful: true };
129
+ }
130
+ exports.schedule = schedule;
131
+ exports.list = list;
132
+ exports.remove = remove;
133
+ exports.markCalled = markCalled;
134
+ exports.update = update;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,10 +1,30 @@
1
- const oauth = require('../lib/oauth');
2
- const { UserModel } = require('../models/userModel');
3
- const connectorRegistry = require('../connector/registry');
4
- const { Connector } = require('../models/dynamo/connectorSchema');
5
- const { handleApiError } = require('../lib/errorHandler');
6
- const { AccountDataModel } = require('../models/accountDataModel');
7
-
1
+ "use strict";
2
+ // @ts-check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ /** @typedef {import('../types').AccountContactDataRecord} AccountContactDataRecord */
5
+ /** @typedef {import('../types').ContactConnectorImplementation} ContactConnectorImplementation */
6
+ /** @typedef {import('../types').ContactHandlerResult} ContactHandlerResult */
7
+ /** @typedef {import('../types').ContactHandlerUser} ContactHandlerUser */
8
+ /** @typedef {import('../types').CreateContactParams} CreateContactParams */
9
+ /** @typedef {import('../types').FindContactParams} FindContactParams */
10
+ /** @typedef {import('../types').FindContactWithNameParams} FindContactWithNameParams */
11
+ /** @typedef {import('../types').OAuthInfo} OAuthInfo */
12
+ /** @typedef {import('../types').ProviderError} ProviderError */
13
+ /** @typedef {import('../types').ProxyConfig} ProxyConfig */
14
+ const oauth = /** @type {{ getOAuthApp(info: OAuthInfo): any, checkAndRefreshAccessToken(oauthApp: any, user: ContactHandlerUser): Promise<ContactHandlerUser | null> }} */ (require('../lib/oauth'));
15
+ const { UserModel: RawUserModel } = require('../models/userModel');
16
+ const UserModel = /** @type {{ findOne(options: Record<string, unknown>): Promise<ContactHandlerUser | null> }} */ (RawUserModel);
17
+ const connectorRegistry = /** @type {{ getConnector(platform: string): ContactConnectorImplementation }} */ ( /** @type {unknown} */(require('../connector/registry')));
18
+ const { Connector: RawConnector } = require('../models/dynamo/connectorSchema');
19
+ const Connector = /** @type {{ getProxyConfig(proxyId: string): Promise<ProxyConfig | null> }} */ ( /** @type {unknown} */(RawConnector));
20
+ const { handleApiError: rawHandleApiError } = require('../lib/errorHandler');
21
+ const handleApiError = /** @type {(error: unknown, platform: string, operation: string, context?: Record<string, unknown>) => ContactHandlerResult} */ (rawHandleApiError);
22
+ const { AccountDataModel: RawAccountDataModel } = require('../models/accountDataModel');
23
+ const AccountDataModel = /** @type {{ findOne(options: Record<string, unknown>): Promise<AccountContactDataRecord | null>, create(values: Record<string, unknown>): Promise<AccountContactDataRecord> }} */ (RawAccountDataModel);
24
+ /**
25
+ * @param {FindContactParams} params
26
+ * @returns {Promise<ContactHandlerResult>}
27
+ */
8
28
  async function findContact({ platform, userId, phoneNumber, overridingFormat, isExtension, tracer, isForceRefreshAccountData = false }) {
9
29
  tracer?.trace('handler.findContact:entered', { platform, userId, phoneNumber });
10
30
  try {
@@ -15,7 +35,6 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
15
35
  }
16
36
  });
17
37
  tracer?.trace('handler.findContact:userFound', { user });
18
-
19
38
  if (!user || !user.accessToken) {
20
39
  tracer?.trace('handler.findContact:noUser', { userId });
21
40
  return {
@@ -34,7 +53,7 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
34
53
  platformName: platform,
35
54
  dataKey: `contact-${phoneNumber}`
36
55
  }
37
- })
56
+ });
38
57
  if (!isForceRefreshAccountData) {
39
58
  if (existingMatchedContactInfo) {
40
59
  console.log('found existing matched contact info in account data');
@@ -50,7 +69,6 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
50
69
  const platformModule = connectorRegistry.getConnector(platform);
51
70
  const authType = await platformModule.getAuthType({ proxyId, proxyConfig });
52
71
  tracer?.trace('handler.findContact:authType', { authType });
53
-
54
72
  let authHeader = '';
55
73
  switch (authType) {
56
74
  case 'oauth':
@@ -65,7 +83,7 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
65
83
  ttl: 5000
66
84
  },
67
85
  isRevokeUserSession: true
68
- }
86
+ };
69
87
  }
70
88
  authHeader = `Bearer ${user.accessToken}`;
71
89
  tracer?.trace('handler.findContact:oauthAuth', { authHeader });
@@ -76,10 +94,8 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
76
94
  tracer?.trace('handler.findContact:apiKeyAuth', {});
77
95
  break;
78
96
  }
79
-
80
97
  const { successful, matchedContactInfo, returnMessage, extraDataTracking } = await platformModule.findContact({ user, authHeader, phoneNumber, overridingFormat, isExtension, proxyConfig, tracer, isForceRefreshAccountData });
81
98
  tracer?.trace('handler.findContact:platformFindResult', { successful, matchedContactInfo });
82
-
83
99
  const matchedNonNewContacts = matchedContactInfo?.filter(c => !c.isNewContact) ?? [];
84
100
  if (matchedContactInfo != null && matchedNonNewContacts.length > 0) {
85
101
  tracer?.trace('handler.findContact:contactsFound', { count: matchedContactInfo.length });
@@ -115,37 +131,40 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
115
131
  returnMessage,
116
132
  extraDataTracking,
117
133
  contact: matchedContactInfo,
118
- }
134
+ };
119
135
  }
120
136
  return {
121
137
  successful,
122
- returnMessage:
123
- {
138
+ returnMessage: {
124
139
  message: `Contact not found`,
125
140
  messageType: 'warning',
126
141
  details: [{
127
- title: 'Details',
128
- items: [
129
- {
130
- id: '1',
131
- type: 'text',
132
- text: `A contact with the phone number ${phoneNumber} could not be found in your ${platform} account.`
133
- }
134
- ]
135
- }],
142
+ title: 'Details',
143
+ items: [
144
+ {
145
+ id: '1',
146
+ type: 'text',
147
+ text: `A contact with the phone number ${phoneNumber} could not be found in your ${platform} account.`
148
+ }
149
+ ]
150
+ }],
136
151
  ttl: 5000
137
152
  },
138
153
  contact: matchedContactInfo,
139
154
  extraDataTracking
140
155
  };
141
156
  }
142
- } catch (e) {
143
- tracer?.traceError('handler.findContact:error', e, { platform, statusCode: e.response?.status });
144
- return handleApiError(e, platform, 'findContact', { userId, overridingFormat, isExtension });
145
-
157
+ }
158
+ catch (e) {
159
+ const error = /** @type {ProviderError} */ (e);
160
+ tracer?.traceError('handler.findContact:error', error, { platform, statusCode: error.response?.status });
161
+ return handleApiError(error, platform, 'findContact', { userId, overridingFormat, isExtension });
146
162
  }
147
163
  }
148
-
164
+ /**
165
+ * @param {CreateContactParams} params
166
+ * @returns {Promise<ContactHandlerResult>}
167
+ */
149
168
  async function createContact({ platform, userId, phoneNumber, newContactName, newContactType, additionalSubmission }) {
150
169
  try {
151
170
  let user = await UserModel.findOne({
@@ -178,7 +197,7 @@ async function createContact({ platform, userId, phoneNumber, newContactName, ne
178
197
  ttl: 5000
179
198
  },
180
199
  isRevokeUserSession: true
181
- }
200
+ };
182
201
  }
183
202
  authHeader = `Bearer ${user.accessToken}`;
184
203
  break;
@@ -194,11 +213,15 @@ async function createContact({ platform, userId, phoneNumber, newContactName, ne
194
213
  else {
195
214
  return { successful: false, returnMessage };
196
215
  }
197
- } catch (e) {
216
+ }
217
+ catch (e) {
198
218
  return handleApiError(e, platform, 'createContact', { userId, phoneNumber, newContactName, newContactType, additionalSubmission });
199
219
  }
200
220
  }
201
-
221
+ /**
222
+ * @param {FindContactWithNameParams} params
223
+ * @returns {Promise<ContactHandlerResult>}
224
+ */
202
225
  async function findContactWithName({ platform, userId, name }) {
203
226
  try {
204
227
  let user = await UserModel.findOne({
@@ -238,7 +261,7 @@ async function findContactWithName({ platform, userId, name }) {
238
261
  ttl: 5000
239
262
  },
240
263
  isRevokeUserSession: true
241
- }
264
+ };
242
265
  }
243
266
  authHeader = `Bearer ${user.accessToken}`;
244
267
  break;
@@ -257,12 +280,11 @@ async function findContactWithName({ platform, userId, name }) {
257
280
  successful,
258
281
  returnMessage,
259
282
  contact: matchedContactInfo,
260
- }
283
+ };
261
284
  }
262
285
  return {
263
286
  successful,
264
- returnMessage:
265
- {
287
+ returnMessage: {
266
288
  message: `No contact found with name ${name} `,
267
289
  messageType: 'warning',
268
290
  ttl: 5000
@@ -270,11 +292,11 @@ async function findContactWithName({ platform, userId, name }) {
270
292
  contact: matchedContactInfo
271
293
  };
272
294
  }
273
- } catch (e) {
295
+ }
296
+ catch (e) {
274
297
  return handleApiError(e, platform, 'findContactWithName', { userId, name });
275
298
  }
276
299
  }
277
-
278
300
  exports.findContact = findContact;
279
301
  exports.createContact = createContact;
280
302
  exports.findContactWithName = findContactWithName;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,11 +1,22 @@
1
- const { CallLogModel } = require('../models/callLogModel');
2
- const { UserModel } = require('../models/userModel');
3
- const oauth = require('../lib/oauth');
4
- const connectorRegistry = require('../connector/registry');
5
- const { Connector } = require('../models/dynamo/connectorSchema');
1
+ "use strict";
2
+ // @ts-check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const { CallLogModel: CallLogModelImport } = require('../models/callLogModel');
5
+ const { UserModel: UserModelImport } = require('../models/userModel');
6
+ const oauth = /** @type {any} */ (require('../lib/oauth'));
7
+ const connectorRegistry = /** @type {any} */ (require('../connector/registry'));
8
+ const { Connector: ConnectorImport } = require('../models/dynamo/connectorSchema');
6
9
  const { handleApiError } = require('../lib/errorHandler');
7
10
  const { buildCallLogSessionWhere } = require('../lib/callLogLookup');
8
-
11
+ const CallLogModel = /** @type {any} */ (CallLogModelImport);
12
+ const UserModel = /** @type {any} */ (UserModelImport);
13
+ const Connector = /** @type {any} */ (ConnectorImport);
14
+ /** @typedef {import('../types').UpsertCallDispositionParams} UpsertCallDispositionParams */
15
+ /** @typedef {import('../types').UpsertCallDispositionResult} UpsertCallDispositionResult */
16
+ /**
17
+ * @param {UpsertCallDispositionParams} params
18
+ * @returns {Promise<UpsertCallDispositionResult>}
19
+ */
9
20
  async function upsertCallDisposition({ platform, userId, sessionId, extensionNumber, hashedExtensionId, dispositions }) {
10
21
  try {
11
22
  const existingCallLog = await CallLogModel.findOne({
@@ -23,7 +34,7 @@ async function upsertCallDisposition({ platform, userId, sessionId, extensionNum
23
34
  messageType: 'warning',
24
35
  ttl: 3000
25
36
  }
26
- }
37
+ };
27
38
  }
28
39
  let user = await UserModel.findByPk(userId);
29
40
  if (!user) {
@@ -34,7 +45,7 @@ async function upsertCallDisposition({ platform, userId, sessionId, extensionNum
34
45
  messageType: 'warning',
35
46
  ttl: 3000
36
47
  }
37
- }
48
+ };
38
49
  }
39
50
  const proxyId = user.platformAdditionalInfo?.proxyId;
40
51
  let proxyConfig = null;
@@ -57,7 +68,7 @@ async function upsertCallDisposition({ platform, userId, sessionId, extensionNum
57
68
  ttl: 5000
58
69
  },
59
70
  isRevokeUserSession: true
60
- }
71
+ };
61
72
  }
62
73
  authHeader = `Bearer ${user.accessToken}`;
63
74
  break;
@@ -79,5 +90,4 @@ async function upsertCallDisposition({ platform, userId, sessionId, extensionNum
79
90
  return handleApiError(e, platform, 'upsertCallDisposition', { userId, sessionId, extensionNumber, hashedExtensionId, dispositions });
80
91
  }
81
92
  }
82
-
83
93
  exports.upsertCallDisposition = upsertCallDisposition;
@@ -0,0 +1 @@
1
+ export {};