@walkthru-earth/objex 1.3.1 → 1.4.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 +5 -0
- package/README.md +20 -12
- package/dist/components/browser/FileTreeSidebar.svelte +32 -17
- package/dist/components/layout/AboutSheet.svelte +5 -2
- package/dist/components/layout/ConnectionDialog.svelte +1 -1
- package/dist/components/layout/SettingsSheet.svelte +237 -0
- package/dist/components/layout/SettingsSheet.svelte.d.ts +6 -0
- package/dist/components/layout/Sidebar.svelte +73 -6
- package/dist/components/layout/Sidebar.svelte.d.ts +4 -1
- package/dist/components/layout/StatusBar.svelte +1 -1
- package/dist/components/layout/TabBar.svelte +2 -2
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +1 -1
- package/dist/components/ui/input/input.svelte.d.ts +1 -1
- package/dist/components/ui/resizable/index.d.ts +1 -1
- package/dist/components/ui/resizable/index.js +2 -2
- package/dist/components/ui/slider/index.d.ts +3 -0
- package/dist/components/ui/slider/index.js +5 -0
- package/dist/components/ui/slider/range-slider.svelte +94 -0
- package/dist/components/ui/slider/range-slider.svelte.d.ts +21 -0
- package/dist/components/ui/slider/slider.svelte +83 -0
- package/dist/components/ui/slider/slider.svelte.d.ts +7 -0
- package/dist/components/viewers/ArchiveViewer.svelte +2 -2
- package/dist/components/viewers/CodeViewer.svelte +31 -22
- package/dist/components/viewers/CogControls.svelte +338 -184
- package/dist/components/viewers/CogControls.svelte.d.ts +33 -10
- package/dist/components/viewers/CogViewer.svelte +263 -112
- package/dist/components/viewers/CopcViewer.svelte +1 -1
- package/dist/components/viewers/FlatGeobufViewer.svelte +1 -1
- package/dist/components/viewers/GeoParquetMapViewer.svelte +6 -6
- package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/ImageViewer.svelte +2 -2
- package/dist/components/viewers/MarkdownViewer.svelte +12 -9
- package/dist/components/viewers/MediaViewer.svelte +2 -2
- package/dist/components/viewers/ModelViewer.svelte +1 -1
- package/dist/components/viewers/MultiCogViewer.svelte +467 -102
- package/dist/components/viewers/MultiCogViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/NotebookViewer.svelte +6 -3
- package/dist/components/viewers/PdfViewer.svelte +2 -2
- package/dist/components/viewers/PmtilesViewer.svelte +3 -6
- package/dist/components/viewers/RawViewer.svelte +6 -3
- package/dist/components/viewers/StacMapViewer.svelte +1 -1
- package/dist/components/viewers/StacMosaicViewer.svelte +1760 -408
- package/dist/components/viewers/StacMosaicViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/StacTabViewer.svelte +24 -13
- package/dist/components/viewers/StacTabViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/TableGrid.svelte +4 -4
- package/dist/components/viewers/TableStatusBar.svelte +1 -1
- package/dist/components/viewers/TableToolbar.svelte +1 -1
- package/dist/components/viewers/TableViewer.svelte +25 -17
- package/dist/components/viewers/TableViewer.svelte.d.ts +1 -0
- package/dist/components/viewers/ViewerRouter.svelte +16 -8
- package/dist/components/viewers/ZarrMapViewer.svelte +11 -9
- package/dist/components/viewers/ZarrViewer.svelte +4 -4
- package/dist/components/viewers/cog/ChannelPicker.svelte +83 -0
- package/dist/components/viewers/cog/ChannelPicker.svelte.d.ts +13 -0
- package/dist/components/viewers/cog/PixelInspectorPanel.svelte +87 -0
- package/dist/components/viewers/cog/PixelInspectorPanel.svelte.d.ts +17 -0
- package/dist/components/viewers/cog/buildRgbLayer.d.ts +78 -0
- package/dist/components/viewers/cog/buildRgbLayer.js +176 -0
- package/dist/components/viewers/map/AttributeTable.svelte +1 -1
- package/dist/components/viewers/map/MapContainer.svelte +37 -11
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +1 -1
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +1 -1
- package/dist/components/viewers/stac/StacDatetimeBar.svelte +175 -0
- package/dist/components/viewers/stac/StacDatetimeBar.svelte.d.ts +10 -0
- package/dist/components/viewers/stac/StacFilterPanel.svelte +243 -0
- package/dist/components/viewers/stac/StacFilterPanel.svelte.d.ts +14 -0
- package/dist/components/viewers/stac/StacItemInspector.svelte +223 -0
- package/dist/components/viewers/stac/StacItemInspector.svelte.d.ts +10 -0
- package/dist/components/viewers/stac/StacItemStrip.svelte +228 -0
- package/dist/components/viewers/stac/StacItemStrip.svelte.d.ts +12 -0
- package/dist/file-icons/index.d.ts +1 -1
- package/dist/file-icons/index.js +1 -1
- package/dist/i18n/ar.js +110 -2
- package/dist/i18n/en.js +110 -2
- package/dist/index.d.ts +2 -28
- package/dist/index.js +7 -23
- package/dist/query/engine.d.ts +10 -0
- package/dist/query/source.js +1 -1
- package/dist/query/stac-source-factory.d.ts +65 -0
- package/dist/query/stac-source-factory.js +77 -0
- package/dist/query/stac-source-parquet.d.ts +135 -0
- package/dist/query/stac-source-parquet.js +465 -0
- package/dist/query/wasm.d.ts +8 -0
- package/dist/query/wasm.js +304 -2
- package/dist/storage/presign.js +1 -1
- package/dist/storage/providers.js +5 -5
- package/dist/stores/config.svelte.d.ts +15 -0
- package/dist/stores/config.svelte.js +46 -0
- package/dist/stores/connections.svelte.d.ts +2 -2
- package/dist/stores/connections.svelte.js +1 -2
- package/dist/stores/files.svelte.d.ts +1 -1
- package/dist/stores/files.svelte.js +1 -1
- package/dist/stores/query-history.svelte.js +1 -1
- package/dist/stores/settings.svelte.d.ts +16 -1
- package/dist/stores/settings.svelte.js +104 -48
- package/dist/stores/tabs.svelte.d.ts +3 -0
- package/dist/stores/tabs.svelte.js +17 -0
- package/dist/utils/cog-histogram.d.ts +121 -0
- package/dist/utils/cog-histogram.js +424 -0
- package/dist/utils/cog.d.ts +177 -20
- package/dist/utils/cog.js +361 -76
- package/dist/utils/colormap-sprite.d.ts +0 -9
- package/dist/utils/colormap-sprite.js +0 -21
- package/dist/utils/deck.d.ts +16 -12
- package/dist/utils/deck.js +10 -4
- package/dist/utils/pmtiles-tile.js +2 -2
- package/dist/utils/{url.d.ts → signed-url.d.ts} +15 -1
- package/dist/utils/{url.js → signed-url.js} +32 -10
- package/dist/utils/url-state.d.ts +36 -0
- package/dist/utils/url-state.js +72 -2
- package/dist/utils/zarr-tab.d.ts +1 -2
- package/dist/utils/zarr-tab.js +1 -2
- package/dist/utils/zarr.d.ts +0 -17
- package/dist/utils/zarr.js +1 -45
- package/package.json +55 -84
- package/dist/components/browser/Breadcrumb.svelte +0 -50
- package/dist/components/browser/Breadcrumb.svelte.d.ts +0 -7
- package/dist/components/browser/CreateFolderDialog.svelte +0 -98
- package/dist/components/browser/CreateFolderDialog.svelte.d.ts +0 -6
- package/dist/components/browser/DeleteConfirmDialog.svelte +0 -90
- package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +0 -8
- package/dist/components/browser/DropZone.svelte +0 -83
- package/dist/components/browser/DropZone.svelte.d.ts +0 -7
- package/dist/components/browser/FileBrowser.svelte +0 -252
- package/dist/components/browser/FileBrowser.svelte.d.ts +0 -3
- package/dist/components/browser/FileRow.svelte +0 -117
- package/dist/components/browser/FileRow.svelte.d.ts +0 -9
- package/dist/components/browser/RenameDialog.svelte +0 -101
- package/dist/components/browser/RenameDialog.svelte.d.ts +0 -8
- package/dist/components/browser/SearchBar.svelte +0 -40
- package/dist/components/browser/SearchBar.svelte.d.ts +0 -6
- package/dist/components/browser/UploadButton.svelte +0 -65
- package/dist/components/browser/UploadButton.svelte.d.ts +0 -3
- package/dist/query/stac-geoparquet.d.ts +0 -31
- package/dist/query/stac-geoparquet.js +0 -136
- package/dist/utils/clipboard.d.ts +0 -13
- package/dist/utils/clipboard.js +0 -38
- package/dist/utils/cloud-url.d.ts +0 -27
- package/dist/utils/cloud-url.js +0 -61
- package/dist/utils/cog-pure.d.ts +0 -25
- package/dist/utils/cog-pure.js +0 -35
- package/dist/utils/column-types.d.ts +0 -5
- package/dist/utils/column-types.js +0 -137
- package/dist/utils/connection-identity.d.ts +0 -51
- package/dist/utils/connection-identity.js +0 -97
- package/dist/utils/error.d.ts +0 -8
- package/dist/utils/error.js +0 -12
- package/dist/utils/evidence-context.d.ts +0 -22
- package/dist/utils/evidence-context.js +0 -56
- package/dist/utils/export.d.ts +0 -22
- package/dist/utils/export.js +0 -76
- package/dist/utils/file-sort.d.ts +0 -20
- package/dist/utils/file-sort.js +0 -41
- package/dist/utils/format.d.ts +0 -24
- package/dist/utils/format.js +0 -78
- package/dist/utils/geoarrow.d.ts +0 -32
- package/dist/utils/geoarrow.js +0 -672
- package/dist/utils/geometry-type.d.ts +0 -52
- package/dist/utils/geometry-type.js +0 -76
- package/dist/utils/hex.d.ts +0 -10
- package/dist/utils/hex.js +0 -27
- package/dist/utils/host-detection.d.ts +0 -23
- package/dist/utils/host-detection.js +0 -95
- package/dist/utils/local-storage.d.ts +0 -16
- package/dist/utils/local-storage.js +0 -37
- package/dist/utils/markdown-sql.d.ts +0 -30
- package/dist/utils/markdown-sql.js +0 -72
- package/dist/utils/notebook.d.ts +0 -59
- package/dist/utils/notebook.js +0 -211
- package/dist/utils/parquet-metadata.d.ts +0 -64
- package/dist/utils/parquet-metadata.js +0 -262
- package/dist/utils/stac-geoparquet.d.ts +0 -90
- package/dist/utils/stac-geoparquet.js +0 -223
- package/dist/utils/stac-hydrate.d.ts +0 -38
- package/dist/utils/stac-hydrate.js +0 -243
- package/dist/utils/stac.d.ts +0 -136
- package/dist/utils/stac.js +0 -176
- package/dist/utils/storage-url.d.ts +0 -90
- package/dist/utils/storage-url.js +0 -568
- package/dist/utils/wkb.d.ts +0 -43
- package/dist/utils/wkb.js +0 -359
|
@@ -1,568 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Universal cloud storage URL / bucket parser.
|
|
3
|
-
*
|
|
4
|
-
* Accepts the many URI/URL formats that users commonly paste and extracts
|
|
5
|
-
* the correct bucket, region, endpoint, and provider.
|
|
6
|
-
*
|
|
7
|
-
* Supported URI schemes:
|
|
8
|
-
* s3:// s3a:// s3n:// aws:// — Amazon S3 / S3-compatible
|
|
9
|
-
* r2:// — Cloudflare R2
|
|
10
|
-
* gs:// gcs:// — Google Cloud Storage
|
|
11
|
-
* azure:// az:// — Azure Blob Storage
|
|
12
|
-
* abfs:// abfss:// — Azure Data Lake (ADLS Gen2)
|
|
13
|
-
* wasbs:// — Azure Blob (Hadoop WASB driver)
|
|
14
|
-
* swift:// — OpenStack Swift
|
|
15
|
-
* file:// filesystem:// — Local filesystem
|
|
16
|
-
*
|
|
17
|
-
* Supported HTTPS URL patterns:
|
|
18
|
-
* https://<bucket>.s3.<region>.amazonaws.com[/prefix] — AWS virtual-hosted
|
|
19
|
-
* https://s3.<region>.amazonaws.com/<bucket>[/prefix] — AWS path-style
|
|
20
|
-
* https://s3.amazonaws.com/<bucket> — AWS global
|
|
21
|
-
* https://<account>.r2.cloudflarestorage.com/<bucket> — Cloudflare R2
|
|
22
|
-
* https://storage.googleapis.com/<bucket> — Google Cloud Storage
|
|
23
|
-
* https://<bucket>.storage.googleapis.com[/prefix] — GCS virtual-hosted
|
|
24
|
-
* https://<bucket>.<region>.digitaloceanspaces.com — DigitalOcean Spaces
|
|
25
|
-
* https://<region>.digitaloceanspaces.com/<bucket> — DO Spaces path-style
|
|
26
|
-
* https://s3.<region>.wasabisys.com/<bucket> — Wasabi
|
|
27
|
-
* https://f<id>.backblazeb2.com/file/<bucket> — Backblaze B2
|
|
28
|
-
* https://<bucket>.s3.<region>.backblazeb2.com — B2 S3-compatible
|
|
29
|
-
* https://<bucket>.oss-<region>.aliyuncs.com — Alibaba Cloud OSS
|
|
30
|
-
* https://<bucket>.cos.<region>.myqcloud.com — Tencent COS
|
|
31
|
-
* https://storage.yandexcloud.net/<bucket> — Yandex Cloud
|
|
32
|
-
* https://gateway.storjshare.io/<bucket> — Storj S3 gateway
|
|
33
|
-
* https://link.storjshare.io/raw/<access>/<bucket> — Storj linksharing
|
|
34
|
-
* https://<custom-endpoint>/<bucket> — Generic S3-compatible
|
|
35
|
-
*
|
|
36
|
-
* Also handles plain bucket names (no protocol).
|
|
37
|
-
*/
|
|
38
|
-
import { PROVIDERS } from '../storage/providers.js';
|
|
39
|
-
/**
|
|
40
|
-
* Build SCHEME_MAP from the provider registry's `schemes` arrays.
|
|
41
|
-
* Each scheme like "s3" generates an entry `"s3://": { provider: "s3", strip: 5 }`.
|
|
42
|
-
*/
|
|
43
|
-
function buildSchemeMap() {
|
|
44
|
-
const map = {};
|
|
45
|
-
for (const [id, def] of Object.entries(PROVIDERS)) {
|
|
46
|
-
for (const scheme of def.schemes) {
|
|
47
|
-
const key = `${scheme}://`;
|
|
48
|
-
map[key] = { provider: id, strip: key.length };
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// Non-registry schemes (no corresponding provider)
|
|
52
|
-
map['swift://'] = { provider: 'unknown', strip: 8 };
|
|
53
|
-
return map;
|
|
54
|
-
}
|
|
55
|
-
/** All recognized URI scheme prefixes (lowercase), derived from provider registry */
|
|
56
|
-
const SCHEME_MAP = buildSchemeMap();
|
|
57
|
-
/**
|
|
58
|
-
* Shared host matchers. Used by both `parseStorageUrl` and `isKnownBucketHost`
|
|
59
|
-
* so provider recognition has a single source of truth.
|
|
60
|
-
*/
|
|
61
|
-
const AWS_VHOST_RE = /^(.+)\.s3[.-]([a-z0-9-]+)\.amazonaws\.com$/;
|
|
62
|
-
const AWS_PATH_RE = /^s3[.-]([a-z0-9-]+)\.amazonaws\.com$/;
|
|
63
|
-
const AWS_GLOBAL_HOST = 's3.amazonaws.com';
|
|
64
|
-
const R2_RE = /^([a-z0-9]+)\.r2\.cloudflarestorage\.com$/;
|
|
65
|
-
const GCS_GLOBAL_HOST = 'storage.googleapis.com';
|
|
66
|
-
const GCS_VHOST_RE = /^(.+)\.storage\.googleapis\.com$/;
|
|
67
|
-
const DO_VHOST_RE = /^(.+)\.([a-z0-9-]+)\.digitaloceanspaces\.com$/;
|
|
68
|
-
const DO_PATH_RE = /^([a-z0-9-]+)\.digitaloceanspaces\.com$/;
|
|
69
|
-
const WASABI_RE = /^s3\.([a-z0-9-]+)\.wasabisys\.com$/;
|
|
70
|
-
const B2_S3_RE = /^(.+)\.s3\.([a-z0-9-]+)\.backblazeb2\.com$/;
|
|
71
|
-
const B2_NATIVE_RE = /^f[a-z0-9]+\.backblazeb2\.com$/;
|
|
72
|
-
const OSS_RE = /^(.+)\.(oss-[a-z0-9-]+)\.aliyuncs\.com$/;
|
|
73
|
-
const COS_RE = /^(.+)\.cos\.([a-z0-9-]+)\.myqcloud\.com$/;
|
|
74
|
-
const YANDEX_HOST = 'storage.yandexcloud.net';
|
|
75
|
-
const CONTABO_RE = /^([a-z0-9]+)\.contabostorage\.com$/;
|
|
76
|
-
const HETZNER_RE = /^([a-z0-9]+)\.your-objectstorage\.com$/;
|
|
77
|
-
const LINODE_VHOST_RE = /^(.+)\.([a-z0-9-]+)\.linodeobjects\.com$/;
|
|
78
|
-
const LINODE_PATH_RE = /^([a-z0-9-]+)\.linodeobjects\.com$/;
|
|
79
|
-
const OVH_RE = /^s3\.([a-z0-9-]+)\.io\.cloud\.ovh\.(?:net|us)$/;
|
|
80
|
-
const AZURE_BLOB_RE = /^([a-z0-9]+)\.blob\.core\.windows\.net$/;
|
|
81
|
-
const STORJ_GATEWAY_RE = /^gateway\.(?:([a-z0-9]+)\.)?storjshare\.io$/;
|
|
82
|
-
const STORJ_LINK_RE = /^link\.(?:([a-z0-9]+)\.)?storjshare\.io$/;
|
|
83
|
-
function isMinioLikeHost(host) {
|
|
84
|
-
return (host.includes('minio') ||
|
|
85
|
-
host === 'localhost' ||
|
|
86
|
-
host === '127.0.0.1' ||
|
|
87
|
-
host.startsWith('192.168.') ||
|
|
88
|
-
host.startsWith('10.'));
|
|
89
|
-
}
|
|
90
|
-
/** STAC API path test, one source of truth. Tests pathname only. */
|
|
91
|
-
export const STAC_API_PATH_RE = /\/(collections|items|catalogs|search)(\/|\?|$)/i;
|
|
92
|
-
/**
|
|
93
|
-
* Returns true when the host matches any of the provider host patterns
|
|
94
|
-
* that `parseStorageUrl` recognizes on the HTTPS branch.
|
|
95
|
-
*/
|
|
96
|
-
export function isKnownBucketHost(host) {
|
|
97
|
-
if (!host)
|
|
98
|
-
return false;
|
|
99
|
-
if (AWS_VHOST_RE.test(host))
|
|
100
|
-
return true;
|
|
101
|
-
if (AWS_PATH_RE.test(host))
|
|
102
|
-
return true;
|
|
103
|
-
if (host === AWS_GLOBAL_HOST)
|
|
104
|
-
return true;
|
|
105
|
-
if (R2_RE.test(host))
|
|
106
|
-
return true;
|
|
107
|
-
if (host === GCS_GLOBAL_HOST)
|
|
108
|
-
return true;
|
|
109
|
-
if (GCS_VHOST_RE.test(host))
|
|
110
|
-
return true;
|
|
111
|
-
if (DO_VHOST_RE.test(host))
|
|
112
|
-
return true;
|
|
113
|
-
if (DO_PATH_RE.test(host))
|
|
114
|
-
return true;
|
|
115
|
-
if (WASABI_RE.test(host))
|
|
116
|
-
return true;
|
|
117
|
-
if (B2_S3_RE.test(host))
|
|
118
|
-
return true;
|
|
119
|
-
if (B2_NATIVE_RE.test(host))
|
|
120
|
-
return true;
|
|
121
|
-
if (OSS_RE.test(host))
|
|
122
|
-
return true;
|
|
123
|
-
if (COS_RE.test(host))
|
|
124
|
-
return true;
|
|
125
|
-
if (host === YANDEX_HOST)
|
|
126
|
-
return true;
|
|
127
|
-
if (CONTABO_RE.test(host))
|
|
128
|
-
return true;
|
|
129
|
-
if (HETZNER_RE.test(host))
|
|
130
|
-
return true;
|
|
131
|
-
if (LINODE_VHOST_RE.test(host))
|
|
132
|
-
return true;
|
|
133
|
-
if (LINODE_PATH_RE.test(host))
|
|
134
|
-
return true;
|
|
135
|
-
if (OVH_RE.test(host))
|
|
136
|
-
return true;
|
|
137
|
-
if (AZURE_BLOB_RE.test(host))
|
|
138
|
-
return true;
|
|
139
|
-
if (STORJ_GATEWAY_RE.test(host))
|
|
140
|
-
return true;
|
|
141
|
-
if (STORJ_LINK_RE.test(host))
|
|
142
|
-
return true;
|
|
143
|
-
if (isMinioLikeHost(host))
|
|
144
|
-
return true;
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
function defaultResult(defaults) {
|
|
148
|
-
return {
|
|
149
|
-
bucket: '',
|
|
150
|
-
region: defaults.region || 'us-east-1',
|
|
151
|
-
endpoint: defaults.endpoint || '',
|
|
152
|
-
provider: defaults.provider || 's3',
|
|
153
|
-
prefix: ''
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
function splitBucketPrefix(rest) {
|
|
157
|
-
const slashIdx = rest.indexOf('/');
|
|
158
|
-
if (slashIdx >= 0) {
|
|
159
|
-
return {
|
|
160
|
-
bucket: rest.slice(0, slashIdx),
|
|
161
|
-
prefix: rest.slice(slashIdx + 1).replace(/\/+$/, '')
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
return { bucket: rest, prefix: '' };
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Parse a user-provided bucket/URL string into structured storage connection parts.
|
|
168
|
-
*/
|
|
169
|
-
export function parseStorageUrl(input, defaults = {}) {
|
|
170
|
-
const trimmed = input.trim();
|
|
171
|
-
// ── Custom URI schemes (s3://, gs://, r2://, az://, etc.) ──────────
|
|
172
|
-
const lower = trimmed.toLowerCase();
|
|
173
|
-
for (const [scheme, { provider, strip }] of Object.entries(SCHEME_MAP)) {
|
|
174
|
-
if (lower.startsWith(scheme)) {
|
|
175
|
-
const rest = trimmed.slice(strip);
|
|
176
|
-
const { bucket, prefix } = splitBucketPrefix(rest);
|
|
177
|
-
return {
|
|
178
|
-
bucket,
|
|
179
|
-
region: defaults.region || 'us-east-1',
|
|
180
|
-
endpoint: defaults.endpoint || '',
|
|
181
|
-
provider,
|
|
182
|
-
prefix
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// ── HTTP(S) URL ─────────────────────────────────────────────────
|
|
187
|
-
if (lower.startsWith('http://') || lower.startsWith('https://')) {
|
|
188
|
-
try {
|
|
189
|
-
const url = new URL(trimmed);
|
|
190
|
-
const host = url.hostname;
|
|
191
|
-
const pathParts = url.pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
192
|
-
// --- AWS S3 ---
|
|
193
|
-
// Virtual-hosted: <bucket>.s3.<region>.amazonaws.com
|
|
194
|
-
const awsVhost = host.match(AWS_VHOST_RE);
|
|
195
|
-
if (awsVhost) {
|
|
196
|
-
return {
|
|
197
|
-
bucket: awsVhost[1],
|
|
198
|
-
region: awsVhost[2],
|
|
199
|
-
endpoint: '',
|
|
200
|
-
provider: 's3',
|
|
201
|
-
prefix: pathParts.join('/')
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
// Path-style: s3.<region>.amazonaws.com/<bucket>
|
|
205
|
-
const awsPath = host.match(AWS_PATH_RE);
|
|
206
|
-
if (awsPath && pathParts.length > 0) {
|
|
207
|
-
return {
|
|
208
|
-
bucket: pathParts[0],
|
|
209
|
-
region: awsPath[1],
|
|
210
|
-
endpoint: '',
|
|
211
|
-
provider: 's3',
|
|
212
|
-
prefix: pathParts.slice(1).join('/')
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
// Global: s3.amazonaws.com/<bucket>
|
|
216
|
-
if (host === AWS_GLOBAL_HOST && pathParts.length > 0) {
|
|
217
|
-
return {
|
|
218
|
-
bucket: pathParts[0],
|
|
219
|
-
region: defaults.region || 'us-east-1',
|
|
220
|
-
endpoint: '',
|
|
221
|
-
provider: 's3',
|
|
222
|
-
prefix: pathParts.slice(1).join('/')
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
// --- Cloudflare R2 ---
|
|
226
|
-
// <account>.r2.cloudflarestorage.com/<bucket>
|
|
227
|
-
const r2Match = host.match(R2_RE);
|
|
228
|
-
if (r2Match && pathParts.length > 0) {
|
|
229
|
-
return {
|
|
230
|
-
bucket: pathParts[0],
|
|
231
|
-
region: 'auto',
|
|
232
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
233
|
-
provider: 'r2',
|
|
234
|
-
prefix: pathParts.slice(1).join('/')
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
// --- Google Cloud Storage ---
|
|
238
|
-
// storage.googleapis.com/<bucket>
|
|
239
|
-
if (host === GCS_GLOBAL_HOST && pathParts.length > 0) {
|
|
240
|
-
return {
|
|
241
|
-
bucket: pathParts[0],
|
|
242
|
-
region: defaults.region || 'us',
|
|
243
|
-
endpoint: '',
|
|
244
|
-
provider: 'gcs',
|
|
245
|
-
prefix: pathParts.slice(1).join('/')
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
// <bucket>.storage.googleapis.com
|
|
249
|
-
const gcsVhost = host.match(GCS_VHOST_RE);
|
|
250
|
-
if (gcsVhost) {
|
|
251
|
-
return {
|
|
252
|
-
bucket: gcsVhost[1],
|
|
253
|
-
region: defaults.region || 'us',
|
|
254
|
-
endpoint: '',
|
|
255
|
-
provider: 'gcs',
|
|
256
|
-
prefix: pathParts.join('/')
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
// --- DigitalOcean Spaces ---
|
|
260
|
-
// <bucket>.<region>.digitaloceanspaces.com
|
|
261
|
-
const doVhost = host.match(DO_VHOST_RE);
|
|
262
|
-
if (doVhost) {
|
|
263
|
-
return {
|
|
264
|
-
bucket: doVhost[1],
|
|
265
|
-
region: doVhost[2],
|
|
266
|
-
endpoint: `${url.protocol}//${doVhost[2]}.digitaloceanspaces.com`,
|
|
267
|
-
provider: 'digitalocean',
|
|
268
|
-
prefix: pathParts.join('/')
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
// <region>.digitaloceanspaces.com/<bucket>
|
|
272
|
-
const doPath = host.match(DO_PATH_RE);
|
|
273
|
-
if (doPath && pathParts.length > 0) {
|
|
274
|
-
return {
|
|
275
|
-
bucket: pathParts[0],
|
|
276
|
-
region: doPath[1],
|
|
277
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
278
|
-
provider: 'digitalocean',
|
|
279
|
-
prefix: pathParts.slice(1).join('/')
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
// --- Wasabi ---
|
|
283
|
-
// s3.<region>.wasabisys.com/<bucket>
|
|
284
|
-
const wasabiMatch = host.match(WASABI_RE);
|
|
285
|
-
if (wasabiMatch && pathParts.length > 0) {
|
|
286
|
-
return {
|
|
287
|
-
bucket: pathParts[0],
|
|
288
|
-
region: wasabiMatch[1],
|
|
289
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
290
|
-
provider: 'wasabi',
|
|
291
|
-
prefix: pathParts.slice(1).join('/')
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
// --- Backblaze B2 ---
|
|
295
|
-
// <bucket>.s3.<region>.backblazeb2.com (S3-compatible)
|
|
296
|
-
const b2S3 = host.match(B2_S3_RE);
|
|
297
|
-
if (b2S3) {
|
|
298
|
-
return {
|
|
299
|
-
bucket: b2S3[1],
|
|
300
|
-
region: b2S3[2],
|
|
301
|
-
endpoint: `${url.protocol}//s3.${b2S3[2]}.backblazeb2.com`,
|
|
302
|
-
provider: 'b2',
|
|
303
|
-
prefix: pathParts.join('/')
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
// f<id>.backblazeb2.com/file/<bucket>
|
|
307
|
-
const b2Native = host.match(B2_NATIVE_RE);
|
|
308
|
-
if (b2Native && pathParts[0] === 'file' && pathParts.length > 1) {
|
|
309
|
-
return {
|
|
310
|
-
bucket: pathParts[1],
|
|
311
|
-
region: defaults.region || 'us-west-000',
|
|
312
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
313
|
-
provider: 'b2',
|
|
314
|
-
prefix: pathParts.slice(2).join('/')
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
// --- Alibaba Cloud OSS ---
|
|
318
|
-
// <bucket>.oss-<region>.aliyuncs.com
|
|
319
|
-
const ossMatch = host.match(OSS_RE);
|
|
320
|
-
if (ossMatch) {
|
|
321
|
-
return {
|
|
322
|
-
bucket: ossMatch[1],
|
|
323
|
-
region: ossMatch[2],
|
|
324
|
-
endpoint: `${url.protocol}//${ossMatch[2]}.aliyuncs.com`,
|
|
325
|
-
provider: 's3',
|
|
326
|
-
prefix: pathParts.join('/')
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
// --- Tencent Cloud COS ---
|
|
330
|
-
// <bucket>.cos.<region>.myqcloud.com
|
|
331
|
-
const cosMatch = host.match(COS_RE);
|
|
332
|
-
if (cosMatch) {
|
|
333
|
-
return {
|
|
334
|
-
bucket: cosMatch[1],
|
|
335
|
-
region: cosMatch[2],
|
|
336
|
-
endpoint: `${url.protocol}//cos.${cosMatch[2]}.myqcloud.com`,
|
|
337
|
-
provider: 's3',
|
|
338
|
-
prefix: pathParts.join('/')
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
// --- Yandex Cloud ---
|
|
342
|
-
// storage.yandexcloud.net/<bucket>
|
|
343
|
-
if (host === YANDEX_HOST && pathParts.length > 0) {
|
|
344
|
-
return {
|
|
345
|
-
bucket: pathParts[0],
|
|
346
|
-
region: defaults.region || 'ru-central1',
|
|
347
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
348
|
-
provider: 's3',
|
|
349
|
-
prefix: pathParts.slice(1).join('/')
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
// --- Contabo ---
|
|
353
|
-
// <region>.contabostorage.com/<bucket>
|
|
354
|
-
const contaboMatch = host.match(CONTABO_RE);
|
|
355
|
-
if (contaboMatch && pathParts.length > 0) {
|
|
356
|
-
return {
|
|
357
|
-
bucket: pathParts[0],
|
|
358
|
-
region: contaboMatch[1],
|
|
359
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
360
|
-
provider: 'contabo',
|
|
361
|
-
prefix: pathParts.slice(1).join('/')
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
// --- Hetzner ---
|
|
365
|
-
// <region>.your-objectstorage.com/<bucket>
|
|
366
|
-
const hetznerMatch = host.match(HETZNER_RE);
|
|
367
|
-
if (hetznerMatch && pathParts.length > 0) {
|
|
368
|
-
return {
|
|
369
|
-
bucket: pathParts[0],
|
|
370
|
-
region: hetznerMatch[1],
|
|
371
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
372
|
-
provider: 'hetzner',
|
|
373
|
-
prefix: pathParts.slice(1).join('/')
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
// --- Linode / Akamai ---
|
|
377
|
-
// <bucket>.<region>.linodeobjects.com or <region>.linodeobjects.com/<bucket>
|
|
378
|
-
const linodeVhost = host.match(LINODE_VHOST_RE);
|
|
379
|
-
if (linodeVhost) {
|
|
380
|
-
return {
|
|
381
|
-
bucket: linodeVhost[1],
|
|
382
|
-
region: linodeVhost[2],
|
|
383
|
-
endpoint: `${url.protocol}//${linodeVhost[2]}.linodeobjects.com`,
|
|
384
|
-
provider: 'linode',
|
|
385
|
-
prefix: pathParts.join('/')
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
const linodePath = host.match(LINODE_PATH_RE);
|
|
389
|
-
if (linodePath && pathParts.length > 0) {
|
|
390
|
-
return {
|
|
391
|
-
bucket: pathParts[0],
|
|
392
|
-
region: linodePath[1],
|
|
393
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
394
|
-
provider: 'linode',
|
|
395
|
-
prefix: pathParts.slice(1).join('/')
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
// --- OVHcloud ---
|
|
399
|
-
// s3.<region>.io.cloud.ovh.net/<bucket>
|
|
400
|
-
const ovhMatch = host.match(OVH_RE);
|
|
401
|
-
if (ovhMatch && pathParts.length > 0) {
|
|
402
|
-
return {
|
|
403
|
-
bucket: pathParts[0],
|
|
404
|
-
region: ovhMatch[1],
|
|
405
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
406
|
-
provider: 'ovhcloud',
|
|
407
|
-
prefix: pathParts.slice(1).join('/')
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
// --- MinIO ---
|
|
411
|
-
// Common patterns: minio.<domain>, localhost with port
|
|
412
|
-
if (isMinioLikeHost(host) && pathParts.length > 0) {
|
|
413
|
-
return {
|
|
414
|
-
bucket: pathParts[0],
|
|
415
|
-
region: defaults.region || 'us-east-1',
|
|
416
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
417
|
-
provider: 'minio',
|
|
418
|
-
prefix: pathParts.slice(1).join('/')
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
// --- Azure Blob Storage ---
|
|
422
|
-
// <account>.blob.core.windows.net/<container>
|
|
423
|
-
const azureBlob = host.match(AZURE_BLOB_RE);
|
|
424
|
-
if (azureBlob && pathParts.length > 0) {
|
|
425
|
-
return {
|
|
426
|
-
bucket: pathParts[0],
|
|
427
|
-
region: defaults.region || '',
|
|
428
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
429
|
-
provider: 'azure',
|
|
430
|
-
prefix: pathParts.slice(1).join('/')
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
// --- Storj ---
|
|
434
|
-
// S3 gateway: gateway.storjshare.io/<bucket> (or gateway.<region>.storjshare.io)
|
|
435
|
-
const storjGateway = host.match(STORJ_GATEWAY_RE);
|
|
436
|
-
if (storjGateway && pathParts.length > 0) {
|
|
437
|
-
return {
|
|
438
|
-
bucket: pathParts[0],
|
|
439
|
-
region: storjGateway[1] || defaults.region || 'us1',
|
|
440
|
-
endpoint: `${url.protocol}//${url.host}`,
|
|
441
|
-
provider: 'storj',
|
|
442
|
-
prefix: pathParts.slice(1).join('/')
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
// Linksharing: link.storjshare.io/raw/<access>/<bucket>/... or /s/<access>/<bucket>/...
|
|
446
|
-
const storjLink = host.match(STORJ_LINK_RE);
|
|
447
|
-
if (storjLink && pathParts.length >= 3 && (pathParts[0] === 'raw' || pathParts[0] === 's')) {
|
|
448
|
-
return {
|
|
449
|
-
bucket: pathParts[2],
|
|
450
|
-
region: storjLink[1] || defaults.region || 'us1',
|
|
451
|
-
endpoint: `${url.protocol}//${url.host}/${pathParts[0]}/${pathParts[1]}`,
|
|
452
|
-
provider: 'storj',
|
|
453
|
-
prefix: pathParts.slice(3).join('/')
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
// --- STAC API endpoints (Element 84, MPC, etc.) ---
|
|
457
|
-
// Paths like /v1/collections/.../items/... are not S3 buckets, the
|
|
458
|
-
// first path segment is an API version, not a bucket name. Return
|
|
459
|
-
// no bucket so detectHostBucket() falls through and the URL opens
|
|
460
|
-
// as a direct remote fetch.
|
|
461
|
-
if (STAC_API_PATH_RE.test(url.pathname)) {
|
|
462
|
-
return {
|
|
463
|
-
...defaultResult(defaults),
|
|
464
|
-
endpoint: `${url.protocol}//${url.host}`
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
// --- Generic custom endpoint with bucket in path ---
|
|
468
|
-
if (pathParts.length > 0) {
|
|
469
|
-
const endpoint = `${url.protocol}//${url.host}`;
|
|
470
|
-
return {
|
|
471
|
-
bucket: pathParts[0],
|
|
472
|
-
region: defaults.region || 'us-east-1',
|
|
473
|
-
endpoint,
|
|
474
|
-
provider: defaults.provider || 's3',
|
|
475
|
-
prefix: pathParts.slice(1).join('/')
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
// Just a host, no path — treat as endpoint with no bucket
|
|
479
|
-
return {
|
|
480
|
-
...defaultResult(defaults),
|
|
481
|
-
endpoint: `${url.protocol}//${url.host}`
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
catch {
|
|
485
|
-
// Not a valid URL, fall through to plain bucket name
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
// ── Plain bucket name (no protocol) ─────────────────────────────
|
|
489
|
-
const cleaned = trimmed.replace(/^\/+|\/+$/g, '');
|
|
490
|
-
return {
|
|
491
|
-
bucket: cleaned,
|
|
492
|
-
region: defaults.region || 'us-east-1',
|
|
493
|
-
endpoint: defaults.endpoint || '',
|
|
494
|
-
provider: defaults.provider || 's3',
|
|
495
|
-
prefix: ''
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* Returns true if the input looks like a URL/URI rather than a plain bucket name.
|
|
500
|
-
* Covers all recognized cloud storage URI schemes.
|
|
501
|
-
*/
|
|
502
|
-
export function looksLikeUrl(input) {
|
|
503
|
-
const lower = input.trim().toLowerCase();
|
|
504
|
-
if (lower.startsWith('http://') || lower.startsWith('https://'))
|
|
505
|
-
return true;
|
|
506
|
-
for (const scheme of Object.keys(SCHEME_MAP)) {
|
|
507
|
-
if (lower.startsWith(scheme))
|
|
508
|
-
return true;
|
|
509
|
-
}
|
|
510
|
-
return false;
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* Given a parsed URL result, build a human-readable summary of what was detected.
|
|
514
|
-
*/
|
|
515
|
-
export function describeParseResult(parsed) {
|
|
516
|
-
const parts = [];
|
|
517
|
-
if (parsed.bucket)
|
|
518
|
-
parts.push(`bucket="${parsed.bucket}"`);
|
|
519
|
-
if (parsed.endpoint)
|
|
520
|
-
parts.push(`endpoint="${parsed.endpoint}"`);
|
|
521
|
-
if (parsed.region && parsed.region !== 'us-east-1')
|
|
522
|
-
parts.push(`region="${parsed.region}"`);
|
|
523
|
-
if (parsed.provider !== 's3')
|
|
524
|
-
parts.push(`provider=${parsed.provider}`);
|
|
525
|
-
if (parsed.prefix)
|
|
526
|
-
parts.push(`prefix="${parsed.prefix}"`);
|
|
527
|
-
return parts.length > 0 ? `Detected: ${parts.join(', ')}` : '';
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Classify a user-supplied URL/URI into one of four buckets. Unparseable or
|
|
531
|
-
* plain inputs fall through to `remote-file` with a best-effort URL parse,
|
|
532
|
-
* returning a synthetic `https://` URL when `new URL()` would throw.
|
|
533
|
-
*/
|
|
534
|
-
export function classifyUrl(input) {
|
|
535
|
-
const trimmed = input.trim();
|
|
536
|
-
const lower = trimmed.toLowerCase();
|
|
537
|
-
for (const scheme of Object.keys(SCHEME_MAP)) {
|
|
538
|
-
if (lower.startsWith(scheme)) {
|
|
539
|
-
return { kind: 'scheme', parsed: parseStorageUrl(trimmed) };
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
if (lower.startsWith('http://') || lower.startsWith('https://')) {
|
|
543
|
-
let url;
|
|
544
|
-
try {
|
|
545
|
-
url = new URL(trimmed);
|
|
546
|
-
}
|
|
547
|
-
catch {
|
|
548
|
-
return {
|
|
549
|
-
kind: 'remote-file',
|
|
550
|
-
url: new URL(`https://${trimmed.replace(/^https?:\/\//i, '')}`)
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
const parsed = parseStorageUrl(trimmed);
|
|
554
|
-
if (parsed.bucket && isKnownBucketHost(url.hostname)) {
|
|
555
|
-
return { kind: 'object-storage', parsed };
|
|
556
|
-
}
|
|
557
|
-
if (STAC_API_PATH_RE.test(url.pathname)) {
|
|
558
|
-
return { kind: 'stac-api', url };
|
|
559
|
-
}
|
|
560
|
-
return { kind: 'remote-file', url };
|
|
561
|
-
}
|
|
562
|
-
try {
|
|
563
|
-
return { kind: 'remote-file', url: new URL(trimmed) };
|
|
564
|
-
}
|
|
565
|
-
catch {
|
|
566
|
-
return { kind: 'remote-file', url: new URL(`https://${trimmed}`) };
|
|
567
|
-
}
|
|
568
|
-
}
|
package/dist/utils/wkb.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight WKB (Well-Known Binary) parser for extracting coordinates.
|
|
3
|
-
* Supports Point, LineString, Polygon, and Multi* variants.
|
|
4
|
-
* Handles standard WKB, ISO WKB (with Z/M), and EWKB (PostGIS SRID).
|
|
5
|
-
*/
|
|
6
|
-
export type GeoType = 'Point' | 'LineString' | 'Polygon' | 'MultiPoint' | 'MultiLineString' | 'MultiPolygon' | 'Unknown';
|
|
7
|
-
export interface ParsedGeometry {
|
|
8
|
-
type: GeoType;
|
|
9
|
-
coordinates: number[] | number[][] | number[][][] | number[][][][];
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Normalize binary data from various formats to Uint8Array.
|
|
13
|
-
* Handles Uint8Array, ArrayBuffer, number arrays, hex strings,
|
|
14
|
-
* and DuckDB toJSON() blob objects ({0: byte, 1: byte, ...}).
|
|
15
|
-
*/
|
|
16
|
-
export declare function toBinary(value: unknown): Uint8Array | null;
|
|
17
|
-
/**
|
|
18
|
-
* Parse a WKB binary blob into coordinates and geometry type.
|
|
19
|
-
*/
|
|
20
|
-
export declare function parseWKB(data: Uint8Array): ParsedGeometry | null;
|
|
21
|
-
/**
|
|
22
|
-
* Find the geometry column name from a schema.
|
|
23
|
-
*
|
|
24
|
-
* Detection priority:
|
|
25
|
-
* 1. Column type contains a geometry keyword (GEOMETRY, POINT, WKB, etc.)
|
|
26
|
-
* 2. Exact well-known column name with BLOB/BINARY type
|
|
27
|
-
* 3. Exact well-known column name regardless of type
|
|
28
|
-
* 4. Column name contains a geo-related substring with BLOB/BINARY type
|
|
29
|
-
* 5. Column name contains a geo-related substring regardless of type
|
|
30
|
-
*/
|
|
31
|
-
export declare function findGeoColumn(schema: {
|
|
32
|
-
name: string;
|
|
33
|
-
type: string;
|
|
34
|
-
}[]): string | null;
|
|
35
|
-
/**
|
|
36
|
-
* Fallback: probe actual row data to find a column containing WKB geometry.
|
|
37
|
-
* Use this when schema-only detection via `findGeoColumn()` returns null.
|
|
38
|
-
* Samples the first row and checks each BLOB/binary column for WKB magic bytes.
|
|
39
|
-
*/
|
|
40
|
-
export declare function findGeoColumnFromRows(rows: Record<string, unknown>[], schema: {
|
|
41
|
-
name: string;
|
|
42
|
-
type: string;
|
|
43
|
-
}[]): string | null;
|