@gisfun/maplibre-gl-components 0.15.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1960 -0
- package/dist/ControlGrid-DN5md8hp.cjs +19636 -0
- package/dist/ControlGrid-rVNG7B9O.js +170422 -0
- package/dist/DuckDBConverter-B98M0DFs.cjs +23 -0
- package/dist/DuckDBConverter-RPq48-t0.js +434 -0
- package/dist/ShapefileConverter-AjbEjEyq.cjs +1 -0
- package/dist/ShapefileConverter-trvt8J3z.js +125 -0
- package/dist/decoder-CLokFc0V.js +8 -0
- package/dist/decoder-D9LU4bUo.cjs +1 -0
- package/dist/deflate-BA1jZeSX.js +10 -0
- package/dist/deflate-DEdCz12a.cjs +1 -0
- package/dist/geojson-BQSVgKFt.cjs +1 -0
- package/dist/geojson-BSUuDj5k.js +2551 -0
- package/dist/geotiff-De1w1lBy.cjs +8 -0
- package/dist/geotiff-o_Fq1Na4.js +3108 -0
- package/dist/index-8ZZtuDTp.js +705 -0
- package/dist/index-B-Nr9y7J.cjs +84 -0
- package/dist/index-B5NoFrpY.js +8892 -0
- package/dist/index-Bi1MMPUx.js +4163 -0
- package/dist/index-C9fk_HKR.js +167 -0
- package/dist/index-CBBRBJvR.cjs +274 -0
- package/dist/index-CZxPF1qt.js +4 -0
- package/dist/index-CiDPSJ9T.cjs +1 -0
- package/dist/index-CjM_nbxd.cjs +107 -0
- package/dist/index-DQXdX5y1.js +4666 -0
- package/dist/index-Dh1kpCb6.cjs +1 -0
- package/dist/index-IrsIiQNM.cjs +4 -0
- package/dist/index.cjs +3819 -0
- package/dist/index.mjs +19580 -0
- package/dist/jpeg-CF9OGQg_.js +533 -0
- package/dist/jpeg-JSQOxGHy.cjs +1 -0
- package/dist/lerc-7LlQoT6u.js +1032 -0
- package/dist/lerc-BIsodce9.cjs +1 -0
- package/dist/lzw-BZniWIYG.js +84 -0
- package/dist/lzw-BhML-BvT.cjs +1 -0
- package/dist/main-dist-Bymiy5aM.cjs +2 -0
- package/dist/main-dist-Cv8AKwrY.js +629 -0
- package/dist/maplibre-geoman.es-Bxdg-2EU.cjs +129 -0
- package/dist/maplibre-geoman.es-CFgM2ajb.js +22827 -0
- package/dist/maplibre-gl-components.css +1 -0
- package/dist/packbits-B9b7gX2c.cjs +1 -0
- package/dist/packbits-DWY5O-FG.js +24 -0
- package/dist/pako.esm-Bx5X36Wo.js +1074 -0
- package/dist/pako.esm-DZC2QrbJ.cjs +1 -0
- package/dist/raw-C3ARbSFo.cjs +1 -0
- package/dist/raw-DUslI1gr.js +9 -0
- package/dist/react.cjs +1 -0
- package/dist/react.mjs +1306 -0
- package/dist/types/index.d.ts +44 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/lib/adapters/AddVectorAdapter.d.ts +66 -0
- package/dist/types/lib/adapters/AddVectorAdapter.d.ts.map +1 -0
- package/dist/types/lib/adapters/CogLayerAdapter.d.ts +126 -0
- package/dist/types/lib/adapters/CogLayerAdapter.d.ts.map +1 -0
- package/dist/types/lib/adapters/PMTilesLayerAdapter.d.ts +78 -0
- package/dist/types/lib/adapters/PMTilesLayerAdapter.d.ts.map +1 -0
- package/dist/types/lib/adapters/StacLayerAdapter.d.ts +71 -0
- package/dist/types/lib/adapters/StacLayerAdapter.d.ts.map +1 -0
- package/dist/types/lib/adapters/ZarrLayerAdapter.d.ts +72 -0
- package/dist/types/lib/adapters/ZarrLayerAdapter.d.ts.map +1 -0
- package/dist/types/lib/adapters/index.d.ts +7 -0
- package/dist/types/lib/adapters/index.d.ts.map +1 -0
- package/dist/types/lib/addControlGrid.d.ts +80 -0
- package/dist/types/lib/addControlGrid.d.ts.map +1 -0
- package/dist/types/lib/colormaps/diverging.d.ts +30 -0
- package/dist/types/lib/colormaps/diverging.d.ts.map +1 -0
- package/dist/types/lib/colormaps/index.d.ts +32 -0
- package/dist/types/lib/colormaps/index.d.ts.map +1 -0
- package/dist/types/lib/colormaps/misc.d.ts +38 -0
- package/dist/types/lib/colormaps/misc.d.ts.map +1 -0
- package/dist/types/lib/colormaps/sequential.d.ts +22 -0
- package/dist/types/lib/colormaps/sequential.d.ts.map +1 -0
- package/dist/types/lib/converters/DuckDBConverter.d.ts +112 -0
- package/dist/types/lib/converters/DuckDBConverter.d.ts.map +1 -0
- package/dist/types/lib/converters/ShapefileConverter.d.ts +56 -0
- package/dist/types/lib/converters/ShapefileConverter.d.ts.map +1 -0
- package/dist/types/lib/converters/index.d.ts +8 -0
- package/dist/types/lib/converters/index.d.ts.map +1 -0
- package/dist/types/lib/converters/types.d.ts +75 -0
- package/dist/types/lib/converters/types.d.ts.map +1 -0
- package/dist/types/lib/core/AddVector.d.ts +116 -0
- package/dist/types/lib/core/AddVector.d.ts.map +1 -0
- package/dist/types/lib/core/Basemap.d.ts +206 -0
- package/dist/types/lib/core/Basemap.d.ts.map +1 -0
- package/dist/types/lib/core/BasemapReact.d.ts +32 -0
- package/dist/types/lib/core/BasemapReact.d.ts.map +1 -0
- package/dist/types/lib/core/BookmarkControl.d.ts +180 -0
- package/dist/types/lib/core/BookmarkControl.d.ts.map +1 -0
- package/dist/types/lib/core/ChoroplethControl.d.ts +105 -0
- package/dist/types/lib/core/ChoroplethControl.d.ts.map +1 -0
- package/dist/types/lib/core/CogLayer.d.ts +139 -0
- package/dist/types/lib/core/CogLayer.d.ts.map +1 -0
- package/dist/types/lib/core/CogLayerReact.d.ts +32 -0
- package/dist/types/lib/core/CogLayerReact.d.ts.map +1 -0
- package/dist/types/lib/core/Colorbar.d.ts +133 -0
- package/dist/types/lib/core/Colorbar.d.ts.map +1 -0
- package/dist/types/lib/core/ColorbarGuiControl.d.ts +79 -0
- package/dist/types/lib/core/ColorbarGuiControl.d.ts.map +1 -0
- package/dist/types/lib/core/ColorbarReact.d.ts +34 -0
- package/dist/types/lib/core/ColorbarReact.d.ts.map +1 -0
- package/dist/types/lib/core/ControlGrid.d.ts +125 -0
- package/dist/types/lib/core/ControlGrid.d.ts.map +1 -0
- package/dist/types/lib/core/ControlGridReact.d.ts +32 -0
- package/dist/types/lib/core/ControlGridReact.d.ts.map +1 -0
- package/dist/types/lib/core/HtmlControl.d.ts +140 -0
- package/dist/types/lib/core/HtmlControl.d.ts.map +1 -0
- package/dist/types/lib/core/HtmlControlReact.d.ts +32 -0
- package/dist/types/lib/core/HtmlControlReact.d.ts.map +1 -0
- package/dist/types/lib/core/HtmlGuiControl.d.ts +68 -0
- package/dist/types/lib/core/HtmlGuiControl.d.ts.map +1 -0
- package/dist/types/lib/core/InspectControl.d.ts +202 -0
- package/dist/types/lib/core/InspectControl.d.ts.map +1 -0
- package/dist/types/lib/core/InspectControlReact.d.ts +32 -0
- package/dist/types/lib/core/InspectControlReact.d.ts.map +1 -0
- package/dist/types/lib/core/Legend.d.ts +142 -0
- package/dist/types/lib/core/Legend.d.ts.map +1 -0
- package/dist/types/lib/core/LegendGuiControl.d.ts +69 -0
- package/dist/types/lib/core/LegendGuiControl.d.ts.map +1 -0
- package/dist/types/lib/core/LegendReact.d.ts +34 -0
- package/dist/types/lib/core/LegendReact.d.ts.map +1 -0
- package/dist/types/lib/core/MeasureControl.d.ts +211 -0
- package/dist/types/lib/core/MeasureControl.d.ts.map +1 -0
- package/dist/types/lib/core/MinimapControl.d.ts +77 -0
- package/dist/types/lib/core/MinimapControl.d.ts.map +1 -0
- package/dist/types/lib/core/MinimapControlReact.d.ts +32 -0
- package/dist/types/lib/core/MinimapControlReact.d.ts.map +1 -0
- package/dist/types/lib/core/PMTilesLayer.d.ts +119 -0
- package/dist/types/lib/core/PMTilesLayer.d.ts.map +1 -0
- package/dist/types/lib/core/PrintControl.d.ts +226 -0
- package/dist/types/lib/core/PrintControl.d.ts.map +1 -0
- package/dist/types/lib/core/SearchControl.d.ts +172 -0
- package/dist/types/lib/core/SearchControl.d.ts.map +1 -0
- package/dist/types/lib/core/SearchControlReact.d.ts +32 -0
- package/dist/types/lib/core/SearchControlReact.d.ts.map +1 -0
- package/dist/types/lib/core/StacLayer.d.ts +107 -0
- package/dist/types/lib/core/StacLayer.d.ts.map +1 -0
- package/dist/types/lib/core/StacSearch.d.ts +109 -0
- package/dist/types/lib/core/StacSearch.d.ts.map +1 -0
- package/dist/types/lib/core/Terrain.d.ts +165 -0
- package/dist/types/lib/core/Terrain.d.ts.map +1 -0
- package/dist/types/lib/core/TerrainReact.d.ts +32 -0
- package/dist/types/lib/core/TerrainReact.d.ts.map +1 -0
- package/dist/types/lib/core/VectorDataset.d.ts +228 -0
- package/dist/types/lib/core/VectorDataset.d.ts.map +1 -0
- package/dist/types/lib/core/VectorDatasetReact.d.ts +31 -0
- package/dist/types/lib/core/VectorDatasetReact.d.ts.map +1 -0
- package/dist/types/lib/core/ViewStateControl.d.ts +205 -0
- package/dist/types/lib/core/ViewStateControl.d.ts.map +1 -0
- package/dist/types/lib/core/ViewStateControlReact.d.ts +32 -0
- package/dist/types/lib/core/ViewStateControlReact.d.ts.map +1 -0
- package/dist/types/lib/core/ZarrLayer.d.ts +110 -0
- package/dist/types/lib/core/ZarrLayer.d.ts.map +1 -0
- package/dist/types/lib/core/types.d.ts +2793 -0
- package/dist/types/lib/core/types.d.ts.map +1 -0
- package/dist/types/lib/hooks/index.d.ts +13 -0
- package/dist/types/lib/hooks/index.d.ts.map +1 -0
- package/dist/types/lib/hooks/useBasemap.d.ts +43 -0
- package/dist/types/lib/hooks/useBasemap.d.ts.map +1 -0
- package/dist/types/lib/hooks/useCogLayer.d.ts +44 -0
- package/dist/types/lib/hooks/useCogLayer.d.ts.map +1 -0
- package/dist/types/lib/hooks/useColorbar.d.ts +36 -0
- package/dist/types/lib/hooks/useColorbar.d.ts.map +1 -0
- package/dist/types/lib/hooks/useControlGrid.d.ts +41 -0
- package/dist/types/lib/hooks/useControlGrid.d.ts.map +1 -0
- package/dist/types/lib/hooks/useHtmlControl.d.ts +39 -0
- package/dist/types/lib/hooks/useHtmlControl.d.ts.map +1 -0
- package/dist/types/lib/hooks/useInspectControl.d.ts +49 -0
- package/dist/types/lib/hooks/useInspectControl.d.ts.map +1 -0
- package/dist/types/lib/hooks/useLegend.d.ts +41 -0
- package/dist/types/lib/hooks/useLegend.d.ts.map +1 -0
- package/dist/types/lib/hooks/useMinimapControl.d.ts +35 -0
- package/dist/types/lib/hooks/useMinimapControl.d.ts.map +1 -0
- package/dist/types/lib/hooks/useSearchControl.d.ts +43 -0
- package/dist/types/lib/hooks/useSearchControl.d.ts.map +1 -0
- package/dist/types/lib/hooks/useTerrain.d.ts +43 -0
- package/dist/types/lib/hooks/useTerrain.d.ts.map +1 -0
- package/dist/types/lib/hooks/useVectorDataset.d.ts +35 -0
- package/dist/types/lib/hooks/useVectorDataset.d.ts.map +1 -0
- package/dist/types/lib/hooks/useViewState.d.ts +43 -0
- package/dist/types/lib/hooks/useViewState.d.ts.map +1 -0
- package/dist/types/lib/utils/color.d.ts +47 -0
- package/dist/types/lib/utils/color.d.ts.map +1 -0
- package/dist/types/lib/utils/fileHelpers.d.ts +207 -0
- package/dist/types/lib/utils/fileHelpers.d.ts.map +1 -0
- package/dist/types/lib/utils/helpers.d.ts +48 -0
- package/dist/types/lib/utils/helpers.d.ts.map +1 -0
- package/dist/types/lib/utils/index.d.ts +4 -0
- package/dist/types/lib/utils/index.d.ts.map +1 -0
- package/dist/types/lib/utils/providers.d.ts +46 -0
- package/dist/types/lib/utils/providers.d.ts.map +1 -0
- package/dist/types/react.d.ts +15 -0
- package/dist/types/react.d.ts.map +1 -0
- package/dist/webimage-CBRffWZD.cjs +1 -0
- package/dist/webimage-ibSPOLHJ.js +19 -0
- package/package.json +137 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";var G=Object.create;var C=Object.defineProperty;var J=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var I=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var K=(p,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of W(e))!M.call(p,i)&&i!==t&&C(p,i,{get:()=>e[i],enumerable:!(r=J(e,i))||r.enumerable});return p};var H=(p,e,t)=>(t=p!=null?G(I(p)):{},K(e||!p||!p.__esModule?C(t,"default",{value:p,enumerable:!0}):t,p));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let B=null;function Y(){return B||(B=new F),B}class F{_duckdb=null;_db=null;_worker=null;_initialized=!1;_initializing=!1;_bundleUrl;constructor(e){this._bundleUrl=e}isReady(){return this._initialized&&this._db!==null}async initialize(e){if(!this._initialized){if(this._initializing){for(;this._initializing;)await new Promise(t=>setTimeout(t,50));return}this._initializing=!0;try{e?.({stage:"initializing",percent:0,message:"Loading DuckDB WASM..."});let t;try{const o=await import("@duckdb/duckdb-wasm");t=o.default||o}catch(o){throw new Error(`DuckDB WASM is not installed or failed to load. Install it with: npm install @duckdb/duckdb-wasm. Error: ${o instanceof Error?o.message:"Unknown error"}`)}this._duckdb=t,e?.({stage:"initializing",percent:30,message:"Selecting DuckDB bundle..."});let r;if(this._duckdb.getJsDelivrBundles){const o=this._duckdb.getJsDelivrBundles();r=await this._duckdb.selectBundle(o)}else{const o=this._getJsDelivrBundles();r=await this._duckdb.selectBundle(o)}e?.({stage:"initializing",percent:50,message:"Instantiating DuckDB..."});const i=new this._duckdb.ConsoleLogger(4);let g,a=null;try{a=URL.createObjectURL(new Blob([`importScripts("${r.mainWorker}");`],{type:"text/javascript"})),g=new Worker(a)}catch(o){throw a&&URL.revokeObjectURL(a),new Error(`Failed to create DuckDB worker: ${o instanceof Error?o.message:"Unknown error"}`)}this._worker=g;const w=new this._duckdb.AsyncDuckDB(i,g);try{await w.instantiate(r.mainModule,r.pthreadWorker)}catch(o){throw new Error(`Failed to instantiate DuckDB: ${o instanceof Error?o.message:"Unknown error"}`)}a&&URL.revokeObjectURL(a),this._db=w,e?.({stage:"initializing",percent:70,message:"Loading spatial extension..."});const n=await this._db.connect();try{await n.query("INSTALL spatial"),await n.query("LOAD spatial")}catch(o){console.warn("Failed to load spatial extension, some features may not work:",o)}finally{await n.close()}this._initialized=!0,e?.({stage:"initializing",percent:100,message:"DuckDB ready"})}catch(t){throw e?.({stage:"error",message:`Failed to initialize DuckDB: ${t instanceof Error?t.message:"Unknown error"}`}),t}finally{this._initializing=!1}}}_getJsDelivrBundles(){const e=this._bundleUrl||"https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm@latest/dist";return{mvp:{mainModule:`${e}/duckdb-mvp.wasm`,mainWorker:`${e}/duckdb-browser-mvp.worker.js`},eh:{mainModule:`${e}/duckdb-eh.wasm`,mainWorker:`${e}/duckdb-browser-eh.worker.js`}}}async convert(e,t,r){const i=performance.now(),g=this._detectFormat(t);if(this.isReady()||await this.initialize(r),!this._db)throw new Error("DuckDB not initialized");r?.({stage:"loading",percent:0,message:`Loading ${t}...`});const a=new Uint8Array(e);await this._db.registerFileBuffer(t,a);const w=await this._db.connect();try{r?.({stage:"converting",percent:30,message:"Reading spatial data..."});let n;g==="geoparquet"||g==="parquet"?n=`read_parquet('${t}')`:n=`ST_Read('${t}')`;const y=(await w.query(`
|
|
2
|
+
DESCRIBE SELECT * FROM ${n}
|
|
3
|
+
`)).toArray();let c=null,k="",h=null,u=null,l=null;const d=[],N=["lat","latitude","y","lat_y","point_y"],E=["lon","lng","long","longitude","x","lon_x","long_x","point_x"],D=["wkt","wkt_geom","wkt_geometry","geometry_wkt"];for(const m of y){const s=m.column_name,L=m.column_type?.toUpperCase()||"",_=s.toLowerCase(),A=L.includes("GEOMETRY"),x=_==="geom"||_==="geometry"||_==="wkb_geometry"||_==="the_geom"||_==="shape",q=L.includes("BLOB")&&x;A||x||q?c||(c=s,k=L):N.includes(_)&&!h?(h=s,d.push(s)):E.includes(_)&&!u?(u=s,d.push(s)):D.includes(_)&&!l?l=s:d.push(s)}let f=!1,b=!1;if(!c)if(l)b=!0;else if(h&&u){f=!0;const m=d.indexOf(h);m>-1&&d.splice(m,1);const s=d.indexOf(u);s>-1&&d.splice(s,1)}else throw new Error("No geometry column found in the file. For CSV/Excel files, include a geometry column, WKT column, or lat/lon columns.");r?.({stage:"converting",percent:50,message:"Converting to GeoJSON..."});const v=d.length>0?`json_object(${d.map(m=>`'${m}', "${m}"`).join(", ")})`:"'{}'::JSON";let S,$;f&&h&&u?(S=`ST_AsGeoJSON(ST_Point("${u}", "${h}"))`,$=`"${h}" IS NOT NULL AND "${u}" IS NOT NULL`):b&&l?(S=`ST_AsGeoJSON(ST_GeomFromText("${l}"))`,$=`"${l}" IS NOT NULL AND "${l}" != ''`):k.includes("BLOB")?(S=`ST_AsGeoJSON(ST_GeomFromWKB("${c}"))`,$=`"${c}" IS NOT NULL`):(S=`ST_AsGeoJSON("${c}")`,$=`"${c}" IS NOT NULL`);const R=(await w.query(`
|
|
4
|
+
SELECT json_object(
|
|
5
|
+
'type', 'Feature',
|
|
6
|
+
'geometry', ${S}::JSON,
|
|
7
|
+
'properties', ${v}
|
|
8
|
+
) as feature
|
|
9
|
+
FROM ${n}
|
|
10
|
+
WHERE ${$}
|
|
11
|
+
`)).toArray();r?.({stage:"converting",percent:80,message:"Building feature collection..."});const T=[],O=new Set;for(const m of R)if(m.feature)try{const s=typeof m.feature=="string"?JSON.parse(m.feature):m.feature;T.push(s),s.geometry?.type&&O.add(s.geometry.type)}catch(s){console.warn("Failed to parse feature:",s)}const U={type:"FeatureCollection",features:T},z=performance.now(),j={originalFormat:g,featureCount:T.length,geometryTypes:Array.from(O),fileSize:e.byteLength,conversionTimeMs:Math.round(z-i)};return r?.({stage:"complete",percent:100,message:`Converted ${T.length} features`}),{geojson:U,warnings:[],metadata:j}}catch(n){throw r?.({stage:"error",message:`Failed to convert: ${n instanceof Error?n.message:"Unknown error"}`}),n}finally{await w.close();try{await this._db.dropFile(t)}catch{}}}_detectFormat(e){switch(e.toLowerCase().split(".").pop()){case"gpkg":return"geopackage";case"parquet":case"geoparquet":return"geoparquet";case"shp":return"shapefile";case"geojson":case"json":return"geojson";case"kml":return"kml";case"kmz":return"kmz";case"gpx":return"gpx";case"fgb":return"flatgeobuf";case"gml":return"gml";case"topojson":return"topojson";case"csv":return"csv";case"xlsx":case"xls":return"xlsx";case"dxf":return"dxf";default:return"unknown"}}async registerRemoteParquet(e,t){if(this.isReady()||await this.initialize(),!this._db||!this._duckdb)throw new Error("DuckDB not initialized");await this._db.registerFileURL(t,e,this._duckdb.DuckDBDataProtocol.HTTP,!1)}async getParquetSchema(e){if(!this._db)throw new Error("DuckDB not initialized");const t=await this._db.connect();try{const i=(await t.query(`DESCRIBE SELECT * FROM read_parquet('${e}')`)).toArray(),g=i.map(y=>({name:y.column_name,type:y.column_type}));let a=null,w=null;const n=[],o=["geom","geometry","wkb_geometry","the_geom","shape"];for(const y of i){const c=y.column_name,k=y.column_type?.toUpperCase()||"",h=c.toLowerCase(),u=k.includes("GEOMETRY"),l=o.includes(h),d=k.includes("BLOB")&&l;(u||l||d)&&!a?(a=c,w=k):n.push(c)}return{geometryColumn:a,geometryColumnType:w,propertyColumns:n,allColumns:g}}finally{await t.close()}}async queryByBounds(e,t,r,i,g){if(!this._db)throw new Error("DuckDB not initialized");const a=await this._db.connect(),[w,n,o,y]=t;try{const c=i.length>0?`json_object(${i.map(f=>`'${f}', "${f}"`).join(", ")})`:"'{}'::JSON",h=(g?.toUpperCase()||"").includes("BLOB");let u,l;h?(u=`ST_AsGeoJSON(ST_GeomFromWKB("${r}"))`,l=`ST_GeomFromWKB("${r}")`):(u=`ST_AsGeoJSON("${r}")`,l=`"${r}"`);const d=`
|
|
12
|
+
SELECT json_object(
|
|
13
|
+
'type', 'Feature',
|
|
14
|
+
'geometry', ${u}::JSON,
|
|
15
|
+
'properties', ${c}
|
|
16
|
+
) as feature
|
|
17
|
+
FROM read_parquet('${e}')
|
|
18
|
+
WHERE "${r}" IS NOT NULL
|
|
19
|
+
AND ST_Intersects(
|
|
20
|
+
${l},
|
|
21
|
+
ST_MakeEnvelope(${w}, ${n}, ${o}, ${y})
|
|
22
|
+
)
|
|
23
|
+
`,E=(await a.query(d)).toArray(),D=[];for(const f of E)if(f.feature)try{const b=typeof f.feature=="string"?JSON.parse(f.feature):f.feature;D.push(b)}catch(b){console.warn("Failed to parse feature:",b)}return{type:"FeatureCollection",features:D}}finally{await a.close()}}async unregisterFile(e){if(this._db)try{await this._db.dropFile(e)}catch{}}dispose(){this._db&&(this._db.terminate().catch(console.error),this._db=null),this._worker&&(this._worker.terminate(),this._worker=null),this._initialized=!1,this._duckdb=null,B===this&&(B=null)}}exports.DuckDBConverter=F;exports.getDuckDBConverter=Y;
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
let S = null;
|
|
2
|
+
function G() {
|
|
3
|
+
return S || (S = new j()), S;
|
|
4
|
+
}
|
|
5
|
+
class j {
|
|
6
|
+
_duckdb = null;
|
|
7
|
+
_db = null;
|
|
8
|
+
_worker = null;
|
|
9
|
+
_initialized = !1;
|
|
10
|
+
_initializing = !1;
|
|
11
|
+
_bundleUrl;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new DuckDBConverter instance.
|
|
14
|
+
*
|
|
15
|
+
* @param bundleUrl - Optional custom URL for DuckDB WASM bundles.
|
|
16
|
+
*/
|
|
17
|
+
constructor(e) {
|
|
18
|
+
this._bundleUrl = e;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Checks if the converter is ready for use.
|
|
22
|
+
*
|
|
23
|
+
* @returns True if initialized and ready.
|
|
24
|
+
*/
|
|
25
|
+
isReady() {
|
|
26
|
+
return this._initialized && this._db !== null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Initializes DuckDB WASM with the spatial extension.
|
|
30
|
+
*
|
|
31
|
+
* @param onProgress - Optional progress callback.
|
|
32
|
+
*/
|
|
33
|
+
async initialize(e) {
|
|
34
|
+
if (!this._initialized) {
|
|
35
|
+
if (this._initializing) {
|
|
36
|
+
for (; this._initializing; )
|
|
37
|
+
await new Promise((t) => setTimeout(t, 50));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this._initializing = !0;
|
|
41
|
+
try {
|
|
42
|
+
e?.({
|
|
43
|
+
stage: "initializing",
|
|
44
|
+
percent: 0,
|
|
45
|
+
message: "Loading DuckDB WASM..."
|
|
46
|
+
});
|
|
47
|
+
let t;
|
|
48
|
+
try {
|
|
49
|
+
const r = await import(
|
|
50
|
+
/* @vite-ignore */
|
|
51
|
+
"@duckdb/duckdb-wasm"
|
|
52
|
+
);
|
|
53
|
+
t = r.default || r;
|
|
54
|
+
} catch (r) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`DuckDB WASM is not installed or failed to load. Install it with: npm install @duckdb/duckdb-wasm. Error: ${r instanceof Error ? r.message : "Unknown error"}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
this._duckdb = t, e?.({
|
|
60
|
+
stage: "initializing",
|
|
61
|
+
percent: 30,
|
|
62
|
+
message: "Selecting DuckDB bundle..."
|
|
63
|
+
});
|
|
64
|
+
let n;
|
|
65
|
+
if (this._duckdb.getJsDelivrBundles) {
|
|
66
|
+
const r = this._duckdb.getJsDelivrBundles();
|
|
67
|
+
n = await this._duckdb.selectBundle(r);
|
|
68
|
+
} else {
|
|
69
|
+
const r = this._getJsDelivrBundles();
|
|
70
|
+
n = await this._duckdb.selectBundle(r);
|
|
71
|
+
}
|
|
72
|
+
e?.({
|
|
73
|
+
stage: "initializing",
|
|
74
|
+
percent: 50,
|
|
75
|
+
message: "Instantiating DuckDB..."
|
|
76
|
+
});
|
|
77
|
+
const h = new this._duckdb.ConsoleLogger(4);
|
|
78
|
+
let m, i = null;
|
|
79
|
+
try {
|
|
80
|
+
i = URL.createObjectURL(
|
|
81
|
+
new Blob([`importScripts("${n.mainWorker}");`], {
|
|
82
|
+
type: "text/javascript"
|
|
83
|
+
})
|
|
84
|
+
), m = new Worker(i);
|
|
85
|
+
} catch (r) {
|
|
86
|
+
throw i && URL.revokeObjectURL(i), new Error(
|
|
87
|
+
`Failed to create DuckDB worker: ${r instanceof Error ? r.message : "Unknown error"}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
this._worker = m;
|
|
91
|
+
const p = new this._duckdb.AsyncDuckDB(h, m);
|
|
92
|
+
try {
|
|
93
|
+
await p.instantiate(n.mainModule, n.pthreadWorker);
|
|
94
|
+
} catch (r) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Failed to instantiate DuckDB: ${r instanceof Error ? r.message : "Unknown error"}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
i && URL.revokeObjectURL(i), this._db = p, e?.({
|
|
100
|
+
stage: "initializing",
|
|
101
|
+
percent: 70,
|
|
102
|
+
message: "Loading spatial extension..."
|
|
103
|
+
});
|
|
104
|
+
const o = await this._db.connect();
|
|
105
|
+
try {
|
|
106
|
+
await o.query("INSTALL spatial"), await o.query("LOAD spatial");
|
|
107
|
+
} catch (r) {
|
|
108
|
+
console.warn(
|
|
109
|
+
"Failed to load spatial extension, some features may not work:",
|
|
110
|
+
r
|
|
111
|
+
);
|
|
112
|
+
} finally {
|
|
113
|
+
await o.close();
|
|
114
|
+
}
|
|
115
|
+
this._initialized = !0, e?.({
|
|
116
|
+
stage: "initializing",
|
|
117
|
+
percent: 100,
|
|
118
|
+
message: "DuckDB ready"
|
|
119
|
+
});
|
|
120
|
+
} catch (t) {
|
|
121
|
+
throw e?.({
|
|
122
|
+
stage: "error",
|
|
123
|
+
message: `Failed to initialize DuckDB: ${t instanceof Error ? t.message : "Unknown error"}`
|
|
124
|
+
}), t;
|
|
125
|
+
} finally {
|
|
126
|
+
this._initializing = !1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Gets the jsdelivr bundle URLs for DuckDB WASM.
|
|
132
|
+
*/
|
|
133
|
+
_getJsDelivrBundles() {
|
|
134
|
+
const e = this._bundleUrl || "https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm@latest/dist";
|
|
135
|
+
return {
|
|
136
|
+
mvp: {
|
|
137
|
+
mainModule: `${e}/duckdb-mvp.wasm`,
|
|
138
|
+
mainWorker: `${e}/duckdb-browser-mvp.worker.js`
|
|
139
|
+
},
|
|
140
|
+
eh: {
|
|
141
|
+
mainModule: `${e}/duckdb-eh.wasm`,
|
|
142
|
+
mainWorker: `${e}/duckdb-browser-eh.worker.js`
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Converts a spatial file to GeoJSON using DuckDB.
|
|
148
|
+
*
|
|
149
|
+
* @param buffer - The file contents as an ArrayBuffer.
|
|
150
|
+
* @param filename - The original filename.
|
|
151
|
+
* @param onProgress - Optional progress callback.
|
|
152
|
+
* @returns The conversion result with GeoJSON.
|
|
153
|
+
*/
|
|
154
|
+
async convert(e, t, n) {
|
|
155
|
+
const h = performance.now(), m = this._detectFormat(t);
|
|
156
|
+
if (this.isReady() || await this.initialize(n), !this._db)
|
|
157
|
+
throw new Error("DuckDB not initialized");
|
|
158
|
+
n?.({
|
|
159
|
+
stage: "loading",
|
|
160
|
+
percent: 0,
|
|
161
|
+
message: `Loading ${t}...`
|
|
162
|
+
});
|
|
163
|
+
const i = new Uint8Array(e);
|
|
164
|
+
await this._db.registerFileBuffer(t, i);
|
|
165
|
+
const p = await this._db.connect();
|
|
166
|
+
try {
|
|
167
|
+
n?.({
|
|
168
|
+
stage: "converting",
|
|
169
|
+
percent: 30,
|
|
170
|
+
message: "Reading spatial data..."
|
|
171
|
+
});
|
|
172
|
+
let o;
|
|
173
|
+
m === "geoparquet" || m === "parquet" ? o = `read_parquet('${t}')` : o = `ST_Read('${t}')`;
|
|
174
|
+
const f = (await p.query(`
|
|
175
|
+
DESCRIBE SELECT * FROM ${o}
|
|
176
|
+
`)).toArray();
|
|
177
|
+
let l = null, y = "", g = null, c = null, a = null;
|
|
178
|
+
const u = [], L = ["lat", "latitude", "y", "lat_y", "point_y"], E = [
|
|
179
|
+
"lon",
|
|
180
|
+
"lng",
|
|
181
|
+
"long",
|
|
182
|
+
"longitude",
|
|
183
|
+
"x",
|
|
184
|
+
"lon_x",
|
|
185
|
+
"long_x",
|
|
186
|
+
"point_x"
|
|
187
|
+
], B = ["wkt", "wkt_geom", "wkt_geometry", "geometry_wkt"];
|
|
188
|
+
for (const d of f) {
|
|
189
|
+
const s = d.column_name, D = d.column_type?.toUpperCase() || "", _ = s.toLowerCase(), z = D.includes("GEOMETRY"), O = _ === "geom" || _ === "geometry" || _ === "wkb_geometry" || _ === "the_geom" || _ === "shape", v = D.includes("BLOB") && O;
|
|
190
|
+
z || O || v ? l || (l = s, y = D) : L.includes(_) && !g ? (g = s, u.push(s)) : E.includes(_) && !c ? (c = s, u.push(s)) : B.includes(_) && !a ? a = s : u.push(s);
|
|
191
|
+
}
|
|
192
|
+
let w = !1, k = !1;
|
|
193
|
+
if (!l)
|
|
194
|
+
if (a)
|
|
195
|
+
k = !0;
|
|
196
|
+
else if (g && c) {
|
|
197
|
+
w = !0;
|
|
198
|
+
const d = u.indexOf(g);
|
|
199
|
+
d > -1 && u.splice(d, 1);
|
|
200
|
+
const s = u.indexOf(c);
|
|
201
|
+
s > -1 && u.splice(s, 1);
|
|
202
|
+
} else
|
|
203
|
+
throw new Error(
|
|
204
|
+
"No geometry column found in the file. For CSV/Excel files, include a geometry column, WKT column, or lat/lon columns."
|
|
205
|
+
);
|
|
206
|
+
n?.({
|
|
207
|
+
stage: "converting",
|
|
208
|
+
percent: 50,
|
|
209
|
+
message: "Converting to GeoJSON..."
|
|
210
|
+
});
|
|
211
|
+
const x = u.length > 0 ? `json_object(${u.map((d) => `'${d}', "${d}"`).join(", ")})` : "'{}'::JSON";
|
|
212
|
+
let b, $;
|
|
213
|
+
w && g && c ? (b = `ST_AsGeoJSON(ST_Point("${c}", "${g}"))`, $ = `"${g}" IS NOT NULL AND "${c}" IS NOT NULL`) : k && a ? (b = `ST_AsGeoJSON(ST_GeomFromText("${a}"))`, $ = `"${a}" IS NOT NULL AND "${a}" != ''`) : y.includes("BLOB") ? (b = `ST_AsGeoJSON(ST_GeomFromWKB("${l}"))`, $ = `"${l}" IS NOT NULL`) : (b = `ST_AsGeoJSON("${l}")`, $ = `"${l}" IS NOT NULL`);
|
|
214
|
+
const F = (await p.query(`
|
|
215
|
+
SELECT json_object(
|
|
216
|
+
'type', 'Feature',
|
|
217
|
+
'geometry', ${b}::JSON,
|
|
218
|
+
'properties', ${x}
|
|
219
|
+
) as feature
|
|
220
|
+
FROM ${o}
|
|
221
|
+
WHERE ${$}
|
|
222
|
+
`)).toArray();
|
|
223
|
+
n?.({
|
|
224
|
+
stage: "converting",
|
|
225
|
+
percent: 80,
|
|
226
|
+
message: "Building feature collection..."
|
|
227
|
+
});
|
|
228
|
+
const T = [], N = /* @__PURE__ */ new Set();
|
|
229
|
+
for (const d of F)
|
|
230
|
+
if (d.feature)
|
|
231
|
+
try {
|
|
232
|
+
const s = typeof d.feature == "string" ? JSON.parse(d.feature) : d.feature;
|
|
233
|
+
T.push(s), s.geometry?.type && N.add(s.geometry.type);
|
|
234
|
+
} catch (s) {
|
|
235
|
+
console.warn("Failed to parse feature:", s);
|
|
236
|
+
}
|
|
237
|
+
const C = {
|
|
238
|
+
type: "FeatureCollection",
|
|
239
|
+
features: T
|
|
240
|
+
}, R = performance.now(), U = {
|
|
241
|
+
originalFormat: m,
|
|
242
|
+
featureCount: T.length,
|
|
243
|
+
geometryTypes: Array.from(N),
|
|
244
|
+
fileSize: e.byteLength,
|
|
245
|
+
conversionTimeMs: Math.round(R - h)
|
|
246
|
+
};
|
|
247
|
+
return n?.({
|
|
248
|
+
stage: "complete",
|
|
249
|
+
percent: 100,
|
|
250
|
+
message: `Converted ${T.length} features`
|
|
251
|
+
}), {
|
|
252
|
+
geojson: C,
|
|
253
|
+
warnings: [],
|
|
254
|
+
metadata: U
|
|
255
|
+
};
|
|
256
|
+
} catch (o) {
|
|
257
|
+
throw n?.({
|
|
258
|
+
stage: "error",
|
|
259
|
+
message: `Failed to convert: ${o instanceof Error ? o.message : "Unknown error"}`
|
|
260
|
+
}), o;
|
|
261
|
+
} finally {
|
|
262
|
+
await p.close();
|
|
263
|
+
try {
|
|
264
|
+
await this._db.dropFile(t);
|
|
265
|
+
} catch {
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Detects the file format from the filename.
|
|
271
|
+
*
|
|
272
|
+
* @param filename - The filename to check.
|
|
273
|
+
* @returns The detected format name.
|
|
274
|
+
*/
|
|
275
|
+
_detectFormat(e) {
|
|
276
|
+
switch (e.toLowerCase().split(".").pop()) {
|
|
277
|
+
case "gpkg":
|
|
278
|
+
return "geopackage";
|
|
279
|
+
case "parquet":
|
|
280
|
+
case "geoparquet":
|
|
281
|
+
return "geoparquet";
|
|
282
|
+
case "shp":
|
|
283
|
+
return "shapefile";
|
|
284
|
+
case "geojson":
|
|
285
|
+
case "json":
|
|
286
|
+
return "geojson";
|
|
287
|
+
case "kml":
|
|
288
|
+
return "kml";
|
|
289
|
+
case "kmz":
|
|
290
|
+
return "kmz";
|
|
291
|
+
case "gpx":
|
|
292
|
+
return "gpx";
|
|
293
|
+
case "fgb":
|
|
294
|
+
return "flatgeobuf";
|
|
295
|
+
case "gml":
|
|
296
|
+
return "gml";
|
|
297
|
+
case "topojson":
|
|
298
|
+
return "topojson";
|
|
299
|
+
case "csv":
|
|
300
|
+
return "csv";
|
|
301
|
+
case "xlsx":
|
|
302
|
+
case "xls":
|
|
303
|
+
return "xlsx";
|
|
304
|
+
case "dxf":
|
|
305
|
+
return "dxf";
|
|
306
|
+
default:
|
|
307
|
+
return "unknown";
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Registers a remote parquet file for HTTP range request access.
|
|
312
|
+
* This allows querying the file without downloading it entirely.
|
|
313
|
+
*
|
|
314
|
+
* @param url - The URL of the remote parquet file.
|
|
315
|
+
* @param fileName - The internal filename to use for queries.
|
|
316
|
+
*/
|
|
317
|
+
async registerRemoteParquet(e, t) {
|
|
318
|
+
if (this.isReady() || await this.initialize(), !this._db || !this._duckdb)
|
|
319
|
+
throw new Error("DuckDB not initialized");
|
|
320
|
+
await this._db.registerFileURL(
|
|
321
|
+
t,
|
|
322
|
+
e,
|
|
323
|
+
this._duckdb.DuckDBDataProtocol.HTTP,
|
|
324
|
+
!1
|
|
325
|
+
// not direct IO
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Gets the schema of a parquet file, identifying geometry and property columns.
|
|
330
|
+
*
|
|
331
|
+
* @param fileName - The registered filename to analyze.
|
|
332
|
+
* @returns Schema information with geometry and property columns.
|
|
333
|
+
*/
|
|
334
|
+
async getParquetSchema(e) {
|
|
335
|
+
if (!this._db)
|
|
336
|
+
throw new Error("DuckDB not initialized");
|
|
337
|
+
const t = await this._db.connect();
|
|
338
|
+
try {
|
|
339
|
+
const h = (await t.query(`DESCRIBE SELECT * FROM read_parquet('${e}')`)).toArray(), m = h.map((f) => ({
|
|
340
|
+
name: f.column_name,
|
|
341
|
+
type: f.column_type
|
|
342
|
+
}));
|
|
343
|
+
let i = null, p = null;
|
|
344
|
+
const o = [], r = [
|
|
345
|
+
"geom",
|
|
346
|
+
"geometry",
|
|
347
|
+
"wkb_geometry",
|
|
348
|
+
"the_geom",
|
|
349
|
+
"shape"
|
|
350
|
+
];
|
|
351
|
+
for (const f of h) {
|
|
352
|
+
const l = f.column_name, y = f.column_type?.toUpperCase() || "", g = l.toLowerCase(), c = y.includes("GEOMETRY"), a = r.includes(g), u = y.includes("BLOB") && a;
|
|
353
|
+
(c || a || u) && !i ? (i = l, p = y) : o.push(l);
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
geometryColumn: i,
|
|
357
|
+
geometryColumnType: p,
|
|
358
|
+
propertyColumns: o,
|
|
359
|
+
allColumns: m
|
|
360
|
+
};
|
|
361
|
+
} finally {
|
|
362
|
+
await t.close();
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Queries features from a registered parquet file within the given bounds.
|
|
367
|
+
*
|
|
368
|
+
* @param fileName - The registered filename to query.
|
|
369
|
+
* @param bounds - The bounding box [west, south, east, north].
|
|
370
|
+
* @param geometryColumn - The name of the geometry column.
|
|
371
|
+
* @param propertyColumns - The property columns to include.
|
|
372
|
+
* @param geometryColumnType - The type of the geometry column (for WKB handling).
|
|
373
|
+
* @returns A GeoJSON FeatureCollection with features in the bounds.
|
|
374
|
+
*/
|
|
375
|
+
async queryByBounds(e, t, n, h, m) {
|
|
376
|
+
if (!this._db)
|
|
377
|
+
throw new Error("DuckDB not initialized");
|
|
378
|
+
const i = await this._db.connect(), [p, o, r, f] = t;
|
|
379
|
+
try {
|
|
380
|
+
const l = h.length > 0 ? `json_object(${h.map((w) => `'${w}', "${w}"`).join(", ")})` : "'{}'::JSON", g = (m?.toUpperCase() || "").includes("BLOB");
|
|
381
|
+
let c, a;
|
|
382
|
+
g ? (c = `ST_AsGeoJSON(ST_GeomFromWKB("${n}"))`, a = `ST_GeomFromWKB("${n}")`) : (c = `ST_AsGeoJSON("${n}")`, a = `"${n}"`);
|
|
383
|
+
const u = `
|
|
384
|
+
SELECT json_object(
|
|
385
|
+
'type', 'Feature',
|
|
386
|
+
'geometry', ${c}::JSON,
|
|
387
|
+
'properties', ${l}
|
|
388
|
+
) as feature
|
|
389
|
+
FROM read_parquet('${e}')
|
|
390
|
+
WHERE "${n}" IS NOT NULL
|
|
391
|
+
AND ST_Intersects(
|
|
392
|
+
${a},
|
|
393
|
+
ST_MakeEnvelope(${p}, ${o}, ${r}, ${f})
|
|
394
|
+
)
|
|
395
|
+
`, E = (await i.query(u)).toArray(), B = [];
|
|
396
|
+
for (const w of E)
|
|
397
|
+
if (w.feature)
|
|
398
|
+
try {
|
|
399
|
+
const k = typeof w.feature == "string" ? JSON.parse(w.feature) : w.feature;
|
|
400
|
+
B.push(k);
|
|
401
|
+
} catch (k) {
|
|
402
|
+
console.warn("Failed to parse feature:", k);
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
type: "FeatureCollection",
|
|
406
|
+
features: B
|
|
407
|
+
};
|
|
408
|
+
} finally {
|
|
409
|
+
await i.close();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Unregisters a file from DuckDB.
|
|
414
|
+
*
|
|
415
|
+
* @param fileName - The filename to unregister.
|
|
416
|
+
*/
|
|
417
|
+
async unregisterFile(e) {
|
|
418
|
+
if (this._db)
|
|
419
|
+
try {
|
|
420
|
+
await this._db.dropFile(e);
|
|
421
|
+
} catch {
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Disposes of DuckDB resources.
|
|
426
|
+
*/
|
|
427
|
+
dispose() {
|
|
428
|
+
this._db && (this._db.terminate().catch(console.error), this._db = null), this._worker && (this._worker.terminate(), this._worker = null), this._initialized = !1, this._duckdb = null, S === this && (S = null);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
export {
|
|
432
|
+
j as DuckDBConverter,
|
|
433
|
+
G as getDuckDBConverter
|
|
434
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var y=Object.create;var h=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var w=Object.getPrototypeOf,C=Object.prototype.hasOwnProperty;var j=(t,e,s,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of d(e))!C.call(t,r)&&r!==s&&h(t,r,{get:()=>e[r],enumerable:!(i=m(e,r))||i.enumerable});return t};var v=(t,e,s)=>(s=t!=null?y(w(t)):{},j(e||!t||!t.__esModule?h(s,"default",{value:t,enumerable:!0}):s,t));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class c{_shpjs=null;_initialized=!1;isReady(){return this._initialized&&this._shpjs!==null}async initialize(e){if(!this._initialized){e?.({stage:"initializing",percent:0,message:"Loading shapefile parser..."});try{this._shpjs=await import("shpjs"),this._initialized=!0,e?.({stage:"initializing",percent:100,message:"Shapefile parser ready"})}catch{throw new Error("shpjs is not installed. Install it with: npm install shpjs")}}}async convert(e,s,i){const r=performance.now();this.isReady()||await this.initialize(i),i?.({stage:"loading",percent:10,message:`Loading ${s}...`});try{i?.({stage:"converting",percent:30,message:"Parsing shapefile..."});const n=await(this._shpjs.default||this._shpjs)(e);i?.({stage:"converting",percent:80,message:"Building feature collection..."});let a;Array.isArray(n)?a={type:"FeatureCollection",features:n.flatMap(o=>o.features||[])}:n.type==="FeatureCollection"?a=n:n.type==="Feature"?a={type:"FeatureCollection",features:[n]}:a={type:"FeatureCollection",features:[{type:"Feature",properties:{},geometry:n}]};const f=new Set;for(const o of a.features)o.geometry&&f.add(o.geometry.type);const g=performance.now(),u={originalFormat:"shapefile",featureCount:a.features.length,geometryTypes:Array.from(f),fileSize:e.byteLength,conversionTimeMs:Math.round(g-r)};return i?.({stage:"complete",percent:100,message:`Converted ${a.features.length} features`}),{geojson:a,warnings:[],metadata:u}}catch(l){throw i?.({stage:"error",message:`Failed to parse shapefile: ${l instanceof Error?l.message:"Unknown error"}`}),l}}dispose(){this._shpjs=null,this._initialized=!1}}let p=null;function _(){return p||(p=new c),p}exports.ShapefileConverter=c;exports.getShapefileConverter=_;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
class f {
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
|
+
_shpjs = null;
|
|
4
|
+
_initialized = !1;
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the converter is ready for use.
|
|
7
|
+
*
|
|
8
|
+
* @returns True if initialized and ready.
|
|
9
|
+
*/
|
|
10
|
+
isReady() {
|
|
11
|
+
return this._initialized && this._shpjs !== null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Initializes the shpjs library.
|
|
15
|
+
*
|
|
16
|
+
* @param onProgress - Optional progress callback.
|
|
17
|
+
*/
|
|
18
|
+
async initialize(a) {
|
|
19
|
+
if (!this._initialized) {
|
|
20
|
+
a?.({
|
|
21
|
+
stage: "initializing",
|
|
22
|
+
percent: 0,
|
|
23
|
+
message: "Loading shapefile parser..."
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
this._shpjs = await import(
|
|
27
|
+
/* @vite-ignore */
|
|
28
|
+
"shpjs"
|
|
29
|
+
), this._initialized = !0, a?.({
|
|
30
|
+
stage: "initializing",
|
|
31
|
+
percent: 100,
|
|
32
|
+
message: "Shapefile parser ready"
|
|
33
|
+
});
|
|
34
|
+
} catch {
|
|
35
|
+
throw new Error(
|
|
36
|
+
"shpjs is not installed. Install it with: npm install shpjs"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Converts a Shapefile (ZIP) to GeoJSON.
|
|
43
|
+
*
|
|
44
|
+
* @param buffer - The ZIP file contents as an ArrayBuffer.
|
|
45
|
+
* @param filename - The original filename.
|
|
46
|
+
* @param onProgress - Optional progress callback.
|
|
47
|
+
* @returns The conversion result with GeoJSON.
|
|
48
|
+
*/
|
|
49
|
+
async convert(a, o, i) {
|
|
50
|
+
const p = performance.now();
|
|
51
|
+
this.isReady() || await this.initialize(i), i?.({
|
|
52
|
+
stage: "loading",
|
|
53
|
+
percent: 10,
|
|
54
|
+
message: `Loading ${o}...`
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
i?.({
|
|
58
|
+
stage: "converting",
|
|
59
|
+
percent: 30,
|
|
60
|
+
message: "Parsing shapefile..."
|
|
61
|
+
});
|
|
62
|
+
const t = await (this._shpjs.default || this._shpjs)(a);
|
|
63
|
+
i?.({
|
|
64
|
+
stage: "converting",
|
|
65
|
+
percent: 80,
|
|
66
|
+
message: "Building feature collection..."
|
|
67
|
+
});
|
|
68
|
+
let e;
|
|
69
|
+
Array.isArray(t) ? e = {
|
|
70
|
+
type: "FeatureCollection",
|
|
71
|
+
features: t.flatMap((r) => r.features || [])
|
|
72
|
+
} : t.type === "FeatureCollection" ? e = t : t.type === "Feature" ? e = {
|
|
73
|
+
type: "FeatureCollection",
|
|
74
|
+
features: [t]
|
|
75
|
+
} : e = {
|
|
76
|
+
type: "FeatureCollection",
|
|
77
|
+
features: [
|
|
78
|
+
{
|
|
79
|
+
type: "Feature",
|
|
80
|
+
properties: {},
|
|
81
|
+
geometry: t
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
const l = /* @__PURE__ */ new Set();
|
|
86
|
+
for (const r of e.features)
|
|
87
|
+
r.geometry && l.add(r.geometry.type);
|
|
88
|
+
const h = performance.now(), c = {
|
|
89
|
+
originalFormat: "shapefile",
|
|
90
|
+
featureCount: e.features.length,
|
|
91
|
+
geometryTypes: Array.from(l),
|
|
92
|
+
fileSize: a.byteLength,
|
|
93
|
+
conversionTimeMs: Math.round(h - p)
|
|
94
|
+
};
|
|
95
|
+
return i?.({
|
|
96
|
+
stage: "complete",
|
|
97
|
+
percent: 100,
|
|
98
|
+
message: `Converted ${e.features.length} features`
|
|
99
|
+
}), {
|
|
100
|
+
geojson: e,
|
|
101
|
+
warnings: [],
|
|
102
|
+
metadata: c
|
|
103
|
+
};
|
|
104
|
+
} catch (s) {
|
|
105
|
+
throw i?.({
|
|
106
|
+
stage: "error",
|
|
107
|
+
message: `Failed to parse shapefile: ${s instanceof Error ? s.message : "Unknown error"}`
|
|
108
|
+
}), s;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Disposes of resources (no-op for shpjs).
|
|
113
|
+
*/
|
|
114
|
+
dispose() {
|
|
115
|
+
this._shpjs = null, this._initialized = !1;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
let n = null;
|
|
119
|
+
function u() {
|
|
120
|
+
return n || (n = new f()), n;
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
f as ShapefileConverter,
|
|
124
|
+
u as getShapefileConverter
|
|
125
|
+
};
|