lifecycleion 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +125 -0
- package/dist/index.cjs +7 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/arrays.cjs +95 -0
- package/dist/lib/arrays.cjs.map +1 -0
- package/dist/lib/arrays.d.cts +15 -0
- package/dist/lib/arrays.d.ts +15 -0
- package/dist/lib/arrays.js +63 -0
- package/dist/lib/arrays.js.map +1 -0
- package/dist/lib/ascii-tables/index.cjs +642 -0
- package/dist/lib/ascii-tables/index.cjs.map +1 -0
- package/dist/lib/ascii-tables/index.d.cts +66 -0
- package/dist/lib/ascii-tables/index.d.ts +66 -0
- package/dist/lib/ascii-tables/index.js +603 -0
- package/dist/lib/ascii-tables/index.js.map +1 -0
- package/dist/lib/clamp.cjs +41 -0
- package/dist/lib/clamp.cjs.map +1 -0
- package/dist/lib/clamp.d.cts +26 -0
- package/dist/lib/clamp.d.ts +26 -0
- package/dist/lib/clamp.js +15 -0
- package/dist/lib/clamp.js.map +1 -0
- package/dist/lib/constants.cjs +73 -0
- package/dist/lib/constants.cjs.map +1 -0
- package/dist/lib/constants.d.cts +17 -0
- package/dist/lib/constants.d.ts +17 -0
- package/dist/lib/constants.js +34 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/curly-brackets.cjs +77 -0
- package/dist/lib/curly-brackets.cjs.map +1 -0
- package/dist/lib/curly-brackets.d.cts +17 -0
- package/dist/lib/curly-brackets.d.ts +17 -0
- package/dist/lib/curly-brackets.js +52 -0
- package/dist/lib/curly-brackets.js.map +1 -0
- package/dist/lib/deep-clone.cjs +87 -0
- package/dist/lib/deep-clone.cjs.map +1 -0
- package/dist/lib/deep-clone.d.cts +19 -0
- package/dist/lib/deep-clone.d.ts +19 -0
- package/dist/lib/deep-clone.js +62 -0
- package/dist/lib/deep-clone.js.map +1 -0
- package/dist/lib/error-to-string.cjs +743 -0
- package/dist/lib/error-to-string.cjs.map +1 -0
- package/dist/lib/error-to-string.d.cts +3 -0
- package/dist/lib/error-to-string.d.ts +3 -0
- package/dist/lib/error-to-string.js +706 -0
- package/dist/lib/error-to-string.js.map +1 -0
- package/dist/lib/event-emitter.cjs +899 -0
- package/dist/lib/event-emitter.cjs.map +1 -0
- package/dist/lib/event-emitter.d.cts +78 -0
- package/dist/lib/event-emitter.d.ts +78 -0
- package/dist/lib/event-emitter.js +861 -0
- package/dist/lib/event-emitter.js.map +1 -0
- package/dist/lib/id-helpers.cjs +205 -0
- package/dist/lib/id-helpers.cjs.map +1 -0
- package/dist/lib/id-helpers.d.cts +198 -0
- package/dist/lib/id-helpers.d.ts +198 -0
- package/dist/lib/id-helpers.js +170 -0
- package/dist/lib/id-helpers.js.map +1 -0
- package/dist/lib/is-boolean.cjs +33 -0
- package/dist/lib/is-boolean.cjs.map +1 -0
- package/dist/lib/is-boolean.d.cts +19 -0
- package/dist/lib/is-boolean.d.ts +19 -0
- package/dist/lib/is-boolean.js +8 -0
- package/dist/lib/is-boolean.js.map +1 -0
- package/dist/lib/is-function.cjs +33 -0
- package/dist/lib/is-function.cjs.map +1 -0
- package/dist/lib/is-function.d.cts +3 -0
- package/dist/lib/is-function.d.ts +3 -0
- package/dist/lib/is-function.js +8 -0
- package/dist/lib/is-function.js.map +1 -0
- package/dist/lib/is-number.cjs +38 -0
- package/dist/lib/is-number.cjs.map +1 -0
- package/dist/lib/is-number.d.cts +38 -0
- package/dist/lib/is-number.d.ts +38 -0
- package/dist/lib/is-number.js +12 -0
- package/dist/lib/is-number.js.map +1 -0
- package/dist/lib/is-plain-object.cjs +33 -0
- package/dist/lib/is-plain-object.cjs.map +1 -0
- package/dist/lib/is-plain-object.d.cts +20 -0
- package/dist/lib/is-plain-object.d.ts +20 -0
- package/dist/lib/is-plain-object.js +8 -0
- package/dist/lib/is-plain-object.js.map +1 -0
- package/dist/lib/is-promise.cjs +34 -0
- package/dist/lib/is-promise.cjs.map +1 -0
- package/dist/lib/is-promise.d.cts +3 -0
- package/dist/lib/is-promise.d.ts +3 -0
- package/dist/lib/is-promise.js +9 -0
- package/dist/lib/is-promise.js.map +1 -0
- package/dist/lib/json-helpers.cjs +49 -0
- package/dist/lib/json-helpers.cjs.map +1 -0
- package/dist/lib/json-helpers.d.cts +10 -0
- package/dist/lib/json-helpers.d.ts +10 -0
- package/dist/lib/json-helpers.js +22 -0
- package/dist/lib/json-helpers.js.map +1 -0
- package/dist/lib/lifecycle-manager/index.cjs +5594 -0
- package/dist/lib/lifecycle-manager/index.cjs.map +1 -0
- package/dist/lib/lifecycle-manager/index.d.cts +2044 -0
- package/dist/lib/lifecycle-manager/index.d.ts +2044 -0
- package/dist/lib/lifecycle-manager/index.js +5543 -0
- package/dist/lib/lifecycle-manager/index.js.map +1 -0
- package/dist/lib/logger/index.cjs +2514 -0
- package/dist/lib/logger/index.cjs.map +1 -0
- package/dist/lib/logger/index.d.cts +630 -0
- package/dist/lib/logger/index.d.ts +630 -0
- package/dist/lib/logger/index.js +2470 -0
- package/dist/lib/logger/index.js.map +1 -0
- package/dist/lib/padding-utils.cjs +77 -0
- package/dist/lib/padding-utils.cjs.map +1 -0
- package/dist/lib/padding-utils.d.cts +44 -0
- package/dist/lib/padding-utils.d.ts +44 -0
- package/dist/lib/padding-utils.js +46 -0
- package/dist/lib/padding-utils.js.map +1 -0
- package/dist/lib/process-signal-manager.cjs +1306 -0
- package/dist/lib/process-signal-manager.cjs.map +1 -0
- package/dist/lib/process-signal-manager.d.cts +305 -0
- package/dist/lib/process-signal-manager.d.ts +305 -0
- package/dist/lib/process-signal-manager.js +1269 -0
- package/dist/lib/process-signal-manager.js.map +1 -0
- package/dist/lib/promise-protected-resolver.cjs +828 -0
- package/dist/lib/promise-protected-resolver.cjs.map +1 -0
- package/dist/lib/promise-protected-resolver.d.cts +17 -0
- package/dist/lib/promise-protected-resolver.d.ts +17 -0
- package/dist/lib/promise-protected-resolver.js +791 -0
- package/dist/lib/promise-protected-resolver.js.map +1 -0
- package/dist/lib/retry-utils/index.cjs +2183 -0
- package/dist/lib/retry-utils/index.cjs.map +1 -0
- package/dist/lib/retry-utils/index.d.cts +321 -0
- package/dist/lib/retry-utils/index.d.ts +321 -0
- package/dist/lib/retry-utils/index.js +2133 -0
- package/dist/lib/retry-utils/index.js.map +1 -0
- package/dist/lib/safe-handle-callback.cjs +818 -0
- package/dist/lib/safe-handle-callback.cjs.map +1 -0
- package/dist/lib/safe-handle-callback.d.cts +43 -0
- package/dist/lib/safe-handle-callback.d.ts +43 -0
- package/dist/lib/safe-handle-callback.js +780 -0
- package/dist/lib/safe-handle-callback.js.map +1 -0
- package/dist/lib/serialize-error/index.cjs +93 -0
- package/dist/lib/serialize-error/index.cjs.map +1 -0
- package/dist/lib/serialize-error/index.d.cts +26 -0
- package/dist/lib/serialize-error/index.d.ts +26 -0
- package/dist/lib/serialize-error/index.js +64 -0
- package/dist/lib/serialize-error/index.js.map +1 -0
- package/dist/lib/single-event-observer.cjs +841 -0
- package/dist/lib/single-event-observer.cjs.map +1 -0
- package/dist/lib/single-event-observer.d.cts +54 -0
- package/dist/lib/single-event-observer.d.ts +54 -0
- package/dist/lib/single-event-observer.js +803 -0
- package/dist/lib/single-event-observer.js.map +1 -0
- package/dist/lib/sleep.cjs +37 -0
- package/dist/lib/sleep.cjs.map +1 -0
- package/dist/lib/sleep.d.cts +11 -0
- package/dist/lib/sleep.d.ts +11 -0
- package/dist/lib/sleep.js +12 -0
- package/dist/lib/sleep.js.map +1 -0
- package/dist/lib/strings.cjs +186 -0
- package/dist/lib/strings.cjs.map +1 -0
- package/dist/lib/strings.d.cts +107 -0
- package/dist/lib/strings.d.ts +107 -0
- package/dist/lib/strings.js +149 -0
- package/dist/lib/strings.js.map +1 -0
- package/dist/lib/tmp-dir.cjs +254 -0
- package/dist/lib/tmp-dir.cjs.map +1 -0
- package/dist/lib/tmp-dir.d.cts +63 -0
- package/dist/lib/tmp-dir.d.ts +63 -0
- package/dist/lib/tmp-dir.js +211 -0
- package/dist/lib/tmp-dir.js.map +1 -0
- package/dist/lib/unix-time-helpers.cjs +53 -0
- package/dist/lib/unix-time-helpers.cjs.map +1 -0
- package/dist/lib/unix-time-helpers.d.cts +56 -0
- package/dist/lib/unix-time-helpers.d.ts +56 -0
- package/dist/lib/unix-time-helpers.js +24 -0
- package/dist/lib/unix-time-helpers.js.map +1 -0
- package/package.json +220 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/strings.ts","../../../src/lib/constants.ts","../../../src/lib/padding-utils.ts","../../../src/lib/ascii-tables/ascii-table-utils.ts","../../../src/lib/ascii-tables/multi-column-ascii-table.ts","../../../src/lib/ascii-tables/key-value-ascii-table.ts","../../../src/lib/clamp.ts","../../../src/lib/error-to-string.ts","../../../src/lib/is-promise.ts","../../../src/lib/is-function.ts","../../../src/lib/safe-handle-callback.ts","../../../src/lib/event-emitter.ts","../../../src/lib/unix-time-helpers.ts","../../../src/lib/curly-brackets.ts","../../../src/lib/is-number.ts","../../../src/lib/logger/sinks/array.ts","../../../src/lib/logger/sinks/console.ts","../../../src/lib/logger/types.ts","../../../src/lib/logger/utils/color.ts","../../../src/lib/logger/utils/redaction.ts","../../../src/lib/deep-clone.ts","../../../src/lib/logger/utils/error-object.ts","../../../src/lib/logger/logger-service.ts","../../../src/lib/logger/sinks/file.ts","../../../src/lib/logger/sinks/named-pipe.ts","../../../src/lib/logger/index.ts"],"sourcesContent":["import { removeEmptyStringsFromArray } from './arrays';\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\n/**\n * Converts a string or an array of strings to Pascal Case.\n *\n * This function takes an input string or an array of strings, each potentially containing hyphens,\n * and converts them to Pascal Case. It removes any characters that are not letters or numbers,\n * capitalizes the first letter of each substring, and ensures the rest of the substring\n * is in lowercase. Finally, it concatenates all these substrings to produce a Pascal Case\n * output.\n *\n * @param {string | string[]} input - The input string or array of strings to be converted to Pascal Case.\n * @returns {string} The converted string in Pascal Case.\n *\n * Examples:\n * toPascalCase(\"hello-world-123!$\") will return \"HelloWorld123\"\n * toPascalCase([\"hello\", \"world-123!$\"]) will return \"HelloWorld123\"\n */\n\nexport function toPascalCase(input: string | string[]): string {\n // Ensure input is an array\n const inputArray = Array.isArray(input) ? input : [input];\n\n // Process each string in the array\n const parts: string[] = [];\n\n for (const item of inputArray) {\n // Clean the string, split by hyphen, and remove empty strings\n const cleanedItem = item.replace(/[^a-zA-Z0-9-]/g, '');\n parts.push(...removeEmptyStringsFromArray(cleanedItem.split('-')));\n }\n\n // Process and rejoin the input strings\n return parts\n .map(\n (subString) =>\n subString.charAt(0).toUpperCase() + subString.slice(1).toLowerCase(),\n )\n .join('');\n}\n\n/**\n * Converts a string or an array of strings to Camel Case.\n *\n * This function takes an input string or an array of strings, each potentially containing hyphens,\n * and converts them to Camel Case. It removes any characters that are not letters or numbers,\n * capitalizes the first letter of each substring after the first one, and ensures the rest of the substring\n * is in lowercase. For the first substring, it ensures the entire substring is in lowercase.\n * Finally, it concatenates all these substrings to produce a Camel Case output.\n *\n * @param {string | string[]} input - The input string or array of strings to be converted to Camel Case.\n * @returns {string} The converted string in Camel Case.\n *\n * Examples:\n * toCamelCase(\"hello-world-123!$\") will return \"helloWorld123\"\n * toCamelCase([\"hello\", \"world-123!$\"]) will return \"helloWorld123\"\n */\n\nexport function toCamelCase(input: string | string[]): string {\n // Ensure input is an array\n const inputArray = Array.isArray(input) ? input : [input];\n\n // Process each string in the array\n const parts: string[] = [];\n\n for (const item of inputArray) {\n // Clean the string, split by hyphen, and remove empty strings\n const cleanedItem = item.replace(/[^a-zA-Z0-9-]/g, '');\n parts.push(...removeEmptyStringsFromArray(cleanedItem.split('-')));\n }\n\n // Process and rejoin the input strings\n return parts\n .map((subString, index) =>\n index === 0\n ? subString.toLowerCase()\n : subString.charAt(0).toUpperCase() + subString.slice(1).toLowerCase(),\n )\n .join('');\n}\n\n/**\n * This method converts a string or an array of strings to camel case,\n * but if starting with a leading hyphen, it will convert to Pascal case.\n */\n\nexport function toCamelCaseWithPascalOverride(\n input: string | string[],\n): string {\n if (isString(input) && input.startsWith('-')) {\n return toPascalCase(input);\n } else if (\n Array.isArray(input) &&\n input.length > 0 &&\n input[0].startsWith('-')\n ) {\n return toPascalCase(input);\n } else {\n return toCamelCase(input);\n }\n}\n\n/**\n * Converts a string or an array of strings to constant case.\n *\n * The function takes a string or an array of strings, where each string can be separated by a '-',\n * and converts them into a constant case format (all uppercase with underscores between words).\n * It first cleans the input by removing non-alphanumeric characters (except for hyphens), splits the\n * string into parts on hyphens, and then joins these parts with underscores, converting the entire\n * result to uppercase.\n *\n * @param {string | string[]} input - The input string or array of strings to be converted.\n * @returns {string} The converted string in constant case.\n *\n * Example:\n * toConstantCase(\"hello-world\") will return \"HELLO_WORLD\"\n * toConstantCase([\"hello\", \"world\"]) will return \"HELLO_WORLD\"\n */\n\nexport function toConstantCase(input: string | string[]): string {\n // Ensure input is an array\n const inputArray = Array.isArray(input) ? input : [input];\n\n // Process each string in the array\n let parts: string[] = [];\n\n for (const item of inputArray) {\n // Clean the string and split by hyphen\n const cleanedItem = item.replace(/[^a-zA-Z0-9-]/g, '');\n parts.push(...cleanedItem.split('-'));\n }\n\n // Remove empty strings from the array\n parts = removeEmptyStringsFromArray(parts);\n\n // Join parts with underscore and convert to uppercase\n return parts.join('_').toUpperCase();\n}\n\nexport function splitGraphemes(text: string): string[] {\n const graphemes: string[] = [];\n let grapheme = '';\n let zwjSequence = '';\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n const nextChar = text[i + 1] || '';\n const code = char.charCodeAt(0);\n\n // Handling combining marks and zero width joiner\n if (\n (code >= 0x0300 && code <= 0x036f) || // Combining Diacritical Marks\n (code >= 0x1ab0 && code <= 0x1aff) || // Combining Diacritical Marks Extended\n (code >= 0x1dc0 && code <= 0x1dff) || // Combining Diacritical Marks Supplement\n (code >= 0xfe20 && code <= 0xfe2f) || // Combining Half Marks\n (code >= 0x0e31 && code <= 0x0e3a) || // Thai combining marks\n (code >= 0x0e47 && code <= 0x0e4e)\n ) {\n // Thai combining marks\n grapheme += char;\n } else if (char === '\\u200d') {\n // Zero Width Joiner (ZWJ)\n zwjSequence += grapheme + char;\n grapheme = '';\n } else {\n if (grapheme) {\n if (zwjSequence) {\n graphemes.push(zwjSequence + grapheme);\n zwjSequence = '';\n } else {\n graphemes.push(grapheme);\n }\n }\n grapheme = char;\n\n // Handle surrogate pairs (needed for certain characters including emojis)\n if (\n char >= '\\ud800' &&\n char <= '\\udbff' &&\n nextChar >= '\\udc00' &&\n nextChar <= '\\udfff'\n ) {\n grapheme += nextChar;\n i++;\n }\n }\n }\n\n if (grapheme) {\n if (zwjSequence) {\n graphemes.push(zwjSequence + grapheme);\n } else {\n graphemes.push(grapheme);\n }\n }\n\n return graphemes;\n}\n\nexport function skipTrailingNewLines(str: string): string {\n return str.replace(/\\n+$/, '');\n}\n\n/**\n * Filters a string to include only specified characters, optionally replacing disallowed characters.\n *\n * @param str - The input string to be filtered.\n * @param list - An array of allowed characters.\n * @param caseInsensitive - Optional. If true, the filtering is case-insensitive. Default is false.\n * @param replacementChar - Optional. Character to replace disallowed characters. If empty, disallowed characters are removed. Default is ''.\n * @returns A new string containing only the allowed characters from the input string, with disallowed characters optionally replaced.\n *\n * @example\n * // Case-sensitive usage, removing disallowed characters\n * characterAllowedOnly(\"Hello123!\", [\"H\", \"e\", \"l\", \"o\"]);\n * // Returns: \"Hello\"\n *\n * @example\n * // Case-insensitive usage, removing disallowed characters\n * characterAllowedOnly(\"Hello123!\", [\"h\", \"E\", \"L\", \"O\"], true);\n * // Returns: \"Hello\"\n *\n * @example\n * // Using replacement character\n * characterAllowedOnly(\"Hello123!\", [\"H\", \"e\", \"l\", \"o\"], false, \"-\");\n * // Returns: \"Hello---\"\n */\n\nexport function characterAllowedOnly(\n str: string,\n list: string[],\n // eslint-disable-next-line @typescript-eslint/naming-convention\n caseInsensitive = false,\n replacementChar = '',\n): string {\n let newStr = '';\n\n // Convert the allowed list to lowercase if case-insensitive\n if (caseInsensitive) {\n list = Array.from(new Set(list.map((item) => item.toLowerCase())));\n }\n\n // Convert the entire input string to lowercase if case-insensitive\n const processedStr = caseInsensitive ? str.toLowerCase() : str;\n\n for (const c of processedStr) {\n if (list.includes(c)) {\n newStr += c;\n } else if (replacementChar !== '') {\n newStr += replacementChar;\n }\n }\n\n return newStr;\n}\n\n// functions to chop characters from a string.\n\n/**\n * Will remove the matching first character from a string\n * @param str\n * @param char\n * @returns\n */\n\nexport function chopBeginningCharacter(str: string, char: string): string {\n if (str.startsWith(char)) {\n return str.slice(1);\n } else {\n return str;\n }\n}\n\n/**\n * Will remove the matching last character from the string\n * @param str\n * @param char\n * @returns\n */\nexport function chopEndingCharacter(str: string, char: string): string {\n if (str.endsWith(char)) {\n return str.slice(0, -1);\n } else {\n return str;\n }\n}\n\n/**\n * Will remove the matching character, from the beginning and/or end of the string if matching\n * @param str\n * @param char\n * @returns\n */\n\nexport function chopBothBeginningAndEndingCharacters(\n str: string,\n char: string,\n): string {\n return chopBeginningCharacter(chopEndingCharacter(str, char), char);\n}\n","// prettier-ignore\nexport const BLANK_SPACE = ' ';\n\nexport const EOL = '\\n';\nexport const DOUBLE_EOL = EOL + EOL;\nexport const INDENT = ' '.repeat(4);\nexport const DOUBLE_INDENT = INDENT + INDENT;\n\n// prettier-ignore\nexport const SINGLE_QUOTE = \"'\";\n\n// similar to Python string library\nexport const ASCII_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';\nexport const ASCII_UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nexport const ASCII_LETTERS = ASCII_LOWERCASE + ASCII_UPPERCASE;\nexport const DIGITS = '0123456789';\nexport const HEX_DIGITS = DIGITS + 'abcdefABCDEF';\nexport const OCT_DIGITS = '01234567';\nexport const PUNCTUATION = '!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~';\nexport const WHITESPACE = ' \\t\\n\\r\\v\\f';\nexport const PRINTABLE = DIGITS + ASCII_LETTERS + PUNCTUATION + WHITESPACE;\n","/**\n * Utilities to pad strings with another string up to a defined length.\n * Each function takes a string, length to pad and the string to be used for padding (but defaults to a blank space if not provided) and returns the modified string\n *\n * This only pads on the left side, so text is added to the front until the total string equals the given length.\n *\n * ```typescript\n * padLeft('Hey', 6, '*'); // returns ***Hey\n * ```\n * @category String Padding\n */\n\nimport { BLANK_SPACE } from './constants';\n\nexport function padLeft(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return str.padStart(length, padStr);\n}\n\n/**\n * This only pads on the right side, so text is added to the end until the total string equals the given length.\n *\n * ```typescript\n * padRight('Hey', 6, '*'); // returns Hey***\n * ```\n *\n * @category String Padding\n */\n\nexport function padRight(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return str.padEnd(length, padStr);\n}\n\n/**\n * Same as `padCenterPreferLeft` and `padCenterPreferRight` but you can pass in a string with `left` or `right` before the padStr to use more direct.\n *\n * Defaults to `left`\n *\n * @category String Padding\n */\n\nexport function padCenter(\n str: string,\n length: number,\n prefer: 'left' | 'right' = 'left',\n padStr = BLANK_SPACE,\n): string {\n const midStrLength = length - str.length;\n\n if (midStrLength > 0) {\n const padLeftAmount =\n prefer === 'left'\n ? Math.ceil(midStrLength / 2)\n : Math.floor(midStrLength / 2);\n\n const padRightAmount =\n prefer === 'left'\n ? Math.floor(midStrLength / 2)\n : Math.ceil(midStrLength / 2);\n\n return (\n padLeft('', padLeftAmount, padStr) +\n str +\n padRight('', padRightAmount, padStr)\n );\n } else {\n return str;\n }\n}\n\n/**\n * It tries to pad equally on both sides in an attempt to center your text. However if it can't the extra character will be added to the left side\n *\n * @category String Padding\n */\n\nexport function padCenterPreferLeft(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return padCenter(str, length, 'left', padStr);\n}\n\n/**\n * It tries to pad equally, but if it can't the extra character will be added to the right side\n *\n * @category String Padding\n */\n\nexport function padCenterPreferRight(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return padCenter(str, length, 'right', padStr);\n}\n","import { padCenterPreferRight, padRight } from '../padding-utils';\nimport stringWidth from 'string-width';\nimport { splitGraphemes } from '../strings';\n\nexport class ASCIITableUtils {\n public static centerText(text: string, width: number): string {\n return padCenterPreferRight(text, width, ' ');\n }\n\n public static createSeparator(\n columnWidths: number[],\n character: string = '=',\n ): string {\n const totalWidth =\n columnWidths.reduce((sum, width) => sum + width + 3, 0) - 1;\n\n return `+${padRight('', totalWidth, character)}+`;\n }\n\n public static wrapText(text: string, maxLength: number): string[] {\n const words = text.split(' ');\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (stringWidth(currentLine) + stringWidth(word) + 1 <= maxLength) {\n currentLine += (currentLine ? ' ' : '') + word;\n } else {\n if (currentLine) {\n lines.push(currentLine);\n }\n\n if (stringWidth(word) <= maxLength) {\n currentLine = word;\n } else {\n const subWords = ASCIITableUtils.splitWord(word, maxLength);\n lines.push(...subWords.slice(0, -1));\n currentLine = subWords[subWords.length - 1];\n }\n }\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n return lines;\n }\n\n public static splitWord(word: string, maxLength: number): string[] {\n const graphemes = splitGraphemes(word);\n const subWords: string[] = [];\n let currentSubWord = '';\n\n for (const grapheme of graphemes) {\n if (stringWidth(currentSubWord + grapheme) <= maxLength) {\n currentSubWord += grapheme;\n } else {\n subWords.push(currentSubWord);\n currentSubWord = grapheme;\n }\n }\n\n if (currentSubWord) {\n subWords.push(currentSubWord);\n }\n\n return subWords;\n }\n}\n","import { ASCIITableUtils } from './ascii-table-utils';\nimport stringWidth from 'string-width';\n\ninterface MultiColumnASCIITableOptions {\n tableWidth?: number;\n emptyMessage?: string;\n widthMode?: 'flex' | 'fixed';\n}\n\nexport class MultiColumnASCIITable {\n private headers: string[];\n private rows: string[][];\n private tableWidth: number;\n private emptyMessage: string;\n private widthMode: 'flex' | 'fixed';\n\n constructor(headers: string[], options: MultiColumnASCIITableOptions = {}) {\n this.headers = headers;\n this.rows = [];\n this.tableWidth = options.tableWidth || 80;\n this.emptyMessage = options.emptyMessage || '';\n this.widthMode = options.widthMode || 'flex';\n\n const minTableWidth = this.getMinimumWidth();\n\n if (this.tableWidth < minTableWidth) {\n throw new Error(\n `Table width must be at least ${minTableWidth} to accommodate the headers.`,\n );\n }\n }\n\n public getMinimumWidth(): number {\n return this.headers.length * 4 + 1;\n }\n\n public addRow(row: string[]): void {\n if (row.length !== this.headers.length) {\n throw new Error(\n `Number of values in the row (${row.length}) must match the number of headers (${this.headers.length}).`,\n );\n }\n\n this.rows.push(row);\n }\n\n public toString(options: MultiColumnASCIITableOptions = {}): string {\n const tableWidth = options.tableWidth || this.tableWidth;\n const emptyMessage = options.emptyMessage || this.emptyMessage;\n\n if (this.rows.length === 0) {\n const emptyTableWidth = Math.min(tableWidth, 40);\n\n const separator = '+' + '-'.repeat(emptyTableWidth - 2) + '+';\n const emptyMessageLines = ASCIITableUtils.wrapText(\n emptyMessage,\n emptyTableWidth - 4,\n );\n\n const emptyRows = emptyMessageLines.map((line) => {\n const paddingLeft = ' '.repeat(\n Math.floor((emptyTableWidth - stringWidth(line) - 4) / 2),\n );\n\n const paddingRight = ' '.repeat(\n Math.ceil((emptyTableWidth - stringWidth(line) - 4) / 2),\n );\n\n return `| ${paddingLeft}${line}${paddingRight} |`;\n });\n\n if (emptyRows.length === 0) {\n emptyRows.push(`| ${' '.repeat(emptyTableWidth - 4)} |`);\n }\n\n return [separator, ...emptyRows, separator].join('\\n');\n }\n\n const columnWidths = this.calculateColumnWidths(options);\n\n const headerSeparator = ASCIITableUtils.createSeparator(columnWidths);\n const rowSeparator = ASCIITableUtils.createSeparator(columnWidths, '-');\n let tableString = headerSeparator + '\\n';\n\n const header = this.renderRow(this.headers, columnWidths);\n tableString += header + '\\n' + rowSeparator + '\\n';\n\n const rows = this.rows.map((row) => {\n return this.renderRow(row, columnWidths);\n });\n\n tableString += rows.join('\\n' + rowSeparator + '\\n');\n tableString += '\\n' + headerSeparator;\n\n return tableString;\n }\n\n public calculateColumnWidths(\n options: MultiColumnASCIITableOptions = {},\n ): number[] {\n const tableWidth = options.tableWidth || this.tableWidth;\n const widthMode = options.widthMode || this.widthMode;\n\n const numColumns = this.headers.length;\n\n if (widthMode === 'fixed') {\n const availableWidth = tableWidth - (numColumns + 1) * 3 + 1;\n const columnWidth = Math.floor(availableWidth / numColumns);\n const extraWidth = availableWidth % numColumns;\n const columnWidths = new Array(numColumns).fill(columnWidth);\n\n // if there is any remaining width (extraWidth), we distribute it evenly among the columns starting from the first column.\n for (let i = 0; i < extraWidth; i++) {\n columnWidths[i] += 1;\n }\n\n return columnWidths as number[];\n }\n\n const availableWidth = tableWidth - (numColumns + 1) * 3 + 1;\n const maxColumnWidth = Math.floor(availableWidth / numColumns);\n const totalContentWidth = this.headers.reduce(\n (sum, header) => sum + stringWidth(header),\n 0,\n );\n\n if (availableWidth >= totalContentWidth) {\n const remainingWidth = availableWidth - totalContentWidth;\n const extraCharWidth = Math.floor(remainingWidth / numColumns);\n const extraCharRemainder = remainingWidth % numColumns;\n\n const columnWidths = this.headers.map((header, index) => {\n const extraWidth = index < extraCharRemainder ? 1 : 0;\n return stringWidth(header) + extraCharWidth + extraWidth;\n });\n\n return columnWidths;\n } else {\n const columnWidths = this.headers.map(() => maxColumnWidth);\n\n return columnWidths;\n }\n }\n\n private renderRow(row: string[], columnWidths: number[]): string {\n const wrappedCells = row.map((value, index) => {\n const wrappedLines = ASCIITableUtils.wrapText(value, columnWidths[index]);\n\n return wrappedLines\n .map((line) => line.padEnd(columnWidths[index]))\n .join('\\n');\n });\n\n const maxLines = Math.max(\n ...wrappedCells.map((cell) => cell.split('\\n').length),\n );\n\n const paddedRows = [];\n\n for (let i = 0; i < maxLines; i++) {\n const rowLine = wrappedCells.map((cell, index) => {\n const cellLines = cell.split('\\n');\n const cellLine = cellLines[i] || '';\n const padding = ' '.repeat(columnWidths[index] - stringWidth(cellLine));\n\n return ' ' + cellLine + padding + ' ';\n });\n\n paddedRows.push('|' + rowLine.join('|') + '|');\n }\n\n return paddedRows.join('\\n');\n }\n}\n","import { isString } from '../strings';\nimport { padRight } from '../padding-utils';\nimport { MultiColumnASCIITable } from './multi-column-ascii-table';\nimport { ASCIITableUtils } from './ascii-table-utils';\nimport stringWidth from 'string-width';\nimport { clamp } from '../clamp';\n\nexport type TableRowValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | KeyValueASCIITable\n | MultiColumnASCIITable\n | NestedKeyValueEntry[];\n\ntype TableRow = TableRowRegular | TableRowOwn;\n\ninterface TableRowRegular {\n kind: 'regular';\n key: string;\n value: TableRowValue;\n}\n\ninterface TableRowOwn {\n kind: 'own';\n key: string;\n value: string | NestedKeyValueEntry[];\n}\n\nexport interface NestedKeyValueEntry {\n key: string;\n value: string | KeyValueASCIITable | NestedKeyValueEntry[];\n}\n\ninterface KeyValueASCIITableOptions {\n tableWidth?: number;\n autoAdjustWidthWhenPossible?: boolean;\n emptyMessage?: string;\n}\n\nexport class KeyValueASCIITable {\n public readonly tableWidth: number;\n private emptyMessage: string;\n private autoAdjustWidthWhenPossible: boolean = true;\n\n private rows: TableRow[] = [];\n\n constructor(options: KeyValueASCIITableOptions = {}) {\n const minTableWidth = this.getMinimumWidth();\n\n if (options.tableWidth && options.tableWidth < minTableWidth) {\n throw new Error(\n `Table width must be at least ${minTableWidth} to accommodate the table structure.`,\n );\n }\n\n this.tableWidth = options.tableWidth || 80;\n this.autoAdjustWidthWhenPossible =\n options.autoAdjustWidthWhenPossible ?? true;\n this.emptyMessage = options.emptyMessage || '';\n }\n\n public getMinimumWidth(): number {\n // The minimum width for the KeyValueASCIITable is 9 characters:\n // - 2 character for the '| ' at the start\n // - 1 character for the minimum key column width\n // - 3 character for the ' | ' separating the key and value columns\n // - 1 character for the minimum value column width\n // - 2 character for the ' |' at the end\n\n return 9;\n }\n\n /**\n * Adds key and value to the table but placing the value on its own row.\n *\n * @param key\n * @param value\n */\n\n public addValueOnSeparateRow(key: string, value: string): void {\n const row: TableRow = { kind: 'own', key, value };\n\n this.rows.push(row);\n }\n\n /**\n * Adds key and value to the table.\n *\n * If provided value is an instance of ASCIITable or MultiColumnASCIITable, it will be rendered as a nested table on its own row for readability.\n *\n * @param key\n * @param value\n */\n\n public addRow(key: string, value: TableRowValue): void {\n const row: TableRow = { kind: 'regular', key, value };\n\n this.rows.push(row);\n }\n\n public toString(options: KeyValueASCIITableOptions = {}): string {\n const tableWidth = options.tableWidth || this.tableWidth;\n const canAutoAdjustWidthWhenPossible =\n options.autoAdjustWidthWhenPossible ?? this.autoAdjustWidthWhenPossible;\n\n const emptyMessage = options.emptyMessage || this.emptyMessage;\n\n if (this.rows.length === 0) {\n const emptyTableWidth = Math.min(tableWidth, 40);\n\n const separator = '+' + '-'.repeat(emptyTableWidth - 2) + '+';\n const emptyMessageLines = ASCIITableUtils.wrapText(\n emptyMessage,\n emptyTableWidth - 4,\n );\n\n const emptyRows = emptyMessageLines.map((line) => {\n const paddingLeft = padRight(\n '',\n Math.floor((emptyTableWidth - stringWidth(line) - 4) / 2),\n ' ',\n );\n\n const paddingRight = padRight(\n '',\n Math.ceil((emptyTableWidth - stringWidth(line) - 4) / 2),\n ' ',\n );\n\n return `| ${paddingLeft}${line}${paddingRight} |`;\n });\n\n if (emptyRows.length === 0) {\n emptyRows.push(`| ${' '.repeat(emptyTableWidth - 4)} |`);\n }\n\n return [separator, ...emptyRows, separator].join('\\n');\n }\n\n const columnWidths = this.calculateColumnWidths(options);\n\n const headerSeparator = ASCIITableUtils.createSeparator(columnWidths);\n const rowSeparator = ASCIITableUtils.createSeparator(columnWidths, '-');\n\n let tableString = headerSeparator + '\\n';\n\n for (const [rowIndex, row] of this.rows.entries()) {\n const { kind, key, value } = row;\n\n if (\n kind === 'own' ||\n value instanceof KeyValueASCIITable ||\n value instanceof MultiColumnASCIITable ||\n Array.isArray(value)\n ) {\n const keyString = ASCIITableUtils.centerText(\n key,\n columnWidths[0] + columnWidths[1] + 3,\n );\n\n tableString += `| ${keyString} |\\n`;\n tableString += rowSeparator + '\\n';\n\n let valueString = '';\n\n if (value instanceof KeyValueASCIITable) {\n valueString = this.formatValue(\n value,\n tableWidth - 4,\n canAutoAdjustWidthWhenPossible,\n '',\n );\n } else if (value instanceof MultiColumnASCIITable) {\n valueString = this.formatValue(\n value,\n tableWidth - 4,\n canAutoAdjustWidthWhenPossible,\n '',\n );\n } else if (Array.isArray(value)) {\n valueString = this.formatValue(\n value,\n tableWidth - 4,\n canAutoAdjustWidthWhenPossible,\n '',\n );\n } else if (row.kind === 'own') {\n valueString = this.formatTableRowOnOwnRow(\n value as string,\n tableWidth - 4,\n tableWidth,\n );\n }\n\n const valueLines = valueString.split('\\n');\n const paddedValueLines = valueLines.map((line) => {\n const padding = padRight('', tableWidth - stringWidth(line) - 4, ' ');\n\n return `| ${line}${padding} |`;\n });\n\n tableString += paddedValueLines.join('\\n') + '\\n';\n tableString += headerSeparator + '\\n';\n } else {\n const keyLines = ASCIITableUtils.wrapText(key, columnWidths[0]);\n\n const valueLines = ASCIITableUtils.wrapText(\n this.formatValue(\n value,\n columnWidths[1],\n canAutoAdjustWidthWhenPossible,\n '',\n ),\n columnWidths[1],\n );\n\n const maxLines = Math.max(keyLines.length, valueLines.length);\n\n for (let i = 0; i < maxLines; i++) {\n const keyLine = keyLines[i] || '';\n const valueLine = valueLines[i] || '';\n\n const keyPadding = ' '.repeat(columnWidths[0] - stringWidth(keyLine));\n\n const valuePadding = ' '.repeat(\n columnWidths[1] - stringWidth(valueLine),\n );\n\n tableString += `| ${keyLine}${keyPadding} | ${valueLine}${valuePadding} |\\n`;\n\n if (i === maxLines - 1) {\n if (rowIndex === this.rows.length - 1) {\n tableString += headerSeparator + '\\n';\n } else {\n tableString += rowSeparator + '\\n';\n }\n }\n }\n }\n }\n\n return tableString.trim();\n }\n\n private calculateColumnWidths(\n options: KeyValueASCIITableOptions = {},\n ): number[] {\n const tableWidth = options.tableWidth || this.tableWidth;\n const canAutoAdjustWidthWhenPossible =\n options.autoAdjustWidthWhenPossible ?? this.autoAdjustWidthWhenPossible;\n\n const columnWidths: number[] = [0, 0];\n\n for (const row of this.rows) {\n const { key, value } = row;\n\n const keyWidth = stringWidth(key);\n const maxKeyWidth = Math.floor((tableWidth - 7) / 2);\n\n if (keyWidth > columnWidths[0]) {\n columnWidths[0] = Math.min(keyWidth, maxKeyWidth);\n columnWidths[1] = Math.max(0, tableWidth - columnWidths[0] - 7);\n }\n\n if (typeof value === 'string') {\n const valueWidth = Math.max(\n ...value.split('\\n').map((line) => stringWidth(line)),\n );\n\n if (valueWidth > columnWidths[1]) {\n columnWidths[1] = Math.min(\n valueWidth,\n tableWidth - columnWidths[0] - 7,\n );\n\n columnWidths[0] = Math.max(0, tableWidth - columnWidths[1] - 7);\n }\n } else if (row.kind === 'own') {\n let valueWidth = 0;\n\n if (isString(value)) {\n valueWidth = Math.max(\n ...value.split('\\n').map((line) => stringWidth(line)),\n );\n }\n\n if (valueWidth > columnWidths[1]) {\n columnWidths[1] = Math.min(\n valueWidth,\n tableWidth - columnWidths[0] - 7,\n );\n\n columnWidths[0] = Math.max(0, tableWidth - columnWidths[1] - 7);\n }\n } else if (value instanceof KeyValueASCIITable) {\n // Update column widths based on the nested table\n let nestedTableColumnWidths: number[] = [];\n\n if (canAutoAdjustWidthWhenPossible) {\n const minWidth = value.getMinimumWidth();\n\n const availableWidth = tableWidth - columnWidths[0] - 7;\n const adjustedWidth = clamp(availableWidth, minWidth, availableWidth);\n\n nestedTableColumnWidths = value.calculateColumnWidths({\n tableWidth: adjustedWidth,\n });\n } else {\n nestedTableColumnWidths = value.calculateColumnWidths();\n }\n\n const nestedTableWidth =\n nestedTableColumnWidths.reduce((sum, width) => sum + width, 0) +\n nestedTableColumnWidths.length * 3 -\n 1;\n\n const availableWidth = tableWidth - columnWidths[0] - 7;\n\n if (nestedTableWidth > availableWidth) {\n columnWidths[1] = availableWidth;\n } else {\n columnWidths[1] = Math.max(columnWidths[1], nestedTableWidth);\n }\n } else if (value instanceof MultiColumnASCIITable) {\n // Update column widths based on the nested multi-column table\n let nestedTableColumnWidths: number[] = [];\n\n if (canAutoAdjustWidthWhenPossible) {\n const minWidth = value.getMinimumWidth();\n\n const availableWidth = tableWidth - columnWidths[0] - 7;\n const adjustedWidth = clamp(availableWidth, minWidth, availableWidth);\n\n nestedTableColumnWidths = value.calculateColumnWidths({\n tableWidth: adjustedWidth,\n });\n } else {\n nestedTableColumnWidths = value.calculateColumnWidths();\n }\n\n const nestedTableWidth =\n nestedTableColumnWidths.reduce((sum, width) => sum + width, 0) +\n nestedTableColumnWidths.length * 3 -\n 1;\n\n const availableWidth = tableWidth - columnWidths[0] - 7;\n\n if (nestedTableWidth > availableWidth) {\n columnWidths[1] = availableWidth;\n } else {\n columnWidths[1] = Math.max(columnWidths[1], nestedTableWidth);\n }\n } else if (Array.isArray(value)) {\n for (const nestedCell of value) {\n const nestedKeyWidth = stringWidth(nestedCell.key);\n const maxNestedKeyWidth = Math.floor((tableWidth - 7) / 2);\n\n if (nestedKeyWidth > columnWidths[0]) {\n columnWidths[0] = Math.min(nestedKeyWidth, maxNestedKeyWidth);\n columnWidths[1] = Math.max(0, tableWidth - columnWidths[0] - 7);\n }\n\n if (typeof nestedCell.value === 'string') {\n const nestedValueWidth = Math.max(\n ...nestedCell.value.split('\\n').map((line) => stringWidth(line)),\n );\n\n if (nestedValueWidth > columnWidths[1]) {\n columnWidths[1] = Math.min(\n nestedValueWidth,\n tableWidth - columnWidths[0] - 7,\n );\n columnWidths[0] = Math.max(0, tableWidth - columnWidths[1] - 7);\n }\n }\n }\n }\n }\n\n return columnWidths;\n }\n\n private formatValue(\n value:\n | string\n | number\n | boolean\n | null\n | undefined\n | KeyValueASCIITable\n | MultiColumnASCIITable\n | NestedKeyValueEntry[],\n cellWidth: number,\n canAutoAdjustWidthWhenPossible: boolean,\n indent = '',\n ): string {\n if (typeof value === 'string') {\n return value;\n } else if (typeof value === 'number') {\n return String(value);\n } else if (typeof value === 'boolean') {\n return String(value);\n } else if (value === null) {\n return 'null';\n } else if (value === undefined) {\n return 'undefined';\n } else if (value instanceof KeyValueASCIITable) {\n let nestedTableLines: string[];\n\n if (canAutoAdjustWidthWhenPossible) {\n const minWidth = value.getMinimumWidth();\n\n const adjustedWidth = clamp(cellWidth, minWidth, cellWidth);\n\n nestedTableLines = value\n .toString({ tableWidth: adjustedWidth })\n .split('\\n');\n } else {\n nestedTableLines = value.toString().split('\\n');\n }\n\n const indentedLines = nestedTableLines.map((line) => `${indent}${line}`);\n\n return indentedLines.join('\\n');\n } else if (value instanceof MultiColumnASCIITable) {\n let nestedTableLines: string[];\n\n if (canAutoAdjustWidthWhenPossible) {\n const minWidth = value.getMinimumWidth();\n\n const adjustedWidth = clamp(cellWidth, minWidth, cellWidth);\n nestedTableLines = value\n .toString({ tableWidth: adjustedWidth })\n .split('\\n');\n } else {\n nestedTableLines = value.toString().split('\\n');\n }\n\n const indentedLines = nestedTableLines.map((line) => `${indent}${line}`);\n\n return indentedLines.join('\\n');\n } else if (Array.isArray(value)) {\n const nestedValueLines: string[] = [];\n\n for (const { key, value: nestedValue } of value) {\n const formattedKey = `${indent}${key}:`;\n const formattedValue = this.formatValue(\n nestedValue,\n cellWidth - indent.length - stringWidth(key) - 2,\n canAutoAdjustWidthWhenPossible,\n `${indent}`,\n );\n\n const wrappedSpacer = padRight('', 4, ' ');\n\n const wrappedValue = formattedValue\n .split('\\n')\n .map((line) => `${indent}${wrappedSpacer}${line}`);\n\n nestedValueLines.push(formattedKey);\n nestedValueLines.push(...wrappedValue);\n nestedValueLines.push('');\n }\n\n return nestedValueLines.slice(0, -1).join('\\n');\n } else {\n throw new TypeError('Invalid value type provided');\n }\n }\n\n private formatTableRowOnOwnRow(\n value: string,\n width: number,\n maxRowLength: number,\n ): string {\n const lines = value.split('\\n');\n\n const paddedLines = lines.map((line) => {\n const wrappedLines = ASCIITableUtils.wrapText(line, maxRowLength - 4);\n\n return wrappedLines\n .map((wrappedLine) => {\n const padding = padRight(\n '',\n width - stringWidth(wrappedLine) - 2,\n ' ',\n );\n\n return `${wrappedLine}${padding}`;\n })\n .join('\\n');\n });\n\n return paddedLines.join('\\n');\n }\n}\n","export function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(value, max));\n}\n\n/**\n * Clamps a value to a minimum, returning a default if the value is not finite or is undefined/null.\n *\n * Useful for config/settings validation where you want to:\n * - Enforce a minimum value\n * - Handle invalid inputs (Infinity, NaN, undefined, null) gracefully\n *\n * @param value - The value to clamp (can be undefined or null)\n * @param min - The minimum allowed value\n * @param defaultValue - The default to return if value is not finite or is undefined/null\n * @returns The clamped value, or defaultValue if value is not finite/undefined/null\n *\n * @example\n * ```typescript\n * finiteClampMin(5000, 1000, 3000) // 5000 (value > min)\n * finiteClampMin(500, 1000, 3000) // 1000 (enforces min)\n * finiteClampMin(Infinity, 1000, 3000) // 3000 (not finite, use default)\n * finiteClampMin(NaN, 1000, 3000) // 3000 (not finite, use default)\n * finiteClampMin(undefined, 1000, 3000) // 3000 (undefined, use default)\n * finiteClampMin(null, 1000, 3000) // 3000 (null, use default)\n * ```\n */\nexport function finiteClampMin(\n value: number | undefined | null,\n min: number,\n defaultValue: number,\n): number {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return defaultValue;\n }\n\n return Math.max(value, min);\n}\n","import type { NestedKeyValueEntry } from './ascii-tables/key-value-ascii-table';\nimport { KeyValueASCIITable } from './ascii-tables/key-value-ascii-table';\n\nfunction safeStringify(value: unknown): string {\n if (value === null || value === undefined) {\n return String(value);\n }\n\n switch (typeof value) {\n case 'string':\n return value;\n case 'number':\n case 'boolean':\n case 'bigint':\n return String(value);\n case 'object':\n return JSON.stringify(value);\n case 'function':\n return '[Function]';\n case 'symbol':\n return value.toString();\n default:\n // This should never happen, but satisfy the linter\n return String(value as string | number | boolean);\n }\n}\n\nexport function errorToString(error: unknown, maxRowLength = 80): string {\n const table = errorToASCIITable(error, maxRowLength);\n\n return table.toString();\n}\n\nfunction errorToASCIITable(\n error: unknown,\n maxRowLength: number,\n): KeyValueASCIITable {\n const table = new KeyValueASCIITable({\n tableWidth: maxRowLength,\n autoAdjustWidthWhenPossible: true,\n });\n\n if (error && typeof error === 'object') {\n const err = error as Record<string, unknown>;\n table.addRow('Key', 'Value');\n\n if (err['message']) {\n table.addRow('Message', safeStringify(err['message']));\n }\n\n if (err['name']) {\n table.addRow('Name', safeStringify(err['name']));\n }\n\n if (err['code']) {\n table.addRow('Code', safeStringify(err['code']));\n }\n\n if (err['errno']) {\n table.addRow('Errno', safeStringify(err['errno']));\n }\n\n // other conventional that might be used to enhance the error object\n if (err['errPrefix']) {\n table.addRow('Prefix', safeStringify(err['errPrefix']));\n }\n\n if (err['errType']) {\n table.addRow('errType', safeStringify(err['errType']));\n }\n\n if (err['errCode']) {\n table.addRow('errCode', safeStringify(err['errCode']));\n }\n\n if (err['additionalInfo']) {\n const additionalInfo = err['additionalInfo'] as Record<string, unknown>;\n const sensitiveFieldNames =\n (err['sensitiveFieldNames'] as string[]) || [];\n\n for (const key in additionalInfo) {\n if (sensitiveFieldNames.includes(key)) {\n table.addRow(`AdditionalInfo.${key}`, '***');\n } else {\n const value = additionalInfo[key];\n\n table.addRow(\n `AdditionalInfo.${key}`,\n stringifyValue(value, table, maxRowLength),\n );\n }\n }\n }\n\n if (err['stack']) {\n table.addValueOnSeparateRow('Stack', safeStringify(err['stack']));\n }\n }\n\n return table;\n}\n\nfunction stringifyValue(\n value: unknown,\n table: KeyValueASCIITable,\n maxRowLength: number,\n): string | KeyValueASCIITable | NestedKeyValueEntry[] {\n if (typeof value === 'string') {\n return value;\n } else if (Array.isArray(value)) {\n // Handle arrays differently\n return value\n .map((item) => {\n const result = stringifyValue(item, table, maxRowLength);\n // Convert complex types to strings for joining\n if (typeof result === 'string') {\n return result;\n } else if (result instanceof KeyValueASCIITable) {\n return result.toString();\n } else {\n return JSON.stringify(result);\n }\n })\n .join(', ');\n } else if (typeof value === 'object' && value !== null) {\n if (value instanceof Error) {\n return errorToASCIITable(value, maxRowLength - 4);\n } else {\n // Handle objects differently\n const entries: NestedKeyValueEntry[] = Object.entries(value).map(\n ([key, val]) => ({\n key,\n value: stringifyValue(val, table, maxRowLength - 4),\n }),\n );\n\n return entries;\n }\n } else {\n return String(value);\n }\n}\n","// Helper from https://github.com/then/is-promise/tree/master\n// For some reason the @types/is-promise package stopped being picked up on\n\nexport function isPromise(obj: unknown): obj is Promise<unknown> {\n return (\n !!obj &&\n (typeof obj === 'object' || typeof obj === 'function') &&\n // @ts-expect-error - obj is checked to be object/function, then property access works at runtime\n typeof obj['then'] === 'function'\n );\n}\n","export function isFunction(value: unknown): boolean {\n return typeof value === 'function' || value instanceof Function;\n}\n","import { errorToString } from './error-to-string';\nimport { isPromise } from './is-promise';\nimport { isFunction } from './is-function';\nimport { DOUBLE_EOL } from './constants';\n\n/**\n * Safely handles a callback function by catching any errors and reporting them\n * using the global `reportError` event (standard API available in Node.js 15+, Bun, Deno, and browsers).\n * This function can seamlessly handle both synchronous and asynchronous (Promise-based) callback functions.\n *\n * Errors are dispatched as ErrorEvent objects with type 'reportError' via `globalThis.dispatchEvent()`.\n * You can listen for these errors using `globalThis.addEventListener('reportError', handler)`.\n *\n * This function is a \"fire-and-forget\" type of function, meaning it doesn't wait\n * for the callback to complete and doesn't return any result or error. If you need\n * to handle the result or error of the callback, consider using the\n * `safeHandleCallbackAndWait` function instead.\n *\n * @param {string} callbackName - The name of the callback function, used for error reporting.\n * @param {unknown} callback - The callback function to be executed. It can be either a\n * synchronous function or a function that returns a Promise.\n * @param {...unknown[]} args - Additional arguments to pass to the callback function.\n */\n\nexport function safeHandleCallback(\n callbackName: string,\n callback: unknown,\n ...args: unknown[]\n): void {\n const handleError = (error: Error): void => {\n // Dispatch error using the standard reportError event API\n // Available in Node.js 15+, Bun, Deno, and browsers\n if (\n typeof (globalThis as Record<string, unknown>).dispatchEvent ===\n 'function'\n ) {\n (\n globalThis as unknown as {\n dispatchEvent: (event: Event) => void;\n }\n ).dispatchEvent(\n new ErrorEvent('reportError', {\n error: new Error(\n `Error in a callback ${callbackName}: ${DOUBLE_EOL}${errorToString(error)}`,\n ),\n }),\n );\n }\n };\n\n if (isFunction(callback)) {\n try {\n // We need to cast callback to the appropriate function type now\n const result = (callback as (...args: unknown[]) => unknown)(...args);\n\n if (isPromise(result)) {\n // Fire-and-forget async callback\n result.catch((error: unknown) => {\n handleError(error as Error);\n });\n }\n } catch (error) {\n handleError(error as Error);\n }\n } else {\n handleError(\n new Error(`Callback provided for ${callbackName} is not a function`),\n );\n }\n}\n\ninterface CallbackResult<T> {\n success: boolean;\n value?: T;\n error?: Error;\n}\n\n/**\n * Safely handles a callback function by catching any errors and reporting them\n * using the global `reportError` event (standard API available in Node.js 15+, Bun, Deno, and browsers).\n * This function can seamlessly handle both synchronous and asynchronous (Promise-based) callback\n * functions, and it waits for the callback to complete before returning the result or an error.\n *\n * Errors are dispatched as ErrorEvent objects with type 'reportError' via `globalThis.dispatchEvent()`.\n * You can listen for these errors using `globalThis.addEventListener('reportError', handler)`.\n *\n * @param {string} callbackName - The name of the callback function, used for error reporting.\n * @param {unknown} callback - The callback function to be executed. It can be either a\n * synchronous function or a function that returns a Promise.\n * @param {...unknown[]} args - Additional arguments to pass to the callback function.\n * @returns {Promise<CallbackResult<unknown>>} - A promise that resolves with an object containing\n * the success status, value (if any), and error (if any).\n */\n\nexport async function safeHandleCallbackAndWait<T>(\n callbackName: string,\n callback: unknown,\n ...args: unknown[]\n): Promise<CallbackResult<T>> {\n const handleError = (error: Error): CallbackResult<T> => {\n // Dispatch error using the standard reportError event API\n // Available in Node.js 15+, Bun, Deno, and browsers\n if (\n typeof (globalThis as Record<string, unknown>).dispatchEvent ===\n 'function'\n ) {\n (\n globalThis as unknown as {\n dispatchEvent: (event: Event) => void;\n }\n ).dispatchEvent(\n new ErrorEvent('reportError', {\n error: new Error(\n `Error in a callback ${callbackName}: ${DOUBLE_EOL}${errorToString(error)}`,\n ),\n }),\n );\n }\n\n return { success: false, error };\n };\n\n if (isFunction(callback)) {\n try {\n // We need to cast callback to the appropriate function type now\n const result = (callback as (...args: unknown[]) => unknown)(...args);\n\n if (isPromise(result)) {\n // Wait for the async callback to complete\n const value = await (result as Promise<T>);\n\n return { success: true, value };\n } else {\n return { success: true, value: result as T };\n }\n } catch (error) {\n return handleError(error as Error);\n }\n } else {\n return handleError(\n new Error(`Callback provided for ${callbackName} is not a function`),\n );\n }\n}\n","/**\n * Instead of using `EventEmitter`, you could extend `EventEmitterProtected`\n * if you want the emit method to be protected, and allow only your class to emit events.\n *\n * A simplified event emitter implementation that works in both browser and Node.js environments.\n * This provides basic event handling functionality with type safety and memory management.\n */\n\nimport { safeHandleCallback } from './safe-handle-callback';\n\ntype EventCallback<T = unknown> = (data: T) => void | Promise<void>;\n\nexport class EventEmitterProtected {\n private events: Map<string, Set<EventCallback<unknown>>>;\n\n constructor() {\n this.events = new Map();\n }\n\n /**\n * Subscribe to an event\n * @param event The event name to subscribe to\n * @param callback The callback function to be called when the event is emitted\n * @returns A function to unsubscribe from the event\n */\n public on<T = unknown>(\n event: string,\n callback: EventCallback<T>,\n ): () => void {\n if (!this.events.has(event)) {\n this.events.set(event, new Set());\n }\n const callbacks = this.events.get(event);\n\n if (callbacks) {\n callbacks.add(callback as EventCallback<unknown>);\n }\n\n // Return unsubscribe function for cleanup\n return () => {\n const callbacks = this.events.get(event);\n if (callbacks) {\n callbacks.delete(callback as EventCallback<unknown>);\n\n if (callbacks.size === 0) {\n this.events.delete(event);\n }\n }\n };\n }\n\n /**\n * Subscribe to an event once - automatically unsubscribes after first emission\n * @param event The event name to subscribe to\n * @param callback The callback function to be called when the event is emitted\n * @returns A function to unsubscribe from the event before it's called\n */\n public once<T = unknown>(\n event: string,\n callback: EventCallback<T>,\n ): () => void {\n const unsubscribe = this.on(event, (data: T) => {\n unsubscribe();\n return callback(data);\n });\n\n return unsubscribe;\n }\n\n /**\n * Check if a specific callback is registered for an event.\n * Note: For 'once' handlers, this will return true for the wrapper function, not the original callback.\n * This means hasListener will return false when checking for the original callback of a 'once' subscription.\n *\n * @param event The event name to check\n * @param callback The callback function to look for\n * @returns true if the exact callback is registered, false otherwise\n */\n public hasListener<T = unknown>(\n event: string,\n callback: EventCallback<T>,\n ): boolean {\n const callbacks = this.events.get(event);\n return callbacks?.has(callback as EventCallback<unknown>) ?? false;\n }\n\n /**\n * Check if an event has any subscribers\n * @param event The event name to check\n * @returns true if the event has subscribers, false otherwise\n */\n public hasListeners(event: string): boolean {\n const callbacks = this.events.get(event);\n return callbacks !== undefined && callbacks.size > 0;\n }\n\n /**\n * Get the number of subscribers for an event\n * @param event The event name to check\n * @returns The number of subscribers\n */\n public listenerCount(event: string): number {\n const callbacks = this.events.get(event);\n return callbacks ? callbacks.size : 0;\n }\n\n /**\n * Remove all event listeners\n * @param event Optional event name. If not provided, removes all listeners for all events\n */\n public clear(event?: string): void {\n if (event) {\n this.events.delete(event);\n } else {\n this.events.clear();\n }\n }\n\n /**\n * Emit an event with optional data\n * This method is protected to allow only derived classes to trigger events.\n * @param event The event name to emit\n * @param data Optional data to pass to the event handlers\n */\n protected emit<T = unknown>(event: string, data?: T): void {\n const callbacks = this.events.get(event);\n if (callbacks) {\n for (const callback of callbacks) {\n safeHandleCallback(`event handler for ${event}`, callback, data);\n }\n }\n }\n}\n\n/**\n * A class that implements the event emitter pattern with public emit method.\n * This class extends EventEmitterProtected and makes the emit method public.\n *\n * Use this when you want any code with access to the emitter to be able to trigger events.\n * If you want to control who can emit events, extend EventEmitterProtected instead.\n */\n\nexport class EventEmitter extends EventEmitterProtected {\n /**\n * Emit an event with optional data\n * This method is public, allowing any code with access to the emitter to trigger events.\n * @param event The event name to emit\n * @param data Optional data to pass to the event handlers\n */\n\n public emit<T = unknown>(event: string, data?: T): void {\n super.emit(event, data);\n }\n}\n","/**\n * Returns the current unix time in seconds\n *\n * ```typescript\n * const time = unix();\n * ```\n */\n\nexport function unix(): number {\n return Math.floor(Date.now() / 1000);\n}\n\n/**\n * Returns the current unix time in milliseconds\n *\n * ```typescript\n * const time = ms();\n * ```\n */\n\nexport function ms(): number {\n return Date.now();\n}\n\n/**\n * Returns a high resolution timestamp\n * Returns the time measured in milliseconds\n * This is aimed at performance monitoring\n *\n * ```typescript\n * const time = performance();\n * ```\n */\n\nexport function performance(): number {\n return globalThis.performance.now();\n}\n\n/**\n * Converts a Unix timestamp from milliseconds to seconds.\n * Useful for converting the millisecond-based timestamp from JavaScript's Date.now() into a Unix timestamp in seconds.\n *\n * @param {number} value - Unix timestamp in milliseconds.\n * @returns {number} - Unix timestamp converted to seconds.\n *\n * ```typescript\n * convertMSToUnix(1593189055006); // returns 1593189055\n * ```\n */\n\nexport function convertMSToUnix(value: number): number {\n return Math.floor(value / 1000);\n}\n\n/**\n * Converts a Unix timestamp from seconds to milliseconds.\n *\n * This function takes a Unix timestamp in seconds and converts it to milliseconds.\n * This is useful when dealing with JavaScript's Date object or other systems that\n * require time in milliseconds.\n *\n * @param {number} value - The Unix timestamp in seconds.\n * @returns {number} The Unix timestamp in milliseconds.\n *\n * Example:\n * ```typescript\n * convertUnix(1593189055); // returns 1593189055000\n * ```\n */\n\nexport function convertUnixToMS(value: number): number {\n return value * 1000;\n}\n","export type TemplateFunction = (locals: Record<string, unknown>) => string;\n\ninterface CurlyBracketsFunction {\n (str?: string, locals?: Record<string, unknown>, fallback?: string): string;\n compileTemplate: (str: string, fallback?: string) => TemplateFunction;\n escape: (str: string) => string;\n}\n\n/**\n * Processes a template string, replacing placeholders with corresponding values from a provided object.\n *\n * @param {string} str - The template string to process.\n * @param locals - An object containing key-value pairs for placeholder replacement.\n * @param fallback - A default string to use when a placeholder's corresponding value is not found.\n * @returns - The processed string with placeholders replaced by their corresponding values.\n */\n\nconst CurlyBrackets: CurlyBracketsFunction = function (\n str: string = '',\n locals: Record<string, unknown> = {},\n fallback: string = '(null)',\n): string {\n // Short-circuit if no brackets - no need to process\n if (!str.includes('{{')) {\n return str;\n }\n\n const compiled = CurlyBrackets.compileTemplate(str, fallback);\n\n return compiled(locals);\n} as CurlyBracketsFunction;\n\n/**\n * Compiles a template string into a reusable function, which can be called with different sets of locals.\n * This is more efficient when you have a template that you want to use with different sets of locals,\n * as it avoids the overhead of parsing the template string each time it is used.\n *\n * @param {string} str - The template string to compile.\n * @param {string} fallback - A default string to use when a placeholder's corresponding value is not found in locals.\n * @returns A function that takes an object of locals and returns a processed string.\n */\n\nCurlyBrackets.compileTemplate = function (\n str: string,\n fallback: string = '(null)',\n): TemplateFunction {\n const pattern = /(?:\\\\)?{{(\\s*[\\w.]+?)(?:\\\\)?\\s*}}/g;\n\n return (locals: Record<string, unknown>): string => {\n return str.replace(pattern, (match, p1: string) => {\n if (typeof p1 !== 'string') {\n return match;\n }\n\n const hasLeadingEscape = match.startsWith('\\\\');\n const hasEndingEscape = match.endsWith('\\\\}}');\n const isFullyEscaped = hasLeadingEscape && hasEndingEscape;\n\n if (isFullyEscaped) {\n return match.slice(1, -3) + '}}';\n }\n\n if (hasLeadingEscape) {\n return match.slice(1);\n }\n\n if (hasEndingEscape) {\n return '{{' + p1.trim() + '}}';\n }\n\n const key = p1.trim();\n const parts = key.split('.');\n\n // Use a more specific approach to ensure the type is consistent\n let replacement: unknown = locals;\n\n for (const part of parts) {\n if (\n replacement !== undefined &&\n replacement !== null &&\n typeof replacement === 'object' &&\n part in replacement\n ) {\n replacement = (replacement as Record<string, unknown>)[part];\n } else {\n replacement = undefined;\n break;\n }\n }\n\n if (replacement === undefined || replacement === null) {\n return fallback;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return String(replacement);\n });\n };\n};\n\n/**\n * Escapes placeholders in a string by prefixing them with a backslash, preventing them from being replaced when processed.\n *\n * @param {string} str - The string in which to escape placeholders.\n * @returns {string} - The string with placeholders escaped.\n */\n\nCurlyBrackets.escape = function (str: string): string {\n // Use a regex to replace instances of {{ and }} that are not already preceded by a backslash\n return str\n .replace(/(\\\\)?{{/g, (match, backslash) => (backslash ? match : '\\\\{{'))\n .replace(/(\\\\)?}}/g, (match, backslash) => (backslash ? match : '\\\\}}'));\n};\n\nexport { CurlyBrackets };\n","/**\n * Type guard to check if a value is a valid number.\n *\n * @param value - Value to check\n * @returns `true` if the value is a number and not NaN, `false` otherwise\n *\n * @example\n * ```typescript\n * isNumber(42); // true\n * isNumber(3.14); // true\n * isNumber(NaN); // false\n * isNumber('123'); // false\n * isNumber(null); // false\n * isNumber(undefined); // false\n * ```\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && !isNaN(value);\n}\n\n/**\n * Type guard to check if a value is a finite number.\n *\n * @param value - Value to check\n * @returns `true` if the value is a number and is finite (excludes NaN, Infinity, -Infinity), `false` otherwise\n *\n * @example\n * ```typescript\n * isFiniteNumber(42); // true\n * isFiniteNumber(3.14); // true\n * isFiniteNumber(Infinity); // false\n * isFiniteNumber(-Infinity); // false\n * isFiniteNumber(NaN); // false\n * isFiniteNumber('123'); // false\n * isFiniteNumber(null); // false\n * isFiniteNumber(undefined); // false\n * ```\n */\nexport function isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && isFinite(value);\n}\n","import type { ArrayLogTransformer, LogEntry, LogSink } from '../types';\n\n/**\n * ArraySink stores logs in memory for testing and debugging\n */\nexport class ArraySink implements LogSink {\n public logs: LogEntry[] = [];\n private transformer?: ArrayLogTransformer;\n private closed = false;\n\n constructor(options?: { transformer?: ArrayLogTransformer }) {\n this.transformer = options?.transformer;\n }\n\n public write(entry: LogEntry): void {\n if (this.closed) {\n return;\n }\n\n if (this.transformer) {\n try {\n const transformed = this.transformer(entry);\n\n if (transformed !== false) {\n // Store the transformed entry\n this.logs.push(transformed);\n return;\n }\n } catch {\n // If transformer fails, fall through to store original entry\n }\n }\n // Store the original entry\n this.logs.push(entry);\n }\n\n /**\n * Clear all stored logs\n */\n public clear(): void {\n this.logs = [];\n }\n\n /**\n * Get logs in a snapshot-friendly format for testing\n */\n public getSnapshotFriendlyLogs(): string[] {\n return this.logs.map((log) => `${log.type}: ${log.message}`);\n }\n\n /**\n * Close the sink and stop accepting new logs\n */\n public close(): void {\n this.closed = true;\n }\n}\n","import { format } from 'date-fns';\nimport type { LogEntry, LogSink } from '../types';\nimport { LogLevel, getLogLevel } from '../types';\nimport { colorize } from '../utils/color';\n\nexport interface ConsoleSinkOptions {\n colors?: boolean;\n timestamps?: boolean;\n typeLabels?: boolean;\n muted?: boolean;\n minLevel?: LogLevel;\n}\n\n/**\n * ConsoleSink writes logs to the console with optional colors, timestamps, and type labels\n */\nexport class ConsoleSink implements LogSink {\n private colors: boolean;\n private timestamps: boolean;\n private typeLabels: boolean;\n private closed = false;\n private muted: boolean;\n private minLevel: LogLevel;\n\n constructor(options: ConsoleSinkOptions = {}) {\n this.colors = options.colors ?? true;\n this.timestamps = options.timestamps ?? false;\n this.typeLabels = options.typeLabels ?? false;\n this.muted = options.muted ?? false;\n this.minLevel = options.minLevel ?? LogLevel.INFO;\n }\n\n public write(entry: LogEntry): void {\n if (this.closed || this.muted) {\n return;\n }\n\n // Raw type - no formatting and always shown\n if (entry.type === 'raw') {\n // eslint-disable-next-line no-console\n console.log(entry.message);\n return;\n }\n\n // Check if log level is below minimum threshold (after raw check)\n const logLevel = getLogLevel(entry.type);\n if (logLevel > this.minLevel) {\n return;\n }\n\n let formattedMessage = '';\n\n // Add timestamp if enabled\n if (this.timestamps) {\n const formattedTimestamp = format(entry.timestamp, 'MM-dd-yyyy HH:mm:ss');\n formattedMessage = '[' + formattedTimestamp + '] ';\n }\n\n // Add type label if enabled\n if (this.typeLabels) {\n formattedMessage += `[${entry.type.toUpperCase()}] `;\n }\n\n // Add service name if present\n if (entry.serviceName) {\n formattedMessage += `[${entry.serviceName}] `;\n }\n\n // Add entity name if present\n if (entry.entityName) {\n formattedMessage += `[${entry.entityName}] `;\n }\n\n // Add the message\n formattedMessage += entry.message;\n\n // Apply colors if enabled\n if (this.colors) {\n const { coloredText, style } = colorize(entry.type, formattedMessage);\n\n switch (entry.type) {\n case 'error':\n if (style) {\n // eslint-disable-next-line no-console\n console.error(coloredText, style);\n } else {\n // eslint-disable-next-line no-console\n console.error(coloredText);\n }\n break;\n case 'info':\n if (style) {\n // eslint-disable-next-line no-console\n console.info(coloredText, style);\n } else {\n // eslint-disable-next-line no-console\n console.info(coloredText);\n }\n break;\n case 'warn':\n if (style) {\n // eslint-disable-next-line no-console\n console.warn(coloredText, style);\n } else {\n // eslint-disable-next-line no-console\n console.warn(coloredText);\n }\n break;\n case 'success':\n case 'notice':\n case 'debug':\n if (style) {\n // eslint-disable-next-line no-console\n console.log(coloredText, style);\n } else {\n // eslint-disable-next-line no-console\n console.log(coloredText);\n }\n break;\n }\n } else {\n // No colors\n switch (entry.type) {\n case 'error':\n // eslint-disable-next-line no-console\n console.error(formattedMessage);\n break;\n case 'info':\n // eslint-disable-next-line no-console\n console.info(formattedMessage);\n break;\n case 'warn':\n // eslint-disable-next-line no-console\n console.warn(formattedMessage);\n break;\n case 'success':\n case 'notice':\n case 'debug':\n // eslint-disable-next-line no-console\n console.log(formattedMessage);\n break;\n }\n }\n }\n\n /**\n * Set the minimum log level for this sink\n */\n public setMinLevel(level: LogLevel): void {\n this.minLevel = level;\n }\n\n /**\n * Get the current minimum log level\n */\n public getMinLevel(): LogLevel {\n return this.minLevel;\n }\n\n /**\n * Mute the sink to stop writing logs to console\n */\n public mute(): void {\n this.muted = true;\n }\n\n /**\n * Unmute the sink to resume writing logs to console\n */\n public unmute(): void {\n this.muted = false;\n }\n\n /**\n * Check if the sink is currently muted\n */\n public isMuted(): boolean {\n return this.muted;\n }\n\n /**\n * Close the sink and stop accepting new logs\n */\n public close(): void {\n this.closed = true;\n }\n}\n","/**\n * Log level enum for filtering logs by severity\n * Lower numbers = more important/higher priority\n * Higher numbers = less important/lower priority\n */\nexport enum LogLevel {\n ERROR = 0,\n WARN = 1,\n NOTICE = 2, // Normal but significant condition\n SUCCESS = 3,\n // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values\n INFO = 3, // Same level as SUCCESS (routine operational info)\n DEBUG = 4,\n RAW = 99,\n}\n\n/**\n * Log level types\n */\nexport type LogType =\n | 'error'\n | 'info'\n | 'warn'\n | 'success'\n | 'notice'\n | 'debug'\n | 'raw';\n\n/**\n * Maps a LogType to its corresponding LogLevel\n */\nexport function getLogLevel(type: LogType): LogLevel {\n switch (type) {\n case 'error':\n return LogLevel.ERROR;\n case 'warn':\n return LogLevel.WARN;\n case 'notice':\n return LogLevel.NOTICE;\n case 'success':\n return LogLevel.SUCCESS;\n case 'info':\n return LogLevel.INFO;\n case 'debug':\n return LogLevel.DEBUG;\n case 'raw':\n return LogLevel.RAW;\n }\n}\n\n/**\n * Options for log methods\n */\nexport interface LogOptions {\n exitCode?: number;\n params?: Record<string, unknown>;\n tags?: string[];\n redactedKeys?: string[];\n}\n\n/**\n * Complete log entry that gets passed to sinks\n */\nexport interface LogEntry {\n timestamp: number;\n type: LogType;\n serviceName?: string; // Service name (if using service logger)\n entityName?: string; // Optional entity identifier (e.g., 'audio-component-123', 'door-main', UUID)\n template: string; // Original template: \"User {{userID}} logged in\"\n message: string; // Computed: \"User 456 logged in\"\n params?: Record<string, unknown>; // Raw params: { userID: 456, password: 'secret' }\n redactedParams?: Record<string, unknown>; // Redacted params: { userID: 456, password: '***' }\n redactedKeys?: string[]; // List of keys that were redacted (e.g., ['password', 'user.apiKey'])\n error?: unknown; // Original error object from errorObject() calls\n exitCode?: number; // Exit code if this log triggers a process exit\n tags?: string[]; // Optional tags for categorizing/filtering logs (e.g., ['auth', 'security'])\n}\n\n/**\n * Sink interface - all sinks must implement this\n */\nexport interface LogSink {\n write(entry: LogEntry): void | Promise<void>;\n close?(): void | Promise<void>;\n}\n\n/**\n * Result from beforeExit callback indicating whether to proceed with exit\n */\nexport interface BeforeExitResult {\n /**\n * Whether to proceed with the exit\n * - 'proceed': Continue with process exit\n * - 'wait': Shutdown is already in progress, wait for it to complete\n */\n action: 'proceed' | 'wait';\n}\n\n/**\n * Redaction function type\n */\nexport type RedactFunction = (keyName: string, value: unknown) => unknown;\n\n/**\n * Array log transformer function type.\n * Receives a log entry and returns either a transformed entry or false to keep the original.\n */\nexport type ArrayLogTransformer = (entry: LogEntry) => LogEntry | false;\n\n/**\n * Main logger configuration options\n */\nexport interface LoggerOptions {\n // Output destinations\n sinks?: LogSink[];\n\n // Security\n redactFunction?: RedactFunction;\n\n // Behavior\n callProcessExit?: boolean;\n beforeExitCallback?: (\n exitCode: number,\n isFirstExit: boolean,\n ) => BeforeExitResult | Promise<BeforeExitResult>;\n onSinkError?: (\n error: Error,\n context: 'write' | 'close',\n sink: LogSink,\n ) => void;\n}\n\n/**\n * Logger event types\n */\nexport interface LoggerEventMap {\n log: {\n eventType: 'log';\n logType: LogType;\n message: string;\n timestamp: number;\n };\n 'exit-called': {\n eventType: 'exit-called';\n code: number;\n isFirstExit: boolean;\n };\n 'exit-process': {\n eventType: 'exit-process';\n code: number;\n };\n uncaughtException: {\n eventType: 'uncaughtException';\n error: Error;\n };\n close: {\n eventType: 'close';\n };\n}\n\nexport type LoggerEvent = LoggerEventMap[keyof LoggerEventMap];\n","import chalk from 'chalk';\nimport type { LogType } from '../types';\n\ninterface ColorResult {\n coloredText: string;\n style?: string;\n}\n\nconst browserColors: Record<Exclude<LogType, 'raw'>, string> = {\n error: 'color: #a95450;', // red\n info: 'color: #ffffff;', // white\n warn: 'color: #f5f566;', // yellow\n success: 'color: #56b97f;', // green\n notice: 'color: #5883bf;', // blue\n debug: 'color: #808080;', // gray\n};\n\nconst chalkColors: Record<Exclude<LogType, 'raw'>, keyof typeof chalk> = {\n error: 'red',\n info: 'white',\n warn: 'yellow',\n success: 'green',\n notice: 'blue',\n debug: 'gray',\n};\n\n/**\n * Colorize text for console output\n * Automatically detects browser vs Node.js environment\n */\nexport function colorize(\n type: Exclude<LogType, 'raw'>,\n text: string,\n): ColorResult {\n const isBrowser =\n typeof globalThis !== 'undefined' &&\n 'window' in globalThis &&\n 'document' in globalThis;\n\n if (isBrowser) {\n return {\n coloredText: `%c${text}`,\n style: browserColors[type],\n };\n } else {\n // Node.js - use chalk\n const colorName = chalkColors[type];\n const chalkColor = chalk[colorName] as (text: string) => string;\n return {\n coloredText: chalkColor(text),\n };\n }\n}\n","import datamask from 'datamask';\nimport { deepClone } from '../../deep-clone';\nimport type { RedactFunction } from '../types';\n\n/**\n * Default redaction function using datamask\n * Masks sensitive values with asterisks\n */\nexport const defaultRedactFunction: RedactFunction = (\n _keyName: string,\n value: unknown,\n): unknown => {\n if (typeof value === 'string') {\n return datamask.string(value, '*', 60);\n }\n // For non-strings, mask as generic redacted value\n return '***REDACTED***';\n};\n\n/**\n * Set a value at a nested path in an object\n */\nfunction setNestedValue(\n obj: Record<string, unknown>,\n path: string,\n value: unknown,\n): void {\n const parts = path.split('.');\n let current: Record<string, unknown> = obj;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n const next = current[part];\n\n if (next === undefined || next === null || typeof next !== 'object') {\n return; // Path doesn't exist, can't set value\n }\n\n current = next as Record<string, unknown>;\n }\n\n const lastPart = parts[parts.length - 1];\n if (lastPart !== undefined && lastPart in current) {\n current[lastPart] = value;\n }\n}\n\n/**\n * Get a value at a nested path in an object\n */\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (\n current === undefined ||\n current === null ||\n typeof current !== 'object' ||\n !(part in current)\n ) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/**\n * Apply redaction to params based on redacted keys\n * Supports both top-level keys and nested paths using dot notation (e.g., 'user.password')\n *\n * @param params Original params object\n * @param redactedKeys Keys to redact (supports dot notation for nested keys)\n * @param redactFunction Custom redaction function (uses defaultRedactFunction if not provided)\n * @returns New object with redacted values\n */\nexport function applyRedaction(\n params: Record<string, unknown>,\n redactedKeys?: string[],\n redactFunction?: RedactFunction,\n): Record<string, unknown> {\n // No redaction needed\n if (!redactedKeys || redactedKeys.length === 0) {\n return params;\n }\n\n const redactFn = redactFunction || defaultRedactFunction;\n\n // Deep clone to avoid mutating original\n const redactedParams = deepClone(params);\n\n // Apply redaction to specified keys (supports dot notation)\n for (const key of redactedKeys) {\n // Check if it's a nested key (contains dots)\n if (key.includes('.')) {\n const value = getNestedValue(redactedParams, key);\n\n if (value !== undefined) {\n const redactedValue = redactFn(key, value);\n setNestedValue(redactedParams, key, redactedValue);\n }\n } else {\n // Top-level key\n if (key in redactedParams) {\n redactedParams[key] = redactFn(key, redactedParams[key]);\n }\n }\n }\n\n return redactedParams;\n}\n","/**\n * Deep clone utility\n *\n * Creates a deep copy of a value, recursively cloning nested structures.\n * Handles most common data types including objects, arrays, dates, regexes,\n * Maps, Sets, and typed arrays.\n *\n * Note: Functions are returned by reference (not cloned). Circular references\n * are detected and handled to prevent infinite recursion.\n */\n\n/**\n * Deep clone an object or value\n *\n * @param obj - The value to clone\n * @returns A deep clone of the input value\n */\nexport function deepClone<T>(obj: T): T {\n return cloneInternal(obj, new WeakMap());\n}\n\nfunction cloneInternal<T>(obj: T, seen: WeakMap<object, unknown>): T {\n // Primitives and null/undefined return as-is\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Check for circular references\n if (seen.has(obj as object)) {\n return seen.get(obj as object) as T;\n }\n\n // Handle Date\n if (obj instanceof Date) {\n return new Date(obj) as T;\n }\n\n // Handle RegExp\n if (obj instanceof RegExp) {\n const flags = obj.flags;\n const cloned = new RegExp(obj.source, flags);\n cloned.lastIndex = obj.lastIndex;\n return cloned as T;\n }\n\n // Handle Map\n if (obj instanceof Map) {\n const cloned = new Map();\n seen.set(obj as object, cloned);\n\n for (const [key, value] of obj) {\n cloned.set(cloneInternal(key, seen), cloneInternal(value, seen));\n }\n\n return cloned as T;\n }\n\n // Handle Set\n if (obj instanceof Set) {\n const cloned = new Set();\n seen.set(obj as object, cloned);\n\n for (const value of obj) {\n cloned.add(cloneInternal(value, seen));\n }\n\n return cloned as T;\n }\n\n // Handle typed arrays\n if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {\n const typedArray = obj as unknown as\n | Int8Array\n | Uint8Array\n | Uint8ClampedArray\n | Int16Array\n | Uint16Array\n | Int32Array\n | Uint32Array\n | Float32Array\n | Float64Array\n | BigInt64Array\n | BigUint64Array;\n const cloned = typedArray.slice();\n return cloned as T;\n }\n\n // Handle Array\n if (Array.isArray(obj)) {\n const cloned: unknown[] = [];\n seen.set(obj as object, cloned);\n\n for (const item of obj) {\n cloned.push(cloneInternal(item, seen));\n }\n\n return cloned as T;\n }\n\n // Handle plain objects\n const cloned: Record<string, unknown> = {};\n seen.set(obj as object, cloned);\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n cloned[key] = cloneInternal((obj as Record<string, unknown>)[key], seen);\n }\n }\n\n return cloned as T;\n}\n","import { errorToString } from '../../error-to-string';\nimport { DOUBLE_EOL } from '../../constants';\n\n/**\n * Prepare an error object for logging with an optional prefix\n */\nexport function prepareErrorObjectLog(prefix: string, error: unknown): string {\n prefix = prefix.trim();\n\n let prefixLine = '';\n\n if (prefix.length > 0) {\n prefixLine = prefix + ': ' + DOUBLE_EOL;\n }\n\n return prefixLine + errorToString(error);\n}\n","import type { LogType, LogOptions } from './types';\nimport type { HandleLogOptions } from './internal-types';\nimport { prepareErrorObjectLog } from './utils/error-object';\n\n/**\n * LoggerService for scoped logging with service names\n */\nexport class LoggerService {\n private handleLog: (\n type: LogType,\n template: string,\n options?: HandleLogOptions,\n ) => void;\n private serviceName: string;\n private entityName?: string;\n\n constructor(\n handleLog: (\n type: LogType,\n template: string,\n options?: HandleLogOptions,\n ) => void,\n serviceName: string,\n entityName?: string,\n ) {\n this.handleLog = handleLog;\n this.serviceName = serviceName;\n this.entityName = entityName;\n }\n\n /**\n * Create a scoped logger for a specific entity within this service\n */\n public entity(entityName: string): LoggerService {\n return new LoggerService(this.handleLog, this.serviceName, entityName);\n }\n\n /**\n * Log an error message\n */\n public error(message: string, options?: LogOptions): void {\n this.handleLog('error', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n\n /**\n * Log an error object with optional prefix\n */\n public errorObject(\n prefix: string,\n error: unknown,\n options?: LogOptions,\n ): void {\n const message = prepareErrorObjectLog(prefix, error);\n\n this.handleLog('error', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n error,\n });\n }\n\n /**\n * Log an informational message\n */\n public info(message: string, options?: LogOptions): void {\n this.handleLog('info', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n\n /**\n * Log a warning message\n */\n public warn(message: string, options?: LogOptions): void {\n this.handleLog('warn', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n\n /**\n * Log a success message\n */\n public success(message: string, options?: LogOptions): void {\n this.handleLog('success', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n\n /**\n * Log a notice message\n */\n public notice(message: string, options?: LogOptions): void {\n this.handleLog('notice', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n\n /**\n * Log a debug message\n */\n public debug(message: string, options?: LogOptions): void {\n this.handleLog('debug', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n\n /**\n * Log a raw message without any formatting\n */\n public raw(message: string, options?: LogOptions): void {\n this.handleLog('raw', message, {\n ...(options ?? {}),\n serviceName: this.serviceName,\n entityName: this.entityName,\n });\n }\n}\n","import fs, { promises as fsPromises } from 'fs';\nimport type { LogEntry, LogSink } from '../types';\nimport { LogLevel, getLogLevel } from '../types';\n\nexport interface FileSinkOptions {\n logDir: string;\n basename: string;\n maxSizeMB?: number;\n jsonFormat?: boolean;\n maxRetries?: number;\n closeTimeoutMS?: number;\n minLevel?: LogLevel;\n onError?: (\n error: Error,\n entry: LogEntry,\n attempt: number,\n willRetry: boolean,\n ) => void;\n}\n\nexport interface FileSinkHealth {\n isHealthy: boolean;\n queueSize: number;\n lastError?: Error;\n consecutiveFailures: number;\n isInitialized: boolean;\n}\n\nexport interface FlushResult {\n success: boolean;\n entriesWritten: number;\n entriesFailed: number;\n timedOut: boolean;\n}\n\n/**\n * Error handler class for FileSink\n */\nclass FileSinkError extends Error {\n constructor(\n message: string,\n public cause?: Error,\n ) {\n super(message);\n this.name = 'FileSinkError';\n }\n}\n\ninterface QueuedEntry {\n entry: LogEntry;\n attempts: number;\n}\n\n/**\n * FileSink writes logs to files with automatic rotation based on size and date\n */\nexport class FileSink implements LogSink {\n private logDir: string;\n private basename: string;\n private maxSizeMB: number;\n private jsonFormat: boolean;\n private maxRetries: number;\n private minLevel: LogLevel;\n private onError?: (\n error: Error,\n entry: LogEntry,\n attempt: number,\n willRetry: boolean,\n ) => void;\n private logFileStream?: fs.WriteStream;\n private currentLogFile?: string;\n private currentLogSize = 0;\n private writeQueue: QueuedEntry[] = [];\n private isInitialized = false;\n private initPromise?: Promise<void>;\n private isProcessing = false;\n private lastError?: Error;\n private consecutiveFailures = 0;\n private totalEntriesWritten = 0;\n private totalEntriesFailed = 0;\n private closing = false;\n private closed = false;\n private closeTimeoutMS: number;\n\n constructor(options: FileSinkOptions) {\n this.logDir = options.logDir;\n this.basename = options.basename;\n this.maxSizeMB = options.maxSizeMB ?? 10;\n this.jsonFormat = options.jsonFormat ?? false;\n this.maxRetries = options.maxRetries ?? 3;\n this.closeTimeoutMS = options.closeTimeoutMS ?? 30000;\n this.minLevel = options.minLevel ?? LogLevel.INFO;\n this.onError = options.onError;\n\n // Initialize asynchronously\n this.initPromise = this.initialize();\n }\n\n public write(entry: LogEntry): void {\n if (this.closing || this.closed) {\n return;\n }\n\n // Check if log level is below minimum threshold (skip for raw logs)\n if (entry.type !== 'raw') {\n const logLevel = getLogLevel(entry.type);\n if (logLevel > this.minLevel) {\n return;\n }\n }\n\n // Add to queue with retry tracking\n this.writeQueue.push({ entry, attempts: 0 });\n\n // Process queue if initialized\n if (this.isInitialized) {\n void this.processQueue();\n } else if (this.initPromise) {\n void this.initPromise.then(() => this.processQueue());\n }\n }\n\n /**\n * Set the minimum log level for this sink\n */\n public setMinLevel(level: LogLevel): void {\n this.minLevel = level;\n }\n\n /**\n * Get the current minimum log level\n */\n public getMinLevel(): LogLevel {\n return this.minLevel;\n }\n\n /**\n * Get current health status of the sink\n */\n public getHealth(): FileSinkHealth {\n return {\n isHealthy: this.consecutiveFailures === 0 && this.isInitialized,\n queueSize: this.writeQueue.length,\n lastError: this.lastError,\n consecutiveFailures: this.consecutiveFailures,\n isInitialized: this.isInitialized,\n };\n }\n\n /**\n * Flush all pending writes and wait for completion\n * Returns statistics about the flush operation\n * @param timeoutMS Maximum time to wait in milliseconds (default: 30000ms / 30s)\n */\n public async flush(timeoutMS: number = 30000): Promise<FlushResult> {\n // Wait for initialization\n if (this.initPromise) {\n await this.initPromise;\n }\n\n const startWritten = this.totalEntriesWritten;\n const startFailed = this.totalEntriesFailed;\n const startTime = Date.now();\n\n // Wait for queue to finish processing with timeout\n while (this.writeQueue.length > 0 || this.isProcessing) {\n if (Date.now() - startTime > timeoutMS) {\n // Timeout reached\n const entriesWritten = this.totalEntriesWritten - startWritten;\n const entriesFailed = this.totalEntriesFailed - startFailed;\n\n return {\n success: false,\n entriesWritten,\n entriesFailed,\n timedOut: true,\n };\n }\n\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n\n const entriesWritten = this.totalEntriesWritten - startWritten;\n const entriesFailed = this.totalEntriesFailed - startFailed;\n\n return {\n success: entriesFailed === 0,\n entriesWritten,\n entriesFailed,\n timedOut: false,\n };\n }\n\n /**\n * Close the log file and wait for all pending writes\n */\n public async close(): Promise<void> {\n this.closing = true;\n\n const startTime = Date.now();\n\n // Wait for initialization with timeout\n if (this.initPromise) {\n let timeoutHandle: NodeJS.Timeout | undefined;\n const timeoutSentinel = { timedOut: true } as const;\n\n try {\n const timeoutPromise = new Promise<typeof timeoutSentinel>(\n (resolve) => {\n timeoutHandle = setTimeout(\n () => resolve(timeoutSentinel),\n this.closeTimeoutMS,\n );\n },\n );\n\n const result = await Promise.race([\n this.initPromise.then(() => undefined),\n timeoutPromise,\n ]);\n\n // Check if timeout fired\n if (result === timeoutSentinel) {\n // Timeout fired - prevent unhandled rejection if initPromise fails later\n Promise.resolve(this.initPromise).catch(() => {\n // Intentionally ignore errors after timeout\n });\n }\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n }\n\n // Wait for queue to finish processing with timeout\n while (this.writeQueue.length > 0 || this.isProcessing) {\n if (Date.now() - startTime > this.closeTimeoutMS) {\n break;\n }\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n\n this.closed = true;\n\n // Close stream\n if (this.logFileStream) {\n return new Promise<void>((resolve) => {\n if (!this.logFileStream) {\n return resolve();\n }\n\n this.logFileStream.end(() => {\n this.logFileStream = undefined;\n resolve();\n });\n });\n }\n }\n\n /**\n * Initialize the file sink asynchronously\n */\n private async initialize(): Promise<void> {\n try {\n // Create log directory if it doesn't exist\n await fsPromises.mkdir(this.logDir, { recursive: true });\n\n // Initialize log file\n await this.setupLogFile();\n this.isInitialized = true;\n\n // Process any queued writes\n await this.processQueue();\n } catch {\n // Silently fail - entries will be queued until next initialization attempt\n }\n }\n\n /**\n * Process the write queue\n * Processes entries one at a time with retry logic\n */\n private async processQueue(): Promise<void> {\n // If already processing, closed, or queue is empty, return\n if (this.isProcessing || this.closed || this.writeQueue.length === 0) {\n return;\n }\n\n this.isProcessing = true;\n\n try {\n while (this.writeQueue.length > 0) {\n const queuedEntry = this.writeQueue.shift();\n if (!queuedEntry) {\n break;\n }\n\n try {\n await this.writeEntry(queuedEntry.entry);\n this.consecutiveFailures = 0;\n this.totalEntriesWritten++;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.lastError = err;\n this.consecutiveFailures++;\n\n // Determine if we should retry\n const willRetry = queuedEntry.attempts < this.maxRetries;\n\n // Call error callback if provided\n if (this.onError) {\n try {\n this.onError(\n err,\n queuedEntry.entry,\n queuedEntry.attempts + 1,\n willRetry,\n );\n } catch {\n // Ignore errors in error callback\n }\n }\n\n if (willRetry) {\n // Re-queue with incremented attempt count\n queuedEntry.attempts++;\n this.writeQueue.push(queuedEntry);\n } else {\n // Max retries exceeded - entry is lost\n this.totalEntriesFailed++;\n }\n }\n }\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Write a single entry to the file\n * If stream is broken, it will be recreated on next attempt\n */\n private async writeEntry(entry: LogEntry): Promise<void> {\n if (this.closed) {\n throw new FileSinkError('Cannot write to closed sink');\n }\n\n if (!this.logFileStream) {\n await this.setupLogFile();\n }\n\n if (!this.logFileStream) {\n throw new FileSinkError('No log file stream available');\n }\n\n // Check rotation before writing (handles date change and size limit)\n await this.rotateIfNeeded();\n\n // Format the entry\n const messageToWrite = this.formatEntry(entry);\n const messageBytes = Buffer.byteLength(messageToWrite, 'utf8');\n\n // Check if writing would exceed limit\n const maxSizeBytes = this.maxSizeMB * 1024 * 1024;\n if (this.currentLogSize + messageBytes > maxSizeBytes) {\n await this.rotateFile();\n }\n\n // Write to file\n return new Promise<void>((resolve, reject) => {\n if (!this.logFileStream) {\n return resolve();\n }\n\n this.logFileStream.write(messageToWrite, (err) => {\n if (err) {\n // Stream is broken - destroy it so it can be recreated\n this.destroyStream();\n reject(new FileSinkError('Error writing to log file', err));\n } else {\n this.currentLogSize += messageBytes;\n resolve();\n }\n });\n });\n }\n\n /**\n * Format a log entry for file output\n */\n private formatEntry(entry: LogEntry): string {\n let formatted: string;\n\n if (this.jsonFormat) {\n formatted = JSON.stringify({\n timestamp: entry.timestamp,\n type: entry.type,\n serviceName: entry.serviceName,\n entityName: entry.entityName,\n message: entry.message,\n params: entry.redactedParams, // Use redacted params for file output\n });\n } else {\n let text = '';\n\n if (entry.type !== 'raw') {\n text = `[${entry.type}] `;\n if (entry.serviceName) {\n text += `[${entry.serviceName}] `;\n }\n\n if (entry.entityName) {\n text += `[${entry.entityName}] `;\n }\n }\n text += entry.message;\n formatted = text;\n }\n\n return formatted + '\\n';\n }\n\n /**\n * Setup the log file\n */\n private async setupLogFile(): Promise<void> {\n const currentDate = new Date().toISOString().slice(0, 10); // YYYY-MM-DD (UTC)\n const currentLogFile = `${this.logDir}/${this.basename}-${currentDate}.log`;\n\n try {\n await fsPromises.mkdir(this.logDir, { recursive: true });\n\n // Explicitly create the file if it doesn't exist to avoid race conditions\n // This ensures the file exists on disk before we try to read it in tests\n try {\n await fsPromises.access(currentLogFile);\n } catch {\n // File doesn't exist, create it\n await fsPromises.writeFile(currentLogFile, '', { flag: 'a' });\n }\n\n this.logFileStream = fs.createWriteStream(currentLogFile, { flags: 'a' });\n this.currentLogFile = currentLogFile;\n\n this.logFileStream.on('error', () => {\n this.destroyStream();\n });\n\n // Get current file size\n try {\n const stats = await fsPromises.stat(currentLogFile);\n this.currentLogSize = stats.size;\n } catch {\n this.currentLogSize = 0;\n }\n\n // Rotate if already at size limit\n const maxSizeBytes = this.maxSizeMB * 1024 * 1024;\n if (this.currentLogSize >= maxSizeBytes) {\n await this.rotateFile();\n }\n } catch (error) {\n throw new FileSinkError(\n `Failed to setup log file: ${currentLogFile}`,\n error as Error,\n );\n }\n }\n\n /**\n * Destroy the current stream\n */\n private destroyStream(): void {\n if (this.logFileStream) {\n try {\n this.logFileStream.destroy();\n } catch {\n // Ignore\n } finally {\n this.logFileStream = undefined;\n }\n }\n }\n\n /**\n * Rotate log file if needed based on size or date\n */\n private async rotateIfNeeded(): Promise<void> {\n if (!this.logFileStream || !this.currentLogFile) {\n return;\n }\n\n const currentDate = new Date().toISOString().slice(0, 10); // YYYY-MM-DD (UTC)\n const expectedFile = `${this.logDir}/${this.basename}-${currentDate}.log`;\n\n // Date changed - setup new file\n if (this.currentLogFile !== expectedFile) {\n await this.setupLogFile();\n return;\n }\n\n // Size limit reached\n const maxSizeBytes = this.maxSizeMB * 1024 * 1024;\n if (this.currentLogSize >= maxSizeBytes) {\n await this.rotateFile();\n }\n }\n\n /**\n * Rotate the current log file\n * Queue processing pauses during rotation, then resumes\n */\n private async rotateFile(): Promise<void> {\n if (!this.logFileStream || !this.currentLogFile) {\n return;\n }\n\n const currentDate = new Date().toISOString().slice(0, 10); // YYYY-MM-DD (UTC)\n\n // Close current stream\n await new Promise<void>((resolve) => {\n if (!this.logFileStream) {\n return resolve();\n }\n\n this.logFileStream.end(() => {\n this.logFileStream = undefined;\n resolve();\n });\n });\n\n // Rename with timestamp\n const timestamp = Math.floor(Date.now() / 1000);\n const rotatedFile = `${this.logDir}/${this.basename}-${currentDate}-${timestamp}.log`;\n\n try {\n await fsPromises.rename(this.currentLogFile, rotatedFile);\n } catch (error) {\n throw new FileSinkError(\n `Error rotating log file from ${this.currentLogFile} to ${rotatedFile}`,\n error as Error,\n );\n }\n\n // Setup new file (queue processing will resume after this)\n await this.setupLogFile();\n }\n}\n","import * as fs from 'fs';\nimport { promises as fsPromises } from 'fs';\nimport * as os from 'os';\nimport type { LogEntry, LogSink } from '../types';\n\n/**\n * Types of pipe errors that can occur\n */\nexport enum PipeErrorType {\n WRITE = 'write',\n CLOSE = 'close',\n NOT_FOUND = 'not_found',\n NOT_A_PIPE = 'not_a_pipe',\n PERMISSION = 'permission',\n UNSUPPORTED_PLATFORM = 'unsupported_platform',\n}\n\nexport interface NamedPipeSinkOptions {\n pipePath: string;\n jsonFormat?: boolean;\n closeTimeoutMS?: number;\n onError?: (errorType: PipeErrorType, error: Error, pipePath: string) => void;\n formatter?: (entry: LogEntry) => string;\n}\n\nexport type ReconnectStatus =\n | { success: true }\n | { success: false; reason: 'already_reconnecting' }\n | { success: false; reason: 'error'; error: Error };\n\n/**\n * NamedPipeSink writes logs to a named pipe (FIFO)\n * Only supported on Linux and macOS\n */\nexport class NamedPipeSink implements LogSink {\n private pipePath: string;\n private jsonFormat: boolean;\n private onError?: (\n errorType: PipeErrorType,\n error: Error,\n pipePath: string,\n ) => void;\n private formatter?: (entry: LogEntry) => string;\n private pipeStream?: fs.WriteStream;\n private writeQueue: LogEntry[] = [];\n private isInitialized = false;\n private _isReconnecting = false;\n private initPromise: Promise<void>;\n private closing = false;\n private closed = false;\n private closeTimeoutMS: number;\n\n constructor(options: NamedPipeSinkOptions) {\n this.pipePath = options.pipePath;\n this.jsonFormat = options.jsonFormat ?? false;\n this.onError = options.onError;\n this.formatter = options.formatter;\n this.closeTimeoutMS = options.closeTimeoutMS ?? 30000;\n\n this.initPromise = this.initializePipe();\n }\n\n public write(entry: LogEntry): void {\n if (this.closing || this.closed) {\n return;\n }\n\n // Queue entry if not initialized\n if (!this.isInitialized) {\n this.writeQueue.push(entry);\n return;\n }\n\n this.writeEntry(entry);\n }\n\n /**\n * Attempt to reconnect to the named pipe.\n * Useful when the pipe reader restarts or after a temporary error.\n * Queued writes during the outage will be flushed on successful reconnection.\n */\n public get isReconnecting(): boolean {\n return this._isReconnecting;\n }\n\n public async reconnect(): Promise<ReconnectStatus> {\n // If already reconnecting, just wait for the existing attempt\n if (this._isReconnecting) {\n await this.initPromise;\n return { success: false, reason: 'already_reconnecting' };\n }\n\n this._isReconnecting = true;\n\n try {\n // Close existing stream if any\n if (this.pipeStream && !this.pipeStream.destroyed) {\n this.pipeStream.end();\n this.pipeStream = undefined;\n }\n\n this.isInitialized = false;\n this.initPromise = this.initializePipe();\n await this.initPromise;\n\n // Check if initialization actually succeeded\n if (this.isInitialized) {\n return { success: true };\n } else {\n return {\n success: false,\n reason: 'error',\n error: new Error('Failed to initialize pipe connection'),\n };\n }\n } finally {\n this._isReconnecting = false;\n }\n }\n\n public async close(): Promise<void> {\n this.closing = true;\n\n // Wait for initialization with timeout\n let timeoutHandle: NodeJS.Timeout | undefined;\n const timeoutSentinel = { timedOut: true } as const;\n\n try {\n const timeoutPromise = new Promise<typeof timeoutSentinel>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve(timeoutSentinel),\n this.closeTimeoutMS,\n );\n });\n\n const result = await Promise.race([\n this.initPromise.then(() => undefined),\n timeoutPromise,\n ]);\n\n // Check if timeout fired\n if (result === timeoutSentinel) {\n // Timeout fired - prevent unhandled rejection if initPromise fails later\n Promise.resolve(this.initPromise).catch(() => {\n // Intentionally ignore errors after timeout\n });\n }\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n\n this.closed = true;\n\n if (this.pipeStream && !this.pipeStream.destroyed) {\n return new Promise<void>((resolve) => {\n try {\n this.pipeStream?.end(() => {\n this.pipeStream = undefined;\n resolve();\n });\n } catch (error) {\n this.handleError(\n PipeErrorType.CLOSE,\n error instanceof Error ? error : new Error(String(error)),\n );\n resolve();\n }\n });\n }\n }\n\n /**\n * Initialize the named pipe connection\n */\n private async initializePipe(): Promise<void> {\n // Check platform support\n const platform = os.platform();\n if (platform !== 'linux' && platform !== 'darwin') {\n this.handleError(\n PipeErrorType.UNSUPPORTED_PLATFORM,\n new Error(\n `Named pipes are only supported on Linux and macOS, current platform: ${platform}`,\n ),\n );\n\n return;\n }\n\n try {\n // Check if the pipe exists and is a FIFO\n const stats = await fsPromises.stat(this.pipePath);\n if (!stats.isFIFO()) {\n this.handleError(\n PipeErrorType.NOT_A_PIPE,\n new Error(`${this.pipePath} exists but is not a named pipe (FIFO)`),\n );\n return;\n }\n\n // Create write stream\n this.pipeStream = fs.createWriteStream(this.pipePath, {\n flags: 'a', // Append mode\n });\n\n this.pipeStream.on('error', (err) => {\n this.handleError(PipeErrorType.WRITE, err);\n this.pipeStream = undefined;\n });\n\n this.isInitialized = true;\n\n // Process any queued writes\n this.processQueue();\n } catch (error) {\n this.handleError(\n PipeErrorType.NOT_FOUND,\n new Error(\n `Could not open named pipe at ${this.pipePath}: ${(error as Error).message}`,\n ),\n );\n }\n }\n\n /**\n * Process queued entries\n */\n private processQueue(): void {\n while (this.writeQueue.length > 0 && !this.closed) {\n const entry = this.writeQueue.shift();\n if (entry) {\n this.writeEntry(entry);\n }\n }\n }\n\n /**\n * Write a single entry\n */\n private writeEntry(entry: LogEntry): void {\n if (this.closed) {\n return;\n }\n\n if (!this.pipeStream || this.pipeStream.destroyed) {\n // Silently skip if pipe is not available\n return;\n }\n\n try {\n const messageToWrite = this.formatEntry(entry);\n\n // Write to pipe with backpressure handling\n if (!this.pipeStream.write(messageToWrite)) {\n this.pipeStream.once('drain', () => {\n // Handle backpressure - stream is ready again\n });\n }\n } catch (error) {\n this.handleError(\n PipeErrorType.WRITE,\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n\n /**\n * Format a log entry for pipe output\n */\n private formatEntry(entry: LogEntry): string {\n // Use custom formatter if provided\n if (this.formatter) {\n try {\n return this.formatter(entry) + '\\n';\n } catch {\n // If formatter fails, fall through to default formatting\n }\n }\n\n let formatted: string;\n\n if (this.jsonFormat) {\n formatted = JSON.stringify({\n timestamp: entry.timestamp,\n type: entry.type,\n serviceName: entry.serviceName,\n entityName: entry.entityName,\n message: entry.message,\n params: entry.redactedParams,\n });\n } else {\n let text = '';\n if (entry.type !== 'raw') {\n text = `[${entry.type}] `;\n if (entry.serviceName) {\n text += `[${entry.serviceName}] `;\n }\n\n if (entry.entityName) {\n text += `[${entry.entityName}] `;\n }\n }\n text += entry.message;\n formatted = text;\n }\n\n return formatted + '\\n';\n }\n\n /**\n * Handle errors\n */\n private handleError(errorType: PipeErrorType, error: Error): void {\n if (this.onError) {\n this.onError(errorType, error, this.pipePath);\n } else {\n // Default: log to console\n // eslint-disable-next-line no-console\n console.error(`NamedPipeSink error (${errorType}): ${error.message}`);\n }\n }\n}\n","import { EventEmitter } from '../event-emitter';\nimport { ms } from '../unix-time-helpers';\nimport { safeHandleCallbackAndWait } from '../safe-handle-callback';\nimport { CurlyBrackets } from '../curly-brackets';\nimport { isNumber } from '../is-number';\nimport { isPromise } from '../is-promise';\nimport type {\n LogEntry,\n LogSink,\n LogType,\n LoggerOptions,\n LogOptions,\n BeforeExitResult,\n} from './types';\nimport type { HandleLogOptions } from './internal-types';\nimport { ArraySink } from './sinks/array';\nimport { ConsoleSink } from './sinks/console';\nimport { applyRedaction } from './utils/redaction';\nimport { prepareErrorObjectLog } from './utils/error-object';\nimport { LoggerService } from './logger-service';\n\n/**\n * Main Logger class with sink-based architecture and EventEmitter support\n */\nexport class Logger extends EventEmitter {\n public readonly isLoggerClass = true;\n\n private sinks: LogSink[];\n private redactFunction?: (key: string, value: unknown) => unknown;\n private callProcessExit: boolean;\n private beforeExitCallback?: (\n exitCode: number,\n isFirstExit: boolean,\n ) => BeforeExitResult | Promise<BeforeExitResult>;\n private onSinkError?: (\n error: Error,\n context: 'write' | 'close',\n sink: LogSink,\n ) => void;\n\n private _didExit = false;\n private _exitCode: number = 0;\n private _exitRequested = false;\n private _isPendingExit = false;\n private _closed = false;\n\n private _reportErrorListenerRegistered = false;\n private _reportErrorListener: ((event: Event) => void) | null = null;\n\n constructor(options: LoggerOptions = {}) {\n super();\n\n this.sinks = options.sinks || [];\n this.redactFunction = options.redactFunction;\n this.callProcessExit = options.callProcessExit ?? true;\n this.beforeExitCallback = options.beforeExitCallback;\n this.onSinkError = options.onSinkError;\n }\n\n public get didExit(): boolean {\n return this._didExit;\n }\n\n public get exitCode(): number {\n return this._exitCode;\n }\n\n public get isPendingExit(): boolean {\n return this._isPendingExit;\n }\n\n public get hasExitedOrPending(): boolean {\n return this._didExit || this._isPendingExit;\n }\n\n public get closed(): boolean {\n return this._closed;\n }\n\n /**\n * Exit the process with the specified code\n */\n public exit(code: number): void {\n const isFirstExit = !this._exitRequested;\n this._exitRequested = true;\n\n if (!this._didExit) {\n this._isPendingExit = true;\n }\n\n this.emit('logger', { eventType: 'exit-called', code, isFirstExit });\n\n if (this.beforeExitCallback) {\n safeHandleCallbackAndWait<BeforeExitResult>(\n 'beforeExit',\n this.beforeExitCallback,\n code,\n isFirstExit,\n )\n .then((result) => {\n // Check if callback returned a result indicating we should wait\n if (result.success && result.value?.action === 'wait') {\n // Shutdown is already in progress, don't proceed with exit\n // The ongoing shutdown will handle the exit when it completes\n return;\n }\n\n // Proceed with exit (either callback returned 'proceed' or failed)\n this.processExit(code);\n })\n .catch(() => {\n // If callback throws an error, proceed with exit anyway\n // This ensures the process doesn't hang on callback failures\n this.processExit(code);\n });\n } else {\n this.processExit(code);\n }\n }\n\n /**\n * Set or update the beforeExit callback\n *\n * This allows setting the callback after Logger construction, which is useful\n * when the callback needs to reference objects that depend on the Logger instance.\n *\n * **Note:** This method overwrites any existing beforeExit callback (including\n * one set in the Logger constructor). Pass `undefined` to remove the callback.\n *\n * **Error Handling:** If the callback throws an error or rejects, the logger will\n * proceed with exit anyway to prevent the process from hanging. The error will be\n * reported via the global `reportError` event.\n *\n * @param callback - Function to call before process exit (receives exitCode and isFirstExit).\n * Must return BeforeExitResult indicating whether to proceed with exit or wait.\n * Return `{ action: 'proceed' }` to continue with exit.\n * Return `{ action: 'wait' }` to prevent exit (e.g., shutdown already in progress).\n * If the callback throws, exit proceeds automatically.\n *\n * Pass undefined to remove the callback.\n *\n * @example\n * ```typescript\n * const logger = new Logger();\n * const lifecycle = new LifecycleManager({ logger });\n *\n * // Set callback after both are constructed\n * logger.setBeforeExitCallback(async (exitCode, isFirstExit) => {\n * if (isFirstExit) {\n * await lifecycle.stopAllComponents();\n * }\n * return { action: 'proceed' };\n * });\n *\n * // Later, remove the callback\n * logger.setBeforeExitCallback(undefined);\n * ```\n */\n public setBeforeExitCallback(\n callback:\n | ((\n exitCode: number,\n isFirstExit: boolean,\n ) => BeforeExitResult | Promise<BeforeExitResult>)\n | undefined,\n ): void {\n this.beforeExitCallback = callback;\n }\n\n /**\n * Log an error message\n */\n public error(message: string, options?: LogOptions): void {\n this.handleLog('error', message, options);\n }\n\n /**\n * Log an error object with optional prefix\n */\n public errorObject(\n prefix: string,\n error: unknown,\n options?: LogOptions,\n ): void {\n const message = prepareErrorObjectLog(prefix, error);\n\n this.handleLog('error', message, { ...(options ?? {}), error });\n }\n\n /**\n * Log an informational message\n */\n public info(message: string, options?: LogOptions): void {\n this.handleLog('info', message, options);\n }\n\n /**\n * Log a warning message\n */\n public warn(message: string, options?: LogOptions): void {\n this.handleLog('warn', message, options);\n }\n\n /**\n * Log a success message\n */\n public success(message: string, options?: LogOptions): void {\n this.handleLog('success', message, options);\n }\n\n /**\n * Log a notice message\n */\n public notice(message: string, options?: LogOptions): void {\n this.handleLog('notice', message, options);\n }\n\n /**\n * Log a debug message\n */\n public debug(message: string, options?: LogOptions): void {\n this.handleLog('debug', message, options);\n }\n\n /**\n * Log a raw message without any formatting\n */\n public raw(message: string, options?: LogOptions): void {\n this.handleLog('raw', message, options);\n }\n\n /**\n * Create a scoped logger with a service name\n */\n public service(serviceName: string): LoggerService {\n return new LoggerService(this.handleLog.bind(this), serviceName);\n }\n\n /**\n * Registers a listener for the 'reportError' event.\n *\n * If the listener is already registered, it returns 'already_registered'.\n * If 'globalThis.reportError' is not available, it returns 'not_available'.\n * Otherwise, it registers the listener and returns 'success'.\n *\n * @param prefix - The prefix to use when logging the error object. Default is 'Uncaught exception'.\n * @returns 'success' if the listener is registered successfully,\n * 'already_registered' if the listener is already registered,\n * 'not_available' if 'globalThis.reportError' is not available.\n */\n\n public registerReportErrorListener(\n prefix: string = 'Uncaught exception',\n ): 'success' | 'already_registered' | 'not_available' {\n if (this._reportErrorListenerRegistered) {\n return 'already_registered';\n }\n\n if (typeof globalThis.reportError === 'undefined') {\n return 'not_available';\n }\n\n this._reportErrorListener = (event: Event): void => {\n const errorEvent = event as ErrorEvent;\n this.errorObject(prefix, errorEvent.error);\n this.emit('logger', {\n eventType: 'uncaughtException',\n error: errorEvent.error as unknown,\n });\n };\n\n globalThis.addEventListener('reportError', this._reportErrorListener);\n this._reportErrorListenerRegistered = true;\n\n return 'success';\n }\n\n /**\n * Unregister the listener for the 'reportError' event.\n *\n * If the listener is not registered, it returns 'not_registered'.\n * Otherwise, it unregister the listener and returns 'success'.\n *\n * @returns 'success' if the listener is unregistered successfully,\n * 'not_registered' if the listener is not registered.\n */\n\n public unregisterReportErrorListener(): 'success' | 'not_registered' {\n if (!this._reportErrorListenerRegistered || !this._reportErrorListener) {\n return 'not_registered';\n }\n\n globalThis.removeEventListener('reportError', this._reportErrorListener);\n\n this._reportErrorListener = null;\n this._reportErrorListenerRegistered = false;\n\n return 'success';\n }\n\n /**\n * Check if the 'reportError' event listener is registered\n *\n * @returns 'true' if the listener is registered, 'false' otherwise.\n */\n public isReportErrorListenerRegistered(): boolean {\n return this._reportErrorListenerRegistered;\n }\n\n /**\n * Check if 'globalThis.reportError' is available\n *\n * @returns 'true' if 'globalThis.reportError' is available, 'false' otherwise.\n */\n public isReportErrorAvailable(): boolean {\n return typeof globalThis.reportError !== 'undefined';\n }\n\n /**\n * Add a sink to the logger\n */\n public addSink(sink: LogSink): void {\n this.sinks.push(sink);\n }\n\n /**\n * Remove a sink from the logger\n * Returns true if the sink was found and removed, false otherwise\n */\n public removeSink(sink: LogSink): boolean {\n const index = this.sinks.indexOf(sink);\n if (index !== -1) {\n this.sinks.splice(index, 1);\n return true;\n }\n return false;\n }\n\n /**\n * Get a readonly copy of the current sinks\n */\n public getSinks(): readonly LogSink[] {\n return [...this.sinks];\n }\n\n /**\n * Close all sinks and cleanup resources\n * After closing, the logger is marked as closed and all sinks are removed\n */\n public async close(): Promise<void> {\n this._closed = true;\n\n // Close all sinks\n await Promise.all(\n this.sinks.map(async (sink) => {\n if (sink.close) {\n try {\n await sink.close();\n } catch (error) {\n this.handleSinkError(error as Error, 'close', sink);\n }\n }\n }),\n );\n\n // Remove all sinks from the array after closing\n this.sinks = [];\n\n this.emit('logger', { eventType: 'close' });\n }\n\n /**\n * Create a logger optimized for testing.\n * Includes an ArraySink by default for easy log inspection.\n * Process exit is disabled to prevent tests from terminating.\n */\n public static createTestOptimizedLogger(options?: {\n sinks?: LogSink[];\n arrayLogTransformer?: (entry: LogEntry) => LogEntry | false;\n includeConsoleSink?: boolean;\n muteConsole?: boolean;\n }): { logger: Logger; arraySink: ArraySink; consoleSink?: ConsoleSink } {\n const arraySink = new ArraySink({\n transformer: options?.arrayLogTransformer,\n });\n\n const consoleSink = options?.includeConsoleSink\n ? new ConsoleSink({ muted: options?.muteConsole ?? true })\n : undefined;\n\n const sinks: LogSink[] = [arraySink];\n\n if (consoleSink) {\n sinks.push(consoleSink);\n }\n\n sinks.push(...(options?.sinks || []));\n\n return {\n logger: new Logger({\n sinks,\n callProcessExit: false,\n }),\n arraySink,\n consoleSink,\n };\n }\n\n /**\n * Create a logger optimized for frontend/browser use.\n * Includes a ConsoleSink by default for browser devtools output.\n * Process exit is disabled since browsers don't have process.exit.\n */\n public static createFrontendOptimizedLogger(options?: {\n sinks?: LogSink[];\n muteConsole?: boolean;\n }): { logger: Logger; consoleSink: ConsoleSink } {\n const consoleSink = new ConsoleSink({\n muted: options?.muteConsole ?? false,\n });\n\n return {\n logger: new Logger({\n sinks: [consoleSink, ...(options?.sinks || [])],\n callProcessExit: false,\n }),\n consoleSink,\n };\n }\n\n /**\n * Internal method to handle all log operations\n */\n protected handleLog(\n type: LogType,\n template: string,\n options?: HandleLogOptions,\n ): void {\n // Don't log if logger is closed\n if (this._closed) {\n return;\n }\n\n const timestamp = ms();\n\n // Extract options\n const exitCode = options?.exitCode;\n const serviceName = options?.serviceName?.trim() || undefined;\n const entityName = options?.entityName?.trim() || undefined;\n const params = options?.params;\n const tags = options?.tags;\n const redactedKeys = options?.redactedKeys;\n\n // Process template and apply redaction\n const message = params ? CurlyBrackets(template, params) : template;\n const redactedParams = params\n ? applyRedaction(params, redactedKeys, this.redactFunction)\n : undefined;\n\n // Create log entry\n const entry: LogEntry = {\n timestamp,\n type,\n serviceName,\n entityName,\n template,\n message,\n params,\n redactedParams,\n redactedKeys:\n params && redactedKeys && redactedKeys.length > 0\n ? redactedKeys\n : undefined,\n error: options?.error,\n exitCode: isNumber(exitCode) ? exitCode : undefined,\n tags: tags && tags.length > 0 ? tags : undefined,\n };\n\n // Write to all sinks\n for (const sink of this.sinks) {\n try {\n const result = sink.write(entry);\n // Handle async errors from sinks that return promises\n if (isPromise(result)) {\n result.catch((error: unknown) => {\n this.handleSinkError(error as Error, 'write', sink);\n });\n }\n } catch (error) {\n // Handle sync errors\n this.handleSinkError(error as Error, 'write', sink);\n }\n }\n\n // Emit log event\n this.emit('logger', {\n eventType: 'log',\n logType: type,\n message,\n timestamp,\n });\n\n // Handle exit if requested (only if exitCode is a valid number)\n if (isNumber(exitCode)) {\n this.exit(exitCode);\n }\n }\n\n /**\n * Handle sink errors by calling the onSinkError callback or falling back to console.error\n */\n private handleSinkError(\n error: Error,\n context: 'write' | 'close',\n sink: LogSink,\n ): void {\n if (this.onSinkError) {\n try {\n this.onSinkError(error, context, sink);\n } catch {\n // Ignore errors in the error handler to prevent infinite loops\n // eslint-disable-next-line no-console\n console.error(`Error in onSinkError handler: ${error.message}`);\n }\n } else {\n // Fallback to console.error\n // eslint-disable-next-line no-console\n console.error(\n `Error ${context === 'write' ? 'writing to' : 'closing'} sink: ${error.message}`,\n );\n }\n }\n\n /**\n * Process the exit\n */\n private processExit(code: number): void {\n this._didExit = true;\n this._exitCode = code;\n this._isPendingExit = false;\n\n this.emit('logger', { eventType: 'exit-process', code });\n\n // Close sinks and then exit\n void this.close().finally(() => {\n if (this.callProcessExit) {\n if (\n typeof globalThis.process !== 'undefined' &&\n typeof globalThis.process.exit === 'function'\n ) {\n globalThis.process.exit(code);\n }\n }\n });\n }\n}\n\n// Re-export types and sinks\nexport * from './types';\nexport * from './sinks';\nexport type { LoggerService } from './logger-service';\n"],"mappings":"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","names":["stringWidth","availableWidth","stringWidth","stringWidth","availableWidth","callbacks","LogLevel","cloned","entriesWritten","entriesFailed","fs","fsPromises","PipeErrorType","platform"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/lib/padding-utils.ts
|
|
21
|
+
var padding_utils_exports = {};
|
|
22
|
+
__export(padding_utils_exports, {
|
|
23
|
+
padCenter: () => padCenter,
|
|
24
|
+
padCenterPreferLeft: () => padCenterPreferLeft,
|
|
25
|
+
padCenterPreferRight: () => padCenterPreferRight,
|
|
26
|
+
padLeft: () => padLeft,
|
|
27
|
+
padRight: () => padRight
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(padding_utils_exports);
|
|
30
|
+
|
|
31
|
+
// src/lib/constants.ts
|
|
32
|
+
var BLANK_SPACE = " ";
|
|
33
|
+
var EOL = "\n";
|
|
34
|
+
var DOUBLE_EOL = EOL + EOL;
|
|
35
|
+
var INDENT = " ".repeat(4);
|
|
36
|
+
var DOUBLE_INDENT = INDENT + INDENT;
|
|
37
|
+
var ASCII_LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
|
|
38
|
+
var ASCII_UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
39
|
+
var ASCII_LETTERS = ASCII_LOWERCASE + ASCII_UPPERCASE;
|
|
40
|
+
var DIGITS = "0123456789";
|
|
41
|
+
var HEX_DIGITS = DIGITS + "abcdefABCDEF";
|
|
42
|
+
var PUNCTUATION = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
|
43
|
+
var WHITESPACE = " \n\r\v\f";
|
|
44
|
+
var PRINTABLE = DIGITS + ASCII_LETTERS + PUNCTUATION + WHITESPACE;
|
|
45
|
+
|
|
46
|
+
// src/lib/padding-utils.ts
|
|
47
|
+
function padLeft(str, length, padStr = BLANK_SPACE) {
|
|
48
|
+
return str.padStart(length, padStr);
|
|
49
|
+
}
|
|
50
|
+
function padRight(str, length, padStr = BLANK_SPACE) {
|
|
51
|
+
return str.padEnd(length, padStr);
|
|
52
|
+
}
|
|
53
|
+
function padCenter(str, length, prefer = "left", padStr = BLANK_SPACE) {
|
|
54
|
+
const midStrLength = length - str.length;
|
|
55
|
+
if (midStrLength > 0) {
|
|
56
|
+
const padLeftAmount = prefer === "left" ? Math.ceil(midStrLength / 2) : Math.floor(midStrLength / 2);
|
|
57
|
+
const padRightAmount = prefer === "left" ? Math.floor(midStrLength / 2) : Math.ceil(midStrLength / 2);
|
|
58
|
+
return padLeft("", padLeftAmount, padStr) + str + padRight("", padRightAmount, padStr);
|
|
59
|
+
} else {
|
|
60
|
+
return str;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function padCenterPreferLeft(str, length, padStr = BLANK_SPACE) {
|
|
64
|
+
return padCenter(str, length, "left", padStr);
|
|
65
|
+
}
|
|
66
|
+
function padCenterPreferRight(str, length, padStr = BLANK_SPACE) {
|
|
67
|
+
return padCenter(str, length, "right", padStr);
|
|
68
|
+
}
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
padCenter,
|
|
72
|
+
padCenterPreferLeft,
|
|
73
|
+
padCenterPreferRight,
|
|
74
|
+
padLeft,
|
|
75
|
+
padRight
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=padding-utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/padding-utils.ts","../../src/lib/constants.ts"],"sourcesContent":["/**\n * Utilities to pad strings with another string up to a defined length.\n * Each function takes a string, length to pad and the string to be used for padding (but defaults to a blank space if not provided) and returns the modified string\n *\n * This only pads on the left side, so text is added to the front until the total string equals the given length.\n *\n * ```typescript\n * padLeft('Hey', 6, '*'); // returns ***Hey\n * ```\n * @category String Padding\n */\n\nimport { BLANK_SPACE } from './constants';\n\nexport function padLeft(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return str.padStart(length, padStr);\n}\n\n/**\n * This only pads on the right side, so text is added to the end until the total string equals the given length.\n *\n * ```typescript\n * padRight('Hey', 6, '*'); // returns Hey***\n * ```\n *\n * @category String Padding\n */\n\nexport function padRight(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return str.padEnd(length, padStr);\n}\n\n/**\n * Same as `padCenterPreferLeft` and `padCenterPreferRight` but you can pass in a string with `left` or `right` before the padStr to use more direct.\n *\n * Defaults to `left`\n *\n * @category String Padding\n */\n\nexport function padCenter(\n str: string,\n length: number,\n prefer: 'left' | 'right' = 'left',\n padStr = BLANK_SPACE,\n): string {\n const midStrLength = length - str.length;\n\n if (midStrLength > 0) {\n const padLeftAmount =\n prefer === 'left'\n ? Math.ceil(midStrLength / 2)\n : Math.floor(midStrLength / 2);\n\n const padRightAmount =\n prefer === 'left'\n ? Math.floor(midStrLength / 2)\n : Math.ceil(midStrLength / 2);\n\n return (\n padLeft('', padLeftAmount, padStr) +\n str +\n padRight('', padRightAmount, padStr)\n );\n } else {\n return str;\n }\n}\n\n/**\n * It tries to pad equally on both sides in an attempt to center your text. However if it can't the extra character will be added to the left side\n *\n * @category String Padding\n */\n\nexport function padCenterPreferLeft(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return padCenter(str, length, 'left', padStr);\n}\n\n/**\n * It tries to pad equally, but if it can't the extra character will be added to the right side\n *\n * @category String Padding\n */\n\nexport function padCenterPreferRight(\n str: string,\n length: number,\n padStr = BLANK_SPACE,\n): string {\n return padCenter(str, length, 'right', padStr);\n}\n","// prettier-ignore\nexport const BLANK_SPACE = ' ';\n\nexport const EOL = '\\n';\nexport const DOUBLE_EOL = EOL + EOL;\nexport const INDENT = ' '.repeat(4);\nexport const DOUBLE_INDENT = INDENT + INDENT;\n\n// prettier-ignore\nexport const SINGLE_QUOTE = \"'\";\n\n// similar to Python string library\nexport const ASCII_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';\nexport const ASCII_UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nexport const ASCII_LETTERS = ASCII_LOWERCASE + ASCII_UPPERCASE;\nexport const DIGITS = '0123456789';\nexport const HEX_DIGITS = DIGITS + 'abcdefABCDEF';\nexport const OCT_DIGITS = '01234567';\nexport const PUNCTUATION = '!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~';\nexport const WHITESPACE = ' \\t\\n\\r\\v\\f';\nexport const PRINTABLE = DIGITS + ASCII_LETTERS + PUNCTUATION + WHITESPACE;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCO,IAAM,cAAc;AAEpB,IAAM,MAAM;AACZ,IAAM,aAAa,MAAM;AACzB,IAAM,SAAS,IAAI,OAAO,CAAC;AAC3B,IAAM,gBAAgB,SAAS;AAM/B,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,gBAAgB,kBAAkB;AACxC,IAAM,SAAS;AACf,IAAM,aAAa,SAAS;AAE5B,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,YAAY,SAAS,gBAAgB,cAAc;;;ADNzD,SAAS,QACd,KACA,QACA,SAAS,aACD;AACR,SAAO,IAAI,SAAS,QAAQ,MAAM;AACpC;AAYO,SAAS,SACd,KACA,QACA,SAAS,aACD;AACR,SAAO,IAAI,OAAO,QAAQ,MAAM;AAClC;AAUO,SAAS,UACd,KACA,QACA,SAA2B,QAC3B,SAAS,aACD;AACR,QAAM,eAAe,SAAS,IAAI;AAElC,MAAI,eAAe,GAAG;AACpB,UAAM,gBACJ,WAAW,SACP,KAAK,KAAK,eAAe,CAAC,IAC1B,KAAK,MAAM,eAAe,CAAC;AAEjC,UAAM,iBACJ,WAAW,SACP,KAAK,MAAM,eAAe,CAAC,IAC3B,KAAK,KAAK,eAAe,CAAC;AAEhC,WACE,QAAQ,IAAI,eAAe,MAAM,IACjC,MACA,SAAS,IAAI,gBAAgB,MAAM;AAAA,EAEvC,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAQO,SAAS,oBACd,KACA,QACA,SAAS,aACD;AACR,SAAO,UAAU,KAAK,QAAQ,QAAQ,MAAM;AAC9C;AAQO,SAAS,qBACd,KACA,QACA,SAAS,aACD;AACR,SAAO,UAAU,KAAK,QAAQ,SAAS,MAAM;AAC/C;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities to pad strings with another string up to a defined length.
|
|
3
|
+
* Each function takes a string, length to pad and the string to be used for padding (but defaults to a blank space if not provided) and returns the modified string
|
|
4
|
+
*
|
|
5
|
+
* This only pads on the left side, so text is added to the front until the total string equals the given length.
|
|
6
|
+
*
|
|
7
|
+
* ```typescript
|
|
8
|
+
* padLeft('Hey', 6, '*'); // returns ***Hey
|
|
9
|
+
* ```
|
|
10
|
+
* @category String Padding
|
|
11
|
+
*/
|
|
12
|
+
declare function padLeft(str: string, length: number, padStr?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* This only pads on the right side, so text is added to the end until the total string equals the given length.
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* padRight('Hey', 6, '*'); // returns Hey***
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @category String Padding
|
|
21
|
+
*/
|
|
22
|
+
declare function padRight(str: string, length: number, padStr?: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Same as `padCenterPreferLeft` and `padCenterPreferRight` but you can pass in a string with `left` or `right` before the padStr to use more direct.
|
|
25
|
+
*
|
|
26
|
+
* Defaults to `left`
|
|
27
|
+
*
|
|
28
|
+
* @category String Padding
|
|
29
|
+
*/
|
|
30
|
+
declare function padCenter(str: string, length: number, prefer?: 'left' | 'right', padStr?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* It tries to pad equally on both sides in an attempt to center your text. However if it can't the extra character will be added to the left side
|
|
33
|
+
*
|
|
34
|
+
* @category String Padding
|
|
35
|
+
*/
|
|
36
|
+
declare function padCenterPreferLeft(str: string, length: number, padStr?: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* It tries to pad equally, but if it can't the extra character will be added to the right side
|
|
39
|
+
*
|
|
40
|
+
* @category String Padding
|
|
41
|
+
*/
|
|
42
|
+
declare function padCenterPreferRight(str: string, length: number, padStr?: string): string;
|
|
43
|
+
|
|
44
|
+
export { padCenter, padCenterPreferLeft, padCenterPreferRight, padLeft, padRight };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities to pad strings with another string up to a defined length.
|
|
3
|
+
* Each function takes a string, length to pad and the string to be used for padding (but defaults to a blank space if not provided) and returns the modified string
|
|
4
|
+
*
|
|
5
|
+
* This only pads on the left side, so text is added to the front until the total string equals the given length.
|
|
6
|
+
*
|
|
7
|
+
* ```typescript
|
|
8
|
+
* padLeft('Hey', 6, '*'); // returns ***Hey
|
|
9
|
+
* ```
|
|
10
|
+
* @category String Padding
|
|
11
|
+
*/
|
|
12
|
+
declare function padLeft(str: string, length: number, padStr?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* This only pads on the right side, so text is added to the end until the total string equals the given length.
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* padRight('Hey', 6, '*'); // returns Hey***
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @category String Padding
|
|
21
|
+
*/
|
|
22
|
+
declare function padRight(str: string, length: number, padStr?: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Same as `padCenterPreferLeft` and `padCenterPreferRight` but you can pass in a string with `left` or `right` before the padStr to use more direct.
|
|
25
|
+
*
|
|
26
|
+
* Defaults to `left`
|
|
27
|
+
*
|
|
28
|
+
* @category String Padding
|
|
29
|
+
*/
|
|
30
|
+
declare function padCenter(str: string, length: number, prefer?: 'left' | 'right', padStr?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* It tries to pad equally on both sides in an attempt to center your text. However if it can't the extra character will be added to the left side
|
|
33
|
+
*
|
|
34
|
+
* @category String Padding
|
|
35
|
+
*/
|
|
36
|
+
declare function padCenterPreferLeft(str: string, length: number, padStr?: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* It tries to pad equally, but if it can't the extra character will be added to the right side
|
|
39
|
+
*
|
|
40
|
+
* @category String Padding
|
|
41
|
+
*/
|
|
42
|
+
declare function padCenterPreferRight(str: string, length: number, padStr?: string): string;
|
|
43
|
+
|
|
44
|
+
export { padCenter, padCenterPreferLeft, padCenterPreferRight, padLeft, padRight };
|