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.
Files changed (177) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +125 -0
  3. package/dist/index.cjs +7 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +5 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/lib/arrays.cjs +95 -0
  10. package/dist/lib/arrays.cjs.map +1 -0
  11. package/dist/lib/arrays.d.cts +15 -0
  12. package/dist/lib/arrays.d.ts +15 -0
  13. package/dist/lib/arrays.js +63 -0
  14. package/dist/lib/arrays.js.map +1 -0
  15. package/dist/lib/ascii-tables/index.cjs +642 -0
  16. package/dist/lib/ascii-tables/index.cjs.map +1 -0
  17. package/dist/lib/ascii-tables/index.d.cts +66 -0
  18. package/dist/lib/ascii-tables/index.d.ts +66 -0
  19. package/dist/lib/ascii-tables/index.js +603 -0
  20. package/dist/lib/ascii-tables/index.js.map +1 -0
  21. package/dist/lib/clamp.cjs +41 -0
  22. package/dist/lib/clamp.cjs.map +1 -0
  23. package/dist/lib/clamp.d.cts +26 -0
  24. package/dist/lib/clamp.d.ts +26 -0
  25. package/dist/lib/clamp.js +15 -0
  26. package/dist/lib/clamp.js.map +1 -0
  27. package/dist/lib/constants.cjs +73 -0
  28. package/dist/lib/constants.cjs.map +1 -0
  29. package/dist/lib/constants.d.cts +17 -0
  30. package/dist/lib/constants.d.ts +17 -0
  31. package/dist/lib/constants.js +34 -0
  32. package/dist/lib/constants.js.map +1 -0
  33. package/dist/lib/curly-brackets.cjs +77 -0
  34. package/dist/lib/curly-brackets.cjs.map +1 -0
  35. package/dist/lib/curly-brackets.d.cts +17 -0
  36. package/dist/lib/curly-brackets.d.ts +17 -0
  37. package/dist/lib/curly-brackets.js +52 -0
  38. package/dist/lib/curly-brackets.js.map +1 -0
  39. package/dist/lib/deep-clone.cjs +87 -0
  40. package/dist/lib/deep-clone.cjs.map +1 -0
  41. package/dist/lib/deep-clone.d.cts +19 -0
  42. package/dist/lib/deep-clone.d.ts +19 -0
  43. package/dist/lib/deep-clone.js +62 -0
  44. package/dist/lib/deep-clone.js.map +1 -0
  45. package/dist/lib/error-to-string.cjs +743 -0
  46. package/dist/lib/error-to-string.cjs.map +1 -0
  47. package/dist/lib/error-to-string.d.cts +3 -0
  48. package/dist/lib/error-to-string.d.ts +3 -0
  49. package/dist/lib/error-to-string.js +706 -0
  50. package/dist/lib/error-to-string.js.map +1 -0
  51. package/dist/lib/event-emitter.cjs +899 -0
  52. package/dist/lib/event-emitter.cjs.map +1 -0
  53. package/dist/lib/event-emitter.d.cts +78 -0
  54. package/dist/lib/event-emitter.d.ts +78 -0
  55. package/dist/lib/event-emitter.js +861 -0
  56. package/dist/lib/event-emitter.js.map +1 -0
  57. package/dist/lib/id-helpers.cjs +205 -0
  58. package/dist/lib/id-helpers.cjs.map +1 -0
  59. package/dist/lib/id-helpers.d.cts +198 -0
  60. package/dist/lib/id-helpers.d.ts +198 -0
  61. package/dist/lib/id-helpers.js +170 -0
  62. package/dist/lib/id-helpers.js.map +1 -0
  63. package/dist/lib/is-boolean.cjs +33 -0
  64. package/dist/lib/is-boolean.cjs.map +1 -0
  65. package/dist/lib/is-boolean.d.cts +19 -0
  66. package/dist/lib/is-boolean.d.ts +19 -0
  67. package/dist/lib/is-boolean.js +8 -0
  68. package/dist/lib/is-boolean.js.map +1 -0
  69. package/dist/lib/is-function.cjs +33 -0
  70. package/dist/lib/is-function.cjs.map +1 -0
  71. package/dist/lib/is-function.d.cts +3 -0
  72. package/dist/lib/is-function.d.ts +3 -0
  73. package/dist/lib/is-function.js +8 -0
  74. package/dist/lib/is-function.js.map +1 -0
  75. package/dist/lib/is-number.cjs +38 -0
  76. package/dist/lib/is-number.cjs.map +1 -0
  77. package/dist/lib/is-number.d.cts +38 -0
  78. package/dist/lib/is-number.d.ts +38 -0
  79. package/dist/lib/is-number.js +12 -0
  80. package/dist/lib/is-number.js.map +1 -0
  81. package/dist/lib/is-plain-object.cjs +33 -0
  82. package/dist/lib/is-plain-object.cjs.map +1 -0
  83. package/dist/lib/is-plain-object.d.cts +20 -0
  84. package/dist/lib/is-plain-object.d.ts +20 -0
  85. package/dist/lib/is-plain-object.js +8 -0
  86. package/dist/lib/is-plain-object.js.map +1 -0
  87. package/dist/lib/is-promise.cjs +34 -0
  88. package/dist/lib/is-promise.cjs.map +1 -0
  89. package/dist/lib/is-promise.d.cts +3 -0
  90. package/dist/lib/is-promise.d.ts +3 -0
  91. package/dist/lib/is-promise.js +9 -0
  92. package/dist/lib/is-promise.js.map +1 -0
  93. package/dist/lib/json-helpers.cjs +49 -0
  94. package/dist/lib/json-helpers.cjs.map +1 -0
  95. package/dist/lib/json-helpers.d.cts +10 -0
  96. package/dist/lib/json-helpers.d.ts +10 -0
  97. package/dist/lib/json-helpers.js +22 -0
  98. package/dist/lib/json-helpers.js.map +1 -0
  99. package/dist/lib/lifecycle-manager/index.cjs +5594 -0
  100. package/dist/lib/lifecycle-manager/index.cjs.map +1 -0
  101. package/dist/lib/lifecycle-manager/index.d.cts +2044 -0
  102. package/dist/lib/lifecycle-manager/index.d.ts +2044 -0
  103. package/dist/lib/lifecycle-manager/index.js +5543 -0
  104. package/dist/lib/lifecycle-manager/index.js.map +1 -0
  105. package/dist/lib/logger/index.cjs +2514 -0
  106. package/dist/lib/logger/index.cjs.map +1 -0
  107. package/dist/lib/logger/index.d.cts +630 -0
  108. package/dist/lib/logger/index.d.ts +630 -0
  109. package/dist/lib/logger/index.js +2470 -0
  110. package/dist/lib/logger/index.js.map +1 -0
  111. package/dist/lib/padding-utils.cjs +77 -0
  112. package/dist/lib/padding-utils.cjs.map +1 -0
  113. package/dist/lib/padding-utils.d.cts +44 -0
  114. package/dist/lib/padding-utils.d.ts +44 -0
  115. package/dist/lib/padding-utils.js +46 -0
  116. package/dist/lib/padding-utils.js.map +1 -0
  117. package/dist/lib/process-signal-manager.cjs +1306 -0
  118. package/dist/lib/process-signal-manager.cjs.map +1 -0
  119. package/dist/lib/process-signal-manager.d.cts +305 -0
  120. package/dist/lib/process-signal-manager.d.ts +305 -0
  121. package/dist/lib/process-signal-manager.js +1269 -0
  122. package/dist/lib/process-signal-manager.js.map +1 -0
  123. package/dist/lib/promise-protected-resolver.cjs +828 -0
  124. package/dist/lib/promise-protected-resolver.cjs.map +1 -0
  125. package/dist/lib/promise-protected-resolver.d.cts +17 -0
  126. package/dist/lib/promise-protected-resolver.d.ts +17 -0
  127. package/dist/lib/promise-protected-resolver.js +791 -0
  128. package/dist/lib/promise-protected-resolver.js.map +1 -0
  129. package/dist/lib/retry-utils/index.cjs +2183 -0
  130. package/dist/lib/retry-utils/index.cjs.map +1 -0
  131. package/dist/lib/retry-utils/index.d.cts +321 -0
  132. package/dist/lib/retry-utils/index.d.ts +321 -0
  133. package/dist/lib/retry-utils/index.js +2133 -0
  134. package/dist/lib/retry-utils/index.js.map +1 -0
  135. package/dist/lib/safe-handle-callback.cjs +818 -0
  136. package/dist/lib/safe-handle-callback.cjs.map +1 -0
  137. package/dist/lib/safe-handle-callback.d.cts +43 -0
  138. package/dist/lib/safe-handle-callback.d.ts +43 -0
  139. package/dist/lib/safe-handle-callback.js +780 -0
  140. package/dist/lib/safe-handle-callback.js.map +1 -0
  141. package/dist/lib/serialize-error/index.cjs +93 -0
  142. package/dist/lib/serialize-error/index.cjs.map +1 -0
  143. package/dist/lib/serialize-error/index.d.cts +26 -0
  144. package/dist/lib/serialize-error/index.d.ts +26 -0
  145. package/dist/lib/serialize-error/index.js +64 -0
  146. package/dist/lib/serialize-error/index.js.map +1 -0
  147. package/dist/lib/single-event-observer.cjs +841 -0
  148. package/dist/lib/single-event-observer.cjs.map +1 -0
  149. package/dist/lib/single-event-observer.d.cts +54 -0
  150. package/dist/lib/single-event-observer.d.ts +54 -0
  151. package/dist/lib/single-event-observer.js +803 -0
  152. package/dist/lib/single-event-observer.js.map +1 -0
  153. package/dist/lib/sleep.cjs +37 -0
  154. package/dist/lib/sleep.cjs.map +1 -0
  155. package/dist/lib/sleep.d.cts +11 -0
  156. package/dist/lib/sleep.d.ts +11 -0
  157. package/dist/lib/sleep.js +12 -0
  158. package/dist/lib/sleep.js.map +1 -0
  159. package/dist/lib/strings.cjs +186 -0
  160. package/dist/lib/strings.cjs.map +1 -0
  161. package/dist/lib/strings.d.cts +107 -0
  162. package/dist/lib/strings.d.ts +107 -0
  163. package/dist/lib/strings.js +149 -0
  164. package/dist/lib/strings.js.map +1 -0
  165. package/dist/lib/tmp-dir.cjs +254 -0
  166. package/dist/lib/tmp-dir.cjs.map +1 -0
  167. package/dist/lib/tmp-dir.d.cts +63 -0
  168. package/dist/lib/tmp-dir.d.ts +63 -0
  169. package/dist/lib/tmp-dir.js +211 -0
  170. package/dist/lib/tmp-dir.js.map +1 -0
  171. package/dist/lib/unix-time-helpers.cjs +53 -0
  172. package/dist/lib/unix-time-helpers.cjs.map +1 -0
  173. package/dist/lib/unix-time-helpers.d.cts +56 -0
  174. package/dist/lib/unix-time-helpers.d.ts +56 -0
  175. package/dist/lib/unix-time-helpers.js +24 -0
  176. package/dist/lib/unix-time-helpers.js.map +1 -0
  177. package/package.json +220 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/strings.ts","../../../src/lib/retry-utils/lib/retry-utils-errors.ts","../../../src/lib/clamp.ts","../../../src/lib/retry-utils/lib/utils.ts","../../../src/lib/retry-utils/lib/retry-policy.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/error-to-string.ts","../../../src/lib/is-promise.ts","../../../src/lib/is-function.ts","../../../src/lib/safe-handle-callback.ts","../../../src/lib/promise-protected-resolver.ts","../../../src/lib/id-helpers.ts","../../../src/lib/unix-time-helpers.ts","../../../src/lib/is-plain-object.ts","../../../src/lib/event-emitter.ts","../../../src/lib/retry-utils/lib/retry-runner.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","/**\n * Simple error classes for retry-utils\n * Following the pattern from FileSinkError\n */\n\nexport class RetryUtilsErrPolicyConfigInvalidStrategy extends Error {\n constructor(\n public strategyProvided: string,\n public validStrategies: string[],\n ) {\n super('Invalid strategy provided.');\n this.name = 'RetryUtilsErrPolicyConfigInvalidStrategy';\n }\n}\n\nexport class RetryUtilsErrRunnerAlreadyCompleted extends Error {\n constructor(public invokedMethod: 'run' | 'resume' | 'forceTry') {\n super(\n 'The runner has already completed running the operation. Use the .reset() method, and .run() to run the operation again.',\n );\n this.name = 'RetryUtilsErrRunnerAlreadyCompleted';\n }\n}\n\nexport class RetryUtilsErrRunnerAlreadyRunning extends Error {\n constructor(public invokedMethod: 'run' | 'resume') {\n super('The operation is already running and cannot be started again.');\n this.name = 'RetryUtilsErrRunnerAlreadyRunning';\n }\n}\n\nexport class RetryUtilsErrRunnerForceTryRetryInProgress extends Error {\n constructor(public invokedMethod: 'forceTry') {\n super('Force try retry is already in progress.');\n this.name = 'RetryUtilsErrRunnerForceTryRetryInProgress';\n }\n}\n\nexport class RetryUtilsErrRunnerNotPaused extends Error {\n constructor(public invokedMethod: 'resume') {\n super(\n 'The runner is not in a paused state. resume() can only be called when the runner state is stopped.',\n );\n this.name = 'RetryUtilsErrRunnerNotPaused';\n }\n}\n\nexport class RetryUtilsErrRunnerCancelPending extends Error {\n constructor(public invokedMethod: 'run' | 'resume') {\n super(\n 'A cancel operation is pending. The operation cannot be started again.',\n );\n this.name = 'RetryUtilsErrRunnerCancelPending';\n }\n}\n\nexport class RetryUtilsErrRunnerRetryCanceled extends Error {\n constructor(public invokedMethod: 'run') {\n super(\n 'The operation was already canceled. Use either .resume(), .forceTry() or .reset() and .run() to run the operation again.',\n );\n this.name = 'RetryUtilsErrRunnerRetryCanceled';\n }\n}\n\nexport class RetryUtilsErrRunnerLastRetryFatallyFailed extends Error {\n constructor(public invokedMethod: 'run' | 'resume') {\n super(\n 'The last retry attempt failed fatally. The operation cannot be retried. Use either .reset() then .run() or .forceTry() to run the operation again.',\n );\n this.name = 'RetryUtilsErrRunnerLastRetryFatallyFailed';\n }\n}\n\nexport class RetryUtilsErrRunnerAttemptsExhausted extends Error {\n constructor(public invokedMethod: 'run' | 'resume') {\n super(\n 'All attempts were exhausted. The operation cannot be retried. Use either .reset() then .run() or .forceTry() to run the operation again.',\n );\n this.name = 'RetryUtilsErrRunnerAttemptsExhausted';\n }\n}\n\nexport class RetryUtilsErrRunnerLockAcquisitionError extends Error {\n constructor(public invokedMethod: 'run' | 'resume' | 'forceTry') {\n super(\n 'Failed to acquire operation lock. Cannot attempt to run the operation.',\n );\n this.name = 'RetryUtilsErrRunnerLockAcquisitionError';\n }\n}\n\nexport class RetryUtilsErrRunnerUnexpectedError extends Error {\n constructor(\n public invokedMethod: 'run' | 'resume' | 'forceTry',\n public originalError: Error,\n ) {\n super('An unexpected error occurred.');\n this.name = 'RetryUtilsErrRunnerUnexpectedError';\n }\n}\n\nexport class RetryUtilsErrRunnerUnknownState extends Error {\n constructor(\n public invokedMethod: 'waitForCompletion',\n public runnerState: string,\n ) {\n super('An unknown runner state was encountered.');\n this.name = 'RetryUtilsErrRunnerUnknownState';\n }\n}\n\nexport class RetryUtilsErrRunnerNotRunning extends Error {\n constructor(public invokedMethod: 'waitForCompletion') {\n super('The operation is not currently running.');\n this.name = 'RetryUtilsErrRunnerNotRunning';\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 { clamp } from '../../clamp';\n\ninterface ExponentialDelayParams {\n retryCount: number;\n minTimeoutMS: number;\n maxTimeoutMS: number;\n factor: number;\n dispersion: number;\n // Provide a function for randomness to make testing easier\n randomFn: () => number;\n}\n\nexport function calculateExponentialDelay({\n retryCount,\n minTimeoutMS,\n maxTimeoutMS,\n factor,\n dispersion,\n randomFn,\n}: ExponentialDelayParams): number {\n let delay = minTimeoutMS * Math.pow(factor, retryCount);\n\n if (dispersion > 0) {\n const dispersionAmount = delay * dispersion;\n // Apply dispersion jitter using the documented formula:\n // randomOffset = (Math.random() * 2 - 1) * (delay * dispersion)\n // Algebraically equivalent to: Math.random() * (dispersionAmount * 2) - dispersionAmount\n delay += randomFn() * (dispersionAmount * 2) - dispersionAmount;\n }\n\n // Use a clamp function to simplify bounds checking\n return clamp(delay, minTimeoutMS, maxTimeoutMS);\n}\n\n/**\n * Extracts a string message from an error value for grouping purposes.\n */\nfunction extractErrorMessage(error: unknown): string {\n // Check if it's an Error instance (most common case)\n if (error instanceof Error) {\n return error.message;\n }\n\n // Check if it's an object with a 'message' property\n if (\n error !== null &&\n error !== undefined &&\n typeof error === 'object' &&\n 'message' in error &&\n typeof (error as { message: unknown }).message === 'string'\n ) {\n return (error as { message: string }).message;\n }\n\n // Check if it's an object with an 'error' property (nested error)\n if (\n error !== null &&\n error !== undefined &&\n typeof error === 'object' &&\n 'error' in error\n ) {\n const nested = (error as { error: unknown }).error;\n\n if (nested instanceof Error) {\n return nested.message;\n } else if (\n nested !== null &&\n nested !== undefined &&\n typeof nested === 'object' &&\n 'message' in nested &&\n typeof (nested as { message: unknown }).message === 'string'\n ) {\n return (nested as { message: string }).message;\n } else {\n return String(nested);\n }\n }\n\n // Fall back to string conversion\n return String(error);\n}\n\nexport function getMostCommonError(errors: unknown[]): unknown {\n if (errors.length === 0) {\n return null;\n }\n\n // Strategy 1: Count by reference equality (===).\n // Handles reused error objects and guards against unstable message extraction.\n const refCounts = new Map<unknown, number>();\n\n for (const error of errors) {\n refCounts.set(error, (refCounts.get(error) ?? 0) + 1);\n }\n\n // Strategy 2: Count by extracted message string.\n // Groups distinct error objects that represent the same logical error.\n const messageCounts = new Map<string, { count: number; error: unknown }>();\n\n for (const error of errors) {\n const message = extractErrorMessage(error);\n const existing = messageCounts.get(message);\n\n if (existing) {\n existing.count += 1;\n } else {\n messageCounts.set(message, { count: 1, error });\n }\n }\n\n // Pick the winner across both strategies (highest count wins).\n let mostCommon: unknown = null;\n let maxCount = 0;\n\n for (const [error, count] of refCounts) {\n if (count > maxCount) {\n maxCount = count;\n mostCommon = error;\n }\n }\n\n for (const { count, error } of messageCounts.values()) {\n if (count > maxCount) {\n maxCount = count;\n mostCommon = error;\n }\n }\n\n return mostCommon;\n}\n","import { isString } from '../../strings';\nimport { RetryUtilsErrPolicyConfigInvalidStrategy } from './retry-utils-errors';\nimport type {\n RetryPolicyOptions,\n RetryPolicyValidated,\n RetryQueryResult,\n} from './types';\nimport { clamp } from '../../clamp';\nimport { calculateExponentialDelay, getMostCommonError } from './utils';\n\ninterface CurrentState {\n wasInitialAttemptTaken: boolean; // Represents if the initial attempt was taken or not since if errors is empty, it should return 1\n wasSuccessful: boolean;\n errors: unknown[];\n mostCommonErrorCached: {\n has: boolean;\n value: unknown;\n };\n}\n\nexport class RetryPolicy {\n private policy!: RetryPolicyValidated;\n private currentState: CurrentState = this.getEmptyCurrentState();\n\n /**\n * Gets the validated policy information for this retry policy instance.\n * @returns {RetryPolicyValidated} The current retry policy settings.\n */\n\n public get policyInfo(): RetryPolicyValidated {\n return this.policy;\n }\n\n /**\n * Gets the total number of attempts made, including the initial attempt and any retries.\n * @returns {number} The total number of attempts.\n */\n\n public get attempts(): number {\n if (this.currentState.wasSuccessful) {\n // When successful, include the initial attempt in the total.\n return this.currentState.errors.length + 1;\n } else {\n // When not successful, clamp to ensure at least 1 once the initial attempt was taken.\n return clamp(\n this.currentState.errors.length,\n this.wasInitialAttemptTaken ? 1 : 0,\n Infinity,\n );\n }\n }\n\n /**\n * Checks if the initial attempt has been taken.\n */\n\n public get wasInitialAttemptTaken(): boolean {\n return this.currentState.wasInitialAttemptTaken;\n }\n\n /**\n * Checks if the last operation attempt was successful. (used to calculate the number of attempts made)\n */\n\n public get wasSuccessful(): boolean {\n return this.currentState.wasSuccessful;\n }\n\n /**\n * Gets the maximum number of retry attempts allowed by the current policy.\n * @returns {number} The maximum number of retry attempts.\n */\n\n public get maxRetryAttempts(): number {\n return this.policy.maxRetryAttempts;\n }\n\n /**\n * Gets the number of retry attempts made, excluding the initial attempt.\n * @returns {number} The number of retries.\n */\n\n public get retryCount(): number {\n // Retry count is always attempts minus the initial attempt,\n // but only once the initial attempt has been taken.\n if (!this.wasInitialAttemptTaken) {\n return 0;\n }\n\n return Math.max(this.attempts - 1, 0);\n }\n\n /**\n * Checks if the retry attempts have been exhausted.\n * @returns {boolean} True if the number of retries has reached the maximum allowed attempts; otherwise, false.\n */\n\n public get areAttemptsExhausted(): boolean {\n return this.retryCount >= this.maxRetryAttempts;\n }\n\n /**\n * Gets a list of errors recorded from each retry attempt.\n * @returns {unknown[]} An array of errors encountered during retry attempts.\n */\n\n public get errors(): unknown[] {\n return [...this.currentState.errors];\n }\n\n /**\n * Gets the most common error encountered across all retry attempts.\n *\n * This method caches the most common error for performance. If the cache is invalidated due to a new error,\n * it recalculates the most common error.\n *\n * @returns {unknown} The most common error, or null if no errors have been encountered.\n */\n\n public get mostCommonError(): unknown {\n if (this.currentState.mostCommonErrorCached.has) {\n return this.currentState.mostCommonErrorCached.value;\n } else {\n const mostCommon = getMostCommonError(this.currentState.errors);\n\n this.currentState.mostCommonErrorCached.has = true;\n this.currentState.mostCommonErrorCached.value = mostCommon;\n\n return mostCommon;\n }\n }\n\n /**\n * Gets the last error encountered during the retry attempts.\n * @returns {unknown} The last error encountered, or null if no errors have been recorded.\n */\n\n public get lastError(): unknown {\n if (this.currentState.errors.length === 0) {\n return null;\n } else {\n return this.currentState.errors[this.currentState.errors.length - 1];\n }\n }\n\n /**\n * Constructs a RetryPolicy instance with specified options.\n *\n * @param {RetryPolicyOptions} policy The retry policy options, including strategy, maximum retry attempts,\n * and other parameters specific to the fixed or exponential strategy.\n *\n * Throws an error if an invalid retry strategy is provided.\n */\n\n constructor(policy: RetryPolicyOptions) {\n const DEFAULT_MAX_RETRY_ATTEMPTS = 10;\n const DEFAULT_FACTOR = 1.5;\n const DEFAULT_MIN_TIMEOUT_MS = 1000;\n const DEFAULT_MAX_TIMEOUT_MS = 30000;\n const DEFAULT_DISPERSION = 0.1;\n\n if (policy.strategy === 'fixed') {\n this.policy = {\n strategy: 'fixed',\n maxRetryAttempts: Math.floor(\n clamp(\n policy.maxRetryAttempts ?? DEFAULT_MAX_RETRY_ATTEMPTS,\n 1,\n Infinity,\n ),\n ),\n delayMS: clamp(policy.delayMS ?? DEFAULT_MIN_TIMEOUT_MS, 1, Infinity),\n };\n } else if (policy.strategy === 'exponential') {\n const minTimeoutMS = clamp(\n policy.minTimeoutMS ?? DEFAULT_MIN_TIMEOUT_MS,\n 1,\n Infinity,\n );\n const maxTimeoutMS = clamp(\n policy.maxTimeoutMS ?? DEFAULT_MAX_TIMEOUT_MS,\n 1,\n Infinity,\n );\n\n // Ensure maxTimeoutMS >= minTimeoutMS by swapping if needed\n const finalMin = Math.min(minTimeoutMS, maxTimeoutMS);\n const finalMax = Math.max(minTimeoutMS, maxTimeoutMS);\n\n this.policy = {\n strategy: 'exponential',\n maxRetryAttempts: Math.floor(\n clamp(\n policy.maxRetryAttempts ?? DEFAULT_MAX_RETRY_ATTEMPTS,\n 1,\n Infinity,\n ),\n ),\n factor: clamp(policy.factor ?? DEFAULT_FACTOR, 1, Infinity),\n minTimeoutMS: finalMin,\n maxTimeoutMS: finalMax,\n dispersion: clamp(policy.dispersion ?? DEFAULT_DISPERSION, 0, 1),\n };\n } else {\n throw new RetryUtilsErrPolicyConfigInvalidStrategy(\n isString(policy['strategy']) ? policy['strategy'] : 'unknown',\n ['fixed', 'exponential'],\n );\n }\n }\n\n /**\n * Resets the retry policy to its initial state.\n *\n * This method clears all recorded errors and marks the initial attempt as not taken,\n * effectively resetting the state of the retry policy for a new operation.\n */\n\n public reset(): void {\n this.currentState = this.getEmptyCurrentState();\n }\n\n /**\n * Determines if the initial operation attempt should proceed.\n *\n * This method checks if the initial attempt has already been taken and updates the state to reflect that\n * the initial attempt is now being made. This method is used to ensure that the retry logic only kicks in after\n * the first attempt has failed.\n *\n * Note that even upon success, you should call the reset method to clear the state for the next operation.\n *\n * @returns {boolean} True if the initial attempt has not been made yet; otherwise, false.\n */\n\n public shouldDoFirstTry(): boolean {\n if (this.currentState.wasInitialAttemptTaken) {\n return false;\n } else {\n this.currentState.wasInitialAttemptTaken = true; // Mark the initial attempt as taken.\n\n return true;\n }\n }\n\n /**\n * Marks the last operation attempt as successful.\n */\n\n public markAsSuccessful(): void {\n this.currentState.wasSuccessful = true;\n }\n\n /**\n * Records an error that occurred during the last operation attempt.\n *\n * Does not check if was successful or not, nor checks if should retry or not.\n */\n\n public reportError(error: unknown): void {\n this.currentState.errors.push(error);\n\n // Invalidate the mostCommonError cache\n this.currentState.mostCommonErrorCached.has = false;\n }\n\n /**\n * Determines if a retry should be made based on the current state and the provided error.\n *\n * When called, this method stores the provided error, checks if further retries are allowed based on the\n * maximum retry attempts, and calculates the delay for the next retry if applicable.\n *\n * It also invalidates the cached most common error since the error state has changed.\n *\n * @param {unknown} error The error that resulted from the last operation attempt. Can be omitted when `isQueryOnly` is `true`.\n * @param {boolean} isQueryOnly If true, the method only queries if a retry should be made without storing the error.\n * @returns {RetryQueryResult} An object indicating whether a retry should be attempted and the delay before the next attempt.\n */\n\n public shouldRetry(\n error?: unknown,\n isQueryOnly: boolean = false,\n ): RetryQueryResult {\n if (this.currentState.wasSuccessful) {\n if (!isQueryOnly) {\n // push the error into the errors array anyways if it was not a query only\n this.reportError(error);\n }\n\n // Once successful, retries are never allowed.\n return { shouldRetry: false, delayMS: 0 };\n }\n\n if (!isQueryOnly) {\n // push the error into the errors array\n this.reportError(error);\n }\n\n // Decide if we should retry - check if we've exhausted our retry attempts\n if (this.areAttemptsExhausted) {\n return { shouldRetry: false, delayMS: 0 };\n } else {\n // Calculate the delay for the next retry attempt\n const delayMS = this.calculateNextDelay();\n\n return { shouldRetry: true, delayMS };\n }\n }\n\n /**\n * Returning a fresh copy of the current state\n * to be immutable and not changed by the caller\n */\n\n private getEmptyCurrentState(): CurrentState {\n return {\n wasInitialAttemptTaken: false,\n wasSuccessful: false,\n errors: [],\n mostCommonErrorCached: {\n has: false,\n value: null,\n },\n };\n }\n\n /**\n * Calculates the delay before the next retry attempt based on the current retry policy.\n *\n * For a fixed strategy, it returns the specified delay. For an exponential strategy, it calculates the delay\n * based on the exponential backoff formula, considering the number of retry attempts, the base delay,\n * the exponential factor, and any specified dispersion to introduce randomness.\n *\n * @returns {number} The calculated delay in milliseconds before the next retry attempt.\n */\n\n private calculateNextDelay(): number {\n if (this.policy.strategy === 'fixed') {\n return this.policy.delayMS;\n } else if (this.policy.strategy === 'exponential') {\n return calculateExponentialDelay({\n retryCount: this.retryCount,\n minTimeoutMS: this.policy.minTimeoutMS,\n maxTimeoutMS: this.policy.maxTimeoutMS,\n factor: this.policy.factor,\n dispersion: this.policy.dispersion,\n randomFn: Math.random,\n });\n }\n\n return 1; // Should never reach here\n }\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","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","import { safeHandleCallback } from './safe-handle-callback';\n\ninterface PromiseProtectedResolverOptions {\n beforeResolveOrReject?: (\n action: 'resolve' | 'reject',\n valueOrReason: unknown,\n ) => void | Promise<void>;\n}\n\nexport class PromiseProtectedResolver<T> {\n public promise: Promise<T>;\n\n public get hasResolved(): boolean {\n return this._hasResolved;\n }\n\n private _hasResolved = false;\n private resolveHandler: ((value: T | PromiseLike<T>) => void) | undefined;\n private rejectHandler: ((reason?: unknown) => void) | undefined;\n private options: PromiseProtectedResolverOptions;\n\n constructor(options: PromiseProtectedResolverOptions = {}) {\n this.options = options;\n this.promise = new Promise<T>((resolve, reject) => {\n this.resolveHandler = resolve;\n this.rejectHandler = reject;\n });\n }\n\n public resolveOnce(value: T): void {\n if (!this._hasResolved && this.resolveHandler) {\n this.executeBeforeCallback('resolve', value);\n this._hasResolved = true;\n this.resolveHandler(value);\n }\n }\n\n public rejectOnce(reason?: unknown): void {\n if (!this._hasResolved && this.rejectHandler) {\n this.executeBeforeCallback('reject', reason);\n this._hasResolved = true;\n this.rejectHandler(reason);\n }\n }\n\n private executeBeforeCallback(\n action: 'resolve' | 'reject',\n valueOrReason: unknown,\n ): void {\n if (this.options.beforeResolveOrReject) {\n safeHandleCallback(\n 'beforeResolveOrReject',\n this.options.beforeResolveOrReject,\n action,\n valueOrReason,\n );\n }\n }\n}\n","import ObjectID from 'bson-objectid';\nimport {\n v4 as UUIDv4,\n v7 as UUIDv7,\n validate as uuidValidate,\n version as uuidVersion,\n} from 'uuid';\nimport { ulid } from 'ulid';\nimport { convertMSToUnix } from './unix-time-helpers';\n\n/**\n * Supported identifier types:\n *\n * - **`objectID`**: MongoDB-style ObjectID\n * - Format: 24 hexadecimal characters\n * - Timestamp-based: Yes (sortable by creation time)\n * - Case-sensitive: No (accepts both uppercase and lowercase)\n * - Example: `\"507f1f77bcf86cd799439011\"`\n *\n * - **`uuid4`**: UUID version 4\n * - Format: 36 characters (32 hex + 4 dashes): `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`\n * - Timestamp-based: No (random)\n * - Case-sensitive: No (accepts both uppercase and lowercase)\n * - Example: `\"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d\"`\n *\n * - **`uuid7`**: UUID version 7\n * - Format: 36 characters (32 hex + 4 dashes): `xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx`\n * - Timestamp-based: Yes (sortable by creation time)\n * - Case-sensitive: No (accepts both uppercase and lowercase)\n * - Example: `\"018e8c6e-4f7e-7000-8000-0123456789ab\"`\n *\n * - **`ulid`**: Universally Unique Lexicographically Sortable Identifier\n * - Format: 26 characters using Crockford's base32 alphabet\n * - Timestamp-based: Yes (sortable by creation time)\n * - Case-sensitive: No (canonical form is uppercase, but accepts lowercase)\n * - Example: `\"01ARZ3NDEKTSV4RRFFQ69G5FAV\"`\n */\nexport type IdentifierType = 'objectID' | 'uuid4' | 'uuid7' | 'ulid';\n\n/**\n * Array of all supported identifier types.\n */\nexport const IDENTIFIER_TYPES = ['objectID', 'uuid4', 'uuid7', 'ulid'] as const;\n\nfunction assertIdentifierType(type: unknown): asserts type is IdentifierType {\n if (!IDENTIFIER_TYPES.includes(type as IdentifierType)) {\n throw new TypeError(\n `Invalid ID type given: \"${type as string}\". Expected one of: ${IDENTIFIER_TYPES.join(', ')}`,\n );\n }\n}\n\n/**\n * Generates a unique identifier of the specified type.\n *\n * @param type - The type of identifier to generate:\n * - `objectID`: MongoDB ObjectID (24 hex chars, timestamp-based)\n * - `uuid4`: UUID v4 (random, not sortable)\n * - `uuid7`: UUID v7 (timestamp-based, sortable)\n * - `ulid`: ULID (timestamp-based, sortable, case-insensitive)\n * @param seedTime - Optional timestamp in milliseconds to seed the ID with.\n * - Supported by: `objectID`, `uuid7`, `ulid`\n * - Ignored by: `uuid4` (always random)\n * - Use this for testing or when you need IDs to have a specific timestamp\n * @returns A unique identifier string\n * @throws {TypeError} If an invalid type is provided\n * @throws {TypeError} If `seedTime` is provided but is not a non-negative finite number\n *\n * @example\n * ```typescript\n * // Generate random IDs\n * const objId = generateID('objectID'); // \"507f1f77bcf86cd799439011\"\n * const uuid4 = generateID('uuid4'); // \"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d\"\n * const uuid7 = generateID('uuid7'); // \"018e8c6e-4f7e-7000-8000-0123456789ab\"\n * const ulid = generateID('ulid'); // \"01ARZ3NDEKTSV4RRFFQ69G5FAV\"\n *\n * // Generate IDs with a specific timestamp\n * const timestamp = Date.now();\n * const seededId = generateID('uuid7', timestamp);\n * ```\n */\nexport function generateID(type: IdentifierType, seedTime?: number): string {\n assertIdentifierType(type);\n\n if (seedTime !== undefined && (!Number.isFinite(seedTime) || seedTime < 0)) {\n throw new TypeError(\n `seedTime must be a non-negative finite number (milliseconds), got: ${seedTime}`,\n );\n }\n\n if (type === 'objectID') {\n if (seedTime !== undefined) {\n // expects as unix time\n const unixTime = convertMSToUnix(seedTime);\n\n return new ObjectID(unixTime).toHexString();\n } else {\n return new ObjectID().toHexString();\n }\n } else if (type === 'uuid4') {\n return UUIDv4();\n } else if (type === 'uuid7') {\n if (seedTime !== undefined) {\n // expect in milliseconds\n return UUIDv7({ msecs: seedTime });\n } else {\n return UUIDv7();\n }\n } else if (type === 'ulid') {\n if (seedTime !== undefined) {\n // expect in milliseconds\n return ulid(seedTime);\n } else {\n return ulid();\n }\n } else {\n throw new TypeError(`Unhandled identifier type: \"${type as string}\"`);\n }\n}\n\n/**\n * Validates that a string is a valid identifier of the specified type.\n *\n * Performs strict validation:\n * - `objectID`: Must be 24 hexadecimal characters\n * - `uuid4`: Must be a valid UUID with version 4\n * - `uuid7`: Must be a valid UUID with version 7\n * - `ulid`: Must be 26 characters from the ULID character set\n *\n * Empty IDs (from `emptyID()`) are considered valid.\n * Non-string `id` values return `false`.\n *\n * @param type - The expected identifier type\n * @param id - The identifier string to validate\n * @returns `true` if the ID is valid for the specified type, `false` otherwise\n * @throws {TypeError} If an invalid type is provided\n *\n * @example\n * ```typescript\n * validateID('uuid4', '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'); // true\n * validateID('uuid4', '018e8c6e-4f7e-7000-8000-0123456789ab'); // false (this is uuid7)\n * validateID('objectID', '507f1f77bcf86cd799439011'); // true\n * validateID('objectID', 'invalid'); // false\n * ```\n */\nexport function validateID(type: IdentifierType, id: string): boolean {\n assertIdentifierType(type);\n\n if (typeof id !== 'string') {\n return false;\n }\n\n if (type === 'objectID') {\n if (id.match(/^[0-9a-fA-F]{24}$/)) {\n return true;\n } else {\n return false;\n }\n } else if (type === 'uuid4' || type === 'uuid7') {\n // Check if it's the empty ID first\n if (isEmptyID(type, id)) {\n return true;\n }\n\n const isValid = uuidValidate(id);\n if (!isValid) {\n return false;\n }\n\n // Check the specific UUID version\n const version = uuidVersion(id);\n if (type === 'uuid4' && version === 4) {\n return true;\n } else if (type === 'uuid7' && version === 7) {\n return true;\n } else {\n return false;\n }\n } else if (type === 'ulid') {\n if (id.match(/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i)) {\n return true;\n } else {\n return false;\n }\n } else {\n throw new TypeError(`Unhandled identifier type: \"${type as string}\"`);\n }\n}\n\n/**\n * Returns an empty/null identifier for the specified type.\n *\n * Empty IDs are valid IDs (pass `validateID()`) but represent a null/empty state.\n * Useful as default values or placeholders in databases.\n *\n * Empty ID formats:\n * - `objectID`: `\"000000000000000000000000\"` (24 zeros)\n * - `uuid4`: `\"00000000-0000-0000-0000-000000000000\"` (nil UUID)\n * - `uuid7`: `\"00000000-0000-0000-0000-000000000000\"` (nil UUID)\n * - `ulid`: `\"00000000000000000000000000\"` (26 zeros)\n *\n * @param type - The type of empty identifier to generate\n * @returns An empty identifier string\n * @throws {TypeError} If an invalid type is provided\n *\n * @example\n * ```typescript\n * const emptyUuid = emptyID('uuid4'); // \"00000000-0000-0000-0000-000000000000\"\n * validateID('uuid4', emptyUuid); // true\n * isEmptyID('uuid4', emptyUuid); // true\n * ```\n */\nexport function emptyID(type: IdentifierType): string {\n assertIdentifierType(type);\n\n if (type === 'objectID') {\n return '0'.repeat(24);\n } else if (type === 'uuid4' || type === 'uuid7') {\n return '00000000-0000-0000-0000-000000000000';\n } else if (type === 'ulid') {\n return '0'.repeat(26);\n } else {\n throw new TypeError(`Unhandled identifier type: \"${type as string}\"`);\n }\n}\n\n/**\n * Checks if an identifier is an empty/null ID.\n *\n * Compares the provided ID against the empty ID for the specified type.\n * This is useful for checking if an ID represents a null/empty state.\n *\n * @param type - The identifier type to check against\n * @param id - The identifier string to check\n * @returns `true` if the ID is empty for the specified type, `false` otherwise.\n * Non-string `id` values return `false`.\n * @throws {TypeError} If an invalid type is provided\n *\n * @example\n * ```typescript\n * const emptyUuid = emptyID('uuid4');\n * const realUuid = generateID('uuid4');\n *\n * isEmptyID('uuid4', emptyUuid); // true\n * isEmptyID('uuid4', realUuid); // false\n * ```\n */\nexport function isEmptyID(type: IdentifierType, id: string): boolean {\n assertIdentifierType(type);\n\n if (typeof id !== 'string') {\n return false;\n }\n\n return emptyID(type) === id;\n}\n\n/**\n * Helper class for working with identifiers of a specific type.\n *\n * This class provides a convenient way to work with IDs without repeatedly\n * specifying the type parameter. Initialize it with your preferred ID type,\n * then use its methods without passing the type each time.\n *\n * @example\n * ```typescript\n * // Create a helper for UUID v7 identifiers\n * const idHelper = new IDHelpers('uuid7');\n *\n * // Generate IDs without specifying type each time\n * const id1 = idHelper.generateID();\n * const id2 = idHelper.generateID(Date.now());\n *\n * // Validate IDs\n * if (idHelper.validateID(someId)) {\n * console.log('Valid uuid7');\n * }\n *\n * // Check for empty IDs\n * const empty = idHelper.emptyID();\n * console.log(idHelper.isEmptyID(empty)); // true\n * ```\n */\nexport class IDHelpers {\n private _type: IdentifierType;\n\n /**\n * Gets the identifier type this helper is configured for.\n */\n public get type(): IdentifierType {\n return this._type;\n }\n\n /**\n * Creates a new ID helper for the specified type.\n * @param type - The identifier type to use for all operations\n * @throws {TypeError} If an invalid type is provided\n */\n constructor(type: IdentifierType) {\n assertIdentifierType(type);\n this._type = type;\n }\n\n /**\n * Generates a new identifier using the configured type.\n * @param seedTime - Optional timestamp in milliseconds to seed the ID with\n * @returns A unique identifier string\n */\n public generateID(seedTime?: number): string {\n return generateID(this._type, seedTime);\n }\n\n /**\n * Validates an identifier against the configured type.\n * @param id - The identifier string to validate\n * @returns `true` if valid, `false` otherwise\n */\n public validateID(id: string): boolean {\n return validateID(this._type, id);\n }\n\n /**\n * Returns an empty identifier for the configured type.\n * @returns An empty identifier string\n */\n public emptyID(): string {\n return emptyID(this._type);\n }\n\n /**\n * Checks if an identifier is empty for the configured type.\n * @param id - The identifier string to check\n * @returns `true` if empty, `false` otherwise\n */\n public isEmptyID(id: string): boolean {\n return isEmptyID(this._type, id);\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","/**\n * Type guard to check if a value is a plain object (not null, not an array).\n *\n * @param value - Value to check\n * @returns `true` if the value is a plain object, `false` otherwise\n *\n * @example\n * ```typescript\n * isPlainObject({}); // true\n * isPlainObject({ a: 1 }); // true\n * isPlainObject([]); // false\n * isPlainObject(null); // false\n * isPlainObject(undefined); // false\n * isPlainObject('string'); // false\n * isPlainObject(42); // false\n * ```\n */\nexport function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\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","import { PromiseProtectedResolver } from '../../promise-protected-resolver';\nimport { generateID } from '../../id-helpers';\nimport { isPromise } from '../../is-promise';\nimport { isString } from '../../strings';\nimport { isPlainObject } from '../../is-plain-object';\nimport { isFunction } from '../../is-function';\nimport { RetryPolicy } from './retry-policy';\nimport type {\n RetryPolicyOptions,\n RetryPolicyValidated,\n RunAttemptStatusCodes,\n RunnerErrorCode,\n} from './types';\nimport {\n RetryUtilsErrRunnerAlreadyCompleted,\n RetryUtilsErrRunnerAlreadyRunning,\n RetryUtilsErrRunnerAttemptsExhausted,\n RetryUtilsErrRunnerCancelPending,\n RetryUtilsErrRunnerForceTryRetryInProgress,\n RetryUtilsErrRunnerLastRetryFatallyFailed,\n RetryUtilsErrRunnerLockAcquisitionError,\n RetryUtilsErrRunnerNotPaused,\n RetryUtilsErrRunnerNotRunning,\n RetryUtilsErrRunnerRetryCanceled,\n RetryUtilsErrRunnerUnexpectedError,\n RetryUtilsErrRunnerUnknownState,\n} from './retry-utils-errors';\nimport { EventEmitterProtected } from '../../event-emitter';\n\nexport type ReportResultStatus =\n // Was successful, no need to retry\n | 'success'\n // something went wrong, but it's not fatal, so retry if within the policy\n | 'error'\n // something went wrong, and it's fatal, so don't retry\n | 'fatal'\n // skip this attempt, like if offline and don't want to count it as a failure and reschedule the operation\n | 'skip';\n\nexport type ReportResult<T = unknown> = {\n (status: 'success', value?: T): void;\n (status: 'skip', value?: T): void;\n (status: 'error', value?: unknown): void;\n (status: 'fatal', value?: unknown): void;\n};\n\nexport interface RunResultSuccess<T> {\n status: 'attempt_success';\n data?: T;\n}\n\nexport interface RunResultNonSuccess {\n status: Exclude<RunAttemptStatusCodes, 'attempt_success'>;\n code?: RunnerErrorCode;\n error?: unknown;\n reattached?: boolean; // Only present when status is 'running' from forceTry()\n}\n\nexport type RunResult<T> = RunResultSuccess<T> | RunResultNonSuccess;\n\nexport type CancelResult = 'canceled' | 'forced' | 'not-running';\n\nclass AttemptContext {\n public handled = false;\n public id: string;\n public abortController: AbortController;\n public startTime: number;\n\n constructor() {\n this.id = generateID('ulid');\n this.abortController = new AbortController();\n this.startTime = Date.now();\n }\n}\n\nexport type OperationStartedType = 'initial' | 'resume' | 'force';\n\nexport interface OnOperationEndedInfo {\n runnerState: RunnerState;\n timeTakenMS: number;\n}\n\nexport interface OnOperationStartedInfo {\n operationType: OperationStartedType;\n}\n\nexport interface OnAttemptStartedInfo {\n attemptID: string;\n operationTimeElapsedMS: number;\n attemptTimeElapsedMS: number;\n}\n\nexport interface OnAttemptHandledInfo<T> {\n attemptID: string;\n status: ReportResultStatus;\n operationTimeElapsedMS: number;\n attemptTimeElapsedMS: number;\n data?: T;\n error?: unknown;\n wasCanceled: boolean;\n}\n\n// Event names\nexport const OPERATION_STARTED = 'operation-started';\nexport const OPERATION_ENDED = 'operation-ended';\nexport const ATTEMPT_STARTED = 'attempt-started';\nexport const ATTEMPT_HANDLED = 'attempt-handled';\n\nexport interface RetryRunnerOptions<T = unknown> {\n operationLabel?: string;\n onOperationStarted?: (info: OnOperationStartedInfo) => void;\n onOperationEnded?: (info: OnOperationEndedInfo) => void;\n onAttemptStarted?: (info: OnAttemptStartedInfo) => void;\n onAttemptHandled?: (info: OnAttemptHandledInfo<T>) => void;\n}\n\nexport interface ForceTryOptions {\n shouldWaitForCompletion?: boolean;\n shouldAbortRunning?: boolean;\n}\n\nexport type RunnerState =\n | 'not-started'\n | 'running'\n | 'stopping'\n | 'stopped'\n | 'completed'\n | 'exhausted'\n | 'fatal-error';\n\ninterface RetryRunnerCurrentState {\n // Mutable runtime state for the currently scheduled/active operation.\n runnerState: RunnerState;\n // Tracks if the last attempt was triggered by forceTry().\n lastAttemptWasForceTry: boolean;\n // Context for the currently running attempt (null if none).\n currentAttemptContext?: AttemptContext | null;\n // Timer handle for scheduled retry delays.\n retryTimeoutHandle: ReturnType<typeof setTimeout> | null;\n // Timestamp when the retry timeout was started.\n retryTimeoutStartTime: number | null;\n // Planned delay duration for the pending retry.\n retryTimeoutDelayMS: number | null;\n // Grace period timer for cancellation acknowledgment.\n cancellationTimeoutHandle: ReturnType<typeof setTimeout> | null;\n // Timestamp when the current operation started.\n operationStartTime: number | null;\n // Frozen time taken value for terminal states (null while running).\n finalTimeTakenMS: number | null;\n // Cached duration of the last completed attempt.\n lastAttemptTimeTakenMS: number;\n}\n\ninterface ConfirmCancellationResolveInfo<T> {\n status: RunAttemptStatusCodes | null;\n code?: RunnerErrorCode;\n data?: T;\n error?: unknown;\n}\n\nexport class RetryRunner<T = unknown> extends EventEmitterProtected {\n // Human-readable label for debugging/logging purposes.\n private _operationLabel = 'Unnamed Operation';\n // Retry policy that determines retry behavior and tracks state.\n private policy: RetryPolicy;\n // Prevents concurrent run/resume/forceTry calls.\n private _isOperationLocked = false;\n // Mutable runtime state for the current operation.\n private currentState: RetryRunnerCurrentState = this.getEmptyCurrentState();\n // Grace period for cancellation before we force-complete.\n private _gracePeriodMS = 1000;\n\n // User-provided operation to retry on failure.\n private operation: (\n reportResult: ReportResult<T>,\n signal: AbortSignal,\n ) => void | Promise<void>;\n\n // Resolver for the current run/resume/forceTry operation.\n private currentOperationResolver!: PromiseProtectedResolver<RunResult<T>>;\n // Resolvers for pending cancel() calls.\n private cancelResolvers = new Set<PromiseProtectedResolver<CancelResult>>();\n\n public get operationLabel(): string {\n return this._operationLabel;\n }\n\n public get runnerState(): RunnerState {\n return this.currentState.runnerState;\n }\n\n public get timeTakenMS(): number {\n if (this.currentState.finalTimeTakenMS !== null) {\n return this.currentState.finalTimeTakenMS;\n } else if (this.currentState.operationStartTime !== null) {\n return Date.now() - this.currentState.operationStartTime;\n }\n\n // -1 indicates the operation has not started.\n return -1;\n }\n\n public get attemptTimeTakenMS(): number {\n if (\n this.currentState.currentAttemptContext instanceof AttemptContext &&\n !this.currentState.currentAttemptContext.handled\n ) {\n return Date.now() - this.currentState.currentAttemptContext.startTime;\n }\n\n // Return the last completed attempt duration, or -1 if no attempt has run yet.\n return this.currentState.lastAttemptTimeTakenMS;\n }\n\n public get retryTimeRemaining(): number {\n if (\n this.currentState.retryTimeoutHandle !== null &&\n this.currentState.retryTimeoutStartTime !== null &&\n this.currentState.retryTimeoutDelayMS !== null\n ) {\n const elapsed = Date.now() - this.currentState.retryTimeoutStartTime;\n const remaining = this.currentState.retryTimeoutDelayMS - elapsed;\n // Clamp to 0 if elapsed time exceeded delay.\n return Math.max(0, remaining);\n } else {\n // -1 indicates no retry is pending.\n return -1;\n }\n }\n\n public get canForceTry(): boolean {\n return (\n this.currentState.runnerState === 'running' ||\n this.currentState.runnerState === 'exhausted' ||\n this.currentState.runnerState === 'fatal-error' ||\n this.currentState.runnerState === 'not-started' ||\n this.currentState.runnerState === 'stopping' ||\n this.currentState.runnerState === 'stopped'\n );\n }\n\n public get wasLastAttemptForced(): boolean {\n return this.currentState.lastAttemptWasForceTry;\n }\n\n public get errors(): unknown[] {\n return this.policy.errors;\n }\n\n public get wasInitialAttemptTaken(): boolean {\n return this.policy.wasInitialAttemptTaken;\n }\n\n public get areAttemptsExhausted(): boolean {\n return this.policy.areAttemptsExhausted;\n }\n\n public get attempts(): number {\n return this.policy.attempts;\n }\n\n public get mostCommonError(): unknown {\n return this.policy.mostCommonError;\n }\n\n public get lastError(): unknown {\n return this.policy.lastError;\n }\n\n public get maxRetryAttempts(): number {\n return this.policy.maxRetryAttempts;\n }\n\n public get policyInfo(): RetryPolicyValidated {\n return this.policy.policyInfo;\n }\n\n public get retryCount(): number {\n return this.policy.retryCount;\n }\n\n public get wasSuccessful(): boolean {\n return this.policy.wasSuccessful;\n }\n\n public get isRetryPending(): boolean {\n return this.currentState.retryTimeoutHandle !== null;\n }\n\n public get isOperationRunning(): boolean {\n return (\n this.currentState.runnerState === 'running' ||\n this.currentState.runnerState === 'stopping'\n );\n }\n\n public get isAttemptRunning(): boolean {\n if (this.currentState.currentAttemptContext instanceof AttemptContext) {\n return !this.currentState.currentAttemptContext.handled;\n } else {\n return false;\n }\n }\n\n public get graceCancelPeriodMS(): number {\n return this._gracePeriodMS;\n }\n\n constructor(\n policy: RetryPolicyOptions,\n operation: (\n reportResult: ReportResult<T>,\n signal: AbortSignal,\n ) => void | Promise<void>,\n options?: RetryRunnerOptions<T>,\n ) {\n super();\n\n this.policy = new RetryPolicy(policy);\n this.operation = operation;\n\n // Handle options\n if (isPlainObject(options)) {\n // set the operation label\n if (isString(options.operationLabel)) {\n this._operationLabel = options.operationLabel;\n }\n\n // subscribe the event handlers\n if (isFunction(options.onOperationStarted)) {\n // operation started\n this.on(\n OPERATION_STARTED,\n options.onOperationStarted as (data: unknown) => void,\n );\n }\n\n // operation ended\n if (isFunction(options.onOperationEnded)) {\n this.on(\n OPERATION_ENDED,\n options.onOperationEnded as (data: unknown) => void,\n );\n }\n\n // attempt started\n if (isFunction(options.onAttemptStarted)) {\n this.on(\n ATTEMPT_STARTED,\n options.onAttemptStarted as (data: unknown) => void,\n );\n }\n\n // attempt handled\n if (isFunction(options.onAttemptHandled)) {\n this.on(\n ATTEMPT_HANDLED,\n options.onAttemptHandled as (data: unknown) => void,\n );\n }\n }\n }\n\n /**\n * Set the grace period for cancellation in milliseconds\n *\n * Overrides the default grace period of 1000ms\n * Non-finite or negative values default to 1000ms. Use 0 for immediate force-cancel.\n */\n\n public overrideGraceCancelPeriodMS(value: number): void {\n if (!isFinite(value) || value < 0) {\n this._gracePeriodMS = 1000;\n } else {\n this._gracePeriodMS = value;\n }\n }\n\n public async waitForCompletion(): Promise<RunResult<T>> {\n switch (this.currentState.runnerState) {\n case 'completed':\n case 'exhausted':\n case 'fatal-error':\n case 'stopped':\n // If the operation has already completed, exhausted, encountered a fatal error, or was stopped,\n // return the last result\n return this.currentOperationResolver.promise;\n case 'running':\n case 'stopping':\n // If the operation is currently running or in the process of stopping, wait for it to complete\n return this.currentOperationResolver.promise;\n case 'not-started':\n // If the operation has not started yet, return an appropriate result\n return {\n status: 'not_started',\n code: 'not_running',\n error: new RetryUtilsErrRunnerNotRunning('waitForCompletion'),\n };\n default:\n throw new RetryUtilsErrRunnerUnknownState(\n 'waitForCompletion',\n this.currentState.runnerState,\n );\n }\n }\n\n public async run(shouldWaitForCompletion = false): Promise<RunResult<T>> {\n // Simple lock check\n if (this._isOperationLocked) {\n return {\n status: 'pre_operation_error',\n code: 'lock_error',\n error: new RetryUtilsErrRunnerLockAcquisitionError('run'),\n };\n }\n\n // Lock prevents concurrent run/resume/forceTry calls from stepping on each other.\n this._isOperationLocked = true;\n\n try {\n // check if in a disallowed state for this operation\n const checkDisallowedStates = this.checkForDisallowedPerOperationStates(\n 'run',\n [\n 'completed',\n 'running',\n 'stopping',\n 'stopped',\n 'fatal-error',\n 'exhausted',\n ],\n );\n\n if (\n checkDisallowedStates.wasDisallowed &&\n checkDisallowedStates.runResult\n ) {\n return checkDisallowedStates.runResult;\n } else if (this.policy.shouldDoFirstTry()) {\n this.currentState.runnerState = 'running';\n\n // Start timing\n this.currentState.operationStartTime = Date.now();\n this.currentState.finalTimeTakenMS = null;\n\n // emit the operation started event\n this.emit(OPERATION_STARTED, { operationType: 'initial' });\n\n // Create a new resolver for the current operation\n this.currentOperationResolver = new PromiseProtectedResolver<\n RunResult<T>\n >();\n\n // Start the initial operation\n void this.attemptOperation(false);\n\n if (shouldWaitForCompletion) {\n return this.currentOperationResolver.promise;\n } else {\n return { status: 'running' };\n }\n } else {\n return {\n status: 'pre_operation_error',\n code: 'unexpected_error',\n error: new RetryUtilsErrRunnerUnexpectedError(\n 'run',\n new Error(\n 'Not first try, but this should had been caught before this point',\n ),\n ),\n };\n }\n } catch (error) {\n // handle error unexpected when starting the operation\n return {\n status: 'pre_operation_error',\n code: 'unexpected_error',\n error: new RetryUtilsErrRunnerUnexpectedError('run', error as Error),\n };\n } finally {\n // Always release the lock.\n this._isOperationLocked = false;\n }\n }\n\n public async cancel(): Promise<CancelResult> {\n // operation is either running or stopping (so just wait to cancel it here)\n if (\n this.currentState.runnerState === 'running' ||\n this.currentState.runnerState === 'stopping'\n ) {\n const cancellationPromiseProtectedResolver =\n new PromiseProtectedResolver<CancelResult>();\n\n this.cancelResolvers.add(cancellationPromiseProtectedResolver);\n\n // Check if cancellation is already pending to avoid multiple abort signals\n if (this.currentState.runnerState !== 'stopping') {\n this.currentState.runnerState = 'stopping';\n\n this.cleanupTimers();\n\n if (\n !this.currentState.currentAttemptContext ||\n this.currentState.currentAttemptContext.handled\n ) {\n // No active attempt, can confirm immediately.\n this.confirmCancellation('stopped', {\n status: 'canceled',\n });\n } else {\n // Signal the running attempt to abort.\n this.currentState.currentAttemptContext.abortController.abort();\n\n // Grace period: if operation doesn't acknowledge abort, force it.\n this.currentState.cancellationTimeoutHandle = setTimeout(() => {\n if (\n this.currentState.currentAttemptContext instanceof\n AttemptContext &&\n !this.currentState.currentAttemptContext.handled\n ) {\n if (this.currentState.runnerState === 'stopping') {\n const context = this.currentState.currentAttemptContext;\n\n // Mark handled and detach the current context\n context.handled = true;\n this.currentState.currentAttemptContext = null;\n\n // Cleanup timers before emitting\n this.cleanupTimers();\n\n // Cache the attempt duration and emit attempt-handled for consistency\n const attemptTimeElapsedMS = Date.now() - context.startTime;\n this.currentState.lastAttemptTimeTakenMS = attemptTimeElapsedMS;\n\n this.emit(ATTEMPT_HANDLED, {\n attemptID: context.id,\n status: 'skip',\n data: undefined,\n error: undefined,\n operationTimeElapsedMS: this.timeTakenMS,\n attemptTimeElapsedMS,\n wasCanceled: true,\n } satisfies OnAttemptHandledInfo<T>);\n\n // Force completion after grace period expired.\n this.confirmCancellation(\n 'stopped',\n {\n status: 'canceled',\n },\n true,\n );\n }\n }\n }, this._gracePeriodMS);\n }\n }\n\n // return the promise\n return cancellationPromiseProtectedResolver.promise;\n } else {\n return 'not-running';\n }\n }\n\n public async reset(): Promise<void> {\n // If an operation is running or pending stopping, cancel it first.\n if (\n this.currentState.runnerState === 'running' ||\n this.currentState.runnerState === 'stopping'\n ) {\n // Cancel any in-flight work before resetting state.\n await this.cancel();\n }\n\n // Reset the internal state to its initial values.\n this.currentState = this.getEmptyCurrentState();\n\n // Also, reset the policy itself if needed.\n this.policy.reset();\n }\n\n public async resume(shouldWaitForCompletion = false): Promise<RunResult<T>> {\n if (this._isOperationLocked) {\n return {\n status: 'pre_operation_error',\n code: 'lock_error',\n error: new RetryUtilsErrRunnerLockAcquisitionError('resume'),\n };\n }\n\n this._isOperationLocked = true;\n\n try {\n // check if in a disallowed state for this operation\n const checkDisallowedStates = this.checkForDisallowedPerOperationStates(\n 'resume',\n ['completed', 'running', 'stopping', 'fatal-error', 'exhausted'],\n );\n\n if (\n checkDisallowedStates.wasDisallowed &&\n checkDisallowedStates.runResult\n ) {\n return checkDisallowedStates.runResult;\n } else {\n if (this.currentState.runnerState !== 'stopped') {\n return {\n status: 'pre_operation_error',\n code: 'not_paused',\n error: new RetryUtilsErrRunnerNotPaused('resume'),\n };\n }\n\n // Resume from the paused/stopped state.\n this.currentState.runnerState = 'running';\n this.currentState.operationStartTime = Date.now();\n this.currentState.finalTimeTakenMS = null;\n\n // emit the operation started event\n this.emit(OPERATION_STARTED, { operationType: 'resume' });\n\n this.currentOperationResolver = new PromiseProtectedResolver<\n RunResult<T>\n >();\n\n // Restart the initial operation\n void this.attemptOperation(false);\n\n if (shouldWaitForCompletion) {\n return this.currentOperationResolver.promise;\n } else {\n return { status: 'running' };\n }\n }\n } catch (error) {\n return {\n status: 'pre_operation_error',\n code: 'unexpected_error',\n error: new RetryUtilsErrRunnerUnexpectedError('resume', error as Error),\n };\n } finally {\n this._isOperationLocked = false;\n }\n }\n\n public async forceTry(options?: ForceTryOptions): Promise<RunResult<T>> {\n const shouldWaitForCompletion = options?.shouldWaitForCompletion ?? false;\n const shouldAbortRunning = options?.shouldAbortRunning ?? false;\n\n if (this._isOperationLocked) {\n return {\n status: 'pre_operation_error',\n code: 'lock_error',\n error: new RetryUtilsErrRunnerLockAcquisitionError('forceTry'),\n };\n }\n\n this._isOperationLocked = true;\n\n try {\n const checkDisallowedStates = this.checkForDisallowedPerOperationStates(\n 'forceTry',\n ['completed'],\n );\n\n if (\n checkDisallowedStates.wasDisallowed &&\n checkDisallowedStates.runResult\n ) {\n return checkDisallowedStates.runResult;\n }\n\n // If an attempt is already running and we don't want to abort it,\n // just attach to the current operation.\n if (this.isAttemptRunning && !shouldAbortRunning) {\n if (shouldWaitForCompletion) {\n return this.currentOperationResolver.promise;\n } else {\n return { status: 'running', reattached: true };\n }\n }\n\n // Prevent double-forcing the same attempt when aborting.\n if (this.isAttemptRunning && this.currentState.lastAttemptWasForceTry) {\n return {\n status: 'pre_operation_error',\n code: 'force_try_in_progress',\n error: new RetryUtilsErrRunnerForceTryRetryInProgress('forceTry'),\n };\n }\n\n // If an attempt is currently running and we want to abort it, do so.\n if (this.isAttemptRunning && this.currentState.currentAttemptContext) {\n this.currentState.currentAttemptContext.abortController.abort();\n }\n\n // Case 1: Retry is scheduled (pending timeout), force it to run now.\n // This starts a NEW ATTEMPT (attempt timer resets) but keeps the SAME OPERATION\n // (operation timer continues - we're just accelerating a scheduled retry, not starting over).\n if (this.currentState.retryTimeoutHandle !== null) {\n clearTimeout(this.currentState.retryTimeoutHandle);\n this.currentState.retryTimeoutHandle = null;\n this.currentState.retryTimeoutStartTime = null;\n this.currentState.retryTimeoutDelayMS = null;\n this.currentState.lastAttemptWasForceTry = true;\n\n void this.attemptOperation(true);\n\n if (shouldWaitForCompletion) {\n return this.currentOperationResolver.promise;\n } else {\n return { status: 'running', reattached: false };\n }\n } else {\n // Case 2: No pending retry, start a brand-new forced attempt.\n if (this.currentState.runnerState === 'not-started') {\n // Treat as a first try so the policy tracks the initial attempt.\n this.policy.shouldDoFirstTry();\n } else if (\n this.currentState.runnerState === 'stopping' ||\n this.currentState.runnerState === 'stopped'\n ) {\n // Transition from stopped/stopping to running.\n this.cleanupTimers();\n this.confirmCancellation('running', {\n status: null,\n });\n }\n\n this.currentState.runnerState = 'running';\n this.currentState.operationStartTime = Date.now();\n this.currentState.finalTimeTakenMS = null;\n\n this.emit(OPERATION_STARTED, { operationType: 'force' });\n\n if (\n !this.currentOperationResolver ||\n this.currentOperationResolver.hasResolved\n ) {\n // Create a new resolver for the forced operation.\n this.currentOperationResolver = new PromiseProtectedResolver<\n RunResult<T>\n >();\n }\n\n void this.attemptOperation(true);\n\n if (shouldWaitForCompletion) {\n return this.currentOperationResolver.promise;\n } else {\n return { status: 'running', reattached: false };\n }\n }\n } catch (error) {\n return {\n status: 'pre_operation_error',\n code: 'unexpected_error',\n error: new RetryUtilsErrRunnerUnexpectedError(\n 'forceTry',\n error as Error,\n ),\n };\n } finally {\n this._isOperationLocked = false;\n }\n }\n\n /**\n * Returning a fresh copy of the current state\n * to be immutable and not changed by the caller\n */\n\n private getEmptyCurrentState(): RetryRunnerCurrentState {\n return {\n runnerState: 'not-started',\n lastAttemptWasForceTry: false,\n currentAttemptContext: null,\n retryTimeoutHandle: null,\n retryTimeoutStartTime: null,\n retryTimeoutDelayMS: null,\n cancellationTimeoutHandle: null,\n operationStartTime: null,\n finalTimeTakenMS: null,\n lastAttemptTimeTakenMS: -1,\n };\n }\n\n private checkForDisallowedPerOperationStates(\n methodName: 'run' | 'resume' | 'forceTry',\n disallowedStates: Array<\n | 'completed'\n | 'running'\n | 'stopping'\n | 'stopped'\n | 'fatal-error'\n | 'exhausted'\n >,\n ): {\n wasDisallowed: boolean;\n runResult?: RunResult<T>;\n } {\n // Preflight state checks to normalize errors for each entrypoint.\n for (const checkForState of disallowedStates) {\n if (\n checkForState === 'completed' &&\n this.currentState.runnerState === 'completed'\n ) {\n return {\n wasDisallowed: true,\n runResult: {\n status: 'pre_operation_error',\n code: 'already_completed',\n error: new RetryUtilsErrRunnerAlreadyCompleted(methodName),\n },\n };\n } else if (\n checkForState === 'running' &&\n this.currentState.runnerState === 'running'\n ) {\n return {\n wasDisallowed: true,\n runResult: {\n status: 'pre_operation_error',\n code: 'already_running',\n error: new RetryUtilsErrRunnerAlreadyRunning(\n methodName as 'run' | 'resume',\n ),\n },\n };\n } else if (\n checkForState === 'stopping' &&\n this.currentState.runnerState === 'stopping'\n ) {\n return {\n wasDisallowed: true,\n runResult: {\n status: 'pre_operation_error',\n code: 'cancel_pending',\n error: new RetryUtilsErrRunnerCancelPending(\n methodName as 'run' | 'resume',\n ),\n },\n };\n } else if (\n checkForState === 'stopped' &&\n this.currentState.runnerState === 'stopped'\n ) {\n return {\n wasDisallowed: true,\n runResult: {\n status: 'pre_operation_error',\n code: 'retry_canceled',\n error: new RetryUtilsErrRunnerRetryCanceled('run'),\n },\n };\n } else if (\n checkForState === 'fatal-error' &&\n this.currentState.runnerState === 'fatal-error'\n ) {\n return {\n wasDisallowed: true,\n runResult: {\n status: 'pre_operation_error',\n code: 'fatally_failed',\n error: new RetryUtilsErrRunnerLastRetryFatallyFailed(\n methodName as 'run' | 'resume',\n ),\n },\n };\n } else if (\n checkForState === 'exhausted' &&\n (this.currentState.runnerState === 'exhausted' ||\n this.policy.areAttemptsExhausted)\n ) {\n return {\n wasDisallowed: true,\n runResult: {\n status: 'pre_operation_error',\n code: 'attempts_exhausted',\n error: new RetryUtilsErrRunnerAttemptsExhausted(\n methodName as 'run' | 'resume',\n ),\n },\n };\n }\n }\n\n // if no disallowed states were found\n return { wasDisallowed: false };\n }\n\n private cleanupTimers(): void {\n // Clear any pending retry or cancellation timers.\n if (this.currentState.retryTimeoutHandle) {\n clearTimeout(this.currentState.retryTimeoutHandle);\n this.currentState.retryTimeoutHandle = null;\n this.currentState.retryTimeoutStartTime = null;\n this.currentState.retryTimeoutDelayMS = null;\n }\n\n if (this.currentState.cancellationTimeoutHandle) {\n clearTimeout(this.currentState.cancellationTimeoutHandle);\n this.currentState.cancellationTimeoutHandle = null;\n }\n }\n\n private confirmCancellation(\n runnerState: RunnerState,\n resolveInfo: ConfirmCancellationResolveInfo<T>,\n wasForced = false,\n ): void {\n // Resolve cancel promises and finalize operation state transitions.\n if (this.currentState.runnerState === 'stopping') {\n this.cleanupTimers();\n\n this.currentState.runnerState = runnerState;\n\n // resolve all cancel promises\n for (const resolver of this.cancelResolvers) {\n resolver.resolveOnce(wasForced ? 'forced' : 'canceled');\n this.cancelResolvers.delete(resolver);\n }\n } else {\n this.currentState.runnerState = runnerState;\n }\n\n if (runnerState !== 'running') {\n // Freeze timeTakenMS for terminal states\n this.currentState.finalTimeTakenMS =\n this.currentState.operationStartTime !== null\n ? Date.now() - this.currentState.operationStartTime\n : -1;\n\n // emit the operation ended event\n this.emit(OPERATION_ENDED, {\n runnerState,\n timeTakenMS: this.timeTakenMS,\n });\n\n if (resolveInfo.status !== null) {\n if (resolveInfo.status === 'attempt_success') {\n this.currentOperationResolver.resolveOnce({\n status: 'attempt_success',\n ...(resolveInfo.data !== undefined\n ? { data: resolveInfo.data }\n : {}),\n });\n } else {\n const nonSuccessResult: RunResultNonSuccess = {\n status: resolveInfo.status,\n };\n\n if (resolveInfo.code !== undefined) {\n nonSuccessResult.code = resolveInfo.code;\n }\n\n if (resolveInfo.error !== undefined) {\n nonSuccessResult.error = resolveInfo.error;\n }\n\n this.currentOperationResolver.resolveOnce(nonSuccessResult);\n }\n }\n }\n }\n\n private handleReportResult(\n context: AttemptContext,\n status: ReportResultStatus,\n valueInfo: {\n data?: T;\n error?: unknown;\n },\n ): void {\n // Guard against multiple calls to reportResult\n if (\n // Ensure the context matches the current context\n (this.currentState.currentAttemptContext &&\n context.id !== this.currentState.currentAttemptContext.id) ||\n // Ensure the result hasn't already been handled\n context.handled\n ) {\n return; // Ensures we only handle the result once per context\n }\n\n // cleanup the current attempt context\n this.currentState.currentAttemptContext = null;\n\n // Cleanup any timers\n this.cleanupTimers();\n\n // Mark the context as handled\n context.handled = true;\n\n // Handle the result based on status\n let isSkip = false;\n let shouldQueryForRetry = false;\n\n let confirmCancellationInfo: {\n run: boolean;\n runnerState: RunnerState | null;\n resolveInfo: ConfirmCancellationResolveInfo<T> | null;\n } = {\n run: false,\n runnerState: null,\n resolveInfo: null,\n };\n\n if (status === 'success') {\n this.policy.markAsSuccessful();\n\n confirmCancellationInfo = {\n run: true,\n runnerState: 'completed',\n resolveInfo: {\n status: 'attempt_success',\n data: valueInfo.data,\n },\n };\n } else if (status === 'error') {\n shouldQueryForRetry = true;\n } else if (status === 'fatal') {\n // Fatal errors are recorded, but never retried.\n this.policy.shouldRetry(valueInfo.error ?? valueInfo.data, false);\n\n confirmCancellationInfo = {\n run: true,\n runnerState: 'fatal-error',\n resolveInfo: {\n status: 'attempt_fatal',\n error: valueInfo.error,\n },\n };\n } else {\n // Skip is treated like a non-fatal error that doesn't count as a failure.\n isSkip = true;\n shouldQueryForRetry = true;\n }\n\n // Handle if query for retry\n if (shouldQueryForRetry) {\n const shouldRetryQuery = this.policy.shouldRetry(\n valueInfo.error ?? valueInfo.data,\n isSkip,\n );\n\n const isCanceledOrPendingCancel =\n this.currentState.runnerState === 'stopping' ||\n this.currentState.runnerState === 'stopped';\n\n if (isCanceledOrPendingCancel) {\n confirmCancellationInfo = {\n run: true,\n runnerState: 'stopped',\n resolveInfo: {\n status: 'canceled',\n },\n };\n } else {\n if (shouldRetryQuery.shouldRetry) {\n if (shouldRetryQuery.delayMS > 0) {\n this.currentState.retryTimeoutStartTime = Date.now();\n this.currentState.retryTimeoutDelayMS = shouldRetryQuery.delayMS;\n this.currentState.retryTimeoutHandle = setTimeout(() => {\n this.currentState.retryTimeoutHandle = null;\n this.currentState.retryTimeoutStartTime = null;\n this.currentState.retryTimeoutDelayMS = null;\n void this.attemptOperation(false);\n }, shouldRetryQuery.delayMS);\n } else {\n void this.attemptOperation(false);\n }\n } else {\n // No retry allowed: mark as exhausted.\n confirmCancellationInfo = {\n run: true,\n runnerState: 'exhausted',\n resolveInfo: {\n status: 'attempts_exhausted',\n error: valueInfo.error,\n },\n };\n }\n }\n }\n\n // Cache the attempt duration before emitting\n const attemptTimeElapsedMS = Date.now() - context.startTime;\n this.currentState.lastAttemptTimeTakenMS = attemptTimeElapsedMS;\n\n // emit the attempt handled event\n this.emit(ATTEMPT_HANDLED, {\n attemptID: context.id,\n status,\n data: valueInfo.data,\n error: valueInfo.error,\n operationTimeElapsedMS: this.timeTakenMS,\n attemptTimeElapsedMS,\n wasCanceled:\n this.currentState.runnerState === 'stopping' ||\n this.currentState.runnerState === 'stopped',\n } satisfies OnAttemptHandledInfo<T>);\n\n // if a confirm cancel should run\n if (\n confirmCancellationInfo.run &&\n confirmCancellationInfo.runnerState !== null &&\n confirmCancellationInfo.resolveInfo !== null\n ) {\n this.confirmCancellation(\n confirmCancellationInfo.runnerState,\n confirmCancellationInfo.resolveInfo,\n );\n }\n\n // if cancellation is pending, confirm it since we're not rescheduling anything\n if (this.currentState.runnerState === 'stopping') {\n this.confirmCancellation('stopped', {\n status: null,\n });\n }\n }\n\n private async attemptOperation(wasForced: boolean): Promise<void> {\n // If there's an existing attempt that has already been handled but not yet cleaned up, return early\n if (this.currentState.currentAttemptContext instanceof AttemptContext) {\n if (this.currentState.currentAttemptContext.handled) {\n return;\n }\n }\n\n // make sure the operation is running still, and not pending cancellation or canceled\n if (this.currentState.runnerState === 'running') {\n this.currentState.lastAttemptWasForceTry = wasForced;\n\n // Create a new context for this attempt\n const context = new AttemptContext();\n this.currentState.currentAttemptContext = context;\n\n // emit the attempt started event\n this.emit(ATTEMPT_STARTED, {\n attemptID: context.id,\n operationTimeElapsedMS: this.timeTakenMS,\n attemptTimeElapsedMS: 0,\n });\n\n // reportResult is how the operation communicates outcome of this attempt.\n // Route the value to `data` for success/skip, or `error` for error/fatal.\n const reportResult: ReportResult = (status, value) => {\n if (status === 'success' || status === 'skip') {\n this.handleReportResult(context, status, {\n data: value as T,\n });\n } else {\n this.handleReportResult(context, status, {\n error: value,\n });\n }\n };\n\n try {\n const result = this.operation(\n reportResult,\n context.abortController.signal,\n );\n\n if (isPromise(result)) {\n await result;\n }\n } catch (error) {\n // Treat thrown errors as retryable errors by default.\n this.handleReportResult(context, 'error', {\n error: error,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":["stringWidth","availableWidth","stringWidth","stringWidth","availableWidth","callbacks"]}