@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,218 +0,0 @@
1
- const logger = require('./logger');
2
- const errorMessage = require('./generalErrorMessage');
3
-
4
- /**
5
- * Centralized error handler for API operations
6
- * Handles common error patterns (rate limits, auth errors, etc.)
7
- *
8
- * @param {Error} error - The error object
9
- * @param {string} platform - Platform name (clio, bullhorn, etc.)
10
- * @param {string} operation - Operation name (createCallLog, findContact, etc.)
11
- * @param {Object} additionalContext - Additional logging context
12
- * @returns {Object} Standardized error response
13
- */
14
- function handleApiError(error, platform, operation, additionalContext = {}) {
15
- const statusCode = error.response?.status ?? 'unknown';
16
-
17
- // Log the error with full context
18
- logger.error(`${operation} failed for platform ${platform}`, {
19
- platform,
20
- operation,
21
- statusCode,
22
- errorMessage: error.message,
23
- errorStack: error.stack,
24
- errorResponse: error.response?.data,
25
- ...additionalContext,
26
- });
27
-
28
- // Rate limit error (429)
29
- if (statusCode === 429) {
30
- return {
31
- successful: false,
32
- returnMessage: errorMessage.rateLimitErrorMessage({ platform }),
33
- extraDataTracking: {
34
- statusCode,
35
- },
36
- };
37
- }
38
-
39
- // Authorization/Authentication errors (400-409)
40
- if (statusCode >= 400 && statusCode < 410) {
41
- return {
42
- successful: false,
43
- returnMessage: errorMessage.authorizationErrorMessage({ platform }),
44
- extraDataTracking: {
45
- statusCode,
46
- },
47
- };
48
- }
49
-
50
- // Get operation-specific error message
51
- const defaultErrorMessage = getOperationErrorMessage(operation, platform);
52
-
53
- return {
54
- successful: false,
55
- returnMessage: defaultErrorMessage,
56
- extraDataTracking: {
57
- statusCode,
58
- },
59
- };
60
- }
61
-
62
- /**
63
- * Get operation-specific error message
64
- * @param {string} operation - Operation name
65
- * @param {string} platform - Platform name
66
- * @returns {Object} Error message object
67
- */
68
- function getOperationErrorMessage(operation, platform) {
69
- const operationMessages = {
70
- createCallLog: {
71
- message: 'Error creating call log',
72
- details: ['Please check if your account has permission to CREATE logs.'],
73
- },
74
- updateCallLog: {
75
- message: 'Error updating call log',
76
- details: [`Please check if the log entity still exists on ${platform} and your account has permission to EDIT logs.`],
77
- },
78
- getCallLog: {
79
- message: 'Error getting call log',
80
- details: ['Please check if your account has permission to READ logs.'],
81
- },
82
- createMessageLog: {
83
- message: 'Error creating message log',
84
- details: ['Please check if your account has permission to CREATE logs.'],
85
- },
86
- updateMessageLog: {
87
- message: 'Error updating message log',
88
- details: [`Please check if the log entity still exists on ${platform} and your account has permission to EDIT logs.`],
89
- },
90
- findContact: {
91
- message: 'Error finding contact',
92
- details: ['Please check if your account has permission to GET contacts.'],
93
- },
94
- createContact: {
95
- message: 'Error creating contact',
96
- details: ['Please check if your account has permission to CREATE contacts.'],
97
- },
98
- findContactWithName: {
99
- message: 'Error searching contacts',
100
- details: ['Please check if your account has permission to GET contacts.'],
101
- },
102
- createAppointment: {
103
- message: 'Error creating appointment',
104
- details: ['Please check if your account has permission to CREATE appointments. or All attendees have email address.'],
105
- },
106
- updateAppointment: {
107
- message: 'Error updating appointment',
108
- details: [`Please check if the appointment entity still exists on ${platform} and your account has permission to EDIT appointments. or All attendees have email address.`],
109
- },
110
- getAppointment: {
111
- message: 'Error getting appointment',
112
- details: ['Please check if your account has permission to GET appointments.'],
113
- },
114
- };
115
-
116
- const operationInfo = operationMessages[operation] || {
117
- message: `Error performing ${operation}`,
118
- details: ['Please check if your account has the necessary permissions.'],
119
- };
120
-
121
- return {
122
- message: operationInfo.message,
123
- messageType: 'warning',
124
- details: [
125
- {
126
- title: 'Details',
127
- items: operationInfo.details.map((detail, index) => ({
128
- id: index + 1,
129
- type: 'text',
130
- text: detail,
131
- })),
132
- },
133
- ],
134
- ttl: 5000,
135
- };
136
- }
137
-
138
- /**
139
- * Handle database errors
140
- * @param {Error} error - The error object
141
- * @param {string} operation - Database operation name
142
- * @param {Object} context - Additional context
143
- */
144
- function handleDatabaseError(error, operation, context = {}) {
145
- logger.error(`Database operation failed: ${operation}`, {
146
- operation,
147
- errorMessage: error.message,
148
- errorStack: error.stack,
149
- ...context,
150
- });
151
-
152
- return {
153
- successful: false,
154
- returnMessage: {
155
- message: 'Database operation failed',
156
- messageType: 'warning',
157
- ttl: 5000,
158
- },
159
- };
160
- }
161
-
162
- /**
163
- * Wrap async route handlers to catch errors
164
- * Prevents unhandled promise rejections
165
- * @param {Function} fn - Async route handler
166
- * @returns {Function} Wrapped handler
167
- */
168
- function asyncHandler(fn) {
169
- return (req, res, next) => {
170
- Promise.resolve(fn(req, res, next)).catch(next);
171
- };
172
- }
173
-
174
- /**
175
- * Express error handling middleware
176
- * Should be added after all routes
177
- * @param {Error} err - Error object
178
- * @param {Object} req - Express request
179
- * @param {Object} res - Express response
180
- * @param {Function} next - Express next function (required by Express signature)
181
- */
182
- function errorMiddleware(err, req, res, next) { // eslint-disable-line no-unused-vars
183
- const platform = req.platform || req.query?.platform || 'unknown';
184
- const operation = req.route?.path || 'unknown';
185
-
186
- logger.error('Request failed', {
187
- platform,
188
- operation,
189
- method: req.method,
190
- path: req.path,
191
- statusCode: err.statusCode || 500,
192
- error: err,
193
- correlationId: req.correlationId,
194
- });
195
-
196
- // Don't expose internal errors in production
197
- const message = process.env.NODE_ENV === 'production'
198
- ? 'An internal error occurred'
199
- : err.message;
200
-
201
- res.status(err.statusCode || 500).json({
202
- successful: false,
203
- returnMessage: {
204
- message,
205
- messageType: 'error',
206
- ttl: 5000,
207
- },
208
- });
209
- }
210
-
211
- module.exports = {
212
- handleApiError,
213
- handleDatabaseError,
214
- asyncHandler,
215
- errorMiddleware,
216
- getOperationErrorMessage,
217
- };
218
-
package/lib/jwt.js DELETED
@@ -1,18 +0,0 @@
1
- const { sign, verify } = require('jsonwebtoken');
2
- const logger = require('./logger');
3
-
4
- function generateJwt(data) {
5
- return sign(data, process.env.APP_SERVER_SECRET_KEY, { expiresIn: '2w' })
6
- }
7
-
8
- function decodeJwt(token) {
9
- try {
10
- return verify(token, process.env.APP_SERVER_SECRET_KEY);
11
- } catch (e) {
12
- logger.error('Error decoding JWT', { stack: e.stack });
13
- return null;
14
- }
15
- }
16
-
17
- exports.generateJwt = generateJwt;
18
- exports.decodeJwt = decodeJwt;
package/lib/logger.js DELETED
@@ -1,190 +0,0 @@
1
- const util = require('util');
2
-
3
- /**
4
- * Logger levels
5
- */
6
- const LOG_LEVELS = {
7
- ERROR: 0,
8
- WARN: 1,
9
- INFO: 2,
10
- DEBUG: 3,
11
- };
12
-
13
- /**
14
- * Color codes for terminal output
15
- */
16
- const COLORS = {
17
- ERROR: '\x1b[31m', // Red
18
- WARN: '\x1b[33m', // Yellow
19
- INFO: '\x1b[36m', // Cyan
20
- DEBUG: '\x1b[90m', // Gray
21
- RESET: '\x1b[0m',
22
- };
23
-
24
- class Logger {
25
- constructor(options = {}) {
26
- this.level = this._getLogLevel(options.level || process.env.LOG_LEVEL || 'INFO');
27
- this.isProd = process.env.NODE_ENV === 'production';
28
- this.enableColors = !this.isProd && process.stdout.isTTY;
29
- }
30
-
31
- _getLogLevel(levelName) {
32
- const upperLevel = levelName.toUpperCase();
33
- return LOG_LEVELS[upperLevel] !== undefined ? LOG_LEVELS[upperLevel] : LOG_LEVELS.INFO;
34
- }
35
-
36
- _shouldLog(level) {
37
- return LOG_LEVELS[level] <= this.level;
38
- }
39
-
40
- _formatMessage(level, message, context = {}) {
41
- const timestamp = new Date().toISOString();
42
-
43
- if (this.isProd) {
44
- // Production: JSON format for log aggregation tools
45
- return JSON.stringify({
46
- timestamp,
47
- level,
48
- message,
49
- ...context,
50
- });
51
- } else {
52
- // Development: Human-readable format with colors
53
- const color = this.enableColors ? COLORS[level] : '';
54
- const reset = this.enableColors ? COLORS.RESET : '';
55
- const contextStr = Object.keys(context).length > 0
56
- ? '\n' + util.inspect(context, { depth: 4, colors: this.enableColors })
57
- : '';
58
-
59
- return `${color}[${timestamp}] [${level}]${reset} ${message}${contextStr}`;
60
- }
61
- }
62
-
63
- _log(level, message, context = {}) {
64
- if (!this._shouldLog(level)) {
65
- return;
66
- }
67
-
68
- const formattedMessage = this._formatMessage(level, message, context);
69
-
70
- if (level === 'ERROR' || level === 'WARN') {
71
- console.error(formattedMessage);
72
- } else {
73
- console.log(formattedMessage);
74
- }
75
- }
76
-
77
- /**
78
- * Log error level messages
79
- * @param {string} message - Log message
80
- * @param {Object} context - Additional context (error, stack, platform, etc.)
81
- */
82
- error(message, context = {}) {
83
- // If context has an error object, extract useful information
84
- let enrichedContext = context;
85
- if (context.error instanceof Error) {
86
- const { error, ...rest } = context;
87
- enrichedContext = {
88
- ...rest,
89
- errorMessage: error.message,
90
- errorStack: error.stack,
91
- errorResponse: error.response?.data,
92
- errorStatus: error.response?.status,
93
- };
94
- }
95
-
96
- this._log('ERROR', message, enrichedContext);
97
- }
98
-
99
- /**
100
- * Log warning level messages
101
- * @param {string} message - Log message
102
- * @param {Object} context - Additional context
103
- */
104
- warn(message, context = {}) {
105
- this._log('WARN', message, context);
106
- }
107
-
108
- /**
109
- * Log info level messages
110
- * @param {string} message - Log message
111
- * @param {Object} context - Additional context
112
- */
113
- info(message, context = {}) {
114
- this._log('INFO', message, context);
115
- }
116
-
117
- /**
118
- * Log debug level messages
119
- * @param {string} message - Log message
120
- * @param {Object} context - Additional context
121
- */
122
- debug(message, context = {}) {
123
- this._log('DEBUG', message, context);
124
- }
125
-
126
- /**
127
- * Create a child logger with default context
128
- * Useful for adding request-specific or module-specific context
129
- * @param {Object} defaultContext - Context to include in all logs
130
- * @returns {Object} Child logger with bound context
131
- */
132
- child(defaultContext = {}) {
133
- return {
134
- error: (message, context = {}) => this.error(message, { ...defaultContext, ...context }),
135
- warn: (message, context = {}) => this.warn(message, { ...defaultContext, ...context }),
136
- info: (message, context = {}) => this.info(message, { ...defaultContext, ...context }),
137
- debug: (message, context = {}) => this.debug(message, { ...defaultContext, ...context }),
138
- child: (additionalContext) => this.child({ ...defaultContext, ...additionalContext }),
139
- };
140
- }
141
-
142
- /**
143
- * Log API request/response for debugging
144
- * @param {Object} options - Request details
145
- */
146
- logApiRequest({ method, url, status, duration, platform, error }) {
147
- const context = {
148
- method,
149
- url,
150
- status,
151
- duration: duration ? `${duration}ms` : undefined,
152
- platform,
153
- };
154
-
155
- if (error) {
156
- this.error('API request failed', { ...context, error });
157
- } else if (status >= 400) {
158
- this.warn('API request returned error status', context);
159
- } else {
160
- this.debug('API request completed', context);
161
- }
162
- }
163
-
164
- /**
165
- * Log database query for debugging
166
- * @param {Object} options - Query details
167
- */
168
- logDatabaseQuery({ operation, table, duration, error }) {
169
- const context = {
170
- operation,
171
- table,
172
- duration: duration ? `${duration}ms` : undefined,
173
- };
174
-
175
- if (error) {
176
- this.error('Database query failed', { ...context, error });
177
- } else {
178
- this.debug('Database query completed', context);
179
- }
180
- }
181
- }
182
-
183
- // Create singleton instance
184
- const logger = new Logger();
185
-
186
- // Export both the class and instance
187
- module.exports = logger;
188
- module.exports.Logger = Logger;
189
- module.exports.LOG_LEVELS = LOG_LEVELS;
190
-
@@ -1,237 +0,0 @@
1
- const Sequelize = require('sequelize');
2
-
3
- const CALL_LOGS_TABLE = 'callLogs';
4
- const HASHED_EXTENSION_ID_COLUMN = 'hashedExtensionId';
5
- const CALL_LOG_IDENTITY_PK_COLUMNS = ['id', 'sessionId', 'extensionNumber', HASHED_EXTENSION_ID_COLUMN];
6
-
7
- function findColumnKey(tableDescription, name) {
8
- const lower = name.toLowerCase();
9
- return Object.keys(tableDescription).find((k) => k.toLowerCase() === lower);
10
- }
11
-
12
- async function fetchCallLogsCreateSqlSqlite(sequelize, options = {}) {
13
- const rows = await sequelize.query(
14
- "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'callLogs'",
15
- { type: Sequelize.QueryTypes.SELECT, ...options },
16
- );
17
- return rows[0]?.sql ?? null;
18
- }
19
-
20
- function callLogsCreateSqlClaimsPkColumns(createSql, columns) {
21
- if (!createSql || typeof createSql !== 'string') {
22
- return false;
23
- }
24
- const pkRegex = /PRIMARY\s+KEY\s*\(([^)]+)\)/gi;
25
- let m;
26
- while ((m = pkRegex.exec(createSql)) !== null) {
27
- const pkColumns = m[1]
28
- .split(',')
29
- .map((column) => column.replace(/["'`\[\]\s]/g, '').toLowerCase());
30
- if (columns.every((column) => pkColumns.includes(column.toLowerCase()))) {
31
- return true;
32
- }
33
- }
34
- return false;
35
- }
36
-
37
- function callLogsCreateSqlClaimsExtensionPk(createSql) {
38
- return callLogsCreateSqlClaimsPkColumns(createSql, ['extensionNumber']);
39
- }
40
-
41
- async function sqliteCallLogsPkIncludesExtension(sequelize, options = {}) {
42
- const sql = await fetchCallLogsCreateSqlSqlite(sequelize, options);
43
- return callLogsCreateSqlClaimsExtensionPk(sql);
44
- }
45
-
46
- async function sqliteCallLogsPkIncludesHashedExtension(sequelize, options = {}) {
47
- const sql = await fetchCallLogsCreateSqlSqlite(sequelize, options);
48
- return callLogsCreateSqlClaimsPkColumns(sql, CALL_LOG_IDENTITY_PK_COLUMNS);
49
- }
50
-
51
- async function describeCallLogsTable(sequelize, options = {}) {
52
- return sequelize.getQueryInterface().describeTable(CALL_LOGS_TABLE, options);
53
- }
54
-
55
- /**
56
- * SQLite cannot change composite PK via Sequelize addConstraint (it appends a second PRIMARY KEY).
57
- * Rebuild the table with the current call-log identity primary key and copy rows.
58
- */
59
- async function migrateCallLogsIdentitySqlite(sequelize, transaction) {
60
- const qg = sequelize.getQueryInterface().queryGenerator;
61
- const qi = sequelize.getQueryInterface();
62
- const q = (id) => qg.quoteIdentifier(id);
63
- const tmpName = `callLogs_mig_legacy_${Date.now()}`;
64
- const mainTableSql = qg.quoteTable({ tableName: CALL_LOGS_TABLE });
65
- const tmpTableSql = qg.quoteTable({ tableName: tmpName });
66
-
67
- await sequelize.query(
68
- `ALTER TABLE ${mainTableSql} RENAME TO ${qg.quoteIdentifier(tmpName)};`,
69
- { transaction },
70
- );
71
-
72
- await sequelize.query(
73
- `
74
- CREATE TABLE ${mainTableSql} (
75
- ${q('id')} VARCHAR(255) NOT NULL,
76
- ${q('sessionId')} VARCHAR(255) NOT NULL,
77
- ${q('extensionNumber')} VARCHAR(255) NOT NULL DEFAULT '',
78
- ${q(HASHED_EXTENSION_ID_COLUMN)} VARCHAR(255) NOT NULL DEFAULT '',
79
- ${q('platform')} VARCHAR(255),
80
- ${q('thirdPartyLogId')} VARCHAR(255),
81
- ${q('userId')} VARCHAR(255),
82
- ${q('contactId')} VARCHAR(255),
83
- ${q('createdAt')} DATETIME NOT NULL,
84
- ${q('updatedAt')} DATETIME NOT NULL,
85
- PRIMARY KEY (${CALL_LOG_IDENTITY_PK_COLUMNS.map(q).join(', ')})
86
- );
87
- `,
88
- { transaction },
89
- );
90
-
91
- const oldDesc = await qi.describeTable(tmpName, { transaction });
92
-
93
- const targetCols = [
94
- 'id',
95
- 'sessionId',
96
- 'extensionNumber',
97
- HASHED_EXTENSION_ID_COLUMN,
98
- 'platform',
99
- 'thirdPartyLogId',
100
- 'userId',
101
- 'contactId',
102
- 'createdAt',
103
- 'updatedAt',
104
- ];
105
-
106
- const missingRequired = targetCols.filter(
107
- (c) => findColumnKey(oldDesc, c) == null && c !== 'extensionNumber' && c !== HASHED_EXTENSION_ID_COLUMN,
108
- );
109
- if (missingRequired.length) {
110
- throw new Error(
111
- `unexpected callLogs schema before migration (missing columns: ${missingRequired.join(', ')})`,
112
- );
113
- }
114
-
115
- const insertCols = targetCols.map(q).join(', ');
116
- const selectExprs = targetCols
117
- .map((col) => {
118
- const key = findColumnKey(oldDesc, col);
119
- if (key != null) {
120
- return q(key);
121
- }
122
- return `CAST('' AS VARCHAR(255))`;
123
- })
124
- .join(', ');
125
-
126
- await sequelize.query(
127
- `INSERT INTO ${mainTableSql} (${insertCols}) SELECT ${selectExprs} FROM ${tmpTableSql};`,
128
- { transaction },
129
- );
130
-
131
- await sequelize.query(`DROP TABLE ${tmpTableSql};`, { transaction });
132
- }
133
-
134
- async function migrateCallLogsExtensionNumberSqlite(sequelize, transaction) {
135
- return migrateCallLogsIdentitySqlite(sequelize, transaction);
136
- }
137
-
138
- async function getPostgresPrimaryKeyConstraint(sequelize, options = {}) {
139
- const constraints = await sequelize.query(
140
- `
141
- SELECT tc.constraint_name AS "constraintName"
142
- FROM information_schema.table_constraints tc
143
- WHERE tc.table_name = :tableName
144
- AND tc.constraint_type = 'PRIMARY KEY'
145
- LIMIT 1
146
- `,
147
- {
148
- type: Sequelize.QueryTypes.SELECT,
149
- replacements: { tableName: CALL_LOGS_TABLE },
150
- ...options,
151
- },
152
- );
153
- return constraints[0]?.constraintName ?? null;
154
- }
155
-
156
- async function postgresCallLogsPkIncludesHashedExtension(sequelize, options = {}) {
157
- const pkConstraintName = await getPostgresPrimaryKeyConstraint(sequelize, options);
158
- if (!pkConstraintName) {
159
- return false;
160
- }
161
- const rows = await sequelize.query(
162
- `
163
- SELECT kcu.column_name AS "columnName"
164
- FROM information_schema.key_column_usage kcu
165
- WHERE kcu.table_name = :tableName
166
- AND kcu.constraint_name = :constraintName
167
- ORDER BY kcu.ordinal_position
168
- `,
169
- {
170
- type: Sequelize.QueryTypes.SELECT,
171
- replacements: { tableName: CALL_LOGS_TABLE, constraintName: pkConstraintName },
172
- ...options,
173
- },
174
- );
175
- const pkColumns = rows.map((row) => row.columnName.toLowerCase());
176
- return CALL_LOG_IDENTITY_PK_COLUMNS.every((column) => pkColumns.includes(column.toLowerCase()));
177
- }
178
-
179
- async function migrateCallLogsIdentityPostgres(sequelize, transaction) {
180
- const qi = sequelize.getQueryInterface();
181
- const qg = qi.queryGenerator;
182
- const table = qg.quoteTable({ tableName: CALL_LOGS_TABLE });
183
- const pkConstraintName = await getPostgresPrimaryKeyConstraint(sequelize, { transaction });
184
- if (pkConstraintName) {
185
- await sequelize.query(
186
- `ALTER TABLE ${table} DROP CONSTRAINT ${qg.quoteIdentifier(pkConstraintName)};`,
187
- { transaction },
188
- );
189
- }
190
- await sequelize.query(
191
- `ALTER TABLE ${table} ADD PRIMARY KEY (${CALL_LOG_IDENTITY_PK_COLUMNS.map((column) => qg.quoteIdentifier(column)).join(', ')});`,
192
- { transaction },
193
- );
194
- }
195
-
196
- async function ensureCallLogsHashedExtensionIdSchema(sequelize) {
197
- const qi = sequelize.getQueryInterface();
198
- const dialect = sequelize.getDialect();
199
- let desc = await describeCallLogsTable(sequelize);
200
-
201
- if (findColumnKey(desc, HASHED_EXTENSION_ID_COLUMN) == null) {
202
- await qi.addColumn(CALL_LOGS_TABLE, HASHED_EXTENSION_ID_COLUMN, {
203
- type: Sequelize.STRING,
204
- allowNull: false,
205
- defaultValue: '',
206
- });
207
- desc = await describeCallLogsTable(sequelize);
208
- }
209
-
210
- if (dialect === 'sqlite') {
211
- const hasIdentityPk = await sqliteCallLogsPkIncludesHashedExtension(sequelize);
212
- if (!hasIdentityPk) {
213
- await sequelize.transaction(async (transaction) => {
214
- await migrateCallLogsIdentitySqlite(sequelize, transaction);
215
- });
216
- }
217
- return;
218
- }
219
-
220
- if (dialect === 'postgres') {
221
- const hasIdentityPk = await postgresCallLogsPkIncludesHashedExtension(sequelize);
222
- if (!hasIdentityPk) {
223
- await sequelize.transaction(async (transaction) => {
224
- await migrateCallLogsIdentityPostgres(sequelize, transaction);
225
- });
226
- }
227
- }
228
- }
229
-
230
- module.exports = {
231
- findColumnKey,
232
- migrateCallLogsExtensionNumberSqlite,
233
- migrateCallLogsIdentitySqlite,
234
- sqliteCallLogsPkIncludesExtension,
235
- sqliteCallLogsPkIncludesHashedExtension,
236
- ensureCallLogsHashedExtensionIdSchema,
237
- };