{"version":3,"file":"outsiderninjadevs-core.mjs","sources":["../../../../projects/outsiderninjadevs/core/src/lib/csv/ond-csv-builder.service.ts","../../../../projects/outsiderninjadevs/core/src/public-api.ts","../../../../projects/outsiderninjadevs/core/src/outsiderninjadevs-core.ts"],"sourcesContent":["import {Injectable} from '@angular/core';\n\ntype ValidValuesType = string | number | boolean | null | undefined;\ntype DelimitersType = \";\" | \",\";\n\n/**\n * Service for building and manipulating CSV data.\n * This service provides methods for converting lists of objects to CSV strings and downloading CSV files.\n *\n *  Here is how to inject this service in your component, so you can generate and download a `CSV` file\n *\n *  1. If you don't know the type of data you have, you can use the `any` type\n *\n *  @example\n *\n *  ```ts\n *    constructor(private readonly csv: OndCsvBuilderService){}\n *\n *    handle_click() {\n *      this.csv.toCSVAsync<any>(this.list)\n *        .then(res => {\n *          // Do something\n *        })\n *    }\n *  ```\n *\n *  2. If you have strongly typed your data (you have a data of type `Pet`)\n *\n *  @example\n *\n *  ```ts\n *    constructor(private readonly csv: OndCsvBuilderService){}\n *\n *    handle_click() {\n *      this.csv.toCSVAsync<Pet>(this.list)\n *        .then(res => {\n *          // Do something\n *        })\n *    }\n *  ```\n */\n@Injectable({\n  providedIn: 'root',\n})\nexport class OndCsvBuilderService {\n\n  /**\n   * @description\n   *\n   * Async function that converts a list of objects of type `T` to CSV.\n   *\n   * @example\n   *\n   *  ```ts\n   *    // we declare the Pet type\n   *    interface Pet {\n   *      name: string;\n   *      age: number;\n   *    }\n   *\n   *    // we create a list of pets\n   *    const pets: Pet[] = [\n   *      {\n   *        name: \"Filo\",\n   *        age: 4\n   *      },\n   *      {\n   *        name: \"Rob\",\n   *        age: 9\n   *      },\n   *    ];\n   *\n   *    // we generate the CSV string value of this list\n   *    // csv is an instance of OndCsvBuilderService injected here\n   *    csv.toCSV<Pet>(pets, \";\")\n   *     .then(csvStr => {\n   *       // do whatever you want with the string csv value.\n   *     });\n   *  ```\n   *\n   * @template T\n   * @param {T[]} items The list of objects to convert to CSV.\n   * @param {DelimitersType} delimiter (optional) the delimiter of the CSV cells\n   * @returns {Promise<string>}\n   */\n  public toCSVAsync = async <T extends object>(items: T[], delimiter: DelimitersType = \",\"): Promise<string> => {\n    return new Promise<string>((resolve, reject) => {\n      try {\n\n        const headers = this.generateHeaders(items);\n        let csvString = headers.join(delimiter) + '\\n';\n\n        for (const item of items) {\n          const values = this.getElementValuesOfKeys(item, headers);\n          csvString += values.join(delimiter) + '\\n';\n        }\n\n        resolve(csvString);\n      } catch (err) {\n        reject(err);\n      }\n    });\n  }\n\n  /**\n   * @description\n   *\n   * Parses a CSV file into an array of objects.\n   *\n   * @param {File} file - The CSV file to parse.\n   * @param {DelimitersType} delimiter - The delimiter used in the CSV file (default: \",\").\n   * @param hasHeader - Indicates whether the CSV file has a header line (default: true).\n   * @returns A promise that resolves to an array of objects representing the CSV data.\n   * @throws An error if the CSV file is invalid or missing a header line.\n   *\n   * @example\n   *\n   * ```ts\n   *  const file: File = // your CSV File object;\n   *\n   *  this.csv.fromCSV(file, ';', true)\n   *    .then((data) => {\n   *      console.log(data); // the result is here\n   *    })\n   *    .catch((error) => {\n   *      console.error(error);\n   *    });\n   * ```\n   */\n  public fromCSV = async (file: File, delimiter: DelimitersType = \",\", hasHeader?: boolean): Promise<Record<string, ValidValuesType>[]> => {\n    return new Promise<Record<string, ValidValuesType>[]>((resolve, reject) => {\n      const reader = new FileReader();\n\n      reader.onload = (): void => {\n        const fileContents: string | ArrayBuffer | null = reader.result;\n\n        try {\n          if (typeof fileContents !== 'string') {\n            reject(new Error('Invalid file content.'));\n          } else {\n            const lines: string[] = fileContents?.split(/\\r\\n|\\r|\\n/);\n\n            if (hasHeader && lines.length > 0) {\n              const header: string[] | null = this.extractHeader(lines.shift(), delimiter);\n\n              if (!header) {\n                reject(new Error('CSV file does not have a valid header line.'));\n                return;\n              }\n\n              const data: Record<string, ValidValuesType>[] = this.parseData(lines, delimiter, header);\n              resolve(data);\n            } else {\n              reject(new Error('CSV file does not have a header line.'));\n            }\n          }\n        } catch (error) {\n          reject(error);\n        }\n      };\n\n      reader.readAsText(file);\n    });\n  };\n\n  /**\n   * @description\n   *\n   * Extracts the header line from the CSV content.\n   *\n   * @param line - The header line from the CSV file.\n   * @param delimiter - The delimiter used in the CSV file.\n   * @returns {string[] | null} An array of column names from the header line.\n   */\n  private extractHeader(line: string | undefined, delimiter: DelimitersType): string[] | null {\n    if (!line) return null;\n    return line.split(delimiter).map((columnName) => columnName.trim());\n  }\n\n  /**\n   * @description\n   *\n   * Parses the data lines from the CSV content.\n   *\n   * @param {string[]} lines - The data lines from the CSV file.\n   * @param {DelimitersType} delimiter - The delimiter used in the CSV file.\n   * @param {string[]} header - An array of column names from the header line.\n   * @returns {Record<string, any>[]} An array of objects representing the parsed CSV data.\n   */\n  private parseData(lines: string[], delimiter: DelimitersType, header: string[]): Record<string, ValidValuesType>[] {\n    const data: Record<string, ValidValuesType>[] = [];\n\n    for (const line of lines) {\n      const values = line.split(delimiter);\n      const rowData: Record<string, ValidValuesType> = {};\n\n      if (line === \"\") continue;\n      for (let i = 0; i < header.length; i++) {\n        const key = header[i];\n        const value = this.getBestValueOfData(values[i]);\n        if (value === undefined || value === null) continue;\n        rowData[key] = value;\n      }\n\n      data.push(rowData);\n    }\n\n    return data;\n  }\n\n\n  /**\n   * @description\n   *\n   * A function that receive a string value and returns this value in its appropriate type\n   *\n   * @param {string | undefined} value The string value\n   * @returns {ValidValuesType} The value in the appropriate type\n   */\n  private getBestValueOfData = (value?: string): ValidValuesType => {\n    if (value === undefined || value.trim() === \"\") return undefined;\n    if (value.toLowerCase().trim() === \"true\") return true;\n    if (value.toLowerCase().trim() === \"false\") return false;\n    if (!isNaN(Number(value.toLowerCase().trim()))) return Number(value.toLowerCase().trim());\n    return value;\n  }\n\n\n  /**\n   * @description\n   *\n   * private\n   *\n   * @param element\n   * @param keys\n   * @returns values\n   */\n  private getElementValuesOfKeys = <T extends object>(element: T, keys: (keyof T)[]): string[] => {\n    const values: string[] = [];\n    for (const key of keys) {\n      values.push(element[key] as string);\n    }\n    return values;\n  }\n\n  /**\n   * @description\n   *\n   * Async function that downloads a CSV file from a CSV string.\n   *\n   * @param {string} csvString The CSV string to download.\n   * @param {string} filename The name of the CSV file to download.\n   * @returns\n   */\n  public downloadCSVAsync = async (csvString: string, filename: string): Promise<void> => {\n    return new Promise<void>((resolve, reject) => {\n      try {\n        const blob = new Blob([csvString], {type: 'text/csv'});\n        const anchorElement = document.createElement('a');\n        anchorElement.href = URL.createObjectURL(blob);\n        anchorElement.download = filename;\n        anchorElement.click();\n        resolve();\n      } catch (error) {\n        reject(error);\n      }\n    });\n  }\n\n  /**\n   * @description\n   * Generates the headers list\n   *\n   * @param list\n   * @returns headers\n   */\n  private generateHeaders = <T extends object>(list: T[]): (keyof T)[] => {\n    const strKeys: string[] = list ? [...new Set(list.flatMap(obj => Object.keys(obj)))] : [];\n    return strKeys.map(val => {\n      return val as keyof T;\n    });\n\n  }\n}\n","/*\n * Public API Surface of core\n */\n\nexport * from './lib/csv/ond-csv-builder.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCG;MAIU,oBAAoB,CAAA;AAHjC,IAAA,WAAA,GAAA;AAKE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCG;QACI,IAAU,CAAA,UAAA,GAAG,OAAyB,KAAU,EAAE,SAA4B,GAAA,GAAG,KAAqB;YAC3G,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,KAAI;AAC7C,gBAAA,IAAI;oBAEF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;oBAC5C,IAAI,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;AAE/C,oBAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;wBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;wBAC1D,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;qBAC5C;oBAED,OAAO,CAAC,SAAS,CAAC,CAAC;iBACpB;gBAAC,OAAO,GAAG,EAAE;oBACZ,MAAM,CAAC,GAAG,CAAC,CAAC;iBACb;AACH,aAAC,CAAC,CAAC;AACL,SAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;QACI,IAAO,CAAA,OAAA,GAAG,OAAO,IAAU,EAAE,YAA4B,GAAG,EAAE,SAAmB,KAAgD;YACtI,OAAO,IAAI,OAAO,CAAoC,CAAC,OAAO,EAAE,MAAM,KAAI;AACxE,gBAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;AAEhC,gBAAA,MAAM,CAAC,MAAM,GAAG,MAAW;AACzB,oBAAA,MAAM,YAAY,GAAgC,MAAM,CAAC,MAAM,CAAC;AAEhE,oBAAA,IAAI;AACF,wBAAA,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;AACpC,4BAAA,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;yBAC5C;6BAAM;4BACL,MAAM,KAAK,GAAa,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;4BAE1D,IAAI,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACjC,gCAAA,MAAM,MAAM,GAAoB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;gCAE7E,IAAI,CAAC,MAAM,EAAE;AACX,oCAAA,MAAM,CAAC,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC,CAAC;oCACjE,OAAO;iCACR;AAED,gCAAA,MAAM,IAAI,GAAsC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;gCACzF,OAAO,CAAC,IAAI,CAAC,CAAC;6BACf;iCAAM;AACL,gCAAA,MAAM,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;6BAC5D;yBACF;qBACF;oBAAC,OAAO,KAAK,EAAE;wBACd,MAAM,CAAC,KAAK,CAAC,CAAC;qBACf;AACH,iBAAC,CAAC;AAEF,gBAAA,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC1B,aAAC,CAAC,CAAC;AACL,SAAC,CAAC;AAgDF;;;;;;;AAOG;AACK,QAAA,IAAA,CAAA,kBAAkB,GAAG,CAAC,KAAc,KAAqB;YAC/D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;AAAE,gBAAA,OAAO,SAAS,CAAC;YACjE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM;AAAE,gBAAA,OAAO,IAAI,CAAC;YACvD,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,OAAO;AAAE,gBAAA,OAAO,KAAK,CAAC;AACzD,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAE,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1F,YAAA,OAAO,KAAK,CAAC;AACf,SAAC,CAAA;AAGD;;;;;;;;AAQG;AACK,QAAA,IAAA,CAAA,sBAAsB,GAAG,CAAmB,OAAU,EAAE,IAAiB,KAAc;YAC7F,MAAM,MAAM,GAAa,EAAE,CAAC;AAC5B,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;gBACtB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAW,CAAC,CAAC;aACrC;AACD,YAAA,OAAO,MAAM,CAAC;AAChB,SAAC,CAAA;AAED;;;;;;;;AAQG;AACI,QAAA,IAAA,CAAA,gBAAgB,GAAG,OAAO,SAAiB,EAAE,QAAgB,KAAmB;YACrF,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;AAC3C,gBAAA,IAAI;AACF,oBAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAC,IAAI,EAAE,UAAU,EAAC,CAAC,CAAC;oBACvD,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;oBAClD,aAAa,CAAC,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/C,oBAAA,aAAa,CAAC,QAAQ,GAAG,QAAQ,CAAC;oBAClC,aAAa,CAAC,KAAK,EAAE,CAAC;AACtB,oBAAA,OAAO,EAAE,CAAC;iBACX;gBAAC,OAAO,KAAK,EAAE;oBACd,MAAM,CAAC,KAAK,CAAC,CAAC;iBACf;AACH,aAAC,CAAC,CAAC;AACL,SAAC,CAAA;AAED;;;;;;AAMG;AACK,QAAA,IAAA,CAAA,eAAe,GAAG,CAAmB,IAAS,KAAiB;AACrE,YAAA,MAAM,OAAO,GAAa,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC1F,YAAA,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,IAAG;AACvB,gBAAA,OAAO,GAAc,CAAC;AACxB,aAAC,CAAC,CAAC;AAEL,SAAC,CAAA;AACF,KAAA;AAtHC;;;;;;;;AAQG;IACK,aAAa,CAAC,IAAwB,EAAE,SAAyB,EAAA;AACvE,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,IAAI,CAAC;AACvB,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;KACrE;AAED;;;;;;;;;AASG;AACK,IAAA,SAAS,CAAC,KAAe,EAAE,SAAyB,EAAE,MAAgB,EAAA;QAC5E,MAAM,IAAI,GAAsC,EAAE,CAAC;AAEnD,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACrC,MAAM,OAAO,GAAoC,EAAE,CAAC;YAEpD,IAAI,IAAI,KAAK,EAAE;gBAAE,SAAS;AAC1B,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACtC,gBAAA,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,gBAAA,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;oBAAE,SAAS;AACpD,gBAAA,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;aACtB;AAED,YAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SACpB;AAED,QAAA,OAAO,IAAI,CAAC;KACb;8GApKU,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA,EAAA;AAApB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,oBAAoB,cAFnB,MAAM,EAAA,CAAA,CAAA,EAAA;;2FAEP,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAHhC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA,CAAA;;;AC3CD;;AAEG;;ACFH;;AAEG;;;;"}