tango-app-api-audio-analytics 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +41 -0
- package/API_EXAMPLES.md +310 -0
- package/COHORT_API.md +513 -0
- package/COHORT_API_EXAMPLES.sh +235 -0
- package/COHORT_API_IMPLEMENTATION.md +296 -0
- package/COHORT_API_QUICKSTART.md +387 -0
- package/index.js +6 -0
- package/package.json +36 -0
- package/src/controllers/audioAnalytics.controller.js +116 -0
- package/src/controllers/cohort.controller.js +357 -0
- package/src/controllers/cohortAnalytics.controller.js +46 -0
- package/src/controllers/conversationAnalytics.controller.js +92 -0
- package/src/dtos/audioAnalytics.dtos.js +537 -0
- package/src/middlewares/validation.middleware.js +624 -0
- package/src/routes/audioAnalytics.routes.js +18 -0
- package/src/services/cohort.service.js +332 -0
- package/src/validations/cohort.validation.js +113 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort Controller
|
|
3
|
+
* Handles cohort creation and management endpoints
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
createCohort as createCohortService,
|
|
8
|
+
getCohortById,
|
|
9
|
+
getCohortsByClientId,
|
|
10
|
+
updateCohort as updateCohortService,
|
|
11
|
+
deleteCohort as deleteCohortService,
|
|
12
|
+
searchCohorts,
|
|
13
|
+
getCohortAnalytics,
|
|
14
|
+
cohortExists,
|
|
15
|
+
} from '../services/cohort.service.js';
|
|
16
|
+
import {
|
|
17
|
+
cohortCreationSchema,
|
|
18
|
+
cohortUpdateSchema,
|
|
19
|
+
cohortQuerySchema,
|
|
20
|
+
validateCohortData,
|
|
21
|
+
} from '../validations/cohort.validation.js';
|
|
22
|
+
import { logger } from 'tango-app-api-middleware';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create new cohort
|
|
26
|
+
* POST /cohorts
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} req - Express request object
|
|
29
|
+
* @param {Object} res - Express response object
|
|
30
|
+
*/
|
|
31
|
+
export const createCohort = async ( req, res ) => {
|
|
32
|
+
try {
|
|
33
|
+
logger.info( 'Creating new cohort' );
|
|
34
|
+
|
|
35
|
+
const { error, value: validatedData } = await validateCohortData(
|
|
36
|
+
req.body,
|
|
37
|
+
cohortCreationSchema,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if ( error ) {
|
|
41
|
+
logger.warn( 'Cohort validation failed', error );
|
|
42
|
+
return res.status( 400 ).json( {
|
|
43
|
+
status: 'error',
|
|
44
|
+
message: error.message,
|
|
45
|
+
code: 'VALIDATION_ERROR',
|
|
46
|
+
details: error.details,
|
|
47
|
+
timestamp: new Date().toISOString(),
|
|
48
|
+
} );
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Check if cohort already exists
|
|
52
|
+
const exists = await cohortExists( validatedData.cohortId );
|
|
53
|
+
if ( exists ) {
|
|
54
|
+
logger.warn( `Cohort already exists: ${validatedData.cohortId}` );
|
|
55
|
+
return res.status( 409 ).json( {
|
|
56
|
+
status: 'error',
|
|
57
|
+
message: 'Cohort with this ID already exists',
|
|
58
|
+
code: 'COHORT_EXISTS',
|
|
59
|
+
timestamp: new Date().toISOString(),
|
|
60
|
+
} );
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Create cohort in OpenSearch
|
|
64
|
+
const result = await createCohortService( validatedData );
|
|
65
|
+
|
|
66
|
+
logger.info( 'Cohort created successfully', {
|
|
67
|
+
cohortId: validatedData.cohortId,
|
|
68
|
+
documentId: result.data.documentId,
|
|
69
|
+
} );
|
|
70
|
+
|
|
71
|
+
res.status( 201 ).json( {
|
|
72
|
+
status: 'success',
|
|
73
|
+
message: result.message,
|
|
74
|
+
data: {
|
|
75
|
+
cohortId: result.data.cohortId,
|
|
76
|
+
cohortName: result.data.cohortName,
|
|
77
|
+
clientId: result.data.clientId,
|
|
78
|
+
documentId: result.data.documentId,
|
|
79
|
+
createdAt: result.data.createdAt,
|
|
80
|
+
metricsCount: result.data.metrics.length,
|
|
81
|
+
},
|
|
82
|
+
timestamp: new Date().toISOString(),
|
|
83
|
+
} );
|
|
84
|
+
} catch ( error ) {
|
|
85
|
+
logger.error( `Error creating cohort: ${error.message}`, error );
|
|
86
|
+
|
|
87
|
+
if ( error.code === 'COHORT_CREATE_ERROR' ) {
|
|
88
|
+
return res.status( 500 ).json( {
|
|
89
|
+
status: 'error',
|
|
90
|
+
message: error.message,
|
|
91
|
+
code: error.code,
|
|
92
|
+
timestamp: new Date().toISOString(),
|
|
93
|
+
} );
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
res.status( 500 ).json( {
|
|
97
|
+
status: 'error',
|
|
98
|
+
message: 'Internal server error',
|
|
99
|
+
code: 'INTERNAL_ERROR',
|
|
100
|
+
timestamp: new Date().toISOString(),
|
|
101
|
+
} );
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get cohort by ID
|
|
107
|
+
* GET /cohorts/:cohortId
|
|
108
|
+
*
|
|
109
|
+
* @param {Object} req - Express request object
|
|
110
|
+
* @param {Object} res - Express response object
|
|
111
|
+
*/
|
|
112
|
+
export const getCohort = async ( req, res ) => {
|
|
113
|
+
try {
|
|
114
|
+
const { cohortId } = req.params;
|
|
115
|
+
|
|
116
|
+
logger.info( `Fetching cohort: ${cohortId}` );
|
|
117
|
+
|
|
118
|
+
const cohort = await getCohortById( cohortId );
|
|
119
|
+
|
|
120
|
+
res.status( 200 ).json( {
|
|
121
|
+
status: 'success',
|
|
122
|
+
data: cohort,
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
} );
|
|
125
|
+
} catch ( error ) {
|
|
126
|
+
logger.error( `Error fetching cohort: ${error.message}`, error );
|
|
127
|
+
|
|
128
|
+
if ( error.message.includes( 'not found' ) ) {
|
|
129
|
+
return res.status( 404 ).json( {
|
|
130
|
+
status: 'error',
|
|
131
|
+
message: 'Cohort not found',
|
|
132
|
+
code: 'COHORT_NOT_FOUND',
|
|
133
|
+
timestamp: new Date().toISOString(),
|
|
134
|
+
} );
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
res.status( 500 ).json( {
|
|
138
|
+
status: 'error',
|
|
139
|
+
message: 'Internal server error',
|
|
140
|
+
code: 'INTERNAL_ERROR',
|
|
141
|
+
timestamp: new Date().toISOString(),
|
|
142
|
+
} );
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get cohorts by client ID
|
|
148
|
+
* GET /cohorts/client/:clientId
|
|
149
|
+
*
|
|
150
|
+
* @param {Object} req - Express request object
|
|
151
|
+
* @param {Object} res - Express response object
|
|
152
|
+
*/
|
|
153
|
+
export const getCohortsByClient = async ( req, res ) => {
|
|
154
|
+
try {
|
|
155
|
+
const { clientId } = req.params;
|
|
156
|
+
const { limit = 10, offset = 0 } = req.query;
|
|
157
|
+
|
|
158
|
+
logger.info( `Fetching cohorts for client: ${clientId}` );
|
|
159
|
+
|
|
160
|
+
const result = await getCohortsByClientId(
|
|
161
|
+
clientId,
|
|
162
|
+
parseInt( limit ),
|
|
163
|
+
parseInt( offset ),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
res.status( 200 ).json( {
|
|
167
|
+
status: 'success',
|
|
168
|
+
data: result.cohorts,
|
|
169
|
+
pagination: result.pagination,
|
|
170
|
+
timestamp: new Date().toISOString(),
|
|
171
|
+
} );
|
|
172
|
+
} catch ( error ) {
|
|
173
|
+
logger.error( `Error fetching cohorts: ${error.message}`, error );
|
|
174
|
+
|
|
175
|
+
res.status( 500 ).json( {
|
|
176
|
+
status: 'error',
|
|
177
|
+
message: 'Internal server error',
|
|
178
|
+
code: 'INTERNAL_ERROR',
|
|
179
|
+
timestamp: new Date().toISOString(),
|
|
180
|
+
} );
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Search cohorts
|
|
186
|
+
* POST /cohorts/search
|
|
187
|
+
*
|
|
188
|
+
* @param {Object} req - Express request object
|
|
189
|
+
* @param {Object} res - Express response object
|
|
190
|
+
*/
|
|
191
|
+
export const searchCohortsEndpoint = async ( req, res ) => {
|
|
192
|
+
try {
|
|
193
|
+
const { error, value: validatedData } = await validateCohortData(
|
|
194
|
+
req.body,
|
|
195
|
+
cohortQuerySchema,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if ( error ) {
|
|
199
|
+
return res.status( 400 ).json( {
|
|
200
|
+
status: 'error',
|
|
201
|
+
message: error.message,
|
|
202
|
+
code: 'VALIDATION_ERROR',
|
|
203
|
+
details: error.details,
|
|
204
|
+
timestamp: new Date().toISOString(),
|
|
205
|
+
} );
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
logger.info( 'Searching cohorts' );
|
|
209
|
+
|
|
210
|
+
const result = await searchCohorts(
|
|
211
|
+
{
|
|
212
|
+
clientId: validatedData.clientId,
|
|
213
|
+
cohortId: validatedData.cohortId,
|
|
214
|
+
cohortName: validatedData.cohortName,
|
|
215
|
+
},
|
|
216
|
+
validatedData.limit,
|
|
217
|
+
validatedData.offset,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
res.status( 200 ).json( {
|
|
221
|
+
status: 'success',
|
|
222
|
+
data: result.cohorts,
|
|
223
|
+
pagination: result.pagination,
|
|
224
|
+
timestamp: new Date().toISOString(),
|
|
225
|
+
} );
|
|
226
|
+
} catch ( error ) {
|
|
227
|
+
logger.error( `Error searching cohorts: ${error.message}`, error );
|
|
228
|
+
|
|
229
|
+
res.status( 500 ).json( {
|
|
230
|
+
status: 'error',
|
|
231
|
+
message: 'Internal server error',
|
|
232
|
+
code: 'INTERNAL_ERROR',
|
|
233
|
+
timestamp: new Date().toISOString(),
|
|
234
|
+
} );
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Update cohort
|
|
240
|
+
* PUT /cohorts/:documentId
|
|
241
|
+
*
|
|
242
|
+
* @param {Object} req - Express request object
|
|
243
|
+
* @param {Object} res - Express response object
|
|
244
|
+
*/
|
|
245
|
+
export const updateCohort = async ( req, res ) => {
|
|
246
|
+
try {
|
|
247
|
+
const { documentId } = req.params;
|
|
248
|
+
|
|
249
|
+
const { error, value: validatedData } = await validateCohortData(
|
|
250
|
+
req.body,
|
|
251
|
+
cohortUpdateSchema,
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
if ( error ) {
|
|
255
|
+
return res.status( 400 ).json( {
|
|
256
|
+
status: 'error',
|
|
257
|
+
message: error.message,
|
|
258
|
+
code: 'VALIDATION_ERROR',
|
|
259
|
+
details: error.details,
|
|
260
|
+
timestamp: new Date().toISOString(),
|
|
261
|
+
} );
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
logger.info( `Updating cohort: ${documentId}` );
|
|
265
|
+
|
|
266
|
+
const result = await updateCohortService( documentId, validatedData );
|
|
267
|
+
|
|
268
|
+
res.status( 200 ).json( {
|
|
269
|
+
status: 'success',
|
|
270
|
+
message: result.message,
|
|
271
|
+
data: result.data,
|
|
272
|
+
timestamp: new Date().toISOString(),
|
|
273
|
+
} );
|
|
274
|
+
} catch ( error ) {
|
|
275
|
+
logger.error( `Error updating cohort: ${error.message}`, error );
|
|
276
|
+
|
|
277
|
+
res.status( 500 ).json( {
|
|
278
|
+
status: 'error',
|
|
279
|
+
message: 'Internal server error',
|
|
280
|
+
code: 'INTERNAL_ERROR',
|
|
281
|
+
timestamp: new Date().toISOString(),
|
|
282
|
+
} );
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Delete cohort
|
|
288
|
+
* DELETE /cohorts/:documentId
|
|
289
|
+
*
|
|
290
|
+
* @param {Object} req - Express request object
|
|
291
|
+
* @param {Object} res - Express response object
|
|
292
|
+
*/
|
|
293
|
+
export const deleteCohort = async ( req, res ) => {
|
|
294
|
+
try {
|
|
295
|
+
const { documentId } = req.params;
|
|
296
|
+
|
|
297
|
+
logger.info( `Deleting cohort: ${documentId}` );
|
|
298
|
+
|
|
299
|
+
const result = await deleteCohortService( documentId );
|
|
300
|
+
|
|
301
|
+
res.status( 200 ).json( {
|
|
302
|
+
status: 'success',
|
|
303
|
+
message: result.message,
|
|
304
|
+
timestamp: new Date().toISOString(),
|
|
305
|
+
} );
|
|
306
|
+
} catch ( error ) {
|
|
307
|
+
logger.error( `Error deleting cohort: ${error.message}`, error );
|
|
308
|
+
|
|
309
|
+
res.status( 500 ).json( {
|
|
310
|
+
status: 'error',
|
|
311
|
+
message: 'Internal server error',
|
|
312
|
+
code: 'INTERNAL_ERROR',
|
|
313
|
+
timestamp: new Date().toISOString(),
|
|
314
|
+
} );
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Get cohort analytics
|
|
320
|
+
* GET /cohorts/:cohortId/analytics
|
|
321
|
+
*
|
|
322
|
+
* @param {Object} req - Express request object
|
|
323
|
+
* @param {Object} res - Express response object
|
|
324
|
+
*/
|
|
325
|
+
export const getCohortAnalyticsEndpoint = async ( req, res ) => {
|
|
326
|
+
try {
|
|
327
|
+
const { cohortId } = req.params;
|
|
328
|
+
|
|
329
|
+
logger.info( `Fetching analytics for cohort: ${cohortId}` );
|
|
330
|
+
|
|
331
|
+
const analytics = await getCohortAnalytics( cohortId );
|
|
332
|
+
|
|
333
|
+
res.status( 200 ).json( {
|
|
334
|
+
status: 'success',
|
|
335
|
+
data: analytics,
|
|
336
|
+
timestamp: new Date().toISOString(),
|
|
337
|
+
} );
|
|
338
|
+
} catch ( error ) {
|
|
339
|
+
logger.error( `Error fetching cohort analytics: ${error.message}`, error );
|
|
340
|
+
|
|
341
|
+
if ( error.message.includes( 'not found' ) ) {
|
|
342
|
+
return res.status( 404 ).json( {
|
|
343
|
+
status: 'error',
|
|
344
|
+
message: 'Cohort not found',
|
|
345
|
+
code: 'COHORT_NOT_FOUND',
|
|
346
|
+
timestamp: new Date().toISOString(),
|
|
347
|
+
} );
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
res.status( 500 ).json( {
|
|
351
|
+
status: 'error',
|
|
352
|
+
message: 'Internal server error',
|
|
353
|
+
code: 'INTERNAL_ERROR',
|
|
354
|
+
timestamp: new Date().toISOString(),
|
|
355
|
+
} );
|
|
356
|
+
}
|
|
357
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// import { sampleCohortData } from '../models/cohortAnalysis.model.js';
|
|
2
|
+
import { logger } from 'tango-app-api-middleware';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get Complete Cohort Analysis
|
|
6
|
+
* GET /cohort-analysis
|
|
7
|
+
* @param {Object} req - Express request object
|
|
8
|
+
* @param {Object} req.body - Request body with analysis parameters
|
|
9
|
+
* @param {string} req.body.startDate - Start date for analysis
|
|
10
|
+
* @param {string} req.body.endDate - End date for analysis
|
|
11
|
+
* @param {string} req.body.storeId - Store ID for filtering
|
|
12
|
+
* @param {Object} res - Express response object
|
|
13
|
+
* @return {void} Returns JSON response with cohort analysis data
|
|
14
|
+
*/
|
|
15
|
+
export const getCohortAnalysis = async ( req, res ) => {
|
|
16
|
+
try {
|
|
17
|
+
const { startDate, endDate, storeId } = req.body;
|
|
18
|
+
|
|
19
|
+
// Validation
|
|
20
|
+
if ( !startDate || !endDate || !storeId ) {
|
|
21
|
+
return res.status( 400 ).json( {
|
|
22
|
+
status: 'error',
|
|
23
|
+
message: 'Missing required parameters: startDate, endDate, storeId',
|
|
24
|
+
code: 'MISSING_PARAMETERS',
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
} );
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
logger.info( `Fetching cohort analysis for store ${storeId} from ${startDate} to ${endDate}` );
|
|
30
|
+
|
|
31
|
+
// Return sample data (replace with database query later)
|
|
32
|
+
return res.status( 200 ).json( {
|
|
33
|
+
status: 'success',
|
|
34
|
+
data: 'sampleCohortData',
|
|
35
|
+
timestamp: new Date().toISOString(),
|
|
36
|
+
} );
|
|
37
|
+
} catch ( error ) {
|
|
38
|
+
logger.error( `Error fetching cohort analysis: ${error.message}` );
|
|
39
|
+
return res.status( 500 ).json( {
|
|
40
|
+
status: 'error',
|
|
41
|
+
message: 'Internal server error',
|
|
42
|
+
code: 'INTERNAL_ERROR',
|
|
43
|
+
timestamp: new Date().toISOString(),
|
|
44
|
+
} );
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// import { sampleConversationData, sampleConversationsList } from '../models/conversationAnalysis.model.js';
|
|
2
|
+
import { logger } from 'tango-app-api-middleware';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get Conversation Analysis List
|
|
6
|
+
* POST /conversations/list
|
|
7
|
+
* @param {Object} req - Express request object
|
|
8
|
+
* @param {Object} req.body - Request body with query parameters
|
|
9
|
+
* @param {string} req.body.startDate - Start date for filtering
|
|
10
|
+
* @param {string} req.body.endDate - End date for filtering
|
|
11
|
+
* @param {string} req.body.storeId - Store ID for filtering
|
|
12
|
+
* @param {Object} res - Express response object
|
|
13
|
+
* @return {void} Returns JSON response with conversations list
|
|
14
|
+
*/
|
|
15
|
+
export const getConversationsList = async ( req, res ) => {
|
|
16
|
+
try {
|
|
17
|
+
const { startDate, endDate, storeId } = req.body;
|
|
18
|
+
|
|
19
|
+
// Validation
|
|
20
|
+
if ( !startDate || !endDate || !storeId ) {
|
|
21
|
+
return res.status( 400 ).json( {
|
|
22
|
+
status: 'error',
|
|
23
|
+
message: 'Missing required parameters: startDate, endDate, storeId',
|
|
24
|
+
code: 'MISSING_PARAMETERS',
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
} );
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
logger.info( `Fetching conversations for store ${storeId} from ${startDate} to ${endDate}` );
|
|
30
|
+
|
|
31
|
+
return res.status( 200 ).json( {
|
|
32
|
+
status: 'success',
|
|
33
|
+
data: {
|
|
34
|
+
totalConversations: 0,
|
|
35
|
+
conversations: 'sampleConversationsList',
|
|
36
|
+
},
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
} );
|
|
39
|
+
} catch ( error ) {
|
|
40
|
+
logger.error( `Error fetching conversations: ${error.message}` );
|
|
41
|
+
return res.status( 500 ).json( {
|
|
42
|
+
status: 'error',
|
|
43
|
+
message: 'Internal server error',
|
|
44
|
+
code: 'INTERNAL_ERROR',
|
|
45
|
+
timestamp: new Date().toISOString(),
|
|
46
|
+
} );
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get Single Conversation Details
|
|
52
|
+
* POST /conversations/:conversationId
|
|
53
|
+
* @param {Object} req - Express request object
|
|
54
|
+
* @param {Object} req.params - URL parameters
|
|
55
|
+
* @param {string} req.params.conversationId - Conversation ID from URL
|
|
56
|
+
* @param {Object} req.body - Request body with store information
|
|
57
|
+
* @param {string} req.body.storeId - Store ID for filtering
|
|
58
|
+
* @param {Object} res - Express response object
|
|
59
|
+
* @return {void} Returns JSON response with conversation details
|
|
60
|
+
*/
|
|
61
|
+
export const getConversationDetails = async ( req, res ) => {
|
|
62
|
+
try {
|
|
63
|
+
const { conversationId } = req.params;
|
|
64
|
+
const { storeId } = req.body;
|
|
65
|
+
|
|
66
|
+
if ( !conversationId || !storeId ) {
|
|
67
|
+
return res.status( 400 ).json( {
|
|
68
|
+
status: 'error',
|
|
69
|
+
message: 'Missing required parameters',
|
|
70
|
+
code: 'MISSING_PARAMETERS',
|
|
71
|
+
timestamp: new Date().toISOString(),
|
|
72
|
+
} );
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
logger.info( `Fetching conversation ${conversationId}` );
|
|
76
|
+
|
|
77
|
+
return res.status( 200 ).json( {
|
|
78
|
+
status: 'success',
|
|
79
|
+
data: 'sampleConversationData',
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
} );
|
|
82
|
+
} catch ( error ) {
|
|
83
|
+
logger.error( `Error fetching conversation: ${error.message}` );
|
|
84
|
+
return res.status( 500 ).json( {
|
|
85
|
+
status: 'error',
|
|
86
|
+
message: 'Internal server error',
|
|
87
|
+
code: 'INTERNAL_ERROR',
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
} );
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|