{"version":3,"file":"underscore-ClYSgvuy.mjs","names":[],"sources":["../../src/underscore.ts"],"sourcesContent":["/**\n * Convert words to a sentence.\n *\n * @param items - An array of words to be joined.\n * @returns A string with the items joined by a comma and the last item joined by \", or\".\n */\nexport const toSentence = (items: string[]): string => {\n  // TODO: Once Safari supports it, use Intl.ListFormat\n  if (items.length == 0) {\n    return '';\n  }\n  if (items.length == 1) {\n    return items[0];\n  }\n  let sentence = items.slice(0, -1).join(', ');\n  sentence += `, or ${items.slice(-1)}`;\n  return sentence;\n};\n\nconst IP_V4_ADDRESS_REGEX =\n  /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n\n/**\n * Checks if a string is a valid IPv4 address.\n *\n * @returns True if the string is a valid IPv4 address, false otherwise.\n */\nexport function isIPV4Address(str: string | undefined | null): boolean {\n  return IP_V4_ADDRESS_REGEX.test(str || '');\n}\n\n/**\n * Converts the first character of a string to uppercase.\n *\n * @param str - The string to be converted.\n * @returns The modified string with the rest of the string unchanged.\n *\n * @example\n * ```ts\n * titleize('hello world') // 'Hello world'\n * ```\n */\nexport function titleize(str: string | undefined | null): string {\n  const s = str || '';\n  return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/**\n * Converts a string from snake_case to camelCase.\n */\nexport function snakeToCamel(str: string | undefined): string {\n  return str ? str.replace(/([-_][a-z])/g, match => match.toUpperCase().replace(/-|_/, '')) : '';\n}\n\n/**\n * Converts a string from camelCase to snake_case.\n */\nexport function camelToSnake(str: string | undefined): string {\n  return str ? str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`) : '';\n}\n\nconst createDeepObjectTransformer = (transform: any) => {\n  const deepTransform = (obj: any): any => {\n    if (!obj) {\n      return obj;\n    }\n\n    if (Array.isArray(obj)) {\n      return obj.map(el => {\n        if (typeof el === 'object' || Array.isArray(el)) {\n          return deepTransform(el);\n        }\n        return el;\n      });\n    }\n\n    const copy = { ...obj };\n    const keys = Object.keys(copy);\n    for (const oldName of keys) {\n      const newName = transform(oldName.toString());\n      if (newName !== oldName) {\n        copy[newName] = copy[oldName];\n        delete copy[oldName];\n      }\n      if (typeof copy[newName] === 'object') {\n        copy[newName] = deepTransform(copy[newName]);\n      }\n    }\n    return copy;\n  };\n\n  return deepTransform;\n};\n\n/**\n * Transforms camelCased objects/ arrays to snake_cased.\n * This function recursively traverses all objects and arrays of the passed value\n * camelCased keys are removed.\n *\n * @function\n */\nexport const deepCamelToSnake = createDeepObjectTransformer(camelToSnake);\n\n/**\n * Transforms snake_cased objects/ arrays to camelCased.\n * This function recursively traverses all objects and arrays of the passed value\n * camelCased keys are removed.\n *\n * @function\n */\nexport const deepSnakeToCamel = createDeepObjectTransformer(snakeToCamel);\n\n/**\n * A function to determine if a value is truthy.\n *\n * @returns True for `true`, true, positive numbers. False for `false`, false, 0, negative integers and anything else.\n */\nexport function isTruthy(value: unknown): boolean {\n  // Return if Boolean\n  if (typeof value === `boolean`) {\n    return value;\n  }\n\n  // Return false if null or undefined\n  if (value === undefined || value === null) {\n    return false;\n  }\n\n  // If the String is true or false\n  if (typeof value === `string`) {\n    if (value.toLowerCase() === `true`) {\n      return true;\n    }\n\n    if (value.toLowerCase() === `false`) {\n      return false;\n    }\n  }\n\n  // Now check if it's a number\n  const number = parseInt(value as string, 10);\n  if (isNaN(number)) {\n    return false;\n  }\n\n  if (number > 0) {\n    return true;\n  }\n\n  // Default to false\n  return false;\n}\n\n/**\n * Get all non-undefined values from an object.\n */\nexport function getNonUndefinedValues<T extends object>(obj: T): Partial<T> {\n  return Object.entries(obj).reduce((acc, [key, value]) => {\n    if (value !== undefined) {\n      acc[key as keyof T] = value;\n    }\n    return acc;\n  }, {} as Partial<T>);\n}\n"],"mappings":";;;;;;;AAMA,MAAa,cAAc,UAA4B;AAErD,KAAI,MAAM,UAAU,EAClB,QAAO;AAET,KAAI,MAAM,UAAU,EAClB,QAAO,MAAM;CAEf,IAAI,WAAW,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,KAAK;AAC5C,aAAY,QAAQ,MAAM,MAAM,GAAG;AACnC,QAAO;;AAGT,MAAM,sBACJ;;;;;;AAOF,SAAgB,cAAc,KAAyC;AACrE,QAAO,oBAAoB,KAAK,OAAO,GAAG;;;;;;;;;;;;;AAc5C,SAAgB,SAAS,KAAwC;CAC/D,MAAM,IAAI,OAAO;AACjB,QAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE;;;;;AAM/C,SAAgB,aAAa,KAAiC;AAC5D,QAAO,MAAM,IAAI,QAAQ,iBAAgB,UAAS,MAAM,aAAa,CAAC,QAAQ,OAAO,GAAG,CAAC,GAAG;;;;;AAM9F,SAAgB,aAAa,KAAiC;AAC5D,QAAO,MAAM,IAAI,QAAQ,WAAU,WAAU,IAAI,OAAO,aAAa,GAAG,GAAG;;AAG7E,MAAM,+BAA+B,cAAmB;CACtD,MAAM,iBAAiB,QAAkB;AACvC,MAAI,CAAC,IACH,QAAO;AAGT,MAAI,MAAM,QAAQ,IAAI,CACpB,QAAO,IAAI,KAAI,OAAM;AACnB,OAAI,OAAO,OAAO,YAAY,MAAM,QAAQ,GAAG,CAC7C,QAAO,cAAc,GAAG;AAE1B,UAAO;IACP;EAGJ,MAAM,OAAO,EAAE,GAAG,KAAK;EACvB,MAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,OAAK,MAAM,WAAW,MAAM;GAC1B,MAAM,UAAU,UAAU,QAAQ,UAAU,CAAC;AAC7C,OAAI,YAAY,SAAS;AACvB,SAAK,WAAW,KAAK;AACrB,WAAO,KAAK;;AAEd,OAAI,OAAO,KAAK,aAAa,SAC3B,MAAK,WAAW,cAAc,KAAK,SAAS;;AAGhD,SAAO;;AAGT,QAAO;;;;;;;;;AAUT,MAAa,mBAAmB,4BAA4B,aAAa;;;;;;;;AASzE,MAAa,mBAAmB,4BAA4B,aAAa;;;;;;AAOzE,SAAgB,SAAS,OAAyB;AAEhD,KAAI,OAAO,UAAU,UACnB,QAAO;AAIT,KAAI,UAAU,UAAa,UAAU,KACnC,QAAO;AAIT,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,MAAM,aAAa,KAAK,OAC1B,QAAO;AAGT,MAAI,MAAM,aAAa,KAAK,QAC1B,QAAO;;CAKX,MAAM,SAAS,SAAS,OAAiB,GAAG;AAC5C,KAAI,MAAM,OAAO,CACf,QAAO;AAGT,KAAI,SAAS,EACX,QAAO;AAIT,QAAO;;;;;AAMT,SAAgB,sBAAwC,KAAoB;AAC1E,QAAO,OAAO,QAAQ,IAAI,CAAC,QAAQ,KAAK,CAAC,KAAK,WAAW;AACvD,MAAI,UAAU,OACZ,KAAI,OAAkB;AAExB,SAAO;IACN,EAAE,CAAe"}