{"version":3,"file":"safeJsonParse-DDs3Voa4.cjs","names":["isNonEmptyString","createMessage","getPreciseType","safeStableStringify","isPlainObject","noop","isBoolean","isArray","isFunction","createMessage","getPreciseType","isNull","isUndefined","isString","isArray","isEmptyArray","isObject","isEmptyObject","isString","isNumber","isNull","isNaN","isNonEmptyString","isNumber","isString","isError"],"sources":["../src/conversions/json/parseCustomDate.ts","../src/conversions/json/_private/utils/validateJsonParsingOptions.ts","../src/conversions/json/cleanParsedData.ts","../src/conversions/numerics/extractDigits.ts","../src/conversions/json/_private/utils/fixSingleQuotesEscapeBackslash.ts","../src/conversions/json/safeJsonParse.ts"],"sourcesContent":["import { createMessage } from \"@/_private/logger\";\n\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { safeStableStringify } from \"../stringify/safeStableStringify\";\n\n/** ---------------------------------------------------------------------------------------\n * * ***Utility: `parseCustomDate`.***\n * ----------------------------------------------------------------------------------------\n * **Parses custom date formats like `\"DD/MM/YYYY\"` or `\"MM/DD/YYYY\"`.**\n *\n * ---\n * @param {string} dateString - Date string to parse.\n * @param {string} format - Date format to match.\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `dateString` **(first parameter)** and\n *         `format` **(second parameter)** is not a string or empty-string.\n *\n * ---\n * @returns {Date | null} Returns a `Date` object if valid, otherwise `null`.\n *\n * ---\n * @example\n * 1. #### Parse European date format:\n *    ```ts\n *    const date1 = parseCustomDate(\n *      \"03/09/2025\",\n *      \"DD/MM/YYYY\"\n *    );\n *\n *    console.log(date1);\n *    // ➔ Date { Wed Sep 03 2025 ... }\n *    ```\n *    ---\n * 2. #### Parse US date format:\n *    ```ts\n *    const date2 = parseCustomDate(\n *      \"09/03/2025\",\n *      \"MM/DD/YYYY\"\n *    );\n *\n *    console.log(date2);\n *    // ➔ Date { Wed Sep 03 2025 ... }\n *    ```\n *    ---\n * 3. #### Invalid date format:\n *    ```ts\n *    const date3 = parseCustomDate(\n *      \"2025-09-03\",\n *      \"DD/MM/YYYY\"\n *    );\n *\n *    console.log(date3);\n *    // ➔ null\n *    ```\n *    ---\n * 4. #### Invalid date string:\n *    ```ts\n *    const date4 = parseCustomDate(\n *      \"hello\",\n *      \"DD/MM/YYYY\"\n *    );\n *\n *    console.log(date4);\n *    // ➔ null\n *    ```\n *    ---\n * 5. #### Invalid parameter types:\n *    ```ts\n *    parseCustomDate(\n *      123,\n *      \"DD/MM/YYYY\"\n *    );\n *\n *    // ➔ TypeError: Parameter `dateString` and `format` must be of type `string`...\n *    ```\n */\nexport const parseCustomDate = (\n  dateString: string,\n  format: string\n): Date | null => {\n  if (!isNonEmptyString(dateString) || !isNonEmptyString(format)) {\n    throw new TypeError(\n      createMessage(\n        \"parseCustomDate\",\n        `Parameter \\`dateString\\` and \\`format\\` must be of type \\`string\\` and not empty-string, but received: \"['dateString': \\`${getPreciseType(\n          dateString\n        )}\\` - (current value: \\`${safeStableStringify(dateString, {\n          keepUndefined: true\n        })}\\`), 'format': \\`${getPreciseType(\n          format\n        )}\\` - (current value: \\`${safeStableStringify(format, {\n          keepUndefined: true\n        })}\\`)]\".`\n      )\n    );\n  }\n\n  const dateParts = dateString.split(/[-/]/).map(Number);\n  if (dateParts.length !== 3 || dateParts.some(isNaN)) return null;\n\n  let day: number | undefined,\n    month: number | undefined,\n    year: number | undefined;\n\n  if (format === \"DD/MM/YYYY\") {\n    [day, month, year] = dateParts;\n  } else if (format === \"MM/DD/YYYY\") {\n    [month, day, year] = dateParts;\n  } else {\n    return null;\n  }\n\n  if (month) month -= 1;\n  const date = year && month && day ? new Date(year, month, day) : undefined;\n\n  if (\n    !date ||\n    date.getFullYear() !== year ||\n    date.getMonth() !== month ||\n    date.getDate() !== day\n  ) {\n    return null;\n  }\n\n  return date;\n};\n","import type { Prettify } from \"@rzl-zone/ts-types-plus\";\n\nimport type { ParseParsedDataOptions } from \"../types/ParseParsedDataOptions\";\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { cleanParsedData } from \"../../cleanParsedData\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { parseCustomDate } from \"../../parseCustomDate\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { safeJsonParse } from \"../../safeJsonParse\";\n\nimport { isArray } from \"@/predicates/is/isArray\";\nimport { isBoolean } from \"@/predicates/is/isBoolean\";\nimport { isFunction } from \"@/predicates/is/isFunction\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\n\nimport { noop } from \"@/generators/utils/noop\";\nimport { createMessage } from \"@/_private/logger\";\n\ntype ValidatedParsedDataOptions = Prettify<Required<ParseParsedDataOptions>>;\n\n/** * ***Private Helper for Options Validation Function: {@link cleanParsedData | `cleanParsedData`}, {@link parseCustomDate | `parseCustomDate`} and {@link safeJsonParse | `safeJsonParse`}.***\n *\n * @internal\n */\nexport const validateJsonParsingOptions = (\n  optionsValue: ParseParsedDataOptions,\n  calledFromSource: string\n): ValidatedParsedDataOptions => {\n  if (!isPlainObject(optionsValue)) optionsValue = {};\n\n  const convertBooleans = optionsValue.convertBooleans ?? false;\n  const convertDates = optionsValue.convertDates ?? false;\n  const convertNumbers = optionsValue.convertNumbers ?? false;\n  const loggingOnFail = optionsValue.loggingOnFail ?? false;\n  const removeEmptyArrays = optionsValue.removeEmptyArrays ?? false;\n  const removeEmptyObjects = optionsValue.removeEmptyObjects ?? false;\n  const removeNulls = optionsValue.removeNulls ?? false;\n  const removeUndefined = optionsValue.removeUndefined ?? false;\n  const strictMode = optionsValue.strictMode ?? false;\n  const checkSymbols = optionsValue.checkSymbols ?? false;\n  const convertNaN = optionsValue.convertNaN ?? false;\n\n  const customDateFormats = optionsValue.customDateFormats ?? [];\n  const onError = optionsValue.onError ?? noop;\n\n  if (\n    !(\n      isBoolean(convertBooleans) &&\n      isBoolean(convertDates) &&\n      isBoolean(convertNumbers) &&\n      isBoolean(convertNaN) &&\n      isBoolean(checkSymbols) &&\n      isBoolean(loggingOnFail) &&\n      isBoolean(removeEmptyArrays) &&\n      isBoolean(removeEmptyObjects) &&\n      isBoolean(removeNulls) &&\n      isBoolean(removeUndefined) &&\n      isBoolean(strictMode) &&\n      isArray(customDateFormats) &&\n      isFunction(onError)\n    )\n  ) {\n    throw new TypeError(\n      createMessage(\n        calledFromSource,\n        `Invalid \\`options\\` parameter (second argument): \\`convertBooleans\\`, \\`convertDates\\`, \\`convertNumbers\\`, \\`loggingOnFail\\`, \\`removeEmptyArrays\\`, \\`removeEmptyObjects\\`, \\`removeNulls\\`, \\`removeUndefined\\`, \\`strictMode\\` expected to be a \\`boolean\\` type, \\`customDateFormats\\` expected to be a \\`array\\` type and \\`onError\\` expected to be a \\`void function\\` type. But received: ['convertBooleans': \\`${getPreciseType(\n          convertBooleans\n        )}\\`, 'convertDates': \\`${getPreciseType(\n          convertDates\n        )}\\`, 'convertNumbers': \\`${getPreciseType(\n          convertNumbers\n        )}\\`, 'loggingOnFail': \\`${getPreciseType(\n          loggingOnFail\n        )}\\`, 'removeEmptyArrays': \\`${getPreciseType(\n          removeEmptyArrays\n        )}\\`, 'removeEmptyObjects': \\`${getPreciseType(\n          removeEmptyObjects\n        )}\\`, 'removeNulls': \\`${getPreciseType(\n          removeNulls\n        )}\\`, 'removeUndefined': \\`${getPreciseType(\n          removeUndefined\n        )}\\`, 'strictMode': \\`${getPreciseType(\n          strictMode\n        )}\\`, 'customDateFormats': \\`${getPreciseType(\n          customDateFormats\n        )}\\`, 'onError': \\`${getPreciseType(onError)}\\`].`\n      )\n    );\n  }\n\n  return {\n    convertBooleans,\n    convertDates,\n    convertNumbers,\n    convertNaN,\n    loggingOnFail,\n    removeEmptyArrays,\n    removeEmptyObjects,\n    removeNulls,\n    removeUndefined,\n    strictMode,\n    customDateFormats,\n    onError,\n    checkSymbols\n  };\n};\n","import type { ParseParsedDataOptions } from \"./_private/types/ParseParsedDataOptions\";\n\nimport { isNull } from \"@/predicates/is/isNull\";\nimport { isArray } from \"@/predicates/is/isArray\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isObject } from \"@/predicates/is/isObject\";\nimport { isUndefined } from \"@/predicates/is/isUndefined\";\nimport { isEmptyArray } from \"@/predicates/is/isEmptyArray\";\nimport { isEmptyObject } from \"@/predicates/is/isEmptyObject\";\n\nimport { parseCustomDate } from \"./parseCustomDate\";\nimport { validateJsonParsingOptions } from \"./_private/utils/validateJsonParsingOptions\";\n\n/** --------------------------------------------------------------------------------------------\n * * ***Utility: `cleanParsedData`.***\n * ---------------------------------------------------------------------------------------------\n * **Cleans parsed JSON data based on provided options.**\n *\n * ---\n * @template T - Expected output type.\n *\n * ---\n * @param {*} data - The parsed JSON data.\n * @param {ParseParsedDataOptions} [options] - The cleaning options.\n *\n * ---\n * @returns {T | null | undefined} The cleaned data.\n * - ***⚠️ Notice:*** _If data is JSON string, we recommend use ***`safeJsonParse` utility\n *   function*** for more safe._\n * - ***⚠️ Note:*** _If using **`convertDates`** **options**, result may contain Date objects,\n *   you may need type assertions in strict TypeScript settings._\n *\n * ---\n * @example\n * 1. #### Convert numbers and remove null values:\n *    ```ts\n *    const result = cleanParsedData(\n *      { age: \"25\", name: null },\n *      { convertNumbers: true, removeNulls: true }\n *    );\n *\n *    console.log(result);\n *    // ➔ { age: 25 }\n *    ```\n *    ---\n * 2. #### Convert boolean strings:\n *    ```ts\n *    const result = cleanParsedData(\n *      { isActive: \"true\" },\n *      { convertBooleans: true }\n *    );\n *\n *    console.log(result);\n *    // ➔ { isActive: true }\n *    ```\n */\nexport const cleanParsedData = <T = unknown>(\n  data: T,\n  options?: ParseParsedDataOptions\n): T | undefined | null => {\n  const validOptions = validateJsonParsingOptions(\n    options ?? {},\n    \"cleanParsedData\"\n  );\n\n  if (isNull(data)) return validOptions.removeNulls ? undefined : null;\n  if (isUndefined(data))\n    return validOptions.removeUndefined ? undefined : undefined;\n\n  if (isString(data)) {\n    const trimmed = data.trim();\n\n    if (validOptions.convertNaN && trimmed === \"NaN\") return NaN as T;\n\n    if (validOptions.convertNumbers && !isNaN(Number(trimmed))) {\n      return Number(trimmed) as T;\n    }\n\n    if (validOptions.convertBooleans) {\n      if (trimmed === \"true\") return true as T;\n      if (trimmed === \"false\") return false as T;\n    }\n\n    if (validOptions.convertDates) {\n      if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/.test(trimmed)) {\n        return new Date(trimmed) as T;\n      }\n\n      if (validOptions.customDateFormats?.length) {\n        for (const format of validOptions.customDateFormats) {\n          const date = parseCustomDate(trimmed, format);\n          if (date) return date as T;\n        }\n      }\n    }\n\n    return validOptions.strictMode ? undefined : (trimmed as T);\n  }\n\n  if (isArray(data)) {\n    const cleanedArray = data\n      .map((item) => cleanParsedData(item, validOptions))\n      .filter((item) => !isUndefined(item));\n\n    return validOptions.removeEmptyArrays && isEmptyArray(cleanedArray)\n      ? undefined\n      : (cleanedArray as T);\n  }\n\n  if (isObject(data)) {\n    const cleanedObject: Record<string, unknown> = {};\n\n    for (const key in data) {\n      if (Object.prototype.hasOwnProperty.call(data, key)) {\n        const cleanedValue = cleanParsedData(data[key], validOptions);\n        if (!isUndefined(cleanedValue)) {\n          cleanedObject[key] = cleanedValue;\n        }\n      }\n    }\n\n    return validOptions.removeEmptyObjects &&\n      isEmptyObject(cleanedObject, { checkSymbols: validOptions.checkSymbols })\n      ? undefined\n      : (cleanedObject as T);\n  }\n\n  return validOptions.strictMode ? undefined : data;\n};\n","import { isNumber } from \"@/predicates/is/isNumber\";\nimport { isString } from \"@/predicates/is/isString\";\n\n/** -----------------------------------------------------------------------------------------------------------------------------------------\n * * ***Utility: `extractDigits`.***\n * ------------------------------------------------------------------------------------------------------------------------------------------\n * **Extracts digits from a string or number input.**\n *\n * ---\n * - **Behavior:**\n *     - Converts the input to a string, trims whitespace, and removes any characters that are not digits (`0-9`).\n *     - Returns the cleaned numeric value as a `number`.\n *     - If the input is a `null`, `undefined`, results in no digits, or not a `string` (or empty-string) or `number`, it safely return `0`.\n *\n * ---\n * @param {*} [value]\n *  ***The value to process.***\n *     - Accepts a string, number, `null`, or `undefined`.\n *\n * ---\n * @returns {number} The numeric value after extracting digits (returns `0` if input is invalid or contains no digits).\n *\n * ---\n * @example\n * extractDigits(12345);\n * // ➔ 12345\n * extractDigits(\"9A8B7C6X1\");\n * // ➔ 98761\n * extractDigits(\"123abc456\");\n * // ➔ 123456\n * extractDigits(\"$1,234.56\");\n * // ➔ 123456\n * extractDigits(NaN);\n * // ➔ 0\n * extractDigits(null);\n * // ➔ 0\n * extractDigits(undefined);\n * // ➔ 0\n * extractDigits(Infinity);\n * // ➔ 0\n * extractDigits(-Infinity);\n * // ➔ 0\n * extractDigits({});\n * // ➔ 0\n * extractDigits([]);\n * // ➔ 0\n * extractDigits(\"\");\n * // ➔ 0\n * extractDigits(\" \");\n * // ➔ 0\n * extractDigits(\"abc\");\n * // ➔ 0\n * extractDigits(\"   00a  \");\n * // ➔ 0\n */\nexport const extractDigits = (value: unknown): number => {\n  if (!isString(value) && !isNumber(value)) return 0;\n\n  const cleaned = String(value)\n    .trim()\n    .replace(/[^0-9]/g, \"\");\n\n  return Number(cleaned) || 0;\n};\n","/* eslint-disable quotes */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { safeJsonParse } from \"../../safeJsonParse\";\n\n/** * ***Util Helper for {@link safeJsonParse | `safeJsonParse`}.***\n *\n * @internal\n */\nexport function fixSingleQuotesEscapeBackslash(input: string): string {\n  const validEscapes = new Set([\"\\\\\", '\"', \"/\", \"b\", \"f\", \"n\", \"r\", \"t\", \"u\"]);\n\n  let output = \"\";\n  let inSingleQuote = false;\n  let inDoubleQuote = false;\n  let escapeNext = false;\n\n  for (let i = 0; i < input.length; i++) {\n    const c = input[i] || \"\";\n\n    if (escapeNext) {\n      if (inSingleQuote) {\n        if (c === \"'\") {\n          output += \"'\";\n        } else if (validEscapes.has(c)) {\n          if (c === \"\\\\\") {\n            output += \"\\\\\\\\\";\n          } else if (c === '\"') {\n            output += '\\\\\"';\n          } else {\n            output += \"\\\\\" + c;\n          }\n        } else {\n          output += \"\\\\\\\\\" + c;\n        }\n      } else if (inDoubleQuote) {\n        if (c === '\"') {\n          output += '\\\\\"';\n        } else if (validEscapes.has(c)) {\n          output += \"\\\\\" + c;\n        } else {\n          output += \"\\\\\\\\\" + c;\n        }\n      } else {\n        output += \"\\\\\" + c;\n      }\n      escapeNext = false;\n      continue;\n    }\n\n    if (c === \"\\\\\") {\n      escapeNext = true;\n      continue;\n    }\n\n    if (!inSingleQuote && !inDoubleQuote) {\n      if (c === \"'\") {\n        output += '\"';\n        inSingleQuote = true;\n        continue;\n      }\n      if (c === '\"') {\n        output += '\"';\n        inDoubleQuote = true;\n        continue;\n      }\n    } else if (inSingleQuote) {\n      if (c === \"'\") {\n        output += '\"';\n        inSingleQuote = false;\n        continue;\n      }\n    } else if (inDoubleQuote) {\n      if (c === '\"') {\n        output += '\"';\n        inDoubleQuote = false;\n        continue;\n      }\n    }\n\n    output += c;\n  }\n\n  return output;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { IsAny } from \"@rzl-zone/ts-types-plus\";\nimport type { ParseParsedDataOptions } from \"./_private/types/ParseParsedDataOptions\";\nimport type {\n  SafeJsonParseResult,\n  UnknownValue\n} from \"./_private/types/safeJsonParse\";\n\nimport { isNaN } from \"@/predicates/is/isNaN\";\nimport { isNull } from \"@/predicates/is/isNull\";\nimport { isError } from \"@/predicates/is/isError\";\nimport { isNumber } from \"@/predicates/is/isNumber\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { cleanParsedData } from \"./cleanParsedData\";\nimport { extractDigits } from \"../numerics/extractDigits\";\nimport { validateJsonParsingOptions } from \"./_private/utils/validateJsonParsingOptions\";\nimport { fixSingleQuotesEscapeBackslash } from \"./_private/utils/fixSingleQuotesEscapeBackslash\";\n\n/** ------------------------------------------------------------------------------------------------------------------------------------------\n * * ***Utility: `safeJsonParse`.***\n * -------------------------------------------------------------------------------------------------------------------------------------------\n * **Safely parses JSON while handling errors and applying transformations.**\n *\n * ---\n * - **Supports generics** to ensure accurate return type inference.\n *      - Always provide both `<TData, TInput>` for best results.\n *      - ℹ️ ***Scroll down for full generic behavior explanation.***\n * - Automatically parses valid JSON strings into `objects`, `arrays`, `numbers`, etc.\n * - Supports data transformation via options (e.g., convert strings to `numbers`, `booleans`, or `dates`).\n * - **Returns:**\n *      1. `null` ➔ if input is explicitly `null`.\n *      2. `undefined` ➔ if input is `undefined`, not a `string`, or if parsing fails.\n *      3. Parsed and cleaned result (`TData`) ➔ if input is a valid JSON string.\n *\n * ---\n * - ⚠️ **JSON.stringify note**:\n *      - _If the input JSON string was created using `JSON.stringify()`, any properties with `undefined`\n *        values would have been automatically removed or converted to `null` depending on the serializer, example:_\n *        ```ts\n *        JSON.stringify({ a: undefined, b: 1 });\n *        // ➔ '{\"b\":1}'\n *        JSON.parse('{\"a\": undefined, \"b\": 1}')\n *        // ❌ invalid JSON\n *        ```\n *        _Therefore, if you see `undefined` in raw input, it will likely throw unless pre-cleaned or replaced with `null`._\n *\n *        ```ts\n *        safeJsonParse('{\"name\": \"John\", \"score\": undefined}');\n *        // result ➔ { name: \"John\", score: null } <- because `undefined` is not valid JSON, gets replaced to null.\n *        ```\n *\n * ---\n * - ℹ️ **Additionally:**\n *      - This function normalizes single quotes (`'`) to double quotes (`\"`) before parsing,\n *        so JSON strings using single quotes will be converted to valid JSON format, example:\n *        ```ts\n *        safeJsonParse(\"{'name': 'John', 'age': 30}\");\n *        // result ➔ { name: \"John\", age: 30 }\n *\n *        safeJsonParse(\"{'string\\\\'s': 'abc', \\\"quote's\\\": 'It\\\\'s awesome!', 'aNumber\\\\'s': 123, 'keyWith\\\\'Backslash\\\\'s': 'value\\\\'s'}\");\n *        // result ➔ { \"string's\": \"abc\", \"quote's\": \"It's awesome!\", \"aNumber's\": 123, \"keyWith'Backslash's\": \"value's\" }\n *        ```\n *\n * ---\n * @template TData - The expected output type after parsing and cleaning.\n * @template TInput - The input value type, used for advanced type inference and return typing.\n *\n * ---\n * @param {TInput} [value] - The JSON string or value to parse.\n * @param {ParseParsedDataOptions} [options] - Options to clean, convert types, enable strict mode,\n *   support custom date formats, enable logging, or handle errors via callback.\n *\n * ---\n * @returns {SafeJsonParseResult<TData, TInput>} Parsed and optionally cleaned result, or `null`/`undefined`.\n *\n * ---\n * @example\n * 1. #### *Basic parse with number & boolean conversion:*\n *       ```ts\n *       const result = safeJsonParse(30);\n *       // result ➔ undefined\n *       const result = safeJsonParse(30, {\n *         convertNumbers: true\n *       });\n *       // result ➔ 30\n *\n *       const result = safeJsonParse('{\"age\": \"30\", \"isActive\": \"true\"}', {\n *         convertNumbers: true,\n *         convertBooleans: true\n *       });\n *       // result ➔ { age: 30, isActive: true }\n *       ```\n *       ---\n * 2. #### *Handling `undefined` in input string (manually written, not JSON.stringify):*\n *       ```ts\n *       const result = safeJsonParse('{\"score\": undefined}');\n *       // result ➔ { score: null } <- because `undefined` is not valid JSON, gets replaced\n *       ```\n *       ---\n * 3. #### *Handling `NaN` in input string (manually written, not JSON.stringify):*\n *       ```ts\n *       const value = NaN; // <- value is NaN or \"NaN\";\n *       const result = safeJsonParse(value);\n *       // result ➔ undefined <- will return as undefined, because options `convertNaN` is false (default),\n *       const result2 = safeJsonParse(value, { convertNaN: true });\n *       // result2 ➔ NaN <- will return as undefined because options `convertNaN` is false,\n *\n *       const result4 = safeJsonParse('{\"strNan\": \"NaN\", \"pureNan\": NaN}');\n *       // NaN will convert to string (NaN ➔ \"NaN\") because options `convertNaN` is false (default),\n *       // result4 ➔ { strNan: \"NaN\", pureNan: \"NaN\" }\n *\n *       const result3 = safeJsonParse('{\"strNan\": \"NaN\", \"pureNan\": NaN}', {\n *         convertNaN: true\n *       });\n *       // String \"NaN\" will convert to NaN (\"NaN\" ➔ NaN) because options `convertNaN` is true,\n *       // result3 ➔ { strNan: NaN, pureNan: NaN }\n *       ```\n *       ---\n * 4. #### *Strict mode (removes invalid values):*\n *       ```ts\n *       const result = safeJsonParse('{\"name\": \"   \", \"score\": \"99abc\"}', {\n *         convertNumbers: true,\n *         strictMode: true\n *       });\n *       // result ➔ {}\n *\n *       const result2 = safeJsonParse('{\"name\": \"   \", \"score\": undefined}');\n *       // result2 ➔ { name: \"\",score: null }\n *       ```\n *       ---\n * 5. #### *Custom date format parsing:*\n *       ```ts\n *       const result = safeJsonParse('{\"birthday\": \"25/12/2000\"}', {\n *         convertDates: true,\n *         customDateFormats: [\"DD/MM/YYYY\"]\n *       });\n *       // result ➔ { birthday: new Date(\"2000-12-25T00:00:00.000Z\") }\n *       ```\n *       ---\n * 6. #### *Invalid JSON with custom error handling:*\n *       ```ts\n *       safeJsonParse(\"{invalid}\", {\n *         loggingOnFail: true,\n *         onError: (err) => console.log(\"Custom handler:\", err.message)\n *       });\n *       // ➔ Logs parsing error and invokes handler\n *       ```\n *       ---\n * 7. #### *Null or non-string input returns null/undefined (default options):*\n *       ```ts\n *       safeJsonParse(123);\n *       // ➔ undefined\n *       safeJsonParse(null);\n *       // ➔ null\n *       safeJsonParse(undefined);\n *       // ➔ undefined\n *       ```\n *       ---\n * 8. #### *Generic usage: Provide both output and input type to ensure correct return typing:*\n *       ```ts\n *       type UserType = { name: string };\n *\n *       const obj = JSON.stringify({\n *         name: \"John\"\n *       });\n *\n *       const toParse = isAuth() ? obj : null;\n *       const toParse2 = isAuth() ? obj : undefined;\n *\n *       //! * `Without Generic`:\n *         const parsed = safeJsonParse(toParse);\n *         //- runtime: { name: \"John\" } | undefined | null\n *         //- type: Record<string, unknown> | undefined | null\n *         const parsed2 = safeJsonParse(toParse);\n *         //- runtime: { name: \"John\" } | undefined\n *         //- type: Record<string, unknown> | undefined\n *\n *       //! * `With Generic`:\n *         const parsed = safeJsonParse<UserType>(toParse);\n *         //- runtime: { name: \"John\" } | undefined | null\n *         //- type: undefined  <- (⚠️ unexpected!)\n *         const parsed2 = safeJsonParse<UserType>(toParse);\n *         //- runtime: { name: \"John\" } | undefined\n *         //- type: undefined  <- (⚠️ unexpected!)\n *         const parsed = safeJsonParse<UserType, typeof toParse>(toParse);\n *         //- runtime: { name: \"John\" } | null | undefined\n *         //- type: UserType | null | undefined\n *         const parsed2 = safeJsonParse<UserType, typeof toParse>(toParse);\n *         //- runtime: { name: \"John\" } | undefined\n *         //- type: UserType | undefined\n *       ```\n *\n * ---\n * @note\n * - ⚠️ **Generic Behavior:**\n *      - This function supports advanced generic inference for clean, type-safe return values.\n *      - If only the first generic (`TData`) is provided and the second (`TInput`) is omitted,\n *        then `TInput` defaults to `undefined`, resulting in a return type of `undefined`.\n *      - To ensure correct return typing, **always pass both generics** when `value` is dynamic,\n *        nullable, or unioned: `safeJsonParse<TData, typeof value>(value)`.\n *      - This makes the returned type exactly match your expectation: `TData | null | undefined`.\n */\nexport function safeJsonParse<\n  TData extends Record<string, any> = Record<string, unknown>,\n  TInput extends UnknownValue = UnknownValue\n>(\n  value: TInput,\n  options?: ParseParsedDataOptions\n): IsAny<TInput> extends true ? TData | null | undefined : undefined;\nexport function safeJsonParse<\n  TData extends Record<string, any> = Record<string, unknown>,\n  TInput extends string | null | undefined | unknown = undefined\n>(\n  value: TInput,\n  options?: ParseParsedDataOptions\n): SafeJsonParseResult<TData, TInput>;\n//! implement main function\nexport function safeJsonParse<TData extends Record<string, unknown>>(\n  value: unknown,\n  options?: ParseParsedDataOptions\n) {\n  if (isNull(value)) return null;\n  const validOptions = validateJsonParsingOptions(\n    options ?? {},\n    \"safeJsonParse\"\n  );\n\n  if (\n    validOptions.convertNaN &&\n    (isNaN(value) || (isNonEmptyString(value) && value === \"NaN\"))\n  ) {\n    return NaN;\n  }\n  if (\n    validOptions.convertNumbers &&\n    !isNaN(Number(value)) &&\n    isNumber(extractDigits(value))\n  ) {\n    return Number(value);\n  }\n\n  if (!isString(value)) return undefined;\n\n  try {\n    // First, normalize all single quotes to double quotes\n    let normalized = fixSingleQuotesEscapeBackslash(value);\n\n    if (validOptions.removeUndefined) {\n      normalized = normalized\n        .replace(/,\\s*\"[^\"]*\"\\s*:\\s*undefined(?=\\s*[},])/g, \"\")\n        // ➔ remove , \"key\": undefined\n        .replace(/\"[^\"]*\"\\s*:\\s*undefined\\s*(,)?/g, \"\");\n      // ➔ remove \"key\": undefined\n    } else {\n      normalized = normalized.replace(/:\\s*undefined(?=\\s*[,}])/g, \":null\");\n      // ➔ replace :undefined with :null\n    }\n\n    if (validOptions.convertNaN) {\n      // eslint-disable-next-line quotes\n      normalized = normalized.replace(/:\\s*NaN(?=\\s*[,}])/g, ':\"NaN\"');\n      // ➔ convert :NaN to :\"NaN\"\n    } else {\n      normalized = normalized\n        // eslint-disable-next-line quotes\n        .replace(/:\\s*NaN(?=\\s*[,}])/g, ':\"NaN\"')\n        // ➔ convert :NaN to :\"NaN\"\n        .replace(/,\\s*\"[^\"]*\"\\s*:\\s*NaN(?=\\s*[},])/g, \"\")\n        // ➔ remove , \"key\": NaN\n        .replace(/\"[^\"]*\"\\s*:\\s*NaN\\s*(,)?/g, \"\");\n      // ➔ remove \"key\": NaN\n    }\n\n    normalized = normalized.replace(/,(\\s*[}\\]])/g, \"$1\");\n    // ➔ remove trailing comma before } or ]\n\n    const parsed = JSON.parse(normalized);\n    return cleanParsedData<TData>(parsed, validOptions);\n  } catch (error) {\n    if (validOptions.loggingOnFail) {\n      console.error(\n        \"Failed to parsing at `[@rzl-zone/utils-js]:safeJsonParse`:\",\n        error\n      );\n    }\n\n    validOptions.onError(\n      isError(error)\n        ? new Error(error.message.replace(/^JSON\\.parse:/, \"Failed to parsing\"))\n        : new Error(String(error))\n    );\n\n    return undefined;\n  }\n}\n"],"mappings":"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"}
