{"version":3,"file":"index.cjs","sources":["../src/src/common/ipc/IpcEvents.ts","../src/src/renderer/common.ts","../src/src/renderer/ipc/PreloadIpcRpc.ts","../src/src/renderer/ipc/getIpcRpc.ts","../src/src/renderer/ipc/PreloadIpcTransport.ts","../src/src/renderer/ipc/getIpcTransport.ts","../src/src/renderer/modules/ConstSessionProvider.ts","../../sdk-core/lib/bundle.mjs","../src/src/renderer/modules/IpcAsyncSessionProvider.ts","../src/src/renderer/modules/IpcBreadcrumbsStorage.ts","../src/src/common/ipc/ipcHandshake.ts","../src/src/renderer/ipc/WritableIpcStream.ts","../src/src/renderer/modules/IpcReportSubmission.ts","../src/src/renderer/modules/IpcRequestHandler.ts","../src/src/renderer/modules/IpcSummedMetricsQueue.ts","../src/src/renderer/modules/StubMetricsQueue.ts","../src/src/renderer/addBacktraceElectron.ts"],"sourcesContent":[null,null,null,null,null,null,null,"class BacktraceReportSubmissionResult {\n    message;\n    get result() {\n        return this._result;\n    }\n    status = 'Ok';\n    _result;\n    constructor(statusOrResponse, message) {\n        this.message = message;\n        if (this.isSubmissionResponse(statusOrResponse)) {\n            this.status = statusOrResponse;\n            return;\n        }\n        this._result = statusOrResponse;\n    }\n    static OnLimitReached(target = 'Server') {\n        return new BacktraceReportSubmissionResult('Limit reached', `${target} report limit reached`);\n    }\n    static SdkDisabled() {\n        return new BacktraceReportSubmissionResult('Disabled SDK');\n    }\n    static Unsupported(message) {\n        return new BacktraceReportSubmissionResult('Unsupported', message);\n    }\n    static ReportSkipped() {\n        return new BacktraceReportSubmissionResult('Report skipped');\n    }\n    static OnInternalServerError(message) {\n        return new BacktraceReportSubmissionResult('Server Error', message);\n    }\n    static OnInvalidToken() {\n        return new BacktraceReportSubmissionResult('Invalid token');\n    }\n    static OnUnknownError(message) {\n        return new BacktraceReportSubmissionResult('Unknown', message);\n    }\n    static OnNetworkingError(message) {\n        return new BacktraceReportSubmissionResult('Network Error', message);\n    }\n    static Ok(response) {\n        return new BacktraceReportSubmissionResult(response);\n    }\n    isSubmissionResponse(statusOrResponse) {\n        return typeof statusOrResponse === 'string';\n    }\n}\n\nfunction jsonEscaper() {\n    const ancestors = [];\n    const keys = [];\n    // in TypeScript add \"this: any\" param to avoid compliation errors - as follows\n    //    return function (this: any, field: any, value: any) {\n    return function (key, value) {\n        if (value === null) {\n            return value;\n        }\n        const valueType = typeof value;\n        if (valueType === 'bigint') {\n            return value.toString();\n        }\n        if (valueType !== 'object') {\n            return value;\n        }\n        // `this` is the object that value is contained in,\n        // i.e., its direct parent.\n        while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) {\n            ancestors.pop();\n            keys.pop();\n        }\n        if (ancestors.includes(value)) {\n            return `[Circular].${keys.filter((k) => !!k).join('.')}.${key}`;\n        }\n        keys.push(key);\n        ancestors.push(value);\n        return value;\n    };\n}\n\nclass SubmissionUrlInformation {\n    static SUBMIT_PREFIX = 'submit.backtrace.io/';\n    /**\n     * Convert url/token from credentials to JSON submission URL\n     * @param url credentials URL\n     * @param token credentials token\n     * @returns JSON submissionURL\n     */\n    static toJsonReportSubmissionUrl(url, token) {\n        // if the token doesn't exist - use URL\n        if (!token) {\n            return url;\n        }\n        // if the url points to submit, we should always use it without any modifications\n        if (url.includes(this.SUBMIT_PREFIX)) {\n            return url;\n        }\n        // if the URL has token in the URL, the user probably added a token once again\n        // in this case, don't do anything\n        if (url.indexOf(token) !== -1) {\n            return url;\n        }\n        const result = new URL(`/post`, url);\n        result.searchParams.append('format', 'json');\n        result.searchParams.append('token', token);\n        return result.href;\n    }\n    /**\n     * Converts full submission JSON URL to PlCrashReporter submission URL\n     * @param submissionUrl Backtrace Submission URL\n     */\n    static toPlCrashReporterSubmissionUrl(submissionUrl) {\n        return this.changeSubmissionFormat(submissionUrl, 'plcrash');\n    }\n    /**\n     * Converts full submission JSON URL to minidump submission URL\n     * @param submissionUrl Backtrace Submission URL\n     */\n    static toMinidumpSubmissionUrl(submissionUrl) {\n        return this.changeSubmissionFormat(submissionUrl, 'minidump');\n    }\n    static toAttachmentSubmissionUrl(submissionUrl, rxid, attachmentName) {\n        const query = `object=${rxid}&attachment_name=${attachmentName}`;\n        if (submissionUrl.includes('?')) {\n            return (submissionUrl += `&` + query);\n        }\n        return (submissionUrl += '?' + query);\n    }\n    /**\n     * Find the universe based on the submission URL\n     * @param submissionUrl submission URL - full submission URL to Backtrace.\n     * @returns universe name\n     */\n    static findUniverse(submissionUrl) {\n        const submitIndex = submissionUrl.indexOf(this.SUBMIT_PREFIX);\n        if (submitIndex !== -1) {\n            // submit format URL\n            // submit.backtrace.io/universe/token/format\n            // we can expect the universe name just after the hostname\n            const universeStartIndex = submitIndex + this.SUBMIT_PREFIX.length;\n            const endOfUniverseName = submissionUrl.indexOf('/', universeStartIndex);\n            return submissionUrl.substring(universeStartIndex, endOfUniverseName);\n        }\n        // the universe name should be available in the hostname\n        // for example abc.sp.backtrace.io or zyx.in.backtrace.io or foo.backtrace.io\n        const domainIndex = submissionUrl.indexOf('.backtrace.io');\n        if (domainIndex === -1) {\n            return undefined;\n        }\n        const protocolSeparator = '://';\n        let protocolEndIndex = submissionUrl.indexOf(protocolSeparator);\n        if (protocolEndIndex === -1) {\n            protocolEndIndex = 0;\n        }\n        else {\n            protocolEndIndex += protocolSeparator.length;\n        }\n        const hostname = submissionUrl.substring(protocolEndIndex, domainIndex);\n        const endOfUniverseName = hostname.indexOf('.');\n        return endOfUniverseName === -1 ? hostname : hostname.substring(0, endOfUniverseName);\n    }\n    static findToken(submissionUrl) {\n        const submitIndex = submissionUrl.indexOf(this.SUBMIT_PREFIX);\n        if (submitIndex !== -1) {\n            const submissionUrlParts = submissionUrl.split('/');\n            // submit format URL\n            // submit.backtrace.io/universe/token/format\n            // by spliting the submission URL by `/` and dropping the last\n            // part of the URL, the last element on the list is the token.\n            return submissionUrlParts[submissionUrlParts.length - 2] ?? null;\n        }\n        const url = new URL(submissionUrl);\n        return url.searchParams.get('token');\n    }\n    static changeSubmissionFormat(submissionUrl, desiredFormat) {\n        const submitIndex = submissionUrl.indexOf(this.SUBMIT_PREFIX);\n        if (submitIndex !== -1) {\n            const queryParametersIndex = submissionUrl.indexOf('?');\n            const queryParameters = queryParametersIndex === -1 ? '' : submissionUrl.substring(queryParametersIndex);\n            const pathname = submissionUrl.substring(submitIndex + this.SUBMIT_PREFIX.length, queryParametersIndex === -1 ? undefined : queryParametersIndex);\n            const pathParts = pathname.split('/');\n            // path parts are prefixed with '/' character. Expected and valid submit format is:\n            // /universe/token/format\n            // splitting pathname should generate at least 4 elements ('', universe, token, format)\n            // if pathParts length is not equal to 4 then the invalid were passed.\n            const expectedMinimalPathParts = 3;\n            if (pathParts.length < expectedMinimalPathParts) {\n                return submissionUrl;\n            }\n            pathParts[2] = desiredFormat;\n            return (submissionUrl.substring(0, submitIndex + this.SUBMIT_PREFIX.length) +\n                pathParts.join('/') +\n                queryParameters);\n        }\n        else {\n            const url = new URL(submissionUrl);\n            url.searchParams.set('format', desiredFormat);\n            return url.href;\n        }\n    }\n}\n\nclass RequestBacktraceReportSubmission {\n    _requestHandler;\n    _submissionUrl;\n    constructor(options, _requestHandler) {\n        this._requestHandler = _requestHandler;\n        this._submissionUrl = SubmissionUrlInformation.toJsonReportSubmissionUrl(options.url, options.token);\n    }\n    send(data, attachments, abortSignal) {\n        try {\n            const json = JSON.stringify(data, jsonEscaper());\n            return this._requestHandler.postError(this._submissionUrl, json, attachments, abortSignal);\n        }\n        catch (error) {\n            // catch error generated during toJSON execution or unsupported objects to not cause the app crash.\n            return Promise.resolve(BacktraceReportSubmissionResult.OnUnknownError(error instanceof Error ? error.message : String(error)));\n        }\n    }\n    async sendAttachment(rxid, attachment, abortSignal) {\n        if (!this._requestHandler.postAttachment) {\n            return BacktraceReportSubmissionResult.Unsupported('postAttachment is not implemented');\n        }\n        return await this._requestHandler.postAttachment(SubmissionUrlInformation.toAttachmentSubmissionUrl(this._submissionUrl, rxid, attachment.name), attachment, abortSignal);\n    }\n}\n\nconst DEFAULT_TIMEOUT = 15_000;\n\nclass ConnectionError {\n    /**\n     * Verifies if an Error is a connection error\n     * @param err error\n     * @returns true if the error was caused by ETIMEDOUT or ECONNRESET or ECONNABORTED\n     */\n    static isConnectionError(err) {\n        const error = err;\n        return error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET' || error.code === 'ECONNABORTED';\n    }\n}\n\nclass MetricsUrlInformation {\n    static generateSummedEventsUrl(hostname, submissionUrl, credentialsToken) {\n        const submissionInformation = this.findSubmissionInformation(submissionUrl, credentialsToken);\n        if (!submissionInformation) {\n            return undefined;\n        }\n        return this.generateEventsServiceUrl(hostname, 'summed-events', submissionInformation.universe, submissionInformation.token);\n    }\n    static generateUniqueEventsUrl(hostname, submissionUrl, credentialsToken) {\n        const submissionInformation = this.findSubmissionInformation(submissionUrl, credentialsToken);\n        if (!submissionInformation) {\n            return undefined;\n        }\n        return this.generateEventsServiceUrl(hostname, 'unique-events', submissionInformation.universe, submissionInformation.token);\n    }\n    static generateEventsServiceUrl(hostname, eventServiceName, universe, token) {\n        return new URL(`/api/${eventServiceName}/submit?universe=${universe}&token=${token}`, hostname).toString();\n    }\n    static findSubmissionInformation(submissionUrl, token) {\n        const universe = SubmissionUrlInformation.findUniverse(submissionUrl);\n        if (!universe) {\n            return undefined;\n        }\n        token = token ?? SubmissionUrlInformation.findToken(submissionUrl);\n        if (!token) {\n            return undefined;\n        }\n        return { universe, token };\n    }\n}\n\nclass BacktraceCoreApi {\n    _requestHandler;\n    _summedMetricsSubmissionUrl;\n    _uniqueMetricsSubmissionUrl;\n    _requestBacktraceReportSubmission;\n    constructor(options, _requestHandler) {\n        this._requestHandler = _requestHandler;\n        this._summedMetricsSubmissionUrl = MetricsUrlInformation.generateSummedEventsUrl(options.metrics?.url ?? 'https://events.backtrace.io', options.url, options.token);\n        this._uniqueMetricsSubmissionUrl = MetricsUrlInformation.generateUniqueEventsUrl(options.metrics?.url ?? 'https://events.backtrace.io', options.url, options.token);\n        this._requestBacktraceReportSubmission =\n            options.requestBacktraceReportSubmission ??\n                new RequestBacktraceReportSubmission({\n                    url: options.url,\n                }, this._requestHandler);\n    }\n    sendReport(data, attachments, abortSignal) {\n        return this._requestBacktraceReportSubmission.send(data, attachments, abortSignal);\n    }\n    sendAttachment(rxid, attachment, abortSignal) {\n        return this._requestBacktraceReportSubmission.sendAttachment(rxid, attachment, abortSignal);\n    }\n    sendUniqueMetrics(metrics, abortSignal) {\n        if (!this._uniqueMetricsSubmissionUrl) {\n            throw new Error('Unique metrics URL is not available.');\n        }\n        return this._requestHandler.post(this._uniqueMetricsSubmissionUrl, JSON.stringify(metrics), abortSignal);\n    }\n    sendSummedMetrics(metrics, abortSignal) {\n        if (!this._summedMetricsSubmissionUrl) {\n            throw new Error('Summed metrics URL is not available.');\n        }\n        return this._requestHandler.post(this._summedMetricsSubmissionUrl, JSON.stringify(metrics), abortSignal);\n    }\n}\n\nclass Events {\n    _callbacks = {};\n    on(event, callback) {\n        this.addCallback(event, { callback });\n        return this;\n    }\n    once(event, callback) {\n        this.addCallback(event, { callback, once: true });\n        return this;\n    }\n    off(event, callback) {\n        this.removeCallback(event, callback);\n        return this;\n    }\n    emit(event, ...args) {\n        const callbacks = this._callbacks[event];\n        if (!callbacks || !callbacks.length) {\n            return false;\n        }\n        for (const { callback, once } of [...callbacks]) {\n            try {\n                callback(...args);\n            }\n            catch {\n                // Do nothing\n            }\n            if (once) {\n                this.removeCallback(event, callback);\n            }\n        }\n        return true;\n    }\n    addCallback(event, callback) {\n        const list = this._callbacks[event];\n        if (list) {\n            list.push(callback);\n        }\n        else {\n            this._callbacks[event] = [callback];\n        }\n    }\n    removeCallback(event, callback) {\n        const list = this._callbacks[event];\n        if (!list) {\n            return;\n        }\n        const index = list.findIndex((el) => el.callback === callback);\n        if (index === -1) {\n            return;\n        }\n        list.splice(index, 1);\n        if (!list.length) {\n            delete this._callbacks[event];\n        }\n    }\n}\n\nclass TimeHelper {\n    static now() {\n        return Date.now();\n    }\n    static toTimestampInSec(timestampMs) {\n        return Math.floor(timestampMs / 1000);\n    }\n    static convertSecondsToMilliseconds(timeInSec) {\n        return timeInSec * 1000;\n    }\n}\n\nclass BacktraceReport {\n    data;\n    attributes;\n    attachments;\n    /**\n     * Report classifiers\n     */\n    classifiers = [];\n    /**\n     * Report annotations\n     */\n    annotations = {};\n    /**\n     * Report stack trace\n     */\n    stackTrace = {};\n    /**\n     * Report message\n     */\n    message;\n    /**\n     * Report inner errors\n     */\n    innerReport = [];\n    /**\n     * Report timestamp in ms\n     */\n    timestamp = TimeHelper.now();\n    /**\n     * Sets how many top frames should be skipped.\n     */\n    skipFrames = 0;\n    addStackTrace(name, stack, message = '') {\n        if (typeof stack === 'string') {\n            this.stackTrace[name] = {\n                stack,\n                message,\n            };\n        }\n        else {\n            this.stackTrace[name] = stack;\n        }\n        return this;\n    }\n    constructor(data, attributes = {}, attachments = [], options = {}) {\n        this.data = data;\n        this.attributes = attributes;\n        this.attachments = attachments;\n        this.skipFrames = options?.skipFrames ?? 0;\n        let errorType = 'Exception';\n        if (data instanceof Error) {\n            this.message = this.generateErrorMessage(data.message);\n            this.annotations['error'] = this.unwrapErrorToAnnotation(data);\n            this.classifiers = [data.name];\n            this.stackTrace['main'] = {\n                stack: data.stack ?? '',\n                message: this.message,\n            };\n            // Supported in ES2022\n            if (data.cause) {\n                this.innerReport.push(data.cause);\n            }\n        }\n        else {\n            this.message = this.generateErrorMessage(data);\n            this.stackTrace['main'] = {\n                stack: new Error().stack ?? '',\n                message: this.message,\n            };\n            this.classifiers = ['Message'];\n            errorType = 'Message';\n            this.skipFrames += 1;\n        }\n        if (!this.attributes['error.type']) {\n            this.attributes['error.type'] = errorType;\n        }\n        this.attributes['error.message'] = this.message;\n        if (options?.timestamp) {\n            this.timestamp = options.timestamp;\n        }\n        if (options?.classifiers) {\n            this.classifiers.unshift(...options.classifiers);\n        }\n    }\n    unwrapErrorToAnnotation(error, seen = new WeakSet()) {\n        seen.add(error);\n        return {\n            ...error,\n            message: this.generateErrorMessage(error.message),\n            name: error.name,\n            stack: error.stack,\n            cause: error.cause instanceof Error\n                ? seen.has(error.cause)\n                    ? `[Circular] ${error.cause.message}`\n                    : this.unwrapErrorToAnnotation(error.cause, seen)\n                : error.cause,\n        };\n    }\n    generateErrorMessage(data) {\n        return typeof data === 'object' ? JSON.stringify(data, jsonEscaper()) : (data?.toString() ?? '');\n    }\n}\n\nclass AttachmentManager {\n    attachmentEvents;\n    _attachmentProviders = [];\n    constructor() {\n        this.attachmentEvents = new Events();\n    }\n    /**\n     * Adds attachment to manager cache.\n     * @param attachments attachments or attachment returning functions\n     */\n    add(...attachments) {\n        this.addProviders(...attachments.map((a) => typeof a === 'function'\n            ? {\n                type: 'dynamic',\n                get: a,\n            }\n            : {\n                type: 'scoped',\n                get: () => a,\n            }));\n    }\n    /**\n     * Adds `BacktraceAttachmentProvider` to manager cache.\n     * @param attachmentProviders attachment providers\n     */\n    addProviders(...attachmentProviders) {\n        let anyScoped = false;\n        for (const provider of attachmentProviders) {\n            if (provider.type === 'dynamic') {\n                this._attachmentProviders.push(provider);\n            }\n            else {\n                const attachment = provider.get();\n                this._attachmentProviders.push({\n                    type: 'scoped',\n                    get: () => attachment,\n                });\n                anyScoped = true;\n            }\n        }\n        if (anyScoped) {\n            this.attachmentEvents.emit('scoped-attachments-updated', this.get('scoped'));\n        }\n    }\n    /**\n     * Returns scoped, dynamic, or all attachments.\n     * @param type optional type to filter attachments\n     * @returns array of `BacktraceAttachment`\n     */\n    get(type) {\n        const result = [];\n        for (const provider of this._attachmentProviders) {\n            if (type && provider.type !== type) {\n                continue;\n            }\n            const attachment = provider.get();\n            if (!attachment) {\n                continue;\n            }\n            if (Array.isArray(attachment)) {\n                result.push(...attachment);\n            }\n            else {\n                result.push(attachment);\n            }\n        }\n        return result;\n    }\n}\n\nclass ReportDataBuilder {\n    static build(attributes) {\n        const result = { annotations: {}, attributes: {} };\n        if (!attributes) {\n            return result;\n        }\n        for (const attributeKey in attributes) {\n            const attribute = attributes[attributeKey];\n            if (attribute == null) {\n                result.attributes[attributeKey] = attribute;\n                continue;\n            }\n            switch (typeof attribute) {\n                case 'object': {\n                    try {\n                        // try to convert known objects into attributes\n                        if (attribute instanceof Date) {\n                            result.attributes[attributeKey] = attribute.toISOString();\n                            break;\n                        }\n                        else if (attribute instanceof URL) {\n                            result.attributes[attributeKey] = attribute.toString();\n                            break;\n                        }\n                    }\n                    catch {\n                        // invalid attribute type - not able to serialize, skip it.\n                        break;\n                    }\n                    result.annotations[attributeKey] = attribute;\n                    break;\n                }\n                case 'bigint': {\n                    result.attributes[attributeKey] = attribute.toString();\n                    break;\n                }\n                default: {\n                    result.attributes[attributeKey] = attribute;\n                    break;\n                }\n            }\n        }\n        return result;\n    }\n}\n\nclass AttributeManager {\n    attributeEvents;\n    _attributeProviders = [];\n    constructor(providers) {\n        this.attributeEvents = new Events();\n        for (const provider of providers) {\n            this.addProvider(provider);\n        }\n    }\n    /**\n     * Adds attributes to manager cache\n     * @param attributes attributes object\n     */\n    add(attributes) {\n        if (typeof attributes === 'function') {\n            this.addProvider({ type: 'dynamic', get: attributes });\n        }\n        else {\n            this.addProvider({ type: 'scoped', get: () => attributes });\n        }\n    }\n    /**\n     * Adds attribute provider to the manager\n     * @param attributeProvider\n     * @returns\n     */\n    addProvider(attributeProvider) {\n        if (attributeProvider.type === 'dynamic') {\n            this._attributeProviders.push(attributeProvider);\n            return;\n        }\n        else {\n            const attributes = attributeProvider.get();\n            this._attributeProviders.push({\n                type: 'scoped',\n                get: () => attributes,\n            });\n            this.attributeEvents.emit('scoped-attributes-updated', this.get('scoped'));\n        }\n    }\n    /**\n     * Gets client attributes\n     * @returns Report attribute - client attributes and annotations\n     */\n    get(attributeType) {\n        const result = {\n            annotations: {},\n            attributes: {},\n        };\n        for (const attributeProvider of this._attributeProviders) {\n            if (attributeType && attributeProvider.type != attributeType) {\n                continue;\n            }\n            const providerResult = ReportDataBuilder.build(attributeProvider.get());\n            result.attributes = {\n                ...result.attributes,\n                ...providerResult.attributes,\n            };\n            result.annotations = {\n                ...result.annotations,\n                ...providerResult.annotations,\n            };\n        }\n        return result;\n    }\n}\n\nclass ClientAttributeProvider {\n    _sdkName;\n    _sdkVersion;\n    _sessionId;\n    constructor(_sdkName, _sdkVersion, _sessionId) {\n        this._sdkName = _sdkName;\n        this._sdkVersion = _sdkVersion;\n        this._sessionId = _sessionId;\n    }\n    get type() {\n        return 'scoped';\n    }\n    get() {\n        return {\n            'application.session': this._sessionId,\n            'backtrace.agent': this._sdkName,\n            'backtrace.version': this._sdkVersion,\n        };\n    }\n}\n\nclass UserAttributeProvider {\n    type;\n    _source;\n    constructor(source) {\n        this._source = typeof source === 'function' ? source : () => source;\n        this.type = typeof source === 'function' ? 'dynamic' : 'scoped';\n    }\n    get() {\n        return this._source();\n    }\n}\n\nfunction stringifiedSize(value) {\n    return JSON.stringify(value).length;\n}\nfunction toStringSize(value) {\n    return value.toString().length;\n}\nconst stringSize = (value) => stringifiedSize(value);\nconst numberSize = (toStringSize);\nconst bigintSize = (toStringSize);\nconst symbolSize = 0;\nconst functionSize = 0;\nconst booleanSize = (value) => (value ? 4 : 5);\nconst undefinedSize = 0;\nconst nullSize = 'null'.length;\nfunction arraySize(array, replacer) {\n    const bracketLength = 2;\n    const commaLength = array.length - 1;\n    let elementsLength = 0;\n    for (let i = 0; i < array.length; i++) {\n        const element = array[i];\n        switch (typeof element) {\n            case 'function':\n            case 'symbol':\n            case 'undefined':\n                elementsLength += nullSize;\n                break;\n            default:\n                elementsLength += _safeJsonSize(array, i.toString(), element, replacer);\n        }\n    }\n    return bracketLength + commaLength + elementsLength;\n}\nconst objectSize = (obj, replacer) => {\n    const entries = Object.entries(obj);\n    const bracketLength = 2;\n    let entryCount = 0;\n    let entriesLength = 0;\n    for (const [k, v] of entries) {\n        const valueSize = _safeJsonSize(obj, k, v, replacer);\n        if (valueSize === 0) {\n            continue;\n        }\n        entryCount++;\n        // +1 adds the comma size\n        entriesLength += keySize(k) + valueSize + 1;\n    }\n    // -1 removes previously added last comma size (there is no trailing comma)\n    const commaLength = Math.max(0, entryCount - 1);\n    return bracketLength + commaLength + entriesLength;\n};\nfunction keySize(key) {\n    const QUOTE_SIZE = 2;\n    if (key === null) {\n        return nullSize + QUOTE_SIZE;\n    }\n    else if (key === undefined) {\n        return '\"undefined\"'.length;\n    }\n    switch (typeof key) {\n        case 'string':\n            return stringSize(key);\n        case 'number':\n            return numberSize(key) + QUOTE_SIZE;\n        case 'boolean':\n            return booleanSize(key) + QUOTE_SIZE;\n        case 'symbol':\n            return symbolSize; // key not used in JSON\n        default:\n            return stringSize(key.toString());\n    }\n}\nfunction _safeJsonSize(parent, key, value, replacer) {\n    try {\n        return _jsonSize(parent, key, value, replacer);\n    }\n    catch (err) {\n        return 0;\n    }\n}\nfunction _jsonSize(parent, key, value, replacer) {\n    try {\n        if (value && typeof value === 'object' && 'toJSON' in value && typeof value.toJSON === 'function') {\n            value = value.toJSON();\n        }\n    }\n    catch (err) {\n        // handle proxy errors that will break other parts of the flow\n        if (err instanceof TypeError) {\n            return 0;\n        }\n        // continue in case of the error in the toJSON method or unsupported toJSON method\n    }\n    value = replacer ? replacer.call(parent, key, value) : value;\n    if (value === null) {\n        return nullSize;\n    }\n    else if (value === undefined) {\n        return undefinedSize;\n    }\n    if (Array.isArray(value)) {\n        return arraySize(value, replacer);\n    }\n    switch (typeof value) {\n        case 'bigint':\n            return bigintSize(value);\n        case 'boolean':\n            return booleanSize(value);\n        case 'function':\n            return functionSize;\n        case 'number':\n            return numberSize(value);\n        case 'object':\n            return objectSize(value, replacer);\n        case 'string':\n            return stringSize(value);\n        case 'symbol':\n            return symbolSize;\n        case 'undefined':\n            return undefinedSize;\n    }\n    return 0;\n}\n/**\n * Calculates size of the object as it would be serialized into JSON.\n *\n * _Should_ return the same value as `JSON.stringify(value, replacer).length`.\n * This may not be 100% accurate, but should work for our requirements.\n * @param value Value to compute length for.\n * @param replacer A function that transforms the results as in `JSON.stringify`.\n * @returns Final string length.\n */\nfunction jsonSize(value, replacer) {\n    return _safeJsonSize(undefined, '', value, replacer);\n}\n\nconst REMOVED_PLACEHOLDER = '<removed>';\nfunction limitObjectDepth(val, depth) {\n    if (typeof val !== 'object' || !val) {\n        return val;\n    }\n    if (!(depth < Infinity)) {\n        return val;\n    }\n    if (depth < 0) {\n        return REMOVED_PLACEHOLDER;\n    }\n    try {\n        if ('toJSON' in val && typeof val.toJSON === 'function') {\n            return limitObjectDepth(val.toJSON(), depth - 1);\n        }\n    }\n    catch (err) {\n        if (err instanceof TypeError) {\n            return REMOVED_PLACEHOLDER;\n        }\n        // broken toJSON — fall through to iterate own properties\n    }\n    const limitChild = (value) => limitObjectDepth(value, depth - 1);\n    const result = {};\n    for (const key in val) {\n        try {\n            const value = val[key];\n            if (Array.isArray(value)) {\n                result[key] = value.map(limitChild);\n            }\n            else {\n                result[key] = limitChild(value);\n            }\n        }\n        catch {\n            // catch revoked proxies and other broken objects\n            result[key] = REMOVED_PLACEHOLDER;\n        }\n    }\n    return result;\n}\n\nfunction textFormatter() {\n    const defaultFormatter = fallbackFormatter(jsonEscaper());\n    try {\n        // eslint-disable-next-line @typescript-eslint/no-var-requires\n        const util = require('util');\n        return util.format ?? defaultFormatter;\n    }\n    catch {\n        return defaultFormatter;\n    }\n}\nfunction fallbackFormatter(jsonEscapeFunction) {\n    return function fallbackFormatter(...params) {\n        let result = '';\n        for (const param of params) {\n            result += typeof param === 'object' ? JSON.stringify(param, jsonEscapeFunction) : param?.toString();\n        }\n        return result;\n    };\n}\n\nvar BreadcrumbLogLevel;\n(function (BreadcrumbLogLevel) {\n    BreadcrumbLogLevel[BreadcrumbLogLevel[\"Verbose\"] = 1] = \"Verbose\";\n    BreadcrumbLogLevel[BreadcrumbLogLevel[\"Debug\"] = 2] = \"Debug\";\n    BreadcrumbLogLevel[BreadcrumbLogLevel[\"Info\"] = 4] = \"Info\";\n    BreadcrumbLogLevel[BreadcrumbLogLevel[\"Warning\"] = 8] = \"Warning\";\n    BreadcrumbLogLevel[BreadcrumbLogLevel[\"Error\"] = 16] = \"Error\";\n})(BreadcrumbLogLevel || (BreadcrumbLogLevel = {}));\nconst defaultBreadcrumbsLogLevel = (1 << 5) - 1;\n\nvar BreadcrumbType;\n(function (BreadcrumbType) {\n    BreadcrumbType[BreadcrumbType[\"Manual\"] = 1] = \"Manual\";\n    BreadcrumbType[BreadcrumbType[\"Log\"] = 2] = \"Log\";\n    BreadcrumbType[BreadcrumbType[\"Navigation\"] = 4] = \"Navigation\";\n    BreadcrumbType[BreadcrumbType[\"Http\"] = 8] = \"Http\";\n    BreadcrumbType[BreadcrumbType[\"System\"] = 16] = \"System\";\n    BreadcrumbType[BreadcrumbType[\"User\"] = 32] = \"User\";\n    BreadcrumbType[BreadcrumbType[\"Configuration\"] = 64] = \"Configuration\";\n})(BreadcrumbType || (BreadcrumbType = {}));\nconst defaultBreadcurmbType = (1 << 7) - 1;\n\nclass ConsoleEventSubscriber {\n    /**\n     * All overriden console events\n     */\n    _events = {};\n    _formatter;\n    start(backtraceBreadcrumbs) {\n        if ((backtraceBreadcrumbs.breadcrumbsType & BreadcrumbType.Log) !== BreadcrumbType.Log) {\n            return;\n        }\n        this._formatter = textFormatter();\n        this.bindToConsoleMethod('log', BreadcrumbLogLevel.Info, backtraceBreadcrumbs);\n        this.bindToConsoleMethod('warn', BreadcrumbLogLevel.Warning, backtraceBreadcrumbs);\n        this.bindToConsoleMethod('error', BreadcrumbLogLevel.Error, backtraceBreadcrumbs);\n        this.bindToConsoleMethod('debug', BreadcrumbLogLevel.Debug, backtraceBreadcrumbs);\n        this.bindToConsoleMethod('trace', BreadcrumbLogLevel.Verbose, backtraceBreadcrumbs);\n    }\n    dispose() {\n        for (const key in this._events) {\n            const consoleMethod = this._events[key];\n            console[key] = consoleMethod;\n        }\n    }\n    bindToConsoleMethod(name, level, backtraceBreadcrumbs) {\n        const originalMethod = console[name];\n        console[name] = (...args) => {\n            originalMethod(...args);\n            const message = this._formatter(...args);\n            backtraceBreadcrumbs.addBreadcrumb(message, level, BreadcrumbType.Log);\n        };\n        this._events[name] = originalMethod;\n    }\n}\n\n/**\n * Constrains `value` to `min` and `max` values, wrapping not matching values around.\n * @param min minimum value to allow\n * @param max maximum value to allow\n * @returns function accepting `value`\n *\n * @example\n * const wrap = wrapped(10, 20);\n * console.log(wrap(15)); // 15\n * console.log(wrap(21)); // 10, wrapped around\n * console.log(wrap(8)); // 18, wrapped around\n */\nfunction wrapped(min, max) {\n    function wrapped(value) {\n        const range = max - min;\n        let newValue;\n        if (value < min) {\n            newValue = max - ((min - value) % range);\n            if (newValue === max) {\n                newValue = min;\n            }\n        }\n        else if (value >= max) {\n            newValue = min + ((value - max) % range);\n            if (newValue === max) {\n                newValue = min;\n            }\n        }\n        else {\n            newValue = value;\n        }\n        return newValue;\n    }\n    return wrapped;\n}\n/**\n * Constrains `value` to `min` and `max` values.\n * @param min minimum value to allow\n * @param max maximum value to allow\n * @returns function accepting `value`\n *\n * @example\n * const clamp = clamped(10, 20);\n * console.log(wrap(15)); // 15\n * console.log(wrap(21)); // 20\n * console.log(wrap(8)); // 10\n */\nfunction clamped(min, max) {\n    function clamped(value) {\n        return Math.max(min, Math.min(value, max));\n    }\n    return clamped;\n}\n\nclass OverwritingArray {\n    capacity;\n    _array;\n    _headConstraint;\n    _lengthConstraint;\n    _head = 0;\n    _length = 0;\n    get head() {\n        return this._head;\n    }\n    set head(value) {\n        this._head = this._headConstraint(value);\n    }\n    get length() {\n        return this._length;\n    }\n    set length(value) {\n        this._length = this._lengthConstraint(value);\n    }\n    get start() {\n        return this._headConstraint(this.head - this.length);\n    }\n    constructor(capacity, items) {\n        this.capacity = capacity;\n        this._array = new Array(capacity);\n        // Head must be always between 0 and capacity.\n        // If lower than 0, it needs to go from the end\n        // If larger than capacity, it needs to go from the start\n        // Wrapping solves this\n        this._headConstraint = wrapped(0, capacity);\n        // Length must be always no less than 0 and no larger than capacity\n        this._lengthConstraint = clamped(0, capacity);\n        if (items) {\n            this.push(...items);\n        }\n    }\n    add(item) {\n        return this.pushOne(item);\n    }\n    push(...items) {\n        for (const item of items) {\n            this.pushOne(item);\n        }\n        return this.length;\n    }\n    pop() {\n        this.head--;\n        const element = this._array[this.head];\n        this._array[this.head] = undefined;\n        this.length--;\n        return element;\n    }\n    shift() {\n        const element = this._array[this.start];\n        this._array[this.start] = undefined;\n        this.length--;\n        return element;\n    }\n    at(index) {\n        return this._array[this.index(index)];\n    }\n    *values() {\n        for (let i = 0; i < this.length; i++) {\n            const index = this.index(i);\n            yield this._array[index];\n        }\n    }\n    *keys() {\n        for (let i = 0; i < this.length; i++) {\n            yield i;\n        }\n    }\n    *entries() {\n        for (let i = 0; i < this.length; i++) {\n            const index = this.index(i);\n            yield [i, this._array[index]];\n        }\n    }\n    [Symbol.iterator]() {\n        return this.values();\n    }\n    pushOne(item) {\n        this._array[this.head] = item;\n        this.head++;\n        this.length++;\n    }\n    index(value) {\n        if (!this.length) {\n            return this._headConstraint(value);\n        }\n        const index = (value % this.length) + this.start;\n        return this._headConstraint(index);\n    }\n}\n\nclass InMemoryBreadcrumbsStorage {\n    _limits;\n    get lastBreadcrumbId() {\n        return this._lastBreadcrumbId;\n    }\n    /**\n     * Breadcrumb name\n     */\n    name = 'bt-breadcrumbs-0';\n    _lastBreadcrumbId = TimeHelper.toTimestampInSec(TimeHelper.now());\n    _breadcrumbs;\n    _breadcrumbSizes;\n    constructor(_limits) {\n        this._limits = _limits;\n        this._breadcrumbs = new OverwritingArray(_limits.maximumBreadcrumbs ?? 100);\n        this._breadcrumbSizes = new OverwritingArray(this._breadcrumbs.capacity);\n    }\n    getAttachments() {\n        return [this];\n    }\n    getAttachmentProviders() {\n        return [\n            {\n                get: () => this,\n                type: 'scoped',\n            },\n        ];\n    }\n    static factory({ limits }) {\n        return new InMemoryBreadcrumbsStorage(limits);\n    }\n    /**\n     * Returns breadcrumbs in the JSON format\n     * @returns Breadcrumbs JSON\n     */\n    get() {\n        return JSON.stringify([...this._breadcrumbs], jsonEscaper());\n    }\n    add(rawBreadcrumb) {\n        this._lastBreadcrumbId++;\n        const id = this._lastBreadcrumbId;\n        const breadcrumb = {\n            id,\n            message: rawBreadcrumb.message,\n            timestamp: TimeHelper.now(),\n            type: BreadcrumbType[rawBreadcrumb.type].toLowerCase(),\n            level: BreadcrumbLogLevel[rawBreadcrumb.level].toLowerCase(),\n        };\n        if (rawBreadcrumb.attributes) {\n            breadcrumb.attributes = rawBreadcrumb.attributes;\n        }\n        this._breadcrumbs.add(breadcrumb);\n        if (this._limits.maximumTotalBreadcrumbsSize) {\n            const size = jsonSize(breadcrumb, jsonEscaper());\n            this._breadcrumbSizes.add(size);\n            let totalSize = this.totalSize();\n            while (totalSize > this._limits.maximumTotalBreadcrumbsSize) {\n                this._breadcrumbs.shift();\n                const removedSize = this._breadcrumbSizes.shift() ?? 0;\n                // We subtract removedSize plus comma in JSON\n                totalSize -= removedSize + 1;\n            }\n        }\n        return id;\n    }\n    totalSize() {\n        let sum = 0;\n        for (const size of this._breadcrumbSizes) {\n            sum += size;\n        }\n        // Sum of:\n        // - all breadcrumbs\n        // - comma count\n        // - brackets\n        return sum + Math.max(0, this._breadcrumbSizes.length - 1) + 2;\n    }\n}\n\nconst BREADCRUMB_ATTRIBUTE_NAME = 'breadcrumbs.lastId';\n/**\n * @returns `undefined` if value is `false`, else `value` if defined, else `defaultValue`\n */\nconst defaultIfNotFalse = (value, defaultValue) => {\n    return value === false ? undefined : value !== undefined ? value : defaultValue;\n};\nclass BreadcrumbsManager {\n    /**\n     * Breadcrumbs type\n     */\n    breadcrumbsType;\n    /**\n     * Breadcrumbs Log level\n     */\n    logLevel;\n    /**\n     * Determines if the breadcrumb manager is enabled.\n     */\n    _enabled = false;\n    _limits;\n    _eventSubscribers = [new ConsoleEventSubscriber()];\n    _interceptor;\n    _storage;\n    constructor(configuration, options) {\n        this._limits = {\n            maximumBreadcrumbs: defaultIfNotFalse(configuration?.maximumBreadcrumbs, 100),\n            maximumAttributesDepth: defaultIfNotFalse(configuration?.maximumAttributesDepth, 2),\n            maximumBreadcrumbMessageLength: defaultIfNotFalse(configuration?.maximumBreadcrumbMessageLength, 255),\n            maximumBreadcrumbSize: defaultIfNotFalse(configuration?.maximumBreadcrumbSize, 64 * 1024),\n            maximumTotalBreadcrumbsSize: defaultIfNotFalse(configuration?.maximumTotalBreadcrumbsSize, 1024 * 1024),\n        };\n        this.breadcrumbsType = configuration?.eventType ?? defaultBreadcurmbType;\n        this.logLevel = configuration?.logLevel ?? defaultBreadcrumbsLogLevel;\n        this._storage = (options?.storage ?? InMemoryBreadcrumbsStorage.factory)({ limits: this._limits });\n        this._interceptor = configuration?.intercept;\n        if (options?.subscribers) {\n            this._eventSubscribers.push(...options.subscribers);\n        }\n    }\n    addEventSubscriber(subscriber) {\n        if (this._enabled) {\n            subscriber.start(this);\n        }\n        this._eventSubscribers.push(subscriber);\n    }\n    setStorage(storage) {\n        if (typeof storage === 'function') {\n            this._storage = storage({ limits: this._limits });\n        }\n        else {\n            this._storage = storage;\n        }\n    }\n    dispose() {\n        this._enabled = false;\n        for (const subscriber of this._eventSubscribers) {\n            subscriber.dispose();\n        }\n    }\n    bind({ client, attachmentManager }) {\n        if (this._storage.getAttachmentProviders) {\n            attachmentManager.addProviders(...this._storage.getAttachmentProviders());\n        }\n        else {\n            attachmentManager.add(...this._storage.getAttachments());\n        }\n        client.addAttribute(() => ({\n            [BREADCRUMB_ATTRIBUTE_NAME]: this._storage.lastBreadcrumbId,\n        }));\n        client.on('before-skip', (report) => this.logReport(report));\n    }\n    initialize() {\n        if (this._enabled) {\n            return;\n        }\n        for (const subscriber of this._eventSubscribers) {\n            subscriber.start(this);\n        }\n        this._enabled = true;\n    }\n    verbose(message, attributes) {\n        return this.log(message, BreadcrumbLogLevel.Verbose, attributes);\n    }\n    debug(message, attributes) {\n        return this.log(message, BreadcrumbLogLevel.Debug, attributes);\n    }\n    info(message, attributes) {\n        return this.log(message, BreadcrumbLogLevel.Info, attributes);\n    }\n    warn(message, attributes) {\n        return this.log(message, BreadcrumbLogLevel.Warning, attributes);\n    }\n    error(message, attributes) {\n        return this.log(message, BreadcrumbLogLevel.Error, attributes);\n    }\n    log(message, level, attributes) {\n        return this.addBreadcrumb(message, level, BreadcrumbType.Manual, attributes);\n    }\n    logReport(report) {\n        const level = report.data instanceof Error ? BreadcrumbLogLevel.Error : BreadcrumbLogLevel.Warning;\n        return this.addBreadcrumb(report.message, level, BreadcrumbType.System);\n    }\n    addBreadcrumb(message, level, type, attributes) {\n        if (!this._enabled) {\n            return false;\n        }\n        let rawBreadcrumb = {\n            message: this.prepareBreadcrumbMessage(message),\n            level,\n            type,\n            attributes,\n        };\n        if (this._interceptor) {\n            const interceptorBreadcrumb = this._interceptor(rawBreadcrumb);\n            if (!interceptorBreadcrumb) {\n                return false;\n            }\n            rawBreadcrumb = interceptorBreadcrumb;\n        }\n        if ((this.logLevel & rawBreadcrumb.level) !== level) {\n            return false;\n        }\n        if ((this.breadcrumbsType & rawBreadcrumb.type) !== type) {\n            return false;\n        }\n        if (this._limits.maximumBreadcrumbMessageLength !== undefined) {\n            rawBreadcrumb.message = rawBreadcrumb.message.substring(0, this._limits.maximumBreadcrumbMessageLength);\n        }\n        if (rawBreadcrumb.attributes) {\n            rawBreadcrumb = {\n                ...rawBreadcrumb,\n                attributes: this.prepareAttributes(rawBreadcrumb.attributes),\n            };\n        }\n        let limitedBreadcrumb;\n        if (this._limits.maximumAttributesDepth !== undefined && rawBreadcrumb.attributes) {\n            limitedBreadcrumb = {\n                ...rawBreadcrumb,\n                attributes: limitObjectDepth(rawBreadcrumb.attributes, this._limits.maximumAttributesDepth),\n            };\n        }\n        else {\n            limitedBreadcrumb = rawBreadcrumb;\n        }\n        if (this._limits.maximumBreadcrumbSize !== undefined) {\n            const breadcrumbSize = jsonSize(limitedBreadcrumb, jsonEscaper());\n            if (breadcrumbSize > this._limits.maximumBreadcrumbSize) {\n                // TODO: Trim the breadcrumb\n                return false;\n            }\n        }\n        const id = this._storage.add(limitedBreadcrumb);\n        return id !== undefined;\n    }\n    prepareAttributes(attributes) {\n        const result = {};\n        for (const key in attributes) {\n            const value = attributes[key];\n            switch (typeof value) {\n                case 'number':\n                case 'boolean':\n                case 'string':\n                case 'undefined':\n                    result[key] = value;\n                    break;\n                case 'bigint':\n                    result[key] = value.toString();\n                    break;\n                case 'object': {\n                    if (!value) {\n                        result[key] = value;\n                        break;\n                    }\n                    const unknownValue = value;\n                    try {\n                        if (unknownValue instanceof Date) {\n                            result[key] = unknownValue.toISOString();\n                        }\n                        else if (unknownValue instanceof URL) {\n                            result[key] = unknownValue.toString();\n                        }\n                    }\n                    catch {\n                        // revoked proxy or broken object — drop it\n                    }\n                    // drop all other objects\n                    break;\n                }\n            }\n        }\n        return result;\n    }\n    /**\n     * The expectation is, message should always be defined and passed as string.\n     * However, logger can pass as a message an object or any other unknown type.\n     * To be sure the code won't break, this method ensures the message is always a string\n     * no matter what the logger gives us.\n     * @param message breadcrumb message\n     */\n    prepareBreadcrumbMessage(message) {\n        if (message == null) {\n            return '';\n        }\n        const messageType = typeof message;\n        switch (messageType) {\n            case 'string': {\n                return message;\n            }\n            case 'object': {\n                return JSON.stringify(message, jsonEscaper());\n            }\n            default: {\n                return message.toString();\n            }\n        }\n    }\n}\n\nconst UNKNOWN_FRAME = 'unknown';\nconst ANONYMOUS_FUNCTION = 'anonymous';\n\nclass V8StackTraceConverter {\n    addressSeparator;\n    get engine() {\n        return 'v8';\n    }\n    constructor(addressSeparator = '') {\n        this.addressSeparator = addressSeparator;\n    }\n    convert(stackTrace, message) {\n        const result = [];\n        let stackFrames = stackTrace.split('\\n');\n        const errorHeader = message.split('\\n');\n        // remove error header from stack trace - if the error header exists\n        if (stackFrames[0].indexOf(errorHeader[0]) !== -1) {\n            stackFrames = stackFrames.slice(errorHeader.length);\n        }\n        else {\n            stackFrames = stackFrames.slice(1);\n        }\n        for (const stackFrame of stackFrames) {\n            const normalizedStackFrame = stackFrame.trim();\n            if (!normalizedStackFrame) {\n                continue;\n            }\n            const frame = this.parseFrame(normalizedStackFrame);\n            result.push(frame);\n        }\n        return result;\n    }\n    parseFrame(stackFrame) {\n        const frameSeparator = 'at ';\n        if (!stackFrame.startsWith(frameSeparator)) {\n            return {\n                funcName: stackFrame,\n                library: UNKNOWN_FRAME,\n            };\n        }\n        stackFrame = stackFrame.substring(stackFrame.indexOf(frameSeparator) + frameSeparator.length);\n        const asyncKeyword = 'async ';\n        const sourceCodeSeparator = ' (';\n        let sourceCodeStartIndex = stackFrame.indexOf(sourceCodeSeparator);\n        const anonymousFunction = sourceCodeStartIndex === -1;\n        if (anonymousFunction) {\n            if (stackFrame.startsWith(asyncKeyword)) {\n                stackFrame = stackFrame.substring(asyncKeyword.length);\n            }\n            return {\n                funcName: ANONYMOUS_FUNCTION,\n                ...this.parseSourceCodeInformation(stackFrame),\n            };\n        }\n        let sourceCodeInformation = stackFrame.substring(sourceCodeStartIndex + sourceCodeSeparator.length - 1, stackFrame.length);\n        const anonymousGenericSymbol = '(<anonymous>)';\n        if (sourceCodeInformation.startsWith(anonymousGenericSymbol)) {\n            sourceCodeStartIndex += anonymousGenericSymbol.length + 1;\n            sourceCodeInformation = sourceCodeInformation.substring(anonymousGenericSymbol.length);\n        }\n        if (sourceCodeInformation.startsWith(` ${frameSeparator}`)) {\n            sourceCodeInformation = sourceCodeInformation.substring(frameSeparator.length + 1);\n        }\n        else {\n            sourceCodeInformation = sourceCodeInformation.substring(1, sourceCodeInformation.length - 1);\n        }\n        let functionName = stackFrame.substring(0, sourceCodeStartIndex);\n        if (functionName.startsWith(asyncKeyword)) {\n            functionName = functionName.substring(asyncKeyword.length);\n        }\n        return {\n            funcName: functionName,\n            ...this.parseSourceCodeInformation(sourceCodeInformation),\n        };\n    }\n    parseSourceCodeInformation(sourceCodeInformation) {\n        if (sourceCodeInformation.startsWith('eval')) {\n            return this.extractEvalInformation(sourceCodeInformation);\n        }\n        if (this.addressSeparator && sourceCodeInformation.startsWith(this.addressSeparator)) {\n            sourceCodeInformation = sourceCodeInformation.substring(this.addressSeparator.length).trimStart();\n        }\n        const sourceCodeParts = sourceCodeInformation.split(':');\n        const column = parseInt(sourceCodeParts[sourceCodeParts.length - 1]);\n        const lineNumber = parseInt(sourceCodeParts[sourceCodeParts.length - 2]);\n        const library = sourceCodeParts.slice(0, sourceCodeParts.length - 2).join(':');\n        return {\n            library,\n            column: isNaN(column) ? undefined : column,\n            line: isNaN(lineNumber) ? undefined : lineNumber,\n        };\n    }\n    extractEvalInformation(evalSourceCodeInformation) {\n        const sourceCodeStartSeparatorChar = '(';\n        const sourceCodeEndSeparatorChar = ')';\n        const sourceCodeStart = evalSourceCodeInformation.indexOf(sourceCodeStartSeparatorChar);\n        const sourceCodeEnd = evalSourceCodeInformation.indexOf(sourceCodeEndSeparatorChar);\n        if (sourceCodeStart === -1 || sourceCodeEnd === -1 || sourceCodeStart > sourceCodeEnd) {\n            return {\n                library: UNKNOWN_FRAME,\n            };\n        }\n        const sourceCodeInformation = evalSourceCodeInformation.substring(sourceCodeStart + sourceCodeStartSeparatorChar.length, sourceCodeEnd);\n        return this.parseSourceCodeInformation(sourceCodeInformation);\n    }\n}\n\nclass IdGenerator {\n    static uuid() {\n        const bytes = [...new Array(16)].map(() => Math.floor(Math.random() * 256));\n        bytes[6] = (bytes[6] & 0x0f) | 0x40;\n        bytes[8] = (bytes[8] & 0x3f) | 0x80;\n        return (bytes\n            .slice(0, 4)\n            .map((n) => n.toString(16).padStart(2, '0'))\n            .join('') +\n            '-' +\n            bytes\n                .slice(4, 6)\n                .map((n) => n.toString(16).padStart(2, '0'))\n                .join('') +\n            '-' +\n            bytes\n                .slice(6, 8)\n                .map((n) => n.toString(16).padStart(2, '0'))\n                .join('') +\n            '-' +\n            bytes\n                .slice(8, 10)\n                .map((n) => n.toString(16).padStart(2, '0'))\n                .join('') +\n            '-' +\n            bytes\n                .slice(10, 16)\n                .map((n) => n.toString(16).padStart(2, '0'))\n                .join(''));\n    }\n}\n\nclass BacktraceDataBuilder {\n    _sdkOptions;\n    _stackTraceConverter;\n    _attributeManager;\n    _debugIdProvider;\n    MAIN_THREAD_NAME = 'main';\n    constructor(_sdkOptions, _stackTraceConverter, _attributeManager, _debugIdProvider) {\n        this._sdkOptions = _sdkOptions;\n        this._stackTraceConverter = _stackTraceConverter;\n        this._attributeManager = _attributeManager;\n        this._debugIdProvider = _debugIdProvider;\n    }\n    build(report) {\n        const { annotations, attributes } = this._attributeManager.get();\n        const reportData = ReportDataBuilder.build(report.attributes);\n        const { threads, detectedDebugIdentifier } = this.getThreads(report);\n        const result = {\n            uuid: IdGenerator.uuid(),\n            timestamp: TimeHelper.toTimestampInSec(report.timestamp),\n            agent: this._sdkOptions.agent,\n            agentVersion: this._sdkOptions.agentVersion,\n            lang: this._sdkOptions.langName,\n            langVersion: this._sdkOptions.langVersion,\n            classifiers: report.classifiers,\n            mainThread: this.MAIN_THREAD_NAME,\n            threads,\n            annotations: {\n                ...annotations,\n                ...reportData.annotations,\n                ...report.annotations,\n            },\n            attributes: {\n                ...attributes,\n                ...reportData.attributes,\n            },\n        };\n        if (detectedDebugIdentifier) {\n            result.symbolication = 'sourcemap';\n        }\n        return result;\n    }\n    getThreads(report) {\n        const threads = {};\n        let detectedDebugIdentifier = false;\n        for (const [name, traceInfo] of Object.entries(report.stackTrace)) {\n            let stackFrames;\n            if (Array.isArray(traceInfo)) {\n                stackFrames = traceInfo;\n            }\n            else {\n                const { message, stack } = traceInfo;\n                stackFrames = this._stackTraceConverter.convert(stack, message);\n            }\n            if (name === this.MAIN_THREAD_NAME && report.skipFrames > 0) {\n                stackFrames.splice(0, report.skipFrames);\n            }\n            for (const frame of stackFrames) {\n                const debugIdentifier = this._debugIdProvider.getDebugId(frame.library);\n                if (!debugIdentifier) {\n                    continue;\n                }\n                detectedDebugIdentifier = true;\n                frame.debug_identifier = debugIdentifier;\n            }\n            threads[name] = {\n                fault: name === this.MAIN_THREAD_NAME,\n                name,\n                stack: stackFrames,\n            };\n        }\n        return {\n            threads,\n            detectedDebugIdentifier,\n        };\n    }\n}\n\nclass AbortError extends Error {\n    constructor(message) {\n        super(message ?? 'Operation cancelled.');\n    }\n}\n\n// Required for polyfills to have the same name as the original implementations\nfunction getGlobal(key) {\n    return typeof window !== 'undefined'\n        ? window[key]\n        : typeof global !== 'undefined'\n            ? global[key]\n            : typeof self !== 'undefined'\n                ? self[key]\n                : undefined;\n}\nconst OriginalAbortController = getGlobal('AbortController');\n\n/**\n * Copied and repurposed from https://github.com/mo/abortcontroller-polyfill/blob/master/src/abortcontroller.js\n */\nclass Emitter {\n    _listeners = {};\n    _events = new Events();\n    addEventListener(type, listener, options) {\n        if (!(type in this._listeners)) {\n            this._listeners[type] = [];\n        }\n        const callback = (ev) => {\n            if (typeof listener === 'object') {\n                return listener.handleEvent.call(this, ev);\n            }\n            else {\n                return listener.call(this, ev);\n            }\n        };\n        const { once, signal } = (typeof options === 'object' ? options : {});\n        if (once) {\n            this._events.once(type, callback);\n        }\n        else {\n            this._events.on(type, callback);\n        }\n        if (signal) {\n            const removeFn = () => this.removeEventListener(type, listener);\n            signal.addEventListener(type, removeFn, { once: true });\n        }\n        this._listeners[type].push({ callback, listener, options });\n    }\n    removeEventListener(type, listener) {\n        if (!(type in this._listeners)) {\n            return;\n        }\n        const allListeners = this._listeners[type];\n        const listeners = allListeners.filter((l) => l.listener === listener);\n        for (const elem of listeners) {\n            this._events.off(type, elem.callback);\n            const index = allListeners.indexOf(elem);\n            allListeners.splice(index, 1);\n        }\n    }\n    dispatchEvent(event) {\n        this._events.emit(event.type, event);\n        return !event.defaultPrevented;\n    }\n}\n/**\n * Copied and repurposed from https://github.com/mo/abortcontroller-polyfill/blob/master/src/abortcontroller.js\n */\nclass AbortSignal extends Emitter {\n    aborted = false;\n    onabort = null;\n    reason;\n    constructor() {\n        super();\n        // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and\n        // we want Object.keys(new AbortController().signal) to be [] for compat with the native impl\n        Object.defineProperty(this, 'aborted', { writable: true, configurable: true, enumerable: false });\n        Object.defineProperty(this, 'onabort', { writable: true, configurable: true, enumerable: false });\n        Object.defineProperty(this, 'reason', { writable: true, configurable: true, enumerable: false });\n    }\n    toString() {\n        return '[object AbortSignal]';\n    }\n    throwIfAborted() {\n        if (this.aborted) {\n            throw this.reason;\n        }\n    }\n    dispatchEvent(event) {\n        if (event.type === 'abort') {\n            this.aborted = true;\n            if (typeof this.onabort === 'function') {\n                this.onabort.call(this, event);\n            }\n        }\n        return super.dispatchEvent(event);\n    }\n    any(signals) {\n        return anySignal(...signals);\n    }\n}\n/**\n * Copied and repurposed from https://github.com/mo/abortcontroller-polyfill/blob/master/src/abortcontroller.js\n */\nclass AbortController {\n    signal;\n    constructor() {\n        // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and\n        // we want Object.keys(new AbortController()) to be [] for compat with the native impl\n        this.signal = new AbortSignal();\n        Object.defineProperty(this, 'signal', { configurable: true, enumerable: false });\n    }\n    abort(reason) {\n        let event;\n        try {\n            event = new Event('abort');\n        }\n        catch (e) {\n            if (typeof document !== 'undefined') {\n                const ie8Document = document;\n                if (!ie8Document.createEvent && ie8Document.createEventObject) {\n                    // For Internet Explorer 8:\n                    event = ie8Document.createEventObject();\n                    event.type = 'abort';\n                }\n                else {\n                    // For Internet Explorer 11:\n                    event = document.createEvent('Event');\n                    event.initEvent('abort', false, false);\n                }\n            }\n            else {\n                // Fallback where document isn't available:\n                event = {\n                    type: 'abort',\n                    bubbles: false,\n                    cancelable: false,\n                };\n            }\n        }\n        let signalReason = reason;\n        if (signalReason === undefined) {\n            if (typeof document === 'undefined') {\n                signalReason = new AbortError('This operation was aborted');\n            }\n            else {\n                try {\n                    signalReason = new DOMException('signal is aborted without reason');\n                }\n                catch (err) {\n                    // IE 11 does not support calling the DOMException constructor, use a\n                    // regular error object on it instead.\n                    signalReason = new AbortError('This operation was aborted');\n                }\n            }\n        }\n        this.signal.reason = signalReason;\n        this.signal.dispatchEvent(event);\n    }\n    toString() {\n        return '[object AbortController]';\n    }\n}\n/**\n * Copied and repurposed from https://github.com/mo/abortcontroller-polyfill/blob/master/src/abortcontroller.js\n */\nif (typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n    // These are necessary to make sure that we get correct output for:\n    // Object.prototype.toString.call(new AbortController())\n    AbortController.prototype[Symbol.toStringTag] = 'AbortController';\n    AbortSignal.prototype[Symbol.toStringTag] = 'AbortSignal';\n}\n/**\n * Creates a new abort controller.\n *\n * If the AbortController is not available, a polyfill is used.\n * @returns\n */\nfunction createAbortController() {\n    if (OriginalAbortController) {\n        return new OriginalAbortController();\n    }\n    else {\n        return new AbortController();\n    }\n}\nfunction anySignal(...signals) {\n    const controller = createAbortController();\n    function cleanup() {\n        // Cleanup\n        for (const signal of signals) {\n            if (signal) {\n                signal.removeEventListener('abort', onAbort);\n            }\n        }\n    }\n    function onAbort() {\n        controller.abort();\n        cleanup();\n    }\n    for (const signal of signals) {\n        if (!signal) {\n            continue;\n        }\n        if (signal.aborted) {\n            onAbort();\n            break;\n        }\n        signal.addEventListener('abort', onAbort);\n    }\n    controller.signal.dispose = cleanup;\n    return controller.signal;\n}\n\n/**\n * Due to the event loop, NodeJS application might not exit\n * due to some background work that the SDK delegates to setIntervals.\n * Thanks to this helper we can cancell interval in NodeJS process.\n * @param interval setInterval interval\n */\nfunction unrefInterval(interval) {\n    if (!interval || typeof interval === 'number') {\n        return;\n    }\n    interval.unref();\n}\n\nconst SESSION_MARKER_PREFIX = 'bt-session';\nconst isDefined = (t) => !!t;\nclass SessionFiles {\n    _fileSystem;\n    _directory;\n    sessionId;\n    _maxPreviousLockedSessions;\n    _lockable;\n    marker;\n    _events = new Events();\n    _escapedSessionId;\n    _locks = new Set();\n    _previousSession;\n    _cleared = false;\n    constructor(_fileSystem, _directory, sessionId, _maxPreviousLockedSessions = 1, _lockable = true) {\n        this._fileSystem = _fileSystem;\n        this._directory = _directory;\n        this.sessionId = sessionId;\n        this._maxPreviousLockedSessions = _maxPreviousLockedSessions;\n        this._lockable = _lockable;\n        this._escapedSessionId = this.escapeFileName(sessionId.id);\n        this.marker = this.getFileName(SESSION_MARKER_PREFIX);\n    }\n    initialize() {\n        return this.createSessionMarker();\n    }\n    getPreviousSession() {\n        if (this._previousSession) {\n            return this._previousSession;\n        }\n        const directoryFiles = this.readDirectoryFiles();\n        if (!directoryFiles.length) {\n            return undefined;\n        }\n        const sessionMarkers = directoryFiles\n            .filter((f) => f.startsWith(SESSION_MARKER_PREFIX))\n            .map((f) => this.getFileSession(f))\n            .filter(isDefined)\n            .sort((a, b) => b.sessionId.timestamp - a.sessionId.timestamp);\n        const currentSessionMarker = sessionMarkers.find((s) => this.sessionIdEquals(s.sessionId, this.sessionId));\n        const lastSessionMarker = currentSessionMarker\n            ? sessionMarkers.filter(({ sessionId }) => currentSessionMarker.sessionId.timestamp > sessionId.timestamp)[0]\n            : sessionMarkers[0];\n        if (!lastSessionMarker) {\n            return undefined;\n        }\n        return (this._previousSession = new SessionFiles(this._fileSystem, this._directory, lastSessionMarker.sessionId, this._maxPreviousLockedSessions - 1, this._maxPreviousLockedSessions > 0));\n    }\n    getSessionWithId(sessionId) {\n        // eslint-disable-next-line @typescript-eslint/no-this-alias\n        let session = this;\n        while (session && this.sessionIdEquals(session.sessionId, sessionId)) {\n            session = session.getPreviousSession();\n        }\n        return session;\n    }\n    getPreviousSessions(count = Infinity) {\n        const result = [];\n        let current = this.getPreviousSession();\n        while (current && count > 0) {\n            result.push(current);\n            count--;\n            current = current.getPreviousSession();\n        }\n        return result;\n    }\n    lockPreviousSessions(lockId) {\n        lockId = lockId ?? IdGenerator.uuid();\n        for (const session of this.getPreviousSessions(this._maxPreviousLockedSessions)) {\n            session.lock(lockId);\n        }\n        return lockId;\n    }\n    unlockPreviousSessions(lockId) {\n        for (const session of this.getPreviousSessions(this._maxPreviousLockedSessions)) {\n            session.unlock(lockId);\n        }\n    }\n    clearPreviousSessions() {\n        for (const session of this.getPreviousSessions()) {\n            session.clearSession();\n        }\n    }\n    getFileName(prefix) {\n        this.throwIfCleared();\n        return (this._directory +\n            '/' +\n            `${this.escapeFileName(prefix)}_${this._escapedSessionId}_${this.sessionId.timestamp}`);\n    }\n    getSessionFiles() {\n        this.throwIfCleared();\n        const files = this.readDirectoryFiles();\n        return files\n            .map((file) => this.getFileSession(file))\n            .filter(isDefined)\n            .filter(({ sessionId }) => this.sessionIdEquals(sessionId, this.sessionId))\n            .map(({ file }) => this._directory + '/' + file);\n    }\n    clearSession() {\n        if (this._locks.size > 0) {\n            this._events.once('unlocked', () => this.clearSession());\n            return;\n        }\n        if (this._cleared) {\n            return;\n        }\n        try {\n            const sessionFiles = this.getSessionFiles();\n            for (const file of sessionFiles) {\n                this._fileSystem.unlinkSync(file);\n            }\n        }\n        catch {\n            // Don't propagate errors\n        }\n        finally {\n            this._cleared = true;\n        }\n    }\n    lock(lockId) {\n        if (this._cleared || !this._lockable) {\n            return;\n        }\n        lockId = lockId ?? IdGenerator.uuid();\n        this._locks.add(lockId);\n        return lockId;\n    }\n    unlock(lockId) {\n        this._locks.delete(lockId);\n        if (this._locks.size === 0) {\n            this._events.emit('unlocked');\n        }\n    }\n    getFileSession(file) {\n        const [escapedSessionId, rawTimestamp] = this.splitByOneChar(file, '_').slice(-2);\n        const timestamp = parseInt(rawTimestamp);\n        if (isNaN(timestamp)) {\n            return undefined;\n        }\n        return {\n            file,\n            escapedSessionId,\n            sessionId: {\n                timestamp,\n                id: this.unescapeFileName(escapedSessionId),\n            },\n        };\n    }\n    readDirectoryFiles() {\n        try {\n            return this._fileSystem.readDirSync(this._directory);\n        }\n        catch {\n            return [];\n        }\n    }\n    createSessionMarker() {\n        this._fileSystem.writeFileSync(this.marker, '');\n    }\n    escapeFileName(name) {\n        return name.replace(/_/g, '__');\n    }\n    unescapeFileName(name) {\n        return name.replace(/__/g, '_');\n    }\n    splitByOneChar(str, char) {\n        const result = [];\n        let start = 0;\n        let index = str.indexOf(char);\n        while (index !== -1) {\n            if (str[index + 1] === char) {\n                index = str.indexOf(char, index + 2);\n            }\n            else {\n                result.push(str.substring(start, index));\n                start = index + 1;\n                index = str.indexOf(char, start);\n            }\n        }\n        result.push(str.substring(start));\n        return result;\n    }\n    throwIfCleared() {\n        if (this._cleared) {\n            throw new Error('This session files are cleared.');\n        }\n    }\n    sessionIdEquals(a, b) {\n        return a.id === b.id && a.timestamp === b.timestamp;\n    }\n    static isValidSessionId(value) {\n        return (typeof value === 'object' &&\n            !!value &&\n            'id' in value &&\n            'timestamp' in value &&\n            typeof value.id === 'string' &&\n            typeof value.timestamp === 'number');\n    }\n}\n\nclass BacktraceDatabaseContext {\n    bucketCount;\n    _records;\n    _recordBuckets = {};\n    constructor(bucketCount = 3) {\n        this.bucketCount = bucketCount;\n        this._records = [];\n        this._recordBuckets = {};\n    }\n    find(predicate) {\n        return this._records.find(predicate);\n    }\n    add(record) {\n        if (this._recordBuckets[record.id] !== undefined) {\n            this._recordBuckets[record.id] = 0;\n            return;\n        }\n        this._records.push(record);\n        this._recordBuckets[record.id] = 0;\n    }\n    get() {\n        return this._records.map((r) => ({ ...r }));\n    }\n    getBucket(index) {\n        const bucket = [];\n        for (const record of this._records) {\n            if (this._recordBuckets[record.id] === index) {\n                bucket.push(record);\n            }\n        }\n        return bucket;\n    }\n    count() {\n        return this._records.length;\n    }\n    countByType() {\n        return this._records.reduce((total, current) => {\n            total[current.type]++;\n            return total;\n        }, {});\n    }\n    remove(recordOrId) {\n        const id = typeof recordOrId === 'string' ? recordOrId : recordOrId.id;\n        const index = this._records.findIndex((r) => r.id === id);\n        if (index === -1) {\n            return;\n        }\n        this._records.splice(index, 1);\n        delete this._recordBuckets[id];\n    }\n    increaseBucket(bucketStart) {\n        for (const [id, bucket] of Object.entries(this._recordBuckets)) {\n            if (bucket < bucketStart) {\n                continue;\n            }\n            const newBucket = bucket + 1;\n            if (newBucket >= this.bucketCount) {\n                this.remove(id);\n            }\n            this._recordBuckets[id] = newBucket;\n        }\n    }\n    load(records) {\n        for (const record of records) {\n            this.add(record);\n        }\n    }\n    dropOverLimits(limits) {\n        const remaining = { ...limits };\n        const dropped = [];\n        for (let i = this._records.length - 1; i >= 0; i--) {\n            const record = this._records[i];\n            if (remaining[record.type] === 0) {\n                this.remove(record);\n                dropped.push(record);\n            }\n            else {\n                remaining[record.type]--;\n            }\n        }\n        return dropped;\n    }\n}\n\nclass BacktraceDatabase extends Events {\n    _options;\n    _storageProvider;\n    _requestHandler;\n    _sessionFiles;\n    /**\n     * Determines if the database is enabled.\n     */\n    get enabled() {\n        return this._enabled;\n    }\n    /**\n     * Abort controller to cancel asynchronous database operations when\n     * the database is being disabled by the user.\n     */\n    _abortController = createAbortController();\n    _databaseRecordContext;\n    _storageProviders = [];\n    _recordLimits;\n    _retryInterval;\n    _intervalId;\n    _enabled = false;\n    constructor(_options, _storageProvider, _requestHandler, _sessionFiles) {\n        super();\n        this._options = _options;\n        this._storageProvider = _storageProvider;\n        this._requestHandler = _requestHandler;\n        this._sessionFiles = _sessionFiles;\n        this._databaseRecordContext = new BacktraceDatabaseContext(this._options?.maximumRetries);\n        this._recordLimits = {\n            report: this._options?.maximumNumberOfRecords ?? 8,\n            attachment: this._options?.maximumNumberOfAttachmentRecords ?? 10,\n        };\n        this._retryInterval = this._options?.retryInterval ?? 60_000;\n    }\n    /**\n     * Starts database integration.\n     * @returns true if the database started successfully. Otherwise false.\n     */\n    initialize() {\n        if (this._enabled) {\n            return this._enabled;\n        }\n        if (this._options?.enable === false) {\n            return false;\n        }\n        const startResult = this._storageProvider.start();\n        if (!startResult) {\n            return false;\n        }\n        const lockId = this._sessionFiles?.lockPreviousSessions();\n        this.loadReports()\n            .then(() => {\n            this.setupDatabaseAutoSend();\n        })\n            .finally(() => lockId && this._sessionFiles?.unlockPreviousSessions(lockId));\n        this._enabled = true;\n        return true;\n    }\n    bind({ client }) {\n        if (this._enabled) {\n            return;\n        }\n        if (this._options?.enable === false) {\n            return;\n        }\n        client.on('before-send', (_, data, attachments) => {\n            const record = this.add(data, attachments);\n            if (!record || record.locked) {\n                return undefined;\n            }\n            record.locked = true;\n        });\n        client.on('after-send', (_, data, __, submissionResult) => {\n            const record = this._databaseRecordContext.find((record) => record.type === 'report' && record.data.uuid === data.uuid);\n            if (!record) {\n                return;\n            }\n            record.locked = false;\n            if (submissionResult.status === 'Ok') {\n                this.remove(record);\n                this._sessionFiles?.unlockPreviousSessions(record.id);\n            }\n        });\n    }\n    /**\n     * Adds backtrace data to the database\n     * @param backtraceData diagnostic data object\n     * @param attachments attachments\n     * @returns record if database is enabled. Otherwise undefined.\n     */\n    add(backtraceData, attachments) {\n        if (!this._enabled) {\n            return undefined;\n        }\n        const record = {\n            type: 'report',\n            data: backtraceData,\n            timestamp: TimeHelper.now(),\n            id: IdGenerator.uuid(),\n            locked: false,\n            attachments: attachments,\n            sessionId: this._sessionFiles?.sessionId,\n        };\n        this.prepareDatabase([record]);\n        const saveResult = this._storageProvider.add(record);\n        if (!saveResult) {\n            return undefined;\n        }\n        this._databaseRecordContext.add(record);\n        this.lockSessionWithRecord(record);\n        this.emit('added', record);\n        return record;\n    }\n    /**\n     * Adds Bactrace attachment to the database\n     * @param backtraceData diagnostic data object\n     * @param attachment the attachment to add\n     * @param sessionId session ID to use\n     * @returns record if database is enabled. Otherwise undefined.\n     */\n    addAttachment(rxid, attachment, sessionId) {\n        if (!this._enabled) {\n            return undefined;\n        }\n        const record = {\n            type: 'attachment',\n            timestamp: TimeHelper.now(),\n            id: IdGenerator.uuid(),\n            rxid,\n            locked: false,\n            attachment,\n            sessionId,\n        };\n        this.prepareDatabase([record]);\n        const saveResult = this._storageProvider.add(record);\n        if (!saveResult) {\n            return undefined;\n        }\n        this._databaseRecordContext.add(record);\n        this.lockSessionWithRecord(record);\n        this.emit('added', record);\n        return record;\n    }\n    /**\n     * Returns stored references to Backtrace records\n     * @returns available records in the database\n     */\n    get() {\n        return this._databaseRecordContext.get();\n    }\n    /**\n     * @returns Returns number of records stored in the Database\n     */\n    count() {\n        return this._databaseRecordContext.count();\n    }\n    /**\n     * @returns Returns number of records by type stored in the Database\n     */\n    countByType() {\n        return this._databaseRecordContext.countByType();\n    }\n    /**\n     * Disables database integration. After running the dispose method, you cannot\n     * execute any database operations.\n     */\n    dispose() {\n        this._enabled = false;\n        clearInterval(this._intervalId);\n        this._abortController.abort();\n    }\n    /**\n     * Removes the database record/records\n     * @param recordOrRecords database records\n     */\n    remove(recordOrRecords) {\n        if (!this._enabled) {\n            return;\n        }\n        const records = Array.isArray(recordOrRecords) ? recordOrRecords : [recordOrRecords];\n        for (const record of records) {\n            this._databaseRecordContext.remove(record);\n            this._storageProvider.delete(record);\n            this._sessionFiles?.unlockPreviousSessions(record.id);\n            this.emit('removed', record);\n        }\n    }\n    addStorageProvider(storageProvider) {\n        if (this._enabled) {\n            throw new Error('Cannot add storage provider after the database has been enabled.');\n        }\n        this._storageProviders.push(storageProvider);\n    }\n    /**\n     * Sends all records available in the database to Backtrace and removes them\n     * no matter if the submission process was successful or not.\n     * @param abortSignal optional abort signal to cancel sending requests\n     */\n    async flush(abortSignal) {\n        const start = TimeHelper.now();\n        await this.send(abortSignal);\n        const records = this.get().filter((n) => n.timestamp <= start);\n        for (const record of records) {\n            if (abortSignal?.aborted) {\n                return;\n            }\n            this.remove(record);\n        }\n    }\n    /**\n     * Sends all records available in the database to Backtrace.\n     * @param abortSignal optional abort signal to cancel sending requests\n     */\n    async send(abortSignal) {\n        for (let bucketIndex = 0; bucketIndex < this._databaseRecordContext.bucketCount; bucketIndex++) {\n            // make a copy of records to not update the array after each remove\n            const records = [...this._databaseRecordContext.getBucket(bucketIndex)];\n            const signal = anySignal(abortSignal, this._abortController.signal);\n            try {\n                for (const record of records) {\n                    if (!this.enabled) {\n                        return;\n                    }\n                    if (record.locked) {\n                        continue;\n                    }\n                    try {\n                        record.locked = true;\n                        this.emit('before-send', record);\n                        const result = record.type === 'report'\n                            ? await this._requestHandler.send(record.data, record.attachments, signal)\n                            : await this._requestHandler.sendAttachment(record.rxid, record.attachment, signal);\n                        this.emit('after-send', record, result);\n                        if (result.status === 'Ok' ||\n                            result.status === 'Unsupported' ||\n                            result.status === 'Report skipped') {\n                            this.remove(record);\n                            continue;\n                        }\n                        this._databaseRecordContext.increaseBucket(bucketIndex);\n                        return;\n                    }\n                    finally {\n                        record.locked = false;\n                    }\n                }\n            }\n            finally {\n                signal.dispose();\n            }\n        }\n    }\n    /**\n     * Prepare database to insert records\n     * @param forRecords records for which to update the database\n     */\n    prepareDatabase(forRecords) {\n        const dropLimits = { ...this._recordLimits };\n        for (const record of forRecords) {\n            dropLimits[record.type]--;\n        }\n        const dropped = this._databaseRecordContext.dropOverLimits(dropLimits);\n        this.remove(dropped);\n    }\n    async loadReports() {\n        const records = await this._storageProvider.get();\n        // limit only non-attachment records\n        const countByType = {\n            attachment: 0,\n            report: 0,\n        };\n        const recordsToAdd = [];\n        const recordsToRemove = [];\n        for (const record of records) {\n            if (countByType[record.type] >= this._recordLimits[record.type]) {\n                recordsToRemove.push(record);\n            }\n            else {\n                recordsToAdd.push(record);\n                countByType[record.type]++;\n            }\n        }\n        // delete old records before adding them to the database\n        if (recordsToRemove.length) {\n            this.remove(recordsToRemove);\n        }\n        this.prepareDatabase(recordsToAdd);\n        this._databaseRecordContext.load(recordsToAdd);\n        for (const record of recordsToAdd) {\n            this.lockSessionWithRecord(record);\n            this.emit('added', record);\n        }\n    }\n    async setupDatabaseAutoSend() {\n        if (!this._enabled) {\n            return;\n        }\n        if (this._options?.autoSend === false) {\n            return;\n        }\n        const sendDatabaseReports = async () => {\n            await this.send();\n        };\n        this._intervalId = setInterval(sendDatabaseReports, this._retryInterval);\n        unrefInterval(this._intervalId);\n        await this.send();\n    }\n    lockSessionWithRecord(record) {\n        if (!this._sessionFiles) {\n            return;\n        }\n        const sessionId = record.sessionId;\n        if (!SessionFiles.isValidSessionId(sessionId)) {\n            this._sessionFiles.lockPreviousSessions(record.id);\n            return;\n        }\n        const session = this._sessionFiles.getSessionWithId(sessionId);\n        session?.lock(record.id);\n    }\n}\n\nfunction isFileAttachment(attachment) {\n    return 'filePath' in attachment && typeof attachment.filePath === 'string';\n}\n\nclass AttachmentBacktraceDatabaseFileRecord {\n    type = 'attachment';\n    id;\n    rxid;\n    timestamp;\n    attachment;\n    sessionId;\n    locked;\n    constructor(record) {\n        this.attachment = record.attachment;\n        this.id = record.id;\n        this.timestamp = record.timestamp;\n        this.rxid = record.rxid;\n        this.sessionId = record.sessionId;\n        // make sure the database record stored in the database directory\n        // is never locked. By doing this, we want to be sure once we load\n        // the record once again, the record will be available for future usage\n        this.locked = false;\n    }\n    static fromRecord(record) {\n        return new AttachmentBacktraceDatabaseFileRecord(record);\n    }\n    static fromJson(json, fileSystem) {\n        try {\n            const record = typeof json === 'string' ? JSON.parse(json) : json;\n            if (!isFileAttachment(record.attachment)) {\n                return undefined;\n            }\n            if (!fileSystem.existsSync(record.attachment.filePath)) {\n                return undefined;\n            }\n            const attachment = fileSystem.createAttachment(record.attachment.filePath, record.attachment.name);\n            return new AttachmentBacktraceDatabaseFileRecord({\n                ...record,\n                attachment,\n            });\n        }\n        catch {\n            return undefined;\n        }\n    }\n}\n\nclass ReportBacktraceDatabaseFileRecord {\n    attachments;\n    type = 'report';\n    data;\n    id;\n    timestamp;\n    sessionId;\n    locked;\n    constructor(record, attachments) {\n        this.attachments = attachments;\n        this.data = record.data;\n        this.id = record.id;\n        this.timestamp = record.timestamp;\n        this.sessionId = record.sessionId;\n        // make sure the database record stored in the database directory\n        // is never locked. By doing this, we want to be sure once we load\n        // the record once again, the record will be available for future usage\n        this.locked = false;\n    }\n    static fromRecord(record) {\n        return new ReportBacktraceDatabaseFileRecord(record, record.attachments.filter(isFileAttachment));\n    }\n    static fromJson(json, fileSystem) {\n        try {\n            const record = typeof json === 'string' ? JSON.parse(json) : json;\n            const attachments = record.attachments\n                ? record.attachments\n                    .filter(isFileAttachment)\n                    .map((n) => fileSystem.createAttachment(n.filePath, n.name))\n                : [];\n            return new ReportBacktraceDatabaseFileRecord(record, attachments);\n        }\n        catch {\n            return undefined;\n        }\n    }\n}\n\nconst BacktraceDatabaseFileRecord = {\n    fromRecord(record) {\n        switch (record.type) {\n            case 'attachment':\n                return AttachmentBacktraceDatabaseFileRecord.fromRecord(record);\n            case 'report':\n                return ReportBacktraceDatabaseFileRecord.fromRecord(record);\n            default:\n                throw new Error('unknown record type');\n        }\n    },\n    fromJson(json, fileSystem) {\n        try {\n            const record = JSON.parse(json);\n            switch (record.type) {\n                case 'attachment':\n                    return AttachmentBacktraceDatabaseFileRecord.fromJson(record, fileSystem);\n                case 'report':\n                    return ReportBacktraceDatabaseFileRecord.fromJson(record, fileSystem);\n                default:\n                    return undefined;\n            }\n        }\n        catch {\n            return undefined;\n        }\n    },\n};\n\nclass BacktraceDatabaseFileStorageProvider {\n    _fileSystem;\n    _path;\n    _enabled = true;\n    RECORD_SUFFIX = '-record.json';\n    constructor(_fileSystem, _path) {\n        this._fileSystem = _fileSystem;\n        this._path = _path;\n    }\n    /**\n     * Create a provider if provided options are valid\n     * @param options database configuration\n     * @returns database file storage provider\n     */\n    static createIfValid(fileSystem, options) {\n        if (!options) {\n            return undefined;\n        }\n        if (!options.enable) {\n            return undefined;\n        }\n        if (options.enable && !options.path) {\n            throw new Error('Missing mandatory path to the database. Please define the database.path option in the configuration.');\n        }\n        return new BacktraceDatabaseFileStorageProvider(fileSystem, options.path);\n    }\n    start() {\n        // make sure by mistake we don't create anything or start any operation\n        if (this._enabled === false) {\n            return false;\n        }\n        return true;\n    }\n    delete(record) {\n        const recordPath = this.getRecordPath(record.id);\n        return this.unlinkRecord(recordPath);\n    }\n    add(record) {\n        const recordPath = this.getRecordPath(record.id);\n        try {\n            this._fileSystem.writeFileSync(recordPath, JSON.stringify(BacktraceDatabaseFileRecord.fromRecord(record), jsonEscaper()));\n            return true;\n        }\n        catch {\n            return false;\n        }\n    }\n    async get() {\n        const databaseFiles = await this._fileSystem.readDir(this._path);\n        const recordNames = databaseFiles\n            .filter((file) => file.endsWith(this.RECORD_SUFFIX))\n            .map((f) => this._path + '/' + f);\n        const records = [];\n        for (const recordName of recordNames) {\n            try {\n                const recordJson = await this._fileSystem.readFile(recordName);\n                const record = BacktraceDatabaseFileRecord.fromJson(recordJson, this._fileSystem);\n                if (!record) {\n                    await this._fileSystem.unlink(recordName);\n                    continue;\n                }\n                records.push(record);\n            }\n            catch {\n                await this._fileSystem.unlink(recordName);\n            }\n        }\n        return records;\n    }\n    unlinkRecord(recordPath) {\n        if (!this._fileSystem.existsSync(recordPath)) {\n            return false;\n        }\n        try {\n            this._fileSystem.unlinkSync(recordPath);\n            return true;\n        }\n        catch {\n            return false;\n        }\n    }\n    getRecordPath(id) {\n        return this._path + '/' + `${id}${this.RECORD_SUFFIX}`;\n    }\n}\n\nclass MetricsEvent {\n    metricGroupName;\n    metricGroupValue;\n    attributes;\n    id = IdGenerator.uuid();\n    constructor(metricGroupName, metricGroupValue, attributes = {}) {\n        this.metricGroupName = metricGroupName;\n        this.metricGroupValue = metricGroupValue;\n        this.attributes = attributes;\n    }\n    toJSON() {\n        return {\n            timestamp: TimeHelper.toTimestampInSec(TimeHelper.now()),\n            attributes: this.attributes,\n            [this.metricGroupName]: this.metricGroupValue,\n        };\n    }\n}\n\nclass SummedEvent extends MetricsEvent {\n    constructor(metricGroupName, attributes = {}) {\n        super('metric_group', metricGroupName, attributes);\n    }\n}\n\nclass UniqueEvent extends MetricsEvent {\n    constructor(attributes) {\n        super('unique', ['guid'], attributes);\n    }\n}\n\nclass BacktraceMetrics {\n    _options;\n    _sessionProvider;\n    _attributeManager;\n    _summedEventsSubmissionQueue;\n    _uniqueEventsSubmissionQueue;\n    /**\n     * Returns current session id.\n     */\n    get sessionId() {\n        return this._sessionProvider.sessionId;\n    }\n    /**\n     * Default metrics submission interval. The variable defines how often metrics will be sent to metrics system.\n     */\n    DEFAULT_UPDATE_INTERVAL = TimeHelper.convertSecondsToMilliseconds(30 * 60);\n    DEFAULT_SERVER_URL = 'https://events.backtrace.io';\n    metricsHost;\n    _updateInterval;\n    _updateIntervalId;\n    _abortController;\n    constructor(_options, _sessionProvider, _attributeManager, _summedEventsSubmissionQueue, _uniqueEventsSubmissionQueue) {\n        this._options = _options;\n        this._sessionProvider = _sessionProvider;\n        this._attributeManager = _attributeManager;\n        this._summedEventsSubmissionQueue = _summedEventsSubmissionQueue;\n        this._uniqueEventsSubmissionQueue = _uniqueEventsSubmissionQueue;\n        this.metricsHost = this._options.metricsSubmissionUrl ?? this.DEFAULT_SERVER_URL;\n        this._updateInterval = this._options.autoSendInterval ?? this.DEFAULT_UPDATE_INTERVAL;\n        this._abortController = createAbortController();\n    }\n    /**\n     * Starts metrics submission.\n     */\n    initialize() {\n        if (!this._sessionProvider.newSession) {\n            return;\n        }\n        this.addSummedEvent('Application Launches');\n        this.handleAbort(() => this.send(this._abortController.signal));\n        if (this._updateInterval === 0) {\n            return;\n        }\n        this._updateIntervalId = setInterval(() => {\n            this.handleAbort(() => this.send(this._abortController.signal));\n        }, this._updateInterval);\n        unrefInterval(this._updateIntervalId);\n    }\n    /**\n     * Returns total number of events in the submission queue.\n     */\n    count() {\n        return this._summedEventsSubmissionQueue?.total ?? 0 + this._uniqueEventsSubmissionQueue?.total ?? 0;\n    }\n    /**\n     * Add summed event to next Backtrace Metrics request.\n     * @param metricName Summed event name.\n     * @param eventAttributes event attributes.\n     */\n    addSummedEvent(metricName, eventAttributes = {}) {\n        if (!metricName) {\n            return false;\n        }\n        const attributes = this.convertAttributes({\n            ...this._attributeManager.get().attributes,\n            ...ReportDataBuilder.build(eventAttributes ?? {}).attributes,\n        });\n        this._summedEventsSubmissionQueue.add(new SummedEvent(metricName, attributes));\n        return true;\n    }\n    /**\n     * Sends event to the metrics system.\n     */\n    async send(abortSignal) {\n        if (!this._sessionProvider.shouldSend()) {\n            return false;\n        }\n        await Promise.all([this.sendUniqueEvent(abortSignal), this._summedEventsSubmissionQueue.send(abortSignal)]);\n        this._sessionProvider.afterMetricsSubmission();\n        return true;\n    }\n    /**\n     * Cleans up metrics interface.\n     */\n    dispose() {\n        this._abortController.abort();\n        if (this._updateIntervalId) {\n            clearInterval(this._updateIntervalId);\n        }\n        this._uniqueEventsSubmissionQueue.dispose && this._uniqueEventsSubmissionQueue.dispose();\n        this._summedEventsSubmissionQueue.dispose && this._summedEventsSubmissionQueue.dispose();\n    }\n    async sendUniqueEvent(abortSignal) {\n        // always add the same unique event before send.\n        const { attributes } = this._attributeManager.get();\n        this._uniqueEventsSubmissionQueue.add(new UniqueEvent(this.convertAttributes(attributes)));\n        await this._uniqueEventsSubmissionQueue.send(abortSignal);\n    }\n    /**\n     * Event aggregators expecting to retrieve attributes in a string format. They also\n     * don't expect to retrieve null/undefined as attribute values.\n     */\n    convertAttributes(attributes) {\n        return Object.keys(attributes)\n            .filter((n) => attributes[n] != null)\n            .reduce((acc, n) => {\n            acc[n] = attributes[n]?.toString();\n            return acc;\n        }, {});\n    }\n    async handleAbort(fn) {\n        try {\n            await fn();\n            return true;\n        }\n        catch (err) {\n            if (err instanceof AbortError) {\n                return false;\n            }\n            throw err;\n        }\n    }\n}\n\nclass Delay {\n    /**\n     * Promise set timeout wrapper.\n     * @param timeout timeout in ms\n     * @param signal abort signal\n     */\n    static wait(timeout, signal) {\n        return new Promise((resolve, reject) => {\n            // intervalId has to be defined here,\n            // as abortCallback can execute before setTimeout is executed\n            // eslint-disable-next-line prefer-const\n            let intervalId;\n            function abortCallback() {\n                clearTimeout(intervalId);\n                reject(new AbortError());\n            }\n            if (signal?.aborted) {\n                return abortCallback();\n            }\n            intervalId = setTimeout(() => {\n                signal?.removeEventListener('abort', abortCallback);\n                resolve();\n            }, timeout);\n            signal?.addEventListener('abort', abortCallback);\n        });\n    }\n}\n\nclass MetricsSubmissionQueue {\n    _submissionUrl;\n    _eventName;\n    _requestHandler;\n    _metricMetadata;\n    maximumEvents;\n    get total() {\n        return this._events.length;\n    }\n    get submissionUrl() {\n        return this._submissionUrl;\n    }\n    DELAY_BETWEEN_REQUESTS = TimeHelper.convertSecondsToMilliseconds(10);\n    _events = [];\n    _numberOfDroppedRequests = 0;\n    _abortController;\n    MAXIMUM_NUMBER_OF_ATTEMPTS = 3;\n    constructor(_submissionUrl, _eventName, _requestHandler, _metricMetadata, maximumEvents = 50) {\n        this._submissionUrl = _submissionUrl;\n        this._eventName = _eventName;\n        this._requestHandler = _requestHandler;\n        this._metricMetadata = _metricMetadata;\n        this.maximumEvents = maximumEvents;\n        this._abortController = createAbortController();\n    }\n    add(event) {\n        this._events.push(event);\n        if (this.reachedLimit()) {\n            this.send();\n        }\n    }\n    async send(abortSignal) {\n        const eventsToProcess = this._events.splice(0);\n        const signal = anySignal(abortSignal, this._abortController.signal);\n        try {\n            return await this.submit(eventsToProcess, signal);\n        }\n        finally {\n            signal.dispose();\n        }\n    }\n    dispose() {\n        this._abortController.abort();\n    }\n    async submit(events, abortSignal) {\n        for (let attempts = 0; attempts < this.MAXIMUM_NUMBER_OF_ATTEMPTS; attempts++) {\n            const response = await this._requestHandler.post(this._submissionUrl, JSON.stringify({\n                ...this._metricMetadata,\n                [this._eventName]: events,\n                metadata: {\n                    dropped_events: this._numberOfDroppedRequests,\n                },\n            }, jsonEscaper()), abortSignal);\n            if (response.status === 'Ok') {\n                this._numberOfDroppedRequests = 0;\n                return;\n            }\n            this._numberOfDroppedRequests++;\n            await Delay.wait(2 ** attempts * this.DELAY_BETWEEN_REQUESTS, abortSignal);\n        }\n        // if the code reached this line, it means, we couldn't send data to server\n        // we need to try to return events to the queue and try to send it once again later.\n        this.returnEventsIfPossible(events);\n    }\n    returnEventsIfPossible(events) {\n        if (this.maximumEvents < this._events.length + events.length) {\n            return;\n        }\n        // push events to the beginning of the queue\n        this._events.unshift(...events);\n    }\n    reachedLimit() {\n        return this.maximumEvents === this._events.length && this.maximumEvents !== 0;\n    }\n}\n\nclass MetricsBuilder {\n    _options;\n    _sessionProvider;\n    _attributeManager;\n    _requestHandler;\n    /**\n     * Default metrics submission interval. The variable defines how often metrics will be sent to metrics system\n     * By default 30 mins.\n     */\n    DEFAULT_UPDATE_INTERVAL = TimeHelper.convertSecondsToMilliseconds(30 * 60);\n    APPLICATION_VERSION_ATTRIBUTE = 'application.version';\n    APPLICATION_ATTRIBUTE = 'application';\n    constructor(_options, _sessionProvider, _attributeManager, _requestHandler) {\n        this._options = _options;\n        this._sessionProvider = _sessionProvider;\n        this._attributeManager = _attributeManager;\n        this._requestHandler = _requestHandler;\n    }\n    build(uniqueEventsSubmissionQueue, summedEventsSubmissionQueue) {\n        const metricsOptions = {\n            ...this.optionsWithDefaults(),\n            ...(this._options.metrics ?? {}),\n        };\n        if (!metricsOptions.enable) {\n            return undefined;\n        }\n        const applicationInfo = this.verifyAttributeSetup();\n        if (!applicationInfo) {\n            return undefined;\n        }\n        uniqueEventsSubmissionQueue =\n            uniqueEventsSubmissionQueue ??\n                this.createUniqueEventSubmissionQueue(metricsOptions.metricsSubmissionUrl, applicationInfo);\n        if (!uniqueEventsSubmissionQueue) {\n            return undefined;\n        }\n        summedEventsSubmissionQueue =\n            summedEventsSubmissionQueue ??\n                this.createSummedEventSubmissionQueue(metricsOptions.metricsSubmissionUrl, applicationInfo);\n        if (!summedEventsSubmissionQueue) {\n            return undefined;\n        }\n        return new BacktraceMetrics(metricsOptions, this._sessionProvider, this._attributeManager, summedEventsSubmissionQueue, uniqueEventsSubmissionQueue);\n    }\n    verifyAttributeSetup() {\n        const { attributes } = this._attributeManager.get();\n        const application = attributes[this.APPLICATION_ATTRIBUTE];\n        const applicationVersion = attributes[this.APPLICATION_VERSION_ATTRIBUTE];\n        if (!application || !applicationVersion) {\n            return undefined;\n        }\n        return { application, applicationVersion };\n    }\n    createUniqueEventSubmissionQueue(metricsHost, applicationInfo) {\n        const uniqueEventsSubmissionUrl = MetricsUrlInformation.generateUniqueEventsUrl(metricsHost, this._options.url, this._options.token);\n        if (!uniqueEventsSubmissionUrl) {\n            return undefined;\n        }\n        return new MetricsSubmissionQueue(uniqueEventsSubmissionUrl, 'unique_events', this._requestHandler, {\n            [this.APPLICATION_ATTRIBUTE]: applicationInfo.application,\n            appversion: applicationInfo.applicationVersion,\n        }, this._options?.metrics?.size);\n    }\n    createSummedEventSubmissionQueue(metricsHost, applicationInfo) {\n        const summedEventsSubmissionUrl = MetricsUrlInformation.generateSummedEventsUrl(metricsHost, this._options.url, this._options.token);\n        if (!summedEventsSubmissionUrl) {\n            return undefined;\n        }\n        return new MetricsSubmissionQueue(summedEventsSubmissionUrl, 'summed_events', this._requestHandler, {\n            [this.APPLICATION_ATTRIBUTE]: applicationInfo.application,\n            appversion: applicationInfo.applicationVersion,\n        }, this._options?.metrics?.size);\n    }\n    optionsWithDefaults() {\n        return {\n            enable: true,\n            autoSendInterval: this.DEFAULT_UPDATE_INTERVAL,\n            metricsSubmissionUrl: 'https://events.backtrace.io',\n            size: 50,\n        };\n    }\n}\n\nclass SingleSessionProvider {\n    newSession = true;\n    sessionId = IdGenerator.uuid();\n    _lastActive = 0;\n    get lastActive() {\n        return this._lastActive;\n    }\n    afterMetricsSubmission() {\n        this._lastActive = TimeHelper.now();\n    }\n    /**\n     * Allow to alway send metrics - in the single session there is no reason\n     * to skip sending metrics.\n     */\n    shouldSend() {\n        return true;\n    }\n}\n\nclass RateLimitWatcher {\n    /**\n     * Time the single report can stay in the queue in ms.\n     */\n    MAXIMUM_TIME_IN_QUEUE = 60 * 1000;\n    _reportPerMin;\n    _watcherEnable;\n    _reportQueue = [];\n    get enabled() {\n        return this._watcherEnable;\n    }\n    constructor(reportPerMin) {\n        if (reportPerMin == null) {\n            reportPerMin = 0;\n        }\n        if (reportPerMin < 0) {\n            throw new Error('ReportPerMinute argument must be greater or equal to zero');\n        }\n        this._reportPerMin = reportPerMin;\n        this._watcherEnable = reportPerMin > 0;\n    }\n    skipReport() {\n        const time = TimeHelper.now();\n        if (!this._watcherEnable) {\n            return false;\n        }\n        this.clear(time);\n        if (this._reportQueue.length >= this._reportPerMin) {\n            return true;\n        }\n        this._reportQueue.push(time);\n        return false;\n    }\n    clear(time) {\n        if (this._reportQueue.length === 0) {\n            return;\n        }\n        // we don't have anything to remove\n        if (time - this._reportQueue[0] < this.MAXIMUM_TIME_IN_QUEUE) {\n            return;\n        }\n        for (let queueIndex = this._reportQueue.length; queueIndex != 0; queueIndex--) {\n            if (time - this._reportQueue[queueIndex - 1] > this.MAXIMUM_TIME_IN_QUEUE) {\n                this._reportQueue = this._reportQueue.slice(queueIndex);\n                return;\n            }\n        }\n    }\n}\n\nclass BacktraceCoreClient extends Events {\n    /**\n     * Backtrace client instance\n     */\n    static _instance;\n    /**\n     * Determines if the client is enabled.\n     */\n    get enabled() {\n        return this._enabled;\n    }\n    /**\n     * Current session id\n     */\n    get sessionId() {\n        return this._sessionProvider.sessionId;\n    }\n    /**\n     * Backtrace SDK name\n     */\n    get agent() {\n        return this._sdkOptions.agent;\n    }\n    /**\n     * Backtrace SDK version\n     */\n    get agentVersion() {\n        return this._sdkOptions.agentVersion;\n    }\n    /**\n     * Available cached client attributes\n     */\n    get attributes() {\n        return this.attributeManager.get().attributes;\n    }\n    /**\n     * Available cached client annotatations\n     */\n    get annotations() {\n        return this.attributeManager.get().annotations;\n    }\n    get metrics() {\n        return this._modules.get(BacktraceMetrics);\n    }\n    get breadcrumbs() {\n        return this._modules.get(BreadcrumbsManager);\n    }\n    get database() {\n        return this._modules.get(BacktraceDatabase);\n    }\n    /**\n     * Client cached attachments\n     */\n    get attachments() {\n        return this.attachmentManager.get();\n    }\n    /**\n     * Modules used by the client\n     */\n    get modules() {\n        return this._modules;\n    }\n    get sessionFiles() {\n        return this._modules.get(SessionFiles);\n    }\n    options;\n    attributeManager;\n    attachmentManager;\n    fileSystem;\n    _modules = new Map();\n    _dataBuilder;\n    _reportSubmission;\n    _rateLimitWatcher;\n    _sessionProvider;\n    _sdkOptions;\n    _requestHandler;\n    _enabled = false;\n    constructor(setup) {\n        super();\n        this.options = setup.options;\n        this.fileSystem = setup.fileSystem;\n        this._sdkOptions = setup.sdkOptions;\n        this._sessionProvider = setup.sessionProvider ?? new SingleSessionProvider();\n        this._reportSubmission =\n            setup.reportSubmission ?? new RequestBacktraceReportSubmission(this.options, setup.requestHandler);\n        this._rateLimitWatcher = new RateLimitWatcher(this.options.rateLimit);\n        this._requestHandler = setup.requestHandler;\n        const attributeProviders = [\n            new ClientAttributeProvider(this.agent, this.agentVersion, this._sessionProvider.sessionId),\n        ];\n        if (setup.attributeProviders) {\n            attributeProviders.push(...setup.attributeProviders);\n        }\n        if (this.options.userAttributes) {\n            attributeProviders.push(new UserAttributeProvider(this.options.userAttributes));\n        }\n        this.attributeManager = new AttributeManager(attributeProviders);\n        this.attachmentManager = new AttachmentManager();\n        if (this.options.attachments) {\n            this.attachmentManager.add(...this.options.attachments);\n        }\n        const stackTraceConverter = setup.stackTraceConverter ?? new V8StackTraceConverter();\n        this._dataBuilder = new BacktraceDataBuilder(this._sdkOptions, stackTraceConverter, this.attributeManager, new DebugIdProvider(stackTraceConverter, setup.debugIdMapProvider));\n        if (this.options?.database?.enable === true && setup.fileSystem) {\n            const provider = BacktraceDatabaseFileStorageProvider.createIfValid(setup.fileSystem, this.options.database);\n            if (this.fileSystem) {\n                const sessionFiles = new SessionFiles(this.fileSystem, this.options.database.path, {\n                    id: this.sessionId,\n                    timestamp: Date.now(),\n                }, this.options.database.maximumOldSessions ?? 1);\n                this._modules.set(SessionFiles, sessionFiles);\n            }\n            if (provider) {\n                const database = new BacktraceDatabase(this.options.database, provider, this._reportSubmission, this.sessionFiles);\n                this._modules.set(BacktraceDatabase, database);\n            }\n        }\n        const metrics = new MetricsBuilder(this.options, this._sessionProvider, this.attributeManager, setup.requestHandler).build(setup.uniqueMetricsQueue, setup.summedMetricsQueue);\n        if (metrics) {\n            this._modules.set(BacktraceMetrics, metrics);\n        }\n        if (this.options.breadcrumbs?.enable !== false) {\n            const breadcrumbsManager = new BreadcrumbsManager(this.options?.breadcrumbs, setup.breadcrumbsSetup);\n            this._modules.set(BreadcrumbsManager, breadcrumbsManager);\n        }\n        if (setup.modules) {\n            for (const module of setup.modules) {\n                this.addModule(module);\n            }\n        }\n    }\n    initialize() {\n        this.validateAttributes();\n        if (this.fileSystem && this.options.database?.createDatabaseDirectory) {\n            if (!this.options.database.path) {\n                throw new Error('Missing mandatory path to the database. Please define the database.path option in the configuration.');\n            }\n            this.fileSystem.createDirSync(this.options.database?.path);\n        }\n        for (const module of this._modules.values()) {\n            if (module.bind) {\n                module.bind(this.getModuleBindData());\n            }\n            if (module.initialize) {\n                module.initialize();\n            }\n        }\n        this.sessionFiles?.clearPreviousSessions();\n        this._enabled = true;\n        BacktraceCoreClient._instance = this;\n    }\n    addAttribute(attributes) {\n        this.attributeManager.add(attributes);\n    }\n    addAttachment(...attachments) {\n        this.attachmentManager.add(...attachments);\n    }\n    // This function CANNOT be an async function due to possible async state machine stack frame inclusion, which breaks the skip stacks\n    send(data, reportAttributesOrAbortSignal, reportAttachments = [], abortSignal) {\n        if (!this._enabled) {\n            return Promise.resolve(BacktraceReportSubmissionResult.SdkDisabled());\n        }\n        if (this._rateLimitWatcher.skipReport()) {\n            return Promise.resolve(BacktraceReportSubmissionResult.OnLimitReached('Client'));\n        }\n        // If data is BacktraceReport, we know that the second argument should be only AbortSignal\n        const reportAttributes = !this.isReport(data)\n            ? reportAttributesOrAbortSignal\n            : undefined;\n        // If data is BacktraceReport, we know that the second argument should be only AbortSignal\n        abortSignal = !this.isReport(data) ? abortSignal : reportAttributesOrAbortSignal;\n        const report = this.isReport(data)\n            ? data\n            : new BacktraceReport(data, reportAttributes, [], {\n                skipFrames: this.skipFrameOnMessage(data),\n            });\n        this.emit('before-skip', report);\n        if (this.options.skipReport && this.options.skipReport(report)) {\n            return Promise.resolve(BacktraceReportSubmissionResult.ReportSkipped());\n        }\n        const backtraceData = this.generateSubmissionData(report);\n        if (!backtraceData) {\n            return Promise.resolve(BacktraceReportSubmissionResult.ReportSkipped());\n        }\n        const submissionAttachments = this.generateSubmissionAttachments(report, reportAttachments);\n        this.emit('before-send', report, backtraceData, submissionAttachments);\n        return this._reportSubmission\n            .send(backtraceData, submissionAttachments, abortSignal)\n            .then((submissionResult) => {\n            this.emit('after-send', report, backtraceData, submissionAttachments, submissionResult);\n            return submissionResult;\n        });\n    }\n    /**\n     * Disposes the client and all client callbacks\n     */\n    dispose() {\n        this._enabled = false;\n        for (const module of this._modules.values()) {\n            if (module.dispose) {\n                module.dispose();\n            }\n        }\n        BacktraceCoreClient.destroy();\n    }\n    addModule(typeOrModule, module) {\n        let type;\n        if (typeof typeOrModule === 'function') {\n            type = typeOrModule;\n        }\n        else {\n            module = typeOrModule;\n            type = Object.getPrototypeOf(module);\n        }\n        if (!module) {\n            throw new Error('Module implementation is required.');\n        }\n        this._modules.set(type, module);\n        if (this._enabled) {\n            module.bind && module.bind(this.getModuleBindData());\n            module.initialize && module.initialize();\n        }\n    }\n    generateSubmissionData(report) {\n        const backtraceData = this._dataBuilder.build(report);\n        if (!this.options.beforeSend) {\n            return backtraceData;\n        }\n        return this.options.beforeSend(backtraceData);\n    }\n    generateSubmissionAttachments(report, reportAttachments) {\n        return [...this.attachmentManager.get(), ...(report.attachments ?? []), ...(reportAttachments ?? [])];\n    }\n    skipFrameOnMessage(data) {\n        return typeof data === 'string' ? 1 : 0;\n    }\n    isReport(data) {\n        return data instanceof BacktraceReport;\n    }\n    getModuleBindData() {\n        return {\n            client: this,\n            options: this.options,\n            attributeManager: this.attributeManager,\n            attachmentManager: this.attachmentManager,\n            reportSubmission: this._reportSubmission,\n            requestHandler: this._requestHandler,\n            database: this.database,\n            sessionFiles: this.sessionFiles,\n            fileSystem: this.fileSystem,\n        };\n    }\n    static destroy() {\n        this._instance = undefined;\n    }\n    validateAttributes() {\n        function validateApplicationAndVersion(attributes) {\n            if (!attributes['application'] || !attributes['application.version']) {\n                return 'application and application.version attributes must be defined.';\n            }\n        }\n        // Validate scoped attributes first. If they return no errors, there is no point\n        // in checking all attributes, which resolving of may be slower.\n        const scoped = this.attributeManager.get('scoped');\n        const scopedError = validateApplicationAndVersion(scoped.attributes);\n        if (!scopedError) {\n            return;\n        }\n        const allAttributes = this.attributeManager.get();\n        const error = validateApplicationAndVersion(allAttributes.attributes);\n        if (!error) {\n            return;\n        }\n        throw new Error(error);\n    }\n}\n\nclass BacktraceCoreClientBuilder {\n    clientSetup;\n    constructor(clientSetup) {\n        this.clientSetup = clientSetup;\n    }\n    addAttributeProvider(provider) {\n        if (!this.clientSetup.attributeProviders) {\n            this.clientSetup.attributeProviders = [provider];\n        }\n        else {\n            this.clientSetup.attributeProviders.push(provider);\n        }\n        return this;\n    }\n    useBreadcrumbSubscriber(breadcrumbSubscriber) {\n        if (!this.clientSetup.breadcrumbsSetup) {\n            this.clientSetup.breadcrumbsSetup = {};\n        }\n        if (!this.clientSetup.breadcrumbsSetup.subscribers) {\n            this.clientSetup.breadcrumbsSetup.subscribers = [breadcrumbSubscriber];\n        }\n        else {\n            this.clientSetup.breadcrumbsSetup.subscribers.push(breadcrumbSubscriber);\n        }\n        return this;\n    }\n    useBreadcrumbsStorage(storage) {\n        if (!this.clientSetup.breadcrumbsSetup) {\n            this.clientSetup.breadcrumbsSetup = {};\n        }\n        if (typeof storage === 'function') {\n            this.clientSetup.breadcrumbsSetup.storage = storage;\n        }\n        else {\n            this.clientSetup.breadcrumbsSetup.storage = () => storage;\n        }\n        return this;\n    }\n    useSessionProvider(sessionProvider) {\n        this.clientSetup.sessionProvider = sessionProvider;\n        return this;\n    }\n    useRequestHandler(handler) {\n        this.clientSetup.requestHandler = handler;\n        return this;\n    }\n    useStackTraceConverter(stackTraceConverter) {\n        this.clientSetup.stackTraceConverter = stackTraceConverter;\n        return this;\n    }\n    useFileSystem(fileSystem) {\n        this.clientSetup.fileSystem = fileSystem;\n        return this;\n    }\n    useReportSubmission(reportSubmission) {\n        this.clientSetup.reportSubmission = reportSubmission;\n        return this;\n    }\n    useSummedMetricsQueue(queue) {\n        this.clientSetup.summedMetricsQueue = queue;\n        return this;\n    }\n    useUniqueMetricsQueue(queue) {\n        this.clientSetup.uniqueMetricsQueue = queue;\n        return this;\n    }\n    useModule(module) {\n        if (!this.clientSetup.modules) {\n            this.clientSetup.modules = [module];\n        }\n        else {\n            this.clientSetup.modules.push(module);\n        }\n        return this;\n    }\n}\n\nclass BacktraceStringAttachment {\n    name;\n    data;\n    constructor(name, data) {\n        this.name = name;\n        this.data = data;\n    }\n    get() {\n        return this.data;\n    }\n}\n\nclass BacktraceUint8ArrayAttachment {\n    name;\n    data;\n    constructor(name, data) {\n        this.name = name;\n        this.data = data;\n    }\n    get() {\n        return new Blob([this.data.buffer]);\n    }\n}\n\nconst ATTRIBUTE_FILE_NAME = 'bt-attributes';\nclass FileAttributeManager {\n    _fileSystem;\n    _fileName;\n    _attributeManager;\n    constructor(_fileSystem, _fileName) {\n        this._fileSystem = _fileSystem;\n        this._fileName = _fileName;\n    }\n    static create(fileSystem) {\n        return new FileAttributeManager(fileSystem);\n    }\n    static createFromSession(sessionFiles, fileSystem) {\n        const fileName = sessionFiles.getFileName(ATTRIBUTE_FILE_NAME);\n        return new FileAttributeManager(fileSystem, fileName);\n    }\n    initialize() {\n        this.saveAttributes();\n    }\n    bind({ attributeManager, sessionFiles }) {\n        if (this._fileName) {\n            throw new Error('This instance is already bound.');\n        }\n        if (!sessionFiles) {\n            return;\n        }\n        this._fileName = sessionFiles.getFileName(ATTRIBUTE_FILE_NAME);\n        this._attributeManager = attributeManager;\n        attributeManager.attributeEvents.on('scoped-attributes-updated', () => this.saveAttributes());\n    }\n    dispose() {\n        this._fileName = undefined;\n    }\n    async get() {\n        if (!this._fileName) {\n            return {};\n        }\n        try {\n            const content = await this._fileSystem.readFile(this._fileName);\n            return JSON.parse(content);\n        }\n        catch {\n            return {};\n        }\n    }\n    async saveAttributes() {\n        if (!this._fileName || !this._attributeManager) {\n            return;\n        }\n        const reportData = this._attributeManager.get('scoped');\n        await this._fileSystem.writeFile(this._fileName, JSON.stringify(reportData.attributes, jsonEscaper()));\n    }\n}\n\nconst SOURCE_DEBUG_ID_VARIABLE = '_btDebugIds';\nclass DebugIdProvider {\n    _stackTraceConverter;\n    _debugIdMapProvider;\n    _fileDebugIds;\n    constructor(_stackTraceConverter, _debugIdMapProvider) {\n        this._stackTraceConverter = _stackTraceConverter;\n        this._debugIdMapProvider = _debugIdMapProvider;\n        this._fileDebugIds = this.loadDebugIds();\n    }\n    getDebugId(file) {\n        const debugId = this._fileDebugIds[file];\n        if (debugId) {\n            return debugId;\n        }\n        // in case of dynamic require - lazy load dynamically debug ids\n        this._fileDebugIds = this.loadDebugIds();\n        return this._fileDebugIds[file];\n    }\n    loadDebugIds() {\n        const debugIdMap = this._debugIdMapProvider?.getDebugIdMap();\n        if (!debugIdMap) {\n            return {};\n        }\n        const message = new Error().message;\n        const result = {};\n        for (const [rawStack, debugId] of Object.entries(debugIdMap)) {\n            const frames = this._stackTraceConverter.convert(rawStack, message);\n            if (!frames.length) {\n                continue;\n            }\n            // The first frame will have the file's path\n            const frame = frames[0];\n            result[frame.library] = debugId;\n        }\n        return result;\n    }\n}\n\nclass VariableDebugIdMapProvider {\n    _variable;\n    constructor(_variable) {\n        this._variable = _variable;\n    }\n    getDebugIdMap() {\n        return this._variable[SOURCE_DEBUG_ID_VARIABLE] ?? {};\n    }\n}\n\nexport { ANONYMOUS_FUNCTION, AttachmentManager, BacktraceCoreApi, BacktraceCoreClient, BacktraceCoreClientBuilder, BacktraceDatabase, BacktraceReport, BacktraceReportSubmissionResult, BacktraceStringAttachment, BacktraceUint8ArrayAttachment, BreadcrumbLogLevel, BreadcrumbType, BreadcrumbsManager, ConnectionError, DEFAULT_TIMEOUT, DebugIdProvider, FileAttributeManager, IdGenerator, OverwritingArray, RequestBacktraceReportSubmission, SOURCE_DEBUG_ID_VARIABLE, SessionFiles, SingleSessionProvider, SubmissionUrlInformation, SummedEvent, TimeHelper, UNKNOWN_FRAME, V8StackTraceConverter, VariableDebugIdMapProvider, anySignal, defaultBreadcrumbsLogLevel, defaultBreadcurmbType, jsonEscaper };\n//# sourceMappingURL=bundle.mjs.map\n",null,null,null,null,null,null,null,null,null],"names":[],"mappings":";;AAAA,MAAM,MAAM,GAAG,aAAa,CAAC;AAEtB,MAAM,SAAS,GAAG;IACrB,WAAW,CAAC,IAAY,EAAE,KAAa,EAAA;AACnC,QAAA,OAAO,GAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAI,CAAA,EAAA,KAAK,EAAE,CAAC;KACvC;IACD,eAAe,EAAE,CAAG,EAAA,MAAM,CAAkB,gBAAA,CAAA;IAC5C,WAAW,EAAE,CAAG,EAAA,MAAM,CAAc,YAAA,CAAA;IACpC,UAAU,EAAE,CAAG,EAAA,MAAM,CAAa,WAAA,CAAA;IAClC,cAAc,EAAE,CAAG,EAAA,MAAM,CAAiB,eAAA,CAAA;IAC1C,IAAI,EAAE,CAAG,EAAA,MAAM,CAAO,KAAA,CAAA;IACtB,aAAa,EAAE,CAAG,EAAA,MAAM,CAAgB,cAAA,CAAA;IACxC,IAAI,EAAE,CAAG,EAAA,MAAM,CAAO,KAAA,CAAA;IACtB,IAAI,EAAE,CAAG,EAAA,MAAM,CAAO,KAAA,CAAA;CAChB;;ACdH,MAAM,gBAAgB,GAAG,IAAI,KAAK,CACrC,2GAA2G,CAC9G;;ACMM,MAAM,aAAa,GAAG,MAAM,CAAC,iBAAiB;;SCLrC,SAAS,GAAA;IACrB,IAAI,CAAC,aAAa,EAAE;AAChB,QAAA,MAAM,gBAAgB,CAAC;KAC1B;AAED,IAAA,OAAO,aAAa,CAAC;AACzB;;ACDO,MAAM,mBAAmB,GAAG,MAAM,CAAC,aAAa;;SCLvC,eAAe,GAAA;IAC3B,IAAI,CAAC,mBAAmB,EAAE;AACtB,QAAA,MAAM,gBAAgB,CAAC;KAC1B;AAED,IAAA,OAAO,mBAAmB,CAAC;AAC/B;;MCPa,oBAAoB,CAAA;AAG7B,IAAA,WAAA,CAA4B,SAAiB,EAAA;QAAjB,IAAS,CAAA,SAAA,GAAT,SAAS,CAAQ;QAF7B,IAAU,CAAA,UAAA,GAAG,IAAI,CAAC;KAEe;AAEjD,IAAA,IAAW,UAAU,GAAA;AACjB,QAAA,OAAO,CAAC,CAAC;KACZ;IAEM,sBAAsB,GAAA;;KAE5B;IAEM,UAAU,GAAA;AACb,QAAA,OAAO,IAAI,CAAC;KACf;AACJ;;AClBD,MAAM,+BAA+B,CAAC;AACtC,IAAI,OAAO,CAAC;AACZ,IAAI,IAAI,MAAM,GAAG;AACjB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC;AAC5B,KAAK;AACL,IAAI,MAAM,GAAG,IAAI,CAAC;AAClB,IAAI,OAAO,CAAC;AACZ,IAAI,WAAW,CAAC,gBAAgB,EAAE,OAAO,EAAE;AAC3C,QAAQ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC/B,QAAQ,IAAI,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE;AACzD,YAAY,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC;AAC3C,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,IAAI,CAAC,OAAO,GAAG,gBAAgB,CAAC;AACxC,KAAK;AACL,IAAI,OAAO,cAAc,CAAC,MAAM,GAAG,QAAQ,EAAE;AAC7C,QAAQ,OAAO,IAAI,+BAA+B,CAAC,eAAe,EAAE,CAAC,EAAE,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;AACtG,KAAK;AACL,IAAI,OAAO,WAAW,GAAG;AACzB,QAAQ,OAAO,IAAI,+BAA+B,CAAC,cAAc,CAAC,CAAC;AACnE,KAAK;AACL,IAAI,OAAO,WAAW,CAAC,OAAO,EAAE;AAChC,QAAQ,OAAO,IAAI,+BAA+B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAC3E,KAAK;AACL,IAAI,OAAO,aAAa,GAAG;AAC3B,QAAQ,OAAO,IAAI,+BAA+B,CAAC,gBAAgB,CAAC,CAAC;AACrE,KAAK;AACL,IAAI,OAAO,qBAAqB,CAAC,OAAO,EAAE;AAC1C,QAAQ,OAAO,IAAI,+BAA+B,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAC5E,KAAK;AACL,IAAI,OAAO,cAAc,GAAG;AAC5B,QAAQ,OAAO,IAAI,+BAA+B,CAAC,eAAe,CAAC,CAAC;AACpE,KAAK;AACL,IAAI,OAAO,cAAc,CAAC,OAAO,EAAE;AACnC,QAAQ,OAAO,IAAI,+BAA+B,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AACvE,KAAK;AACL,IAAI,OAAO,iBAAiB,CAAC,OAAO,EAAE;AACtC,QAAQ,OAAO,IAAI,+BAA+B,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AAC7E,KAAK;AACL,IAAI,OAAO,EAAE,CAAC,QAAQ,EAAE;AACxB,QAAQ,OAAO,IAAI,+BAA+B,CAAC,QAAQ,CAAC,CAAC;AAC7D,KAAK;AACL,IAAI,oBAAoB,CAAC,gBAAgB,EAAE;AAC3C,QAAQ,OAAO,OAAO,gBAAgB,KAAK,QAAQ,CAAC;AACpD,KAAK;AACL,CAAC;AACD;AACA,SAAS,WAAW,GAAG;AACvB,IAAI,MAAM,SAAS,GAAG,EAAE,CAAC;AACzB,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;AACpB;AACA;AACA,IAAI,OAAO,UAAU,GAAG,EAAE,KAAK,EAAE;AACjC,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;AAC5B,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT,QAAQ,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC;AACvC,QAAQ,IAAI,SAAS,KAAK,QAAQ,EAAE;AACpC,YAAY,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AACpC,SAAS;AACT,QAAQ,IAAI,SAAS,KAAK,QAAQ,EAAE;AACpC,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT;AACA;AACA,QAAQ,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;AACjF,YAAY,SAAS,CAAC,GAAG,EAAE,CAAC;AAC5B,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC;AACvB,SAAS;AACT,QAAQ,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;AACvC,YAAY,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC5E,SAAS;AACT,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvB,QAAQ,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9B,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK,CAAC;AACN,CAAC;AAoOD;AACA,MAAM,MAAM,CAAC;AACb,IAAI,UAAU,GAAG,EAAE,CAAC;AACpB,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE;AACxB,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9C,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE;AAC1B,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1D,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL,IAAI,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE;AACzB,QAAQ,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC7C,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,EAAE;AACzB,QAAQ,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACjD,QAAQ,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;AAC7C,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT,QAAQ,KAAK,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,EAAE;AACzD,YAAY,IAAI;AAChB,gBAAgB,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;AAClC,aAAa;AACb,YAAY,MAAM;AAClB;AACA,aAAa;AACb,YAAY,IAAI,IAAI,EAAE;AACtB,gBAAgB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AACrD,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL,IAAI,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE;AACjC,QAAQ,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAC5C,QAAQ,IAAI,IAAI,EAAE;AAClB,YAAY,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChC,SAAS;AACT,aAAa;AACb,YAAY,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAChD,SAAS;AACT,KAAK;AACL,IAAI,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE;AACpC,QAAQ,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAC5C,QAAQ,IAAI,CAAC,IAAI,EAAE;AACnB,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;AACvE,QAAQ,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;AAC1B,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC9B,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;AAC1B,YAAY,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAC1C,SAAS;AACT,KAAK;AACL,CAAC;AAkhBD;AACA,IAAI,kBAAkB,CAAC;AACvB,CAAC,UAAU,kBAAkB,EAAE;AAC/B,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;AACtE,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;AAClE,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;AAChE,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;AACtE,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;AACnE,CAAC,EAAE,kBAAkB,KAAK,kBAAkB,GAAG,EAAE,CAAC,CAAC,CAAC;AAEpD;AACA,IAAI,cAAc,CAAC;AACnB,CAAC,UAAU,cAAc,EAAE;AAC3B,IAAI,cAAc,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;AAC5D,IAAI,cAAc,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AACtD,IAAI,cAAc,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC;AACpE,IAAI,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;AACxD,IAAI,cAAc,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC;AAC7D,IAAI,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC;AACzD,IAAI,cAAc,CAAC,cAAc,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,GAAG,eAAe,CAAC;AAC3E,CAAC,EAAE,cAAc,KAAK,cAAc,GAAG,EAAE,CAAC,CAAC,CAAC;AA6kB5C;AACA,MAAM,WAAW,CAAC;AAClB,IAAI,OAAO,IAAI,GAAG;AAClB,QAAQ,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;AACpF,QAAQ,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC;AAC5C,QAAQ,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC;AAC5C,QAAQ,QAAQ,KAAK;AACrB,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AACxB,aAAa,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACxD,aAAa,IAAI,CAAC,EAAE,CAAC;AACrB,YAAY,GAAG;AACf,YAAY,KAAK;AACjB,iBAAiB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAC5B,iBAAiB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5D,iBAAiB,IAAI,CAAC,EAAE,CAAC;AACzB,YAAY,GAAG;AACf,YAAY,KAAK;AACjB,iBAAiB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAC5B,iBAAiB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5D,iBAAiB,IAAI,CAAC,EAAE,CAAC;AACzB,YAAY,GAAG;AACf,YAAY,KAAK;AACjB,iBAAiB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;AAC7B,iBAAiB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5D,iBAAiB,IAAI,CAAC,EAAE,CAAC;AACzB,YAAY,GAAG;AACf,YAAY,KAAK;AACjB,iBAAiB,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;AAC9B,iBAAiB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5D,iBAAiB,IAAI,CAAC,EAAE,CAAC,EAAE;AAC3B,KAAK;AACL,CAAC;AA8ED;AACA,MAAM,UAAU,SAAS,KAAK,CAAC;AAC/B,IAAI,WAAW,CAAC,OAAO,EAAE;AACzB,QAAQ,KAAK,CAAC,OAAO,IAAI,sBAAsB,CAAC,CAAC;AACjD,KAAK;AACL,CAAC;AACD;AACA;AACA,SAAS,SAAS,CAAC,GAAG,EAAE;AACxB,IAAI,OAAO,OAAO,MAAM,KAAK,WAAW;AACxC,UAAU,MAAM,CAAC,GAAG,CAAC;AACrB,UAAU,OAAO,MAAM,KAAK,WAAW;AACvC,cAAc,MAAM,CAAC,GAAG,CAAC;AACzB,cAAc,OAAO,IAAI,KAAK,WAAW;AACzC,kBAAkB,IAAI,CAAC,GAAG,CAAC;AAC3B,kBAAkB,SAAS,CAAC;AAC5B,CAAC;AACD,MAAM,uBAAuB,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;AAC7D;AACA;AACA;AACA;AACA,MAAM,OAAO,CAAC;AACd,IAAI,UAAU,GAAG,EAAE,CAAC;AACpB,IAAI,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;AAC3B,IAAI,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE;AAC9C,QAAQ,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE;AACxC,YAAY,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;AACvC,SAAS;AACT,QAAQ,MAAM,QAAQ,GAAG,CAAC,EAAE,KAAK;AACjC,YAAY,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;AAC9C,gBAAgB,OAAO,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC3D,aAAa;AACb,iBAAiB;AACjB,gBAAgB,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC/C,aAAa;AACb,SAAS,CAAC;AACV,QAAQ,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,OAAO,KAAK,QAAQ,GAAG,OAAO,GAAG,EAAE,CAAC,CAAC;AAC9E,QAAQ,IAAI,IAAI,EAAE;AAClB,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC9C,SAAS;AACT,aAAa;AACb,YAAY,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC5C,SAAS;AACT,QAAQ,IAAI,MAAM,EAAE;AACpB,YAAY,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC5E,YAAY,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACpE,SAAS;AACT,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AACpE,KAAK;AACL,IAAI,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE;AACxC,QAAQ,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE;AACxC,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACnD,QAAQ,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAC9E,QAAQ,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE;AACtC,YAAY,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAClD,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACrD,YAAY,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC1C,SAAS;AACT,KAAK;AACL,IAAI,aAAa,CAAC,KAAK,EAAE;AACzB,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7C,QAAQ,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC;AACvC,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA,MAAM,WAAW,SAAS,OAAO,CAAC;AAClC,IAAI,OAAO,GAAG,KAAK,CAAC;AACpB,IAAI,OAAO,GAAG,IAAI,CAAC;AACnB,IAAI,MAAM,CAAC;AACX,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,EAAE,CAAC;AAChB;AACA;AACA,QAAQ,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1G,QAAQ,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1G,QAAQ,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;AACzG,KAAK;AACL,IAAI,QAAQ,GAAG;AACf,QAAQ,OAAO,sBAAsB,CAAC;AACtC,KAAK;AACL,IAAI,cAAc,GAAG;AACrB,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;AAC1B,YAAY,MAAM,IAAI,CAAC,MAAM,CAAC;AAC9B,SAAS;AACT,KAAK;AACL,IAAI,aAAa,CAAC,KAAK,EAAE;AACzB,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE;AACpC,YAAY,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;AAChC,YAAY,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU,EAAE;AACpD,gBAAgB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC/C,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAC1C,KAAK;AACL,IAAI,GAAG,CAAC,OAAO,EAAE;AACjB,QAAQ,OAAO,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC;AACrC,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA,MAAM,eAAe,CAAC;AACtB,IAAI,MAAM,CAAC;AACX,IAAI,WAAW,GAAG;AAClB;AACA;AACA,QAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;AACxC,QAAQ,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;AACzF,KAAK;AACL,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,QAAQ,IAAI,KAAK,CAAC;AAClB,QAAQ,IAAI;AACZ,YAAY,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AACvC,SAAS;AACT,QAAQ,OAAO,CAAC,EAAE;AAClB,YAAY,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;AACjD,gBAAgB,MAAM,WAAW,GAAG,QAAQ,CAAC;AAC7C,gBAAgB,IAAI,CAAC,WAAW,CAAC,WAAW,IAAI,WAAW,CAAC,iBAAiB,EAAE;AAC/E;AACA,oBAAoB,KAAK,GAAG,WAAW,CAAC,iBAAiB,EAAE,CAAC;AAC5D,oBAAoB,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC;AACzC,iBAAiB;AACjB,qBAAqB;AACrB;AACA,oBAAoB,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAC1D,oBAAoB,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3D,iBAAiB;AACjB,aAAa;AACb,iBAAiB;AACjB;AACA,gBAAgB,KAAK,GAAG;AACxB,oBAAoB,IAAI,EAAE,OAAO;AACjC,oBAAoB,OAAO,EAAE,KAAK;AAClC,oBAAoB,UAAU,EAAE,KAAK;AACrC,iBAAiB,CAAC;AAClB,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,YAAY,GAAG,MAAM,CAAC;AAClC,QAAQ,IAAI,YAAY,KAAK,SAAS,EAAE;AACxC,YAAY,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;AACjD,gBAAgB,YAAY,GAAG,IAAI,UAAU,CAAC,4BAA4B,CAAC,CAAC;AAC5E,aAAa;AACb,iBAAiB;AACjB,gBAAgB,IAAI;AACpB,oBAAoB,YAAY,GAAG,IAAI,YAAY,CAAC,kCAAkC,CAAC,CAAC;AACxF,iBAAiB;AACjB,gBAAgB,OAAO,GAAG,EAAE;AAC5B;AACA;AACA,oBAAoB,YAAY,GAAG,IAAI,UAAU,CAAC,4BAA4B,CAAC,CAAC;AAChF,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC;AAC1C,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACzC,KAAK;AACL,IAAI,QAAQ,GAAG;AACf,QAAQ,OAAO,0BAA0B,CAAC;AAC1C,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,WAAW,EAAE;AACzD;AACA;AACA,IAAI,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,iBAAiB,CAAC;AACtE,IAAI,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC;AAC9D,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,GAAG;AACjC,IAAI,IAAI,uBAAuB,EAAE;AACjC,QAAQ,OAAO,IAAI,uBAAuB,EAAE,CAAC;AAC7C,KAAK;AACL,SAAS;AACT,QAAQ,OAAO,IAAI,eAAe,EAAE,CAAC;AACrC,KAAK;AACL,CAAC;AACD,SAAS,SAAS,CAAC,GAAG,OAAO,EAAE;AAC/B,IAAI,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;AAC/C,IAAI,SAAS,OAAO,GAAG;AACvB;AACA,QAAQ,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AACtC,YAAY,IAAI,MAAM,EAAE;AACxB,gBAAgB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC7D,aAAa;AACb,SAAS;AACT,KAAK;AACL,IAAI,SAAS,OAAO,GAAG;AACvB,QAAQ,UAAU,CAAC,KAAK,EAAE,CAAC;AAC3B,QAAQ,OAAO,EAAE,CAAC;AAClB,KAAK;AACL,IAAI,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AAClC,QAAQ,IAAI,CAAC,MAAM,EAAE;AACrB,YAAY,SAAS;AACrB,SAAS;AACT,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE;AAC5B,YAAY,OAAO,EAAE,CAAC;AACtB,YAAY,MAAM;AAClB,SAAS;AACT,QAAQ,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAClD,KAAK;AACL,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;AACxC,IAAI,OAAO,UAAU,CAAC,MAAM,CAAC;AAC7B;;MCzxDa,uBAAuB,CAAA;AAKhC,IAAA,IAAW,SAAS,GAAA;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC;KAC1B;AAED,IAAA,WAAA,CAAY,YAA0B,EAAA;AAR9B,QAAA,IAAA,CAAA,UAAU,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QAExB,IAAU,CAAA,UAAA,GAAG,IAAI,CAAC;AAO9B,QAAA,YAAY,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAU,EAAE,IAAc,KAAI;AAC3D,YAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;AACrC,SAAC,CAAC,CAAC;KACN;AAED,IAAA,IAAW,UAAU,GAAA;AACjB,QAAA,OAAO,CAAC,CAAC;KACZ;IAEM,sBAAsB,GAAA;;KAE5B;IAEM,UAAU,GAAA;AACb,QAAA,OAAO,IAAI,CAAC;KACf;AACJ;;MC3BY,qBAAqB,CAAA;AAC9B,IAAA,WAAA,CAA6B,aAA2B,EAAA;QAA3B,IAAa,CAAA,aAAA,GAAb,aAAa,CAAc;KAAI;IAErD,OAAO,OAAO,CAAC,SAAuB,EAAA;QACzC,OAAO,MAAM,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;KACrD;AAED,IAAA,IAAW,gBAAgB,GAAA;QACvB,OAAO,CAAC,CAAC,CAAC;KACb;AAEM,IAAA,GAAG,CAAC,aAA4B,EAAA;QACnC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QAChE,OAAO,CAAC,CAAC,CAAC;KACb;IAEM,cAAc,GAAA;AACjB,QAAA,OAAO,EAAE,CAAC;KACb;AACJ;;ACrBM,eAAe,YAAY,CAAC,GAAiB,EAAE,KAAa,EAAA;IAC/D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,KAAI;AAC1C,QAAA,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,MAAK;AACjB,YAAA,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChB,YAAA,OAAO,EAAE,CAAC;AACd,SAAC,CAAC,CAAC;AACP,KAAC,CAAC,CAAC;AACH,IAAA,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChB,IAAA,OAAO,OAAO,CAAC;AACnB;;ACPA,SAAS,QAAQ,CAAC,KAAa,EAAE,GAAiB,EAAA;IAC9C,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAEK,MAAO,iBAAqB,SAAQ,cAAiB,CAAA;IACvD,WAAY,CAAA,IAAY,EAAE,GAAiB,EAAA;QACvC,KAAK,CAAC,IAAI,qBAAqB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;KAC/C;AACJ,CAAA;AAED,MAAM,qBAAqB,CAAA;IAGvB,WACqB,CAAA,KAAa,EACb,IAAkB,EAAA;QADlB,IAAK,CAAA,KAAA,GAAL,KAAK,CAAQ;QACb,IAAI,CAAA,IAAA,GAAJ,IAAI,CAAc;QAJ/B,IAAS,CAAA,SAAA,GAAG,KAAK,CAAC;QAMtB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,OAAO,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC;KACxF;IAEM,KAAK,GAAA;AACR,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;KAC9E;IAEM,MAAM,KAAK,CAAC,KAAQ,EAAA;AACvB,QAAA,MAAM,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAEtE,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAChB,YAAA,MAAM,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;SAC1E;AAED,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;KACpE;IAEM,KAAK,GAAA;AACR,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;KAC/D;IAEM,KAAK,GAAA;QACR,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;KACrG;AACJ;;MC9BY,mBAAmB,CAAA;IAC5B,WACqB,CAAA,OAAe,EACf,aAA2B,EAAA;QAD3B,IAAO,CAAA,OAAA,GAAP,OAAO,CAAQ;QACf,IAAa,CAAA,aAAA,GAAb,aAAa,CAAc;KAC5C;IAEG,IAAI,CACP,IAAmB,EACnB,WAA2C,EAAA;QAE3C,MAAM,UAAU,GAA6B,EAAE,CAAC;;;QAIhD,IAAK,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAY,GAAG,CAAC,EAAE;AACvD,YAAA,OAAO,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;SAChD;AAED,QAAA,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;YAClC,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAI,CAAC,EAAE,EAAE;gBACL,SAAS;aACZ;YAED,UAAU,CAAC,IAAI,CAAC;gBACZ,EAAE;gBACF,IAAI,EAAE,UAAU,CAAC,IAAI;AACxB,aAAA,CAAC,CAAC;SACN;AAED,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;KACtE;AAEM,IAAA,MAAM,cAAc,CACvB,IAAY,EACZ,UAA+B,EAAA;QAE/B,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,EAAE,EAAE;AACL,YAAA,OAAO,+BAA+B,CAAC,aAAa,EAAE,CAAC;SAC1D;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;KAC7F;AAEO,IAAA,cAAc,CAAC,UAA+B,EAAA;AAClD,QAAA,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC;AACtD,QAAA,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;AACjC,QAAA,IAAI,OAAO,YAAY,IAAI,EAAE;YACzB,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAC7D,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SACnC;AAAM,aAAA,IAAI,OAAO,YAAY,cAAc,EAAE;YAC1C,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;AAC7D,YAAA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SAC1B;AAAM,aAAA,IAAI,OAAO,IAAI,SAAS,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;AAC7D,YAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YAClC,MAAM;iBACD,KAAK,CAAC,OAAO,OAAO,KAAK,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;iBACrF,IAAI,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;iBAChC,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;SACnC;aAAM;AACH,YAAA,OAAO,SAAS,CAAC;SACpB;AAED,QAAA,OAAO,EAAE,CAAC;KACb;AACJ;;MC/EY,iBAAiB,CAAA;AAC1B,IAAA,WAAA,CAA6B,IAAY,EAAA;QAAZ,IAAI,CAAA,IAAA,GAAJ,IAAI,CAAQ;KAAI;IAEtC,SAAS,GAAA;AACZ,QAAA,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;KAChF;IAEM,IAAI,CAAI,aAAqB,EAAE,OAAe,EAAA;AACjD,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;KACnE;AACJ;;MCVY,qBAAqB,CAAA;IAK9B,WACqB,CAAA,aAA2B,EAC3B,OAAe,EAAA;QADf,IAAa,CAAA,aAAA,GAAb,aAAa,CAAc;QAC3B,IAAO,CAAA,OAAA,GAAP,OAAO,CAAQ;QANpB,IAAK,CAAA,KAAA,GAAG,CAAC,CAAC;QACV,IAAa,CAAA,aAAA,GAAG,EAAE,CAAC;QACnB,IAAa,CAAA,aAAA,GAAG,CAAC,CAAC,CAAC;KAK/B;AAEG,IAAA,GAAG,CAAC,KAAkB,EAAA;QACzB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;KAC7D;IAEM,IAAI,GAAA;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;KACrD;AACJ;;MCnBY,gBAAgB,CAAA;AAA7B,IAAA,WAAA,GAAA;QACoB,IAAK,CAAA,KAAA,GAAG,CAAC,CAAC;QACV,IAAa,CAAA,aAAA,GAAG,EAAE,CAAC;QACnB,IAAa,CAAA,aAAA,GAAG,CAAC,CAAC;KASrC;IAPU,GAAG,GAAA;QACN,OAAO;KACV;IAEM,IAAI,GAAA;AACP,QAAA,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;KAC5B;AACJ;;ACYD;;;;;;;;;;AAUG;AACa,SAAA,oBAAoB,CAChC,OAAU,EACV,OAAqC,EAAA;AAErC,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;AACvC,IAAA,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;;IAG3B,MAAM;AACD,SAAA,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;AACtB,SAAA,KAAK,CAAC,CAAC,GAAG,KACP,OAAO,CAAC,KAAK,CACT,sDAAsD,EACtD,4EAA4E,EAC5E,GAAG,CACN,CACJ,CAAC;IAEN,OAAO;AACF,SAAA,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;SAChD,mBAAmB,CAAC,IAAI,mBAAmB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAClE,SAAA,qBAAqB,CAAC,qBAAqB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;SAClE,qBAAqB,CAAC,IAAI,qBAAqB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AACtE,SAAA,qBAAqB,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;IAEnD,IAAI,OAAO,aAAP,OAAO,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAP,OAAO,CAAE,WAAW,EAAE;QACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAW,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO,CAAC,kBAAkB,CAAC,IAAI,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;KAC5E;SAAM;QACH,OAAO,CAAC,kBAAkB,CAAC,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC;AACtE,QAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;KACrC;AAED,IAAA,OAAO,OAAO,CAAC;AACnB;;;;"}