@@ -343,6 +343,18 @@ const getRoomStats = (roomId: string) => {
343343 }
344344}
345345
346+ // async wrapper for regex-powered String.prototype.replace
347+ const strReplaceAsync = async ( str : string , regex : RegExp , fn : ( ...args : string [ ] ) => Promise < string > ) => {
348+ const promises : Promise < string > [ ] = [ ] ;
349+ // dry-run to calculate the replace values
350+ str . replace ( regex , ( ...args : string [ ] ) => {
351+ promises . push ( fn ( ...args ) ) ;
352+ return "" ;
353+ } ) ;
354+ const values = await Promise . all ( promises ) ;
355+ return str . replace ( regex , ( ) => values . shift ( ) ) ;
356+ } ;
357+
346358export default class CountlyAnalytics {
347359 private baseUrl : URL = null ;
348360 private appKey : string = null ;
@@ -495,7 +507,7 @@ export default class CountlyAnalytics {
495507 return this . lastMsTs ;
496508 }
497509
498- public recordError ( err : Error | string , fatal = false ) {
510+ public async recordError ( err : Error | string , fatal = false ) {
499511 if ( this . disabled || this . anonymous ) return ;
500512
501513 let error = "" ;
@@ -523,6 +535,11 @@ export default class CountlyAnalytics {
523535 error = err + "" ;
524536 }
525537
538+ // sanitize the error from identifiers
539+ error = await strReplaceAsync ( error , / ( [ ! @ + # ] ) .+ ?: [ \w : . ] + / g, async ( substring : string , glyph : string ) => {
540+ return glyph + await hashHex ( substring . substring ( 1 ) ) ;
541+ } ) ;
542+
526543 const metrics = this . getMetrics ( ) ;
527544 const ob : ICrash = {
528545 _resolution : metrics ?. _resolution ,
0 commit comments