const Papa = require("papaparse"); const errors = require("./errors.js"); import { ParseResults, Parsers, RemoteSource } from "./freeDatas2HTMLInterfaces"; interface PapaParseOptions { delimiter: string; newline: string; quoteChar: string; escapeChar: string; transformHeader?(field: string, index: number): string; preview: number; comments: false|string, fastMode: boolean|undefined; transform?(value: string): string; } interface PrivatePapaParseOptions { header: boolean; // nécessaire pour obtenir le nom des champs download: boolean; downloadRequestHeaders: undefined| { [index: string]:string|boolean|number } ; skipEmptyLines: string; withCredentials: boolean|undefined; } export class ParserForCSV implements Parsers { private _datasRemoteSource: RemoteSource={ url:"" }; private _datas2Parse:string=""; private _parseResults:ParseResults|undefined=undefined; // Ouverture de certaines options de Papa Parse : // cf. https://www.papaparse.com/docs#config public options: PapaParseOptions = { delimiter: "", newline: "", quoteChar: '"', escapeChar: '"', transformHeader: function(field: string, index: number): string { return field.trim() }, preview: 0, comments: "", fastMode: undefined, transform: undefined } // Options de Papa Parse ne pouvant être modifées de l'extérieur private _privateOptions: PrivatePapaParseOptions = { header: true, // nécessaire pour obtenir le nom des champs download: false, downloadRequestHeaders: undefined, skipEmptyLines:"greedy", withCredentials: undefined } // Revoir tous les protocoles possibles pour une source distante (http(s)://.. , ftp..) set datasRemoteSource(source: RemoteSource) { if(source.url.trim().length === 0) throw new Error(errors.parserNeedUrl); else { source.url=source.url.trim(); this._datasRemoteSource=source; } } get datasRemoteSource() : RemoteSource { 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; } // async dans le cas d'une source distante // Et création d'une Promise car PapaParse utilise des fonctions callback. public async parse(): Promise { const parser=this, options=this.options; 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 i=0; i< parser._datasRemoteSource.headers.length; i++) this._privateOptions.downloadRequestHeaders[parser._datasRemoteSource.headers[i].key]=parser._datasRemoteSource.headers[i].value; } } else if(parser._datas2Parse !== "") parseContent=parser._datas2Parse; else throw new Error(errors.parserNeedSource); return new Promise((resolve,reject) => { Papa.parse(parseContent, { delimiter: options.delimiter, newline: options.newline, quoteChar: options.quoteChar, escapeChar: options.escapeChar, header: true, transformHeader: options.transformHeader, preview: options.preview, comments: options.comments, complete: function(results :any) { // Attention, Papa Parse peut accepter un nom de champ vide let realFields: string[]=[]; for(let field of results.meta.fields) { if(field.trim() !== "") realFields.push(field); } if(realFields.length === 0) reject(new Error(errors.parserFail)); else { parser._parseResults={ datas: results.data, errors: results.errors, fields: realFields, }; resolve(true); } }, download: this._privateOptions.download, downloadRequestHeaders: this._privateOptions.downloadRequestHeaders, skipEmptyLines:"greedy", fastMode: options.fastMode, withCredentials: this._privateOptions.withCredentials, transform: options.transform }); }); } }