@@ -51,7 +51,7 @@ import { useToast } from 'primevue/usetoast';
5151import { db } from ' @/db/SlideRuleDb' ;
5252import { createDuckDbClient } from ' @/utils/SrDuckDb' ;
5353import { useSrParquetCfgStore } from ' @/stores/srParquetCfgStore' ;
54- import {getFetchUrlAndOptions } from " @/utils/fetchUtils" ;
54+ import {getArrowFetchUrlAndOptions } from " @/utils/fetchUtils" ;
5555import { exportCsvStreamed , getWritableFileStream } from " @/utils/SrParquetUtils" ;
5656
5757
@@ -212,43 +212,85 @@ async function exportParquet(fileName: string): Promise<boolean> {
212212}
213213
214214async function exportGeoParquet(fileName : string ) : Promise <boolean > {
215- const { url, options } = await getFetchUrlAndOptions (props .reqId ,true );
215+ // Check if file already has geo metadata
216+ const duckDbClient = await createDuckDbClient ();
217+ const metadata = await duckDbClient .getAllParquetMetadata (fileName );
216218
217- const wb = await getWritableFileStream (` ${fileName }_GEO.parquet ` , ' application/octet-stream' );
218- if (! wb ) return false ;
219+ const hasGeoMetadata = metadata && ' geo' in metadata ;
219220
220- try {
221- console . log ( ' Fetching GeoParquet export: ' , url , options );
222- const response = await fetch ( url , {
223- method: ' POST ' ,
224- body: options . body ,
225- headers: { ' Content-Type ' : ' application/json ' , ... ( options . headers || {}) },
226- } );
221+ if ( hasGeoMetadata ) {
222+ // File already has geo metadata, export as-is using exportParquet pattern
223+ console . log ( ' File already has geo metadata, exporting as-is ' );
224+ const opfsRoot = await navigator . storage . getDirectory ();
225+ const directoryHandle = await opfsRoot . getDirectoryHandle ( ' SlideRule ' );
226+ const fileHandle = await directoryHandle . getFileHandle ( fileName );
227+ const srcFile = await fileHandle . getFile ( );
227228
228- if (! response .ok || ! response .body ) throw new Error (` Export failed with status ${response .status } ` );
229+ const wb = await getWritableFileStream (fileName , ' application/octet-stream' );
230+ if (! wb ) return false ;
229231
230- if (wb .writable ) {
231- // 🚀 Fast path: let the streams connect directly
232- await response .body .pipeTo (wb .writable );
233- } else {
234- // fallback: manual loop (same as version 1)
235- // exportGeoParquet manual loop branch
236- const reader = response .body .getReader ();
237- const writer = wb .getWriter ();
238- while (true ) {
239- const { done, value } = await reader .read ();
240- if (done ) break ;
241- if (value ) {
242- await writer .ready ;
243- await writer .write (value .slice ());
232+ try {
233+ if (wb .writable && typeof srcFile .stream === ' function' ) {
234+ await srcFile .stream ().pipeTo (wb .writable );
235+ } else {
236+ const reader = srcFile .stream ().getReader ();
237+ const writer = wb .getWriter ();
238+ while (true ) {
239+ const { done, value } = await reader .read ();
240+ if (done ) break ;
241+ if (value ) {
242+ await writer .ready ;
243+ await writer .write (value .slice ());
244+ }
244245 }
246+ await writer .close ();
245247 }
246- await writer .close ();
248+ return true ;
249+ } catch (err ) {
250+ console .error (' Stream copy failed:' , err );
251+ try { await wb .abort (err ); } catch {}
252+ return false ;
253+ }
254+ } else {
255+ // No geo metadata, fetch from server with as_geo: true
256+ console .log (' No geo metadata found, fetching GeoParquet from server' );
257+ const { url, options } = await getArrowFetchUrlAndOptions (props .reqId , true );
258+
259+ const baseFileName = fileName .replace (/ \. parquet$ / i , ' ' );
260+ const wb = await getWritableFileStream (` ${baseFileName }_GEO.parquet ` , ' application/octet-stream' );
261+ if (! wb ) return false ;
262+
263+ try {
264+ console .log (' Fetching GeoParquet export:' , url , options );
265+ const response = await fetch (url , {
266+ method: ' POST' ,
267+ body: options .body ,
268+ headers: { ' Content-Type' : ' application/json' , ... (options .headers || {}) },
269+ });
270+
271+ if (! response .ok || ! response .body ) throw new Error (` Export failed with status ${response .status } ` );
272+
273+ if (wb .writable ) {
274+ await response .body .pipeTo (wb .writable );
275+ } else {
276+ const reader = response .body .getReader ();
277+ const writer = wb .getWriter ();
278+ while (true ) {
279+ const { done, value } = await reader .read ();
280+ if (done ) break ;
281+ if (value ) {
282+ await writer .ready ;
283+ await writer .write (value .slice ());
284+ }
285+ }
286+ await writer .close ();
287+ }
288+ return true ;
289+ } catch (err ) {
290+ console .error (' Failed to write GeoParquet file:' , err );
291+ try { await wb .abort (err ); } catch {}
292+ return false ;
247293 }
248- return true ;
249- } catch (err ) {
250- await wb .abort (err );
251- return false ;
252294 }
253295}
254296
0 commit comments