const Papa=require("papaparse"); const errors=require("./errors.js"); import { RemoteSource } from "./RemoteSource"; import { ParseErrors, ParseResults, Parsers, RemoteSources, RemoteSourceSettings } from "./interfaces"; import { PublicPapaParseOptions, PrivatePapaParseOptions } from "./interfacesPapaParse"; export class ParserForCSV implements Parsers { private _datasRemoteSource: RemoteSources; private _datas2Parse:string=""; private _parseResults:ParseResults|undefined=undefined; public options: PublicPapaParseOptions= { delimiter: "", newline: "", quoteChar: '"', escapeChar: '"', transformHeader: function(field: string, index: number): string { return field.trim() }, preview: 0, comments: "", fastMode: undefined, transform: undefined } private _privateOptions: PrivatePapaParseOptions= { header: true, download: false, downloadRequestHeaders: undefined, skipEmptyLines: "greedy", withCredentials: undefined } // L'instance d'une autre classe que RemoteSource peut être passée au constructeur constructor(datasRemoteSource?: RemoteSources) { if(datasRemoteSource !== undefined) this._datasRemoteSource=datasRemoteSource; else this._datasRemoteSource=new RemoteSource({ url:"" }); } public setRemoteSource(source: RemoteSourceSettings) { this._datasRemoteSource=new RemoteSource(source); } get datasRemoteSource() : RemoteSources { return this._datasRemoteSource; } set datas2Parse(datas: string) { if(datas.trim().length === 0) throw new Error(errors.parserNeedDatas); else this._datas2Parse=datas.trim(); } get datas2Parse() : string { return this._datas2Parse; } get parseResults() : ParseResults|undefined { return this._parseResults; } get privateOptions() : any { return this._privateOptions; } public async parse(): Promise { const parser=this; let parseContent=""; if(parser._datasRemoteSource.url !== "") { parseContent=parser._datasRemoteSource.url; this._privateOptions.download=true; this._privateOptions.withCredentials=parser._datasRemoteSource.withCredentials; if(parser._datasRemoteSource.headers !== undefined) { this._privateOptions.downloadRequestHeaders={}; for(let header of parser._datasRemoteSource.headers) this._privateOptions.downloadRequestHeaders[header.key]=header.value; } } else if(parser._datas2Parse !== "") parseContent=parser._datas2Parse; else throw new Error(errors.parserNeedSource); return new Promise((resolve,reject) => { Papa.parse(parseContent, { delimiter: this.options.delimiter, newline: this.options.newline, quoteChar: this.options.quoteChar, escapeChar: this.options.escapeChar, header: true, transformHeader: this.options.transformHeader, preview: this.options.preview, comments: this.options.comments, complete: function(results :any) { // Attention, Papa Parse peut accepter un nom de champ vide ou en doublon // De plus dans le cas de doublons, il renomme les champs surnémaires "_n" au nom du champs // Or, ceci peut être le vrai nom d'un champ // A voir, si cette regression disparait dans l'avenir. Test unitaire désactivé en attendant let realFields: string[]=[], parseErrors: ParseErrors[]=[]; for(let field of results.meta.fields) { let checkField=field.trim(); if(checkField !== "" && realFields.indexOf(checkField) === -1) realFields.push(checkField); else parseErrors.push({ row:-1, message: errors.parserFieldNameFail}); } if(realFields.length === 0) reject(new Error(errors.parserFieldsNotFound)); else { parser._parseResults= { datas: results.data, errors: parseErrors.concat(results.errors), // result.errors = errreurs rencontrées par Papa Parse fields: realFields, }; resolve(true); } }, download: this._privateOptions.download, downloadRequestHeaders: this._privateOptions.downloadRequestHeaders, skipEmptyLines:"greedy", fastMode: this.options.fastMode, withCredentials: this._privateOptions.withCredentials, transform: this.options.transform }); }); } }