abt-universal-search
Version:
Enterprise-grade Universal Search System with cross-platform compatibility, performance optimization, and security hardening
1 lines • 153 kB
JavaScript
"use strict";const e={dataSource:{type:"memory"},queryHandling:{minLength:3,debounceMs:300,triggerOn:"change",caseSensitive:!1,matchMode:"partial",debounceStrategy:"trailing",caseNormalization:"lowercase",xssProtection:!0,sqlInjectionProtection:!0,performanceMonitoring:!0},ui:{maxResults:10,placeholder:"Search...",loadingText:"Loading...",noResultsText:"No results found",theme:"default",rtl:!1},debug:!1,classPrefix:"universal-search"};class t extends Error{constructor(e,t){super(e),this.field=t,this.name="ValidationError"}}class i{constructor(e){this.connections=new Map,this.metrics=new Map,this.adapterType=e}get type(){return this.adapterType}async healthCheck(e){try{return"connected"===e.status}catch{return!1}}getActiveConnections(){return Array.from(this.connections.values()).filter(e=>"connected"===e.status)}getConnection(e){return this.connections.get(e)}getConnectionMetrics(e){if(e)return this.metrics.get(e)||[];const t=[];for(const e of this.metrics.values())t.push(...e);return t}createConnection(e,t={}){const i={id:e,adapterType:this.adapterType,status:"connecting",createdAt:Date.now(),lastUsedAt:Date.now(),metadata:{...t}};return this.connections.set(e,i),i}updateConnectionStatus(e,t,i){const s=this.connections.get(e);s&&(s.status=t,s.lastUsedAt=Date.now(),i&&(s.metadata={...s.metadata,...i}))}removeConnection(e){this.connections.delete(e),this.metrics.delete(e)}recordMetrics(e,t){this.metrics.has(e)||this.metrics.set(e,[]);const i=this.metrics.get(e);i.push(t),i.length>100&&i.splice(0,i.length-100)}createError(e,t,i,s,r){const n=new Error(e);switch(n.type=t,n.code=i,s&&(n.originalError=s),n.context={adapter:this.adapterType,timestamp:Date.now(),...r},t){case"connection":n.recovery={retryable:!0,suggestions:["Check network connectivity","Verify connection configuration","Ensure service is running"],fallbackOptions:["Use cached results","Try alternative adapter"]};break;case"timeout":n.recovery={retryable:!0,suggestions:["Increase timeout configuration","Optimize query complexity","Check system performance"]};break;case"validation":n.recovery={retryable:!1,suggestions:["Check configuration format","Verify required fields","Review data types"]};break;default:n.recovery={retryable:!0,suggestions:["Check logs for details","Try again later"]}}return n}async executeWithMetrics(e,t,i){const s=performance.now();let r=!1,n=0;try{const e=await t();return r=!0,Array.isArray(e)&&(n=e.length),e}finally{const t=performance.now()-s;this.recordMetrics(e,{connectionTime:0,queryTime:"query"===i?t:0,totalTime:t,success:r,resultCount:n})}}async destroy(){const e=Array.from(this.connections.values()).map(e=>this.disconnect(e).catch(()=>{}));await Promise.allSettled(e),this.connections.clear(),this.metrics.clear()}}class s extends i{constructor(e){super("memory"),this.isValidated=!1;const i=this.normalizeConfig(e);if(!i)throw new t("MemoryAdapter requires configuration");this.config={type:"memory",caseSensitive:!1,updateStrategy:"static",searchFields:[],data:[],...i},this.data=Array.isArray(this.config.data)?[...this.config.data]:"function"==typeof this.config.data?[...this.config.data()]:[];try{this.validateConfigSync(this.config),this.isValidated=!0}catch(e){throw e}}normalizeConfig(e){if(!e)return null;const t=e;return t.data&&t.searchFields?{type:"memory",data:t.data,searchFields:t.searchFields,caseSensitive:t.caseSensitive||!1,updateStrategy:"static"}:t}async connect(e){const t=e;await this.validateConfig(t);const i=`memory-${Date.now()}-${Math.random().toString(36).substring(2,11)}`,s=this.createConnection(i,{config:t});return this.updateConnectionStatus(i,"connected"),s}async query(e,t){return this.executeWithMetrics(e.id,async()=>this.search(t.normalized).map((e,i)=>({id:`memory_${i}_${Date.now()}`,data:e.item,score:e.score,matchedFields:e.matchedFields,metadata:{matchedFields:e.matchedFields,adapterType:"memory",searchQuery:t.normalized}})),"query")}async disconnect(e){this.updateConnectionStatus(e.id,"disconnected"),this.removeConnection(e.id)}async validateConfig(e){const i=e;if("memory"!==i.type)throw new t('Config type must be "memory" for MemoryAdapter');this.validateConfigSync(i)}getCapabilities(){return{supportsPooling:!1,supportsRealTime:"reactive"===this.config.updateStrategy,supportsPagination:!0,supportsSorting:!0,supportsFiltering:!0,maxConcurrentConnections:100,supportedQueryTypes:["text","partial","exact"]}}search(e){if(!this.isValidated)throw new t("Adapter configuration is invalid");if(!e||"string"!=typeof e)return[];const i=this.normalizeQuery(e);if(0===i.length)return[];const s=[];for(const e of this.data){const t=this.matchItem(e,i);t.score>0&&s.push({item:e,score:t.score,matchedFields:t.matchedFields})}return s.sort((e,t)=>t.score-e.score)}updateData(e){if(!Array.isArray(e))throw new t("Data must be an array");this.data=[...e],this.validateData()}getData(){return[...this.data]}getConfig(){return{...this.config,data:Array.isArray(this.config.data)?this.config.data:[]}}validateConfigSync(e){const i=Array.isArray(e.data)?e.data:"function"==typeof e.data?e.data():null;if(!Array.isArray(i))throw new t("Data must be an array or function returning an array","data");if(!Array.isArray(e.searchFields)||0===e.searchFields.length)throw new t("searchFields must be a non-empty array","searchFields");for(const i of e.searchFields)if("string"!=typeof i||0===i.trim().length)throw new t("All searchFields must be non-empty strings","searchFields");Array.isArray(i)&&(this.data=[...i]),this.validateData()}validateData(){if(0===this.data.length)return;const e=Math.min(3,this.data.length);for(let i=0;i<e;i++){const e=this.data[i];if(!e||"object"!=typeof e)throw new t(`Data item at index ${i} must be an object`,"data");for(const i of this.config.searchFields){const s=this.getFieldValue(e,i);if(null!=s&&"string"!=typeof s&&"number"!=typeof s)throw new t(`Field "${i}" must be string or number type in data items`,"searchFields")}}}normalizeQuery(e){const t=e.trim();return this.config.caseSensitive?t:t.toLowerCase()}matchItem(e,t){if(!e||"object"!=typeof e)return{score:0,matchedFields:[]};let i=0;const s=[];for(const r of this.config.searchFields){const n=this.getFieldValue(e,r);if(null==n)continue;const a=String(n),o=this.config.caseSensitive?a:a.toLowerCase();if(o.includes(t)){let e=1;e=o===t?10:o.startsWith(t)?5:1,i+=e,s.push(r)}}return{score:i,matchedFields:s}}getFieldValue(e,t){if(!e||"object"!=typeof e)return null;const i=t.split(".");let s=e;for(const e of i){if(!s||"object"!=typeof s||!(e in s))return null;s=s[e]}return s}}const r=[/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,/javascript:/gi,/on\w+\s*=/gi,/style\s*=/gi,/%3c/gi,/%3e/gi,/<script/gi,/<\/script>/gi,/vbscript:/gi,/data:text\/html/gi],n=[/(\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|EXEC|UNION|SCRIPT)\b)/gi,/(;|\||&|\$|\+|--|\/\*|\*\/|xp_|sp_)/gi,/(\b(OR|AND)\s+\d+\s*=\s*\d+)/gi,/(\b(OR|AND)\s+['"]\w+['"]?\s*=\s*['"]\w+['"]?)/gi,/'(\s|%20)*(or|and)(\s|%20)*'/gi,/"(\s|%20)*(or|and)(\s|%20)*"/gi,/(\bunion\s+(all\s+)?select)/gi];function a(e,t={}){if("string"!=typeof e)return"";const{xssProtection:i=!0,sqlInjectionProtection:s=!0}=t;let a=e;return i&&(a=function(e){if("string"!=typeof e)return"";let t=e;return r.forEach(e=>{t=t.replace(e,"")}),t=t.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"),t}(a)),s&&(a=function(e){if("string"!=typeof e)return"";let t=e;return n.forEach(e=>{t=t.replace(e,"")}),t=t.replace(/'/g,"''"),t}(a)),a}function o(e){return"string"==typeof e&&r.some(t=>t.test(e))}function c(e){return"string"==typeof e&&n.some(t=>t.test(e))}function l(e,t={}){const{xssProtection:i=!0,sqlInjectionProtection:s=!0}=t,r={xss:!!i&&o(e),sqlInjection:!!s&&c(e)};return{isSecure:!r.xss&&!r.sqlInjection,threats:r,sanitized:a(e,t)}}const u=new class{constructor(){this.metrics=new Map,this.currentOperation=new Map}startTracking(e,t,i){const s=performance.now(),r=this.getMemoryUsage();this.currentOperation.set(e,{startTime:s,queryLength:t,validationRulesCount:i,...void 0!==r&&{memoryBefore:r}})}endTracking(e){const t=this.currentOperation.get(e);if(!t||!t.startTime)return null;const i=performance.now(),s=i-t.startTime,r=this.getMemoryUsage(),n={startTime:t.startTime,endTime:i,duration:s,queryLength:t.queryLength||0,validationRulesCount:t.validationRulesCount||0,...void 0!==t.memoryBefore&&{memoryBefore:t.memoryBefore},...void 0!==r&&{memoryAfter:r}},a=this.metrics.get(e)||[];return a.push(n),this.metrics.set(e,a),this.currentOperation.delete(e),n}getMetrics(e){return this.metrics.get(e)||[]}getAllMetrics(e=""){const t=[];for(const[i,s]of this.metrics.entries())(""===e||i.includes(e))&&t.push(...s);return t}getAverageMetrics(e){const t=this.getMetrics(e);if(0===t.length)return null;const i=t.reduce((e,t)=>({duration:e.duration+t.duration,queryLength:e.queryLength+t.queryLength,validationRulesCount:e.validationRulesCount+t.validationRulesCount}),{duration:0,queryLength:0,validationRulesCount:0});return{duration:i.duration/t.length,queryLength:i.queryLength/t.length,validationRulesCount:i.validationRulesCount/t.length}}clearMetrics(){this.metrics.clear(),this.currentOperation.clear()}getMemoryUsage(){if("undefined"!=typeof performance&&"memory"in performance)return performance.memory.usedJSHeapSize}};class h{constructor(e){this.debounceTimer=null,this.leadingTimer=null,this.queryCounter=0,this.lastExecutionTime=0,this.config={enableSecurityValidation:!0,enableXSSProtection:!0,enableSQLInjectionProtection:!0,enablePerformanceMonitoring:!0,customValidators:[],debounceStrategy:"trailing",caseNormalization:"lowercase",enableStemming:!1,enablePreprocessing:!0,localization:{language:"en",messages:{minLength:"Please enter at least {minLength} characters",maxLength:"Query is too long (maximum {maxLength} characters)",invalidChars:"Query contains invalid characters",securityThreat:"Query contains potentially harmful content"}},...e},this.validateConfig()}processQuery(e){const t="query-"+ ++this.queryCounter,i=performance.now(),s=Date.now(),r=[];this.config.enablePerformanceMonitoring&&u.startTracking(t,"string"==typeof e?e.length:0,(this.config.customValidators?.length||0)+1);const n=e;if("string"!=typeof e){const e={processingTime:performance.now()-i,originalQuery:String(n),length:0,trimmed:!1,timestamp:s,...this.config.enablePerformanceMonitoring&&{performanceId:t},validationRulesApplied:["type-validation"]};return this.config.enablePerformanceMonitoring&&u.endTracking(t),this.createErrorResult(n,"Query must be a string",e)}const a=e.trim();let o,c,h=this.normalizeQuery(a);r.push("normalization"),this.config.enableSecurityValidation&&(o=l(h,{xssProtection:this.config.enableXSSProtection,sqlInjectionProtection:this.config.enableSQLInjectionProtection}),r.push("security-validation"),c=o.sanitized,o.isSecure||(h=c,r.push("sanitization")));const d=this.validateQuery(h);r.push("basic-validation");const m=[];if(this.config.customValidators&&this.config.customValidators.length>0)for(const e of this.config.customValidators)e.validator(h)||(m.push(e.errorMessage),r.push(`custom-${e.name}`));const p=[...d.errors,...m],f=0===p.length&&!1!==o?.isSecure,g=performance.now()-i;this.config.enablePerformanceMonitoring&&u.endTracking(t);return{original:n,normalized:h,...c&&{sanitized:c},isValid:f,...p.length>0&&{error:p[0]},...o&&{securityInfo:o},metadata:{processingTime:g,originalQuery:n,length:h.length,trimmed:n!==a,timestamp:s,...this.config.enablePerformanceMonitoring&&{performanceId:t},validationRulesApplied:r}}}validateInput(e){if("string"!=typeof e)return{isValid:!1,errors:["Query must be a string"]};const t=e.trim(),i=this.normalizeQuery(t);return this.validateQuery(i)}shouldTriggerSearch(e,t="change"){const i=this.config.triggerOn;return"both"===i||("change"===i&&"change"===t||"enter"===i&&"enter"===t)}debouncedProcess(e,t,i="change"){if(!this.shouldTriggerSearch(e,i))return;if(this.config.debounceMs<=0){return void t(this.processQuery(e))}const s=Date.now();switch(this.config.debounceStrategy||"trailing"){case"leading":this.executeLeadingDebounce(e,t,s);break;case"trailing":default:this.executeTrailingDebounce(e,t);break;case"both":this.executeBothDebounce(e,t,s)}}executeLeadingDebounce(e,t,i){if(i-this.lastExecutionTime>=this.config.debounceMs){t(this.processQuery(e)),this.lastExecutionTime=i,this.leadingTimer&&clearTimeout(this.leadingTimer),this.leadingTimer=window.setTimeout(()=>{this.leadingTimer=null},this.config.debounceMs)}}executeTrailingDebounce(e,t){this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=window.setTimeout(()=>{const i=this.processQuery(e);t(i),this.debounceTimer=null,this.lastExecutionTime=Date.now()},this.config.debounceMs)}executeBothDebounce(e,t,i){if(i-this.lastExecutionTime>=this.config.debounceMs&&!this.leadingTimer){const s=this.processQuery(e);t(s),this.lastExecutionTime=i,this.leadingTimer=window.setTimeout(()=>{this.leadingTimer=null},this.config.debounceMs)}this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=window.setTimeout(()=>{const i=this.processQuery(e);t(i),this.debounceTimer=null,this.lastExecutionTime=Date.now()},this.config.debounceMs)}cancelPendingOperations(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null),this.leadingTimer&&(clearTimeout(this.leadingTimer),this.leadingTimer=null)}destroy(){this.cancelPendingOperations()}getConfig(){return{...this.config}}getPerformanceMetrics(e){return this.config.enablePerformanceMonitoring?e?u.getMetrics(e):u.getAllMetrics("query"):[]}getPerformanceRecommendations(){if(!this.config.enablePerformanceMonitoring)return[];return function(e){const t=[];if(0===e.length)return t;const i=e.reduce((e,t)=>e+t.duration,0)/e.length,s=Math.max(...e.map(e=>e.duration)),r=e.reduce((e,t)=>e+t.queryLength,0)/e.length;return i>10&&t.push({type:"warning",message:"Average query processing time is high. Consider optimizing validation rules.",metric:"duration",threshold:10,currentValue:i}),s>50&&t.push({type:"critical",message:"Some queries are taking too long to process. Review complex validation patterns.",metric:"duration",threshold:50,currentValue:s}),r>100&&t.push({type:"info",message:"Users are entering long queries. Consider adding query length limits.",metric:"queryLength",threshold:100,currentValue:r}),t}(this.getPerformanceMetrics())}clearPerformanceMetrics(){this.config.enablePerformanceMonitoring&&u.clearMetrics()}normalizeQuery(e){let t=e;switch(t=t.trim(),this.config.enablePreprocessing&&(t=t.replace(/\s+/g," "),t=t.replace(/[\r\n\t]/g," "),t=t.replace(/[.,;:!?'"()[\]{}]/g,""),t=t.normalize("NFD").replace(/[\u0300-\u036f]/g,"")),this.config.caseNormalization){case"lowercase":t=t.toLowerCase();break;case"uppercase":t=t.toUpperCase();break;case"preserve":break;default:this.config.caseSensitive||(t=t.toLowerCase())}return this.config.enableStemming&&(t=this.applyStemming(t)),t}applyStemming(e){return e.split(" ").map(e=>e.length<=2?e:e.endsWith("ing")?e.slice(0,-3):e.endsWith("ed")||e.endsWith("er")?e.slice(0,-2):e.endsWith("est")?e.slice(0,-3):e.endsWith("ly")?e.slice(0,-2):e.endsWith("s")&&!e.endsWith("ss")?e.slice(0,-1):e).join(" ")}validateQuery(e){const t=[],i=[];let s="";const r={};if(e.length<this.config.minLength){const e=`Query must be at least ${this.config.minLength} characters long`;t.push(e),s=this.getLocalizedMessage("minLength",{minLength:this.config.minLength.toString()}),r.en=s,"en"!==this.config.localization?.language&&(r[this.config.localization?.language||"en"]=this.config.localization?.messages.minLength?.replace("{minLength}",this.config.minLength.toString())||s)}if(e.length>500){const e="Query is too long (maximum 500 characters)";t.push(e),s=this.getLocalizedMessage("maxLength",{maxLength:"500"}),r.en=s,"en"!==this.config.localization?.language&&(r[this.config.localization?.language||"en"]=this.config.localization?.messages.maxLength?.replace("{maxLength}","500")||s)}return(e.includes("<")||e.includes(">")||e.includes("&"))&&i.push("Query contains special characters that may be filtered"),{isValid:0===t.length,errors:t,warnings:i.length>0?i:void 0,userFriendlyMessage:s||void 0,localizedMessages:Object.keys(r).length>0?r:void 0,validationContext:{field:"query",value:e,rule:t.length>0?"length-validation":"valid"}}}getLocalizedMessage(e,t={}){let i=this.config.localization?.messages[e]||("minLength"===e?"Please enter at least {minLength} characters":"maxLength"===e?"Query is too long (maximum {maxLength} characters)":"Invalid input");for(const[e,s]of Object.entries(t))i=i.replace(`{${e}}`,s);return i}createErrorResult(e,t,i){return{original:e,normalized:"",isValid:!1,error:t,metadata:i}}validateConfig(){if("number"!=typeof this.config.minLength||this.config.minLength<0)throw new t("minLength must be a non-negative number","minLength");if(this.config.minLength>100)throw new t("minLength cannot exceed 100 characters","minLength");if("number"!=typeof this.config.debounceMs||this.config.debounceMs<0)throw new t("debounceMs must be a non-negative number","debounceMs");if(!["change","enter","both"].includes(this.config.triggerOn))throw new t("triggerOn must be one of: change, enter, both","triggerOn");if(!["exact","partial","fuzzy"].includes(this.config.matchMode))throw new t("matchMode must be one of: exact, partial, fuzzy","matchMode")}}new class{constructor(){this.enhancementRules=[],this.categoryMappings=new Map,this.iconMappings=new Map,this.customEnhancers=new Map,this.stats=this.initializeStats()}addRule(e){this.enhancementRules.push(e),this.sortRulesByPriority()}addRules(e){this.enhancementRules.push(...e),this.sortRulesByPriority()}addCategoryMapping(e,t){this.categoryMappings.set(e,t)}addIconMapping(e,t){this.iconMappings.set(e,t)}addCustomEnhancer(e,t){this.customEnhancers.set(e,t)}enhanceResult(e,t){const i=performance.now();this.stats.totalEnhancements++;const s={...e,metadata:{...e.metadata}};try{for(const e of this.enhancementRules)if(this.evaluateRuleConditions(e,s)){const i=e.enhance(s,t);Object.assign(s.metadata,i),this.stats.ruleExecutions[e.name]=(this.stats.ruleExecutions[e.name]||0)+1}this.applySubtitleEnhancement(s),this.applyIconEnhancement(s),this.applyCategoryEnhancement(s),this.applyCustomEnhancements(s),s.metadata.enhanced=!0,s.metadata.enhancementTime=performance.now()-i,this.stats.successfulEnhancements++}catch(e){s.metadata.enhancementError=e instanceof Error?e.message:String(e)}return this.updateStats(performance.now()-i),s}enhanceResults(e,t={}){return e.map((i,s)=>this.enhanceResult(i,{...t,index:s,totalResults:e.length,sourceType:t.sourceType||"unknown"}))}applySubtitleEnhancement(e){if(e.metadata.subtitle)return;const t=[e.description,e.metadata.description,e.metadata.summary,e.metadata.type,e.metadata.category];for(const i of t)if(i&&"string"==typeof i&&i.trim().length>0){e.metadata.subtitle=i.trim();break}if(!e.metadata.subtitle){const t=[];e.metadata.category&&"string"==typeof e.metadata.category&&t.push(e.metadata.category),e.metadata.type&&"string"==typeof e.metadata.type&&t.push(e.metadata.type),t.length>0&&(e.metadata.subtitle=t.join(" • "))}}applyIconEnhancement(e){if(e.metadata.icon)return;const t=[e.metadata.category,e.metadata.type,e.metadata.kind,this.extractFileExtension(e.title||e.url)].filter(e=>e&&"string"==typeof e);for(const i of t){const t=this.iconMappings.get(i);if(t){e.metadata.icon=t;break}}e.metadata.icon||(e.metadata.icon=this.getDefaultIcon(e))}applyCategoryEnhancement(e){if(e.metadata.categoryConfig)return;const t=e.metadata.category;if(t&&this.categoryMappings.has(t)){const i=this.categoryMappings.get(t);e.metadata.categoryConfig=i,!e.metadata.icon&&i.icon&&(e.metadata.icon=i.icon)}}applyCustomEnhancements(e){for(const[t,i]of this.customEnhancers)try{const t=i(e);Object.assign(e.metadata,t)}catch(e){}}evaluateRuleConditions(e,t){return!e.conditions||0===e.conditions.length||e.conditions.every(e=>{const i=this.getFieldValue(t,e.field);switch(e.operator){case"exists":return null!=i;case"equals":return i===e.value;case"contains":return"string"==typeof i&&"string"==typeof e.value&&i.toLowerCase().includes(e.value.toLowerCase());case"startsWith":return"string"==typeof i&&"string"==typeof e.value&&i.toLowerCase().startsWith(e.value.toLowerCase());case"endsWith":return"string"==typeof i&&"string"==typeof e.value&&i.toLowerCase().endsWith(e.value.toLowerCase());case"regex":return"string"==typeof i&&e.regex&&e.regex.test(i);default:return!1}})}getFieldValue(e,t){const i=t.split(".");let s=e;for(const e of i){if(!s||"object"!=typeof s||!(e in s))return null;s=s[e]}return s}getDefaultIcon(e){const t=e.url;if(e.title,t){const e=this.extractFileExtension(t);return e?this.getFileTypeIcon(e):t.includes("github.com")?{type:"font-icon",className:"fab fa-github",alt:"GitHub"}:t.includes("stackoverflow.com")?{type:"font-icon",className:"fab fa-stack-overflow",alt:"Stack Overflow"}:{type:"font-icon",className:"fas fa-external-link-alt",alt:"External Link"}}return{type:"font-icon",className:"fas fa-file",alt:"Document"}}getFileTypeIcon(e){return{pdf:{type:"font-icon",className:"fas fa-file-pdf",color:"#e74c3c",alt:"PDF"},doc:{type:"font-icon",className:"fas fa-file-word",color:"#2980b9",alt:"Word Document"},docx:{type:"font-icon",className:"fas fa-file-word",color:"#2980b9",alt:"Word Document"},xls:{type:"font-icon",className:"fas fa-file-excel",color:"#27ae60",alt:"Excel Spreadsheet"},xlsx:{type:"font-icon",className:"fas fa-file-excel",color:"#27ae60",alt:"Excel Spreadsheet"},ppt:{type:"font-icon",className:"fas fa-file-powerpoint",color:"#e67e22",alt:"PowerPoint"},pptx:{type:"font-icon",className:"fas fa-file-powerpoint",color:"#e67e22",alt:"PowerPoint"},jpg:{type:"font-icon",className:"fas fa-file-image",color:"#9b59b6",alt:"Image"},jpeg:{type:"font-icon",className:"fas fa-file-image",color:"#9b59b6",alt:"Image"},png:{type:"font-icon",className:"fas fa-file-image",color:"#9b59b6",alt:"Image"},gif:{type:"font-icon",className:"fas fa-file-image",color:"#9b59b6",alt:"Image"},mp4:{type:"font-icon",className:"fas fa-file-video",color:"#e74c3c",alt:"Video"},avi:{type:"font-icon",className:"fas fa-file-video",color:"#e74c3c",alt:"Video"},mp3:{type:"font-icon",className:"fas fa-file-audio",color:"#f39c12",alt:"Audio"},wav:{type:"font-icon",className:"fas fa-file-audio",color:"#f39c12",alt:"Audio"},zip:{type:"font-icon",className:"fas fa-file-archive",color:"#34495e",alt:"Archive"},rar:{type:"font-icon",className:"fas fa-file-archive",color:"#34495e",alt:"Archive"},js:{type:"font-icon",className:"fab fa-js-square",color:"#f1c40f",alt:"JavaScript"},ts:{type:"font-icon",className:"fas fa-code",color:"#3498db",alt:"TypeScript"},html:{type:"font-icon",className:"fab fa-html5",color:"#e74c3c",alt:"HTML"},css:{type:"font-icon",className:"fab fa-css3-alt",color:"#3498db",alt:"CSS"}}[e.toLowerCase()]||{type:"font-icon",className:"fas fa-file",alt:"File"}}extractFileExtension(e){if(!e)return null;const t=e.match(/\.([^.]+)(?:\?|$)/);return t?t[1]:null}sortRulesByPriority(){this.enhancementRules.sort((e,t)=>t.priority-e.priority)}updateStats(e){const t=performance.now()-this.stats.lastResetTime;this.stats.averageEnhancementTime=(this.stats.averageEnhancementTime*(this.stats.totalEnhancements-1)+e)/this.stats.totalEnhancements,this.stats.enhancementsPerSecond=t>0?1e3*this.stats.totalEnhancements/t:0}initializeStats(){return{totalEnhancements:0,successfulEnhancements:0,ruleExecutions:{},averageEnhancementTime:0,enhancementsPerSecond:0,lastResetTime:performance.now()}}getStats(){return{...this.stats}}resetStats(){this.stats=this.initializeStats()}clear(){this.enhancementRules=[],this.categoryMappings.clear(),this.iconMappings.clear(),this.customEnhancers.clear()}getRulesCount(){return this.enhancementRules.length}getMappingsCount(){return{categories:this.categoryMappings.size,icons:this.iconMappings.size,customEnhancers:this.customEnhancers.size}}};class d{constructor(e){this.config={...e},this.validateConfiguration()}transformResults(e,t){if(!Array.isArray(e))return[];const i=performance.now(),s=[];for(let i=0;i<e.length;i++){const r=e[i];if(r?.item)try{const e=this.transformSingleResult(r,t,i);e&&s.push(e)}catch(e){}}const r=performance.now()-i;return s.forEach(e=>{e.metadata&&(e.metadata.queryTime=r)}),s}transformSingleResult(e,t,i){if(!e||!e.item)return null;const s=e.item;if(!s||"object"!=typeof s)return null;const r=this.getFieldValue(s,this.config.labelField);if(!r||"string"!=typeof r&&"number"!=typeof r)return null;const n={score:e.score,matchedFields:e.matchedFields||[],originalIndex:e.originalIndex??i,source:{type:t.sourceType,timestamp:t.timestamp,queryTime:0}};if(this.config.metadataFields)for(const[e,t]of Object.entries(this.config.metadataFields))if(t&&"string"==typeof t){const i=this.getFieldValue(s,t);null!=i&&(n[e]=i)}const a={id:this.generateResultId(s,i),title:String(r),metadata:n},o=this.generateDescription(s,n);o&&(a.description=o);const c=this.extractUrl(s);return c&&(a.url=c),a}generateDescription(e,t){if(t.subtitle&&"string"==typeof t.subtitle)return t.subtitle;const i=["description","subtitle","summary","email","type"];for(const t of i){const i=this.getFieldValue(e,t);if(i&&"string"==typeof i&&i.trim().length>0)return i.trim()}}extractUrl(e){const t=["url","link","href","website"];for(const i of t){const t=this.getFieldValue(e,i);if(t&&"string"==typeof t&&t.trim().length>0)return t.trim()}}generateResultId(e,t){const i=["id","_id","uuid","key"];for(const t of i){const i=this.getFieldValue(e,t);if(null!=i&&("string"==typeof i||"number"==typeof i))return i}return`result_${t}_${Date.now()}`}getFieldValue(e,t){if(!e||"object"!=typeof e)return null;const i=t.split(".");let s=e;for(const e of i){if(!s||"object"!=typeof s||!(e in s))return null;s=s[e]}return s}validateConfiguration(){if(!this.config.labelField)throw new Error("labelField is required in mapping configuration");if("string"!=typeof this.config.labelField)throw new Error("labelField must be a string")}}class m{constructor(e,i){if(this.inputElement=null,this.clearButton=null,this.eventListeners=new Map,this.isInitialized=!1,!(e&&e instanceof HTMLElement))throw new t("Container must be a valid HTMLElement");this.container=e,this.config={...i},this.validateConfig()}init(){this.isInitialized||(this.render(),this.bindEvents(),this.isInitialized=!0)}destroy(){this.isInitialized&&(this.unbindEvents(),this.container.innerHTML="",this.inputElement=null,this.clearButton=null,this.eventListeners.clear(),this.isInitialized=!1)}getValue(){return this.inputElement?.value||""}setValue(e){this.inputElement&&(this.inputElement.value=e||"",this.updateClearButton())}focus(){this.inputElement&&this.inputElement.focus()}blur(){this.inputElement&&this.inputElement.blur()}clear(){this.setValue(""),this.emit("clear"),this.emit("input","")}setLoading(e){this.inputElement&&(e?(this.inputElement.classList.add("loading"),this.inputElement.setAttribute("aria-busy","true")):(this.inputElement.classList.remove("loading"),this.inputElement.removeAttribute("aria-busy")))}setError(e){if(this.inputElement)if(e){this.inputElement.classList.add("error"),this.inputElement.setAttribute("aria-invalid","true"),this.inputElement.setAttribute("aria-describedby","search-error");let t=this.container.querySelector(".search-error");t||(t=document.createElement("div"),t.className="search-error",t.id="search-error",t.setAttribute("role","alert"),this.container.appendChild(t)),t.textContent=e}else{this.inputElement.classList.remove("error"),this.inputElement.removeAttribute("aria-invalid"),this.inputElement.removeAttribute("aria-describedby");const e=this.container.querySelector(".search-error");e&&e.remove()}}on(e,t){this.eventListeners.set(e,t)}off(e){this.eventListeners.delete(e)}render(){const e=document.createElement("div");e.className="search-input-wrapper",this.inputElement=document.createElement("input"),this.inputElement.type="text",this.inputElement.className="search-input",this.inputElement.placeholder=this.config.placeholder||"Search...",this.inputElement.autocomplete="off",this.inputElement.spellcheck=!1,this.inputElement.setAttribute("role","searchbox"),this.inputElement.setAttribute("aria-label","Search"),this.inputElement.setAttribute("aria-autocomplete","list"),this.config.rtl&&(this.inputElement.dir="rtl"),this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="search-clear",this.clearButton.innerHTML="×",this.clearButton.setAttribute("aria-label","Clear search"),this.clearButton.style.display="none",e.appendChild(this.inputElement),e.appendChild(this.clearButton),this.container.appendChild(e),this.updateClearButton()}bindEvents(){this.inputElement&&this.clearButton&&(this.inputElement.addEventListener("input",this.handleInput.bind(this)),this.inputElement.addEventListener("focus",this.handleFocus.bind(this)),this.inputElement.addEventListener("blur",this.handleBlur.bind(this)),this.inputElement.addEventListener("keydown",this.handleKeydown.bind(this)),this.clearButton.addEventListener("click",this.handleClear.bind(this)))}unbindEvents(){this.inputElement&&this.clearButton&&(this.inputElement.removeEventListener("input",this.handleInput.bind(this)),this.inputElement.removeEventListener("focus",this.handleFocus.bind(this)),this.inputElement.removeEventListener("blur",this.handleBlur.bind(this)),this.inputElement.removeEventListener("keydown",this.handleKeydown.bind(this)),this.clearButton.removeEventListener("click",this.handleClear.bind(this)))}handleInput(e){const t=e.target.value;this.updateClearButton(),this.emit("input",t)}handleFocus(e){this.emit("focus",e)}handleBlur(e){this.emit("blur",e)}handleKeydown(e){this.emit("keydown",e)}handleClear(){this.clear(),this.focus()}updateClearButton(){if(this.clearButton){const e=this.getValue().length>0;this.clearButton.style.display=e?"block":"none"}}emit(e,...t){const i=this.eventListeners.get(e);if(i)try{i(...t)}catch(e){}}validateConfig(){if("string"!=typeof this.config.placeholder)throw new t("placeholder must be a string","placeholder");if("boolean"!=typeof this.config.rtl)throw new t("rtl must be a boolean","rtl")}}class p{constructor(e,i){if(this.dropdownElement=null,this.listElement=null,this.results=[],this.selectedIndex=-1,this.eventListeners=new Map,this.isInitialized=!1,this.isVisible=!1,!(e&&e instanceof HTMLElement))throw new t("Container must be a valid HTMLElement");this.container=e,this.config={...i},this.validateConfig()}init(){this.isInitialized||(this.render(),this.bindEvents(),this.isInitialized=!0)}destroy(){this.isInitialized&&(this.unbindEvents(),this.container.innerHTML="",this.dropdownElement=null,this.listElement=null,this.results=[],this.selectedIndex=-1,this.eventListeners.clear(),this.isInitialized=!1,this.isVisible=!1)}showResults(e){if(!Array.isArray(e))throw new t("Results must be an array");this.results=[...e],this.selectedIndex=-1,this.renderResults(),this.show()}clearResults(){this.results=[],this.selectedIndex=-1,this.renderResults(),this.hide()}showLoading(){if(!this.listElement)return;this.listElement.innerHTML="";const e=this.createLoadingItem();this.listElement.appendChild(e),this.show()}showError(e){if(!this.listElement)return;this.listElement.innerHTML="";const t=this.createErrorItem(e);this.listElement.appendChild(t),this.show()}showNoResults(){if(!this.listElement)return;this.listElement.innerHTML="";const e=this.createNoResultsItem();this.listElement.appendChild(e),this.show()}hide(){this.dropdownElement&&(this.dropdownElement.style.display="none",this.dropdownElement.setAttribute("aria-hidden","true"),this.isVisible=!1)}show(){this.dropdownElement&&(this.dropdownElement.style.display="block",this.dropdownElement.setAttribute("aria-hidden","false"),this.isVisible=!0)}navigate(e){if(0===this.results.length)return;let t=this.selectedIndex;switch(e){case"up":t=t<=0?this.results.length-1:t-1;break;case"down":t=t>=this.results.length-1?0:t+1;break;case"first":t=0;break;case"last":t=this.results.length-1}this.setSelectedIndex(t),this.emit("navigate",e)}selectCurrent(){if(this.selectedIndex>=0&&this.selectedIndex<this.results.length){const e=this.results[this.selectedIndex];e&&this.emit("select",e,this.selectedIndex)}}getSelectedResult(){return this.selectedIndex>=0&&this.selectedIndex<this.results.length&&this.results[this.selectedIndex]||null}setSelectedIndex(e){const t=this.selectedIndex;this.selectedIndex=Math.max(-1,Math.min(e,this.results.length-1)),t!==this.selectedIndex&&this.updateSelection()}isOpen(){return this.isVisible}on(e,t){this.eventListeners.set(e,t)}off(e){this.eventListeners.delete(e)}render(){this.dropdownElement=document.createElement("div"),this.dropdownElement.className="search-dropdown",this.dropdownElement.style.display="none",this.dropdownElement.setAttribute("aria-hidden","true"),this.listElement=document.createElement("ul"),this.listElement.className="search-results",this.listElement.setAttribute("role","listbox"),this.listElement.setAttribute("aria-label","Search results"),this.config.rtl&&(this.dropdownElement.dir="rtl"),this.dropdownElement.appendChild(this.listElement),this.container.appendChild(this.dropdownElement)}renderResults(){if(!this.listElement)return;if(this.listElement.innerHTML="",0===this.results.length)return;const e=Math.min(this.results.length,this.config.maxResults);for(let t=0;t<e;t++){const e=this.results[t];if(e){const i=this.createResultItem(e,t);this.listElement.appendChild(i)}}this.updateSelection()}createResultItem(e,t){const i=document.createElement("li");i.className="search-result",i.setAttribute("role","option"),i.setAttribute("data-index",String(t));const s=document.createElement("div");if(s.className="result-title",s.textContent=e.title,i.appendChild(s),e.description){const t=document.createElement("div");t.className="result-description",t.textContent=e.description,i.appendChild(t)}if(e.metadata?.category){const t=document.createElement("div");t.className="result-category",t.textContent=String(e.metadata.category),i.appendChild(t)}return i}createLoadingItem(){const e=document.createElement("li");return e.className="search-loading",e.setAttribute("role","status"),e.setAttribute("aria-live","polite"),e.textContent=this.config.loadingText||"Loading...",e}createErrorItem(e){const t=document.createElement("li");return t.className="search-error",t.setAttribute("role","alert"),t.textContent=e,t}createNoResultsItem(){const e=document.createElement("li");return e.className="search-no-results",e.setAttribute("role","status"),e.textContent=this.config.noResultsText||"No results found",e}updateSelection(){if(!this.listElement)return;this.listElement.querySelectorAll(".search-result").forEach((e,t)=>{t===this.selectedIndex?(e.classList.add("selected"),e.setAttribute("aria-selected","true"),e.scrollIntoView({block:"nearest"})):(e.classList.remove("selected"),e.setAttribute("aria-selected","false"))})}bindEvents(){this.listElement&&(this.listElement.addEventListener("click",this.handleClick.bind(this)),this.listElement.addEventListener("mouseenter",this.handleMouseEnter.bind(this),!0))}unbindEvents(){this.listElement&&(this.listElement.removeEventListener("click",this.handleClick.bind(this)),this.listElement.removeEventListener("mouseenter",this.handleMouseEnter.bind(this),!0))}handleClick(e){const t=e.target.closest(".search-result");if(t){const e=parseInt(t.getAttribute("data-index")||"-1");e>=0&&e<this.results.length&&(this.setSelectedIndex(e),this.selectCurrent())}}handleMouseEnter(e){const t=e.target.closest(".search-result");if(t){const e=parseInt(t.getAttribute("data-index")||"-1");e>=0&&e<this.results.length&&this.setSelectedIndex(e)}}emit(e,...t){const i=this.eventListeners.get(e);if(i)try{i(...t)}catch(e){}}validateConfig(){if("number"!=typeof this.config.maxResults||this.config.maxResults<=0)throw new t("maxResults must be a positive number","maxResults");if("string"!=typeof this.config.loadingText)throw new t("loadingText must be a string","loadingText");if("string"!=typeof this.config.noResultsText)throw new t("noResultsText must be a string","noResultsText");if("boolean"!=typeof this.config.rtl)throw new t("rtl must be a boolean","rtl")}}class f{constructor(){this.frameRateObserver=null,this.interactionObserver=null,this.measurementIdCounter=0,this.enabled=!0,this.measurements=new Map,this.baselines=new Map,this.initializePerformanceObservers(),this.establishDefaultBaselines()}startMeasurement(e,t){if(!this.enabled)return"";const i=`perf_${e}_${++this.measurementIdCounter}_${Date.now()}`,s={id:i,operation:e,startTime:performance.now(),metadata:{...t,userAgent:"undefined"!=typeof navigator?navigator.userAgent:"server",timestamp:Date.now()}};return"undefined"!=typeof performance&&performance.memory&&(s.memoryBefore=performance.memory.usedJSHeapSize),this.measurements.has(e)||this.measurements.set(e,[]),this.measurements.get(e).push(s),i}endMeasurement(e,t=!0,i){const s=performance.now();let r,n="";for(const[t,i]of Array.from(this.measurements.entries())){const s=i.find(t=>t.id===e);if(s){r=s,n=t;break}}if(!r)return{id:e,operation:"unknown",startTime:s,endTime:s,duration:0,success:!1,error:"Measurement not found"};r.endTime=s,r.duration=s-r.startTime,r.success=t,i&&(r.resultCount=i.resultCount,r.cacheStatus=i.cacheStatus,r.sourceLatency=i.sourceLatency,r.frameRate=i.frameRate,r.interactionType=i.interactionType),"undefined"!=typeof performance&&performance.memory&&(r.memoryAfter=performance.memory.usedJSHeapSize);const a=this.measurements.get(n);return a.length>1e3&&a.splice(0,a.length-1e3),this.checkForRegressions(n,r),r}recordInteractionLatency(e,t,i){if(!this.enabled)return;const s={id:`interaction_${++this.measurementIdCounter}_${Date.now()}`,operation:"user_interaction",startTime:performance.now()-t,endTime:performance.now(),duration:t,success:!0,interactionType:e,metadata:{targetElement:i,timestamp:Date.now()}};this.measurements.has("user_interaction")||this.measurements.set("user_interaction",[]),this.measurements.get("user_interaction").push(s)}recordRenderingPerformance(e,t,i){if(!this.enabled)return;const s={id:`render_${++this.measurementIdCounter}_${Date.now()}`,operation:"result_rendering",startTime:performance.now()-e,endTime:performance.now(),duration:e,success:!0,resultCount:t,frameRate:i,metadata:{timestamp:Date.now()}};this.measurements.has("result_rendering")||this.measurements.set("result_rendering",[]),this.measurements.get("result_rendering").push(s)}establishBaseline(e,t,i=16.67,s=100,r=.2){const n={name:e,targetResponseTime:t,targetRenderTime:i,targetInteractionLatency:s,regressionThreshold:r,establishedDate:Date.now(),sampleSize:100};this.baselines.set(e,n)}detectRegressions(e){const t=(this.measurements.get(e)||[]).slice(-50);if(t.length<10)return{detected:!1,affectedMetrics:[],severity:"minor",comparison:[],recommendations:[],timestamp:Date.now()};const i=this.baselines.get("default");if(!i)return{detected:!1,affectedMetrics:[],severity:"minor",comparison:[],recommendations:[],timestamp:Date.now()};const s=t.filter(e=>void 0!==e.duration).reduce((e,t)=>e+t.duration,0)/t.length,r=t.filter(e=>void 0!==e.frameRate).reduce((e,t)=>e+16.67/(t.frameRate/60),0)/t.length,n=[],a=[];let o=0;if(s>i.targetResponseTime*(1+i.regressionThreshold)){const e=(s-i.targetResponseTime)/i.targetResponseTime;n.push({metric:"response_time",current:s,baseline:i.targetResponseTime,degradation:e}),a.push("response_time"),o=Math.max(o,e)}if(r>i.targetRenderTime*(1+i.regressionThreshold)){const e=(r-i.targetRenderTime)/i.targetRenderTime;n.push({metric:"render_time",current:r,baseline:i.targetRenderTime,degradation:e}),a.push("render_time"),o=Math.max(o,e)}let c="minor";o>.5?c="severe":o>.3&&(c="moderate");const l=this.generateRegressionRecommendations(a,c);return{detected:a.length>0,affectedMetrics:a,severity:c,comparison:n,recommendations:l,timestamp:Date.now()}}getMetricsSummary(e,t){const i=t?Date.now()-t:0;let s=[];if(e)s=(this.measurements.get(e)||[]).filter(e=>e.startTime>=i);else for(const e of Array.from(this.measurements.values()))s.push(...e.filter(e=>e.startTime>=i));const r=s.filter(e=>void 0!==e.duration).map(e=>e.duration).sort((e,t)=>e-t),n=r.length>0?r.reduce((e,t)=>e+t,0)/r.length:0,a=s.filter(e=>void 0!==e.frameRate),o=a.length>0?a.reduce((e,t)=>e+16.67/(t.frameRate/60),0)/a.length:0,c=a.length>0?a.reduce((e,t)=>e+t.frameRate,0)/a.length:60,l=s.filter(e=>void 0!==e.interactionType),u={};for(const e of l){const t=e.interactionType;u[t]||(u[t]=[]),void 0!==e.duration&&u[t].push(e.duration)}const h=l.length>0?l.reduce((e,t)=>e+(t.duration||0),0)/l.length:0,d={};for(const[e,t]of Object.entries(u))d[e]=t.reduce((e,t)=>e+t,0)/t.length;const m=s.filter(e=>void 0!==e.cacheStatus),p=m.filter(e=>"hit"===e.cacheStatus),f=m.filter(e=>"miss"===e.cacheStatus),g=m.length>0?p.length/m.length:0,y=p.length>0?p.reduce((e,t)=>e+(t.duration||0),0)/p.length:0,w=f.length>0?f.reduce((e,t)=>e+(t.duration||0),0)/f.length:0,b=[];if(e)b.push(this.detectRegressions(e));else for(const e of Array.from(this.measurements.keys()))b.push(this.detectRegressions(e));return{responseTime:{avg:n,p95:this.getPercentile(r,.95),p99:this.getPercentile(r,.99)},renderTime:{avg:o,targetFps:c},interactionLatency:{avg:h,byType:d},cachePerformance:{hitRate:g,avgHitTime:y,avgMissTime:w},regressions:b.filter(e=>e.detected)}}setEnabled(e){this.enabled=e,e?this.initializePerformanceObservers():this.cleanup()}clearMeasurements(e){e?this.measurements.delete(e):this.measurements.clear()}getMeasurements(e){return[...this.measurements.get(e)||[]]}cleanup(){this.frameRateObserver&&(this.frameRateObserver.disconnect(),this.frameRateObserver=null),this.interactionObserver&&(this.interactionObserver.disconnect(),this.interactionObserver=null)}initializePerformanceObservers(){if("undefined"!=typeof PerformanceObserver)try{this.frameRateObserver=new PerformanceObserver(e=>{for(const t of e.getEntries())if("measure"===t.entryType||"paint"===t.entryType){const e=t.duration||t.startTime,i=e>0?1e3/e:60;i<55&&this.recordRenderingPerformance(e,0,i)}}),this.frameRateObserver.observe({entryTypes:["measure","paint"]}),this.interactionObserver=new PerformanceObserver(e=>{for(const t of e.getEntries())if("event"===t.entryType){const e=t,i=e.processingEnd-e.startTime;let s="click";e.name.includes("key")?s="keyboard":e.name.includes("touch")&&(s="touch"),this.recordInteractionLatency(s,i,e.target?.toString())}}),"PerformanceEventTiming"in window&&this.interactionObserver.observe({entryTypes:["event"]})}catch(e){}}establishDefaultBaselines(){this.establishBaseline("default",200,16.67,100,.2),this.establishBaseline("search_query",150,16.67,50,.15),this.establishBaseline("result_rendering",50,16.67,30,.1),this.establishBaseline("user_interaction",16,16.67,100,.25)}checkForRegressions(e,t){if(this.measurementIdCounter%10!=0)return;const i=this.detectRegressions(e);i.detected&&"undefined"!=typeof window&&window.dispatchEvent(new CustomEvent("performance-regression",{detail:{operation:e,regression:i,measurement:t}}))}generateRegressionRecommendations(e,t){const i=[];return e.includes("response_time")&&(i.push("Consider implementing or improving result caching"),i.push("Review data source query optimization"),"severe"===t&&i.push("Implement request debouncing or throttling")),e.includes("render_time")&&(i.push("Optimize result rendering with virtual scrolling"),i.push("Reduce DOM manipulations during rendering"),"severe"===t&&i.push("Consider implementing progressive rendering")),e.includes("interaction_latency")&&(i.push("Optimize event handlers and reduce processing time"),i.push("Implement event delegation for better performance")),i}getPercentile(e,t){if(0===e.length)return 0;const i=Math.ceil(e.length*t)-1;return e[Math.max(0,Math.min(i,e.length-1))]}}new f;const g={enabled:!0,sampleRate:1,sessionTimeout:30,bufferSize:100,flushInterval:30,privacyMode:"balanced",collectSearchTerms:!0,anonymizeIPs:!0,retentionPeriod:90};class y{constructor(e={}){this.currentSession=null,this.flushTimer=null,this.eventHandlers=[],this.sessionCounter=0,this.eventCounter=0,this.metricsCache=null,this.metricsCacheTimestamp=0,this.CACHE_DURATION=6e4,this.config={...g,...e},this.eventBuffer=[],this.sessions=new Map,this.initialize()}trackEvent(e,t={},i){if(!this.config.enabled||Math.random()>this.config.sampleRate)return;const s=this.getCurrentSession(),r=`event_${++this.eventCounter}_${Date.now()}`,n={consent:this.hasUserConsent(),anonymized:"strict"===this.config.privacyMode||this.shouldAnonymize(e),region:this.getUserRegion()},a={id:r,type:e,timestamp:Date.now(),sessionId:s.id,userAgent:"undefined"!=typeof navigator?navigator.userAgent:void 0,properties:this.sanitizeProperties(t,n.anonymized),context:{url:"undefined"!=typeof location?location.href:void 0,referrer:"undefined"!=typeof document?document.referrer:void 0,viewport:this.getViewportSize(),deviceType:this.getDeviceType(),...i},privacy:n};this.eventBuffer.push(a),this.updateSession(s,a),this.eventBuffer.length>=this.config.bufferSize&&this.flush()}trackSearchInitiated(e,t){this.trackEvent("search_initiated",{query:this.config.collectSearchTerms?e:"[REDACTED]",queryLength:e.length,hasFilters:Boolean(t&&Object.keys(t).length>0),filterCount:t?Object.keys(t).length:0,filters:"strict"!==this.config.privacyMode?t:void 0})}trackSearchCompleted(e,t,i,s){this.trackEvent("search_completed",{query:this.config.collectSearchTerms?e:"[REDACTED]",queryLength:e.length,resultCount:t,responseTime:i,dataSource:s,hasResults:t>0})}trackResultSelection(e,t,i,s){this.trackEvent("result_selected",{query:this.config.collectSearchTerms?e:"[REDACTED]",queryLength:e.length,resultPosition:t,resultId:i||"[ANONYMOUS]",resultType:s,isFirstResult:0===t})}trackError(e,t,i,s){this.trackEvent("error_occurred",{errorType:e,errorMessage:this.sanitizeErrorMessage(t),query:i&&this.config.collectSearchTerms?i:"[REDACTED]",queryLength:i?i.length:0,timestamp:Date.now(),...s})}trackFeatureUsage(e,t){this.trackEvent("feature_used",{feature:e,...t})}getMetrics(e){const t=Date.now();if(this.metricsCache&&t-this.metricsCacheTimestamp<this.CACHE_DURATION)return this.metricsCache;const i=e?t-e:t-864e5,s=this.eventBuffer.filter(e=>e.timestamp>=i),r=Array.from(this.sessions.values()).filter(e=>e.startTime>=i),n=this.calculateMetrics(s,r,i,t);return this.metricsCache=n,this.metricsCacheTimestamp=t,n}analyzeFunnel(e="default"){const t=[{name:"Search Initiated",eventType:"search_initiated"},{name:"Search Completed",eventType:"search_completed"},{name:"Result Viewed",eventType:"result_viewed"},{name:"Result Selected",eventType:"result_selected"}],i=Array.from(this.sessions.values()),s=new Map,r=new Map,n=i.length;for(const e of i){const i=[...e.searchEvents,...e.selectionEvents,...e.errorEvents].sort((e,t)=>e.timestamp-t.timestamp),n=new Set;for(const a of i)if(!n.has(a.type)&&t.some(e=>e.eventType===a.type)){s.set(a.type,(s.get(a.type)||0)+1),n.add(a.type);const t=a.timestamp-e.startTime;r.has(a.type)||r.set(a.type,[]),r.get(a.type).push(t)}}const a=t.map((e,i)=>{const a=s.get(e.eventType)||0,o=0===i?n:s.get(t[i-1].eventType)||0,c=o>0?a/o:0,l=1-c,u=r.get(e.eventType)||[],h=u.length>0?u.reduce((e,t)=>e+t,0)/u.length:0;return{name:e.name,eventType:e.eventType,count:a,conversionRate:c,dropoffRate:l,averageTime:h}}),o=a[0]?.count||0,c=a[a.length-1]?.count||0,l=o>0?c/o:0,u=n>0?c/n:0,h=a.filter(e=>e.dropoffRate>.3).map(e=>({step:e.name,dropoffRate:e.dropoffRate,severity:e.dropoffRate>.6?"high":e.dropoffRate>.4?"medium":"low"}));return{name:e,steps:a,overallConversionRate:l,totalUsers:n,completionRate:u,bottlenecks:h}}onEvent(e){this.eventHandlers.push(e)}flush(){if(0===this.eventBuffer.length)return;const e=[...this.eventBuffer];this.eventBuffer=[];for(const t of this.eventHandlers)try{t(e)}catch(e){}}clear(){this.eventBuffer=[],this.sessions.clear(),this.currentSession=null,this.metricsCache=null,this.metricsCacheTimestamp=0}destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.flush(),this.clear()}initialize(){this.config.enabled&&(this.flushTimer=setInterval(()=>{this.flush()},1e3*this.config.flushInterval),this.startSession(),setInterval(()=>{this.cleanupOldSessions()},3e5))}getCurrentSession(){return this.currentSession&&!this.isSessionExpired(this.currentSession)||this.startSession(),this.currentSession.lastActivity=Date.now(),this.currentSession}startSession(){const e=`session_${++this.sessionCounter}_${Date.now()}`,t=Date.now();this.currentSession&&!this.currentSession.ended&&this.endSession(this.currentSession),this.currentSession={id:e,startTime:t,lastActivity:t,duration:0,searchEvents:[],selectionEvents:[],errorEvents:[],totalSearches:0,totalSelections:0,totalErrors:0,ended:!1},this.sessions.set(e,this.currentSession),this.trackEvent("session_started")}endSession(e){if(e.ended)return;e.ended=!0,e.duration=e.lastActivity-e.startTime;const t=this.currentSession;this.currentSession=e,this.trackEvent("session_ended",{sessionDuration:e.duration,totalSearches:e.totalSearches,totalSelections:e.totalSelections,totalErrors:e.totalErrors,selectionRate:e.totalSearches>0?e.totalSelections/e.totalSearches:0}),this.currentSession=t}updateSession(e,t){switch(e.lastActivity=t.timestamp,t.type){case"search_initiated":case"search_completed":e.searchEvents.push(t),"search_initiated"===t.type&&e.totalSearches++;break;case"result_selected":e.selectionEvents.push(t),e.totalSelections++;break;case"error_occurred":e.errorEvents.push(t),e.totalErrors++}}isSessionExpired(e){return Date.now()-e.lastActivity>60*this.config.sessionTimeout*1e3}cleanupOldSessions(){const e=Date.now()-60*this.config.sessionTimeout*1e3;for(const[t,i]of Array.from(this.sessions.entries()))i.lastActivity<e&&!i.ended&&this.endSession(i),i.startTime<Date.now()-24*this.config.retentionPeriod*60*60*1e3&&this.sessions.delete(t)}calculateMetrics(e,t,i,s){const r=new Map;for(const t of e)r.has(t.type)||r.set(t.type,[]),r.get(t.type).push(t);const n=r.get("search_initiated")||[],a=r.get("sea