| 169 | |
| 170 | // Utility to create aggregated error analytics |
| 171 | export function aggregateErrorAnalytics( |
| 172 | errorDetails: ErrorDetail[], |
| 173 | buckets: any[], |
| 174 | targetLocales: string[], |
| 175 | i18nConfig: any, |
| 176 | ) { |
| 177 | if (errorDetails.length === 0) { |
| 178 | return { |
| 179 | errorCount: 0, |
| 180 | errorTypes: [], |
| 181 | errorsByBucket: {}, |
| 182 | errorsByType: {}, |
| 183 | firstError: undefined, |
| 184 | bucketCount: buckets.length, |
| 185 | localeCount: targetLocales.length, |
| 186 | i18nConfig: { |
| 187 | sourceLocale: i18nConfig.locale.source, |
| 188 | targetLocales: i18nConfig.locale.targets, |
| 189 | bucketTypes: Object.keys(i18nConfig.buckets), |
| 190 | }, |
| 191 | }; |
| 192 | } |
| 193 | |
| 194 | const errorsByBucket = errorDetails.reduce( |
| 195 | (acc, error) => { |
| 196 | if (error.bucket) { |
| 197 | acc[error.bucket] = (acc[error.bucket] || 0) + 1; |
| 198 | } |
| 199 | return acc; |
| 200 | }, |
| 201 | {} as Record<string, number>, |
| 202 | ); |
| 203 | |
| 204 | const errorsByType = errorDetails.reduce( |
| 205 | (acc, error) => { |
| 206 | acc[error.type] = (acc[error.type] || 0) + 1; |
| 207 | return acc; |
| 208 | }, |
| 209 | {} as Record<string, number>, |
| 210 | ); |
| 211 | |
| 212 | return { |
| 213 | errorCount: errorDetails.length, |
| 214 | errorTypes: [...new Set(errorDetails.map((e) => e.type))], |
| 215 | errorsByBucket, |
| 216 | errorsByType, |
| 217 | firstError: { |
| 218 | type: errorDetails[0].type, |
| 219 | bucket: errorDetails[0].bucket, |
| 220 | locale: errorDetails[0].locale, |
| 221 | pathPattern: errorDetails[0].pathPattern, |
| 222 | message: errorDetails[0].message, |
| 223 | }, |
| 224 | bucketCount: buckets.length, |
| 225 | localeCount: targetLocales.length, |
| 226 | i18nConfig: { |
| 227 | sourceLocale: i18nConfig.locale.source, |
| 228 | targetLocales: i18nConfig.locale.targets, |