| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  | import * as plugins from './smartcsv.plugins'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface ICsvConstructorOptions { | 
					
						
							|  |  |  |   headers: boolean; | 
					
						
							| 
									
										
										
										
											2019-10-11 15:48:23 +02:00
										 |  |  |   unquote?: boolean; | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class Csv { | 
					
						
							| 
									
										
										
										
											2019-05-23 17:28:21 +02:00
										 |  |  |   // STATIC
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * creates a Csv Object from string | 
					
						
							|  |  |  |    * @param csvStringArg | 
					
						
							|  |  |  |    * @param optionsArg | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |   public static async createCsvFromString( | 
					
						
							|  |  |  |     csvStringArg: string, | 
					
						
							| 
									
										
										
										
											2018-10-14 23:26:54 +02:00
										 |  |  |     optionsArg: ICsvConstructorOptions | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |   ): Promise<Csv> { | 
					
						
							| 
									
										
										
										
											2018-10-14 23:26:54 +02:00
										 |  |  |     const csvInstance = new Csv(csvStringArg, optionsArg); | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |     await csvInstance.exportAsObject(); | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     return csvInstance; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-23 17:28:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   public static async createCsvStringFromArray(arrayArg: any[]): Promise<string> { | 
					
						
							|  |  |  |     const foundKeys: string[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // lets deal with the keys
 | 
					
						
							|  |  |  |     for (const objectArg of arrayArg) { | 
					
						
							|  |  |  |       for (const key of Object.keys(objectArg)) { | 
					
						
							|  |  |  |         foundKeys.includes(key) ? null : foundKeys.push(key); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // lets deal with the data
 | 
					
						
							|  |  |  |     const dataRows: string[] = []; | 
					
						
							|  |  |  |     for (const objectArg of arrayArg) { | 
					
						
							|  |  |  |       const dataRowArray: string[] = []; | 
					
						
							|  |  |  |       for (const key of foundKeys) { | 
					
						
							|  |  |  |         dataRowArray.push(objectArg[key]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       dataRows.push(dataRowArray.join(',')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // lets put togehter the csv string and return it
 | 
					
						
							|  |  |  |     const headerString = foundKeys.join(','); | 
					
						
							|  |  |  |     const dataString = dataRows.join('\n'); | 
					
						
							|  |  |  |     const csvString = `${headerString}\n${dataString}\n`; | 
					
						
							|  |  |  |     return csvString; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // INSTANCE
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |   public csvString: string; | 
					
						
							|  |  |  |   public headers: string[]; | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |   public keyFrame: string = null; | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |   public data: any[]; | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   public options: ICsvConstructorOptions = { | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |     headers: true, | 
					
						
							|  |  |  |     unquote: true | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-14 23:26:54 +02:00
										 |  |  |   constructor(csvStringArg: string, optionsArg: ICsvConstructorOptions) { | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |     this.options = { | 
					
						
							|  |  |  |       ...this.options, | 
					
						
							|  |  |  |       ...optionsArg | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let csvStringToParse = csvStringArg; | 
					
						
							|  |  |  |     if (this.options.unquote) { | 
					
						
							|  |  |  |       csvStringToParse = csvStringToParse.replace( | 
					
						
							|  |  |  |         /"(.*?)"/gi, | 
					
						
							|  |  |  |         (match, p1, offset, originalString) => { | 
					
						
							|  |  |  |           return plugins.smartstring.base64.encode(match); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.csvString = csvStringToParse; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-14 23:26:54 +02:00
										 |  |  |     this.determineKeyframe(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * determines the keyframe of the csv string | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |   private determineKeyframe() { | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |     let commaLength = 0; | 
					
						
							|  |  |  |     let semicolonLength = 0; | 
					
						
							|  |  |  |     const commaRegexResult = this.csvString.match(/,/g); | 
					
						
							|  |  |  |     const semicolonRegexResult = this.csvString.match(/;/g); | 
					
						
							|  |  |  |     if (commaRegexResult) { | 
					
						
							|  |  |  |       commaLength = commaRegexResult.length; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (semicolonRegexResult) { | 
					
						
							|  |  |  |       semicolonLength = semicolonRegexResult.length; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // tslint:disable-next-line:prefer-conditional-expression
 | 
					
						
							|  |  |  |     if (commaLength < semicolonLength) { | 
					
						
							|  |  |  |       this.keyFrame = ';'; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       this.keyFrame = ','; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-14 23:26:54 +02:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * serializes the csv string | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |   private serializeCsvString() { | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     const rowArray = this.getRows(); | 
					
						
							|  |  |  |     const resultArray = []; | 
					
						
							|  |  |  |     if (this.options.headers) { | 
					
						
							|  |  |  |       this.getHeaders(); | 
					
						
							|  |  |  |       rowArray.shift(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (const row of rowArray) { | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |       resultArray.push(row.split(this.keyFrame)); | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return resultArray; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * gets the rows of the csv | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   private getRows(): string[] { | 
					
						
							| 
									
										
										
										
											2018-06-10 14:29:09 +02:00
										 |  |  |     const rowsArray = this.csvString.split('\n'); | 
					
						
							|  |  |  |     if (rowsArray[rowsArray.length - 1] === '') { | 
					
						
							|  |  |  |       rowsArray.pop(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rowsArray; | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |   private getHeaders() { | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     const rowArray = this.getRows(); | 
					
						
							|  |  |  |     if (this.options.headers) { | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |       let headerRow = rowArray[0]; | 
					
						
							|  |  |  |       this.headers = headerRow.split(this.keyFrame); | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |       if (this.options.unquote) { | 
					
						
							|  |  |  |         const unquotedHeaders: string[] = []; | 
					
						
							|  |  |  |         for (const header of this.headers) { | 
					
						
							|  |  |  |           if (plugins.smartstring.type.isBase64(header)) { | 
					
						
							|  |  |  |             unquotedHeaders.push(plugins.smartstring.base64.decode(header).replace(/['"]+/g, '')); | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             unquotedHeaders.push(header); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this.headers = unquotedHeaders; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return this.headers; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |   private createDataObject(dataArray: string[]) { | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     const neededIterations = dataArray.length; | 
					
						
							|  |  |  |     let resultJson: any = {}; | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |     for (let i = 0; i < neededIterations; i++) { | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |       let value = dataArray[i]; | 
					
						
							|  |  |  |       if (this.options.unquote && plugins.smartstring.type.isBase64(value)) { | 
					
						
							|  |  |  |         value = plugins.smartstring.base64.decode(value).replace(/['"]+/g, '').replace(/['"]+/g, ''); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       resultJson[this.headers[i]] = value; | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return resultJson; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 00:53:27 +02:00
										 |  |  |   public async exportAsObject(): Promise<any> { | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     const serializedData = this.serializeCsvString(); | 
					
						
							|  |  |  |     const dataObjects = []; | 
					
						
							|  |  |  |     for (const dataArray of serializedData) { | 
					
						
							|  |  |  |       dataObjects.push(this.createDataObject(dataArray)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-10 18:30:29 +02:00
										 |  |  |     this.data = dataObjects; | 
					
						
							| 
									
										
										
										
											2018-05-10 19:47:14 +02:00
										 |  |  |     return dataObjects; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |