"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__tsfTypeAliases = exports.pinoLogger = exports.ExtendedLogger = exports.ScopedLogger = exports.Logger = exports.LoggerContextSymbol = exports.LoggerHttpContextProps = exports.LoggerContextProps = exports.shouldUseSingleLine = exports.shouldUsePinoPretty = exports.LoggerLevel = void 0;
exports.createLogger = createLogger;
exports.withLoggerContext = withLoggerContext;
exports.projectLoggerHttpContext = projectLoggerHttpContext;
exports.setLogSink = setLogSink;
exports.resetLogSink = resetLogSink;
exports.createLoggerProviders = createLoggerProviders;
const tslib_1 = require("tslib");
const _a = tslib_1.__importStar(require("@zyno-io/ts-server-foundation/type-metadata-runtime"));
const debug_1 = tslib_1.__importDefault(require("debug"));
const pino_1 = tslib_1.__importDefault(require("pino"));
const config_1 = require("../app/config");
const const_1 = require("../app/const");
const env_1 = require("../env");
const context_1 = require("../helpers/async/context");
const error_1 = require("../helpers/utils/error");
const __tsf_metadata_type = _a.createCompactMetadataRegistryV1("[1,[{\"kind\":2},{\"kind\":6},{\"kind\":18,\"typeName\":\"Record\",\"utilityType\":\"Record\",\"typeArguments\":[{\"kind\":6},{\"kind\":2}],\"index\":{\"kind\":2},\"types\":[],\"typeName\":\"LogData\"},{\"kind\":11,\"typeName\":\"LoggerLevel\",\"values\":[0,1,2,3,4,5,6,7]},{\"kind\":8},{\"kind\":14,\"type\":{\"kind\":2}},{\"kind\":3},{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},{\"kind\":12,\"types\":[{\"kind\":18,\"typeName\":\"Record\",\"utilityType\":\"Record\",\"typeArguments\":[{\"kind\":6},{\"kind\":2}],\"index\":{\"kind\":2},\"types\":[],\"typeName\":\"LogData\"},{\"kind\":4}]},{\"kind\":2,\"typeName\":\"(entry: LogEntry) =\\u003e void\",\"typeName\":\"LogSink\"}]]", []);
var LoggerLevel;
(function (LoggerLevel) {
    LoggerLevel[LoggerLevel["none"] = 0] = "none";
    LoggerLevel[LoggerLevel["alert"] = 1] = "alert";
    LoggerLevel[LoggerLevel["error"] = 2] = "error";
    LoggerLevel[LoggerLevel["warning"] = 3] = "warning";
    LoggerLevel[LoggerLevel["log"] = 4] = "log";
    LoggerLevel[LoggerLevel["info"] = 5] = "info";
    LoggerLevel[LoggerLevel["debug"] = 6] = "debug";
    LoggerLevel[LoggerLevel["debug2"] = 7] = "debug2";
})(LoggerLevel || (exports.LoggerLevel = LoggerLevel = {}));
exports.shouldUsePinoPretty = (0, config_1.isDevFeatureEnabled)(env_1.Env.ENABLE_PINO_PRETTY);
exports.shouldUseSingleLine = (0, config_1.isDevFeatureEnabled)(env_1.Env.ENABLE_PINO_SINGLE_LINE);
exports.LoggerContextProps = ['http', 'job'];
exports.LoggerHttpContextProps = ['reqId', 'traceId'];
exports.LoggerContextSymbol = Symbol('LoggerContext');
const PinoSeverityMap = {
    [LoggerLevel.none]: 'DEFAULT',
    [LoggerLevel.alert]: 'ALERT',
    [LoggerLevel.error]: 'ERROR',
    [LoggerLevel.warning]: 'WARNING',
    [LoggerLevel.log]: 'NOTICE',
    [LoggerLevel.info]: 'INFO',
    [LoggerLevel.debug]: 'DEBUG',
    [LoggerLevel.debug2]: 'DEBUG'
};
const InvertedPinoSeverityMap = {
    DEFAULT: LoggerLevel.none,
    ALERT: LoggerLevel.alert,
    ERROR: LoggerLevel.error,
    WARNING: LoggerLevel.warning,
    NOTICE: LoggerLevel.log,
    INFO: LoggerLevel.info,
    DEBUG: LoggerLevel.debug
};
const StandardSeverityAliases = {
    fatal: 'ALERT',
    error: 'ERROR',
    warn: 'WARNING',
    info: 'INFO',
    debug: 'DEBUG',
    trace: 'DEBUG'
};
let currentSink = defaultLogSink;
let defaultLogger;
let defaultPinoLogger;
let _LoggerMetadata_1;
class Logger {
    scope;
    scopeData;
    sink;
    level = LoggerLevel.info;
    constructor(scope = '', scopeData, sink = currentSink) {
        this.scope = scope;
        this.scopeData = scopeData;
        this.sink = sink;
    }
    scoped(shortName, data) {
        const name = shortName ? (this.scope.length ? `${this.scope}:${shortName}` : shortName) : this.scope;
        const scoped = new ScopedLogger(name, mergeData(this.scopeData, data), this.sink);
        scoped.level = this.level;
        return scoped;
    }
    setScopeData(data) {
        this.scopeData = data;
        return this;
    }
    data(data) {
        return this.scoped('', data);
    }
    is(level) {
        return level <= this.level;
    }
    alert(...messages) {
        this.write(LoggerLevel.alert, messages);
    }
    error(...messages) {
        this.write(LoggerLevel.error, messages);
    }
    warning(...messages) {
        this.write(LoggerLevel.warning, messages);
    }
    warn(...messages) {
        this.warning(...messages);
    }
    log(...messages) {
        this.write(LoggerLevel.log, messages);
    }
    info(...messages) {
        this.write(LoggerLevel.info, messages);
    }
    debug(...messages) {
        if (!(0, debug_1.default)(this.scope).enabled)
            return;
        this.write(LoggerLevel.debug, messages, true);
    }
    debug2(...messages) {
        this.write(LoggerLevel.debug2, messages);
    }
    write(level, messages, force = false) {
        if (!force && level > this.level)
            return;
        const parsed = parseLogMessages(messages, this.scopeData);
        const message = stripColors(parsed.message);
        const error = transformLogError(parsed.error);
        const contextProps = getLoggerContextProps();
        const entryData = mergeData(parsed.data, contextProps);
        this.sink({
            level,
            levelName: getLevelName(level),
            scope: this.scope || undefined,
            message,
            data: entryData,
            error,
            timestamp: new Date()
        });
        if (error || level === LoggerLevel.alert || level === LoggerLevel.error) {
            this.handleError(level, message, error, parsed.data, contextProps);
        }
    }
    handleError(level, message, error, data, contextProps) {
        const resolvedError = message && message !== 'Controller error' ? new Error(message) : error ? (0, error_1.toError)(error) : new Error('Unknown error');
        if (resolvedError !== error && error !== undefined) {
            resolvedError.cause = error;
        }
        (0, error_1.reportError)(level, resolvedError, {
            data,
            scope: this.scope || undefined,
            scopeData: this.scopeData,
            ...contextProps
        });
    }
    static __tsfType = _LoggerMetadata_1 = _a.decodeCompactMetadataV1("[1,{\"kind\":16,\"name\":\"Logger\",\"typeName\":\"Logger\",\"classType\":{\"$tsf\":0},\"properties\":[{\"name\":\"level\",\"type\":{\"$tsfType\":0},\"optional\":false}],\"methods\":[{\"name\":\"scoped\",\"parameters\":[{\"name\":\"shortName\",\"type\":{\"$tsfType\":1},\"optional\":false,\"default\":false},{\"name\":\"data\",\"type\":{\"$tsfType\":2},\"optional\":true,\"default\":false}],\"returnType\":{\"kind\":16,\"typeName\":\"ScopedLogger\",\"classType\":{\"$tsf\":1}}},{\"name\":\"setScopeData\",\"parameters\":[{\"name\":\"data\",\"type\":{\"$tsfType\":2},\"optional\":true,\"default\":false}],\"returnType\":{\"kind\":16,\"typeName\":\"this\",\"classType\":{\"$tsf\":2}}},{\"name\":\"data\",\"parameters\":[{\"name\":\"data\",\"type\":{\"$tsfType\":2},\"optional\":false,\"default\":false}],\"returnType\":{\"kind\":16,\"typeName\":\"ScopedLogger\",\"classType\":{\"$tsf\":1}}},{\"name\":\"is\",\"parameters\":[{\"name\":\"level\",\"type\":{\"$tsfType\":3},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":4}},{\"name\":\"alert\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"error\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"warning\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"warn\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"log\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"info\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"debug\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"debug2\",\"parameters\":[{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"write\",\"parameters\":[{\"name\":\"level\",\"type\":{\"$tsfType\":3},\"optional\":false,\"default\":false},{\"name\":\"messages\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false},{\"name\":\"force\",\"type\":{\"$tsfType\":0},\"optional\":true,\"default\":true}],\"returnType\":{\"$tsfType\":6}},{\"name\":\"handleError\",\"parameters\":[{\"name\":\"level\",\"type\":{\"$tsfType\":3},\"optional\":false,\"default\":false},{\"name\":\"message\",\"type\":{\"$tsfType\":7},\"optional\":false,\"default\":false},{\"name\":\"error\",\"type\":{\"$tsfType\":0},\"optional\":false,\"default\":false},{\"name\":\"data\",\"type\":{\"$tsfType\":8},\"optional\":false,\"default\":false},{\"name\":\"contextProps\",\"type\":{\"$tsfType\":8},\"optional\":false,\"default\":false}],\"returnType\":{\"$tsfType\":6}}],\"hasConstructor\":true,\"constructorParameters\":[{\"name\":\"scope\",\"type\":{\"$tsfType\":0},\"optional\":true,\"default\":true},{\"name\":\"scopeData\",\"type\":{\"$tsfType\":2},\"optional\":true,\"default\":false},{\"name\":\"sink\",\"type\":{\"$tsfType\":9},\"optional\":true,\"default\":true}]}]", [() => Logger, () => (typeof ScopedLogger !== "undefined" ? ScopedLogger : (typeof exports !== "undefined" ? exports.ScopedLogger : undefined)), () => (typeof this !== "undefined" ? this : (typeof exports !== "undefined" ? exports.this : undefined))], __tsf_metadata_type);
}
exports.Logger = Logger;
_LoggerMetadata_1.classType = Logger;
Logger.__tsfType = _LoggerMetadata_1;
let _ScopedLoggerMetadata_1;
class ScopedLogger extends Logger {
    static __tsfType = _ScopedLoggerMetadata_1 = _a.decodeCompactMetadataV1("[1,{\"kind\":16,\"name\":\"ScopedLogger\",\"typeName\":\"ScopedLogger\",\"classType\":{\"$tsf\":0},\"properties\":[],\"methods\":[],\"hasConstructor\":false,\"constructorParameters\":[]}]", [() => ScopedLogger], __tsf_metadata_type);
}
exports.ScopedLogger = ScopedLogger;
_ScopedLoggerMetadata_1.classType = ScopedLogger;
ScopedLogger.__tsfType = _ScopedLoggerMetadata_1;
let _ExtendedLoggerMetadata_1;
class ExtendedLogger extends ScopedLogger {
    static __tsfType = _ExtendedLoggerMetadata_1 = _a.decodeCompactMetadataV1("[1,{\"kind\":16,\"name\":\"ExtendedLogger\",\"typeName\":\"ExtendedLogger\",\"classType\":{\"$tsf\":0},\"properties\":[],\"methods\":[],\"hasConstructor\":false,\"constructorParameters\":[]}]", [() => ExtendedLogger], __tsf_metadata_type);
}
exports.ExtendedLogger = ExtendedLogger;
_ExtendedLoggerMetadata_1.classType = ExtendedLogger;
ExtendedLogger.__tsfType = _ExtendedLoggerMetadata_1;
defaultLogger = new ExtendedLogger();
exports.pinoLogger = new Proxy({}, {
    get(_target, property) {
        const logger = getDefaultPinoLogger();
        if (typeof property === 'string' && property in StandardSeverityAliases && !(property in logger)) {
            const value = logger[StandardSeverityAliases[property]];
            return typeof value === 'function' ? value.bind(logger) : value;
        }
        const value = Reflect.get(logger, property, logger);
        return typeof value === 'function' ? value.bind(logger) : value;
    }
});
function createLogger(subject, defaultData) {
    const name = typeof subject === 'string' ? subject : subject.constructor.name;
    return defaultLogger.scoped(name, defaultData);
}
async function withLoggerContext(data, fn) {
    const existingContext = (0, context_1.getContext)();
    const existingLoggerContext = existingContext?.[exports.LoggerContextSymbol];
    return (0, context_1.withContextData)({
        [exports.LoggerContextSymbol]: {
            ...(isLogObject(existingLoggerContext) ? existingLoggerContext : undefined),
            ...data
        }
    }, fn);
}
function projectLoggerHttpContext(context) {
    if (!isLogObject(context))
        return undefined;
    const entries = exports.LoggerHttpContextProps.flatMap(prop => (Object.hasOwn(context, prop) ? [[prop, context[prop]]] : []));
    return entries.length ? Object.fromEntries(entries) : undefined;
}
function setLogSink(sink) {
    currentSink = sink;
    defaultLogger = new ExtendedLogger('', undefined, sink);
}
function resetLogSink() {
    currentSink = defaultLogSink;
    defaultLogger = new ExtendedLogger();
}
function createLoggerProviders() {
    const logger = new ExtendedLogger('', undefined, currentSink);
    defaultLogger = logger;
    return [
        { provide: ExtendedLogger, useValue: logger },
        {
            provide: ScopedLogger,
            useTargetFactory: (target, resolvedLogger) => (target ? resolvedLogger.scoped(target.name) : resolvedLogger),
            deps: [ExtendedLogger]
        },
        { provide: Logger, useExisting: ExtendedLogger }
    ];
}
function parseLogMessages(input, scopeData) {
    const messages = [...input];
    let error = (0, error_1.isError)(messages[0]) ? messages.shift() : (0, error_1.isError)(messages[1]) ? messages.splice(1, 1).shift() : undefined;
    const message = typeof messages[0] === 'string' ? messages.shift() : '';
    let data;
    if (messages.length === 1 && typeof messages[0] === 'object') {
        data = Object.assign(data ?? {}, messages[0]);
    }
    else if (messages.length) {
        data = {};
        messages.forEach((item, index) => {
            data[`arg${index}`] = item;
        });
    }
    else {
        data = undefined;
    }
    if (!error && data && 'err' in data) {
        error = data.err;
        delete data.err;
    }
    if (scopeData) {
        data = Object.assign(data ?? {}, scopeData);
    }
    return { message, data, error };
}
function mergeData(...values) {
    const merged = Object.assign({}, ...values.filter(Boolean));
    return Object.keys(merged).length ? merged : undefined;
}
function getLevelName(level) {
    return (LoggerLevel[level] ?? 'info');
}
function defaultLogSink(entry) {
    const data = {
        ...(entry.error ? { err: entry.error } : undefined),
        ...(entry.scope ? { scope: entry.scope } : undefined),
        ...entry.data
    };
    const logger = getDefaultPinoLogger();
    logger[PinoSeverityMap[entry.level]](data, entry.message);
}
function getDefaultPinoLogger() {
    defaultPinoLogger ??= (0, pino_1.default)({
        formatters: {
            level: label => ({ severity: label }),
            bindings: (0, const_1.isDevelopmentEnvironment)() ? () => ({ pid: process.pid }) : () => ({})
        },
        timestamp: pino_1.default.stdTimeFunctions.isoTime,
        messageKey: 'message',
        customLevels: InvertedPinoSeverityMap,
        useOnlyCustomLevels: true,
        level: 'DEFAULT'
    }, createPinoPrettyStream());
    return defaultPinoLogger;
}
function createPinoPrettyStream() {
    if (!exports.shouldUsePinoPretty)
        return undefined;
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const PinoPretty = require('pino-pretty');
    const createPrettyStream = typeof PinoPretty === 'function' ? PinoPretty : PinoPretty.default;
    if (!createPrettyStream)
        return undefined;
    return createPrettyStream({
        colorize: true,
        singleLine: exports.shouldUseSingleLine,
        messageFormat: `\x1b[90m${process.pid} \x1b[35m{scope} \x1b[36m{message}`,
        ignore: 'scope',
        level: env_1.Env.LOG_LEVEL || (env_1.Env.NODE_ENV === 'production' ? 'info' : 'debug'),
        levelFirst: true,
        levelKey: 'severity',
        customLevels: Object.entries(InvertedPinoSeverityMap)
            .map(([severity, level]) => `${severity}:${level}`)
            .join(','),
        messageKey: 'message',
        customColors: 'alert:bgRed,error:red,warning:yellow,notice:green,info:blue,debug:gray,default:white',
        sync: (0, const_1.isTestEnvironment)()
    });
}
function getLoggerContextProps() {
    const context = (0, context_1.getContext)();
    if (!context)
        return undefined;
    const entries = [];
    for (const prop of exports.LoggerContextProps) {
        if (!context[prop])
            continue;
        const value = prop === 'http' ? projectLoggerHttpContext(context[prop]) : context[prop];
        if (value)
            entries.push([prop, value]);
    }
    const loggerContext = context[exports.LoggerContextSymbol];
    if (isLogObject(loggerContext)) {
        for (const [key, value] of Object.entries(loggerContext))
            entries.push([key, value]);
    }
    return entries.length ? Object.fromEntries(entries) : undefined;
}
function stripColors(message) {
    return message.includes('<') ? message.replace(/<(\/)?([a-zA-Z]+)>/g, '') : message;
}
function transformLogError(error) {
    if (!isLogObject(error))
        return error;
    if (Array.isArray(error.errors) && error.errors.includes(error))
        return withoutSelfReferentialErrors(error);
    if (error.constructor?.name === 'DatabaseError') {
        delete error.entity;
        delete error.classSchema;
        return error;
    }
    if (error.isAxiosError === true)
        return transformAxiosError(error);
    return error;
}
function withoutSelfReferentialErrors(error) {
    const normalized = Object.create(Object.getPrototypeOf(error), Object.getOwnPropertyDescriptors(error));
    delete normalized.errors;
    return normalized;
}
function transformAxiosError(error) {
    const config = isLogObject(error.config) ? error.config : undefined;
    const response = isLogObject(error.response) ? error.response : undefined;
    const state = createAxiosSanitizationState();
    return {
        code: error.code,
        message: error.message,
        stack: error.stack,
        request: {
            url: sanitizeAxiosUrl(config?.url, state),
            method: config?.method,
            headers: sanitizeAxiosHeaders(config?.headers, state),
            data: sanitizeAxiosPayload(config?.data, state)
        },
        response: {
            status: response?.status,
            headers: sanitizeAxiosHeaders(response?.headers, state),
            data: sanitizeAxiosPayload(response?.data, state)
        }
    };
}
const AxiosSensitiveKey = /(?:authorization|cookie|token|secret|password|passwd|passcode|api[-_]?key|credential|private[-_]?key|client[-_]?secret|signature|(?:^|[-_])sig(?:$|[-_])|jwt|(?:^|[-_])pin(?:$|[-_])|ssn|social[-_]?security|e-?mail|card(?:[-_]?number)?|cc[-_]?number|cvv|cvc|phone|address|date[-_]?of[-_]?birth|dob)/i;
const AxiosSensitiveUrlParameter = /(?:code|authorization|cookie|token|secret|password|passcode|api[-_]?key|credential|private[-_]?key|client[-_]?secret|signature|(?:^|[-_])sig(?:$|[-_])|jwt|(?:^|[-_])pin(?:$|[-_])|ssn|social[-_]?security|e-?mail|card(?:[-_]?number)?|cc[-_]?number|cvv|cvc|phone|address|date[-_]?of[-_]?birth|dob)/i;
const AxiosSafeHeader = /^(?:x[-_]?)?(?:request|correlation)[-_]?id$|^(?:traceparent|tracestate|b3|x-b3-[a-z-]+|x-amzn-(?:requestid|trace-id)|(?:x-)?intuit[-_]?tid)$/i;
const AxiosRedacted = '[REDACTED]';
const AxiosMaxDepth = 5;
const AxiosMaxProperties = 50;
const AxiosMaxArrayItems = 50;
const AxiosMaxQueryParameters = 50;
const AxiosMaxStringLength = 4096;
const AxiosMaxNodes = 200;
const AxiosMaxOutputLength = 32768;
const AxiosJwt = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
const AxiosEmail = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;
const AxiosCardNumber = /(?:\d[ -]?){13,19}/;
/**
 * Axios errors commonly contain complete request configs. Normalize them into a
 * useful but safe diagnostic shape; never mutate the error/config owned by Axios.
 */
function createAxiosSanitizationState() {
    return { seen: new WeakSet(), nodes: 0, outputLength: 0 };
}
function sanitizeAxiosHeaders(headers, state) {
    const source = toAxiosHeadersObject(headers);
    if (!source)
        return undefined;
    const safeHeaders = {};
    for (const name in source) {
        if (!Object.hasOwn(source, name))
            continue;
        if (!AxiosSafeHeader.test(name))
            continue;
        if (!consumeAxiosNode(state) || !consumeAxiosOutput(state, name.length))
            break;
        safeHeaders[name] = sanitizeAxiosHeaderValue(source[name], state);
    }
    return Object.keys(safeHeaders).length ? safeHeaders : undefined;
}
function sanitizeAxiosHeaderValue(value, state) {
    if (typeof value === 'string')
        return sanitizeAxiosScalarString(value, state);
    if (Array.isArray(value))
        return value
            .slice(0, AxiosMaxArrayItems)
            .map(item => (typeof item === 'string' ? sanitizeAxiosScalarString(item, state) : '[non-scalar header]'));
    return value === undefined ? undefined : '[non-scalar header]';
}
function sanitizeAxiosUrl(value, state) {
    if (typeof value !== 'string')
        return value === undefined ? undefined : '[invalid URL]';
    if (value.length > AxiosMaxOutputLength)
        return `[TRUNCATED URL: ${value.length} chars]`;
    try {
        const isAbsolute = /^[a-z][a-z\d+.-]*:/i.test(value);
        const url = new URL(value, 'http://axios.invalid');
        url.username = '';
        url.password = '';
        url.search = sanitizeAxiosQuery(url.search.slice(1));
        // URL fragments are not sent in an HTTP request and commonly carry OAuth credentials.
        url.hash = '';
        return sanitizeAxiosScalarString(isAbsolute ? url.toString() : `${url.pathname}${url.search}`, state);
    }
    catch {
        const [path, queryAndHash = ''] = value.split('?', 2);
        if (!queryAndHash)
            return sanitizeAxiosScalarString(path.split('#', 1)[0], state);
        const [query] = queryAndHash.split('#', 1);
        return sanitizeAxiosScalarString(`${path}?${sanitizeAxiosQuery(query)}`, state);
    }
}
function sanitizeAxiosQuery(query) {
    const parts = [];
    let start = 0;
    for (let count = 0; start <= query.length && count < AxiosMaxQueryParameters; count++) {
        const end = query.indexOf('&', start);
        const part = query.slice(start, end === -1 ? undefined : end);
        const separator = part.indexOf('=');
        const key = separator === -1 ? part : part.slice(0, separator);
        let decodedKey = key;
        try {
            decodedKey = decodeURIComponent(key.replace(/\+/g, ' '));
        }
        catch {
            // Preserve malformed query strings as-is unless their raw key is sensitive.
        }
        parts.push(AxiosSensitiveUrlParameter.test(decodedKey) ? `${key}=${AxiosRedacted}` : part);
        if (end === -1)
            return parts.join('&');
        start = end + 1;
    }
    return `${parts.join('&')}&[TRUNCATED]`;
}
function sanitizeAxiosPayload(value, state) {
    return sanitizeAxiosValue(value, 0, state);
}
function sanitizeAxiosValue(value, depth, state) {
    if (!consumeAxiosNode(state))
        return '[TRUNCATED: output limit]';
    if (typeof value === 'string')
        return sanitizeAxiosString(value, depth, state);
    if (value === null || typeof value !== 'object')
        return value;
    if (depth >= AxiosMaxDepth)
        return '[TRUNCATED: maximum depth]';
    if (state.seen.has(value))
        return '[CIRCULAR]';
    state.seen.add(value);
    if (isOpaqueAxiosPayload(value))
        return `[${value.constructor?.name ?? 'opaque payload'}]`;
    if (Array.isArray(value)) {
        const items = [];
        for (let index = 0; index < Math.min(value.length, AxiosMaxArrayItems); index++)
            items.push(sanitizeAxiosValue(value[index], depth + 1, state));
        if (value.length > AxiosMaxArrayItems)
            items.push(`[TRUNCATED: ${value.length - AxiosMaxArrayItems} items]`);
        return items;
    }
    const source = isLogObject(value) ? value : undefined;
    if (!source)
        return `[${value.constructor?.name ?? 'object'}]`;
    const result = {};
    let propertyCount = 0;
    for (const key in source) {
        if (!Object.hasOwn(source, key))
            continue;
        if (propertyCount++ >= AxiosMaxProperties || !consumeAxiosOutput(state, key.length)) {
            result._truncated = 'additional properties';
            break;
        }
        result[key] = AxiosSensitiveKey.test(key) ? AxiosRedacted : sanitizeAxiosValue(source[key], depth + 1, state);
    }
    return result;
}
function sanitizeAxiosString(value, depth, state) {
    const trimmed = value.trimStart();
    if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
        if (value.length > AxiosMaxOutputLength)
            return `[TRUNCATED JSON body: ${value.length} chars]`;
        try {
            return sanitizeAxiosValue(JSON.parse(value), depth + 1, state);
        }
        catch {
            return '[UNPARSEABLE JSON body]';
        }
    }
    if (value.includes('=') && !/[\r\n]/.test(value))
        return sanitizeAxiosScalarString(sanitizeAxiosQuery(value), state);
    return sanitizeAxiosScalarString(value, state);
}
function sanitizeAxiosScalarString(value, state) {
    if (AxiosJwt.test(value) || AxiosEmail.test(value) || AxiosCardNumber.test(value))
        return AxiosRedacted;
    const remaining = AxiosMaxOutputLength - state.outputLength;
    if (remaining <= 0)
        return '[TRUNCATED: output limit]';
    const length = Math.min(value.length, AxiosMaxStringLength, remaining);
    state.outputLength += length;
    return length === value.length ? value : `${value.slice(0, length)}[TRUNCATED]`;
}
function consumeAxiosNode(state) {
    return ++state.nodes <= AxiosMaxNodes;
}
function consumeAxiosOutput(state, length) {
    if (state.outputLength + length > AxiosMaxOutputLength)
        return false;
    state.outputLength += length;
    return true;
}
function isOpaqueAxiosPayload(value) {
    if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value))
        return true;
    if (value instanceof ArrayBuffer || ArrayBuffer.isView(value))
        return true;
    return /(?:formdata|stream|readable|writable|duplex|blob|file)/i.test(value.constructor?.name ?? '');
}
function toAxiosHeadersObject(value) {
    if (!value || typeof value !== 'object')
        return undefined;
    if (isOpaqueAxiosPayload(value))
        return undefined;
    if (typeof value.toJSON === 'function') {
        try {
            const json = value.toJSON();
            return isLogObject(json) ? json : undefined;
        }
        catch {
            return undefined;
        }
    }
    return isLogObject(value) ? value : undefined;
}
function isLogObject(value) {
    return !!value && typeof value === 'object';
}
exports.__tsfTypeAliases = _a.decodeCompactMetadataV1("[1,{\"LogData\":{\"kind\":18,\"typeName\":\"Record\",\"utilityType\":\"Record\",\"typeArguments\":[{\"kind\":6},{\"kind\":2}],\"index\":{\"kind\":2},\"types\":[],\"typeName\":\"LogData\"},\"LogEntry\":{\"kind\":18,\"typeName\":\"LogEntry\",\"types\":[{\"kind\":20,\"name\":\"level\",\"type\":{\"kind\":11,\"typeName\":\"LoggerLevel\",\"values\":[0,1,2,3,4,5,6,7]},\"optional\":false},{\"kind\":20,\"name\":\"levelName\",\"type\":{\"kind\":2,\"typeName\":\"keyof typeof LoggerLevel\"},\"optional\":false},{\"kind\":20,\"name\":\"scope\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"message\",\"type\":{\"kind\":6},\"optional\":false},{\"kind\":20,\"name\":\"data\",\"type\":{\"kind\":12,\"types\":[{\"kind\":18,\"typeName\":\"Record\",\"utilityType\":\"Record\",\"typeArguments\":[{\"kind\":6},{\"kind\":2}],\"index\":{\"kind\":2},\"types\":[],\"typeName\":\"LogData\"},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"error\",\"type\":{\"kind\":12,\"types\":[{\"kind\":2},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"timestamp\",\"type\":{\"kind\":16,\"typeName\":\"Date\",\"classType\":{\"$tsf\":0}},\"optional\":false}]},\"LogSink\":{\"kind\":2,\"typeName\":\"(entry: LogEntry) =\\u003e void\",\"typeName\":\"LogSink\"},\"LoggerInterface\":{\"kind\":16,\"typeName\":\"Logger\",\"classType\":{\"$tsf\":1},\"typeName\":\"LoggerInterface\"}}]", [() => (typeof Date !== "undefined" ? Date : (typeof exports !== "undefined" ? exports.Date : undefined)), () => (typeof Logger !== "undefined" ? Logger : (typeof exports !== "undefined" ? exports.Logger : undefined))], __tsf_metadata_type);
//# sourceMappingURL=logger.js.map