@syntropysoft/syntropyfront 0.4.5 → 0.4.7
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/CHANGELOG.md +458 -0
- package/NOTICE +1 -1
- package/README.md +2 -0
- package/dist/index.cjs +11 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +18 -26
package/dist/index.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var SyntropyFront=function(){"use strict";const e=new class{constructor(e=25){this.maxBreadcrumbs=e,this.breadcrumbs=[],this.onBreadcrumbAdded=null}setMaxBreadcrumbs(e){this.maxBreadcrumbs=e,this.breadcrumbs.length>this.maxBreadcrumbs&&(this.breadcrumbs=this.breadcrumbs.slice(-this.maxBreadcrumbs))}getMaxBreadcrumbs(){return this.maxBreadcrumbs}add(e){const t={...e,timestamp:(new Date).toISOString()};if(this.breadcrumbs=[...this.breadcrumbs,t].slice(-this.maxBreadcrumbs),this.onBreadcrumbAdded)try{this.onBreadcrumbAdded(t)}catch(e){console.warn("SyntropyFront: Error in onBreadcrumbAdded:",e)}}getAll(){return[...this.breadcrumbs]}clear(){this.breadcrumbs=[]}count(){return this.breadcrumbs.length}getByCategory(e){return this.breadcrumbs.filter(t=>t.category===e)}};class t{constructor(){this.endpoint=null,this.headers={"Content-Type":"application/json"},this.batchSize=10,this.batchTimeout=null,this.isEnabled=!1,this.sendBreadcrumbs=!1,this.encrypt=null,this.usePersistentBuffer=!1,this.maxRetries=5,this.baseDelay=1e3,this.maxDelay=3e4,this.samplingRate=1}configure(e){this.endpoint=e.endpoint,this.headers={...this.headers,...e.headers},this.batchSize=e.batchSize||this.batchSize,this.batchTimeout=e.batchTimeout,this.isEnabled=!!e.endpoint,this.encrypt=e.encrypt||null,this.usePersistentBuffer=!0===e.usePersistentBuffer,this.maxRetries=e.maxRetries||this.maxRetries,this.samplingRate="number"==typeof e.samplingRate?e.samplingRate:this.samplingRate,this.sendBreadcrumbs=!!e.batchTimeout}isAgentEnabled(){return this.isEnabled}shouldSendBreadcrumbs(){return this.sendBreadcrumbs}getConfig(){return{endpoint:this.endpoint,headers:this.headers,batchSize:this.batchSize,batchTimeout:this.batchTimeout,isEnabled:this.isEnabled,sendBreadcrumbs:this.sendBreadcrumbs,encrypt:this.encrypt,usePersistentBuffer:this.usePersistentBuffer,maxRetries:this.maxRetries,baseDelay:this.baseDelay,maxDelay:this.maxDelay,samplingRate:this.samplingRate}}}class r{constructor(e){this.config=e,this.queue=[],this.batchTimer=null,this.flushCallback=null}add(e){if(e){if(this.queue.push(e),this.queue.length>=this.config.batchSize)return this.flush(this.flushCallback);this.config.batchTimeout&&!this.batchTimer&&(this.batchTimer=setTimeout(()=>{this.flush(this.flushCallback)},this.config.batchTimeout))}}getAll(){return[...this.queue]}clear(){this.queue=[],this.clearTimer()}clearTimer(){this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null)}getSize(){return this.queue.length}isEmpty(){return 0===this.queue.length}async flush(e){if(0===this.queue.length)return;const t=[...this.queue];this.queue=[],this.clearTimer(),e&&await e(t)}}class s{constructor(e){this.config=e,this.retryQueue=[],this.retryTimer=null}addToRetryQueue(e,t=1,r=null){if(!e||0===e.length)return;const s=Math.min(this.config.baseDelay*Math.pow(2,t-1),this.config.maxDelay);this.retryQueue.push({items:e,retryCount:t,persistentId:r,nextRetry:Date.now()+s}),this.scheduleRetry()}async processRetryQueue(e,t){if(this.retryTimer=null,0===this.retryQueue.length)return;const r=Date.now(),s=this.retryQueue.filter(e=>e.nextRetry<=r);for(const r of s)await this.handleRetryItem(r,e,t);this.retryQueue.length>0&&this.scheduleRetry()}scheduleRetry(){if(this.retryTimer)return;const e=this.retryQueue.find(e=>e.nextRetry<=Date.now());if(!e)return;const t=Math.max(0,e.nextRetry-Date.now());this.retryTimer=setTimeout(()=>{this.processRetryQueue(this.sendCallback,this.removePersistentCallback)},t)}async handleRetryItem(e,t,r){try{t&&await t(e.items),this.retryQueue=this.retryQueue.filter(t=>t!==e),e.persistentId&&r&&await r(e.persistentId),console.log(`SyntropyFront: Successful retry (${e.retryCount})`)}catch(t){this.handleRetryFailure(e,t)}}handleRetryFailure(e,t){if(console.warn(`SyntropyFront: Retry ${e.retryCount} failed:`,t),e.retryCount>=this.config.maxRetries)return this.retryQueue=this.retryQueue.filter(t=>t!==e),void console.error("SyntropyFront: Item exceeded maximum retries, data lost");e.retryCount++,e.nextRetry=Date.now()+Math.min(this.config.baseDelay*Math.pow(2,e.retryCount-1),this.config.maxDelay)}clear(){this.retryQueue=[],this.clearTimer()}clearTimer(){this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=null)}getSize(){return this.retryQueue.length}isEmpty(){return 0===this.retryQueue.length}}const n=new class{constructor(){this.seen=new WeakSet,this.circularRefs=new Map,this.refCounter=0}serialize(e){try{return this.seen=new WeakSet,this.circularRefs=new Map,this.refCounter=0,JSON.stringify(this.makeSerializable(e))}catch(t){return console.error("SyntropyFront: Error in robust serialization:",t),JSON.stringify({__serializationError:!0,error:t.message,originalType:typeof e,isObject:null!==e&&"object"==typeof e,timestamp:(new Date).toISOString()})}}_serializeKnownType(e,t){return null==e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:e instanceof Date?{__type:"Date",value:e.toISOString()}:e instanceof Error?(s=e=>this.makeSerializable(e,`${t}.cause`),{__type:"Error",name:(r=e).name,message:r.message,stack:r.stack,cause:r.cause?s(r.cause):void 0}):e instanceof RegExp?{__type:"RegExp",source:(n=e).source,flags:n.flags}:"function"==typeof e?{__type:"Function",name:(i=e).name||"anonymous",length:i.length,toString:`${i.toString().substring(0,200)}...`}:void 0;var r,s,n,i}makeSerializable(e,t=""){if(null==e)return e;const r=this._serializeKnownType(e,t);return void 0!==r?r:Array.isArray(e)?this._serializeArray(e,t):"object"==typeof e?this._serializeObject(e,t):(e=>({__type:"Unknown",constructor:e.constructor?e.constructor.name:"Unknown",toString:`${String(e).substring(0,200)}...`}))(e)}_serializeArray(e,t){return this.seen.has(e)?{__circular:!0,refId:this.circularRefs.get(e)}:(this.seen.add(e),this.circularRefs.set(e,"ref_"+ ++this.refCounter),e.map((e,r)=>this.makeSerializable(e,`${t}[${r}]`)))}_serializeObjectKey(e,t,r,s){try{e[r]=this.makeSerializable(t[r],`${s}.${r}`)}catch(t){e[r]={__serializationError:!0,error:t.message,propertyName:r}}}_serializeObjectSymbols(e,t,r){if(!Object.getOwnPropertySymbols)return;const s=Object.getOwnPropertySymbols(e);for(const n of s){const s=`__symbol_${n.description||"anonymous"}`;try{r[s]=this.makeSerializable(e[n],`${t}[Symbol]`)}catch(e){r[s]={__serializationError:!0,error:e.message,symbolName:n.description||"anonymous"}}}}_serializeObject(e,t){if(this.seen.has(e))return{__circular:!0,refId:this.circularRefs.get(e)};this.seen.add(e),this.circularRefs.set(e,"ref_"+ ++this.refCounter);const r={};for(const s in e)Object.prototype.hasOwnProperty.call(e,s)&&this._serializeObjectKey(r,e,s,t);return this._serializeObjectSymbols(e,t,r),r}deserialize(e){try{const t=JSON.parse(e);return this.restoreCircularRefs(t)}catch(e){return console.error("SyntropyFront: Error in deserialization:",e),null}}_restoreKnownType(e,t){return null==e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:"Date"===e.__type?(e=>new Date(e.value))(e):"Error"===e.__type?((e,t)=>{const r=new Error(e.message);return r.name=e.name,r.stack=e.stack,e.cause&&(r.cause=t(e.cause)),r})(e,e=>this.restoreCircularRefs(e,t)):"RegExp"===e.__type?(e=>new RegExp(e.source,e.flags))(e):"Function"===e.__type?(e=>`[Function: ${e.name}]`)(e):void 0}restoreCircularRefs(e,t=new Map){const r=this._restoreKnownType(e,t);return void 0!==r?r:Array.isArray(e)?this._restoreArray(e,t):"object"==typeof e?this._restoreObject(e,t):e}_restoreArray(e,t){const r=[];t.set(e,r);for(let s=0;s<e.length;s++)e[s]?.__circular?r[s]=t.has(e[s].refId)?t.get(e[s].refId):null:r[s]=this.restoreCircularRefs(e[s],t);return r}_restoreObject(e,t){const r={};t.set(e,r);for(const s in e){if(!Object.prototype.hasOwnProperty.call(e,s)||s.startsWith("__"))continue;const n=e[s];r[s]=n?.__circular?t.has(n.refId)?t.get(n.refId):null:this.restoreCircularRefs(n,t)}return r}serializeForLogging(e){try{return this.serialize(e)}catch(e){return JSON.stringify({__logError:!0,message:"Error serializing for logging",originalError:e.message,timestamp:(new Date).toISOString()})}}};class i{constructor(e){this.config=e}async send(e){const t={timestamp:(new Date).toISOString(),items:e};let r;try{r=n.serialize(t)}catch(t){console.error("SyntropyFront: Error in payload serialization:",t),r=JSON.stringify({__serializationError:!0,error:t.message,timestamp:(new Date).toISOString(),itemsCount:e.length,fallbackData:"Serialization failed, data not sent"})}const s=await fetch(this.config.endpoint,{method:"POST",headers:this.config.headers,body:r});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);return s.json()}applyEncryption(e){return this.config.encrypt?this.config.encrypt(e):e}isConfigured(){return!!this.config.endpoint}}class a{constructor(e,t,r){this.dbName=e,this.dbVersion=t,this.storeName=r}validateConfig(){const e={isValid:!0,errors:[],timestamp:(new Date).toISOString()};return this.dbName&&"string"==typeof this.dbName||(e.isValid=!1,e.errors.push("dbName must be a non-empty string")),(!this.dbVersion||"number"!=typeof this.dbVersion||this.dbVersion<1)&&(e.isValid=!1,e.errors.push("dbVersion must be a number greater than 0")),this.storeName&&"string"==typeof this.storeName||(e.isValid=!1,e.errors.push("storeName must be a non-empty string")),e}checkIndexedDBAvailability(){const e={isAvailable:!1,reason:null,timestamp:(new Date).toISOString()};return"undefined"==typeof window?(e.reason="Not in a browser environment",e):window.indexedDB?(e.isAvailable=!0,e):(e.reason="IndexedDB is not available in this browser",e)}getConfig(){return{dbName:this.dbName,dbVersion:this.dbVersion,storeName:this.storeName}}getStoreConfig(){return{keyPath:"id",autoIncrement:!0}}}class o{constructor(e){this.configManager=e,this.db=null,this.isAvailable=!1}async init(){const e=this.configManager.validateConfig();if(!e.isValid)return{success:!1,error:`Invalid configuration: ${e.errors.join(", ")}`,timestamp:(new Date).toISOString()};const t=this.configManager.checkIndexedDBAvailability();if(!t.isAvailable)return{success:!1,error:t.reason,timestamp:(new Date).toISOString()};try{const e=await this.openConnection();return e.success?(this.db=e.db,this.isAvailable=!0,{success:!0,error:null,timestamp:(new Date).toISOString()}):{success:!1,error:e.error,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,error:`Unexpected error: ${e.message}`,timestamp:(new Date).toISOString()}}}openConnection(){return new Promise(e=>{const t=this.configManager.getConfig(),r=indexedDB.open(t.dbName,t.dbVersion);r.onerror=()=>{e({success:!1,error:"Error opening IndexedDB",db:null})},r.onupgradeneeded=e=>{const r=e.target.result,s=this.configManager.getStoreConfig();r.objectStoreNames.contains(t.storeName)||r.createObjectStore(t.storeName,s)},r.onsuccess=()=>{e({success:!0,error:null,db:r.result})}})}close(){if(!this.db)return{success:!1,error:"No active connection to close",timestamp:(new Date).toISOString()};try{return this.db.close(),this.db=null,this.isAvailable=!1,{success:!0,error:null,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,error:`Error closing connection: ${e.message}`,timestamp:(new Date).toISOString()}}}isDatabaseAvailable(){return this.isAvailable&&null!==this.db}getDatabase(){return this.isDatabaseAvailable()?this.db:null}}class c{constructor(e,t){this.connectionManager=e,this.configManager=t}getReadTransaction(){this.ensureDatabaseAvailable();const e=this.configManager.getConfig();return this.connectionManager.getDatabase().transaction([e.storeName],"readonly")}getWriteTransaction(){this.ensureDatabaseAvailable();const e=this.configManager.getConfig();return this.connectionManager.getDatabase().transaction([e.storeName],"readwrite")}getObjectStore(e){const t=this.configManager.getConfig();return e.objectStore(t.storeName)}async executeReadOperation(e){const t={success:!1,data:null,error:null,timestamp:(new Date).toISOString()};try{const r=this.getReadTransaction(),s=this.getObjectStore(r),n=await e(s);return t.success=!0,t.data=n,t}catch(e){return t.error=`Error in read operation: ${e.message}`,t}}async executeWriteOperation(e){const t={success:!1,data:null,error:null,timestamp:(new Date).toISOString()};try{const r=this.getWriteTransaction(),s=this.getObjectStore(r),n=await e(s);return t.success=!0,t.data=n,t}catch(e){return t.error=`Error in write operation: ${e.message}`,t}}ensureDatabaseAvailable(){if(!this.connectionManager.isDatabaseAvailable())throw new Error("Database not available")}getTransactionStatus(){return{isDatabaseAvailable:this.connectionManager.isDatabaseAvailable(),storeName:this.configManager.getConfig().storeName,timestamp:(new Date).toISOString()}}}class l{constructor(e,t,r){this.configManager=new a(e,t,r),this.connectionManager=new o(this.configManager),this.transactionManager=new c(this.connectionManager,this.configManager)}async init(){const e=await this.connectionManager.init();return e.success?(console.log("SyntropyFront: Database initialized"),!0):(console.warn("SyntropyFront: Error initializing database:",e.error),!1)}getReadTransaction(){return this.transactionManager.getReadTransaction()}getWriteTransaction(){return this.transactionManager.getWriteTransaction()}close(){const e=this.connectionManager.close();return!!e.success||(console.warn("SyntropyFront: Error closing database:",e.error),!1)}isDatabaseAvailable(){return this.connectionManager.isDatabaseAvailable()}get dbName(){return this.configManager.dbName}get dbVersion(){return this.configManager.dbVersion}get storeName(){return this.configManager.storeName}get db(){return this.connectionManager.getDatabase()}get isAvailable(){return this.connectionManager.isDatabaseAvailable()}}class u{constructor(e,t){this.databaseManager=e,this.serializationManager=t}async save(e){this.ensureDatabaseAvailable();const t=this.serializationManager.serialize(e),r={items:this.serializationManager.getData(t,"[]"),timestamp:(new Date).toISOString(),retryCount:0,serializationError:t.error};return this.executeWriteOperation(e=>e.add(r))}async retrieve(){if(!this.databaseManager.isDatabaseAvailable())return[];const e=await this.executeReadOperation(e=>e.getAll());return this.deserializeItems(e)}async retrieveById(e){if(!this.databaseManager.isDatabaseAvailable())return null;const t=await this.executeReadOperation(t=>t.get(e));return t?this.deserializeItem(t):null}async remove(e){return this.ensureDatabaseAvailable(),this.executeWriteOperation(t=>t.delete(e))}async update(e,t){this.ensureDatabaseAvailable();const r=await this.retrieveById(e);if(!r)throw new Error("Item not found");const s={...r,...t};return this.executeWriteOperation(e=>e.put(s))}async clear(){return this.ensureDatabaseAvailable(),this.executeWriteOperation(e=>e.clear())}ensureDatabaseAvailable(){if(!this.databaseManager.isDatabaseAvailable())throw new Error("Database not available")}executeReadOperation(e){return new Promise((t,r)=>{try{const s=this.databaseManager.getReadTransaction().objectStore(this.databaseManager.storeName),n=e(s);n.onsuccess=()=>t(n.result),n.onerror=()=>r(n.error)}catch(e){r(e)}})}executeWriteOperation(e){return new Promise((t,r)=>{try{const s=this.databaseManager.getWriteTransaction().objectStore(this.databaseManager.storeName),n=e(s);n.onsuccess=()=>t(n.result),n.onerror=()=>r(n.error)}catch(e){r(e)}})}deserializeItems(e){return e.map(e=>this.deserializeItem(e))}deserializeItem(e){const t=this.serializationManager.deserialize(e.items),r=this.serializationManager.getData(t,[]);return{...e,items:r,deserializationError:t.error}}}class h{constructor(e,t){this.storageManager=e,this.config=t}async retryFailedItems(e,t){if(this.storageManager)try{const r=await this.storageManager.retrieve();for(const s of r)if(s.retryCount<this.config.maxRetries){let r;try{r="string"==typeof s.items?n.deserialize(s.items):s.items}catch(e){console.error("SyntropyFront: Error deserializing buffer items:",e),await this.removeFailedItem(s.id);continue}if(e)try{await e(r,s.retryCount+1,s.id),t?await t(s.id):await this.removeFailedItem(s.id),console.log(`SyntropyFront: Retry successful for item ${s.id}`)}catch(e){console.warn(`SyntropyFront: Retry failed for item ${s.id}:`,e),await this.incrementRetryCount(s.id)}}else console.warn(`SyntropyFront: Item ${s.id} exceeded maximum retries, removing from buffer`),await this.removeFailedItem(s.id)}catch(e){console.error("SyntropyFront: Error processing retries:",e)}else console.warn("SyntropyFront: Storage manager not available")}async incrementRetryCount(e){try{const t=await this.storageManager.retrieveById(e);t&&await this.storageManager.update(e,{retryCount:t.retryCount+1})}catch(e){console.error("SyntropyFront: Error incrementing retry count:",e)}}async removeFailedItem(e){try{await this.storageManager.remove(e)}catch(e){console.error("SyntropyFront: Error removing failed item:",e)}}async cleanupExpiredItems(){try{const e=(await this.storageManager.retrieve()).filter(e=>e.retryCount>=this.config.maxRetries);for(const t of e)await this.removeFailedItem(t.id),console.warn(`SyntropyFront: Item ${t.id} removed for exceeding maximum retries`);e.length>0&&console.log(`SyntropyFront: Cleanup completed, ${e.length} items removed`)}catch(e){console.error("SyntropyFront: Error cleaning up expired items:",e)}}async getRetryStats(){try{const e=await this.storageManager.retrieve(),t={totalItems:e.length,itemsByRetryCount:{},averageRetryCount:0};if(e.length>0){const r=e.reduce((e,t)=>e+t.retryCount,0);t.averageRetryCount=r/e.length,e.forEach(e=>{const r=e.retryCount;t.itemsByRetryCount[r]=(t.itemsByRetryCount[r]||0)+1})}return t}catch(e){return console.error("SyntropyFront: Error getting retry statistics:",e),{totalItems:0,itemsByRetryCount:{},averageRetryCount:0}}}}const g={credit_card:(e,t)=>{const r=e.replace(/\D/g,"");return t.preserveLength?e.replace(/\d/g,(s,n)=>e.substring(0,n).replace(/\D/g,"").length<r.length-4?t.maskChar:s):`${t.maskChar.repeat(4)}-${t.maskChar.repeat(4)}-${t.maskChar.repeat(4)}-${r.slice(-4)}`},ssn:(e,t)=>{const r=e.replace(/\D/g,"");return t.preserveLength?e.replace(/\d/g,(s,n)=>e.substring(0,n).replace(/\D/g,"").length<r.length-4?t.maskChar:s):`***-**-${r.slice(-4)}`},email:(e,t)=>{const r=e.indexOf("@");if(r<=0)return g.default(e,t);const s=e.substring(0,r),n=e.substring(r);if(t.preserveLength){return(s.length>1?s.charAt(0)+t.maskChar.repeat(s.length-1):t.maskChar.repeat(s.length))+n}return`${s.charAt(0)}***${n}`},phone:(e,t)=>{const r=e.replace(/\D/g,"");return t.preserveLength?e.replace(/\d/g,(s,n)=>e.substring(0,n).replace(/\D/g,"").length<r.length-4?t.maskChar:s):`${t.maskChar.repeat(3)}-${t.maskChar.repeat(3)}-${r.slice(-4)}`},secret:(e,t)=>t.preserveLength?t.maskChar.repeat(e.length):t.maskChar.repeat(8),custom:(e,t)=>"function"==typeof t.customMask?t.customMask(e):e,default:(e,t)=>t.preserveLength?t.maskChar.repeat(e.length):t.maskChar.repeat(Math.min(e.length,8))};g.password=g.secret,g.token=g.secret;const d="credit_card",m="ssn",y="email",p="phone",f="password";const b=new class{constructor(e={}){this.maskChar=e.maskChar||"*",this.preserveLength=!1!==e.preserveLength,this.rules=[],this.strategies=new Map(Object.entries(g)),this.ansiRegex=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,!1!==e.enableDefaultRules&&this.addDefaultRules(),e.rules&&e.rules.forEach(e=>this.addRule(e))}addDefaultRules(){[{pattern:/credit_card|card_number|payment_number/i,strategy:d},{pattern:/ssn|social_security|security_number/i,strategy:m},{pattern:/email/i,strategy:y},{pattern:/phone|phone_number|mobile_number/i,strategy:p},{pattern:/password|pass|pwd|secret|api_key|token|auth_token|jwt|bearer/i,strategy:f}].forEach(e=>this.addRule(e))}addRule(e){this.rules.push({...e,_compiledPattern:"string"==typeof e.pattern?new RegExp(e.pattern,"i"):e.pattern,preserveLength:e.preserveLength??this.preserveLength,maskChar:e.maskChar??this.maskChar})}registerStrategy(e,t){"function"==typeof t&&this.strategies.set(e,t)}process(e){if(null==e)return e;return({string:e=>e.replace(this.ansiRegex,""),object:e=>Array.isArray(e)?e.map(e=>this.process(e)):e&&e.constructor===Object?this.maskObject(e):e}[typeof e]||(e=>e))(e)}maskObject(e){return Object.entries(e).reduce((e,[t,r])=>(e[t]=this.maskValue(t,r),e),{})}maskValue(e,t){if("string"!=typeof t)return this.process(t);const r=this.rules.find(t=>t._compiledPattern?.test(e));return r?this.applyStrategy(t,r):t.replace(this.ansiRegex,"")}applyStrategy(e,t){return(this.strategies.get(t.strategy)||this.strategies.get("default"))(e,t)}};class w{constructor(e={}){this.serializer=e.serializer??n,this.masking=e.masking??b}serialize(e){try{if(null==e)return{success:!0,data:this.serializer.serialize([]),error:null,timestamp:(new Date).toISOString()};const t=this.masking.process(e);return{success:!0,data:this.serializer.serialize(t),error:null,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,data:this.createFallbackData(e),error:this.createSerializationError(e),timestamp:(new Date).toISOString()}}}deserialize(e){try{if(!e)return{success:!0,data:[],error:null,timestamp:(new Date).toISOString()};return{success:!0,data:this.serializer.deserialize(e),error:null,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,data:[],error:this.createDeserializationError(e),timestamp:(new Date).toISOString()}}}createSerializationError(e){return{type:"serialization_error",message:e.message,originalError:e,timestamp:(new Date).toISOString()}}createDeserializationError(e){return{type:"deserialization_error",message:e.message,originalError:e,timestamp:(new Date).toISOString()}}createFallbackData(e){const t={__serializationError:!0,error:e.message,timestamp:(new Date).toISOString(),fallbackData:"Items not serializable - using fallback"};return JSON.stringify(t)}isSuccessful(e){return Boolean(e&&!0===e.success)}getData(e,t=null){return this.isSuccessful(e)?e.data:t}}class S{constructor(e,t={}){this.config=e,this.usePersistentBuffer=!1,this.databaseManager=t.databaseManager??new l("SyntropyFrontBuffer",1,"failedItems"),this.serializationManager=t.serializationManager??new w,this.storageManager=t.storageManager??new u(this.databaseManager,this.serializationManager),this.retryLogicManager=t.retryLogicManager??new h(this.storageManager,this.config),this.initPersistentBuffer()}async initPersistentBuffer(){try{await this.databaseManager.init()&&(this.usePersistentBuffer=this.config.usePersistentBuffer,console.log("SyntropyFront: Persistent buffer initialized"))}catch(e){console.warn("SyntropyFront: Error initializing persistent buffer:",e)}}async save(e){if(this.usePersistentBuffer)try{await this.storageManager.save(e),console.log("SyntropyFront: Items saved to persistent buffer")}catch(e){console.error("SyntropyFront: Error saving to persistent buffer:",e)}}async retrieve(){if(!this.usePersistentBuffer)return[];try{return await this.storageManager.retrieve()}catch(e){return console.error("SyntropyFront: Error retrieving from persistent buffer:",e),[]}}async remove(e){if(this.usePersistentBuffer)try{await this.storageManager.remove(e)}catch(e){console.error("SyntropyFront: Error removing from persistent buffer:",e)}}async retryFailedItems(e,t){this.usePersistentBuffer&&await this.retryLogicManager.retryFailedItems(e,t)}async cleanupExpiredItems(){this.usePersistentBuffer&&await this.retryLogicManager.cleanupExpiredItems()}async getStats(){if(!this.usePersistentBuffer)return{totalItems:0,itemsByRetryCount:{},averageRetryCount:0,isAvailable:!1};try{return{...await this.retryLogicManager.getRetryStats(),isAvailable:this.isAvailable()}}catch(e){return console.error("SyntropyFront: Error getting statistics:",e),{totalItems:0,itemsByRetryCount:{},averageRetryCount:0,isAvailable:this.isAvailable()}}}isAvailable(){return this.usePersistentBuffer&&this.databaseManager.isDatabaseAvailable()}async clear(){if(this.usePersistentBuffer)try{await this.storageManager.clear(),console.log("SyntropyFront: Persistent buffer cleared")}catch(e){console.error("SyntropyFront: Error clearing persistent buffer:",e)}}close(){this.databaseManager.close(),this.usePersistentBuffer=!1}}const v=new class{constructor(e={}){this.config=e.config||new t,this.masking=e.masking||b,this.queue=e.queue||new r(this.config),this.retry=e.retry||new s(this.config),this.transport=e.transport||new i(this.config),this.buffer=e.buffer||new S(this.config),this.setupCallbacks()}setupCallbacks(){this.queue.flushCallback=async e=>{try{await this.transport.send(e),console.log("SyntropyFront: Data sent successfully")}catch(t){console.error("SyntropyFront Agent: Error sending data:",t),this.retry.addToRetryQueue(e),await this.buffer.save(e)}},this.retry.sendCallback=async e=>await this.transport.send(e),this.retry.removePersistentCallback=async e=>{await this.buffer.remove(e)},this.buffer.sendCallback=(e,t,r)=>{this.retry.addToRetryQueue(e,t,r)}}configure(e){this.config.configure(e)}sendError(e,t=null){if(!this.config.isAgentEnabled())return void console.warn("SyntropyFront Agent: Not configured, error not sent");if(Math.random()>this.config.samplingRate)return;const r=t?{...e,context:t}:e,s=this.transport.applyEncryption(r),n=this.masking.process(s);this.queue.add({type:"error",data:n,timestamp:(new Date).toISOString()})}sendBreadcrumbs(e){if(!this.config.isAgentEnabled()||!this.config.shouldSendBreadcrumbs()||!e.length)return;if(Math.random()>this.config.samplingRate)return;const t=this.transport.applyEncryption(e),r=this.masking.process(t);this.queue.add({type:"breadcrumbs",data:r,timestamp:(new Date).toISOString()})}addToQueue(e){this.queue.add(e)}addToRetryQueue(e,t=1,r=null){this.retry.addToRetryQueue(e,t,r)}async processRetryQueue(){await this.retry.processRetryQueue(this.retry.sendCallback,this.retry.removePersistentCallback)}async flush(){await this.queue.flush(this.queue.flushCallback)}async forceFlush(){await this.flush(),this.retry.isEmpty()||(console.log("SyntropyFront: Attempting to send pending retries..."),await this.processRetryQueue())}getStats(){const e=this.config.getConfig();return{queueLength:this.queue.getSize(),retryQueueLength:this.retry.getSize(),isEnabled:this.config.isAgentEnabled(),usePersistentBuffer:e.usePersistentBuffer,maxRetries:e.maxRetries}}async retryFailedItems(){await this.buffer.retryFailedItems(this.buffer.sendCallback)}isEnabled(){return this.config.isAgentEnabled()}shouldSendBreadcrumbs(){return this.config.shouldSendBreadcrumbs()}disable(){this.config.configure({endpoint:null}),this.queue.clear(),this.retry.clear()}},I={isBrowser:()=>"undefined"!=typeof window&&"undefined"!=typeof document,getGlobal:()=>"undefined"!=typeof window?window:{},hasApi:e=>null!==e.split(".").reduce((e,t)=>null==e?null:void 0!==e[t]?e[t]:null,I.getGlobal()),runIf:(e,t,r=null)=>("function"==typeof e?e():I.hasApi(e))?t():r},k={INTERACTIVE_SELECTOR:["a","button","input","select","textarea","label","summary",'[role="button"]','[role="link"]','[role="checkbox"]','[role="radio"]','[role="menuitem"]','[role="option"]','[role="switch"]','[role="tab"]',".interactive",".btn",".clickable","[onclick]","[ng-click]","[v-on:click]","[@click]"].join(", "),hasPointerCursor:e=>{try{return"pointer"===window.getComputedStyle(e).cursor}catch(e){return!1}},findTargetByStyle:e=>e&&1===e.nodeType?k.hasPointerCursor(e)?e:e.parentElement&&e.parentElement!==document.body?k.findTargetByStyle(e.parentElement):null:null,findInteractiveTarget:e=>e&&e!==document.body&&1===e.nodeType?e.closest(k.INTERACTIVE_SELECTOR)||k.findTargetByStyle(e):null,generateSelector:e=>{if(!e)return"unknown";return`${e.tagName.toLowerCase()}${e.id?`#${e.id}`:""}${"string"==typeof e.className&&e.className?`.${e.className.split(" ").filter(Boolean).join(".")}`:""}`}};class E{constructor(){this.handler=null,this.lastClickTime=0,this.THROTTLE_MS=500}init(){I.isBrowser()&&(this.handler=e=>this.processClick(e),document.addEventListener("click",this.handler,!0))}processClick(e){const t=e?.target;if(!t||this.isThrottled())return;const r=k.findInteractiveTarget(t);r&&this.recordBreadcrumb(r)}isThrottled(){const e=Date.now(),t=e-this.lastClickTime<this.THROTTLE_MS;return t||(this.lastClickTime=e),t}recordBreadcrumb(t){const r=k.generateSelector(t);e.add({category:"ui",message:`User clicked on '${r}'`,data:{selector:r,tagName:t.tagName,id:t.id||null,className:t.className||null,text:(t.innerText||t.value||"").substring(0,30).trim()}})}destroy(){I.isBrowser()&&this.handler&&(document.removeEventListener("click",this.handler,!0),this.handler=null)}}const C=(e,t,r,s="original handler")=>{if("function"==typeof e)try{return e.apply(t,r)}catch(e){return void console.error(`SyntropyFront: Error in ${s}:`,e)}},R=(e,t,r)=>{if(!e||!(t in e))return null;const s=e[t],n=r(s);return e[t]=n,{target:e,property:t,original:s,wrapped:n,destroy:()=>{e[t]===n&&(e[t]=s)}}};class D{constructor(){this.wrapper=null}init(){"undefined"!=typeof window&&window.fetch&&(this.wrapper=R(window,"fetch",t=>(...r)=>{const s=r[0]instanceof Request?r[0].url:r[0]||"unknown",n=r[0]instanceof Request?r[0].method:r[1]?.method||"GET";return e.add({category:"network",message:`Request: ${n} ${s}`,data:{url:s,method:n,timestamp:Date.now()}}),t.apply(window,r)}))}destroy(){this.wrapper&&(this.wrapper.destroy(),this.wrapper=null)}}const z={device:{userAgent:()=>I.runIf("navigator.userAgent",()=>navigator.userAgent),language:()=>I.runIf("navigator.language",()=>navigator.language),languages:()=>I.runIf("navigator.languages",()=>navigator.languages),screen:()=>I.runIf("window.screen",()=>({width:window.screen.width,height:window.screen.height,availWidth:window.screen.availWidth,availHeight:window.screen.availHeight,colorDepth:window.screen.colorDepth,pixelDepth:window.screen.pixelDepth})),timezone:()=>I.runIf("Intl.DateTimeFormat",()=>{try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch(e){return null}}),cookieEnabled:()=>I.runIf("navigator.cookieEnabled",()=>navigator.cookieEnabled),doNotTrack:()=>I.runIf("navigator.doNotTrack",()=>navigator.doNotTrack)},window:{url:()=>I.runIf("window.location.href",()=>window.location.href),pathname:()=>I.runIf("window.location.pathname",()=>window.location.pathname),search:()=>I.runIf("window.location.search",()=>window.location.search),hash:()=>I.runIf("window.location.hash",()=>window.location.hash),referrer:()=>I.runIf("document.referrer",()=>document.referrer),title:()=>I.runIf("document.title",()=>document.title),viewport:()=>I.runIf("window.innerWidth",()=>({width:window.innerWidth,height:window.innerHeight}))},storage:{localStorage:()=>I.runIf("localStorage",()=>{try{const e=window.localStorage;return{keys:Object.keys(e).length,size:JSON.stringify(e).length,keyNames:Object.keys(e)}}catch(e){return null}}),sessionStorage:()=>I.runIf("sessionStorage",()=>{try{const e=window.sessionStorage;return{keys:Object.keys(e).length,size:JSON.stringify(e).length,keyNames:Object.keys(e)}}catch(e){return null}})},network:{online:()=>I.runIf("navigator.onLine",()=>navigator.onLine),connection:()=>I.runIf(()=>!("undefined"==typeof navigator||!(navigator.connection||navigator.mozConnection||navigator.webkitConnection)),()=>{const e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{effectiveType:e.effectiveType,downlink:e.downlink,rtt:e.rtt}})},ui:{focused:()=>I.runIf("document.hasFocus",()=>document.hasFocus()),visibility:()=>I.runIf("document.visibilityState",()=>document.visibilityState),activeElement:()=>I.runIf("document.activeElement",()=>({tagName:document.activeElement.tagName,id:document.activeElement.id,className:document.activeElement.className}))},performance:{memory:()=>I.runIf("performance.memory",()=>({used:Math.round(performance.memory.usedJSHeapSize/1048576),total:Math.round(performance.memory.totalJSHeapSize/1048576),limit:Math.round(performance.memory.jsHeapSizeLimit/1048576)})),timing:()=>I.runIf("performance.timing",()=>({navigationStart:performance.timing.navigationStart,loadEventEnd:performance.timing.loadEventEnd}))},session:{sessionId:e=>e.generateSessionId(),startTime:()=>(new Date).toISOString(),pageLoadTime:()=>I.runIf("performance.now",()=>performance.now())}},T={device:["userAgent","language","screen","timezone"],window:["url","viewport","title"],session:["sessionId","pageLoadTime"],ui:["visibility","activeElement"],network:["online","connection"]};const M=new class{constructor(){this.sessionId=null,this.providers=new Map(Object.entries(z))}collect(e={}){const t=this.normalizeConfig(e);return Object.entries(t).reduce((e,[t,r])=>{try{const s=this.providers.get(t);if(!1!==r&&!s)throw new Error(`Provider for '${t}' not found`);const n=this.resolveFields(t,s,r);n&&(e[t]=this.extractFields(s,n))}catch(r){console.warn(`SyntropyFront: Error collecting context for ${t}:`,r),e[t]={error:"Collection failed"}}return e},{})}resolveFields(e,t,r){const s=()=>Object.keys(t||{}),n={boolean:t=>t?T[e]||s():null,object:e=>Array.isArray(e)?e:s()}[typeof r];return n?n(r):null}normalizeConfig(e){return Array.isArray(e)?e.reduce((e,t)=>({...e,[t]:!0}),{}):e||{}}extractFields(e,t){return t.reduce((t,r)=>{const s=e[r];if("function"!=typeof s)return t;try{t[r]=s(this)}catch(e){console.warn(`SyntropyFront: Error collecting field ${r}:`,e),t[r]=null}return t},{})}registerProvider(e,t){this.providers.set(e,t)}generateSessionId(){return this.sessionId=this.sessionId||`session_${this.generateSecureId()}`,this.sessionId}generateSecureId(e=("undefined"!=typeof crypto?crypto:null)){return((e=("undefined"!=typeof crypto?crypto:null))=>{if("function"==typeof e?.randomUUID)return e.randomUUID();if("function"==typeof e?.getRandomValues){const t=new Uint8Array(16);return e.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}return`${Date.now()}_${Math.random().toString(36).substring(2,9)}`})(e)}getAvailableTypes(){return Array.from(this.providers.keys())}get allFields(){return Array.from(this.providers.entries()).reduce((e,[t,r])=>(e[t]=r,e),{})}get defaultContexts(){return this.allFields}},O=(t,r,s,n,i)=>({type:"uncaught_exception",error:{message:t,source:r,lineno:s,colno:n,stack:i?.stack},breadcrumbs:e.getAll(),timestamp:(new Date).toISOString()}),A=t=>({type:"unhandled_rejection",error:{message:t.reason?.message||"Promise rejection without message",stack:t.reason?.stack},breadcrumbs:e.getAll(),timestamp:(new Date).toISOString()});class _{constructor(){this.errorWrapper=null,this.rejectionWrapper=null,this.config={captureErrors:!0,captureUnhandledRejections:!0},this.contextTypes=[],this.onErrorCallback=null}configure(e,t,r){this.config={...this.config,...e},this.contextTypes=t||[],this.onErrorCallback=r}init(){I.isBrowser()&&(this.setupExceptionCapture(),this.setupRejectionCapture())}setupExceptionCapture(){this.config.captureErrors&&(this.errorWrapper=R(window,"onerror",e=>(t,r,s,n,i)=>{const a=O(t,r,s,n,i);return this.handleError(a),C(e,window,[t,r,s,n,i],"original window.onerror")}))}setupRejectionCapture(){this.config.captureUnhandledRejections&&(this.rejectionWrapper=R(window,"onunhandledrejection",e=>t=>{const r=A(t);this.handleError(r),C(e,window,[t],"original window.onunhandledrejection")}))}handleError(e){const t=this.contextTypes.length>0?M.collect(this.contextTypes):null;v.sendError(e,t),this.onErrorCallback&&this.onErrorCallback(e)}destroy(){this.errorWrapper?.destroy(),this.rejectionWrapper?.destroy(),this.errorWrapper=null,this.rejectionWrapper=null}}const x=new class{constructor(){this.isInitialized=!1,this.config={captureClicks:!0,captureFetch:!0,captureErrors:!0,captureUnhandledRejections:!0},this.registry=new Map,this.initializeRegistry()}initializeRegistry(){this.registry.set("clicks",new E),this.registry.set("fetch",new D),this.registry.set("errors",new _)}configure(e={}){this.config={...this.config,...e},this.registry.get("errors")?.configure?.(this.config,e.context||[],e.onError)}init(){this.isInitialized||(this.runLifecycle("init"),this.isInitialized=!0,console.log("SyntropyFront: Interceptors initialized (Refactored architecture)"))}destroy(){this.isInitialized&&(this.runLifecycle("destroy"),this.isInitialized=!1,console.log("SyntropyFront: Interceptors destroyed"))}runLifecycle(e){[{key:"clicks",enabled:this.config.captureClicks},{key:"fetch",enabled:this.config.captureFetch},{key:"errors",enabled:this.config.captureErrors||this.config.captureUnhandledRejections}].filter(e=>e.enabled).map(e=>this.registry.get(e.key)).filter(t=>t&&"function"==typeof t[e]).forEach(t=>t[e]())}get clickInterceptor(){return this.registry.get("clicks")}get fetchInterceptor(){return this.registry.get("fetch")}get errorInterceptor(){return this.registry.get("errors")}};return new class{constructor(){this.isActive=!1,this.config={maxEvents:50,endpoint:null,headers:{},usePersistentBuffer:!0,captureClicks:!0,captureFetch:!0,captureErrors:!0,captureUnhandledRejections:!0,samplingRate:1,onError:null},this.init()}init(){this.isActive||(this._applyConfig(),x.init(),v.retryFailedItems().catch(e=>{console.warn("SyntropyFront: Error attempting to recover persistent items:",e)}),this.isActive=!0,console.log("🚀 SyntropyFront: Initialized with modular resilient architecture"))}_applyConfig(){v.configure({endpoint:this.config.endpoint,headers:this.config.headers,usePersistentBuffer:this.config.usePersistentBuffer,samplingRate:this.config.samplingRate,batchTimeout:this.config.batchTimeout??(this.config.captureClicks||this.config.captureFetch?5e3:null)}),e.onBreadcrumbAdded=e=>{v.isEnabled()&&v.shouldSendBreadcrumbs()&&v.sendBreadcrumbs([e])},x.configure({captureClicks:this.config.captureClicks,captureFetch:this.config.captureFetch,captureErrors:this.config.captureErrors,captureUnhandledRejections:this.config.captureUnhandledRejections,onError:this.config.onError})}configure(e={}){this.config={...this.config,...e},e.fetch&&(this.config.endpoint=e.fetch.url,this.config.headers=e.fetch.options?.headers||{}),this._applyConfig();const t=this.config.endpoint?`endpoint: ${this.config.endpoint}`:"console only";console.log(`✅ SyntropyFront: Configured - ${t}`)}addBreadcrumb(t,r,s={}){return e.add({category:t,message:r,data:s})}getBreadcrumbs(){return e.getAll()}clearBreadcrumbs(){e.clear()}sendError(e,t={}){const r={type:"manual_error",error:{message:e.message||String(e),name:e.name||"Error",stack:e.stack},breadcrumbs:this.getBreadcrumbs(),timestamp:(new Date).toISOString()};return v.sendError(r,t),r}async flush(){await v.forceFlush()}getStats(){return{isActive:this.isActive,breadcrumbs:e.count(),agent:v.getStats(),config:{...this.config}}}destroy(){x.destroy(),v.disable(),this.isActive=!1,console.log("SyntropyFront: Deactivated")}}}();
|
|
1
|
+
var SyntropyFront=function(){"use strict";const e=new class{constructor(e=25){this.maxBreadcrumbs=e,this.breadcrumbs=[],this.onBreadcrumbAdded=null}setMaxBreadcrumbs(e){this.maxBreadcrumbs=e,this.breadcrumbs.length>this.maxBreadcrumbs&&(this.breadcrumbs=this.breadcrumbs.slice(-this.maxBreadcrumbs))}getMaxBreadcrumbs(){return this.maxBreadcrumbs}add(e){const t={...e,timestamp:(new Date).toISOString()};if(this.breadcrumbs=[...this.breadcrumbs,t].slice(-this.maxBreadcrumbs),this.onBreadcrumbAdded)try{this.onBreadcrumbAdded(t)}catch(e){console.warn("SyntropyFront: Error in onBreadcrumbAdded:",e)}}getAll(){return[...this.breadcrumbs]}clear(){this.breadcrumbs=[]}count(){return this.breadcrumbs.length}getByCategory(e){return this.breadcrumbs.filter(t=>t.category===e)}};class t{constructor(){this.endpoint=null,this.headers={"Content-Type":"application/json"},this.batchSize=10,this.batchTimeout=null,this.isEnabled=!1,this.sendBreadcrumbs=!1,this.encrypt=null,this.usePersistentBuffer=!1,this.maxRetries=5,this.baseDelay=1e3,this.maxDelay=3e4,this.samplingRate=1}configure(e){this.endpoint=e.endpoint,this.headers={...this.headers,...e.headers},this.batchSize=e.batchSize||this.batchSize,this.batchTimeout=e.batchTimeout,this.isEnabled=!!e.endpoint,this.encrypt=e.encrypt||null,this.usePersistentBuffer=!0===e.usePersistentBuffer,this.maxRetries=e.maxRetries||this.maxRetries,this.samplingRate="number"==typeof e.samplingRate?e.samplingRate:this.samplingRate,this.sendBreadcrumbs=!!e.batchTimeout}isAgentEnabled(){return this.isEnabled}shouldSendBreadcrumbs(){return this.sendBreadcrumbs}getConfig(){return{endpoint:this.endpoint,headers:this.headers,batchSize:this.batchSize,batchTimeout:this.batchTimeout,isEnabled:this.isEnabled,sendBreadcrumbs:this.sendBreadcrumbs,encrypt:this.encrypt,usePersistentBuffer:this.usePersistentBuffer,maxRetries:this.maxRetries,baseDelay:this.baseDelay,maxDelay:this.maxDelay,samplingRate:this.samplingRate}}}class r{constructor(e){this.config=e,this.queue=[],this.batchTimer=null,this.flushCallback=null}add(e){if(e){if(this.queue.push(e),this.queue.length>=this.config.batchSize)return this.flush(this.flushCallback);this.config.batchTimeout&&!this.batchTimer&&(this.batchTimer=setTimeout(()=>{this.flush(this.flushCallback)},this.config.batchTimeout))}}getAll(){return[...this.queue]}clear(){this.queue=[],this.clearTimer()}clearTimer(){this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null)}getSize(){return this.queue.length}isEmpty(){return 0===this.queue.length}async flush(e){if(0===this.queue.length)return;const t=[...this.queue];this.queue=[],this.clearTimer(),e&&await e(t)}}class s{constructor(e){this.config=e,this.retryQueue=[],this.retryTimer=null}addToRetryQueue(e,t=1,r=null){if(!e||0===e.length)return;const s=Math.min(this.config.baseDelay*Math.pow(2,t-1),this.config.maxDelay);this.retryQueue.push({items:e,retryCount:t,persistentId:r,nextRetry:Date.now()+s}),this.scheduleRetry()}async processRetryQueue(e,t){if(this.retryTimer=null,0===this.retryQueue.length)return;const r=Date.now(),s=this.retryQueue.filter(e=>e.nextRetry<=r);for(const r of s)await this.handleRetryItem(r,e,t);this.retryQueue.length>0&&this.scheduleRetry()}scheduleRetry(){if(this.retryTimer)return;const e=this.retryQueue.find(e=>e.nextRetry<=Date.now());if(!e)return;const t=Math.max(0,e.nextRetry-Date.now());this.retryTimer=setTimeout(()=>{this.processRetryQueue(this.sendCallback,this.removePersistentCallback)},t)}async handleRetryItem(e,t,r){try{t&&await t(e.items),this.retryQueue=this.retryQueue.filter(t=>t!==e),e.persistentId&&r&&await r(e.persistentId),console.log(`SyntropyFront: Successful retry (${e.retryCount})`)}catch(t){this.handleRetryFailure(e,t)}}handleRetryFailure(e,t){if(console.warn(`SyntropyFront: Retry ${e.retryCount} failed:`,t),e.retryCount>=this.config.maxRetries)return this.retryQueue=this.retryQueue.filter(t=>t!==e),void console.error("SyntropyFront: Item exceeded maximum retries, data lost");e.retryCount++,e.nextRetry=Date.now()+Math.min(this.config.baseDelay*Math.pow(2,e.retryCount-1),this.config.maxDelay)}clear(){this.retryQueue=[],this.clearTimer()}clearTimer(){this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=null)}getSize(){return this.retryQueue.length}isEmpty(){return 0===this.retryQueue.length}}const n=new class{constructor(){this.seen=new WeakSet,this.circularRefs=new Map,this.refCounter=0}serialize(e){try{return this.seen=new WeakSet,this.circularRefs=new Map,this.refCounter=0,JSON.stringify(this.makeSerializable(e))}catch(t){return console.error("SyntropyFront: Error in robust serialization:",t),JSON.stringify({__serializationError:!0,error:t.message,originalType:typeof e,isObject:null!==e&&"object"==typeof e,timestamp:(new Date).toISOString()})}}_serializeKnownType(e,t){return null==e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:e instanceof Date?{__type:"Date",value:e.toISOString()}:e instanceof Error?(s=e=>this.makeSerializable(e,`${t}.cause`),{__type:"Error",name:(r=e).name,message:r.message,stack:r.stack,cause:r.cause?s(r.cause):void 0}):e instanceof RegExp?{__type:"RegExp",source:(n=e).source,flags:n.flags}:"function"==typeof e?{__type:"Function",name:(i=e).name||"anonymous",length:i.length,toString:`${i.toString().substring(0,200)}...`}:void 0;var r,s,n,i}makeSerializable(e,t=""){if(null==e)return e;const r=this._serializeKnownType(e,t);return void 0!==r?r:Array.isArray(e)?this._serializeArray(e,t):"object"==typeof e?this._serializeObject(e,t):(e=>({__type:"Unknown",constructor:e.constructor?e.constructor.name:"Unknown",toString:`${String(e).substring(0,200)}...`}))(e)}_serializeArray(e,t){return this.seen.has(e)?{__circular:!0,refId:this.circularRefs.get(e)}:(this.seen.add(e),this.circularRefs.set(e,"ref_"+ ++this.refCounter),e.map((e,r)=>this.makeSerializable(e,`${t}[${r}]`)))}_serializeObjectKey(e,t,r,s){try{e[r]=this.makeSerializable(t[r],`${s}.${r}`)}catch(t){e[r]={__serializationError:!0,error:t.message,propertyName:r}}}_serializeObjectSymbols(e,t,r){if(!Object.getOwnPropertySymbols)return;const s=Object.getOwnPropertySymbols(e);for(const n of s){const s=`__symbol_${n.description||"anonymous"}`;try{r[s]=this.makeSerializable(e[n],`${t}[Symbol]`)}catch(e){r[s]={__serializationError:!0,error:e.message,symbolName:n.description||"anonymous"}}}}_serializeObject(e,t){if(this.seen.has(e))return{__circular:!0,refId:this.circularRefs.get(e)};this.seen.add(e),this.circularRefs.set(e,"ref_"+ ++this.refCounter);const r={};for(const s in e)Object.prototype.hasOwnProperty.call(e,s)&&this._serializeObjectKey(r,e,s,t);return this._serializeObjectSymbols(e,t,r),r}deserialize(e){try{const t=JSON.parse(e);return this.restoreCircularRefs(t)}catch(e){return console.error("SyntropyFront: Error in deserialization:",e),null}}_restoreKnownType(e,t){return null==e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:"Date"===e.__type?(e=>new Date(e.value))(e):"Error"===e.__type?((e,t)=>{const r=new Error(e.message);return r.name=e.name,r.stack=e.stack,e.cause&&(r.cause=t(e.cause)),r})(e,e=>this.restoreCircularRefs(e,t)):"RegExp"===e.__type?(e=>new RegExp(e.source,e.flags))(e):"Function"===e.__type?(e=>`[Function: ${e.name}]`)(e):void 0}restoreCircularRefs(e,t=new Map){const r=this._restoreKnownType(e,t);return void 0!==r?r:Array.isArray(e)?this._restoreArray(e,t):"object"==typeof e?this._restoreObject(e,t):e}_restoreArray(e,t){const r=[];t.set(e,r);for(let s=0;s<e.length;s++)e[s]?.__circular?r[s]=t.has(e[s].refId)?t.get(e[s].refId):null:r[s]=this.restoreCircularRefs(e[s],t);return r}_restoreObject(e,t){const r={};t.set(e,r);for(const s in e){if(!Object.prototype.hasOwnProperty.call(e,s)||s.startsWith("__"))continue;const n=e[s];r[s]=n?.__circular?t.has(n.refId)?t.get(n.refId):null:this.restoreCircularRefs(n,t)}return r}serializeForLogging(e){try{return this.serialize(e)}catch(e){return JSON.stringify({__logError:!0,message:"Error serializing for logging",originalError:e.message,timestamp:(new Date).toISOString()})}}};class i{constructor(e){this.config=e}async send(e){const t={timestamp:(new Date).toISOString(),items:e};let r;try{r=n.serialize(t)}catch(t){console.error("SyntropyFront: Error in payload serialization:",t),r=JSON.stringify({__serializationError:!0,error:t.message,timestamp:(new Date).toISOString(),itemsCount:e.length,fallbackData:"Serialization failed, data not sent"})}const s=await fetch(this.config.endpoint,{method:"POST",headers:this.config.headers,body:r});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);return s.json()}applyEncryption(e){return this.config.encrypt?this.config.encrypt(e):e}isConfigured(){return!!this.config.endpoint}}class a{constructor(e,t,r){this.dbName=e,this.dbVersion=t,this.storeName=r}validateConfig(){const e={isValid:!0,errors:[],timestamp:(new Date).toISOString()};return this.dbName&&"string"==typeof this.dbName||(e.isValid=!1,e.errors.push("dbName must be a non-empty string")),(!this.dbVersion||"number"!=typeof this.dbVersion||this.dbVersion<1)&&(e.isValid=!1,e.errors.push("dbVersion must be a number greater than 0")),this.storeName&&"string"==typeof this.storeName||(e.isValid=!1,e.errors.push("storeName must be a non-empty string")),e}checkIndexedDBAvailability(){const e={isAvailable:!1,reason:null,timestamp:(new Date).toISOString()};return"undefined"==typeof window?(e.reason="Not in a browser environment",e):window.indexedDB?(e.isAvailable=!0,e):(e.reason="IndexedDB is not available in this browser",e)}getConfig(){return{dbName:this.dbName,dbVersion:this.dbVersion,storeName:this.storeName}}getStoreConfig(){return{keyPath:"id",autoIncrement:!0}}}class o{constructor(e){this.configManager=e,this.db=null,this.isAvailable=!1}async init(){const e=this.configManager.validateConfig();if(!e.isValid)return{success:!1,error:`Invalid configuration: ${e.errors.join(", ")}`,timestamp:(new Date).toISOString()};const t=this.configManager.checkIndexedDBAvailability();if(!t.isAvailable)return{success:!1,error:t.reason,timestamp:(new Date).toISOString()};try{const e=await this.openConnection();return e.success?(this.db=e.db,this.isAvailable=!0,{success:!0,error:null,timestamp:(new Date).toISOString()}):{success:!1,error:e.error,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,error:`Unexpected error: ${e.message}`,timestamp:(new Date).toISOString()}}}openConnection(){return new Promise(e=>{const t=this.configManager.getConfig(),r=indexedDB.open(t.dbName,t.dbVersion);r.onerror=()=>{e({success:!1,error:"Error opening IndexedDB",db:null})},r.onupgradeneeded=e=>{const r=e.target.result,s=this.configManager.getStoreConfig();r.objectStoreNames.contains(t.storeName)||r.createObjectStore(t.storeName,s)},r.onsuccess=()=>{e({success:!0,error:null,db:r.result})}})}close(){if(!this.db)return{success:!1,error:"No active connection to close",timestamp:(new Date).toISOString()};try{return this.db.close(),this.db=null,this.isAvailable=!1,{success:!0,error:null,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,error:`Error closing connection: ${e.message}`,timestamp:(new Date).toISOString()}}}isDatabaseAvailable(){return this.isAvailable&&null!==this.db}getDatabase(){return this.isDatabaseAvailable()?this.db:null}}class c{constructor(e,t){this.connectionManager=e,this.configManager=t}getReadTransaction(){this.ensureDatabaseAvailable();const e=this.configManager.getConfig();return this.connectionManager.getDatabase().transaction([e.storeName],"readonly")}getWriteTransaction(){this.ensureDatabaseAvailable();const e=this.configManager.getConfig();return this.connectionManager.getDatabase().transaction([e.storeName],"readwrite")}getObjectStore(e){const t=this.configManager.getConfig();return e.objectStore(t.storeName)}async executeReadOperation(e){const t={success:!1,data:null,error:null,timestamp:(new Date).toISOString()};try{const r=this.getReadTransaction(),s=this.getObjectStore(r),n=await e(s);return t.success=!0,t.data=n,t}catch(e){return t.error=`Error in read operation: ${e.message}`,t}}async executeWriteOperation(e){const t={success:!1,data:null,error:null,timestamp:(new Date).toISOString()};try{const r=this.getWriteTransaction(),s=this.getObjectStore(r),n=await e(s);return t.success=!0,t.data=n,t}catch(e){return t.error=`Error in write operation: ${e.message}`,t}}ensureDatabaseAvailable(){if(!this.connectionManager.isDatabaseAvailable())throw new Error("Database not available")}getTransactionStatus(){return{isDatabaseAvailable:this.connectionManager.isDatabaseAvailable(),storeName:this.configManager.getConfig().storeName,timestamp:(new Date).toISOString()}}}class l{constructor(e,t,r){this.configManager=new a(e,t,r),this.connectionManager=new o(this.configManager),this.transactionManager=new c(this.connectionManager,this.configManager)}async init(){const e=await this.connectionManager.init();return e.success?(console.log("SyntropyFront: Database initialized"),!0):(console.warn("SyntropyFront: Error initializing database:",e.error),!1)}getReadTransaction(){return this.transactionManager.getReadTransaction()}getWriteTransaction(){return this.transactionManager.getWriteTransaction()}close(){const e=this.connectionManager.close();return!!e.success||(console.warn("SyntropyFront: Error closing database:",e.error),!1)}isDatabaseAvailable(){return this.connectionManager.isDatabaseAvailable()}get dbName(){return this.configManager.dbName}get dbVersion(){return this.configManager.dbVersion}get storeName(){return this.configManager.storeName}get db(){return this.connectionManager.getDatabase()}get isAvailable(){return this.connectionManager.isDatabaseAvailable()}}class u{constructor(e,t){this.databaseManager=e,this.serializationManager=t}async save(e){this.ensureDatabaseAvailable();const t=this.serializationManager.serialize(e),r={items:this.serializationManager.getData(t,"[]"),timestamp:(new Date).toISOString(),retryCount:0,serializationError:t.error};return this.executeWriteOperation(e=>e.add(r))}async retrieve(){if(!this.databaseManager.isDatabaseAvailable())return[];const e=await this.executeReadOperation(e=>e.getAll());return this.deserializeItems(e)}async retrieveById(e){if(!this.databaseManager.isDatabaseAvailable())return null;const t=await this.executeReadOperation(t=>t.get(e));return t?this.deserializeItem(t):null}async remove(e){return this.ensureDatabaseAvailable(),this.executeWriteOperation(t=>t.delete(e))}async update(e,t){this.ensureDatabaseAvailable();const r=await this.retrieveById(e);if(!r)throw new Error("Item not found");const s={...r,...t};return this.executeWriteOperation(e=>e.put(s))}async clear(){return this.ensureDatabaseAvailable(),this.executeWriteOperation(e=>e.clear())}ensureDatabaseAvailable(){if(!this.databaseManager.isDatabaseAvailable())throw new Error("Database not available")}executeReadOperation(e){return new Promise((t,r)=>{try{const s=this.databaseManager.getReadTransaction().objectStore(this.databaseManager.storeName),n=e(s);n.onsuccess=()=>t(n.result),n.onerror=()=>r(n.error)}catch(e){r(e)}})}executeWriteOperation(e){return new Promise((t,r)=>{try{const s=this.databaseManager.getWriteTransaction().objectStore(this.databaseManager.storeName),n=e(s);n.onsuccess=()=>t(n.result),n.onerror=()=>r(n.error)}catch(e){r(e)}})}deserializeItems(e){return e.map(e=>this.deserializeItem(e))}deserializeItem(e){const t=this.serializationManager.deserialize(e.items),r=this.serializationManager.getData(t,[]);return{...e,items:r,deserializationError:t.error}}}class h{constructor(e,t){this.storageManager=e,this.config=t}async retryFailedItems(e,t){if(this.storageManager)try{const r=await this.storageManager.retrieve();for(const s of r)if(s.retryCount<this.config.maxRetries){let r;try{r="string"==typeof s.items?n.deserialize(s.items):s.items}catch(e){console.error("SyntropyFront: Error deserializing buffer items:",e),await this.removeFailedItem(s.id);continue}if(e)try{await e(r,s.retryCount+1,s.id),t?await t(s.id):await this.removeFailedItem(s.id),console.log(`SyntropyFront: Retry successful for item ${s.id}`)}catch(e){console.warn(`SyntropyFront: Retry failed for item ${s.id}:`,e),await this.incrementRetryCount(s.id)}}else console.warn(`SyntropyFront: Item ${s.id} exceeded maximum retries, removing from buffer`),await this.removeFailedItem(s.id)}catch(e){console.error("SyntropyFront: Error processing retries:",e)}else console.warn("SyntropyFront: Storage manager not available")}async incrementRetryCount(e){try{const t=await this.storageManager.retrieveById(e);t&&await this.storageManager.update(e,{retryCount:t.retryCount+1})}catch(e){console.error("SyntropyFront: Error incrementing retry count:",e)}}async removeFailedItem(e){try{await this.storageManager.remove(e)}catch(e){console.error("SyntropyFront: Error removing failed item:",e)}}async cleanupExpiredItems(){try{const e=(await this.storageManager.retrieve()).filter(e=>e.retryCount>=this.config.maxRetries);for(const t of e)await this.removeFailedItem(t.id),console.warn(`SyntropyFront: Item ${t.id} removed for exceeding maximum retries`);e.length>0&&console.log(`SyntropyFront: Cleanup completed, ${e.length} items removed`)}catch(e){console.error("SyntropyFront: Error cleaning up expired items:",e)}}async getRetryStats(){try{const e=await this.storageManager.retrieve(),t={totalItems:e.length,itemsByRetryCount:{},averageRetryCount:0};if(e.length>0){const r=e.reduce((e,t)=>e+t.retryCount,0);t.averageRetryCount=r/e.length,e.forEach(e=>{const r=e.retryCount;t.itemsByRetryCount[r]=(t.itemsByRetryCount[r]||0)+1})}return t}catch(e){return console.error("SyntropyFront: Error getting retry statistics:",e),{totalItems:0,itemsByRetryCount:{},averageRetryCount:0}}}}const g={credit_card:(e,t)=>{const r=e.replace(/\D/g,"");return t.preserveLength?e.replace(/\d/g,(s,n)=>e.substring(0,n).replace(/\D/g,"").length<r.length-4?t.maskChar:s):`${t.maskChar.repeat(4)}-${t.maskChar.repeat(4)}-${t.maskChar.repeat(4)}-${r.slice(-4)}`},ssn:(e,t)=>{const r=e.replace(/\D/g,"");return t.preserveLength?e.replace(/\d/g,(s,n)=>e.substring(0,n).replace(/\D/g,"").length<r.length-4?t.maskChar:s):`***-**-${r.slice(-4)}`},email:(e,t)=>{const r=e.indexOf("@");if(r<=0)return g.default(e,t);const s=e.substring(0,r),n=e.substring(r);if(t.preserveLength){return(s.length>1?s.charAt(0)+t.maskChar.repeat(s.length-1):t.maskChar.repeat(s.length))+n}return`${s.charAt(0)}***${n}`},phone:(e,t)=>{const r=e.replace(/\D/g,"");return t.preserveLength?e.replace(/\d/g,(s,n)=>e.substring(0,n).replace(/\D/g,"").length<r.length-4?t.maskChar:s):`${t.maskChar.repeat(3)}-${t.maskChar.repeat(3)}-${r.slice(-4)}`},secret:(e,t)=>t.preserveLength?t.maskChar.repeat(e.length):t.maskChar.repeat(8),custom:(e,t)=>"function"==typeof t.customMask?t.customMask(e):e,default:(e,t)=>t.preserveLength?t.maskChar.repeat(e.length):t.maskChar.repeat(Math.min(e.length,8))};g.password=g.secret,g.token=g.secret;const d="credit_card",m="ssn",y="email",p="phone",f="password";const b=new class{constructor(e={}){this.maskChar=e.maskChar||"*",this.preserveLength=!1!==e.preserveLength,this.rules=[],this.strategies=new Map(Object.entries(g)),this.ansiRegex=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,!1!==e.enableDefaultRules&&this.addDefaultRules(),e.rules&&e.rules.forEach(e=>this.addRule(e))}addDefaultRules(){[{pattern:/credit_card|card_number|payment_number/i,strategy:d},{pattern:/ssn|social_security|security_number/i,strategy:m},{pattern:/email/i,strategy:y},{pattern:/phone|phone_number|mobile_number/i,strategy:p},{pattern:/password|pass|pwd|secret|api_key|token|auth_token|jwt|bearer/i,strategy:f}].forEach(e=>this.addRule(e))}addRule(e){this.rules.push({...e,_compiledPattern:"string"==typeof e.pattern?new RegExp(e.pattern,"i"):e.pattern,preserveLength:e.preserveLength??this.preserveLength,maskChar:e.maskChar??this.maskChar})}registerStrategy(e,t){"function"==typeof t&&this.strategies.set(e,t)}process(e){if(null==e)return e;return({string:e=>e.replace(this.ansiRegex,""),object:e=>Array.isArray(e)?e.map(e=>this.process(e)):e&&e.constructor===Object?this.maskObject(e):e}[typeof e]||(e=>e))(e)}maskObject(e){return Object.entries(e).reduce((e,[t,r])=>(e[t]=this.maskValue(t,r),e),{})}maskValue(e,t){if("string"!=typeof t)return this.process(t);const r=this.rules.find(t=>t._compiledPattern?.test(e));return r?this.applyStrategy(t,r):t.replace(this.ansiRegex,"")}applyStrategy(e,t){return(this.strategies.get(t.strategy)||this.strategies.get("default"))(e,t)}};class w{constructor(e={}){this.serializer=e.serializer??n,this.masking=e.masking??b}serialize(e){try{if(null==e)return{success:!0,data:this.serializer.serialize([]),error:null,timestamp:(new Date).toISOString()};const t=this.masking.process(e);return{success:!0,data:this.serializer.serialize(t),error:null,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,data:this.createFallbackData(e),error:this.createSerializationError(e),timestamp:(new Date).toISOString()}}}deserialize(e){try{if(!e)return{success:!0,data:[],error:null,timestamp:(new Date).toISOString()};return{success:!0,data:this.serializer.deserialize(e),error:null,timestamp:(new Date).toISOString()}}catch(e){return{success:!1,data:[],error:this.createDeserializationError(e),timestamp:(new Date).toISOString()}}}createSerializationError(e){return{type:"serialization_error",message:e.message,originalError:e,timestamp:(new Date).toISOString()}}createDeserializationError(e){return{type:"deserialization_error",message:e.message,originalError:e,timestamp:(new Date).toISOString()}}createFallbackData(e){const t={__serializationError:!0,error:e.message,timestamp:(new Date).toISOString(),fallbackData:"Items not serializable - using fallback"};return JSON.stringify(t)}isSuccessful(e){return Boolean(e&&!0===e.success)}getData(e,t=null){return this.isSuccessful(e)?e.data:t}}class S{constructor(e,t={}){this.config=e,this.usePersistentBuffer=!1,this.databaseManager=t.databaseManager??new l("SyntropyFrontBuffer",1,"failedItems"),this.serializationManager=t.serializationManager??new w,this.storageManager=t.storageManager??new u(this.databaseManager,this.serializationManager),this.retryLogicManager=t.retryLogicManager??new h(this.storageManager,this.config),this.initPersistentBuffer()}async initPersistentBuffer(){try{await this.databaseManager.init()&&(this.usePersistentBuffer=this.config.usePersistentBuffer,console.log("SyntropyFront: Persistent buffer initialized"))}catch(e){console.warn("SyntropyFront: Error initializing persistent buffer:",e)}}async save(e){if(this.usePersistentBuffer)try{await this.storageManager.save(e),console.log("SyntropyFront: Items saved to persistent buffer")}catch(e){console.error("SyntropyFront: Error saving to persistent buffer:",e)}}async retrieve(){if(!this.usePersistentBuffer)return[];try{return await this.storageManager.retrieve()}catch(e){return console.error("SyntropyFront: Error retrieving from persistent buffer:",e),[]}}async remove(e){if(this.usePersistentBuffer)try{await this.storageManager.remove(e)}catch(e){console.error("SyntropyFront: Error removing from persistent buffer:",e)}}async retryFailedItems(e,t){this.usePersistentBuffer&&await this.retryLogicManager.retryFailedItems(e,t)}async cleanupExpiredItems(){this.usePersistentBuffer&&await this.retryLogicManager.cleanupExpiredItems()}async getStats(){if(!this.usePersistentBuffer)return{totalItems:0,itemsByRetryCount:{},averageRetryCount:0,isAvailable:!1};try{return{...await this.retryLogicManager.getRetryStats(),isAvailable:this.isAvailable()}}catch(e){return console.error("SyntropyFront: Error getting statistics:",e),{totalItems:0,itemsByRetryCount:{},averageRetryCount:0,isAvailable:this.isAvailable()}}}isAvailable(){return this.usePersistentBuffer&&this.databaseManager.isDatabaseAvailable()}async clear(){if(this.usePersistentBuffer)try{await this.storageManager.clear(),console.log("SyntropyFront: Persistent buffer cleared")}catch(e){console.error("SyntropyFront: Error clearing persistent buffer:",e)}}close(){this.databaseManager.close(),this.usePersistentBuffer=!1}}const v=new class{constructor(e={}){this.config=e.config||new t,this.masking=e.masking||b,this.queue=e.queue||new r(this.config),this.retry=e.retry||new s(this.config),this.transport=e.transport||new i(this.config),this.buffer=e.buffer||new S(this.config),this.setupCallbacks()}setupCallbacks(){this.queue.flushCallback=async e=>{try{await this.transport.send(e),console.log("SyntropyFront: Data sent successfully")}catch(t){console.error("SyntropyFront Agent: Error sending data:",t),this.retry.addToRetryQueue(e),await this.buffer.save(e)}},this.retry.sendCallback=async e=>await this.transport.send(e),this.retry.removePersistentCallback=async e=>{await this.buffer.remove(e)},this.buffer.sendCallback=(e,t,r)=>{this.retry.addToRetryQueue(e,t,r)}}configure(e){this.config.configure(e)}sendError(e,t=null){if(!this.config.isAgentEnabled())return void console.warn("SyntropyFront Agent: Not configured, error not sent");if(Math.random()>this.config.samplingRate)return;const r=t?{...e,context:t}:e,s=this.transport.applyEncryption(r),n=this.masking.process(s);this.queue.add({type:"error",data:n,timestamp:(new Date).toISOString()})}sendBreadcrumbs(e){if(!this.config.isAgentEnabled()||!this.config.shouldSendBreadcrumbs()||!e.length)return;if(Math.random()>this.config.samplingRate)return;const t=this.transport.applyEncryption(e),r=this.masking.process(t);this.queue.add({type:"breadcrumbs",data:r,timestamp:(new Date).toISOString()})}addToQueue(e){this.queue.add(e)}addToRetryQueue(e,t=1,r=null){this.retry.addToRetryQueue(e,t,r)}async processRetryQueue(){await this.retry.processRetryQueue(this.retry.sendCallback,this.retry.removePersistentCallback)}async flush(){await this.queue.flush(this.queue.flushCallback)}async forceFlush(){await this.flush(),this.retry.isEmpty()||(console.log("SyntropyFront: Attempting to send pending retries..."),await this.processRetryQueue())}getStats(){const e=this.config.getConfig();return{queueLength:this.queue.getSize(),retryQueueLength:this.retry.getSize(),isEnabled:this.config.isAgentEnabled(),usePersistentBuffer:e.usePersistentBuffer,maxRetries:e.maxRetries}}async retryFailedItems(){await this.buffer.retryFailedItems(this.buffer.sendCallback)}isEnabled(){return this.config.isAgentEnabled()}shouldSendBreadcrumbs(){return this.config.shouldSendBreadcrumbs()}disable(){this.config.configure({endpoint:null}),this.queue.clear(),this.retry.clear()}},I={isBrowser:()=>"undefined"!=typeof window&&"undefined"!=typeof document,getGlobal:()=>"undefined"!=typeof window?window:{},hasApi:e=>null!==e.split(".").reduce((e,t)=>null==e?null:void 0!==e[t]?e[t]:null,I.getGlobal()),runIf:(e,t,r=null)=>("function"==typeof e?e():I.hasApi(e))?t():r},E={INTERACTIVE_SELECTOR:["a","button","input","select","textarea","label","summary",'[role="button"]','[role="link"]','[role="checkbox"]','[role="radio"]','[role="menuitem"]','[role="option"]','[role="switch"]','[role="tab"]',".interactive",".btn",".clickable","[onclick]","[ng-click]","[v-on:click]"].join(", "),hasPointerCursor:e=>{try{return"pointer"===window.getComputedStyle(e).cursor}catch(e){return!1}},findTargetByStyle:e=>e&&1===e.nodeType?E.hasPointerCursor(e)?e:e.parentElement&&e.parentElement!==document.body?E.findTargetByStyle(e.parentElement):null:null,findInteractiveTarget:e=>{if(!e||e===document.body||1!==e.nodeType)return null;try{const t=e.closest(E.INTERACTIVE_SELECTOR);if(t)return t}catch(e){}return E.findTargetByStyle(e)},generateSelector:e=>{if(!e)return"unknown";return`${e.tagName.toLowerCase()}${e.id?`#${e.id}`:""}${"string"==typeof e.className&&e.className?`.${e.className.split(" ").filter(Boolean).join(".")}`:""}`}};class k{constructor(){this.handler=null,this.lastClickTime=0,this.THROTTLE_MS=500}init(){I.isBrowser()&&(this.handler=e=>this.processClick(e),document.addEventListener("click",this.handler,!0))}processClick(e){const t=e?.target;if(!t||this.isThrottled())return;const r=E.findInteractiveTarget(t);r&&this.recordBreadcrumb(r)}isThrottled(){const e=Date.now(),t=e-this.lastClickTime<this.THROTTLE_MS;return t||(this.lastClickTime=e),t}recordBreadcrumb(t){const r=E.generateSelector(t);e.add({category:"ui",message:`User clicked on '${r}'`,data:{selector:r,tagName:t.tagName,id:t.id||null,className:t.className||null,text:(t.innerText||t.value||"").substring(0,30).trim()}})}destroy(){I.isBrowser()&&this.handler&&(document.removeEventListener("click",this.handler,!0),this.handler=null)}}const C=(e,t,r,s="original handler")=>{if("function"==typeof e)try{return e.apply(t,r)}catch(e){return void console.error(`SyntropyFront: Error in ${s}:`,e)}},R=(e,t,r)=>{if(!e||!(t in e))return null;const s=e[t],n=r(s);return e[t]=n,{target:e,property:t,original:s,wrapped:n,destroy:()=>{e[t]===n&&(e[t]=s)}}};class D{constructor(){this.wrapper=null}init(){"undefined"!=typeof window&&window.fetch&&(this.wrapper=R(window,"fetch",t=>(...r)=>{const s=r[0]instanceof Request?r[0].url:r[0]||"unknown",n=r[0]instanceof Request?r[0].method:r[1]?.method||"GET";return e.add({category:"network",message:`Request: ${n} ${s}`,data:{url:s,method:n,timestamp:Date.now()}}),t.apply(window,r)}))}destroy(){this.wrapper&&(this.wrapper.destroy(),this.wrapper=null)}}const z={device:{userAgent:()=>I.runIf("navigator.userAgent",()=>navigator.userAgent),language:()=>I.runIf("navigator.language",()=>navigator.language),languages:()=>I.runIf("navigator.languages",()=>navigator.languages),screen:()=>I.runIf("window.screen",()=>({width:window.screen.width,height:window.screen.height,availWidth:window.screen.availWidth,availHeight:window.screen.availHeight,colorDepth:window.screen.colorDepth,pixelDepth:window.screen.pixelDepth})),timezone:()=>I.runIf("Intl.DateTimeFormat",()=>{try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch(e){return null}}),cookieEnabled:()=>I.runIf("navigator.cookieEnabled",()=>navigator.cookieEnabled),doNotTrack:()=>I.runIf("navigator.doNotTrack",()=>navigator.doNotTrack)},window:{url:()=>I.runIf("window.location.href",()=>window.location.href),pathname:()=>I.runIf("window.location.pathname",()=>window.location.pathname),search:()=>I.runIf("window.location.search",()=>window.location.search),hash:()=>I.runIf("window.location.hash",()=>window.location.hash),referrer:()=>I.runIf("document.referrer",()=>document.referrer),title:()=>I.runIf("document.title",()=>document.title),viewport:()=>I.runIf("window.innerWidth",()=>({width:window.innerWidth,height:window.innerHeight}))},storage:{localStorage:()=>I.runIf("localStorage",()=>{try{const e=window.localStorage;return{keys:Object.keys(e).length,size:JSON.stringify(e).length,keyNames:Object.keys(e)}}catch(e){return null}}),sessionStorage:()=>I.runIf("sessionStorage",()=>{try{const e=window.sessionStorage;return{keys:Object.keys(e).length,size:JSON.stringify(e).length,keyNames:Object.keys(e)}}catch(e){return null}})},network:{online:()=>I.runIf("navigator.onLine",()=>navigator.onLine),connection:()=>I.runIf(()=>!("undefined"==typeof navigator||!(navigator.connection||navigator.mozConnection||navigator.webkitConnection)),()=>{const e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{effectiveType:e.effectiveType,downlink:e.downlink,rtt:e.rtt}})},ui:{focused:()=>I.runIf("document.hasFocus",()=>document.hasFocus()),visibility:()=>I.runIf("document.visibilityState",()=>document.visibilityState),activeElement:()=>I.runIf("document.activeElement",()=>({tagName:document.activeElement.tagName,id:document.activeElement.id,className:document.activeElement.className}))},performance:{memory:()=>I.runIf("performance.memory",()=>({used:Math.round(performance.memory.usedJSHeapSize/1048576),total:Math.round(performance.memory.totalJSHeapSize/1048576),limit:Math.round(performance.memory.jsHeapSizeLimit/1048576)})),timing:()=>I.runIf("performance.timing",()=>({navigationStart:performance.timing.navigationStart,loadEventEnd:performance.timing.loadEventEnd}))},session:{sessionId:e=>e.generateSessionId(),startTime:()=>(new Date).toISOString(),pageLoadTime:()=>I.runIf("performance.now",()=>performance.now())}},T={device:["userAgent","language","screen","timezone"],window:["url","viewport","title"],session:["sessionId","pageLoadTime"],ui:["visibility","activeElement"],network:["online","connection"]};const M=new class{constructor(){this.sessionId=null,this.providers=new Map(Object.entries(z))}collect(e={}){const t=this.normalizeConfig(e);return Object.entries(t).reduce((e,[t,r])=>{try{const s=this.providers.get(t);if(!1!==r&&!s)throw new Error(`Provider for '${t}' not found`);const n=this.resolveFields(t,s,r);n&&(e[t]=this.extractFields(s,n))}catch(r){console.warn(`SyntropyFront: Error collecting context for ${t}:`,r),e[t]={error:"Collection failed"}}return e},{})}resolveFields(e,t,r){const s=()=>Object.keys(t||{}),n={boolean:t=>t?T[e]||s():null,object:e=>Array.isArray(e)?e:s()}[typeof r];return n?n(r):null}normalizeConfig(e){return Array.isArray(e)?e.reduce((e,t)=>({...e,[t]:!0}),{}):e||{}}extractFields(e,t){return t.reduce((t,r)=>{const s=e[r];if("function"!=typeof s)return t;try{t[r]=s(this)}catch(e){console.warn(`SyntropyFront: Error collecting field ${r}:`,e),t[r]=null}return t},{})}registerProvider(e,t){this.providers.set(e,t)}generateSessionId(){return this.sessionId=this.sessionId||`session_${this.generateSecureId()}`,this.sessionId}generateSecureId(e=("undefined"!=typeof crypto?crypto:null)){return((e=("undefined"!=typeof crypto?crypto:null))=>{if("function"==typeof e?.randomUUID)return e.randomUUID();if("function"==typeof e?.getRandomValues){const t=new Uint8Array(16);return e.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}return`${Date.now()}_${Math.random().toString(36).substring(2,9)}`})(e)}getAvailableTypes(){return Array.from(this.providers.keys())}get allFields(){return Array.from(this.providers.entries()).reduce((e,[t,r])=>(e[t]=r,e),{})}get defaultContexts(){return this.allFields}},O=(t,r,s,n,i)=>({type:"uncaught_exception",error:{message:t,source:r,lineno:s,colno:n,stack:i?.stack},breadcrumbs:e.getAll(),timestamp:(new Date).toISOString()}),A=t=>({type:"unhandled_rejection",error:{message:t.reason?.message||"Promise rejection without message",stack:t.reason?.stack},breadcrumbs:e.getAll(),timestamp:(new Date).toISOString()});class _{constructor(){this.errorWrapper=null,this.rejectionWrapper=null,this.config={captureErrors:!0,captureUnhandledRejections:!0},this.contextTypes=[],this.onErrorCallback=null}configure(e,t,r){this.config={...this.config,...e},this.contextTypes=t||[],this.onErrorCallback=r}init(){I.isBrowser()&&(this.setupExceptionCapture(),this.setupRejectionCapture())}setupExceptionCapture(){this.config.captureErrors&&(this.errorWrapper=R(window,"onerror",e=>(t,r,s,n,i)=>{const a=O(t,r,s,n,i);return this.handleError(a),C(e,window,[t,r,s,n,i],"original window.onerror")}))}setupRejectionCapture(){this.config.captureUnhandledRejections&&(this.rejectionWrapper=R(window,"onunhandledrejection",e=>t=>{const r=A(t);this.handleError(r),C(e,window,[t],"original window.onunhandledrejection")}))}handleError(e){const t=this.contextTypes.length>0?M.collect(this.contextTypes):null;v.sendError(e,t),this.onErrorCallback&&this.onErrorCallback(e)}destroy(){this.errorWrapper?.destroy(),this.rejectionWrapper?.destroy(),this.errorWrapper=null,this.rejectionWrapper=null}}const x=new class{constructor(){this.isInitialized=!1,this.config={captureClicks:!0,captureFetch:!0,captureErrors:!0,captureUnhandledRejections:!0},this.registry=new Map,this.initializeRegistry()}initializeRegistry(){this.registry.set("clicks",new k),this.registry.set("fetch",new D),this.registry.set("errors",new _)}configure(e={}){this.config={...this.config,...e},this.registry.get("errors")?.configure?.(this.config,e.context||[],e.onError)}init(){this.isInitialized||(this.runLifecycle("init"),this.isInitialized=!0,console.log("SyntropyFront: Interceptors initialized (Refactored architecture)"))}destroy(){this.isInitialized&&(this.runLifecycle("destroy"),this.isInitialized=!1,console.log("SyntropyFront: Interceptors destroyed"))}runLifecycle(e){[{key:"clicks",enabled:this.config.captureClicks},{key:"fetch",enabled:this.config.captureFetch},{key:"errors",enabled:this.config.captureErrors||this.config.captureUnhandledRejections}].filter(e=>e.enabled).map(e=>this.registry.get(e.key)).filter(t=>t&&"function"==typeof t[e]).forEach(t=>t[e]())}get clickInterceptor(){return this.registry.get("clicks")}get fetchInterceptor(){return this.registry.get("fetch")}get errorInterceptor(){return this.registry.get("errors")}};return new class{constructor(){this.isActive=!1,this.config={maxEvents:50,endpoint:null,headers:{},usePersistentBuffer:!0,captureClicks:!0,captureFetch:!0,captureErrors:!0,captureUnhandledRejections:!0,samplingRate:1,onError:null},this.init()}init(){this.isActive||(this._applyConfig(),x.init(),v.retryFailedItems().catch(e=>{console.warn("SyntropyFront: Error attempting to recover persistent items:",e)}),this.isActive=!0,console.log("🚀 SyntropyFront: Initialized with modular resilient architecture"))}_applyConfig(){v.configure({endpoint:this.config.endpoint,headers:this.config.headers,usePersistentBuffer:this.config.usePersistentBuffer,samplingRate:this.config.samplingRate,batchTimeout:this.config.batchTimeout??(this.config.captureClicks||this.config.captureFetch?5e3:null)}),e.onBreadcrumbAdded=e=>{v.isEnabled()&&v.shouldSendBreadcrumbs()&&v.sendBreadcrumbs([e])},x.configure({captureClicks:this.config.captureClicks,captureFetch:this.config.captureFetch,captureErrors:this.config.captureErrors,captureUnhandledRejections:this.config.captureUnhandledRejections,onError:this.config.onError})}configure(e={}){this.config={...this.config,...e},e.fetch&&(this.config.endpoint=e.fetch.url,this.config.headers=e.fetch.options?.headers||{}),this._applyConfig();const t=this.config.endpoint?`endpoint: ${this.config.endpoint}`:"console only";console.log(`✅ SyntropyFront: Configured - ${t}`)}addBreadcrumb(t,r,s={}){return e.add({category:t,message:r,data:s})}getBreadcrumbs(){return e.getAll()}clearBreadcrumbs(){e.clear()}sendError(e,t={}){const r={type:"manual_error",error:{message:e.message||String(e),name:e.name||"Error",stack:e.stack},breadcrumbs:this.getBreadcrumbs(),timestamp:(new Date).toISOString()};return v.sendError(r,t),r}async flush(){await v.forceFlush()}getStats(){return{isActive:this.isActive,breadcrumbs:e.count(),agent:v.getStats(),config:{...this.config}}}destroy(){x.destroy(),v.disable(),this.isActive=!1,console.log("SyntropyFront: Deactivated")}}}();
|
|
2
2
|
//# sourceMappingURL=index.min.js.map
|