@@ -25,6 +25,7 @@ import fs from 'fs'
2525 * hence all PapaParse options are supported.
2626 * @param options Configuration object. Supports all Papaparse parse config options.
2727 * @returns DataFrame containing the parsed CSV file.
28+ * @throws {Error } If file cannot be read or parsed
2829 * @example
2930 * ```
3031 * import { readCSV } from "danfojs-node"
@@ -52,6 +53,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
5253
5354 if ( filePath . startsWith ( "http" ) || filePath . startsWith ( "https" ) ) {
5455 return new Promise ( ( resolve , reject ) => {
56+ let hasError = false ;
5557 const optionsWithDefaults = {
5658 header : true ,
5759 dynamicTyping : true ,
@@ -63,6 +65,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
6365 // reject any non-2xx status codes
6466 dataStream . on ( 'response' , ( response : any ) => {
6567 if ( response . statusCode < 200 || response . statusCode >= 300 ) {
68+ hasError = true ;
6669 reject ( new Error ( `HTTP ${ response . statusCode } : ${ response . statusMessage } ` ) ) ;
6770 }
6871 } ) ;
@@ -72,30 +75,73 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
7275
7376 const data : any = [ ] ;
7477 parseStream . on ( "data" , ( chunk : any ) => {
75- data . push ( chunk ) ;
78+ if ( ! hasError ) {
79+ data . push ( chunk ) ;
80+ }
81+ } ) ;
82+
83+ parseStream . on ( "error" , ( error : any ) => {
84+ hasError = true ;
85+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
7686 } ) ;
7787
7888 parseStream . on ( "finish" , ( ) => {
79- resolve ( new DataFrame ( data , frameConfig ) ) ;
89+ if ( hasError ) return ;
90+
91+ if ( ! data || data . length === 0 ) {
92+ reject ( new Error ( 'No data found in CSV file' ) ) ;
93+ return ;
94+ }
95+
96+ try {
97+ const df = new DataFrame ( data , frameConfig ) ;
98+ resolve ( df ) ;
99+ } catch ( error ) {
100+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
101+ reject ( new Error ( `Failed to create DataFrame: ${ errorMessage } ` ) ) ;
102+ }
80103 } ) ;
81104 } ) ;
82105
83106 } else {
84107 return new Promise ( ( resolve , reject ) => {
85108 fs . access ( filePath , fs . constants . F_OK , ( err ) => {
86109 if ( err ) {
87- reject ( "ENOENT: no such file or directory" ) ;
110+ reject ( new Error ( "ENOENT: no such file or directory" ) ) ;
111+ return ;
88112 }
89113
90114 const fileStream = fs . createReadStream ( filePath )
115+ let hasError = false ;
91116
92117 Papa . parse ( fileStream , {
93118 header : true ,
94119 dynamicTyping : true ,
95120 ...options ,
121+ error : ( error ) => {
122+ hasError = true ;
123+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
124+ } ,
96125 complete : results => {
97- const df = new DataFrame ( results . data , frameConfig ) ;
98- resolve ( df ) ;
126+ if ( hasError ) return ;
127+
128+ if ( ! results . data || results . data . length === 0 ) {
129+ reject ( new Error ( 'No data found in CSV file' ) ) ;
130+ return ;
131+ }
132+
133+ if ( results . errors && results . errors . length > 0 ) {
134+ reject ( new Error ( `CSV parsing errors: ${ results . errors . map ( e => e . message ) . join ( ', ' ) } ` ) ) ;
135+ return ;
136+ }
137+
138+ try {
139+ const df = new DataFrame ( results . data , frameConfig ) ;
140+ resolve ( df ) ;
141+ } catch ( error ) {
142+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
143+ reject ( new Error ( `Failed to create DataFrame: ${ errorMessage } ` ) ) ;
144+ }
99145 }
100146 } ) ;
101147 } )
@@ -109,6 +155,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
109155 * hence all PapaParse options are supported.
110156 * @param callback Callback function to be called once the specifed rows are parsed into DataFrame.
111157 * @param options Configuration object. Supports all Papaparse parse config options.
158+ * @throws {Error } If file cannot be read or parsed
112159 * @example
113160 * ```
114161 * import { streamCSV } from "danfojs-node"
@@ -128,12 +175,14 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o
128175 ...options ,
129176 }
130177 return new Promise ( ( resolve , reject ) => {
131- let count = 0
178+ let count = 0 ;
179+ let hasError = false ;
132180 const dataStream = request . get ( filePath ) ;
133181
134182 // reject any non-2xx status codes
135183 dataStream . on ( 'response' , ( response : any ) => {
136184 if ( response . statusCode < 200 || response . statusCode >= 300 ) {
185+ hasError = true ;
137186 reject ( new Error ( `HTTP ${ response . statusCode } : ${ response . statusMessage } ` ) ) ;
138187 }
139188 } ) ;
@@ -142,35 +191,71 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o
142191 dataStream . pipe ( parseStream ) ;
143192
144193 parseStream . on ( "data" , ( chunk : any ) => {
145- const df = new DataFrame ( [ chunk ] , { ...frameConfig , index : [ count ++ ] , } ) ;
146- callback ( df ) ;
194+ if ( hasError ) return ;
195+ try {
196+ const df = new DataFrame ( [ chunk ] , { ...frameConfig , index : [ count ++ ] } ) ;
197+ callback ( df ) ;
198+ } catch ( error ) {
199+ hasError = true ;
200+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
201+ reject ( new Error ( `Failed to process CSV chunk: ${ errorMessage } ` ) ) ;
202+ }
147203 } ) ;
148204
149- parseStream . on ( "finish" , ( ) => {
150- resolve ( null ) ;
205+ parseStream . on ( "error" , ( error : any ) => {
206+ hasError = true ;
207+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
151208 } ) ;
152209
210+ parseStream . on ( "finish" , ( ) => {
211+ if ( ! hasError ) {
212+ resolve ( null ) ;
213+ }
214+ } ) ;
153215 } ) ;
154216 } else {
155-
156217 return new Promise ( ( resolve , reject ) => {
157218 fs . access ( filePath , fs . constants . F_OK , ( err ) => {
158219 if ( err ) {
159- reject ( "ENOENT: no such file or directory" ) ;
220+ reject ( new Error ( "ENOENT: no such file or directory" ) ) ;
221+ return ;
160222 }
161223
162224 const fileStream = fs . createReadStream ( filePath )
225+ let hasError = false ;
226+ let count = 0 ;
163227
164- let count = 0
165228 Papa . parse ( fileStream , {
166229 header : true ,
167230 dynamicTyping : true ,
168231 ...options ,
232+ error : ( error ) => {
233+ hasError = true ;
234+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
235+ } ,
169236 step : results => {
170- const df = new DataFrame ( [ results . data ] , { ...frameConfig , index : [ count ++ ] } ) ;
171- callback ( df ) ;
237+ if ( hasError ) return ;
238+
239+ if ( results . errors && results . errors . length > 0 ) {
240+ hasError = true ;
241+ reject ( new Error ( `CSV parsing errors: ${ results . errors . map ( e => e . message ) . join ( ', ' ) } ` ) ) ;
242+ return ;
243+ }
244+
245+ try {
246+ const df = new DataFrame ( [ results . data ] , { ...frameConfig , index : [ count ++ ] } ) ;
247+ callback ( df ) ;
248+ } catch ( error ) {
249+ hasError = true ;
250+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
251+ reject ( new Error ( `Failed to process CSV chunk: ${ errorMessage } ` ) ) ;
252+ }
172253 } ,
173- complete : ( ) => resolve ( null )
254+ complete : ( ) => {
255+ if ( ! hasError ) {
256+ resolve ( null ) ;
257+ }
258+ }
174259 } ) ;
175260 } ) ;
176261 } ) ;
0 commit comments