@walkthru-earth/objex 0.1.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 +396 -0
- package/README.md +114 -0
- package/dist/assets/favicon.svg +17 -0
- package/dist/components/CLAUDE.md +44 -0
- package/dist/components/browser/Breadcrumb.svelte +50 -0
- package/dist/components/browser/Breadcrumb.svelte.d.ts +7 -0
- package/dist/components/browser/CreateFolderDialog.svelte +98 -0
- package/dist/components/browser/CreateFolderDialog.svelte.d.ts +6 -0
- package/dist/components/browser/DeleteConfirmDialog.svelte +90 -0
- package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +8 -0
- package/dist/components/browser/DropZone.svelte +83 -0
- package/dist/components/browser/DropZone.svelte.d.ts +7 -0
- package/dist/components/browser/FileBrowser.svelte +229 -0
- package/dist/components/browser/FileBrowser.svelte.d.ts +3 -0
- package/dist/components/browser/FileRow.svelte +112 -0
- package/dist/components/browser/FileRow.svelte.d.ts +9 -0
- package/dist/components/browser/FileTreeSidebar.svelte +559 -0
- package/dist/components/browser/FileTreeSidebar.svelte.d.ts +8 -0
- package/dist/components/browser/RenameDialog.svelte +101 -0
- package/dist/components/browser/RenameDialog.svelte.d.ts +8 -0
- package/dist/components/browser/SearchBar.svelte +40 -0
- package/dist/components/browser/SearchBar.svelte.d.ts +6 -0
- package/dist/components/browser/UploadButton.svelte +65 -0
- package/dist/components/browser/UploadButton.svelte.d.ts +3 -0
- package/dist/components/editor/CodeMirrorEditor.svelte +404 -0
- package/dist/components/editor/CodeMirrorEditor.svelte.d.ts +12 -0
- package/dist/components/editor/MilkdownEditor.svelte +98 -0
- package/dist/components/editor/MilkdownEditor.svelte.d.ts +9 -0
- package/dist/components/editor/SqlEditor.svelte +173 -0
- package/dist/components/editor/SqlEditor.svelte.d.ts +7 -0
- package/dist/components/editor/SqlResultBlock.svelte +199 -0
- package/dist/components/editor/SqlResultBlock.svelte.d.ts +9 -0
- package/dist/components/layout/ConnectionDialog.svelte +439 -0
- package/dist/components/layout/ConnectionDialog.svelte.d.ts +9 -0
- package/dist/components/layout/LocaleToggle.svelte +32 -0
- package/dist/components/layout/LocaleToggle.svelte.d.ts +3 -0
- package/dist/components/layout/SafeLockToggle.svelte +37 -0
- package/dist/components/layout/SafeLockToggle.svelte.d.ts +18 -0
- package/dist/components/layout/Sidebar.svelte +314 -0
- package/dist/components/layout/Sidebar.svelte.d.ts +3 -0
- package/dist/components/layout/StatusBar.svelte +73 -0
- package/dist/components/layout/StatusBar.svelte.d.ts +3 -0
- package/dist/components/layout/TabBar.svelte +102 -0
- package/dist/components/layout/TabBar.svelte.d.ts +7 -0
- package/dist/components/layout/ThemeToggle.svelte +52 -0
- package/dist/components/layout/ThemeToggle.svelte.d.ts +3 -0
- package/dist/components/ui/badge/badge.svelte +49 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +32 -0
- package/dist/components/ui/badge/index.d.ts +1 -0
- package/dist/components/ui/badge/index.js +1 -0
- package/dist/components/ui/button/button.svelte +82 -0
- package/dist/components/ui/button/button.svelte.d.ts +64 -0
- package/dist/components/ui/button/index.d.ts +2 -0
- package/dist/components/ui/button/index.js +4 -0
- package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte +40 -0
- package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/context-menu/context-menu-content.svelte +28 -0
- package/dist/components/ui/context-menu/context-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/context-menu/context-menu-group-heading.svelte +21 -0
- package/dist/components/ui/context-menu/context-menu-group-heading.svelte.d.ts +7 -0
- package/dist/components/ui/context-menu/context-menu-group.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-item.svelte +27 -0
- package/dist/components/ui/context-menu/context-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-label.svelte +24 -0
- package/dist/components/ui/context-menu/context-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-portal.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte +16 -0
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-radio-item.svelte +33 -0
- package/dist/components/ui/context-menu/context-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-separator.svelte +17 -0
- package/dist/components/ui/context-menu/context-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-shortcut.svelte +20 -0
- package/dist/components/ui/context-menu/context-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte +20 -0
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-sub.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/context-menu-trigger.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/index.d.ts +17 -0
- package/dist/components/ui/context-menu/index.js +19 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +33 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
- package/dist/components/ui/dropdown-menu/index.js +18 -0
- package/dist/components/ui/input/index.d.ts +2 -0
- package/dist/components/ui/input/index.js +4 -0
- package/dist/components/ui/input/input.svelte +52 -0
- package/dist/components/ui/input/input.svelte.d.ts +13 -0
- package/dist/components/ui/resizable/index.d.ts +4 -0
- package/dist/components/ui/resizable/index.js +6 -0
- package/dist/components/ui/resizable/resizable-handle.svelte +30 -0
- package/dist/components/ui/resizable/resizable-handle.svelte.d.ts +8 -0
- package/dist/components/ui/resizable/resizable-pane-group.svelte +20 -0
- package/dist/components/ui/resizable/resizable-pane-group.svelte.d.ts +7 -0
- package/dist/components/ui/scroll-area/index.d.ts +3 -0
- package/dist/components/ui/scroll-area/index.js +5 -0
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +31 -0
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
- package/dist/components/ui/scroll-area/scroll-area.svelte +47 -0
- package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +11 -0
- package/dist/components/ui/separator/index.d.ts +2 -0
- package/dist/components/ui/separator/index.js +4 -0
- package/dist/components/ui/separator/separator.svelte +21 -0
- package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/index.d.ts +11 -0
- package/dist/components/ui/sheet/index.js +13 -0
- package/dist/components/ui/sheet/sheet-close.svelte +7 -0
- package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-content.svelte +62 -0
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
- package/dist/components/ui/sheet/sheet-description.svelte +17 -0
- package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
- package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-header.svelte +20 -0
- package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
- package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
- package/dist/components/ui/sheet/sheet-title.svelte +13 -0
- package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet.svelte +7 -0
- package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
- package/dist/components/ui/switch/index.d.ts +2 -0
- package/dist/components/ui/switch/index.js +4 -0
- package/dist/components/ui/switch/switch.svelte +28 -0
- package/dist/components/ui/switch/switch.svelte.d.ts +8 -0
- package/dist/components/ui/tabs/index.d.ts +5 -0
- package/dist/components/ui/tabs/index.js +7 -0
- package/dist/components/ui/tabs/tabs-content.svelte +17 -0
- package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-list.svelte +16 -0
- package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +20 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs.svelte +19 -0
- package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/index.d.ts +6 -0
- package/dist/components/ui/tooltip/index.js +8 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/components/viewers/ArchiveViewer.svelte +586 -0
- package/dist/components/viewers/ArchiveViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CLAUDE.md +60 -0
- package/dist/components/viewers/CodeViewer.svelte +553 -0
- package/dist/components/viewers/CodeViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CogViewer.svelte +1345 -0
- package/dist/components/viewers/CogViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CopcViewer.svelte +25 -0
- package/dist/components/viewers/CopcViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/DatabaseViewer.svelte +169 -0
- package/dist/components/viewers/DatabaseViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/FileInfo.svelte +174 -0
- package/dist/components/viewers/FileInfo.svelte.d.ts +10 -0
- package/dist/components/viewers/FlatGeobufViewer.svelte +755 -0
- package/dist/components/viewers/FlatGeobufViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/GeoParquetMapViewer.svelte +278 -0
- package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +17 -0
- package/dist/components/viewers/ImageViewer.svelte +233 -0
- package/dist/components/viewers/ImageViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/LoadProgress.svelte +93 -0
- package/dist/components/viewers/LoadProgress.svelte.d.ts +15 -0
- package/dist/components/viewers/MapViewer.svelte +234 -0
- package/dist/components/viewers/MapViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/MarkdownViewer.svelte +478 -0
- package/dist/components/viewers/MarkdownViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/MediaViewer.svelte +121 -0
- package/dist/components/viewers/MediaViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/ModelViewer.svelte +164 -0
- package/dist/components/viewers/ModelViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/NotebookViewer.svelte +389 -0
- package/dist/components/viewers/NotebookViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/PdfViewer.svelte +278 -0
- package/dist/components/viewers/PdfViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/PmtilesViewer.svelte +191 -0
- package/dist/components/viewers/PmtilesViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/QueryHistoryPanel.svelte +159 -0
- package/dist/components/viewers/QueryHistoryPanel.svelte.d.ts +8 -0
- package/dist/components/viewers/RawViewer.svelte +117 -0
- package/dist/components/viewers/RawViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/StacMapViewer.svelte +20 -0
- package/dist/components/viewers/StacMapViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/StyleEditorOverlay.svelte +27 -0
- package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +7 -0
- package/dist/components/viewers/TableGrid.svelte +355 -0
- package/dist/components/viewers/TableGrid.svelte.d.ts +12 -0
- package/dist/components/viewers/TableStatusBar.svelte +92 -0
- package/dist/components/viewers/TableStatusBar.svelte.d.ts +11 -0
- package/dist/components/viewers/TableToolbar.svelte +382 -0
- package/dist/components/viewers/TableToolbar.svelte.d.ts +25 -0
- package/dist/components/viewers/TableViewer.svelte +923 -0
- package/dist/components/viewers/TableViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/ViewerRouter.svelte +70 -0
- package/dist/components/viewers/ViewerRouter.svelte.d.ts +7 -0
- package/dist/components/viewers/ZarrMapViewer.svelte +288 -0
- package/dist/components/viewers/ZarrMapViewer.svelte.d.ts +17 -0
- package/dist/components/viewers/ZarrViewer.svelte +256 -0
- package/dist/components/viewers/ZarrViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/map/AttributeTable.svelte +52 -0
- package/dist/components/viewers/map/AttributeTable.svelte.d.ts +8 -0
- package/dist/components/viewers/map/MapContainer.svelte +158 -0
- package/dist/components/viewers/map/MapContainer.svelte.d.ts +12 -0
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +389 -0
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte.d.ts +10 -0
- package/dist/components/viewers/pmtiles/PmtilesMapView.svelte +332 -0
- package/dist/components/viewers/pmtiles/PmtilesMapView.svelte.d.ts +11 -0
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +373 -0
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte.d.ts +12 -0
- package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte +112 -0
- package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte.d.ts +10 -0
- package/dist/file-icons/CLAUDE.md +21 -0
- package/dist/file-icons/FileTypeIcon.svelte +74 -0
- package/dist/file-icons/FileTypeIcon.svelte.d.ts +9 -0
- package/dist/file-icons/index.d.ts +56 -0
- package/dist/file-icons/index.js +1070 -0
- package/dist/i18n/CLAUDE.md +19 -0
- package/dist/i18n/ar.d.ts +1 -0
- package/dist/i18n/ar.js +404 -0
- package/dist/i18n/en.d.ts +1 -0
- package/dist/i18n/en.js +404 -0
- package/dist/i18n/index.svelte.d.ts +9 -0
- package/dist/i18n/index.svelte.js +27 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +13 -0
- package/dist/query/CLAUDE.md +22 -0
- package/dist/query/engine.d.ts +56 -0
- package/dist/query/engine.js +6 -0
- package/dist/query/index.d.ts +4 -0
- package/dist/query/index.js +19 -0
- package/dist/query/wasm.d.ts +20 -0
- package/dist/query/wasm.js +890 -0
- package/dist/storage/CLAUDE.md +23 -0
- package/dist/storage/adapter.d.ts +21 -0
- package/dist/storage/adapter.js +1 -0
- package/dist/storage/browser-azure.d.ts +25 -0
- package/dist/storage/browser-azure.js +271 -0
- package/dist/storage/browser-cloud.d.ts +32 -0
- package/dist/storage/browser-cloud.js +293 -0
- package/dist/storage/index.d.ts +11 -0
- package/dist/storage/index.js +37 -0
- package/dist/storage/url-adapter.d.ts +19 -0
- package/dist/storage/url-adapter.js +51 -0
- package/dist/stores/CLAUDE.md +29 -0
- package/dist/stores/browser.svelte.d.ts +28 -0
- package/dist/stores/browser.svelte.js +160 -0
- package/dist/stores/connections.svelte.d.ts +56 -0
- package/dist/stores/connections.svelte.js +272 -0
- package/dist/stores/credentials.svelte.d.ts +56 -0
- package/dist/stores/credentials.svelte.js +79 -0
- package/dist/stores/files.svelte.d.ts +20 -0
- package/dist/stores/files.svelte.js +76 -0
- package/dist/stores/query-history.svelte.d.ts +16 -0
- package/dist/stores/query-history.svelte.js +57 -0
- package/dist/stores/safelock.svelte.d.ts +8 -0
- package/dist/stores/safelock.svelte.js +52 -0
- package/dist/stores/settings.svelte.d.ts +11 -0
- package/dist/stores/settings.svelte.js +101 -0
- package/dist/stores/tab-resources.svelte.d.ts +25 -0
- package/dist/stores/tab-resources.svelte.js +61 -0
- package/dist/stores/tabs.svelte.d.ts +17 -0
- package/dist/stores/tabs.svelte.js +110 -0
- package/dist/types/notebookjs.d.ts +14 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.js +1 -0
- package/dist/utils/CLAUDE.md +54 -0
- package/dist/utils/analytics.d.ts +10 -0
- package/dist/utils/analytics.js +38 -0
- package/dist/utils/archive.d.ts +70 -0
- package/dist/utils/archive.js +333 -0
- package/dist/utils/column-types.d.ts +5 -0
- package/dist/utils/column-types.js +137 -0
- package/dist/utils/deck.d.ts +98 -0
- package/dist/utils/deck.js +208 -0
- package/dist/utils/evidence-context.d.ts +22 -0
- package/dist/utils/evidence-context.js +56 -0
- package/dist/utils/export.d.ts +2 -0
- package/dist/utils/export.js +51 -0
- package/dist/utils/format.d.ts +14 -0
- package/dist/utils/format.js +56 -0
- package/dist/utils/geoarrow.d.ts +32 -0
- package/dist/utils/geoarrow.js +672 -0
- package/dist/utils/hex.d.ts +10 -0
- package/dist/utils/hex.js +27 -0
- package/dist/utils/host-detection.d.ts +23 -0
- package/dist/utils/host-detection.js +289 -0
- package/dist/utils/map-selection.d.ts +12 -0
- package/dist/utils/map-selection.js +45 -0
- package/dist/utils/markdown-sql.d.ts +30 -0
- package/dist/utils/markdown-sql.js +73 -0
- package/dist/utils/markdown.d.ts +18 -0
- package/dist/utils/markdown.js +146 -0
- package/dist/utils/model3d.d.ts +13 -0
- package/dist/utils/model3d.js +62 -0
- package/dist/utils/parquet-metadata.d.ts +58 -0
- package/dist/utils/parquet-metadata.js +228 -0
- package/dist/utils/pdf.d.ts +8 -0
- package/dist/utils/pdf.js +28 -0
- package/dist/utils/pmtiles-tile.d.ts +38 -0
- package/dist/utils/pmtiles-tile.js +64 -0
- package/dist/utils/pmtiles.d.ts +46 -0
- package/dist/utils/pmtiles.js +135 -0
- package/dist/utils/shiki.d.ts +8 -0
- package/dist/utils/shiki.js +98 -0
- package/dist/utils/storage-url.d.ts +64 -0
- package/dist/utils/storage-url.js +374 -0
- package/dist/utils/url-state.d.ts +40 -0
- package/dist/utils/url-state.js +113 -0
- package/dist/utils/url.d.ts +27 -0
- package/dist/utils/url.js +115 -0
- package/dist/utils/wkb.d.ts +43 -0
- package/dist/utils/wkb.js +345 -0
- package/dist/utils/zarr.d.ts +39 -0
- package/dist/utils/zarr.js +204 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +5 -0
- package/package.json +203 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct WKB → GeoArrow bridge (zero-copy).
|
|
3
|
+
*
|
|
4
|
+
* Reads raw WKB binary directly into pre-allocated Arrow typed arrays
|
|
5
|
+
* without any intermediate JS object allocation. No parseWKB(), no GeoJSON.
|
|
6
|
+
*
|
|
7
|
+
* Data flow: WKB Uint8Array[] → DataView binary reads → Float64Array/Int32Array
|
|
8
|
+
* → arrow.makeData() → arrow.Table with ARROW:extension:name metadata
|
|
9
|
+
*/
|
|
10
|
+
import { Table } from 'apache-arrow';
|
|
11
|
+
export type GeoArrowGeomType = 'point' | 'linestring' | 'polygon' | 'multipoint' | 'multilinestring' | 'multipolygon';
|
|
12
|
+
export interface GeoArrowResult {
|
|
13
|
+
table: Table;
|
|
14
|
+
geometryType: GeoArrowGeomType;
|
|
15
|
+
bounds: [number, number, number, number];
|
|
16
|
+
/** Maps local table row index → original WKB array index (for selection lookup). */
|
|
17
|
+
sourceIndices: number[];
|
|
18
|
+
}
|
|
19
|
+
/** Map DuckDB ST_GeometryType output to our normalized type. */
|
|
20
|
+
export declare function normalizeGeomType(raw: string): GeoArrowGeomType;
|
|
21
|
+
/**
|
|
22
|
+
* Build GeoArrow tables from raw WKB arrays, automatically splitting by geometry type.
|
|
23
|
+
* Returns one GeoArrowResult per non-empty type group, with shared merged bounds.
|
|
24
|
+
*
|
|
25
|
+
* @param wkbArrays Raw WKB binary arrays from DuckDB
|
|
26
|
+
* @param attributes Attribute columns (non-geometry)
|
|
27
|
+
* @param knownGeomType If provided (e.g. from GeoParquet metadata), skip classification
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildGeoArrowTables(wkbArrays: Uint8Array[], attributes: Map<string, {
|
|
30
|
+
values: any[];
|
|
31
|
+
type: string;
|
|
32
|
+
}>, knownGeomType?: GeoArrowGeomType): GeoArrowResult[];
|
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct WKB → GeoArrow bridge (zero-copy).
|
|
3
|
+
*
|
|
4
|
+
* Reads raw WKB binary directly into pre-allocated Arrow typed arrays
|
|
5
|
+
* without any intermediate JS object allocation. No parseWKB(), no GeoJSON.
|
|
6
|
+
*
|
|
7
|
+
* Data flow: WKB Uint8Array[] → DataView binary reads → Float64Array/Int32Array
|
|
8
|
+
* → arrow.makeData() → arrow.Table with ARROW:extension:name metadata
|
|
9
|
+
*/
|
|
10
|
+
import { Field, FixedSizeList, Float64, List, makeData, RecordBatch, Schema, Struct, Table, Utf8 } from 'apache-arrow';
|
|
11
|
+
/** Map DuckDB ST_GeometryType output to our normalized type. */
|
|
12
|
+
export function normalizeGeomType(raw) {
|
|
13
|
+
const s = raw.toUpperCase().replace(/\s+/g, '');
|
|
14
|
+
if (s === 'POINT')
|
|
15
|
+
return 'point';
|
|
16
|
+
if (s === 'LINESTRING')
|
|
17
|
+
return 'linestring';
|
|
18
|
+
if (s === 'POLYGON')
|
|
19
|
+
return 'polygon';
|
|
20
|
+
if (s === 'MULTIPOINT')
|
|
21
|
+
return 'multipoint';
|
|
22
|
+
if (s === 'MULTILINESTRING')
|
|
23
|
+
return 'multilinestring';
|
|
24
|
+
if (s === 'MULTIPOLYGON')
|
|
25
|
+
return 'multipolygon';
|
|
26
|
+
return 'polygon'; // fallback
|
|
27
|
+
}
|
|
28
|
+
/** GeoArrow extension name for each geometry type. */
|
|
29
|
+
const EXTENSION_NAMES = {
|
|
30
|
+
point: 'geoarrow.point',
|
|
31
|
+
linestring: 'geoarrow.linestring',
|
|
32
|
+
polygon: 'geoarrow.polygon',
|
|
33
|
+
multipoint: 'geoarrow.multipoint',
|
|
34
|
+
multilinestring: 'geoarrow.multilinestring',
|
|
35
|
+
multipolygon: 'geoarrow.multipolygon'
|
|
36
|
+
};
|
|
37
|
+
/** Read WKB/EWKB header — 5 bytes + optional SRID. No allocations. */
|
|
38
|
+
function readWkbHeader(wkb) {
|
|
39
|
+
if (wkb.length < 5)
|
|
40
|
+
return null;
|
|
41
|
+
const le = wkb[0] === 1;
|
|
42
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
43
|
+
const rawType = dv.getUint32(1, le);
|
|
44
|
+
let headerSize = 5; // byte_order(1) + type(4)
|
|
45
|
+
// EWKB SRID flag — 4 extra bytes after type
|
|
46
|
+
if ((rawType & 0x20000000) !== 0)
|
|
47
|
+
headerSize += 4;
|
|
48
|
+
// EWKB dimension flags
|
|
49
|
+
const ewkbZ = (rawType & 0x80000000) !== 0;
|
|
50
|
+
const ewkbM = (rawType & 0x40000000) !== 0;
|
|
51
|
+
// Strip all EWKB flags to get base type
|
|
52
|
+
let type = rawType & 0x0fffffff;
|
|
53
|
+
// ISO Z/M ranges: 1001–1006 (Z), 2001–2006 (M), 3001–3006 (ZM)
|
|
54
|
+
let isoZ = false;
|
|
55
|
+
let isoM = false;
|
|
56
|
+
if (type > 3000) {
|
|
57
|
+
isoZ = true;
|
|
58
|
+
isoM = true;
|
|
59
|
+
type -= 3000;
|
|
60
|
+
}
|
|
61
|
+
else if (type > 2000) {
|
|
62
|
+
isoM = true;
|
|
63
|
+
type -= 2000;
|
|
64
|
+
}
|
|
65
|
+
else if (type > 1000) {
|
|
66
|
+
isoZ = true;
|
|
67
|
+
type -= 1000;
|
|
68
|
+
}
|
|
69
|
+
const dims = (ewkbZ || isoZ ? 1 : 0) + (ewkbM || isoM ? 1 : 0);
|
|
70
|
+
const coordStride = (2 + dims) * 8; // 16, 24, or 32 bytes
|
|
71
|
+
return { type, le, coordStride, dataOffset: headerSize };
|
|
72
|
+
}
|
|
73
|
+
/** Classify WKB type from first 5 bytes. No full parse. */
|
|
74
|
+
function classifyWkbType(wkb) {
|
|
75
|
+
const h = readWkbHeader(wkb);
|
|
76
|
+
if (!h)
|
|
77
|
+
return null;
|
|
78
|
+
switch (h.type) {
|
|
79
|
+
case 1:
|
|
80
|
+
return 'point';
|
|
81
|
+
case 2:
|
|
82
|
+
return 'linestring';
|
|
83
|
+
case 3:
|
|
84
|
+
return 'polygon';
|
|
85
|
+
case 4:
|
|
86
|
+
return 'multipoint';
|
|
87
|
+
case 5:
|
|
88
|
+
return 'multilinestring';
|
|
89
|
+
case 6:
|
|
90
|
+
return 'multipolygon';
|
|
91
|
+
default:
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function newBounds() {
|
|
96
|
+
return { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity };
|
|
97
|
+
}
|
|
98
|
+
/** Update bounds, skipping NaN coordinates (EMPTY geometries, invalid data). */
|
|
99
|
+
function expandBounds(b, x, y) {
|
|
100
|
+
if (Number.isNaN(x) || Number.isNaN(y))
|
|
101
|
+
return;
|
|
102
|
+
if (x < b.minX)
|
|
103
|
+
b.minX = x;
|
|
104
|
+
if (y < b.minY)
|
|
105
|
+
b.minY = y;
|
|
106
|
+
if (x > b.maxX)
|
|
107
|
+
b.maxX = x;
|
|
108
|
+
if (y > b.maxY)
|
|
109
|
+
b.maxY = y;
|
|
110
|
+
}
|
|
111
|
+
// ─── Arrow coordinate type (shared) ─────────────────────────────────
|
|
112
|
+
const coordField = new Field('xy', new Float64());
|
|
113
|
+
const coordType = new FixedSizeList(2, coordField);
|
|
114
|
+
/** Build FixedSizeList<Float64> Data from a pre-allocated Float64Array. */
|
|
115
|
+
function makeCoordData(coords, numPoints) {
|
|
116
|
+
const floatData = makeData({ type: new Float64(), length: coords.length, data: coords });
|
|
117
|
+
return makeData({ type: coordType, length: numPoints, nullCount: 0, child: floatData });
|
|
118
|
+
}
|
|
119
|
+
// ─── Direct WKB → Arrow builders (zero intermediate objects) ─────────
|
|
120
|
+
/**
|
|
121
|
+
* POINT: [byte_order:1][type:4][x:8][y:8]
|
|
122
|
+
* Direct read — 2 Float64 reads per geometry. Zero parseWKB.
|
|
123
|
+
*/
|
|
124
|
+
function buildPointData(wkbs, b) {
|
|
125
|
+
const n = wkbs.length;
|
|
126
|
+
const coords = new Float64Array(n * 2);
|
|
127
|
+
for (let i = 0; i < n; i++) {
|
|
128
|
+
const wkb = wkbs[i];
|
|
129
|
+
const h = readWkbHeader(wkb);
|
|
130
|
+
if (!h || h.type !== 1) {
|
|
131
|
+
coords[i * 2] = 0;
|
|
132
|
+
coords[i * 2 + 1] = 0;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
136
|
+
const x = dv.getFloat64(h.dataOffset, h.le);
|
|
137
|
+
const y = dv.getFloat64(h.dataOffset + 8, h.le);
|
|
138
|
+
coords[i * 2] = x;
|
|
139
|
+
coords[i * 2 + 1] = y;
|
|
140
|
+
expandBounds(b, x, y);
|
|
141
|
+
}
|
|
142
|
+
return makeCoordData(coords, n);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* LINESTRING: [byte_order:1][type:4][num_points:4][x:8,y:8 × n]
|
|
146
|
+
* Two-pass: count first to pre-allocate, then extract.
|
|
147
|
+
*/
|
|
148
|
+
function buildLineStringData(wkbs, b) {
|
|
149
|
+
const n = wkbs.length;
|
|
150
|
+
const geomOffsets = new Int32Array(n + 1);
|
|
151
|
+
let totalCoords = 0;
|
|
152
|
+
// Pass 1: count coordinates
|
|
153
|
+
for (let i = 0; i < n; i++) {
|
|
154
|
+
geomOffsets[i] = totalCoords;
|
|
155
|
+
const h = readWkbHeader(wkbs[i]);
|
|
156
|
+
if (!h || h.type !== 2)
|
|
157
|
+
continue;
|
|
158
|
+
const dv = new DataView(wkbs[i].buffer, wkbs[i].byteOffset, wkbs[i].byteLength);
|
|
159
|
+
const numPts = dv.getUint32(h.dataOffset, h.le);
|
|
160
|
+
totalCoords += numPts;
|
|
161
|
+
}
|
|
162
|
+
geomOffsets[n] = totalCoords;
|
|
163
|
+
// Pass 2: extract coordinates directly from binary
|
|
164
|
+
const coords = new Float64Array(totalCoords * 2);
|
|
165
|
+
let ci = 0;
|
|
166
|
+
for (const wkb of wkbs) {
|
|
167
|
+
const h = readWkbHeader(wkb);
|
|
168
|
+
if (!h || h.type !== 2)
|
|
169
|
+
continue;
|
|
170
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
171
|
+
const numPts = dv.getUint32(h.dataOffset, h.le);
|
|
172
|
+
let off = h.dataOffset + 4;
|
|
173
|
+
for (let j = 0; j < numPts; j++) {
|
|
174
|
+
const x = dv.getFloat64(off, h.le);
|
|
175
|
+
const y = dv.getFloat64(off + 8, h.le);
|
|
176
|
+
coords[ci++] = x;
|
|
177
|
+
coords[ci++] = y;
|
|
178
|
+
expandBounds(b, x, y);
|
|
179
|
+
off += h.coordStride;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const fslData = makeCoordData(coords, totalCoords);
|
|
183
|
+
const listType = new List(new Field('vertices', coordType));
|
|
184
|
+
return makeData({
|
|
185
|
+
type: listType,
|
|
186
|
+
length: n,
|
|
187
|
+
nullCount: 0,
|
|
188
|
+
valueOffsets: geomOffsets,
|
|
189
|
+
child: fslData
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* POLYGON: [byte_order:1][type:4][num_rings:4]
|
|
194
|
+
* { [num_points:4][x:8,y:8 × n] } × rings
|
|
195
|
+
* Two-pass: count rings+coords first, then extract.
|
|
196
|
+
*/
|
|
197
|
+
function buildPolygonData(wkbs, b) {
|
|
198
|
+
const n = wkbs.length;
|
|
199
|
+
const geomOffsets = new Int32Array(n + 1);
|
|
200
|
+
let totalRings = 0;
|
|
201
|
+
let totalCoords = 0;
|
|
202
|
+
// Pass 1: count rings and coordinates
|
|
203
|
+
for (let i = 0; i < n; i++) {
|
|
204
|
+
geomOffsets[i] = totalRings;
|
|
205
|
+
const h = readWkbHeader(wkbs[i]);
|
|
206
|
+
if (!h || h.type !== 3)
|
|
207
|
+
continue;
|
|
208
|
+
const dv = new DataView(wkbs[i].buffer, wkbs[i].byteOffset, wkbs[i].byteLength);
|
|
209
|
+
const numRings = dv.getUint32(h.dataOffset, h.le);
|
|
210
|
+
let off = h.dataOffset + 4;
|
|
211
|
+
for (let r = 0; r < numRings; r++) {
|
|
212
|
+
const numPts = dv.getUint32(off, h.le);
|
|
213
|
+
off += 4 + numPts * h.coordStride;
|
|
214
|
+
totalCoords += numPts;
|
|
215
|
+
totalRings++;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
geomOffsets[n] = totalRings;
|
|
219
|
+
// Pass 2: extract coordinates and ring offsets
|
|
220
|
+
const ringOffsets = new Int32Array(totalRings + 1);
|
|
221
|
+
const coords = new Float64Array(totalCoords * 2);
|
|
222
|
+
let ri = 0;
|
|
223
|
+
let ci = 0;
|
|
224
|
+
for (const wkb of wkbs) {
|
|
225
|
+
const h = readWkbHeader(wkb);
|
|
226
|
+
if (!h || h.type !== 3)
|
|
227
|
+
continue;
|
|
228
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
229
|
+
const numRings = dv.getUint32(h.dataOffset, h.le);
|
|
230
|
+
let off = h.dataOffset + 4;
|
|
231
|
+
for (let r = 0; r < numRings; r++) {
|
|
232
|
+
ringOffsets[ri++] = ci >> 1; // coordIndex = ci / 2
|
|
233
|
+
const numPts = dv.getUint32(off, h.le);
|
|
234
|
+
off += 4;
|
|
235
|
+
for (let j = 0; j < numPts; j++) {
|
|
236
|
+
const x = dv.getFloat64(off, h.le);
|
|
237
|
+
const y = dv.getFloat64(off + 8, h.le);
|
|
238
|
+
coords[ci++] = x;
|
|
239
|
+
coords[ci++] = y;
|
|
240
|
+
expandBounds(b, x, y);
|
|
241
|
+
off += h.coordStride;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
ringOffsets[totalRings] = ci >> 1;
|
|
246
|
+
const coordCount = ci >> 1;
|
|
247
|
+
const fslData = makeCoordData(coords, coordCount);
|
|
248
|
+
const ringListType = new List(new Field('vertices', coordType));
|
|
249
|
+
const ringListData = makeData({
|
|
250
|
+
type: ringListType,
|
|
251
|
+
length: totalRings,
|
|
252
|
+
nullCount: 0,
|
|
253
|
+
valueOffsets: ringOffsets,
|
|
254
|
+
child: fslData
|
|
255
|
+
});
|
|
256
|
+
const polyType = new List(new Field('rings', ringListType));
|
|
257
|
+
return makeData({
|
|
258
|
+
type: polyType,
|
|
259
|
+
length: n,
|
|
260
|
+
nullCount: 0,
|
|
261
|
+
valueOffsets: geomOffsets,
|
|
262
|
+
child: ringListData
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/** MultiPoint has same Arrow structure as LineString: List<FixedSizeList(2)>. */
|
|
266
|
+
function buildMultiPointData(wkbs, b) {
|
|
267
|
+
// MultiPoint WKB: [header][num_points:4]{Point WKB × n}
|
|
268
|
+
// Each inner point has its own WKB header.
|
|
269
|
+
const n = wkbs.length;
|
|
270
|
+
const geomOffsets = new Int32Array(n + 1);
|
|
271
|
+
let totalCoords = 0;
|
|
272
|
+
// Pass 1: count
|
|
273
|
+
for (let i = 0; i < n; i++) {
|
|
274
|
+
geomOffsets[i] = totalCoords;
|
|
275
|
+
const h = readWkbHeader(wkbs[i]);
|
|
276
|
+
if (!h || h.type !== 4)
|
|
277
|
+
continue;
|
|
278
|
+
const dv = new DataView(wkbs[i].buffer, wkbs[i].byteOffset, wkbs[i].byteLength);
|
|
279
|
+
totalCoords += dv.getUint32(h.dataOffset, h.le);
|
|
280
|
+
}
|
|
281
|
+
geomOffsets[n] = totalCoords;
|
|
282
|
+
// Pass 2: extract from inner point WKBs
|
|
283
|
+
const coords = new Float64Array(totalCoords * 2);
|
|
284
|
+
let ci = 0;
|
|
285
|
+
for (const wkb of wkbs) {
|
|
286
|
+
const h = readWkbHeader(wkb);
|
|
287
|
+
if (!h || h.type !== 4)
|
|
288
|
+
continue;
|
|
289
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
290
|
+
const numPts = dv.getUint32(h.dataOffset, h.le);
|
|
291
|
+
let off = h.dataOffset + 4;
|
|
292
|
+
for (let j = 0; j < numPts; j++) {
|
|
293
|
+
// Each inner point is a full WKB: skip its header to get coords
|
|
294
|
+
const innerH = readWkbHeader(new Uint8Array(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off));
|
|
295
|
+
if (innerH) {
|
|
296
|
+
const x = dv.getFloat64(off + innerH.dataOffset, innerH.le);
|
|
297
|
+
const y = dv.getFloat64(off + innerH.dataOffset + 8, innerH.le);
|
|
298
|
+
coords[ci++] = x;
|
|
299
|
+
coords[ci++] = y;
|
|
300
|
+
expandBounds(b, x, y);
|
|
301
|
+
off += innerH.dataOffset + innerH.coordStride;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
coords[ci++] = 0;
|
|
305
|
+
coords[ci++] = 0;
|
|
306
|
+
off += 21; // minimum point WKB size
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const fslData = makeCoordData(coords, totalCoords);
|
|
311
|
+
const listType = new List(new Field('vertices', coordType));
|
|
312
|
+
return makeData({
|
|
313
|
+
type: listType,
|
|
314
|
+
length: n,
|
|
315
|
+
nullCount: 0,
|
|
316
|
+
valueOffsets: geomOffsets,
|
|
317
|
+
child: fslData
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* MULTILINESTRING: [header][num_lines:4]{LineString WKB × n}
|
|
322
|
+
* Each inner LineString has its own WKB header.
|
|
323
|
+
*/
|
|
324
|
+
function buildMultiLineStringData(wkbs, b) {
|
|
325
|
+
const n = wkbs.length;
|
|
326
|
+
const geomOffsetsArr = [0];
|
|
327
|
+
let totalLines = 0;
|
|
328
|
+
let totalCoords = 0;
|
|
329
|
+
// Pass 1: count lines and coordinates
|
|
330
|
+
for (const wkb of wkbs) {
|
|
331
|
+
const h = readWkbHeader(wkb);
|
|
332
|
+
if (!h || h.type !== 5) {
|
|
333
|
+
geomOffsetsArr.push(totalLines);
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
337
|
+
const numLines = dv.getUint32(h.dataOffset, h.le);
|
|
338
|
+
let off = h.dataOffset + 4;
|
|
339
|
+
for (let l = 0; l < numLines; l++) {
|
|
340
|
+
const innerH = readWkbHeader(new Uint8Array(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off));
|
|
341
|
+
if (!innerH)
|
|
342
|
+
break;
|
|
343
|
+
const innerDv = new DataView(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off);
|
|
344
|
+
const numPts = innerDv.getUint32(innerH.dataOffset, innerH.le);
|
|
345
|
+
totalCoords += numPts;
|
|
346
|
+
off += innerH.dataOffset + 4 + numPts * innerH.coordStride;
|
|
347
|
+
totalLines++;
|
|
348
|
+
}
|
|
349
|
+
geomOffsetsArr.push(totalLines);
|
|
350
|
+
}
|
|
351
|
+
// Pass 2: extract
|
|
352
|
+
const geomOffsets = new Int32Array(geomOffsetsArr);
|
|
353
|
+
const lineOffsets = new Int32Array(totalLines + 1);
|
|
354
|
+
const coords = new Float64Array(totalCoords * 2);
|
|
355
|
+
let li = 0;
|
|
356
|
+
let ci = 0;
|
|
357
|
+
for (const wkb of wkbs) {
|
|
358
|
+
const h = readWkbHeader(wkb);
|
|
359
|
+
if (!h || h.type !== 5)
|
|
360
|
+
continue;
|
|
361
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
362
|
+
const numLines = dv.getUint32(h.dataOffset, h.le);
|
|
363
|
+
let off = h.dataOffset + 4;
|
|
364
|
+
for (let l = 0; l < numLines; l++) {
|
|
365
|
+
lineOffsets[li++] = ci >> 1;
|
|
366
|
+
const innerH = readWkbHeader(new Uint8Array(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off));
|
|
367
|
+
if (!innerH)
|
|
368
|
+
break;
|
|
369
|
+
const numPts = new DataView(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off).getUint32(innerH.dataOffset, innerH.le);
|
|
370
|
+
let ptOff = off + innerH.dataOffset + 4;
|
|
371
|
+
for (let j = 0; j < numPts; j++) {
|
|
372
|
+
const x = dv.getFloat64(ptOff, innerH.le);
|
|
373
|
+
const y = dv.getFloat64(ptOff + 8, innerH.le);
|
|
374
|
+
coords[ci++] = x;
|
|
375
|
+
coords[ci++] = y;
|
|
376
|
+
expandBounds(b, x, y);
|
|
377
|
+
ptOff += innerH.coordStride;
|
|
378
|
+
}
|
|
379
|
+
off = ptOff;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
lineOffsets[totalLines] = ci >> 1;
|
|
383
|
+
const fslData = makeCoordData(coords, ci >> 1);
|
|
384
|
+
const lineListType = new List(new Field('vertices', coordType));
|
|
385
|
+
const lineListData = makeData({
|
|
386
|
+
type: lineListType,
|
|
387
|
+
length: totalLines,
|
|
388
|
+
nullCount: 0,
|
|
389
|
+
valueOffsets: lineOffsets,
|
|
390
|
+
child: fslData
|
|
391
|
+
});
|
|
392
|
+
const multiLineType = new List(new Field('lines', lineListType));
|
|
393
|
+
return makeData({
|
|
394
|
+
type: multiLineType,
|
|
395
|
+
length: n,
|
|
396
|
+
nullCount: 0,
|
|
397
|
+
valueOffsets: geomOffsets,
|
|
398
|
+
child: lineListData
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* MULTIPOLYGON: [header][num_polys:4]{Polygon WKB × n}
|
|
403
|
+
* Each inner Polygon has its own WKB header.
|
|
404
|
+
*/
|
|
405
|
+
function buildMultiPolygonData(wkbs, b) {
|
|
406
|
+
const n = wkbs.length;
|
|
407
|
+
const geomOffsetsArr = [0];
|
|
408
|
+
let totalPolys = 0;
|
|
409
|
+
let totalRings = 0;
|
|
410
|
+
let totalCoords = 0;
|
|
411
|
+
// Pass 1: count polygons, rings, coordinates
|
|
412
|
+
for (const wkb of wkbs) {
|
|
413
|
+
const h = readWkbHeader(wkb);
|
|
414
|
+
if (!h || h.type !== 6) {
|
|
415
|
+
geomOffsetsArr.push(totalPolys);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
419
|
+
const numPolys = dv.getUint32(h.dataOffset, h.le);
|
|
420
|
+
let off = h.dataOffset + 4;
|
|
421
|
+
for (let p = 0; p < numPolys; p++) {
|
|
422
|
+
const innerH = readWkbHeader(new Uint8Array(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off));
|
|
423
|
+
if (!innerH)
|
|
424
|
+
break;
|
|
425
|
+
const innerDv = new DataView(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off);
|
|
426
|
+
const numRings = innerDv.getUint32(innerH.dataOffset, innerH.le);
|
|
427
|
+
let ringOff = innerH.dataOffset + 4;
|
|
428
|
+
for (let r = 0; r < numRings; r++) {
|
|
429
|
+
const numPts = innerDv.getUint32(ringOff, innerH.le);
|
|
430
|
+
ringOff += 4 + numPts * innerH.coordStride;
|
|
431
|
+
totalCoords += numPts;
|
|
432
|
+
totalRings++;
|
|
433
|
+
}
|
|
434
|
+
off += ringOff;
|
|
435
|
+
totalPolys++;
|
|
436
|
+
}
|
|
437
|
+
geomOffsetsArr.push(totalPolys);
|
|
438
|
+
}
|
|
439
|
+
// Pass 2: extract
|
|
440
|
+
const geomOffsets = new Int32Array(geomOffsetsArr);
|
|
441
|
+
const polyOffsets = new Int32Array(totalPolys + 1);
|
|
442
|
+
const ringOffsets = new Int32Array(totalRings + 1);
|
|
443
|
+
const coords = new Float64Array(totalCoords * 2);
|
|
444
|
+
let pi = 0;
|
|
445
|
+
let ri = 0;
|
|
446
|
+
let ci = 0;
|
|
447
|
+
for (const wkb of wkbs) {
|
|
448
|
+
const h = readWkbHeader(wkb);
|
|
449
|
+
if (!h || h.type !== 6)
|
|
450
|
+
continue;
|
|
451
|
+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength);
|
|
452
|
+
const numPolys = dv.getUint32(h.dataOffset, h.le);
|
|
453
|
+
let off = h.dataOffset + 4;
|
|
454
|
+
for (let p = 0; p < numPolys; p++) {
|
|
455
|
+
polyOffsets[pi++] = ri;
|
|
456
|
+
const innerH = readWkbHeader(new Uint8Array(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off));
|
|
457
|
+
if (!innerH)
|
|
458
|
+
break;
|
|
459
|
+
const innerDv = new DataView(wkb.buffer, wkb.byteOffset + off, wkb.byteLength - off);
|
|
460
|
+
const numRings = innerDv.getUint32(innerH.dataOffset, innerH.le);
|
|
461
|
+
let ringOff = off + innerH.dataOffset + 4;
|
|
462
|
+
for (let r = 0; r < numRings; r++) {
|
|
463
|
+
ringOffsets[ri++] = ci >> 1;
|
|
464
|
+
const numPts = dv.getUint32(ringOff, innerH.le);
|
|
465
|
+
ringOff += 4;
|
|
466
|
+
for (let j = 0; j < numPts; j++) {
|
|
467
|
+
const x = dv.getFloat64(ringOff, innerH.le);
|
|
468
|
+
const y = dv.getFloat64(ringOff + 8, innerH.le);
|
|
469
|
+
coords[ci++] = x;
|
|
470
|
+
coords[ci++] = y;
|
|
471
|
+
expandBounds(b, x, y);
|
|
472
|
+
ringOff += innerH.coordStride;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
off = ringOff;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
polyOffsets[totalPolys] = ri;
|
|
479
|
+
ringOffsets[totalRings] = ci >> 1;
|
|
480
|
+
const fslData = makeCoordData(coords, ci >> 1);
|
|
481
|
+
const ringListType = new List(new Field('vertices', coordType));
|
|
482
|
+
const ringListData = makeData({
|
|
483
|
+
type: ringListType,
|
|
484
|
+
length: totalRings,
|
|
485
|
+
nullCount: 0,
|
|
486
|
+
valueOffsets: ringOffsets,
|
|
487
|
+
child: fslData
|
|
488
|
+
});
|
|
489
|
+
const polyListType = new List(new Field('rings', ringListType));
|
|
490
|
+
const polyListData = makeData({
|
|
491
|
+
type: polyListType,
|
|
492
|
+
length: totalPolys,
|
|
493
|
+
nullCount: 0,
|
|
494
|
+
valueOffsets: polyOffsets,
|
|
495
|
+
child: ringListData
|
|
496
|
+
});
|
|
497
|
+
const multiPolyType = new List(new Field('polygons', polyListType));
|
|
498
|
+
return makeData({
|
|
499
|
+
type: multiPolyType,
|
|
500
|
+
length: n,
|
|
501
|
+
nullCount: 0,
|
|
502
|
+
valueOffsets: geomOffsets,
|
|
503
|
+
child: polyListData
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
// ─── Build a single GeoArrow table for one type group ────────────────
|
|
507
|
+
/** Build attribute columns for a subset of rows identified by indices. */
|
|
508
|
+
function buildAttributeColumns(indices, attributes) {
|
|
509
|
+
const n = indices.length;
|
|
510
|
+
const fields = [];
|
|
511
|
+
const dataArr = [];
|
|
512
|
+
for (const [name, col] of attributes) {
|
|
513
|
+
const { values } = col;
|
|
514
|
+
// Detect whether values are numeric or string
|
|
515
|
+
let isNumeric = true;
|
|
516
|
+
const sampleEnd = Math.min(n, 100);
|
|
517
|
+
for (let i = 0; i < sampleEnd; i++) {
|
|
518
|
+
if (values[indices[i]] != null && typeof values[indices[i]] !== 'number') {
|
|
519
|
+
isNumeric = false;
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (isNumeric) {
|
|
524
|
+
const arr = new Float64Array(n);
|
|
525
|
+
for (let i = 0; i < n; i++)
|
|
526
|
+
arr[i] = values[indices[i]] ?? NaN;
|
|
527
|
+
const data = makeData({ type: new Float64(), length: n, data: arr });
|
|
528
|
+
fields.push(new Field(name, new Float64(), true));
|
|
529
|
+
dataArr.push(data);
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
const encoder = new TextEncoder();
|
|
533
|
+
const offsets = new Int32Array(n + 1);
|
|
534
|
+
let totalBytes = 0;
|
|
535
|
+
// Single pass: encode directly into a growing buffer
|
|
536
|
+
const strParts = [];
|
|
537
|
+
for (let i = 0; i < n; i++) {
|
|
538
|
+
offsets[i] = totalBytes;
|
|
539
|
+
const s = values[indices[i]] != null ? String(values[indices[i]]) : '';
|
|
540
|
+
const encoded = encoder.encode(s);
|
|
541
|
+
strParts.push(encoded);
|
|
542
|
+
totalBytes += encoded.length;
|
|
543
|
+
}
|
|
544
|
+
offsets[n] = totalBytes;
|
|
545
|
+
const valueBuffer = new Uint8Array(totalBytes);
|
|
546
|
+
let pos = 0;
|
|
547
|
+
for (const sv of strParts) {
|
|
548
|
+
valueBuffer.set(sv, pos);
|
|
549
|
+
pos += sv.length;
|
|
550
|
+
}
|
|
551
|
+
const data = makeData({
|
|
552
|
+
type: new Utf8(),
|
|
553
|
+
length: n,
|
|
554
|
+
valueOffsets: offsets,
|
|
555
|
+
data: valueBuffer
|
|
556
|
+
});
|
|
557
|
+
fields.push(new Field(name, new Utf8(), true));
|
|
558
|
+
dataArr.push(data);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return { fields, data: dataArr };
|
|
562
|
+
}
|
|
563
|
+
/** Build a single GeoArrow table for one geometry type group. */
|
|
564
|
+
function buildSingleTable(geomType, wkbs, indices, attributes, b) {
|
|
565
|
+
const n = wkbs.length;
|
|
566
|
+
let geomData;
|
|
567
|
+
switch (geomType) {
|
|
568
|
+
case 'point':
|
|
569
|
+
geomData = buildPointData(wkbs, b);
|
|
570
|
+
break;
|
|
571
|
+
case 'linestring':
|
|
572
|
+
geomData = buildLineStringData(wkbs, b);
|
|
573
|
+
break;
|
|
574
|
+
case 'polygon':
|
|
575
|
+
geomData = buildPolygonData(wkbs, b);
|
|
576
|
+
break;
|
|
577
|
+
case 'multipoint':
|
|
578
|
+
geomData = buildMultiPointData(wkbs, b);
|
|
579
|
+
break;
|
|
580
|
+
case 'multilinestring':
|
|
581
|
+
geomData = buildMultiLineStringData(wkbs, b);
|
|
582
|
+
break;
|
|
583
|
+
case 'multipolygon':
|
|
584
|
+
geomData = buildMultiPolygonData(wkbs, b);
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
const extensionName = EXTENSION_NAMES[geomType];
|
|
588
|
+
const geomMetadata = new Map([
|
|
589
|
+
['ARROW:extension:name', extensionName],
|
|
590
|
+
[
|
|
591
|
+
'ARROW:extension:metadata',
|
|
592
|
+
JSON.stringify({
|
|
593
|
+
crs: {
|
|
594
|
+
type: 'name',
|
|
595
|
+
properties: { name: 'urn:ogc:def:crs:OGC:1.3:CRS84' }
|
|
596
|
+
}
|
|
597
|
+
})
|
|
598
|
+
]
|
|
599
|
+
]);
|
|
600
|
+
const geomField = new Field('geometry', geomData.type, false, geomMetadata);
|
|
601
|
+
const attrCols = buildAttributeColumns(indices, attributes);
|
|
602
|
+
const fields = [geomField, ...attrCols.fields];
|
|
603
|
+
const childrenData = [geomData, ...attrCols.data];
|
|
604
|
+
const arrowSchema = new Schema(fields);
|
|
605
|
+
const structType = new Struct(fields);
|
|
606
|
+
const structData = makeData({
|
|
607
|
+
type: structType,
|
|
608
|
+
length: n,
|
|
609
|
+
nullCount: 0,
|
|
610
|
+
children: childrenData
|
|
611
|
+
});
|
|
612
|
+
const batch = new RecordBatch(arrowSchema, structData);
|
|
613
|
+
const table = new Table(arrowSchema, batch);
|
|
614
|
+
return {
|
|
615
|
+
table,
|
|
616
|
+
geometryType: geomType,
|
|
617
|
+
bounds: [b.minX, b.minY, b.maxX, b.maxY],
|
|
618
|
+
sourceIndices: indices
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
// ─── Main entry point ────────────────────────────────────────────────
|
|
622
|
+
/**
|
|
623
|
+
* Build GeoArrow tables from raw WKB arrays, automatically splitting by geometry type.
|
|
624
|
+
* Returns one GeoArrowResult per non-empty type group, with shared merged bounds.
|
|
625
|
+
*
|
|
626
|
+
* @param wkbArrays Raw WKB binary arrays from DuckDB
|
|
627
|
+
* @param attributes Attribute columns (non-geometry)
|
|
628
|
+
* @param knownGeomType If provided (e.g. from GeoParquet metadata), skip classification
|
|
629
|
+
*/
|
|
630
|
+
export function buildGeoArrowTables(wkbArrays, attributes, knownGeomType) {
|
|
631
|
+
if (wkbArrays.length === 0)
|
|
632
|
+
return [];
|
|
633
|
+
// Fast path: known geometry type from metadata — skip classification entirely
|
|
634
|
+
if (knownGeomType) {
|
|
635
|
+
const globalBounds = newBounds();
|
|
636
|
+
const indices = Array.from({ length: wkbArrays.length }, (_, i) => i);
|
|
637
|
+
const result = buildSingleTable(knownGeomType, wkbArrays, indices, attributes, globalBounds);
|
|
638
|
+
return [result];
|
|
639
|
+
}
|
|
640
|
+
// Classify by reading only the type bytes (5 bytes per WKB, not full parse)
|
|
641
|
+
const groups = new Map();
|
|
642
|
+
for (let i = 0; i < wkbArrays.length; i++) {
|
|
643
|
+
const geomType = classifyWkbType(wkbArrays[i]);
|
|
644
|
+
if (!geomType)
|
|
645
|
+
continue;
|
|
646
|
+
let group = groups.get(geomType);
|
|
647
|
+
if (!group) {
|
|
648
|
+
group = { wkbs: [], indices: [] };
|
|
649
|
+
groups.set(geomType, group);
|
|
650
|
+
}
|
|
651
|
+
group.wkbs.push(wkbArrays[i]);
|
|
652
|
+
group.indices.push(i);
|
|
653
|
+
}
|
|
654
|
+
if (groups.size === 0)
|
|
655
|
+
return [];
|
|
656
|
+
const globalBounds = newBounds();
|
|
657
|
+
const results = [];
|
|
658
|
+
for (const [geomType, { wkbs, indices }] of groups) {
|
|
659
|
+
const result = buildSingleTable(geomType, wkbs, indices, attributes, globalBounds);
|
|
660
|
+
results.push(result);
|
|
661
|
+
}
|
|
662
|
+
// Share merged bounds across all results
|
|
663
|
+
const mergedBounds = [
|
|
664
|
+
globalBounds.minX,
|
|
665
|
+
globalBounds.minY,
|
|
666
|
+
globalBounds.maxX,
|
|
667
|
+
globalBounds.maxY
|
|
668
|
+
];
|
|
669
|
+
for (const r of results)
|
|
670
|
+
r.bounds = mergedBounds;
|
|
671
|
+
return results;
|
|
672
|
+
}
|