Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@exceptionless/core

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@exceptionless/core - npm Package Compare versions

Comparing version 3.0.5 to 3.1.0

205

dist/configuration/Configuration.js

@@ -15,89 +15,2 @@ import { DefaultLastReferenceIdManager } from "../lastReferenceIdManager/DefaultLastReferenceIdManager.js";

constructor() {
/**
* A default list of tags that will automatically be added to every
* report submitted to the server.
*/
this.defaultTags = [];
/**
* A default list of of extended data objects that will automatically
* be added to every report submitted to the server.
*/
this.defaultData = {};
/**
* Whether the client is currently enabled or not. If it is disabled,
* submitted errors will be discarded and no data will be sent to the server.
*
* @returns {boolean}
*/
this.enabled = true;
/**
* Maximum number of events that should be sent to the server together in a batch. (Defaults to 50)
*/
this.submissionBatchSize = 50;
/**
* Contains a dictionary of custom settings that can be used to control
* the client and will be automatically updated from the server.
*/
this.settings = {};
this.settingsVersion = 0;
/**
* The API key that will be used when sending events to the server.
*/
this.apiKey = "";
/**
* The server url that all events will be sent to.
* @type {string}
*/
this._serverUrl = "https://collector.exceptionless.io";
/**
* The config server url that all configuration will be retrieved from.
*/
this.configServerUrl = "https://config.exceptionless.io";
/**
* The heartbeat server url that all heartbeats will be sent to.
*/
this.heartbeatServerUrl = "https://heartbeat.exceptionless.io";
/**
* How often the client should check for updated server settings when idle. The default is every 2 minutes.
*/
this._updateSettingsWhenIdleInterval = 120000;
/**
* A list of exclusion patterns.
*/
this._dataExclusions = [];
this._includePrivateInformation = true;
this._includeUserName = true;
this._includeMachineName = true;
this._includeIpAddress = true;
this._includeHeaders = true;
this._includeCookies = true;
this._includePostData = true;
this._includeQueryString = true;
/**
* A list of user agent patterns.
*/
this._userAgentBotPatterns = [];
/**
* The list of plugins that will be used in this configuration.
*/
this._plugins = [];
/**
* A list of subscribers that will be fired when configuration changes.
*/
this._subscribers = [];
/**
* Writes events to storage on enqueue and removes them when submitted. (Defaults to false)
* This setting only works in environments that supports persisted storage.
* There is also a performance penalty of extra IO/serialization.
*/
this.usePersistedQueueStorage = false;
/**
* Gets or sets a value indicating whether to automatically send session start,
* session heartbeats and session end events.
*/
this.sessionsEnabled = false;
/**
* Internal property used to track the current session identifier.
*/
this.currentSessionIdentifier = null;
this.services = {

@@ -108,3 +21,3 @@ lastReferenceIdManager: new DefaultLastReferenceIdManager(),

queue: new DefaultEventQueue(this),
submissionClient: new DefaultSubmissionClient(this),
submissionClient: new DefaultSubmissionClient(this)
};

@@ -114,2 +27,75 @@ EventPluginManager.addDefaultPlugins(this);

/**
* A default list of tags that will automatically be added to every
* report submitted to the server.
*/
defaultTags = [];
/**
* A default list of of extended data objects that will automatically
* be added to every report submitted to the server.
*/
defaultData = {};
/**
* Whether the client is currently enabled or not. If it is disabled,
* submitted errors will be discarded and no data will be sent to the server.
*
* @returns {boolean}
*/
enabled = true;
services;
/**
* Maximum number of events that should be sent to the server together in a batch. (Defaults to 50)
*/
submissionBatchSize = 50;
/**
* Contains a dictionary of custom settings that can be used to control
* the client and will be automatically updated from the server.
*/
settings = {};
settingsVersion = 0;
/**
* The API key that will be used when sending events to the server.
*/
apiKey = "";
/**
* The server url that all events will be sent to.
* @type {string}
*/
_serverUrl = "https://collector.exceptionless.io";
/**
* The config server url that all configuration will be retrieved from.
*/
configServerUrl = "https://config.exceptionless.io";
/**
* The heartbeat server url that all heartbeats will be sent to.
*/
heartbeatServerUrl = "https://heartbeat.exceptionless.io";
/**
* How often the client should check for updated server settings when idle. The default is every 2 minutes.
*/
_updateSettingsWhenIdleInterval = 120000;
/**
* A list of exclusion patterns.
*/
_dataExclusions = [];
_includePrivateInformation = true;
_includeUserName = true;
_includeMachineName = true;
_includeIpAddress = true;
_includeHeaders = true;
_includeCookies = true;
_includePostData = true;
_includeQueryString = true;
/**
* A list of user agent patterns.
*/
_userAgentBotPatterns = [];
/**
* The list of plugins that will be used in this configuration.
*/
_plugins = [];
/**
* A list of subscribers that will be fired when configuration changes.
*/
_subscribers = [];
/**
* Returns true if the apiKey is valid.

@@ -167,3 +153,3 @@ */

const exclusions = this.settings["@@DataExclusions"];
return this._dataExclusions.concat(exclusions && exclusions.split(",") || []);
return this._dataExclusions.concat((exclusions && exclusions.split(",")) || []);
}

@@ -300,3 +286,3 @@ /**

const patterns = this.settings["@@UserAgentBotPatterns"];
return this._userAgentBotPatterns.concat(patterns && patterns.split(",") || []);
return this._userAgentBotPatterns.concat((patterns && patterns.split(",")) || []);
}

@@ -309,6 +295,3 @@ /**

addUserAgentBotPatterns(...userAgentBotPatterns) {
this._userAgentBotPatterns = [
...this._userAgentBotPatterns,
...userAgentBotPatterns,
];
this._userAgentBotPatterns = [...this._userAgentBotPatterns, ...userAgentBotPatterns];
}

@@ -336,5 +319,3 @@ /**

addPlugin(pluginOrName, priority, pluginAction) {
const plugin = pluginAction
? { name: pluginOrName, priority, run: pluginAction }
: pluginOrName;
const plugin = pluginAction ? { name: pluginOrName, priority, run: pluginAction } : pluginOrName;
if (!plugin || !(plugin.startup || plugin.run)) {

@@ -350,3 +331,3 @@ this.services.log.error("Add plugin failed: startup or run method not defined");

}
if (!this._plugins.find(f => f.name === plugin.name)) {
if (!this._plugins.find((f) => f.name === plugin.name)) {
this._plugins.push(plugin);

@@ -359,5 +340,3 @@ }

removePlugin(pluginOrName) {
const name = typeof pluginOrName === "string"
? pluginOrName
: pluginOrName.name || "";
const name = typeof pluginOrName === "string" ? pluginOrName : pluginOrName.name || "";
if (!name) {

@@ -393,5 +372,3 @@ this.services.log.error("Remove plugin failed: Plugin name not defined");

setUserIdentity(userInfoOrIdentity, name) {
const userInfo = typeof userInfoOrIdentity !== "string"
? userInfoOrIdentity
: { identity: userInfoOrIdentity, name };
const userInfo = typeof userInfoOrIdentity !== "string" ? userInfoOrIdentity : { identity: userInfoOrIdentity, name };
const shouldRemove = !userInfo || (!userInfo.identity && !userInfo.name);

@@ -410,3 +387,3 @@ if (shouldRemove) {

get userAgent() {
return "exceptionless-js/3.0.5";
return "exceptionless-js/3.1.0";
}

@@ -422,2 +399,17 @@ /**

/**
* Writes events to storage on enqueue and removes them when submitted. (Defaults to false)
* This setting only works in environments that supports persisted storage.
* There is also a performance penalty of extra IO/serialization.
*/
usePersistedQueueStorage = false;
/**
* Gets or sets a value indicating whether to automatically send session start,
* session heartbeats and session end events.
*/
sessionsEnabled = false;
/**
* Internal property used to track the current session identifier.
*/
currentSessionIdentifier = null;
/**
*

@@ -441,2 +433,3 @@ * @param sendHeartbeats Controls whether heartbeat events are sent on an interval.

}
originalSettings;
applyServerSettings(serverSettings) {

@@ -464,3 +457,3 @@ if (!this.originalSettings) {

catch (ex) {
this.services.log.error(`Error calling subscribe handler: ${ex instanceof Error ? ex.message : ex + ''}`);
this.services.log.error(`Error calling subscribe handler: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -467,0 +460,0 @@ }

export class ServerSettings {
settings;
version;
constructor(settings, version) {

@@ -8,2 +10,4 @@ this.settings = settings;

export class SettingsManager {
static SettingsKey = "settings";
static _isUpdatingSettings = false;
static async applySavedServerSettings(config) {

@@ -46,3 +50,3 @@ if (!config?.isValid) {

catch (ex) {
log.error(`Error updating settings: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error updating settings: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -57,6 +61,6 @@ finally {

const settings = await storage.getItem(SettingsManager.SettingsKey);
return settings && JSON.parse(settings) || new ServerSettings({}, 0);
return (settings && JSON.parse(settings)) || new ServerSettings({}, 0);
}
catch (ex) {
log.error(`Error getting saved settings: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error getting saved settings: ${ex instanceof Error ? ex.message : ex + ""}`);
return new ServerSettings({}, 0);

@@ -66,4 +70,2 @@ }

}
SettingsManager.SettingsKey = "settings";
SettingsManager._isUpdatingSettings = false;
//# sourceMappingURL=SettingsManager.js.map

@@ -5,4 +5,7 @@ import { KnownEventDataKeys } from "./models/Event.js";

export class EventBuilder {
target;
client;
context;
_validIdentifierErrorMessage = "must contain between 8 and 100 alphanumeric or '-' characters.";
constructor(event, client, context) {
this._validIdentifierErrorMessage = "must contain between 8 and 100 alphanumeric or '-' characters.";
this.target = event;

@@ -63,5 +66,3 @@ this.client = client;

setUserIdentity(userInfoOrIdentity, name) {
const userInfo = typeof userInfoOrIdentity !== "string"
? userInfoOrIdentity
: { identity: userInfoOrIdentity, name };
const userInfo = typeof userInfoOrIdentity !== "string" ? userInfoOrIdentity : { identity: userInfoOrIdentity, name };
if (!userInfo || (!userInfo.identity && !userInfo.name)) {

@@ -83,3 +84,3 @@ return this;

email_address: emailAddress,
description,
description
});

@@ -128,3 +129,3 @@ }

addTags(...tags) {
this.target.tags = [...this.target.tags || [], ...tags];
this.target.tags = [...(this.target.tags || []), ...tags];
return this;

@@ -141,3 +142,3 @@ }

setProperty(name, value, maxDepth, excludedPropertyNames) {
if (!name || (value === undefined || value == null)) {
if (!name || value === undefined || value == null) {
return this;

@@ -177,5 +178,4 @@ }

const code = value.charCodeAt(index);
const isDigit = (code >= 48) && (code <= 57);
const isLetter = ((code >= 65) && (code <= 90)) ||
((code >= 97) && (code <= 122));
const isDigit = code >= 48 && code <= 57;
const isLetter = (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
const isMinus = code === 45;

@@ -182,0 +182,0 @@ if (!(isDigit || isLetter) && !isMinus) {

@@ -11,5 +11,8 @@ import { Configuration } from "./configuration/Configuration.js";

export class ExceptionlessClient {
config;
_intervalId;
_timeoutId;
_initialized = false;
constructor(config = new Configuration()) {
this.config = config;
this._initialized = false;
}

@@ -110,4 +113,3 @@ /** Resume background submission, resume any timers. */

if (level) {
builder = builder.setSource(sourceOrMessage).setMessage(message)
.setProperty(KnownEventDataKeys.Level, level);
builder = builder.setSource(sourceOrMessage).setMessage(message).setProperty(KnownEventDataKeys.Level, level);
}

@@ -125,3 +127,3 @@ else if (message) {

catch (ex) {
this.config.services.log.trace(`Unable to resolve log source: ${ex instanceof Error ? ex.message : ex + ''}`);
this.config.services.log.trace(`Unable to resolve log source: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -128,0 +130,0 @@ }

@@ -1,2 +0,2 @@

var S=class{constructor(){this._lastReferenceId=null}getLast(){return this._lastReferenceId}clearLast(){this._lastReferenceId=null}setLast(e){this._lastReferenceId=e}};var x=class{trace(e){this.log("debug",e)}info(e){this.log("info",e)}warn(e){this.log("warn",e)}error(e){this.log("error",e)}log(e,t){if(console){let i=`Exceptionless:${new Date().toISOString()} [${e}] ${t}`,r=console[e];r?r(i):console.log&&console.log(i)}}};var _=class{trace(e){}info(e){}warn(e){}error(e){}};var G=(c=>(c.Error="@error",c.SimpleError="@simple_error",c.RequestInfo="@request",c.TraceLog="@trace",c.EnvironmentInfo="@environment",c.UserInfo="@user",c.UserDescription="@user_description",c.Version="@version",c.Level="@level",c.SubmissionMethod="@submission_method",c.ManualStackingInfo="@stack",c))(G||{});function F(s){if(!s||s.length===0)return 0;let e=0;for(let t=0;t<s.length;t++){let i=s.charCodeAt(t);e=(e<<5)-e+i,e|=0}return e}function te(s,e){let t={},i=(s||"").split("; ");for(let r of i){let n=r.split("=");y(n[0],e||[])||(t[n[0]]=n[1])}return d(t)?null:t}function b(){function s(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}return s()+s()+"-"+s()+"-"+s()+"-"+s()+"-"+s()+s()+s()}function ie(s){if(!s)return null;let t=/(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?)/.exec(s);return t&&t.length>0?t[0]:null}function re(s,e){if(!s||s.length===0)return{};let t=s.split("&");if(t.length===0)return{};let i={};for(let r of t){let n=r.split("=");(!e||!y(n[0],e))&&(i[decodeURIComponent(n[0])]=decodeURIComponent(n[1]))}return d(i)?{}:i}function ne(){return Math.floor(Math.random()*9007199254740992)}function y(s,e,t=!0){if(typeof s!="string")return!1;let i=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;return s=(t?s.toLowerCase():s).replace(i,""),(e||[]).some(r=>{if(typeof r!="string")return!1;if(r&&(r=(t?r.toLowerCase():r).replace(i,"")),!r)return s==null;if(r==="*")return!0;if(s==null)return!1;let n=r[0]==="*";n&&(r=r.slice(1));let o=r[r.length-1]==="*";return o&&(r=r.substring(0,r.length-1)),n&&o?r.length<=s.length&&s.indexOf(r,0)!==-1:n?Z(s,r):o?V(s,r):s===r})}function d(s){if(s==null)return!0;if(typeof s=="object")return Array.isArray(s)?s.length===0:s instanceof Date?!1:Object.getOwnPropertyNames(s).length===0;if(typeof s=="string"){let e=s.trim();return e.length===0||e==="{}"||e==="[]"}return!1}function V(s,e){return s.substring(0,e.length)===e}function Z(s,e){return s.indexOf(e,s.length-e.length)!==-1}function X(s,e=10){function t(n){if(n==null)return!1;switch(typeof n){case"function":return!0;case"object":switch(Object.prototype.toString.call(n)){case"[object AsyncGenerator]":case"[object Generator]":case"[object ArrayBuffer]":case"[object Buffer]":case"[object DataView]":case"[object Promise]":case"[object WeakMap]":case"[object WeakSet]":return!0}if("writeBigInt64LE"in n)return!0;break}return!1}function i(n){function o(a){return a!==null&&typeof a=="object"&&typeof a.toJSON=="function"}if(typeof n=="bigint")return`${n.toString()}n`;if(typeof n=="object"){if(Array.isArray(n)||n instanceof Date)return n;if(n instanceof Map){let l={};for(let[g,u]of n)l[g]=u;return l}if(n instanceof RegExp)return n.toString();if(n instanceof Set)return Array.from(n);let a=Object.getPrototypeOf(Uint8Array);return n instanceof a?Array.from(n):o(n)?i(n.toJSON()):n}return typeof n=="symbol"?n.description:n}function r(n,o,a=10,l=new WeakSet,g=!1){if(n==null)return n;if(a>o||t(n))return;let u=i(n);if(typeof u=="object"){if(a==o)return;if(Array.isArray(u)){let E=g?a+1:a;return u.map(K=>r(K,o,E,l,!0))}if(u instanceof Date)return u;if(Object.prototype.toString.call(u)==="[object Object]"){if(l.has(u))return;l.add(u)}let c=new Set([...Object.getOwnPropertyNames(u),...Object.getOwnPropertySymbols(u)]);for(let E in u)c.add(E);let z={};for(let E of c){let K=i(E),ee=u[E];z[K]=r(ee,o,a+1,l)}return z}return u}if(!(e<0))return r(s,e,0)}function h(s,e,t=10){function i(n,o){return JSON.stringify(n,(a,l)=>{if(!y(a,o))return l})}if(s===void 0)return s;let r=X(s,t);return i(r,e||[])}function W(s,e=!1){if(typeof s=="boolean")return s;if(s===null||typeof s!="number"&&typeof s!="string")return e;switch((s+"").toLowerCase().trim()){case"true":case"yes":case"1":return!0;case"false":case"no":case"0":case null:return!1}return e}function se(s,e="Unknown Error"){if(s==null){let i=new Error(e);return i.stack=void 0,i}if(s instanceof Error)return s;if(typeof s=="string"){let i=new Error(s);return i.stack=void 0,i}let t=new Error(h(s)||e);return t.stack=void 0,t}function f(s){typeof s=="object"&&"unref"in s&&s.unref()}var w=class{constructor(e=6e4){this.priority=100;this.name="HeartbeatPlugin";this._interval=e>=3e4?e:6e4}startup(){return clearInterval(this._intervalId),this._intervalId=void 0,Promise.resolve()}suspend(){return clearInterval(this._intervalId),this._intervalId=void 0,Promise.resolve()}run(e){if(this._interval<=0)return Promise.resolve();clearInterval(this._intervalId),this._intervalId=void 0;let{config:t}=e.client;if(!t.currentSessionIdentifier){let i=e.event.data?.["@user"];if(!i?.identity)return Promise.resolve();t.currentSessionIdentifier=i.identity}return t.currentSessionIdentifier&&(this._intervalId=setInterval(()=>void e.client.submitSessionHeartbeat(t.currentSessionIdentifier),this._interval),f(this._intervalId)),Promise.resolve()}};var C=class{constructor(){this.priority=25;this.name="SessionIdManagementPlugin"}run(e){let t=e.event,i=t.type==="session",{config:r}=e.client;return(i||!r.currentSessionIdentifier)&&(r.currentSessionIdentifier=b().replaceAll("-","")),i?t.reference_id=r.currentSessionIdentifier:(t.data||(t.data={}),t.data["@ref:session"]=r.currentSessionIdentifier),Promise.resolve()}};var U=class{constructor(){this.priority=10;this.name="ConfigurationDefaultsPlugin"}run(e){let{dataExclusions:t,defaultData:i,defaultTags:r}=e.client.config,n=e.event;if(r&&(n.tags=[...n.tags||[],...r]),i){n.data||(n.data={});for(let o in i){if(n.data[o]!==void 0||d(i[o]))continue;let a=h(i[o],t);d(a)||(n.data[o]=JSON.parse(a))}}return Promise.resolve()}};var k=class{constructor(e=()=>Date.now(),t=3e4){this.priority=1010;this.name="DuplicateCheckerPlugin";this._mergedEvents=[];this._processedHashCodes=[];this._getCurrentTime=e,this._interval=t}startup(){return clearInterval(this._intervalId),this._intervalId=setInterval(()=>void this.submitEvents(),this._interval),f(this._intervalId),Promise.resolve()}async suspend(){clearInterval(this._intervalId),this._intervalId=void 0,await this.submitEvents()}run(e){function t(n){let o=0;for(;n;)n.message&&n.message.length&&(o+=o*397^F(n.message)),n.stack_trace&&n.stack_trace.length&&(o+=o*397^F(JSON.stringify(n.stack_trace))),n=n.inner;return o}let i=e.event.data?.["@error"],r=t(i);if(r){let n=e.event.count||1,o=this._getCurrentTime(),a=this._mergedEvents.filter(l=>l.hashCode===r)[0];if(a&&(a.incrementCount(n),a.updateDate(e.event.date),e.log.info("Ignoring duplicate event with hash: "+r),e.cancelled=!0),!e.cancelled&&this._processedHashCodes.some(l=>l.hash===r&&l.timestamp>=o-this._interval)&&(e.log.trace("Adding event with hash: "+r),this._mergedEvents.push(new O(r,e,n)),e.cancelled=!0),!e.cancelled)for(e.log.trace(`Enqueueing event with hash: ${r} to cache`),this._processedHashCodes.push({hash:r,timestamp:o});this._processedHashCodes.length>50;)this._processedHashCodes.shift()}return Promise.resolve()}async submitEvents(){for(;this._mergedEvents.length>0;)await this._mergedEvents.shift()?.resubmit()}},O=class{constructor(e,t,i){this.hashCode=e,this._context=t,this._count=i}incrementCount(e){this._count+=e}async resubmit(){this._context.event.count=this._count,await this._context.client.config.services.queue.enqueue(this._context.event)}updateDate(e){let t=this._context.event;e&&t.date&&e>t.date&&(t.date=e)}};var L=class{constructor(){this.priority=45;this.name="EventExclusionPlugin"}run(e){let t=e.event,i=e.log,r=e.client.config.settings;if(t.type==="log"){let n=this.getMinLogLevel(r,t.source),o=this.getLogLevel(t.data&&t.data["@level"]);o!==-1&&(o===6||o<n)&&(i.info("Cancelling log event due to minimum log level."),e.cancelled=!0)}else if(t.type==="error"){let n=t.data&&t.data["@error"];for(;!e.cancelled&&n;)this.getTypeAndSourceSetting(r,t.type,n.type,!0)===!1&&(i.info(`Cancelling error from excluded exception type: ${n.type}`),e.cancelled=!0),n=n.inner}else this.getTypeAndSourceSetting(r,t.type,t.source,!0)===!1&&(i.info(`Cancelling event from excluded type: ${t.type} and source: ${t.source}`),e.cancelled=!0);return Promise.resolve()}getLogLevel(e){switch((e||"").toLowerCase().trim()){case"trace":case"true":case"1":case"yes":return 0;case"debug":return 1;case"info":return 2;case"warn":return 3;case"error":return 4;case"fatal":return 5;case"off":case"false":case"0":case"no":return 6;default:return-1}}getMinLogLevel(e,t){return this.getLogLevel(this.getTypeAndSourceSetting(e,"log",t,"other")+"")}getTypeAndSourceSetting(e={},t,i,r){if(!t)return r;i||(i="");let n=t==="log",o=`@@${t}:`,a=e[o+i];if(a)return n?a:W(a);let l=Object.keys(e).sort((g,u)=>u.length-g.length||g.localeCompare(u));for(let g of l){if(!V(g.toLowerCase(),o))continue;let u=g.substring(o.length);if(y(i,[u]))return n?e[g]:W(e[g])}return r}};var R=class{constructor(){this.priority=20;this.name="ReferenceIdPlugin"}run(e){return!e.event.reference_id&&e.event.type==="error"&&(e.event.reference_id=b().replaceAll("-","").substring(0,10)),Promise.resolve()}};var Y=["arguments","column","columnNumber","description","fileName","message","name","number","line","lineNumber","opera#sourceloc","sourceId","sourceURL","stack","stackArray","stacktrace"],T=class{constructor(){this.priority=30;this.name="SimpleErrorPlugin"}async run(e){let t=e.eventContext.getException();if(t&&(e.event.type||(e.event.type="error"),e.event.data&&!e.event.data["@simple_error"])){let i={type:t.name||"Error",message:t.message,stack_trace:t.stack,data:{}},r=e.client.config.dataExclusions.concat(Y),n=h(t,r);d(n)||(i.data["@ext"]=JSON.parse(n)),e.event.data["@simple_error"]=i}return Promise.resolve()}};var $=class{constructor(){this.priority=100;this.name="SubmissionMethodPlugin"}run(e){let t=e.eventContext.getSubmissionMethod();return t&&e.event.data&&(e.event.data["@submission_method"]=t),Promise.resolve()}};var m=class{static async startup(e){for(let t of e.client.config.plugins)if(t.startup)try{await t.startup(e)}catch(i){e.log.error(`Error running plugin startup"${t.name}": ${i instanceof Error?i.message:i+""}`)}}static async suspend(e){for(let t of e.client.config.plugins)if(t.suspend)try{await t.suspend(e)}catch(i){e.log.error(`Error running plugin suspend"${t.name}": ${i instanceof Error?i.message:i+""}`)}}static async run(e){for(let t of e.client.config.plugins){if(e.cancelled)break;if(t.run)try{await t.run(e)}catch(i){e.cancelled=!0,e.log.error(`Error running plugin "${t.name}": ${i instanceof Error?i.message:i+""}. Discarding Event.`)}}}static addDefaultPlugins(e){e.addPlugin(new U),e.addPlugin(new T),e.addPlugin(new R),e.addPlugin(new k),e.addPlugin(new L),e.addPlugin(new $)}};var M=class{constructor(e,t=250){this.config=e;this.maxItems=t;this._handlers=[];this._processingQueue=!1;this.QUEUE_PREFIX="q:";this._lastFileTimestamp=0;this._queue=[];this._loadPersistedEvents=!0}async enqueue(e){let t="The event will not be queued.",i=this.config,r=i.services.log;if(!i.enabled){r.info(`Configuration is disabled. ${t}`);return}if(!i.isValid){r.info(`Invalid Api Key. ${t}`);return}if(this.areQueuedItemsDiscarded()){r.info(`Queue items are currently being discarded. ${t}`);return}let n=await this.enqueueEvent(e),o=`type=${e.type} reference_id=${e.reference_id} source=${e.source} message=${e.message}`;r.info(`Enqueued event: ${n} (${o})`)}async process(){let e="The queue will not be processed",{log:t}=this.config.services;if(!this._processingQueue){if(t.trace("Processing queue..."),!this.config.enabled){t.info(`Configuration is disabled: ${e}`);return}if(!this.config.isValid){t.info(`Invalid Api Key: ${e}`);return}this._processingQueue=!0;try{this._loadPersistedEvents&&(this.config.usePersistedQueueStorage&&await this.loadEvents(),this._loadPersistedEvents=!1);let i=this._queue.slice(0,this.config.submissionBatchSize);if(!i||i.length===0){this._processingQueue=!1;return}t.info(`Sending ${i.length} events to ${this.config.serverUrl}`);let r=i.map(o=>o.event),n=await this.config.services.submissionClient.submitEvents(r);await this.processSubmissionResponse(n,i),await this.eventsPosted(r,n),t.trace("Finished processing queue"),this._processingQueue=!1}catch(i){t.error(`Error processing queue: ${i instanceof Error?i.message:i+""}`),await this.suspendProcessing(),this._processingQueue=!1}}}startup(){return this._queueIntervalId||(this._queueIntervalId=setInterval(()=>void this.onProcessQueue(),1e4),f(this._queueIntervalId)),Promise.resolve()}suspend(){return clearInterval(this._queueIntervalId),this._queueIntervalId=void 0,Promise.resolve()}async suspendProcessing(e,t,i){let r=this.config,n=new Date;(!e||e<=0)&&(e=Math.ceil(n.getMinutes()/15)*15-n.getMinutes()),r.services.log.info(`Suspending processing for ${e} minutes.`),this._suspendProcessingUntil=new Date(n.getTime()+e*6e4),t&&(this._discardQueuedItemsUntil=this._suspendProcessingUntil),i&&await this.removeEvents(this._queue)}onEventsPosted(e){e&&this._handlers.push(e)}async eventsPosted(e,t){let i=this._handlers;for(let r of i)try{await r(e,t)}catch(n){this.config.services.log.error(`Error calling onEventsPosted handler: ${n instanceof Error?n.message:n+""}`)}}areQueuedItemsDiscarded(){return this._discardQueuedItemsUntil&&this._discardQueuedItemsUntil>new Date||!1}isQueueProcessingSuspended(){return this._suspendProcessingUntil&&this._suspendProcessingUntil>new Date||!1}async onProcessQueue(){!this.isQueueProcessingSuspended()&&!this._processingQueue&&await this.process()}async processSubmissionResponse(e,t){let i="The event will not be submitted",r=this.config,n=r.services.log;if(e.status===202){n.info(`Sent ${t.length} events`),await this.removeEvents(t);return}if(e.status===429||e.rateLimitRemaining===0||e.status===503){n.error("Server returned service unavailable"),await this.suspendProcessing();return}if(e.status===402){n.info("Too many events have been submitted, please upgrade your plan"),await this.suspendProcessing(0,!0,!0);return}if(e.status===401||e.status===403){n.info(`Unable to authenticate, please check your configuration. ${i}`),await this.suspendProcessing(15),await this.removeEvents(t);return}if(e.status===400||e.status===404){n.error(`Error while trying to submit data: ${e.message}`),await this.suspendProcessing(60*4),await this.removeEvents(t);return}if(e.status===413){let o="Event submission discarded for being too large.";r.submissionBatchSize>1?(n.error(`${o} Retrying with smaller batch size.`),r.submissionBatchSize=Math.max(1,Math.round(r.submissionBatchSize/1.5))):(n.error(`${o} ${i}`),await this.removeEvents(t));return}n.error(`Error submitting events: ${e.message||"Please check the network tab for more info."}`),await this.suspendProcessing()}async loadEvents(){if(this.config.usePersistedQueueStorage){let{log:e,storage:t}=this.config.services;try{let i=await t.keys();for(let r of i)if(r?.startsWith(this.QUEUE_PREFIX)){let n=await t.getItem(r);n&&this._queue.push({file:r,event:JSON.parse(n)})}}catch(i){e.error(`Error loading queue items from storage: ${i instanceof Error?i.message:i+""}`)}}}async enqueueEvent(e){this._lastFileTimestamp=Math.max(Date.now(),this._lastFileTimestamp+1);let t=`${this.QUEUE_PREFIX}${this._lastFileTimestamp}.json`,{log:i,storage:r}=this.config.services,n=this.config.usePersistedQueueStorage;if(this._queue.push({file:t,event:e})>this.maxItems){i.trace("Removing oldest queue entry: maxItems exceeded");let o=this._queue.shift();if(n&&o)try{await r.removeItem(o.file)}catch(a){i.error(`Error removing oldest queue entry from storage: ${a instanceof Error?a.message:a+""}`)}}if(n)try{await r.setItem(t,JSON.stringify(e))}catch(o){i.error(`Error saving queue entry to storage: ${o instanceof Error?o.message:o+""}`)}return t}async removeEvents(e){let t=e.map(i=>i.file);if(this.config.usePersistedQueueStorage){let{log:i,storage:r}=this.config.services;for(let n of t)try{await r.removeItem(n)}catch(o){i.error(`Error removing queue item from storage: ${o instanceof Error?o.message:o+""}`)}}this._queue=this._queue.filter(i=>!t.includes(i.file))}};var H=class{constructor(e,t){this.settings=e;this.version=t}},I=class I{static async applySavedServerSettings(e){if(!e?.isValid)return;let t=await this.getSavedServerSettings(e);t&&e.applyServerSettings(t)}static async updateSettings(e){if(!e?.enabled||this._isUpdatingSettings)return;this._isUpdatingSettings=!0;let{log:t,storage:i,submissionClient:r}=e.services;try{let n="Unable to update settings";if(!e.isValid){t.error(`${n}: ApiKey is not set`);return}let o=e.settingsVersion;t.trace(`Checking for updated settings from: v${o}`);let a=await r.getSettings(o);if(a.status===304){t.trace("Settings are up-to-date");return}if(!a?.success||!a.data){t.warn(`${n}: ${a.message}`);return}e.applyServerSettings(a.data),await i.setItem(I.SettingsKey,JSON.stringify(a.data)),t.trace(`Updated settings: v${a.data.version}`)}catch(n){t.error(`Error updating settings: ${n instanceof Error?n.message:n+""}`)}finally{this._isUpdatingSettings=!1}}static async getSavedServerSettings(e){let{log:t,storage:i}=e.services;try{let r=await i.getItem(I.SettingsKey);return r&&JSON.parse(r)||new H({},0)}catch(r){return t.error(`Error getting saved settings: ${r instanceof Error?r.message:r+""}`),new H({},0)}}};I.SettingsKey="settings",I._isUpdatingSettings=!1;var v=I;var D=class{constructor(e,t,i,r,n){this.status=e;this.message=t;this.rateLimitRemaining=i;this.settingsVersion=r;this.data=n}get success(){return this.status>=200&&this.status<=299}};var A=class{constructor(e,t=globalThis.fetch?.bind(globalThis)){this.config=e;this.fetch=t;this.RateLimitRemainingHeader="x-ratelimit-remaining";this.ConfigurationVersionHeader="x-exceptionless-configversion"}getSettings(e){let t=`${this.config.serverUrl}/api/v2/projects/config?v=${e}`;return this.apiFetch(t,{method:"GET"})}async submitEvents(e){let t=`${this.config.serverUrl}/api/v2/events`,i=await this.apiFetch(t,{method:"POST",body:JSON.stringify(e)});return await this.updateSettingsVersion(i.settingsVersion),i}async submitUserDescription(e,t){let i=`${this.config.serverUrl}/api/v2/events/by-ref/${encodeURIComponent(e)}/user-description`,r=await this.apiFetch(i,{method:"POST",body:JSON.stringify(t)});return await this.updateSettingsVersion(r.settingsVersion),r}async submitHeartbeat(e,t){let i=`${this.config.heartbeatServerUrl}/api/v2/events/session/heartbeat?id=${e}&close=${t+""}`;return await this.apiFetch(i,{method:"GET"})}async updateSettingsVersion(e){isNaN(e)?this.config.services.log.error("No config version header was returned."):e>this.config.settingsVersion&&await v.updateSettings(this.config)}async apiFetch(e,t){let i={method:t.method,headers:{Accept:"application/json",Authorization:`Bearer ${this.config.apiKey}`,"User-Agent":this.config.userAgent},body:t.body??null};t.method==="POST"&&this.isHeaders(i.headers)&&(i.headers["Content-Type"]="application/json");let r=await this.fetch(e,i),n=parseInt(r.headers.get(this.RateLimitRemainingHeader)||"",10),o=parseInt(r.headers.get(this.ConfigurationVersionHeader)||"",10),a=await r.text(),l=a&&a.length>0?JSON.parse(a):null;return new D(r.status,r.statusText,n,o,l)}isHeaders(e){return e!==void 0}};var j=class{constructor(){this.items=new Map}length(){return Promise.resolve(this.items.size)}clear(){return this.items.clear(),Promise.resolve()}getItem(e){let t=this.items.get(e);return Promise.resolve(t||null)}async key(e){if(e<0)return Promise.resolve(null);let t=await this.keys();if(e>t.length)return Promise.resolve(null);let i=t[e];return Promise.resolve(i||null)}keys(){return Promise.resolve(Array.from(this.items.keys()))}removeItem(e){return this.items.delete(e),Promise.resolve()}setItem(e,t){return this.items.set(e,t),Promise.resolve()}};var q=class{constructor(e="exceptionless-",t=globalThis.localStorage){this.prefix=e;this.storage=t}length(){return Promise.resolve(this.getKeys().length)}clear(){for(let e of this.getKeys())this.storage.removeItem(this.getKey(e));return Promise.resolve()}getItem(e){return Promise.resolve(this.storage.getItem(this.getKey(e)))}key(e){let t=this.getKeys();return Promise.resolve(e<t.length?t[e]:null)}keys(){return Promise.resolve(this.getKeys())}removeItem(e){return this.storage.removeItem(this.getKey(e)),Promise.resolve()}setItem(e,t){return this.storage.setItem(this.getKey(e),t),Promise.resolve()}getKeys(){return Object.keys(this.storage).filter(e=>e.startsWith(this.prefix)).map(e=>e?.substr(this.prefix.length))}getKey(e){return this.prefix+e}};var B=class{constructor(){this.defaultTags=[];this.defaultData={};this.enabled=!0;this.submissionBatchSize=50;this.settings={};this.settingsVersion=0;this.apiKey="";this._serverUrl="https://collector.exceptionless.io";this.configServerUrl="https://config.exceptionless.io";this.heartbeatServerUrl="https://heartbeat.exceptionless.io";this._updateSettingsWhenIdleInterval=12e4;this._dataExclusions=[];this._includePrivateInformation=!0;this._includeUserName=!0;this._includeMachineName=!0;this._includeIpAddress=!0;this._includeHeaders=!0;this._includeCookies=!0;this._includePostData=!0;this._includeQueryString=!0;this._userAgentBotPatterns=[];this._plugins=[];this._subscribers=[];this.usePersistedQueueStorage=!1;this.sessionsEnabled=!1;this.currentSessionIdentifier=null;this.services={lastReferenceIdManager:new S,log:new _,storage:new j,queue:new M(this),submissionClient:new A(this)},m.addDefaultPlugins(this)}get isValid(){return this.apiKey?.length>=10}get serverUrl(){return this._serverUrl}set serverUrl(e){e&&(this._serverUrl=e,this.configServerUrl=e,this.heartbeatServerUrl=e)}get updateSettingsWhenIdleInterval(){return this._updateSettingsWhenIdleInterval}set updateSettingsWhenIdleInterval(e){typeof e=="number"&&(e<=0?e=-1:e>0&&e<12e4&&(e=12e4),this._updateSettingsWhenIdleInterval=e)}get dataExclusions(){let e=this.settings["@@DataExclusions"];return this._dataExclusions.concat(e&&e.split(",")||[])}addDataExclusions(...e){this._dataExclusions=[...this._dataExclusions,...e]}get includePrivateInformation(){return this._includePrivateInformation}set includePrivateInformation(e){let t=e===!0;this._includePrivateInformation=t,this._includeUserName=t,this._includeMachineName=t,this._includeIpAddress=t,this._includeHeaders=t,this._includeCookies=t,this._includePostData=t,this._includeQueryString=t}get includeUserName(){return this._includeUserName}set includeUserName(e){this._includeUserName=e===!0}get includeMachineName(){return this._includeMachineName}set includeMachineName(e){this._includeMachineName=e===!0}get includeIpAddress(){return this._includeIpAddress}set includeIpAddress(e){this._includeIpAddress=e===!0}get includeHeaders(){return this._includeHeaders}set includeHeaders(e){this._includeHeaders=e===!0}get includeCookies(){return this._includeCookies}set includeCookies(e){this._includeCookies=e===!0}get includePostData(){return this._includePostData}set includePostData(e){this._includePostData=e===!0}get includeQueryString(){return this._includeQueryString}set includeQueryString(e){this._includeQueryString=e===!0}get userAgentBotPatterns(){let e=this.settings["@@UserAgentBotPatterns"];return this._userAgentBotPatterns.concat(e&&e.split(",")||[])}addUserAgentBotPatterns(...e){this._userAgentBotPatterns=[...this._userAgentBotPatterns,...e]}get plugins(){return this._plugins.sort((e,t)=>e==null&&t==null?0:e?.priority==null?-1:t?.priority==null?1:e.priority==t.priority?0:e.priority>t.priority?1:-1)}addPlugin(e,t,i){let r=i?{name:e,priority:t,run:i}:e;if(!r||!(r.startup||r.run)){this.services.log.error("Add plugin failed: startup or run method not defined");return}r.name||(r.name=b()),r.priority||(r.priority=0),this._plugins.find(n=>n.name===r.name)||this._plugins.push(r)}removePlugin(e){let t=typeof e=="string"?e:e.name||"";if(!t){this.services.log.error("Remove plugin failed: Plugin name not defined");return}let i=this._plugins;for(let r=0;r<i.length;r++)if(i[r].name===t){i.splice(r,1);break}}get version(){return this.defaultData["@version"]}set version(e){e?this.defaultData["@version"]=e:delete this.defaultData["@version"]}setUserIdentity(e,t){let i=typeof e!="string"?e:{identity:e,name:t},r=!i||!i.identity&&!i.name;r?delete this.defaultData["@user"]:this.defaultData["@user"]=i,this.services.log.info(`user identity: ${r?"null":i.identity}`)}get userAgent(){return"exceptionless-js/3.0.5"}useLocalStorage(){globalThis?.localStorage&&(this.services.storage=new q)}useSessions(e=!0,t=6e4,i=!1){this.sessionsEnabled=!0,i&&this.addPlugin(new C);let r=new w(t);e?this.addPlugin(r):this.removePlugin(r)}applyServerSettings(e){this.originalSettings||(this.originalSettings=JSON.parse(JSON.stringify(this.settings))),this.services.log.trace(`Applying saved settings: v${e.version}`),this.settings=Object.assign(this.originalSettings,e.settings),this.settingsVersion=e.version,this.notifySubscribers()}useDebugLogger(){this.services.log=new x}subscribeServerSettingsChange(e){e&&this._subscribers.push(e)}notifySubscribers(){for(let e of this._subscribers)try{e(this)}catch(t){this.services.log.error(`Error calling subscribe handler: ${t instanceof Error?t.message:t+""}`)}}};var p=class{getException(){return this["@@_Exception"]||null}setException(e){e&&(this["@@_Exception"]=e)}get hasException(){return!!this["@@_Exception"]}markAsUnhandledError(){this["@@_IsUnhandledError"]=!0}get isUnhandledError(){return!!this["@@_IsUnhandledError"]}getSubmissionMethod(){return this["@@_SubmissionMethod"]||null}setSubmissionMethod(e){e&&(this["@@_SubmissionMethod"]=e)}};var P=class{constructor(e){this.client=e}get log(){return this.client.config.services.log}};var Q=class{constructor(e,t,i){this.client=e;this.event=t;this.eventContext=i;this.cancelled=!1;this.eventContext||(this.eventContext=new p)}get log(){return this.client.config.services.log}};var N=class{constructor(e,t,i){this._validIdentifierErrorMessage="must contain between 8 and 100 alphanumeric or '-' characters.";this.target=e,this.client=t,this.context=i||new p}setType(e){return e&&(this.target.type=e),this}setSource(e){return e&&(this.target.source=e),this}setReferenceId(e){if(!this.isValidIdentifier(e))throw new Error(`ReferenceId ${this._validIdentifierErrorMessage}`);return this.target.reference_id=e,this}setEventReference(e,t){if(!e)throw new Error("Invalid name");if(!t||!this.isValidIdentifier(t))throw new Error(`Id ${this._validIdentifierErrorMessage}`);return this.setProperty("@ref:"+e,t),this}setMessage(e){return e&&(this.target.message=e),this}setGeo(e,t){if(e<-90||e>90)throw new Error("Must be a valid latitude value between -90.0 and 90.0.");if(t<-180||t>180)throw new Error("Must be a valid longitude value between -180.0 and 180.0.");return this.target.geo=`${e},${t}`,this}setUserIdentity(e,t){let i=typeof e!="string"?e:{identity:e,name:t};return!i||!i.identity&&!i.name?this:(this.setProperty("@user",i),this)}setUserDescription(e,t){return e&&t&&this.setProperty("@user_description",{email_address:e,description:t}),this}setManualStackingInfo(e,t){if(e){let i={signature_data:e};t&&(i.title=t),this.setProperty("@stack",i)}return this}setManualStackingKey(e,t){if(e){let i={ManualStackingKey:e};this.setManualStackingInfo(i,t)}return this}setValue(e){return e&&(this.target.value=e),this}addTags(...e){return this.target.tags=[...this.target.tags||[],...e],this}setProperty(e,t,i,r){if(!e||t===void 0||t==null)return this;this.target.data||(this.target.data={});let n=this.client.config.dataExclusions.concat(r||[]),o=h(t,n,i);return d(o)||(this.target.data[e]=JSON.parse(o)),this}setContextProperty(e,t){return this.context[e]=t,this}markAsCritical(e){return e&&this.addTags("Critical"),this}submit(){return this.client.submitEvent(this.target,this.context)}isValidIdentifier(e){if(!e)return!0;if(e.length<8||e.length>100)return!1;for(let t=0;t<e.length;t++){let i=e.charCodeAt(t),r=i>=48&&i<=57,n=i>=65&&i<=90||i>=97&&i<=122;if(!(r||n)&&!(i===45))return!1}return!0}};var J=class{constructor(e=new B){this.config=e;this._initialized=!1}async startup(e){if(e&&!this._initialized&&(this._initialized=!0,typeof e=="string"?this.config.apiKey=e:e(this.config),this.config.services.queue.onEventsPosted(()=>Promise.resolve(this.updateSettingsTimer())),await v.applySavedServerSettings(this.config)),!this.config.isValid){this.config.services.log.warn("Exceptionless is not configured and will not process events.");return}this.updateSettingsTimer(!!e),await m.startup(new P(this));let{queue:t}=this.config.services;await t.startup(),this.config.usePersistedQueueStorage&&await t.process(),this.config.sessionsEnabled&&await this.submitSessionStart()}async suspend(){await m.suspend(new P(this));let{queue:e}=this.config.services;await e.suspend(),await e.process(),this.suspendSettingsTimer()}suspendSettingsTimer(){clearTimeout(this._timeoutId),this._timeoutId=void 0,clearInterval(this._intervalId),this._intervalId=void 0}async processQueue(){await this.config.services.queue.process()}updateSettingsTimer(e=!1){if(this.suspendSettingsTimer(),!this.config.isValid)return;let t=this.config.updateSettingsWhenIdleInterval;if(t>0){let i=t;e&&(i=this.config.settingsVersion>0?15e3:5e3),this.config.services.log.info(`Update settings every ${t}ms (${i||0}ms delay)`);let r=()=>void v.updateSettings(this.config);i<t&&(this._timeoutId=setTimeout(r,i),f(this._timeoutId)),this._intervalId=setInterval(r,t),f(this._intervalId)}}createException(e){let t=new p;return t.setException(e),this.createEvent(t).setType("error")}submitException(e){return this.createException(e).submit()}createUnhandledException(e,t){let i=this.createException(e);return i.context.markAsUnhandledError(),i.context.setSubmissionMethod(t||""),i}submitUnhandledException(e,t){return this.createUnhandledException(e,t).submit()}createFeatureUsage(e){return this.createEvent().setType("usage").setSource(e)}submitFeatureUsage(e){return this.createFeatureUsage(e).submit()}createLog(e,t,i){let r=this.createEvent().setType("log");if(i)r=r.setSource(e).setMessage(t).setProperty("@level",i);else if(t)r=r.setSource(e).setMessage(t);else{r=r.setMessage(e);try{let n=this.createLog.caller;r=r.setSource(n&&n.caller&&n.caller.name)}catch(n){this.config.services.log.trace(`Unable to resolve log source: ${n instanceof Error?n.message:n+""}`)}}return r}submitLog(e,t,i){return this.createLog(e,t,i).submit()}createNotFound(e){return this.createEvent().setType("404").setSource(e)}submitNotFound(e){return this.createNotFound(e).submit()}createSessionStart(){return this.createEvent().setType("session")}submitSessionStart(){return this.createSessionStart().submit()}async submitSessionEnd(e){let{currentSessionIdentifier:t,enabled:i,isValid:r,services:n}=this.config,o=e||t;o&&i&&r&&(n.log.info(`Submitting session end: ${o}`),await n.submissionClient.submitHeartbeat(o,!0))}async submitSessionHeartbeat(e){let{currentSessionIdentifier:t,enabled:i,isValid:r,services:n}=this.config,o=e||t;o&&i&&r&&(n.log.info(`Submitting session heartbeat: ${o}`),await n.submissionClient.submitHeartbeat(o,!1))}createEvent(e){return new N({date:new Date},this,e)}async submitEvent(e,t){let i=new Q(this,e,t??new p);if(!e)return i.cancelled=!0,i;if(!this.config.enabled||!this.config.isValid)return this.config.services.log.info("Event submission is currently disabled."),i.cancelled=!0,i;if(e.data||(e.data={}),(!e.tags||!e.tags.length)&&(e.tags=[]),await m.run(i),i.cancelled)return i;let r=i.event;return(!r.type||r.type.length===0)&&(r.type="log"),r.date||(r.date=new Date),await this.config.services.queue.enqueue(r),r.reference_id&&r.reference_id.length>0&&(i.log.info(`Setting last reference id "${r.reference_id}"`),this.config.services.lastReferenceIdManager.setLast(r.reference_id)),i}async updateUserEmailAndDescription(e,t,i){if(!e||!t||!i||!this.config.enabled||!this.config.isValid)return;let r={email_address:t,description:i},n=await this.config.services.submissionClient.submitUserDescription(e,r);n.success||this.config.services.log.error(`Failed to submit user email and description for event "${e}": ${n.status} ${n.message}`)}getLastReferenceId(){return this.config.services.lastReferenceIdManager.getLast()}};export{B as Configuration,U as ConfigurationDefaultsPlugin,x as ConsoleLog,M as DefaultEventQueue,S as DefaultLastReferenceIdManager,A as DefaultSubmissionClient,k as DuplicateCheckerPlugin,N as EventBuilder,p as EventContext,L as EventExclusionPlugin,Q as EventPluginContext,m as EventPluginManager,J as ExceptionlessClient,w as HeartbeatPlugin,Y as IgnoredErrorProperties,j as InMemoryStorage,G as KnownEventDataKeys,q as LocalStorage,_ as NullLog,P as PluginContext,R as ReferenceIdPlugin,D as Response,C as SessionIdManagementPlugin,v as SettingsManager,T as SimpleErrorPlugin,$ as SubmissionMethodPlugin,Z as endsWith,te as getCookies,F as getHashCode,b as guid,d as isEmpty,y as isMatch,re as parseQueryString,ie as parseVersion,X as prune,ne as randomNumber,V as startsWith,h as stringify,W as toBoolean,se as toError};
var P=class{_lastReferenceId=null;getLast(){return this._lastReferenceId}clearLast(){this._lastReferenceId=null}setLast(e){this._lastReferenceId=e}};var S=class{trace(e){this.log("debug",e)}info(e){this.log("info",e)}warn(e){this.log("warn",e)}error(e){this.log("error",e)}log(e,t){if(console){let i=`Exceptionless:${new Date().toISOString()} [${e}] ${t}`,r=console[e];r?r(i):console.log&&console.log(i)}}};var x=class{trace(e){}info(e){}warn(e){}error(e){}};var z=(c=>(c.Error="@error",c.SimpleError="@simple_error",c.RequestInfo="@request",c.TraceLog="@trace",c.EnvironmentInfo="@environment",c.UserInfo="@user",c.UserDescription="@user_description",c.Version="@version",c.Level="@level",c.SubmissionMethod="@submission_method",c.ManualStackingInfo="@stack",c))(z||{});function N(s){if(!s||s.length===0)return 0;let e=0;for(let t=0;t<s.length;t++){let i=s.charCodeAt(t);e=(e<<5)-e+i,e|=0}return e}function ee(s,e){let t={},i=(s||"").split("; ");for(let r of i){let n=r.split("=");y(n[0],e||[])||(t[n[0]]=n[1])}return d(t)?null:t}function b(){function s(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}return s()+s()+"-"+s()+"-"+s()+"-"+s()+"-"+s()+s()+s()}function te(s){if(!s)return null;let t=/(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?)/.exec(s);return t&&t.length>0?t[0]:null}function ie(s,e){if(!s||s.length===0)return{};let t=s.split("&");if(t.length===0)return{};let i={};for(let r of t){let n=r.split("=");(!e||!y(n[0],e))&&(i[decodeURIComponent(n[0])]=decodeURIComponent(n[1]))}return d(i)?{}:i}function re(){return Math.floor(Math.random()*9007199254740992)}function y(s,e,t=!0){if(typeof s!="string")return!1;let i=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;return s=(t?s.toLowerCase():s).replace(i,""),(e||[]).some(r=>{if(typeof r!="string")return!1;if(r&&(r=(t?r.toLowerCase():r).replace(i,"")),!r)return s==null;if(r==="*")return!0;if(s==null)return!1;let n=r[0]==="*";n&&(r=r.slice(1));let o=r[r.length-1]==="*";return o&&(r=r.substring(0,r.length-1)),n&&o?r.length<=s.length&&s.indexOf(r,0)!==-1:n?G(s,r):o?F(s,r):s===r})}function d(s){if(s==null)return!0;if(typeof s=="object")return Array.isArray(s)?s.length===0:s instanceof Date?!1:Object.getOwnPropertyNames(s).length===0;if(typeof s=="string"){let e=s.trim();return e.length===0||e==="{}"||e==="[]"}return!1}function F(s,e){return s.substring(0,e.length)===e}function G(s,e){return s.indexOf(e,s.length-e.length)!==-1}function Z(s,e=10){function t(n){if(n==null)return!1;switch(typeof n){case"function":return!0;case"object":switch(Object.prototype.toString.call(n)){case"[object AsyncGenerator]":case"[object Generator]":case"[object ArrayBuffer]":case"[object Buffer]":case"[object DataView]":case"[object Promise]":case"[object WeakMap]":case"[object WeakSet]":return!0}if("writeBigInt64LE"in n)return!0;break}return!1}function i(n){function o(a){return a!==null&&typeof a=="object"&&typeof a.toJSON=="function"}if(typeof n=="bigint")return`${n.toString()}n`;if(typeof n=="object"){if(Array.isArray(n)||n instanceof Date)return n;if(n instanceof Map){let l={};for(let[g,u]of n)l[g]=u;return l}if(n instanceof RegExp)return n.toString();if(n instanceof Set)return Array.from(n);let a=Object.getPrototypeOf(Uint8Array);return n instanceof a?Array.from(n):o(n)?i(n.toJSON()):n}return typeof n=="symbol"?n.description:n}function r(n,o,a=10,l=new WeakSet,g=!1){if(n==null)return n;if(a>o||t(n))return;let u=i(n);if(typeof u=="object"){if(a==o)return;if(Array.isArray(u)){let E=g?a+1:a;return u.map(H=>r(H,o,E,l,!0))}if(u instanceof Date)return u;if(Object.prototype.toString.call(u)==="[object Object]"){if(l.has(u))return;l.add(u)}let c=new Set([...Object.getOwnPropertyNames(u),...Object.getOwnPropertySymbols(u)]);for(let E in u)c.add(E);let J={};for(let E of c){let H=i(E),Y=u[E];J[H]=r(Y,o,a+1,l)}return J}return u}if(!(e<0))return r(s,e,0)}function h(s,e,t=10){function i(n,o){return JSON.stringify(n,(a,l)=>{if(!y(a,o))return l})}if(s===void 0)return s;let r=Z(s,t);return i(r,e||[])}function V(s,e=!1){if(typeof s=="boolean")return s;if(s===null||typeof s!="number"&&typeof s!="string")return e;switch((s+"").toLowerCase().trim()){case"true":case"yes":case"1":return!0;case"false":case"no":case"0":case null:return!1}return e}function ne(s,e="Unknown Error"){if(s==null){let i=new Error(e);return i.stack=void 0,i}if(s instanceof Error)return s;if(typeof s=="string"){let i=new Error(s);return i.stack=void 0,i}let t=new Error(h(s)||e);return t.stack=void 0,t}function f(s){typeof s=="object"&&"unref"in s&&s.unref()}var _=class{priority=100;name="HeartbeatPlugin";_interval;_intervalId;constructor(e=6e4){this._interval=e>=3e4?e:6e4}startup(){return clearInterval(this._intervalId),this._intervalId=void 0,Promise.resolve()}suspend(){return clearInterval(this._intervalId),this._intervalId=void 0,Promise.resolve()}run(e){if(this._interval<=0)return Promise.resolve();clearInterval(this._intervalId),this._intervalId=void 0;let{config:t}=e.client;if(!t.currentSessionIdentifier){let i=e.event.data?.["@user"];if(!i?.identity)return Promise.resolve();t.currentSessionIdentifier=i.identity}return t.currentSessionIdentifier&&(this._intervalId=setInterval(()=>void e.client.submitSessionHeartbeat(t.currentSessionIdentifier),this._interval),f(this._intervalId)),Promise.resolve()}};var w=class{priority=25;name="SessionIdManagementPlugin";run(e){let t=e.event,i=t.type==="session",{config:r}=e.client;return(i||!r.currentSessionIdentifier)&&(r.currentSessionIdentifier=b().replaceAll("-","")),i?t.reference_id=r.currentSessionIdentifier:(t.data||(t.data={}),t.data["@ref:session"]=r.currentSessionIdentifier),Promise.resolve()}};var C=class{priority=10;name="ConfigurationDefaultsPlugin";run(e){let{dataExclusions:t,defaultData:i,defaultTags:r}=e.client.config,n=e.event;if(r&&(n.tags=[...n.tags||[],...r]),i){n.data||(n.data={});for(let o in i){if(n.data[o]!==void 0||d(i[o]))continue;let a=h(i[o],t);d(a)||(n.data[o]=JSON.parse(a))}}return Promise.resolve()}};var U=class{priority=1010;name="DuplicateCheckerPlugin";_mergedEvents=[];_processedHashCodes=[];_getCurrentTime;_intervalId;_interval;constructor(e=()=>Date.now(),t=3e4){this._getCurrentTime=e,this._interval=t}startup(){return clearInterval(this._intervalId),this._intervalId=setInterval(()=>void this.submitEvents(),this._interval),f(this._intervalId),Promise.resolve()}async suspend(){clearInterval(this._intervalId),this._intervalId=void 0,await this.submitEvents()}run(e){function t(n){let o=0;for(;n;)n.message&&n.message.length&&(o+=o*397^N(n.message)),n.stack_trace&&n.stack_trace.length&&(o+=o*397^N(JSON.stringify(n.stack_trace))),n=n.inner;return o}let i=e.event.data?.["@error"],r=t(i);if(r){let n=e.event.count||1,o=this._getCurrentTime(),a=this._mergedEvents.filter(l=>l.hashCode===r)[0];if(a&&(a.incrementCount(n),a.updateDate(e.event.date),e.log.info("Ignoring duplicate event with hash: "+r),e.cancelled=!0),!e.cancelled&&this._processedHashCodes.some(l=>l.hash===r&&l.timestamp>=o-this._interval)&&(e.log.trace("Adding event with hash: "+r),this._mergedEvents.push(new K(r,e,n)),e.cancelled=!0),!e.cancelled)for(e.log.trace(`Enqueueing event with hash: ${r} to cache`),this._processedHashCodes.push({hash:r,timestamp:o});this._processedHashCodes.length>50;)this._processedHashCodes.shift()}return Promise.resolve()}async submitEvents(){for(;this._mergedEvents.length>0;)await this._mergedEvents.shift()?.resubmit()}},K=class{hashCode;_count;_context;constructor(e,t,i){this.hashCode=e,this._context=t,this._count=i}incrementCount(e){this._count+=e}async resubmit(){this._context.event.count=this._count,await this._context.client.config.services.queue.enqueue(this._context.event)}updateDate(e){let t=this._context.event;e&&t.date&&e>t.date&&(t.date=e)}};var k=class{priority=45;name="EventExclusionPlugin";run(e){let t=e.event,i=e.log,r=e.client.config.settings;if(t.type==="log"){let n=this.getMinLogLevel(r,t.source),o=this.getLogLevel(t.data&&t.data["@level"]);o!==-1&&(o===6||o<n)&&(i.info("Cancelling log event due to minimum log level."),e.cancelled=!0)}else if(t.type==="error"){let n=t.data&&t.data["@error"];for(;!e.cancelled&&n;)this.getTypeAndSourceSetting(r,t.type,n.type,!0)===!1&&(i.info(`Cancelling error from excluded exception type: ${n.type}`),e.cancelled=!0),n=n.inner}else this.getTypeAndSourceSetting(r,t.type,t.source,!0)===!1&&(i.info(`Cancelling event from excluded type: ${t.type} and source: ${t.source}`),e.cancelled=!0);return Promise.resolve()}getLogLevel(e){switch((e||"").toLowerCase().trim()){case"trace":case"true":case"1":case"yes":return 0;case"debug":return 1;case"info":return 2;case"warn":return 3;case"error":return 4;case"fatal":return 5;case"off":case"false":case"0":case"no":return 6;default:return-1}}getMinLogLevel(e,t){return this.getLogLevel(this.getTypeAndSourceSetting(e,"log",t,"other")+"")}getTypeAndSourceSetting(e={},t,i,r){if(!t)return r;i||(i="");let n=t==="log",o=`@@${t}:`,a=e[o+i];if(a)return n?a:V(a);let l=Object.keys(e).sort((g,u)=>u.length-g.length||g.localeCompare(u));for(let g of l){if(!F(g.toLowerCase(),o))continue;let u=g.substring(o.length);if(y(i,[u]))return n?e[g]:V(e[g])}return r}};var L=class{priority=20;name="ReferenceIdPlugin";run(e){return!e.event.reference_id&&e.event.type==="error"&&(e.event.reference_id=b().replaceAll("-","").substring(0,10)),Promise.resolve()}};var X=["arguments","column","columnNumber","description","fileName","message","name","number","line","lineNumber","opera#sourceloc","sourceId","sourceURL","stack","stackArray","stacktrace"],R=class{priority=30;name="SimpleErrorPlugin";async run(e){let t=e.eventContext.getException();if(t&&(e.event.type||(e.event.type="error"),e.event.data&&!e.event.data["@simple_error"])){let i={type:t.name||"Error",message:t.message,stack_trace:t.stack,data:{}},r=e.client.config.dataExclusions.concat(X),n=h(t,r);d(n)||(i.data["@ext"]=JSON.parse(n)),e.event.data["@simple_error"]=i}return Promise.resolve()}};var T=class{priority=100;name="SubmissionMethodPlugin";run(e){let t=e.eventContext.getSubmissionMethod();return t&&e.event.data&&(e.event.data["@submission_method"]=t),Promise.resolve()}};var m=class{static async startup(e){for(let t of e.client.config.plugins)if(t.startup)try{await t.startup(e)}catch(i){e.log.error(`Error running plugin startup"${t.name}": ${i instanceof Error?i.message:i+""}`)}}static async suspend(e){for(let t of e.client.config.plugins)if(t.suspend)try{await t.suspend(e)}catch(i){e.log.error(`Error running plugin suspend"${t.name}": ${i instanceof Error?i.message:i+""}`)}}static async run(e){for(let t of e.client.config.plugins){if(e.cancelled)break;if(t.run)try{await t.run(e)}catch(i){e.cancelled=!0,e.log.error(`Error running plugin "${t.name}": ${i instanceof Error?i.message:i+""}. Discarding Event.`)}}}static addDefaultPlugins(e){e.addPlugin(new C),e.addPlugin(new R),e.addPlugin(new L),e.addPlugin(new U),e.addPlugin(new k),e.addPlugin(new T)}};var $=class{constructor(e,t=250){this.config=e;this.maxItems=t}_handlers=[];_suspendProcessingUntil;_discardQueuedItemsUntil;_processingQueue=!1;_queueIntervalId;QUEUE_PREFIX="q:";_lastFileTimestamp=0;_queue=[];_loadPersistedEvents=!0;async enqueue(e){let t="The event will not be queued.",i=this.config,r=i.services.log;if(!i.enabled){r.info(`Configuration is disabled. ${t}`);return}if(!i.isValid){r.info(`Invalid Api Key. ${t}`);return}if(this.areQueuedItemsDiscarded()){r.info(`Queue items are currently being discarded. ${t}`);return}let n=await this.enqueueEvent(e),o=`type=${e.type} reference_id=${e.reference_id} source=${e.source} message=${e.message}`;r.info(`Enqueued event: ${n} (${o})`)}async process(){let e="The queue will not be processed",{log:t}=this.config.services;if(!this._processingQueue){if(t.trace("Processing queue..."),!this.config.enabled){t.info(`Configuration is disabled: ${e}`);return}if(!this.config.isValid){t.info(`Invalid Api Key: ${e}`);return}this._processingQueue=!0;try{this._loadPersistedEvents&&(this.config.usePersistedQueueStorage&&await this.loadEvents(),this._loadPersistedEvents=!1);let i=this._queue.slice(0,this.config.submissionBatchSize);if(!i||i.length===0){this._processingQueue=!1;return}t.info(`Sending ${i.length} events to ${this.config.serverUrl}`);let r=i.map(o=>o.event),n=await this.config.services.submissionClient.submitEvents(r);await this.processSubmissionResponse(n,i),await this.eventsPosted(r,n),t.trace("Finished processing queue"),this._processingQueue=!1}catch(i){t.error(`Error processing queue: ${i instanceof Error?i.message:i+""}`),await this.suspendProcessing(),this._processingQueue=!1}}}startup(){return this._queueIntervalId||(this._queueIntervalId=setInterval(()=>void this.onProcessQueue(),1e4),f(this._queueIntervalId)),Promise.resolve()}suspend(){return clearInterval(this._queueIntervalId),this._queueIntervalId=void 0,Promise.resolve()}async suspendProcessing(e,t,i){let r=this.config,n=new Date;(!e||e<=0)&&(e=Math.ceil(n.getMinutes()/15)*15-n.getMinutes()),r.services.log.info(`Suspending processing for ${e} minutes.`),this._suspendProcessingUntil=new Date(n.getTime()+e*6e4),t&&(this._discardQueuedItemsUntil=this._suspendProcessingUntil),i&&await this.removeEvents(this._queue)}onEventsPosted(e){e&&this._handlers.push(e)}async eventsPosted(e,t){let i=this._handlers;for(let r of i)try{await r(e,t)}catch(n){this.config.services.log.error(`Error calling onEventsPosted handler: ${n instanceof Error?n.message:n+""}`)}}areQueuedItemsDiscarded(){return this._discardQueuedItemsUntil&&this._discardQueuedItemsUntil>new Date||!1}isQueueProcessingSuspended(){return this._suspendProcessingUntil&&this._suspendProcessingUntil>new Date||!1}async onProcessQueue(){!this.isQueueProcessingSuspended()&&!this._processingQueue&&await this.process()}async processSubmissionResponse(e,t){let i="The event will not be submitted",r=this.config,n=r.services.log;if(e.status===202){n.info(`Sent ${t.length} events`),await this.removeEvents(t);return}if(e.status===429||e.rateLimitRemaining===0||e.status===503){n.error("Server returned service unavailable"),await this.suspendProcessing();return}if(e.status===402){n.info("Too many events have been submitted, please upgrade your plan"),await this.suspendProcessing(0,!0,!0);return}if(e.status===401||e.status===403){n.info(`Unable to authenticate, please check your configuration. ${i}`),await this.suspendProcessing(15),await this.removeEvents(t);return}if(e.status===400||e.status===404){n.error(`Error while trying to submit data: ${e.message}`),await this.suspendProcessing(60*4),await this.removeEvents(t);return}if(e.status===413){let o="Event submission discarded for being too large.";r.submissionBatchSize>1?(n.error(`${o} Retrying with smaller batch size.`),r.submissionBatchSize=Math.max(1,Math.round(r.submissionBatchSize/1.5))):(n.error(`${o} ${i}`),await this.removeEvents(t));return}n.error(`Error submitting events: ${e.message||"Please check the network tab for more info."}`),await this.suspendProcessing()}async loadEvents(){if(this.config.usePersistedQueueStorage){let{log:e,storage:t}=this.config.services;try{let i=await t.keys();for(let r of i)if(r?.startsWith(this.QUEUE_PREFIX)){let n=await t.getItem(r);n&&this._queue.push({file:r,event:JSON.parse(n)})}}catch(i){e.error(`Error loading queue items from storage: ${i instanceof Error?i.message:i+""}`)}}}async enqueueEvent(e){this._lastFileTimestamp=Math.max(Date.now(),this._lastFileTimestamp+1);let t=`${this.QUEUE_PREFIX}${this._lastFileTimestamp}.json`,{log:i,storage:r}=this.config.services,n=this.config.usePersistedQueueStorage;if(this._queue.push({file:t,event:e})>this.maxItems){i.trace("Removing oldest queue entry: maxItems exceeded");let o=this._queue.shift();if(n&&o)try{await r.removeItem(o.file)}catch(a){i.error(`Error removing oldest queue entry from storage: ${a instanceof Error?a.message:a+""}`)}}if(n)try{await r.setItem(t,JSON.stringify(e))}catch(o){i.error(`Error saving queue entry to storage: ${o instanceof Error?o.message:o+""}`)}return t}async removeEvents(e){let t=e.map(i=>i.file);if(this.config.usePersistedQueueStorage){let{log:i,storage:r}=this.config.services;for(let n of t)try{await r.removeItem(n)}catch(o){i.error(`Error removing queue item from storage: ${o instanceof Error?o.message:o+""}`)}}this._queue=this._queue.filter(i=>!t.includes(i.file))}};var W=class{constructor(e,t){this.settings=e;this.version=t}},v=class s{static SettingsKey="settings";static _isUpdatingSettings=!1;static async applySavedServerSettings(e){if(!e?.isValid)return;let t=await this.getSavedServerSettings(e);t&&e.applyServerSettings(t)}static async updateSettings(e){if(!e?.enabled||this._isUpdatingSettings)return;this._isUpdatingSettings=!0;let{log:t,storage:i,submissionClient:r}=e.services;try{let n="Unable to update settings";if(!e.isValid){t.error(`${n}: ApiKey is not set`);return}let o=e.settingsVersion;t.trace(`Checking for updated settings from: v${o}`);let a=await r.getSettings(o);if(a.status===304){t.trace("Settings are up-to-date");return}if(!a?.success||!a.data){t.warn(`${n}: ${a.message}`);return}e.applyServerSettings(a.data),await i.setItem(s.SettingsKey,JSON.stringify(a.data)),t.trace(`Updated settings: v${a.data.version}`)}catch(n){t.error(`Error updating settings: ${n instanceof Error?n.message:n+""}`)}finally{this._isUpdatingSettings=!1}}static async getSavedServerSettings(e){let{log:t,storage:i}=e.services;try{let r=await i.getItem(s.SettingsKey);return r&&JSON.parse(r)||new W({},0)}catch(r){return t.error(`Error getting saved settings: ${r instanceof Error?r.message:r+""}`),new W({},0)}}};var M=class{constructor(e,t,i,r,n){this.status=e;this.message=t;this.rateLimitRemaining=i;this.settingsVersion=r;this.data=n}get success(){return this.status>=200&&this.status<=299}};var D=class{constructor(e,t=globalThis.fetch?.bind(globalThis)){this.config=e;this.fetch=t}RateLimitRemainingHeader="x-ratelimit-remaining";ConfigurationVersionHeader="x-exceptionless-configversion";getSettings(e){let t=`${this.config.serverUrl}/api/v2/projects/config?v=${e}`;return this.apiFetch(t,{method:"GET"})}async submitEvents(e){let t=`${this.config.serverUrl}/api/v2/events`,i=await this.apiFetch(t,{method:"POST",body:JSON.stringify(e)});return await this.updateSettingsVersion(i.settingsVersion),i}async submitUserDescription(e,t){let i=`${this.config.serverUrl}/api/v2/events/by-ref/${encodeURIComponent(e)}/user-description`,r=await this.apiFetch(i,{method:"POST",body:JSON.stringify(t)});return await this.updateSettingsVersion(r.settingsVersion),r}async submitHeartbeat(e,t){let i=`${this.config.heartbeatServerUrl}/api/v2/events/session/heartbeat?id=${e}&close=${t+""}`;return await this.apiFetch(i,{method:"GET"})}async updateSettingsVersion(e){isNaN(e)?this.config.services.log.error("No config version header was returned."):e>this.config.settingsVersion&&await v.updateSettings(this.config)}async apiFetch(e,t){let i={method:t.method,headers:{Accept:"application/json",Authorization:`Bearer ${this.config.apiKey}`,"User-Agent":this.config.userAgent},body:t.body??null};t.method==="POST"&&this.isHeaders(i.headers)&&(i.headers["Content-Type"]="application/json");let r=await this.fetch(e,i),n=parseInt(r.headers.get(this.RateLimitRemainingHeader)||"",10),o=parseInt(r.headers.get(this.ConfigurationVersionHeader)||"",10),a=await r.text(),l=a&&a.length>0?JSON.parse(a):null;return new M(r.status,r.statusText,n,o,l)}isHeaders(e){return e!==void 0}};var A=class{items=new Map;length(){return Promise.resolve(this.items.size)}clear(){return this.items.clear(),Promise.resolve()}getItem(e){let t=this.items.get(e);return Promise.resolve(t||null)}async key(e){if(e<0)return Promise.resolve(null);let t=await this.keys();if(e>t.length)return Promise.resolve(null);let i=t[e];return Promise.resolve(i||null)}keys(){return Promise.resolve(Array.from(this.items.keys()))}removeItem(e){return this.items.delete(e),Promise.resolve()}setItem(e,t){return this.items.set(e,t),Promise.resolve()}};var j=class{constructor(e="exceptionless-",t=globalThis.localStorage){this.prefix=e;this.storage=t}length(){return Promise.resolve(this.getKeys().length)}clear(){for(let e of this.getKeys())this.storage.removeItem(this.getKey(e));return Promise.resolve()}getItem(e){return Promise.resolve(this.storage.getItem(this.getKey(e)))}key(e){let t=this.getKeys();return Promise.resolve(e<t.length?t[e]:null)}keys(){return Promise.resolve(this.getKeys())}removeItem(e){return this.storage.removeItem(this.getKey(e)),Promise.resolve()}setItem(e,t){return this.storage.setItem(this.getKey(e),t),Promise.resolve()}getKeys(){return Object.keys(this.storage).filter(e=>e.startsWith(this.prefix)).map(e=>e?.substr(this.prefix.length))}getKey(e){return this.prefix+e}};var q=class{constructor(){this.services={lastReferenceIdManager:new P,log:new x,storage:new A,queue:new $(this),submissionClient:new D(this)},m.addDefaultPlugins(this)}defaultTags=[];defaultData={};enabled=!0;services;submissionBatchSize=50;settings={};settingsVersion=0;apiKey="";_serverUrl="https://collector.exceptionless.io";configServerUrl="https://config.exceptionless.io";heartbeatServerUrl="https://heartbeat.exceptionless.io";_updateSettingsWhenIdleInterval=12e4;_dataExclusions=[];_includePrivateInformation=!0;_includeUserName=!0;_includeMachineName=!0;_includeIpAddress=!0;_includeHeaders=!0;_includeCookies=!0;_includePostData=!0;_includeQueryString=!0;_userAgentBotPatterns=[];_plugins=[];_subscribers=[];get isValid(){return this.apiKey?.length>=10}get serverUrl(){return this._serverUrl}set serverUrl(e){e&&(this._serverUrl=e,this.configServerUrl=e,this.heartbeatServerUrl=e)}get updateSettingsWhenIdleInterval(){return this._updateSettingsWhenIdleInterval}set updateSettingsWhenIdleInterval(e){typeof e=="number"&&(e<=0?e=-1:e>0&&e<12e4&&(e=12e4),this._updateSettingsWhenIdleInterval=e)}get dataExclusions(){let e=this.settings["@@DataExclusions"];return this._dataExclusions.concat(e&&e.split(",")||[])}addDataExclusions(...e){this._dataExclusions=[...this._dataExclusions,...e]}get includePrivateInformation(){return this._includePrivateInformation}set includePrivateInformation(e){let t=e===!0;this._includePrivateInformation=t,this._includeUserName=t,this._includeMachineName=t,this._includeIpAddress=t,this._includeHeaders=t,this._includeCookies=t,this._includePostData=t,this._includeQueryString=t}get includeUserName(){return this._includeUserName}set includeUserName(e){this._includeUserName=e===!0}get includeMachineName(){return this._includeMachineName}set includeMachineName(e){this._includeMachineName=e===!0}get includeIpAddress(){return this._includeIpAddress}set includeIpAddress(e){this._includeIpAddress=e===!0}get includeHeaders(){return this._includeHeaders}set includeHeaders(e){this._includeHeaders=e===!0}get includeCookies(){return this._includeCookies}set includeCookies(e){this._includeCookies=e===!0}get includePostData(){return this._includePostData}set includePostData(e){this._includePostData=e===!0}get includeQueryString(){return this._includeQueryString}set includeQueryString(e){this._includeQueryString=e===!0}get userAgentBotPatterns(){let e=this.settings["@@UserAgentBotPatterns"];return this._userAgentBotPatterns.concat(e&&e.split(",")||[])}addUserAgentBotPatterns(...e){this._userAgentBotPatterns=[...this._userAgentBotPatterns,...e]}get plugins(){return this._plugins.sort((e,t)=>e==null&&t==null?0:e?.priority==null?-1:t?.priority==null?1:e.priority==t.priority?0:e.priority>t.priority?1:-1)}addPlugin(e,t,i){let r=i?{name:e,priority:t,run:i}:e;if(!r||!(r.startup||r.run)){this.services.log.error("Add plugin failed: startup or run method not defined");return}r.name||(r.name=b()),r.priority||(r.priority=0),this._plugins.find(n=>n.name===r.name)||this._plugins.push(r)}removePlugin(e){let t=typeof e=="string"?e:e.name||"";if(!t){this.services.log.error("Remove plugin failed: Plugin name not defined");return}let i=this._plugins;for(let r=0;r<i.length;r++)if(i[r].name===t){i.splice(r,1);break}}get version(){return this.defaultData["@version"]}set version(e){e?this.defaultData["@version"]=e:delete this.defaultData["@version"]}setUserIdentity(e,t){let i=typeof e!="string"?e:{identity:e,name:t},r=!i||!i.identity&&!i.name;r?delete this.defaultData["@user"]:this.defaultData["@user"]=i,this.services.log.info(`user identity: ${r?"null":i.identity}`)}get userAgent(){return"exceptionless-js/3.1.0"}useLocalStorage(){globalThis?.localStorage&&(this.services.storage=new j)}usePersistedQueueStorage=!1;sessionsEnabled=!1;currentSessionIdentifier=null;useSessions(e=!0,t=6e4,i=!1){this.sessionsEnabled=!0,i&&this.addPlugin(new w);let r=new _(t);e?this.addPlugin(r):this.removePlugin(r)}originalSettings;applyServerSettings(e){this.originalSettings||(this.originalSettings=JSON.parse(JSON.stringify(this.settings))),this.services.log.trace(`Applying saved settings: v${e.version}`),this.settings=Object.assign(this.originalSettings,e.settings),this.settingsVersion=e.version,this.notifySubscribers()}useDebugLogger(){this.services.log=new S}subscribeServerSettingsChange(e){e&&this._subscribers.push(e)}notifySubscribers(){for(let e of this._subscribers)try{e(this)}catch(t){this.services.log.error(`Error calling subscribe handler: ${t instanceof Error?t.message:t+""}`)}}};var p=class{getException(){return this["@@_Exception"]||null}setException(e){e&&(this["@@_Exception"]=e)}get hasException(){return!!this["@@_Exception"]}markAsUnhandledError(){this["@@_IsUnhandledError"]=!0}get isUnhandledError(){return!!this["@@_IsUnhandledError"]}getSubmissionMethod(){return this["@@_SubmissionMethod"]||null}setSubmissionMethod(e){e&&(this["@@_SubmissionMethod"]=e)}};var I=class{constructor(e){this.client=e}get log(){return this.client.config.services.log}};var B=class{constructor(e,t,i){this.client=e;this.event=t;this.eventContext=i;this.eventContext||(this.eventContext=new p)}cancelled=!1;get log(){return this.client.config.services.log}};var Q=class{target;client;context;_validIdentifierErrorMessage="must contain between 8 and 100 alphanumeric or '-' characters.";constructor(e,t,i){this.target=e,this.client=t,this.context=i||new p}setType(e){return e&&(this.target.type=e),this}setSource(e){return e&&(this.target.source=e),this}setReferenceId(e){if(!this.isValidIdentifier(e))throw new Error(`ReferenceId ${this._validIdentifierErrorMessage}`);return this.target.reference_id=e,this}setEventReference(e,t){if(!e)throw new Error("Invalid name");if(!t||!this.isValidIdentifier(t))throw new Error(`Id ${this._validIdentifierErrorMessage}`);return this.setProperty("@ref:"+e,t),this}setMessage(e){return e&&(this.target.message=e),this}setGeo(e,t){if(e<-90||e>90)throw new Error("Must be a valid latitude value between -90.0 and 90.0.");if(t<-180||t>180)throw new Error("Must be a valid longitude value between -180.0 and 180.0.");return this.target.geo=`${e},${t}`,this}setUserIdentity(e,t){let i=typeof e!="string"?e:{identity:e,name:t};return!i||!i.identity&&!i.name?this:(this.setProperty("@user",i),this)}setUserDescription(e,t){return e&&t&&this.setProperty("@user_description",{email_address:e,description:t}),this}setManualStackingInfo(e,t){if(e){let i={signature_data:e};t&&(i.title=t),this.setProperty("@stack",i)}return this}setManualStackingKey(e,t){if(e){let i={ManualStackingKey:e};this.setManualStackingInfo(i,t)}return this}setValue(e){return e&&(this.target.value=e),this}addTags(...e){return this.target.tags=[...this.target.tags||[],...e],this}setProperty(e,t,i,r){if(!e||t===void 0||t==null)return this;this.target.data||(this.target.data={});let n=this.client.config.dataExclusions.concat(r||[]),o=h(t,n,i);return d(o)||(this.target.data[e]=JSON.parse(o)),this}setContextProperty(e,t){return this.context[e]=t,this}markAsCritical(e){return e&&this.addTags("Critical"),this}submit(){return this.client.submitEvent(this.target,this.context)}isValidIdentifier(e){if(!e)return!0;if(e.length<8||e.length>100)return!1;for(let t=0;t<e.length;t++){let i=e.charCodeAt(t),r=i>=48&&i<=57,n=i>=65&&i<=90||i>=97&&i<=122;if(!(r||n)&&!(i===45))return!1}return!0}};var O=class{constructor(e=new q){this.config=e}_intervalId;_timeoutId;_initialized=!1;async startup(e){if(e&&!this._initialized&&(this._initialized=!0,typeof e=="string"?this.config.apiKey=e:e(this.config),this.config.services.queue.onEventsPosted(()=>Promise.resolve(this.updateSettingsTimer())),await v.applySavedServerSettings(this.config)),!this.config.isValid){this.config.services.log.warn("Exceptionless is not configured and will not process events.");return}this.updateSettingsTimer(!!e),await m.startup(new I(this));let{queue:t}=this.config.services;await t.startup(),this.config.usePersistedQueueStorage&&await t.process(),this.config.sessionsEnabled&&await this.submitSessionStart()}async suspend(){await m.suspend(new I(this));let{queue:e}=this.config.services;await e.suspend(),await e.process(),this.suspendSettingsTimer()}suspendSettingsTimer(){clearTimeout(this._timeoutId),this._timeoutId=void 0,clearInterval(this._intervalId),this._intervalId=void 0}async processQueue(){await this.config.services.queue.process()}updateSettingsTimer(e=!1){if(this.suspendSettingsTimer(),!this.config.isValid)return;let t=this.config.updateSettingsWhenIdleInterval;if(t>0){let i=t;e&&(i=this.config.settingsVersion>0?15e3:5e3),this.config.services.log.info(`Update settings every ${t}ms (${i||0}ms delay)`);let r=()=>void v.updateSettings(this.config);i<t&&(this._timeoutId=setTimeout(r,i),f(this._timeoutId)),this._intervalId=setInterval(r,t),f(this._intervalId)}}createException(e){let t=new p;return t.setException(e),this.createEvent(t).setType("error")}submitException(e){return this.createException(e).submit()}createUnhandledException(e,t){let i=this.createException(e);return i.context.markAsUnhandledError(),i.context.setSubmissionMethod(t||""),i}submitUnhandledException(e,t){return this.createUnhandledException(e,t).submit()}createFeatureUsage(e){return this.createEvent().setType("usage").setSource(e)}submitFeatureUsage(e){return this.createFeatureUsage(e).submit()}createLog(e,t,i){let r=this.createEvent().setType("log");if(i)r=r.setSource(e).setMessage(t).setProperty("@level",i);else if(t)r=r.setSource(e).setMessage(t);else{r=r.setMessage(e);try{let n=this.createLog.caller;r=r.setSource(n&&n.caller&&n.caller.name)}catch(n){this.config.services.log.trace(`Unable to resolve log source: ${n instanceof Error?n.message:n+""}`)}}return r}submitLog(e,t,i){return this.createLog(e,t,i).submit()}createNotFound(e){return this.createEvent().setType("404").setSource(e)}submitNotFound(e){return this.createNotFound(e).submit()}createSessionStart(){return this.createEvent().setType("session")}submitSessionStart(){return this.createSessionStart().submit()}async submitSessionEnd(e){let{currentSessionIdentifier:t,enabled:i,isValid:r,services:n}=this.config,o=e||t;o&&i&&r&&(n.log.info(`Submitting session end: ${o}`),await n.submissionClient.submitHeartbeat(o,!0))}async submitSessionHeartbeat(e){let{currentSessionIdentifier:t,enabled:i,isValid:r,services:n}=this.config,o=e||t;o&&i&&r&&(n.log.info(`Submitting session heartbeat: ${o}`),await n.submissionClient.submitHeartbeat(o,!1))}createEvent(e){return new Q({date:new Date},this,e)}async submitEvent(e,t){let i=new B(this,e,t??new p);if(!e)return i.cancelled=!0,i;if(!this.config.enabled||!this.config.isValid)return this.config.services.log.info("Event submission is currently disabled."),i.cancelled=!0,i;if(e.data||(e.data={}),(!e.tags||!e.tags.length)&&(e.tags=[]),await m.run(i),i.cancelled)return i;let r=i.event;return(!r.type||r.type.length===0)&&(r.type="log"),r.date||(r.date=new Date),await this.config.services.queue.enqueue(r),r.reference_id&&r.reference_id.length>0&&(i.log.info(`Setting last reference id "${r.reference_id}"`),this.config.services.lastReferenceIdManager.setLast(r.reference_id)),i}async updateUserEmailAndDescription(e,t,i){if(!e||!t||!i||!this.config.enabled||!this.config.isValid)return;let r={email_address:t,description:i},n=await this.config.services.submissionClient.submitUserDescription(e,r);n.success||this.config.services.log.error(`Failed to submit user email and description for event "${e}": ${n.status} ${n.message}`)}getLastReferenceId(){return this.config.services.lastReferenceIdManager.getLast()}};export{q as Configuration,C as ConfigurationDefaultsPlugin,S as ConsoleLog,$ as DefaultEventQueue,P as DefaultLastReferenceIdManager,D as DefaultSubmissionClient,U as DuplicateCheckerPlugin,Q as EventBuilder,p as EventContext,k as EventExclusionPlugin,B as EventPluginContext,m as EventPluginManager,O as ExceptionlessClient,_ as HeartbeatPlugin,X as IgnoredErrorProperties,A as InMemoryStorage,z as KnownEventDataKeys,j as LocalStorage,x as NullLog,I as PluginContext,L as ReferenceIdPlugin,M as Response,w as SessionIdManagementPlugin,v as SettingsManager,R as SimpleErrorPlugin,T as SubmissionMethodPlugin,G as endsWith,ee as getCookies,N as getHashCode,b as guid,d as isEmpty,y as isMatch,ie as parseQueryString,te as parseVersion,Z as prune,re as randomNumber,F as startsWith,h as stringify,V as toBoolean,ne as toError};
//# sourceMappingURL=index.bundle.min.js.map

@@ -16,3 +16,3 @@ export { Configuration } from "./configuration/Configuration.js";

export type { ModuleInfo } from "./models/data/ModuleInfo.js";
export type { SimpleError, ErrorInfo, InnerErrorInfo, MethodInfo, ParameterInfo, StackFrameInfo, } from "./models/data/ErrorInfo.js";
export type { SimpleError, ErrorInfo, InnerErrorInfo, MethodInfo, ParameterInfo, StackFrameInfo } from "./models/data/ErrorInfo.js";
export { ConfigurationDefaultsPlugin } from "./plugins/default/ConfigurationDefaultsPlugin.js";

@@ -42,3 +42,3 @@ export { DuplicateCheckerPlugin } from "./plugins/default/DuplicateCheckerPlugin.js";

export { ExceptionlessClient } from "./ExceptionlessClient.js";
export { endsWith, getCookies, getHashCode, guid, isEmpty, isMatch, parseQueryString, parseVersion, prune, randomNumber, startsWith, stringify, toBoolean, toError, } from "./Utils.js";
export { endsWith, getCookies, getHashCode, guid, isEmpty, isMatch, parseQueryString, parseVersion, prune, randomNumber, startsWith, stringify, toBoolean, toError } from "./Utils.js";
//# sourceMappingURL=index.d.ts.map

@@ -26,3 +26,3 @@ export { Configuration } from "./configuration/Configuration.js";

export { ExceptionlessClient } from "./ExceptionlessClient.js";
export { endsWith, getCookies, getHashCode, guid, isEmpty, isMatch, parseQueryString, parseVersion, prune, randomNumber, startsWith, stringify, toBoolean, toError, } from "./Utils.js";
export { endsWith, getCookies, getHashCode, guid, isEmpty, isMatch, parseQueryString, parseVersion, prune, randomNumber, startsWith, stringify, toBoolean, toError } from "./Utils.js";
//# sourceMappingURL=index.js.map
export class DefaultLastReferenceIdManager {
constructor() {
/**
* Gets the last event's reference id that was submitted to the server.
*/
this._lastReferenceId = null;
}
/**
* Gets the last event's reference id that was submitted to the server.
*/
_lastReferenceId = null;
/**
* Gets the last event's reference id that was submitted to the server.
*/
getLast() {

@@ -12,0 +10,0 @@ return this._lastReferenceId;

export class NullLog {
trace(_) { }
info(_) { }
warn(_) { }
error(_) { }
trace(_) {
/* empty */
}
info(_) {
/* empty */
}
warn(_) {
/* empty */
}
error(_) {
/* empty */
}
}
//# sourceMappingURL=NullLog.js.map
import { isEmpty, stringify } from "../../Utils.js";
export class ConfigurationDefaultsPlugin {
constructor() {
this.priority = 10;
this.name = "ConfigurationDefaultsPlugin";
}
priority = 10;
name = "ConfigurationDefaultsPlugin";
run(context) {

@@ -11,3 +9,3 @@ const { dataExclusions, defaultData, defaultTags } = context.client.config;

if (defaultTags) {
ev.tags = [...ev.tags || [], ...defaultTags];
ev.tags = [...(ev.tags || []), ...defaultTags];
}

@@ -14,0 +12,0 @@ if (defaultData) {

import { KnownEventDataKeys } from "../../models/Event.js";
import { allowProcessToExitWithoutWaitingForTimerOrInterval, getHashCode } from "../../Utils.js";
export class DuplicateCheckerPlugin {
priority = 1010;
name = "DuplicateCheckerPlugin";
_mergedEvents = [];
_processedHashCodes = [];
_getCurrentTime;
_intervalId;
_interval;
constructor(getCurrentTime = () => Date.now(), interval = 30000) {
this.priority = 1010;
this.name = "DuplicateCheckerPlugin";
this._mergedEvents = [];
this._processedHashCodes = [];
this._getCurrentTime = getCurrentTime;

@@ -49,4 +52,3 @@ this._interval = interval;

}
if (!context.cancelled &&
this._processedHashCodes.some((h) => h.hash === hashCode && h.timestamp >= (now - this._interval))) {
if (!context.cancelled && this._processedHashCodes.some((h) => h.hash === hashCode && h.timestamp >= now - this._interval)) {
context.log.trace("Adding event with hash: " + hashCode);

@@ -74,2 +76,5 @@ this._mergedEvents.push(new MergedEvent(hashCode, context, count));

class MergedEvent {
hashCode;
_count;
_context;
constructor(hashCode, context, count) {

@@ -76,0 +81,0 @@ this.hashCode = hashCode;

import { KnownEventDataKeys } from "../../models/Event.js";
import { isMatch, startsWith, toBoolean } from "../../Utils.js";
export class EventExclusionPlugin {
constructor() {
this.priority = 45;
this.name = "EventExclusionPlugin";
}
priority = 45;
name = "EventExclusionPlugin";
run(context) {

@@ -9,0 +7,0 @@ const ev = context.event;

import { KnownEventDataKeys } from "../../models/Event.js";
import { allowProcessToExitWithoutWaitingForTimerOrInterval } from "../../Utils.js";
export class HeartbeatPlugin {
priority = 100;
name = "HeartbeatPlugin";
_interval;
_intervalId;
constructor(heartbeatInterval = 60000) {
this.priority = 100;
this.name = "HeartbeatPlugin";
this._interval = heartbeatInterval >= 30000 ? heartbeatInterval : 60000;

@@ -8,0 +10,0 @@ }

import { guid } from "../../Utils.js";
export class ReferenceIdPlugin {
constructor() {
this.priority = 20;
this.name = "ReferenceIdPlugin";
}
priority = 20;
name = "ReferenceIdPlugin";
run(context) {

@@ -8,0 +6,0 @@ if (!context.event.reference_id && context.event.type === "error") {

import { guid } from "../../Utils.js";
export class SessionIdManagementPlugin {
constructor() {
this.priority = 25;
this.name = "SessionIdManagementPlugin";
}
priority = 25;
name = "SessionIdManagementPlugin";
run(context) {

@@ -8,0 +6,0 @@ const ev = context.event;

@@ -22,6 +22,4 @@ import { isEmpty, stringify } from "../../Utils.js";

export class SimpleErrorPlugin {
constructor() {
this.priority = 30;
this.name = "SimpleErrorPlugin";
}
priority = 30;
name = "SimpleErrorPlugin";
async run(context) {

@@ -28,0 +26,0 @@ const exception = context.eventContext.getException();

import { KnownEventDataKeys } from "../../models/Event.js";
export class SubmissionMethodPlugin {
constructor() {
this.priority = 100;
this.name = "SubmissionMethodPlugin";
}
priority = 100;
name = "SubmissionMethodPlugin";
run(context) {

@@ -8,0 +6,0 @@ const submissionMethod = context.eventContext.getSubmissionMethod();

import { EventContext } from "../models/EventContext.js";
export class EventPluginContext {
client;
event;
eventContext;
cancelled = false;
constructor(client, event, eventContext) {

@@ -7,3 +11,2 @@ this.client = client;

this.eventContext = eventContext;
this.cancelled = false;
if (!this.eventContext)

@@ -10,0 +13,0 @@ this.eventContext = new EventContext();

@@ -17,3 +17,3 @@ import { ConfigurationDefaultsPlugin } from "./default/ConfigurationDefaultsPlugin.js";

catch (ex) {
context.log.error(`Error running plugin startup"${plugin.name}": ${ex instanceof Error ? ex.message : ex + ''}`);
context.log.error(`Error running plugin startup"${plugin.name}": ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -31,3 +31,3 @@ }

catch (ex) {
context.log.error(`Error running plugin suspend"${plugin.name}": ${ex instanceof Error ? ex.message : ex + ''}`);
context.log.error(`Error running plugin suspend"${plugin.name}": ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -49,3 +49,3 @@ }

context.cancelled = true;
context.log.error(`Error running plugin "${plugin.name}": ${ex instanceof Error ? ex.message : ex + ''}. Discarding Event.`);
context.log.error(`Error running plugin "${plugin.name}": ${ex instanceof Error ? ex.message : ex + ""}. Discarding Event.`);
}

@@ -52,0 +52,0 @@ }

export class PluginContext {
client;
constructor(client) {

@@ -3,0 +4,0 @@ this.client = client;

import { allowProcessToExitWithoutWaitingForTimerOrInterval } from "../Utils.js";
export class DefaultEventQueue {
config;
maxItems;
/**
* A list of handlers that will be fired when events are submitted.
* @type {Array}
* @private
*/
_handlers = [];
/**
* Suspends processing until the specified time.
* @type {Date}
* @private
*/
_suspendProcessingUntil;
/**
* Discards queued items until the specified time.
* @type {Date}
* @private
*/
_discardQueuedItemsUntil;
/**
* Returns true if the queue is processing.
* @type {boolean}
* @private
*/
_processingQueue = false;
/**
* Processes the queue every xx seconds.
* @type {Interval}
* @private
*/
_queueIntervalId;
QUEUE_PREFIX = "q:";
_lastFileTimestamp = 0;
_queue = [];
_loadPersistedEvents = true;
constructor(config, maxItems = 250) {
this.config = config;
this.maxItems = maxItems;
/**
* A list of handlers that will be fired when events are submitted.
* @type {Array}
* @private
*/
this._handlers = [];
/**
* Returns true if the queue is processing.
* @type {boolean}
* @private
*/
this._processingQueue = false;
this.QUEUE_PREFIX = "q:";
this._lastFileTimestamp = 0;
this._queue = [];
this._loadPersistedEvents = true;
}

@@ -72,3 +92,3 @@ async enqueue(event) {

log.info(`Sending ${items.length} events to ${this.config.serverUrl}`);
const events = items.map(i => i.event);
const events = items.map((i) => i.event);
const response = await this.config.services.submissionClient.submitEvents(events);

@@ -81,3 +101,3 @@ await this.processSubmissionResponse(response, items);

catch (ex) {
log.error(`Error processing queue: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error processing queue: ${ex instanceof Error ? ex.message : ex + ""}`);
await this.suspendProcessing();

@@ -107,3 +127,3 @@ this._processingQueue = false;

config.services.log.info(`Suspending processing for ${durationInMinutes} minutes.`);
this._suspendProcessingUntil = new Date(currentDate.getTime() + (durationInMinutes * 60000));
this._suspendProcessingUntil = new Date(currentDate.getTime() + durationInMinutes * 60000);
if (discardFutureQueuedItems) {

@@ -128,3 +148,3 @@ this._discardQueuedItemsUntil = this._suspendProcessingUntil;

catch (ex) {
this.config.services.log.error(`Error calling onEventsPosted handler: ${ex instanceof Error ? ex.message : ex + ''}`);
this.config.services.log.error(`Error calling onEventsPosted handler: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -134,8 +154,6 @@ }

areQueuedItemsDiscarded() {
return this._discardQueuedItemsUntil &&
this._discardQueuedItemsUntil > new Date() || false;
return (this._discardQueuedItemsUntil && this._discardQueuedItemsUntil > new Date()) || false;
}
isQueueProcessingSuspended() {
return this._suspendProcessingUntil &&
this._suspendProcessingUntil > new Date() || false;
return (this._suspendProcessingUntil && this._suspendProcessingUntil > new Date()) || false;
}

@@ -211,3 +229,3 @@ async onProcessQueue() {

catch (ex) {
log.error(`Error loading queue items from storage: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error loading queue items from storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -229,3 +247,3 @@ }

catch (ex) {
log.error(`Error removing oldest queue entry from storage: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error removing oldest queue entry from storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -239,3 +257,3 @@ }

catch (ex) {
log.error(`Error saving queue entry to storage: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error saving queue entry to storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -246,3 +264,3 @@ }

async removeEvents(items) {
const files = items.map(i => i.file);
const files = items.map((i) => i.file);
if (this.config.usePersistedQueueStorage) {

@@ -255,9 +273,9 @@ const { log, storage } = this.config.services;

catch (ex) {
log.error(`Error removing queue item from storage: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error removing queue item from storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}
}
}
this._queue = this._queue.filter(i => !files.includes(i.file));
this._queue = this._queue.filter((i) => !files.includes(i.file));
}
}
//# sourceMappingURL=DefaultEventQueue.js.map
export class InMemoryStorage {
constructor() {
this.items = new Map();
}
items = new Map();
length() {

@@ -6,0 +4,0 @@ return Promise.resolve(this.items.size);

export class LocalStorage {
prefix;
storage;
constructor(prefix = "exceptionless-", storage = globalThis.localStorage) {

@@ -35,4 +37,4 @@ this.prefix = prefix;

return Object.keys(this.storage)
.filter(key => key.startsWith(this.prefix))
.map(key => key?.substr(this.prefix.length));
.filter((key) => key.startsWith(this.prefix))
.map((key) => key?.substr(this.prefix.length));
}

@@ -39,0 +41,0 @@ getKey(key) {

@@ -1,9 +0,11 @@

import { SettingsManager, } from "../configuration/SettingsManager.js";
import { SettingsManager } from "../configuration/SettingsManager.js";
import { Response } from "./Response.js";
export class DefaultSubmissionClient {
config;
fetch;
RateLimitRemainingHeader = "x-ratelimit-remaining";
ConfigurationVersionHeader = "x-exceptionless-configversion";
constructor(config, fetch = globalThis.fetch?.bind(globalThis)) {
this.config = config;
this.fetch = fetch;
this.RateLimitRemainingHeader = "x-ratelimit-remaining";
this.ConfigurationVersionHeader = "x-exceptionless-configversion";
}

@@ -13,3 +15,3 @@ getSettings(version) {

return this.apiFetch(url, {
method: "GET",
method: "GET"
});

@@ -21,3 +23,3 @@ }

method: "POST",
body: JSON.stringify(events),
body: JSON.stringify(events)
});

@@ -31,3 +33,3 @@ await this.updateSettingsVersion(response.settingsVersion);

method: "POST",
body: JSON.stringify(description),
body: JSON.stringify(description)
});

@@ -40,3 +42,3 @@ await this.updateSettingsVersion(response.settingsVersion);

return await this.apiFetch(url, {
method: "GET",
method: "GET"
});

@@ -57,5 +59,5 @@ }

headers: {
"Accept": "application/json",
"Authorization": `Bearer ${this.config.apiKey}`,
"User-Agent": this.config.userAgent,
Accept: "application/json",
Authorization: `Bearer ${this.config.apiKey}`,
"User-Agent": this.config.userAgent
},

@@ -62,0 +64,0 @@ body: options.body ?? null

export class Response {
status;
message;
rateLimitRemaining;
settingsVersion;
data;
constructor(status, message, rateLimitRemaining, settingsVersion, data) {

@@ -3,0 +8,0 @@ this.status = status;

@@ -8,3 +8,3 @@ export function getHashCode(source) {

const character = source.charCodeAt(index);
hash = ((hash << 5) - hash) + character;
hash = (hash << 5) - hash + character;
hash |= 0;

@@ -27,6 +27,7 @@ }

function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() +
s4() + s4();
return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
}

@@ -253,3 +254,3 @@ export function parseVersion(source) {

const depth = parentIsArray ? currentDepth + 1 : currentDepth;
return normalizedValue.map(e => pruneImpl(e, maxDepth, depth, seen, true));
return normalizedValue.map((e) => pruneImpl(e, maxDepth, depth, seen, true));
}

@@ -306,3 +307,3 @@ if (normalizedValue instanceof Date) {

}
if (input === null || typeof input !== "number" && typeof input !== "string") {
if (input === null || (typeof input !== "number" && typeof input !== "string")) {
return defaultValue;

@@ -309,0 +310,0 @@ }

{
"name": "@exceptionless/core",
"version": "3.0.5",
"version": "3.1.0",
"description": "JavaScript client for Exceptionless",

@@ -48,4 +48,4 @@ "author": {

"scripts": {
"build": "tsc -p tsconfig.json && esbuild src/index.ts --bundle --sourcemap --target=es2021 --format=esm --outfile=dist/index.bundle.js && esbuild src/index.ts --bundle --minify --sourcemap --target=es2021 --format=esm --outfile=dist/index.bundle.min.js",
"watch": "tsc -p tsconfig.json -w --preserveWatchOutput & esbuild src/index.ts --bundle --sourcemap --target=es2021 --format=esm --watch --outfile=dist/index.bundle.js",
"build": "tsc -p tsconfig.json && esbuild src/index.ts --bundle --sourcemap --target=es2022 --format=esm --outfile=dist/index.bundle.js && esbuild src/index.ts --bundle --minify --sourcemap --target=es2022 --format=esm --outfile=dist/index.bundle.min.js",
"watch": "tsc -p tsconfig.json -w --preserveWatchOutput & esbuild src/index.ts --bundle --sourcemap --target=es2022 --format=esm --watch --outfile=dist/index.bundle.js",
"test": "jest",

@@ -60,8 +60,8 @@ "test:watch": "jest --watch"

"@jest/globals": "^29.7.0",
"esbuild": "^0.19.5",
"esbuild": "^0.20.2",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-ts-webcompat-resolver": "^1.0.0",
"ts-jest": "^29.1.1"
"ts-jest": "^29.1.2"
}
}

@@ -31,3 +31,3 @@ # Exceptionless Client SDK

await Exceptionless.startup(c => {
await Exceptionless.startup((c) => {
c.apiKey = "API_KEY_HERE";

@@ -34,0 +34,0 @@ c.setUserIdentity("12345678", "Blake");

@@ -30,3 +30,3 @@ import { DefaultLastReferenceIdManager } from "../lastReferenceIdManager/DefaultLastReferenceIdManager.js";

queue: new DefaultEventQueue(this),
submissionClient: new DefaultSubmissionClient(this),
submissionClient: new DefaultSubmissionClient(this)
};

@@ -185,5 +185,3 @@

const exclusions: string = this.settings["@@DataExclusions"];
return this._dataExclusions.concat(
exclusions && exclusions.split(",") || [],
);
return this._dataExclusions.concat((exclusions && exclusions.split(",")) || []);
}

@@ -338,5 +336,3 @@

const patterns: string = this.settings["@@UserAgentBotPatterns"];
return this._userAgentBotPatterns.concat(
patterns && patterns.split(",") || [],
);
return this._userAgentBotPatterns.concat((patterns && patterns.split(",")) || []);
}

@@ -350,6 +346,3 @@

public addUserAgentBotPatterns(...userAgentBotPatterns: string[]): void {
this._userAgentBotPatterns = [
...this._userAgentBotPatterns,
...userAgentBotPatterns,
];
this._userAgentBotPatterns = [...this._userAgentBotPatterns, ...userAgentBotPatterns];
}

@@ -392,5 +385,3 @@

public addPlugin(pluginOrName: IEventPlugin | string | undefined, priority?: number, pluginAction?: (context: EventPluginContext) => Promise<void>): void {
const plugin: IEventPlugin = pluginAction
? <IEventPlugin>{ name: pluginOrName as string, priority, run: pluginAction }
: pluginOrName as IEventPlugin;
const plugin: IEventPlugin = pluginAction ? <IEventPlugin>{ name: pluginOrName as string, priority, run: pluginAction } : (pluginOrName as IEventPlugin);

@@ -410,3 +401,3 @@ if (!plugin || !(plugin.startup || plugin.run)) {

if (!this._plugins.find(f => f.name === plugin.name)) {
if (!this._plugins.find((f) => f.name === plugin.name)) {
this._plugins.push(plugin);

@@ -420,5 +411,3 @@ }

public removePlugin(pluginOrName: IEventPlugin | string): void {
const name: string = typeof pluginOrName === "string"
? pluginOrName
: pluginOrName.name || "";
const name: string = typeof pluginOrName === "string" ? pluginOrName : pluginOrName.name || "";
if (!name) {

@@ -463,5 +452,3 @@ this.services.log.error("Remove plugin failed: Plugin name not defined");

public setUserIdentity(userInfoOrIdentity: UserInfo | string, name?: string): void {
const userInfo: UserInfo = typeof userInfoOrIdentity !== "string"
? userInfoOrIdentity
: <UserInfo>{ identity: userInfoOrIdentity, name };
const userInfo: UserInfo = typeof userInfoOrIdentity !== "string" ? userInfoOrIdentity : <UserInfo>{ identity: userInfoOrIdentity, name };

@@ -482,3 +469,3 @@ const shouldRemove: boolean = !userInfo || (!userInfo.identity && !userInfo.name);

public get userAgent(): string {
return "exceptionless-js/3.0.5";
return "exceptionless-js/3.1.0";
}

@@ -561,3 +548,3 @@

} catch (ex) {
this.services.log.error(`Error calling subscribe handler: ${ex instanceof Error ? ex.message : ex + ''}`);
this.services.log.error(`Error calling subscribe handler: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -564,0 +551,0 @@ }

@@ -7,3 +7,3 @@ import { Configuration } from "./Configuration.js";

public version: number
) { }
) {}
}

@@ -60,3 +60,3 @@

} catch (ex) {
log.error(`Error updating settings: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error updating settings: ${ex instanceof Error ? ex.message : ex + ""}`);
} finally {

@@ -71,5 +71,5 @@ this._isUpdatingSettings = false;

const settings = await storage.getItem(SettingsManager.SettingsKey);
return settings && JSON.parse(settings) as ServerSettings || new ServerSettings({}, 0);
return (settings && (JSON.parse(settings) as ServerSettings)) || new ServerSettings({}, 0);
} catch (ex) {
log.error(`Error getting saved settings: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error getting saved settings: ${ex instanceof Error ? ex.message : ex + ""}`);
return new ServerSettings({}, 0);

@@ -76,0 +76,0 @@ }

@@ -79,5 +79,3 @@ import { ExceptionlessClient } from "./ExceptionlessClient.js";

if (longitude < -180.0 || longitude > 180.0) {
throw new Error(
"Must be a valid longitude value between -180.0 and 180.0.",
);
throw new Error("Must be a valid longitude value between -180.0 and 180.0.");
}

@@ -93,5 +91,3 @@

public setUserIdentity(userInfoOrIdentity: UserInfo | string, name?: string): EventBuilder {
const userInfo = typeof userInfoOrIdentity !== "string"
? userInfoOrIdentity
: { identity: userInfoOrIdentity, name };
const userInfo = typeof userInfoOrIdentity !== "string" ? userInfoOrIdentity : { identity: userInfoOrIdentity, name };
if (!userInfo || (!userInfo.identity && !userInfo.name)) {

@@ -115,3 +111,3 @@ return this;

email_address: emailAddress,
description,
description
});

@@ -169,3 +165,3 @@ }

public addTags(...tags: string[]): EventBuilder {
this.target.tags = [...this.target.tags || [], ...tags];
this.target.tags = [...(this.target.tags || []), ...tags];
return this;

@@ -183,3 +179,3 @@ }

public setProperty(name: string, value: unknown, maxDepth?: number, excludedPropertyNames?: string[]): EventBuilder {
if (!name || (value === undefined || value == null)) {
if (!name || value === undefined || value == null) {
return this;

@@ -229,5 +225,4 @@ }

const code = value.charCodeAt(index);
const isDigit = (code >= 48) && (code <= 57);
const isLetter = ((code >= 65) && (code <= 90)) ||
((code >= 97) && (code <= 122));
const isDigit = code >= 48 && code <= 57;
const isLetter = (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
const isMinus = code === 45;

@@ -234,0 +229,0 @@

@@ -17,3 +17,3 @@ import { Configuration } from "./configuration/Configuration.js";

public constructor(public config: Configuration = new Configuration()) { }
public constructor(public config: Configuration = new Configuration()) {}

@@ -31,5 +31,3 @@ /** Resume background submission, resume any timers. */

this.config.services.queue.onEventsPosted(() =>
Promise.resolve(this.updateSettingsTimer())
);
this.config.services.queue.onEventsPosted(() => Promise.resolve(this.updateSettingsTimer()));
await SettingsManager.applySavedServerSettings(this.config);

@@ -94,4 +92,3 @@ }

// TODO: Look into better async scheduling..
const updateSettings = () =>
void SettingsManager.updateSettings(this.config);
const updateSettings = () => void SettingsManager.updateSettings(this.config);
if (initialDelay < interval) {

@@ -144,4 +141,3 @@ this._timeoutId = setTimeout(updateSettings, initialDelay);

if (level) {
builder = builder.setSource(sourceOrMessage).setMessage(message)
.setProperty(KnownEventDataKeys.Level, level);
builder = builder.setSource(sourceOrMessage).setMessage(message).setProperty(KnownEventDataKeys.Level, level);
} else if (message) {

@@ -155,7 +151,5 @@ builder = builder.setSource(sourceOrMessage).setMessage(message);

const caller = this.createLog.caller;
builder = builder.setSource(
caller && caller.caller && caller.caller.name,
);
builder = builder.setSource(caller && caller.caller && caller.caller.name);
} catch (ex) {
this.config.services.log.trace(`Unable to resolve log source: ${ex instanceof Error ? ex.message : ex + ''}`);
this.config.services.log.trace(`Unable to resolve log source: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -281,5 +275,3 @@ }

if (!response.success) {
this.config.services.log.error(
`Failed to submit user email and description for event "${referenceId}": ${response.status} ${response.message}`,
);
this.config.services.log.error(`Failed to submit user email and description for event "${referenceId}": ${response.status} ${response.message}`);
}

@@ -286,0 +278,0 @@ }

@@ -20,10 +20,3 @@ export { Configuration } from "./configuration/Configuration.js";

export type {
SimpleError,
ErrorInfo,
InnerErrorInfo,
MethodInfo,
ParameterInfo,
StackFrameInfo,
} from "./models/data/ErrorInfo.js";
export type { SimpleError, ErrorInfo, InnerErrorInfo, MethodInfo, ParameterInfo, StackFrameInfo } from "./models/data/ErrorInfo.js";

@@ -36,3 +29,3 @@ export { ConfigurationDefaultsPlugin } from "./plugins/default/ConfigurationDefaultsPlugin.js";

export { SessionIdManagementPlugin } from "./plugins/default/SessionIdManagementPlugin.js";
export { IgnoredErrorProperties, SimpleErrorPlugin } from "./plugins/default/SimpleErrorPlugin.js"
export { IgnoredErrorProperties, SimpleErrorPlugin } from "./plugins/default/SimpleErrorPlugin.js";
export { SubmissionMethodPlugin } from "./plugins/default/SubmissionMethodPlugin.js";

@@ -73,3 +66,3 @@ export { EventContext } from "./models/EventContext.js";

toBoolean,
toError,
toError
} from "./Utils.js";

@@ -5,6 +5,14 @@ /* eslint-disable @typescript-eslint/no-unused-vars */

export class NullLog implements ILog {
public trace(_: string): void { /* empty */ }
public info(_: string): void { /* empty */ }
public warn(_: string): void { /* empty */ }
public error(_: string): void { /* empty */ }
public trace(_: string): void {
/* empty */
}
public info(_: string): void {
/* empty */
}
public warn(_: string): void {
/* empty */
}
public error(_: string): void {
/* empty */
}
}

@@ -44,3 +44,3 @@ import { ErrorInfo, SimpleError } from "./data/ErrorInfo.js";

SubmissionMethod = "@submission_method",
ManualStackingInfo = "@stack",
ManualStackingInfo = "@stack"
}

@@ -47,0 +47,0 @@

@@ -1,2 +0,1 @@

const enum KnownContextKeys {

@@ -12,3 +11,3 @@ Exception = "@@_Exception",

public getException(): Error | null {
return this[KnownContextKeys.Exception] as Error || null;
return (this[KnownContextKeys.Exception] as Error) || null;
}

@@ -35,3 +34,3 @@

public getSubmissionMethod(): string | null {
return this[KnownContextKeys.SubmissionMethod] as string || null;
return (this[KnownContextKeys.SubmissionMethod] as string) || null;
}

@@ -38,0 +37,0 @@

@@ -14,3 +14,3 @@ import { isEmpty, stringify } from "../../Utils.js";

if (defaultTags) {
ev.tags = [...ev.tags || [], ...defaultTags];
ev.tags = [...(ev.tags || []), ...defaultTags];
}

@@ -17,0 +17,0 @@

@@ -17,6 +17,3 @@ import { InnerErrorInfo } from "../../models/data/ErrorInfo.js";

constructor(
getCurrentTime: () => number = () => Date.now(),
interval: number = 30000
) {
constructor(getCurrentTime: () => number = () => Date.now(), interval: number = 30000) {
this._getCurrentTime = getCurrentTime;

@@ -69,8 +66,3 @@ this._interval = interval;

if (
!context.cancelled &&
this._processedHashCodes.some((h) =>
h.hash === hashCode && h.timestamp >= (now - this._interval)
)
) {
if (!context.cancelled && this._processedHashCodes.some((h) => h.hash === hashCode && h.timestamp >= now - this._interval)) {
context.log.trace("Adding event with hash: " + hashCode);

@@ -77,0 +69,0 @@ this._mergedEvents.push(new MergedEvent(hashCode, context, count));

@@ -76,3 +76,3 @@ import { KnownEventDataKeys, LogLevel } from "../../models/Event.js";

source: string | undefined,
defaultValue: string | boolean,
defaultValue: string | boolean
): string | boolean {

@@ -96,5 +96,3 @@ if (!type) {

// sort object keys longest first, then alphabetically.
const sortedKeys = Object.keys(configSettings).sort((a, b) =>
b.length - a.length || a.localeCompare(b)
);
const sortedKeys = Object.keys(configSettings).sort((a, b) => b.length - a.length || a.localeCompare(b));
for (const key of sortedKeys) {

@@ -101,0 +99,0 @@ if (!startsWith(key.toLowerCase(), sourcePrefix)) {

@@ -49,6 +49,3 @@ import { KnownEventDataKeys } from "../../models/Event.js";

if (config.currentSessionIdentifier) {
this._intervalId = setInterval(
() => void context.client.submitSessionHeartbeat(<string>config.currentSessionIdentifier),
this._interval
);
this._intervalId = setInterval(() => void context.client.submitSessionHeartbeat(<string>config.currentSessionIdentifier), this._interval);

@@ -55,0 +52,0 @@ allowProcessToExitWithoutWaitingForTimerOrInterval(this._intervalId);

@@ -1,2 +0,1 @@

import { EventPluginContext } from "../EventPluginContext.js";

@@ -44,3 +43,3 @@ import { IEventPlugin } from "../IEventPlugin.js";

data: {}
}
};

@@ -50,3 +49,3 @@ const exclusions = context.client.config.dataExclusions.concat(IgnoredErrorProperties);

if (!isEmpty(additionalData)) {
(error.data as Record<string, unknown>)["@ext"] = JSON.parse(additionalData);
error.data!["@ext"] = JSON.parse(additionalData);
}

@@ -53,0 +52,0 @@

@@ -9,5 +9,8 @@ import { ExceptionlessClient } from "../ExceptionlessClient.js";

constructor(public client: ExceptionlessClient, public event: Event, public eventContext: EventContext) {
if (!this.eventContext)
this.eventContext = new EventContext();
constructor(
public client: ExceptionlessClient,
public event: Event,
public eventContext: EventContext
) {
if (!this.eventContext) this.eventContext = new EventContext();
}

@@ -14,0 +17,0 @@

@@ -21,3 +21,3 @@ import { Configuration } from "../configuration/Configuration.js";

} catch (ex) {
context.log.error(`Error running plugin startup"${<string>plugin.name}": ${ex instanceof Error ? ex.message : ex + ''}`);
context.log.error(`Error running plugin startup"${<string>plugin.name}": ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -36,3 +36,3 @@ }

} catch (ex) {
context.log.error(`Error running plugin suspend"${<string>plugin.name}": ${ex instanceof Error ? ex.message : ex + ''}`);
context.log.error(`Error running plugin suspend"${<string>plugin.name}": ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -56,3 +56,3 @@ }

context.cancelled = true;
context.log.error(`Error running plugin "${<string>plugin.name}": ${ex instanceof Error ? ex.message : ex + ''}. Discarding Event.`);
context.log.error(`Error running plugin "${<string>plugin.name}": ${ex instanceof Error ? ex.message : ex + ""}. Discarding Event.`);
}

@@ -59,0 +59,0 @@ }

@@ -5,3 +5,3 @@ import { ExceptionlessClient } from "../ExceptionlessClient.js";

export class PluginContext {
constructor(public client: ExceptionlessClient) { }
constructor(public client: ExceptionlessClient) {}

@@ -8,0 +8,0 @@ public get log(): ILog {

@@ -9,4 +9,4 @@ import { Configuration } from "../configuration/Configuration.js";

interface EventQueueItem {
file: string,
event: Event
file: string;
event: Event;
}

@@ -58,3 +58,3 @@

private maxItems: number = 250
) { }
) {}

@@ -122,3 +122,3 @@ public async enqueue(event: Event): Promise<void> {

log.info(`Sending ${items.length} events to ${this.config.serverUrl}`);
const events = items.map(i => i.event);
const events = items.map((i) => i.event);
const response = await this.config.services.submissionClient.submitEvents(events);

@@ -130,3 +130,3 @@ await this.processSubmissionResponse(response, items);

} catch (ex) {
log.error(`Error processing queue: ${ex instanceof Error ? ex.message : ex + ''}`);
log.error(`Error processing queue: ${ex instanceof Error ? ex.message : ex + ""}`);
await this.suspendProcessing();

@@ -162,3 +162,3 @@ this._processingQueue = false;

config.services.log.info(`Suspending processing for ${durationInMinutes} minutes.`);
this._suspendProcessingUntil = new Date(currentDate.getTime() + (durationInMinutes * 60000));
this._suspendProcessingUntil = new Date(currentDate.getTime() + durationInMinutes * 60000);

@@ -186,3 +186,3 @@ if (discardFutureQueuedItems) {

} catch (ex) {
this.config.services.log.error(`Error calling onEventsPosted handler: ${ex instanceof Error ? ex.message : ex + ''}`);
this.config.services.log.error(`Error calling onEventsPosted handler: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -193,9 +193,7 @@ }

private areQueuedItemsDiscarded(): boolean {
return this._discardQueuedItemsUntil &&
this._discardQueuedItemsUntil > new Date() || false;
return (this._discardQueuedItemsUntil && this._discardQueuedItemsUntil > new Date()) || false;
}
private isQueueProcessingSuspended(): boolean {
return this._suspendProcessingUntil &&
this._suspendProcessingUntil > new Date() || false;
return (this._suspendProcessingUntil && this._suspendProcessingUntil > new Date()) || false;
}

@@ -277,8 +275,7 @@

const json = await storage.getItem(file);
if (json)
this._queue.push({ file, event: JSON.parse(json) as Event });
if (json) this._queue.push({ file, event: JSON.parse(json) as Event });
}
}
} catch (ex) {
log.error(`Error loading queue items from storage: ${ex instanceof Error ? ex.message : ex + ''}`)
log.error(`Error loading queue items from storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -301,3 +298,3 @@ }

} catch (ex) {
log.error(`Error removing oldest queue entry from storage: ${ex instanceof Error ? ex.message : ex + ''}`)
log.error(`Error removing oldest queue entry from storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -311,3 +308,3 @@ }

} catch (ex) {
log.error(`Error saving queue entry to storage: ${ex instanceof Error ? ex.message : ex + ''}`)
log.error(`Error saving queue entry to storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -320,3 +317,3 @@ }

private async removeEvents(items: EventQueueItem[]): Promise<void> {
const files = items.map(i => i.file);
const files = items.map((i) => i.file);
if (this.config.usePersistedQueueStorage) {

@@ -329,3 +326,3 @@ const { log, storage } = this.config.services;

} catch (ex) {
log.error(`Error removing queue item from storage: ${ex instanceof Error ? ex.message : ex + ''}`)
log.error(`Error removing queue item from storage: ${ex instanceof Error ? ex.message : ex + ""}`);
}

@@ -335,4 +332,4 @@ }

this._queue = this._queue.filter(i => !files.includes(i.file));
this._queue = this._queue.filter((i) => !files.includes(i.file));
}
}

@@ -21,9 +21,7 @@ import { IStorage } from "./IStorage.js";

public async key(index: number): Promise<string | null> {
if (index < 0)
return Promise.resolve(null);
if (index < 0) return Promise.resolve(null);
const keys = await this.keys();
if (index > keys.length)
return Promise.resolve(null);
if (index > keys.length) return Promise.resolve(null);

@@ -30,0 +28,0 @@ const key = keys[index];

import { IStorage } from "./IStorage.js";
export class LocalStorage implements IStorage {
constructor(private prefix: string = "exceptionless-", private storage: Storage = globalThis.localStorage) { }
constructor(
private prefix: string = "exceptionless-",
private storage: Storage = globalThis.localStorage
) {}

@@ -43,4 +46,4 @@ public length(): Promise<number> {

return Object.keys(this.storage)
.filter(key => key.startsWith(this.prefix))
.map(key => key?.substr(this.prefix.length));
.filter((key) => key.startsWith(this.prefix))
.map((key) => key?.substr(this.prefix.length));
}

@@ -47,0 +50,0 @@

import { Configuration } from "../configuration/Configuration.js";
import {
ServerSettings,
SettingsManager,
} from "../configuration/SettingsManager.js";
import { ServerSettings, SettingsManager } from "../configuration/SettingsManager.js";
import { Event } from "../models/Event.js";

@@ -13,6 +10,8 @@ import { UserDescription } from "../models/data/UserDescription.js";

protected readonly RateLimitRemainingHeader: string = "x-ratelimit-remaining";
protected readonly ConfigurationVersionHeader: string =
"x-exceptionless-configversion";
protected readonly ConfigurationVersionHeader: string = "x-exceptionless-configversion";
public constructor(protected config: Configuration, private fetch = globalThis.fetch?.bind(globalThis)) { }
public constructor(
protected config: Configuration,
private fetch = globalThis.fetch?.bind(globalThis)
) {}

@@ -22,3 +21,3 @@ public getSettings(version: number): Promise<Response<ServerSettings>> {

return this.apiFetch<ServerSettings>(url, {
method: "GET",
method: "GET"
});

@@ -31,3 +30,3 @@ }

method: "POST",
body: JSON.stringify(events),
body: JSON.stringify(events)
});

@@ -40,8 +39,7 @@

public async submitUserDescription(referenceId: string, description: UserDescription): Promise<Response> {
const url = `${this.config.serverUrl}/api/v2/events/by-ref/${encodeURIComponent(referenceId)
}/user-description`;
const url = `${this.config.serverUrl}/api/v2/events/by-ref/${encodeURIComponent(referenceId)}/user-description`;
const response = await this.apiFetch(url, {
method: "POST",
body: JSON.stringify(description),
body: JSON.stringify(description)
});

@@ -57,3 +55,3 @@

return await this.apiFetch<void>(url, {
method: "GET",
method: "GET"
});

@@ -75,5 +73,5 @@ }

headers: {
"Accept": "application/json",
"Authorization": `Bearer ${this.config.apiKey}`,
"User-Agent": this.config.userAgent,
Accept: "application/json",
Authorization: `Bearer ${this.config.apiKey}`,
"User-Agent": this.config.userAgent
},

@@ -93,11 +91,5 @@ body: options.body ?? null

const responseText = await response.text();
const data = responseText && responseText.length > 0 ? JSON.parse(responseText) as T : null;
const data = responseText && responseText.length > 0 ? (JSON.parse(responseText) as T) : null;
return new Response<T>(
response.status,
response.statusText,
rateLimitRemaining,
settingsVersion,
<T>data,
);
return new Response<T>(response.status, response.statusText, rateLimitRemaining, settingsVersion, <T>data);
}

@@ -104,0 +96,0 @@

@@ -8,3 +8,3 @@ export class Response<T = void> {

public data: T
) { }
) {}

@@ -11,0 +11,0 @@ public get success(): boolean {

@@ -9,3 +9,3 @@ export function getHashCode(source: string): number {

const character = source.charCodeAt(index);
hash = ((hash << 5) - hash) + character;
hash = (hash << 5) - hash + character;
hash |= 0;

@@ -17,6 +17,3 @@ }

export function getCookies(
cookies: string,
exclusions?: string[],
): Record<string, string> | null {
export function getCookies(cookies: string, exclusions?: string[]): Record<string, string> | null {
const result: Record<string, string> = {};

@@ -37,7 +34,8 @@

function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() +
s4() + s4();
return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
}

@@ -50,4 +48,3 @@

const versionRegex =
/(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?)/;
const versionRegex = /(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?)/;
const matches = versionRegex.exec(source);

@@ -61,6 +58,3 @@ if (matches && matches.length > 0) {

export function parseQueryString(
query: string,
exclusions?: string[],
): Record<string, string> {
export function parseQueryString(query: string, exclusions?: string[]): Record<string, string> {
if (!query || query.length === 0) {

@@ -95,7 +89,3 @@ return {};

*/
export function isMatch(
input: string | undefined,
patterns: string[],
ignoreCase = true,
): boolean {
export function isMatch(input: string | undefined, patterns: string[], ignoreCase = true): boolean {
if (typeof input !== "string") {

@@ -114,6 +104,3 @@ return false;

if (pattern) {
pattern = (ignoreCase ? pattern.toLowerCase() : pattern).replace(
trim,
"",
);
pattern = (ignoreCase ? pattern.toLowerCase() : pattern).replace(trim, "");
}

@@ -309,3 +296,9 @@

function pruneImpl(value: unknown, maxDepth: number, currentDepth: number = 10, seen: WeakSet<object> = new WeakSet(), parentIsArray: boolean = false): unknown {
function pruneImpl(
value: unknown,
maxDepth: number,
currentDepth: number = 10,
seen: WeakSet<object> = new WeakSet(),
parentIsArray: boolean = false
): unknown {
if (value === null || value === undefined) {

@@ -332,3 +325,3 @@ return value;

const depth: number = parentIsArray ? currentDepth + 1 : currentDepth;
return normalizedValue.map(e => pruneImpl(e, maxDepth, depth, seen, true));
return normalizedValue.map((e) => pruneImpl(e, maxDepth, depth, seen, true));
}

@@ -402,5 +395,3 @@

if (
input === null || typeof input !== "number" && typeof input !== "string"
) {
if (input === null || (typeof input !== "number" && typeof input !== "string")) {
return defaultValue;

@@ -407,0 +398,0 @@ }

@@ -88,3 +88,3 @@ import { describe, test } from "@jest/globals";

test("should call subscribe handler", done => {
test("should call subscribe handler", (done) => {
const config = new Configuration();

@@ -99,4 +99,4 @@ expect(config.settings.someValue).toBeUndefined();

config.applyServerSettings({ settings: { someValue: "UNIT_TEST_API_KEY" }, version: 2 })
config.applyServerSettings({ settings: { someValue: "UNIT_TEST_API_KEY" }, version: 2 });
});
});

@@ -85,3 +85,3 @@ import { describe, test } from "@jest/globals";

await client.startup(c => {
await client.startup((c) => {
c.apiKey = "UNIT_TEST_API_KEY";

@@ -97,3 +97,2 @@ c.serverUrl = "https://localhost:5100";

function createException(): ReferenceError {

@@ -109,4 +108,4 @@ function throwError() {

return new ReferenceError("No Stack Trace")
return new ReferenceError("No Stack Trace");
}
});
export function delay(ms: number): Promise<unknown> {
return new Promise(r => setTimeout(r, ms));
return new Promise((r) => setTimeout(r, ms));
}

@@ -44,7 +44,7 @@ import { describe, test } from "@jest/globals";

return context.event;
}
};
test("tags", async () => {
const ev = await run();
expect(ev.tags).toStrictEqual(defaultTags)
expect(ev.tags).toStrictEqual(defaultTags);
});

@@ -62,3 +62,3 @@

const expected = { "id": 1, "name": "Blake", "customValue": "Password", "value": {} };
const expected = { id: 1, name: "Blake", customValue: "Password", value: {} };
expect(ev.data && ev.data[userDataKey]).toStrictEqual(expected);

@@ -65,0 +65,0 @@ });

@@ -7,6 +7,3 @@ import { describe, test } from "@jest/globals";

import { EventPluginContext } from "../../../src/plugins/EventPluginContext.js";
import {
InnerErrorInfo,
StackFrameInfo
} from "../../../src/models/data/ErrorInfo.js";
import { InnerErrorInfo, StackFrameInfo } from "../../../src/models/data/ErrorInfo.js";
import { delay } from "../../helpers.js";

@@ -21,3 +18,3 @@ import { EventContext } from "../../../src/models/EventContext.js";

is_signature_target: true,
name: "createException",
name: "createException"
},

@@ -29,3 +26,3 @@ {

is_signature_target: false,
name: "throwError",
name: "throwError"
}

@@ -40,3 +37,3 @@ ];

is_signature_target: true,
name: "createException2",
name: "createException2"
},

@@ -48,3 +45,3 @@ {

is_signature_target: false,
name: "throwError2",
name: "throwError2"
}

@@ -63,18 +60,22 @@ ];

const run = async(stackTrace?: StackFrameInfo[]): Promise<EventPluginContext> => {
const run = async (stackTrace?: StackFrameInfo[]): Promise<EventPluginContext> => {
// TODO: Generate unique stack traces based on test data.
const context = new EventPluginContext(client, {
type: "error",
data: {
"@error": <InnerErrorInfo>{
type: "ReferenceError",
message: "This is a test",
stack_trace: stackTrace
const context = new EventPluginContext(
client,
{
type: "error",
data: {
"@error": <InnerErrorInfo>{
type: "ReferenceError",
message: "This is a test",
stack_trace: stackTrace
}
}
}
}, new EventContext());
},
new EventContext()
);
await plugin.run(context);
return context;
}
};

@@ -81,0 +82,0 @@ test("should ignore duplicate within window", async () => {

@@ -13,3 +13,8 @@ import { describe, test } from "@jest/globals";

describe("should exclude log levels", () => {
const run = async (source: string | undefined, level: LogLevel | null | undefined, settingKey: string | null | undefined, settingValue: string | null | undefined): Promise<boolean> => {
const run = async (
source: string | undefined,
level: LogLevel | null | undefined,
settingKey: string | null | undefined,
settingValue: string | null | undefined
): Promise<boolean> => {
const client = new ExceptionlessClient();

@@ -30,3 +35,3 @@ if (typeof settingKey == "string") {

return context.cancelled;
}
};

@@ -57,3 +62,8 @@ test("<null>", async () => expect(await run(undefined, null, null, null)).toBe(false));

describe("should exclude log levels with info default", () => {
const run = async (source: string | undefined, level: LogLevel | null | undefined, settingKey: string | null | undefined, settingValue: string | null | undefined): Promise<boolean> => {
const run = async (
source: string | undefined,
level: LogLevel | null | undefined,
settingKey: string | null | undefined,
settingValue: string | null | undefined
): Promise<boolean> => {
const client = new ExceptionlessClient();

@@ -75,3 +85,3 @@ client.config.settings["@@log:*"] = "info";

return context.cancelled;
}
};

@@ -106,3 +116,3 @@ test("<null>", async () => expect(await run(undefined, null, null, null)).toBe(false));

const settings = {
"@@log:*": "Fatal",
"@@log:*": "Fatal"
};

@@ -150,3 +160,8 @@

describe("should exclude source type", () => {
const run = async (type: EventType | null | undefined, source: string | undefined, settingKey: string | null | undefined, settingValue: string | null | undefined): Promise<boolean> => {
const run = async (
type: EventType | null | undefined,
source: string | undefined,
settingKey: string | null | undefined,
settingValue: string | null | undefined
): Promise<boolean> => {
const client = new ExceptionlessClient();

@@ -163,3 +178,3 @@

return context.cancelled;
}
};

@@ -190,12 +205,16 @@ test("<null>", async () => expect(await run(null, undefined, null, null)).toBe(false));

const context = new EventPluginContext(client, {
type: "error",
data: {
"@error": <InnerErrorInfo>{
type: "ReferenceError",
message: "This is a test",
stack_trace: []
const context = new EventPluginContext(
client,
{
type: "error",
data: {
"@error": <InnerErrorInfo>{
type: "ReferenceError",
message: "This is a test",
stack_trace: []
}
}
}
}, new EventContext());
},
new EventContext()
);

@@ -205,3 +224,3 @@ const plugin = new EventExclusionPlugin();

return context.cancelled;
}
};

@@ -208,0 +227,0 @@ test("<null>", async () => expect(await run(null)).toBe(false));

export const CapturedExceptions = {
OPERA_854: {
"message": "Statement on line 44: Type mismatch (usually a non-object value used where an object is required)\n" +
message:
"Statement on line 44: Type mismatch (usually a non-object value used where an object is required)\n" +
"Backtrace:\n" +

@@ -23,3 +24,4 @@ " Line 44 of linked script http://path/to/file.js\n" +

OPERA_902: {
"message": "Statement on line 44: Type mismatch (usually a non-object value used where an object is required)\n" +
message:
"Statement on line 44: Type mismatch (usually a non-object value used where an object is required)\n" +
"Backtrace:\n" +

@@ -44,3 +46,4 @@ " Line 44 of linked script http://path/to/file.js\n" +

OPERA_927: {
"message": "Statement on line 43: Type mismatch (usually a non-object value used where an object is required)\n" +
message:
"Statement on line 43: Type mismatch (usually a non-object value used where an object is required)\n" +
"Backtrace:\n" +

@@ -57,3 +60,4 @@ " Line 43 of linked script http://path/to/file.js\n" +

OPERA_964: {
"message": "Statement on line 42: Type mismatch (usually non-object value supplied where object required)\n" +
message:
"Statement on line 42: Type mismatch (usually non-object value supplied where object required)\n" +
"Backtrace:\n" +

@@ -76,3 +80,4 @@ " Line 42 of linked script http://path/to/file.js\n" +

"opera#sourceloc": 42,
"stacktrace": " ... Line 27 of linked script http://path/to/file.js\n" +
stacktrace:
" ... Line 27 of linked script http://path/to/file.js\n" +
" ex = ex || this.createException();\n" +

@@ -92,5 +97,6 @@ " Line 18 of linked script http://path/to/file.js: In function printStackTrace\n" +

OPERA_10: {
"message": "Statement on line 42: Type mismatch (usually non-object value supplied where object required)",
message: "Statement on line 42: Type mismatch (usually non-object value supplied where object required)",
"opera#sourceloc": 42,
"stacktrace": " Line 42 of linked script http://path/to/file.js\n" +
stacktrace:
" Line 42 of linked script http://path/to/file.js\n" +
" this.undef();\n" +

@@ -112,4 +118,5 @@ " Line 27 of linked script http://path/to/file.js\n" +

OPERA_11: {
message: "\"this.undef\" is not a function",
stack: "<anonymous function: run>([arguments not available])@http://path/to/file.js:27\n" +
message: '"this.undef" is not a function',
stack:
"<anonymous function: run>([arguments not available])@http://path/to/file.js:27\n" +
"bar([arguments not available])@http://domain.com:1234/path/to/file.js:18\n" +

@@ -119,3 +126,4 @@ "foo([arguments not available])@http://domain.com:1234/path/to/file.js:11\n" +

"Error created at <anonymous function>@http://path/to/file.js:15",
stacktrace: "Error thrown at line 42, column 12 in <anonymous function: createException>() in http://path/to/file.js:\n" +
stacktrace:
"Error thrown at line 42, column 12 in <anonymous function: createException>() in http://path/to/file.js:\n" +
" this.undef();\n" +

@@ -136,7 +144,9 @@ "called from line 27, column 8 in <anonymous function: run>(ex) in http://path/to/file.js:\n" +

OPERA_12: {
message: "Cannot convert \"x\" to object",
stack: "<anonymous function>([arguments not available])@http://localhost:8000/ExceptionLab.html:48\n" +
message: 'Cannot convert "x" to object',
stack:
"<anonymous function>([arguments not available])@http://localhost:8000/ExceptionLab.html:48\n" +
"dumpException3([arguments not available])@http://localhost:8000/ExceptionLab.html:46\n" +
"<anonymous function>([arguments not available])@http://localhost:8000/ExceptionLab.html:1",
stacktrace: "Error thrown at line 48, column 12 in <anonymous function>(x) in http://localhost:8000/ExceptionLab.html:\n" +
stacktrace:
"Error thrown at line 48, column 12 in <anonymous function>(x) in http://localhost:8000/ExceptionLab.html:\n" +
" x.undef();\n" +

@@ -149,5 +159,6 @@ "called from line 46, column 8 in dumpException3() in http://localhost:8000/ExceptionLab.html:\n" +

OPERA_25: {
message: "Cannot read property \"undef\" of null",
message: 'Cannot read property "undef" of null',
name: "TypeError",
stack: "TypeError: Cannot read property \"undef\" of null\n" +
stack:
'TypeError: Cannot read property "undef" of null\n' +
" at http://path/to/file.js:47:22\n" +

@@ -159,4 +170,5 @@ " at foo (http://path/to/file.js:52:15)\n" +

arguments: ["undef"],
message: "Object #<Object> has no method \"undef\"",
stack: "TypeError: Object #<Object> has no method \"undef\"\n" +
message: 'Object #<Object> has no method "undef"',
stack:
'TypeError: Object #<Object> has no method "undef"\n' +
" at bar (http://path/to/file.js:13:17)\n" +

@@ -170,3 +182,4 @@ " at bar (http://path/to/file.js:16:5)\n" +

name: "Error",
stack: "Error: Default error\n" +
stack:
"Error: Default error\n" +
" at dumpExceptionError (http://localhost:8080/file.js:41:27)\n" +

@@ -180,3 +193,4 @@ " at HTMLButtonElement.onclick (http://localhost:8080/file.js:107:146)"

name: "TypeError",
stack: "()@http://127.0.0.1:8000/js/stacktrace.js:44\n" +
stack:
"()@http://127.0.0.1:8000/js/stacktrace.js:44\n" +
"(null)@http://127.0.0.1:8000/js/stacktrace.js:31\n" +

@@ -193,3 +207,4 @@ "printStackTrace()@http://127.0.0.1:8000/js/stacktrace.js:18\n" +

lineNumber: 44,
stack: "()@file:///G:/js/stacktrace.js:44\n" +
stack:
"()@file:///G:/js/stacktrace.js:44\n" +
"(null)@file:///G:/js/stacktrace.js:31\n" +

@@ -205,6 +220,3 @@ "printStackTrace()@file:///G:/js/stacktrace.js:18\n" +

message: "x is null",
stack: "@http://path/to/file.js:48\n" +
"dumpException3@http://path/to/file.js:52\n" +
"onclick@http://path/to/file.js:1\n" +
"",
stack: "@http://path/to/file.js:48\n" + "dumpException3@http://path/to/file.js:52\n" + "onclick@http://path/to/file.js:1\n" + "",
fileName: "http://path/to/file.js",

@@ -216,5 +228,3 @@ lineNumber: 48

name: "Error",
stack: "foo@http://path/to/file.js:41:13\n" +
"bar@http://path/to/file.js:1:1\n" +
"",
stack: "foo@http://path/to/file.js:41:13\n" + "bar@http://path/to/file.js:1:1\n" + "",
fileName: "http://path/to/file.js",

@@ -225,7 +235,4 @@ lineNumber: 41,

SAFARI_6: {
message: "\"null\" is not an object (evaluating \"x.undef\")",
stack: "@http://path/to/file.js:48\n" +
"dumpException3@http://path/to/file.js:52\n" +
"onclick@http://path/to/file.js:82\n" +
"[native code]",
message: '"null" is not an object (evaluating "x.undef")',
stack: "@http://path/to/file.js:48\n" + "dumpException3@http://path/to/file.js:52\n" + "onclick@http://path/to/file.js:82\n" + "[native code]",
line: 48,

@@ -235,7 +242,5 @@ sourceURL: "http://path/to/file.js"

SAFARI_7: {
message: "\"null\" is not an object (evaluating \"x.undef\")",
message: '"null" is not an object (evaluating "x.undef")',
name: "TypeError",
stack: "http://path/to/file.js:48:22\n" +
"foo@http://path/to/file.js:52:15\n" +
"bar@http://path/to/file.js:108:107",
stack: "http://path/to/file.js:48:22\n" + "foo@http://path/to/file.js:52:15\n" + "bar@http://path/to/file.js:108:107",
line: 47,

@@ -245,7 +250,5 @@ sourceURL: "http://path/to/file.js"

SAFARI_8: {
message: "null is not an object (evaluating \"x.undef\")",
message: 'null is not an object (evaluating "x.undef")',
name: "TypeError",
stack: "http://path/to/file.js:47:22\n" +
"foo@http://path/to/file.js:52:15\n" +
"bar@http://path/to/file.js:108:23",
stack: "http://path/to/file.js:47:22\n" + "foo@http://path/to/file.js:52:15\n" + "bar@http://path/to/file.js:108:23",
line: 47,

@@ -256,8 +259,5 @@ column: 22,

SAFARI_8_EVAL: {
message: "Can\"t find variable: getExceptionProps",
message: 'Can"t find variable: getExceptionProps',
name: "ReferenceError",
stack: "eval code\n" +
"eval@[native code]\n" +
"foo@http://path/to/file.js:58:21\n" +
"bar@http://path/to/file.js:109:91",
stack: "eval code\n" + "eval@[native code]\n" + "foo@http://path/to/file.js:58:21\n" + "bar@http://path/to/file.js:109:91",
line: 1,

@@ -267,34 +267,37 @@ column: 18

IE_9: {
message: "Unable to get property \"undef\" of undefined or null reference",
description: "Unable to get property \"undef\" of undefined or null reference"
message: 'Unable to get property "undef" of undefined or null reference',
description: 'Unable to get property "undef" of undefined or null reference'
},
IE_10: {
message: "Unable to get property \"undef\" of undefined or null reference",
stack: "TypeError: Unable to get property \"undef\" of undefined or null reference\n" +
message: 'Unable to get property "undef" of undefined or null reference',
stack:
'TypeError: Unable to get property "undef" of undefined or null reference\n' +
" at Anonymous function (http://path/to/file.js:48:13)\n" +
" at foo (http://path/to/file.js:46:9)\n" +
" at bar (http://path/to/file.js:82:1)",
description: "Unable to get property \"undef\" of undefined or null reference",
description: 'Unable to get property "undef" of undefined or null reference',
number: -2146823281
},
IE_11: {
message: "Unable to get property \"undef\" of undefined or null reference",
message: 'Unable to get property "undef" of undefined or null reference',
name: "TypeError",
stack: "TypeError: Unable to get property \"undef\" of undefined or null reference\n" +
stack:
'TypeError: Unable to get property "undef" of undefined or null reference\n' +
" at Anonymous function (http://path/to/file.js:47:21)\n" +
" at foo (http://path/to/file.js:45:13)\n" +
" at bar (http://path/to/file.js:108:1)",
description: "Unable to get property \"undef\" of undefined or null reference",
description: 'Unable to get property "undef" of undefined or null reference',
number: -2146823281
},
IE_11_EVAL: {
message: "\"getExceptionProps\" is undefined",
message: '"getExceptionProps" is undefined',
name: "ReferenceError",
stack: "ReferenceError: \"getExceptionProps\" is undefined\n" +
stack:
'ReferenceError: "getExceptionProps" is undefined\n' +
" at eval code (eval code:1:1)\n" +
" at foo (http://path/to/file.js:58:17)\n" +
" at bar (http://path/to/file.js:109:1)",
description: "\"getExceptionProps\" is undefined",
description: '"getExceptionProps" is undefined',
number: -2146823279
}
}
};

@@ -53,3 +53,3 @@ import { describe, test } from "@jest/globals";

test("should suspend processing", async () => {
await config.services.queue.suspendProcessing(.0001);
await config.services.queue.suspendProcessing(0.0001);

@@ -56,0 +56,0 @@ const event: Event = { type: "log", reference_id: "123454321" };

@@ -5,5 +5,2 @@ import { InMemoryStorage } from "../../src/storage/InMemoryStorage.js";

describeStorage(
"InMemoryStorage",
(): IStorage => new InMemoryStorage()
);
describeStorage("InMemoryStorage", (): IStorage => new InMemoryStorage());

@@ -9,7 +9,2 @@ import { IStorage } from "../../src/storage/IStorage.js";

describeStorage(
"LocalStorage",
(): IStorage => new LocalStorage(),
resetLocalStorage,
resetLocalStorage
);
describeStorage("LocalStorage", (): IStorage => new LocalStorage(), resetLocalStorage, resetLocalStorage);

@@ -6,8 +6,3 @@ import { describe, test } from "@jest/globals";

export function describeStorage(
name: string,
storageFactory: () => IStorage,
afterEachCallback?: () => void,
beforeEachCallback?: () => void
): void {
export function describeStorage(name: string, storageFactory: () => IStorage, afterEachCallback?: () => void, beforeEachCallback?: () => void): void {
describe(name, () => {

@@ -14,0 +9,0 @@ if (beforeEachCallback) {

@@ -9,3 +9,3 @@ import { describe, jest, test } from "@jest/globals";

import { Response } from "../../src/submission/Response.js";
import { TestSubmissionClient } from "./TestSubmissionClient.js"
import { TestSubmissionClient } from "./TestSubmissionClient.js";
import { FetchOptions } from "../../src/submission/DefaultSubmissionClient.js";

@@ -21,3 +21,4 @@

test("should submit events", async () => {
const apiFetchMock = jest.fn<(url: string, options: FetchOptions) => Promise<Response<undefined>>>()
const apiFetchMock = jest
.fn<(url: string, options: FetchOptions) => Promise<Response<undefined>>>()
.mockReturnValueOnce(Promise.resolve(new Response(202, "", NaN, NaN, undefined)));

@@ -37,11 +38,19 @@

test("should submit invalid object data", async () => {
const apiFetchMock = jest.fn<(url: string, options: FetchOptions) => Promise<Response<undefined>>>()
const apiFetchMock = jest
.fn<(url: string, options: FetchOptions) => Promise<Response<undefined>>>()
.mockReturnValueOnce(Promise.resolve(new Response(202, "", NaN, NaN, undefined)));
const events: Event[] = [{
type: "log", message: "From js client", reference_id: "123454321", data: {
name: "blake",
age: () => { throw new Error("Test"); }
const events: Event[] = [
{
type: "log",
message: "From js client",
reference_id: "123454321",
data: {
name: "blake",
age: () => {
throw new Error("Test");
}
}
}
}];
];

@@ -59,3 +68,4 @@ const client = new TestSubmissionClient(config, apiFetchMock);

test("should submit user description", async () => {
const apiFetchMock = jest.fn<(url: string, options: FetchOptions) => Promise<Response<unknown>>>()
const apiFetchMock = jest
.fn<(url: string, options: FetchOptions) => Promise<Response<unknown>>>()
.mockReturnValueOnce(Promise.resolve(new Response(202, "", NaN, 1, undefined)))

@@ -69,3 +79,3 @@ .mockReturnValueOnce(Promise.resolve(new Response(202, "", NaN, NaN, JSON.stringify(new ServerSettings({}, 1)))));

const client = config.services.submissionClient = new TestSubmissionClient(config, apiFetchMock);
const client = (config.services.submissionClient = new TestSubmissionClient(config, apiFetchMock));
await client.submitUserDescription("123454321", description);

@@ -83,3 +93,4 @@ expect(apiFetchMock).toHaveBeenCalledTimes(2);

test("should submit heartbeat", async () => {
const apiFetchMock = jest.fn<(url: string, options: FetchOptions) => Promise<Response<undefined>>>()
const apiFetchMock = jest
.fn<(url: string, options: FetchOptions) => Promise<Response<undefined>>>()
.mockReturnValueOnce(Promise.resolve(new Response(200, "", NaN, NaN, undefined)));

@@ -95,3 +106,4 @@

test("should get project settings", async () => {
const apiFetchMock = jest.fn<(url: string, options: FetchOptions) => Promise<Response<unknown>>>()
const apiFetchMock = jest
.fn<(url: string, options: FetchOptions) => Promise<Response<unknown>>>()
.mockReturnValueOnce(Promise.resolve(new Response(200, "", NaN, NaN, JSON.stringify(new ServerSettings({}, 1)))));

@@ -98,0 +110,0 @@

@@ -8,3 +8,6 @@ import { Configuration } from "../../src/configuration/Configuration.js";

export class TestSubmissionClient extends DefaultSubmissionClient {
public constructor(protected config: Configuration, protected apiFetchMock: ApiFetchMock) {
public constructor(
protected config: Configuration,
protected apiFetchMock: ApiFetchMock
) {
super(config);

@@ -11,0 +14,0 @@ }

import { describe, test } from "@jest/globals";
import { expect } from "expect";
import {
endsWith,
isEmpty,
isMatch,
parseVersion,
prune,
startsWith,
stringify,
toBoolean
} from "../src/Utils.js";
import { endsWith, isEmpty, isMatch, parseVersion, prune, startsWith, stringify, toBoolean } from "../src/Utils.js";
describe("Utils", () => {
function getObjectWithInheritedProperties(): unknown {
// @ts-expect-error TS2683
const Foo = function () { this.a = "a"; };
// @ts-expect-error TS2683
const Bar = function () { this.b = "b"; };
const Foo = function () {
// @ts-expect-error TS2683
this.a = "a";
};
const Bar = function () {
// @ts-expect-error TS2683
this.b = "b";
};
// @ts-expect-error TS7009

@@ -29,7 +25,7 @@ Bar.prototype = new Foo();

test("circular reference", () => {
type Circular = { property: string, circularRef?: Circular };
type Circular = { property: string; circularRef?: Circular };
const circular: Circular = { property: "string" };
circular.circularRef = circular;
const expected = { "property": "string", "circularRef": undefined };
const expected = { property: "string", circularRef: undefined };
const actual = prune(circular);

@@ -40,3 +36,3 @@ expect(actual).toStrictEqual(expected);

test("circular array reference", () => {
type Circular = { property: string, circularRef?: Circular, list?: Circular[] };
type Circular = { property: string; circularRef?: Circular; list?: Circular[] };
const circular: Circular = { property: "string" };

@@ -46,3 +42,3 @@ circular.circularRef = circular;

const expected = { "property": "string", "circularRef": undefined, "list": [undefined] };
const expected = { property: "string", circularRef: undefined, list: [undefined] };
const actual = prune(circular);

@@ -56,3 +52,3 @@ expect(actual).toStrictEqual(expected);

const expected = [{ "property": "string" }, undefined];
const expected = [{ property: "string" }, undefined];
const actual = prune([propObject, propObject]);

@@ -63,4 +59,4 @@ expect(actual).toStrictEqual(expected);

test("array cloned no object references", () => {
const expected = [{ "property": "string" }, { "property": "string" }];
const actual = prune([{ "property": "string" }, { "property": "string" }]);
const expected = [{ property: "string" }, { property: "string" }];
const actual = prune([{ property: "string" }, { property: "string" }]);
expect(actual).toStrictEqual(expected);

@@ -73,10 +69,10 @@ });

const primitiveValues = {
"undefined": undefined,
"null": null,
"string": "string",
"number": 1,
"Infinity": Infinity,
undefined: undefined,
null: null,
string: "string",
number: 1,
Infinity: Infinity,
"-Infinity": -Infinity,
"NaN": NaN,
"boolean": true
NaN: NaN,
boolean: true
};

@@ -93,11 +89,11 @@

const typedArrayValues = {
"Int8Array": new Int8Array([1]),
"Uint8Array": new Uint8Array([1]),
"Uint8ClampedArray": new Uint8ClampedArray([1]),
"Int16Array": new Int16Array([1]),
"Uint16Array": new Uint16Array([1]),
"Int32Array": new Int32Array([1]),
"Uint32Array": new Uint32Array([1]),
"Float32Array": new Float32Array([1]),
"Float64Array": new Float64Array([1])
Int8Array: new Int8Array([1]),
Uint8Array: new Uint8Array([1]),
Uint8ClampedArray: new Uint8ClampedArray([1]),
Int16Array: new Int16Array([1]),
Uint16Array: new Uint16Array([1]),
Int32Array: new Int32Array([1]),
Uint32Array: new Uint32Array([1]),
Float32Array: new Float32Array([1]),
Float64Array: new Float64Array([1])
};

@@ -119,4 +115,4 @@

const bigIntTypedArrayValues = {
"BigInt64Array": new BigInt64Array([1n]),
"BigUint64Array": new BigUint64Array([1n])
BigInt64Array: new BigInt64Array([1n]),
BigUint64Array: new BigUint64Array([1n])
};

@@ -139,9 +135,16 @@

const unsupportedValues = {
"Async Generator": (async function* () { await Promise.resolve(1); yield 1; })(),
"ArrayBuffer": new ArrayBuffer(1),
"Buffer": Buffer.from("buffer"),
"DataView": new DataView(new ArrayBuffer(1)),
"function": () => { return undefined; },
"Generator": (function* () { yield 1; })(),
"Promise": Promise.resolve(1)
"Async Generator": (async function* () {
await Promise.resolve(1);
yield 1;
})(),
ArrayBuffer: new ArrayBuffer(1),
Buffer: Buffer.from("buffer"),
DataView: new DataView(new ArrayBuffer(1)),
function: () => {
return undefined;
},
Generator: (function* () {
yield 1;
})(),
Promise: Promise.resolve(1)
};

@@ -179,3 +182,3 @@

if (error instanceof Error) {
const expected = { "message": error.message, "stack": error.stack };
const expected = { message: error.message, stack: error.stack };
const actual = prune(error, 1);

@@ -191,17 +194,20 @@ expect(actual).toStrictEqual(expected);

"[object Object]": {
"a2": undefined,
"b2": 1
a2: undefined,
b2: 1
},
"string key": "string key",
"symbol": ["symbol key"]
symbol: ["symbol key"]
};
const actual = prune(new Map<unknown, unknown>([
// NOTE: this value is lost due to being converted to ["[object Object]", { a: { b: 2 }, b: 1 }]
[{ id: 1 }, { a: { b: 2 }, b: 1 }],
[{ id: 2 }, { a2: { b2: 2 }, b2: 1 }],
["string key", "string key"],
[123, 123],
[Symbol("symbol"), ["symbol key"]]
]), 2);
const actual = prune(
new Map<unknown, unknown>([
// NOTE: this value is lost due to being converted to ["[object Object]", { a: { b: 2 }, b: 1 }]
[{ id: 1 }, { a: { b: 2 }, b: 1 }],
[{ id: 2 }, { a2: { b2: 2 }, b2: 1 }],
["string key", "string key"],
[123, 123],
[Symbol("symbol"), ["symbol key"]]
]),
2
);

@@ -224,3 +230,3 @@ expect(actual).toStrictEqual(expected);

test("for Set", () => {
const expected = [{ "a": undefined, "b": 1 }, 1];
const expected = [{ a: undefined, b: 1 }, 1];
const actual = prune(new Set([{ a: { b: 2 }, b: 1 }, 1]), 1);

@@ -282,7 +288,7 @@ expect(actual).toStrictEqual(expected);

expect(prune(value, 1)).toStrictEqual({ "ao": undefined });
expect(prune(value, 2)).toStrictEqual({ "ao": { "bo": undefined, "ba": undefined, "bn": 1 } });
expect(prune(value, 3)).toStrictEqual({ "ao": { "bo": { "cn": 1, "co": undefined }, "ba": [{ "cn": 1, "co": undefined }], "bn": 1 } });
expect(prune(value, 4)).toStrictEqual({ "ao": { "bo": { "cn": 1, "co": { "do": undefined } }, "ba": [{ "cn": 1, "co": { "do": undefined } }], "bn": 1 } });
expect(prune(value, 5)).toStrictEqual({ "ao": { "bo": { "cn": 1, "co": { "do": {} } }, "ba": [{ "cn": 1, "co": { "do": {} } }], "bn": 1 } });
expect(prune(value, 1)).toStrictEqual({ ao: undefined });
expect(prune(value, 2)).toStrictEqual({ ao: { bo: undefined, ba: undefined, bn: 1 } });
expect(prune(value, 3)).toStrictEqual({ ao: { bo: { cn: 1, co: undefined }, ba: [{ cn: 1, co: undefined }], bn: 1 } });
expect(prune(value, 4)).toStrictEqual({ ao: { bo: { cn: 1, co: { do: undefined } }, ba: [{ cn: 1, co: { do: undefined } }], bn: 1 } });
expect(prune(value, 5)).toStrictEqual({ ao: { bo: { cn: 1, co: { do: {} } }, ba: [{ cn: 1, co: { do: {} } }], bn: 1 } });
});

@@ -323,3 +329,4 @@

column: 10
}, {
},
{
name: "HTMLButtonElement.onclick",

@@ -330,3 +337,4 @@ parameters: [],

column: 10
}]
}
]
},

@@ -342,7 +350,7 @@ "@submission_method": "onerror"

test("circular reference", () => {
type Circular = { property: string, circularRef?: Circular };
type Circular = { property: string; circularRef?: Circular };
const circular: Circular = { property: "string" };
circular.circularRef = circular;
const expected = JSON.stringify({ "property": "string", "circularRef": undefined });
const expected = JSON.stringify({ property: "string", circularRef: undefined });
const actual = stringify(circular);

@@ -353,3 +361,3 @@ expect(actual).toStrictEqual(expected);

test("circular array reference", () => {
type Circular = { property: string, circularRef?: Circular, list?: Circular[] };
type Circular = { property: string; circularRef?: Circular; list?: Circular[] };
const circular: Circular = { property: "string" };

@@ -359,3 +367,3 @@ circular.circularRef = circular;

const expected = JSON.stringify({ "property": "string", "circularRef": undefined, "list": [undefined] });
const expected = JSON.stringify({ property: "string", circularRef: undefined, list: [undefined] });
const actual = stringify(circular);

@@ -367,10 +375,10 @@ expect(actual).toStrictEqual(expected);

const primitiveValues = {
"undefined": undefined,
"null": null,
"string": "string",
"number": 1,
"Infinity": Infinity,
undefined: undefined,
null: null,
string: "string",
number: 1,
Infinity: Infinity,
"-Infinity": -Infinity,
"NaN": NaN,
"boolean": true
NaN: NaN,
boolean: true
};

@@ -387,11 +395,11 @@

const typedArrayValues = {
"Int8Array": new Int8Array([1]),
"Uint8Array": new Uint8Array([1]),
"Uint8ClampedArray": new Uint8ClampedArray([1]),
"Int16Array": new Int16Array([1]),
"Uint16Array": new Uint16Array([1]),
"Int32Array": new Int32Array([1]),
"Uint32Array": new Uint32Array([1]),
"Float32Array": new Float32Array([1]),
"Float64Array": new Float64Array([1])
Int8Array: new Int8Array([1]),
Uint8Array: new Uint8Array([1]),
Uint8ClampedArray: new Uint8ClampedArray([1]),
Int16Array: new Int16Array([1]),
Uint16Array: new Uint16Array([1]),
Int32Array: new Int32Array([1]),
Uint32Array: new Uint32Array([1]),
Float32Array: new Float32Array([1]),
Float64Array: new Float64Array([1])
};

@@ -408,4 +416,4 @@

const bigIntTypedArrayValues = {
"BigInt64Array": new BigInt64Array([1n]),
"BigUint64Array": new BigUint64Array([1n])
BigInt64Array: new BigInt64Array([1n]),
BigUint64Array: new BigUint64Array([1n])
};

@@ -423,9 +431,16 @@

const unsupportedValues = {
"Async Generator": (async function* () { await Promise.resolve(1); yield 1; })(),
"ArrayBuffer": new ArrayBuffer(1),
"Buffer": Buffer.from("buffer"),
"DataView": new DataView(new ArrayBuffer(1)),
"function": () => { return undefined; },
"Generator": (function* () { yield 1; })(),
"Promise": Promise.resolve(1)
"Async Generator": (async function* () {
await Promise.resolve(1);
yield 1;
})(),
ArrayBuffer: new ArrayBuffer(1),
Buffer: Buffer.from("buffer"),
DataView: new DataView(new ArrayBuffer(1)),
function: () => {
return undefined;
},
Generator: (function* () {
yield 1;
})(),
Promise: Promise.resolve(1)
};

@@ -464,3 +479,3 @@

if (error instanceof Error) {
const expected = JSON.stringify({ "stack": error.stack, "message": error.message });
const expected = JSON.stringify({ stack: error.stack, message: error.message });
const actual = stringify(error, [], 1);

@@ -476,17 +491,21 @@ expect(actual).toStrictEqual(expected);

"[object Object]": {
"a2": undefined,
"b2": 1
a2: undefined,
b2: 1
},
"string key": "string key",
"symbol": ["symbol key"]
symbol: ["symbol key"]
});
const actual = stringify(new Map<unknown, unknown>([
// NOTE: this value is lost due to being converted to ["[object Object]", { a: { b: 2 }, b: 1 }]
[{ id: 1 }, { a: { b: 2 }, b: 1 }],
[{ id: 2 }, { a2: { b2: 2 }, b2: 1 }],
["string key", "string key"],
[123, 123],
[Symbol("symbol"), ["symbol key"]]
]), [], 2);
const actual = stringify(
new Map<unknown, unknown>([
// NOTE: this value is lost due to being converted to ["[object Object]", { a: { b: 2 }, b: 1 }]
[{ id: 1 }, { a: { b: 2 }, b: 1 }],
[{ id: 2 }, { a2: { b2: 2 }, b2: 1 }],
["string key", "string key"],
[123, 123],
[Symbol("symbol"), ["symbol key"]]
]),
[],
2
);

@@ -509,3 +528,3 @@ expect(actual).toStrictEqual(expected);

test("for Set", () => {
const expected = JSON.stringify([{ "a": undefined, "b": 1 }, 1]);
const expected = JSON.stringify([{ a: undefined, b: 1 }, 1]);
const actual = stringify(new Set([{ a: { b: 2 }, b: 1 }, 1]), [], 1);

@@ -568,7 +587,9 @@ expect(actual).toStrictEqual(expected);

expect(stringify(value, [], 1)).toStrictEqual(JSON.stringify({ "ao": undefined }));
expect(stringify(value, [], 2)).toStrictEqual(JSON.stringify({ "ao": { "bo": undefined, "ba": undefined, "bn": 1 } }));
expect(stringify(value, [], 3)).toStrictEqual(JSON.stringify({ "ao": { "bo": { "cn": 1, "co": undefined }, "ba": [{ "cn": 1, "co": undefined }], "bn": 1 } }));
expect(stringify(value, [], 4)).toStrictEqual(JSON.stringify({ "ao": { "bo": { "cn": 1, "co": { "do": undefined } }, "ba": [{ "cn": 1, "co": { "do": undefined } }], "bn": 1 } }));
expect(stringify(value, [], 5)).toStrictEqual(JSON.stringify({ "ao": { "bo": { "cn": 1, "co": { "do": {} } }, "ba": [{ "cn": 1, "co": { "do": {} } }], "bn": 1 } }));
expect(stringify(value, [], 1)).toStrictEqual(JSON.stringify({ ao: undefined }));
expect(stringify(value, [], 2)).toStrictEqual(JSON.stringify({ ao: { bo: undefined, ba: undefined, bn: 1 } }));
expect(stringify(value, [], 3)).toStrictEqual(JSON.stringify({ ao: { bo: { cn: 1, co: undefined }, ba: [{ cn: 1, co: undefined }], bn: 1 } }));
expect(stringify(value, [], 4)).toStrictEqual(
JSON.stringify({ ao: { bo: { cn: 1, co: { do: undefined } }, ba: [{ cn: 1, co: { do: undefined } }], bn: 1 } })
);
expect(stringify(value, [], 5)).toStrictEqual(JSON.stringify({ ao: { bo: { cn: 1, co: { do: {} } }, ba: [{ cn: 1, co: { do: {} } }], bn: 1 } }));
});

@@ -602,3 +623,11 @@

expect(stringify(user, ["pAssword"])).toBe(
JSON.stringify({ "id": 1, "name": "Blake", "passwordResetToken": "a reset token", "myPassword": "123456", "myPasswordValue": "123456", "customValue": "Password", "value": {} })
JSON.stringify({
id: 1,
name: "Blake",
passwordResetToken: "a reset token",
myPassword: "123456",
myPasswordValue: "123456",
customValue: "Password",
value: {}
})
);

@@ -609,3 +638,3 @@ });

expect(stringify(user, ["*password"])).toBe(
JSON.stringify({ "id": 1, "name": "Blake", "passwordResetToken": "a reset token", "myPasswordValue": "123456", "customValue": "Password", "value": {} })
JSON.stringify({ id: 1, name: "Blake", passwordResetToken: "a reset token", myPasswordValue: "123456", customValue: "Password", value: {} })
);

@@ -616,3 +645,3 @@ });

expect(stringify(user, ["password*"])).toBe(
JSON.stringify({ "id": 1, "name": "Blake", "myPassword": "123456", "myPasswordValue": "123456", "customValue": "Password", "value": {} })
JSON.stringify({ id: 1, name: "Blake", myPassword: "123456", myPasswordValue: "123456", customValue: "Password", value: {} })
);

@@ -622,7 +651,7 @@ });

test("*password*", () => {
JSON.stringify(expect(stringify(user, ["*password*"])).toBe(JSON.stringify({ "id": 1, "name": "Blake", "customValue": "Password", "value": {} })));
JSON.stringify(expect(stringify(user, ["*password*"])).toBe(JSON.stringify({ id: 1, name: "Blake", customValue: "Password", value: {} })));
});
test("*Password*", () => {
JSON.stringify(expect(stringify(user, ["*Password*"])).toBe(JSON.stringify({ "id": 1, "name": "Blake", "customValue": "Password", "value": {} })));
JSON.stringify(expect(stringify(user, ["*Password*"])).toBe(JSON.stringify({ id: 1, name: "Blake", customValue: "Password", value: {} })));
});

@@ -649,4 +678,4 @@

const emptyValues = {
"undefined": undefined,
"null": null,
undefined: undefined,
null: null,
"empty string": "",

@@ -667,7 +696,7 @@ "whitespace string": " ",

const values = {
"Date": new Date(),
"number": 1,
"string": "string",
"object": { a: 1 },
"array": [1]
Date: new Date(),
number: 1,
string: "string",
object: { a: 1 },
array: [1]
};

@@ -683,63 +712,63 @@

describe("isMatch", () => {
test("input: blake patterns [\"pAssword\"]", () => {
test('input: blake patterns ["pAssword"]', () => {
expect(isMatch("blake", ["pAssword"])).toBe(false);
});
test("input: pAssword patterns [\"pAssword\"]", () => {
test('input: pAssword patterns ["pAssword"]', () => {
expect(isMatch("pAssword", ["pAssword"])).toBe(true);
});
test("input: passwordResetToken patterns [\"pAssword\"]", () => {
test('input: passwordResetToken patterns ["pAssword"]', () => {
expect(isMatch("passwordResetToken", ["pAssword"])).toBe(false);
});
test("input: myPassword patterns [\"pAssword\"]", () => {
test('input: myPassword patterns ["pAssword"]', () => {
expect(isMatch("myPassword", ["pAssword"])).toBe(false);
});
test("input: blake patterns [\" * pAssword\"]", () => {
test('input: blake patterns [" * pAssword"]', () => {
expect(isMatch("blake", ["*pAssword"])).toBe(false);
});
test("input: pAssword patterns [\" * pAssword\"]", () => {
test('input: pAssword patterns [" * pAssword"]', () => {
expect(isMatch("pAssword", ["*pAssword"])).toBe(true);
});
test("input: passwordResetToken patterns [\" * pAssword\"]", () => {
test('input: passwordResetToken patterns [" * pAssword"]', () => {
expect(isMatch("passwordResetToken", ["*pAssword"])).toBe(false);
});
test("input: myPassword patterns [\" * pAssword\"]", () => {
test('input: myPassword patterns [" * pAssword"]', () => {
expect(isMatch("myPassword", ["*pAssword"])).toBe(true);
});
test("input: blake patterns [\"pAssword * \"]", () => {
test('input: blake patterns ["pAssword * "]', () => {
expect(isMatch("blake", ["pAssword*"])).toBe(false);
});
test("input: pAssword patterns [\"pAssword * \"]", () => {
test('input: pAssword patterns ["pAssword * "]', () => {
expect(isMatch("pAssword", ["pAssword*"])).toBe(true);
});
test("input: passwordResetToken patterns [\"pAssword * \"]", () => {
test('input: passwordResetToken patterns ["pAssword * "]', () => {
expect(isMatch("passwordResetToken", ["pAssword*"])).toBe(true);
});
test("input: myPassword patterns [\"pAssword * \"]", () => {
test('input: myPassword patterns ["pAssword * "]', () => {
expect(isMatch("myPassword", ["pAssword*"])).toBe(false);
});
test("input: blake patterns [\" * pAssword * \"]", () => {
test('input: blake patterns [" * pAssword * "]', () => {
expect(isMatch("blake", ["*pAssword*"])).toBe(false);
});
test("input: pAssword patterns [\" * pAssword * \"]", () => {
test('input: pAssword patterns [" * pAssword * "]', () => {
expect(isMatch("pAssword", ["*pAssword*"])).toBe(true);
});
test("input: passwordResetToken patterns [\" * pAssword * \"]", () => {
test('input: passwordResetToken patterns [" * pAssword * "]', () => {
expect(isMatch("passwordResetToken", ["*pAssword*"])).toBe(true);
});
test("input: myPassword patterns [\" * pAssword * \"]", () => {
test('input: myPassword patterns [" * pAssword * "]', () => {
expect(isMatch("myPassword", ["*pAssword*"])).toBe(true);

@@ -746,0 +775,0 @@ });

@@ -6,9 +6,5 @@ {

"rootDir": "src",
"types": [
"jest"
],
"types": ["jest"]
},
"include": [
"src"
]
"include": ["src"]
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc