@walkthru-earth/objex-utils 1.2.0 → 1.3.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/README.md +8 -0
- package/dist/index.cjs +280 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +178 -2
- package/dist/index.d.ts +178 -2
- package/dist/index.js +270 -31
- package/dist/index.js.map +1 -1
- package/docs/README.md +1 -0
- package/docs/cog.md +14 -225
- package/docs/parquet-metadata.md +9 -1
- package/docs/stac-geoparquet.md +198 -0
- package/docs/storage.md +2 -0
- package/package.json +9 -4
package/dist/index.js
CHANGED
|
@@ -1355,6 +1355,11 @@ function buildEndpointFromTemplate(id, region) {
|
|
|
1355
1355
|
if (!def?.endpointTemplate) return "";
|
|
1356
1356
|
return def.endpointTemplate.replace("{region}", region);
|
|
1357
1357
|
}
|
|
1358
|
+
function resolveProviderEndpoint(provider, region) {
|
|
1359
|
+
const def = PROVIDERS[provider];
|
|
1360
|
+
if (!def?.endpointTemplate) return "";
|
|
1361
|
+
return buildEndpointFromTemplate(provider, region || def.defaultRegion);
|
|
1362
|
+
}
|
|
1358
1363
|
function buildProviderBaseUrl(provider, endpoint, bucket, region) {
|
|
1359
1364
|
if (endpoint) {
|
|
1360
1365
|
return `${endpoint.replace(/\/$/, "")}/${bucket}`;
|
|
@@ -1369,6 +1374,15 @@ function buildProviderBaseUrl(provider, endpoint, bucket, region) {
|
|
|
1369
1374
|
function isGcsProvider(provider, endpoint) {
|
|
1370
1375
|
return provider === "gcs" || !!endpoint && /storage\.googleapis\.com/i.test(endpoint);
|
|
1371
1376
|
}
|
|
1377
|
+
function getAccessMode(conn) {
|
|
1378
|
+
if (conn.provider === "azure") return "sas-https";
|
|
1379
|
+
if (conn.anonymous) return "public-https";
|
|
1380
|
+
return "signed-s3";
|
|
1381
|
+
}
|
|
1382
|
+
function isPubliclyStreamable(conn) {
|
|
1383
|
+
const mode = getAccessMode(conn);
|
|
1384
|
+
return mode === "public-https" || mode === "sas-https";
|
|
1385
|
+
}
|
|
1372
1386
|
|
|
1373
1387
|
// ../../src/lib/storage/url-adapter.ts
|
|
1374
1388
|
var UrlAdapter = class {
|
|
@@ -1638,6 +1652,17 @@ function formatValue(value) {
|
|
|
1638
1652
|
}
|
|
1639
1653
|
|
|
1640
1654
|
// ../../src/lib/utils/export.ts
|
|
1655
|
+
function triggerDownload(content, filename, mimeType) {
|
|
1656
|
+
const blob = new Blob([content], { type: mimeType });
|
|
1657
|
+
const url = URL.createObjectURL(blob);
|
|
1658
|
+
const a = document.createElement("a");
|
|
1659
|
+
a.href = url;
|
|
1660
|
+
a.download = filename;
|
|
1661
|
+
document.body.appendChild(a);
|
|
1662
|
+
a.click();
|
|
1663
|
+
document.body.removeChild(a);
|
|
1664
|
+
URL.revokeObjectURL(url);
|
|
1665
|
+
}
|
|
1641
1666
|
function formatCellValue(value) {
|
|
1642
1667
|
if (value === null || value === void 0) return "";
|
|
1643
1668
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -1672,6 +1697,20 @@ function serializeToJson(columns, rows) {
|
|
|
1672
1697
|
});
|
|
1673
1698
|
return JSON.stringify(data, jsonReplacerBigInt, 2);
|
|
1674
1699
|
}
|
|
1700
|
+
function exportToCsv(columns, rows, filename) {
|
|
1701
|
+
triggerDownload(
|
|
1702
|
+
serializeToCsv(columns, rows),
|
|
1703
|
+
filename.endsWith(".csv") ? filename : `${filename}.csv`,
|
|
1704
|
+
"text/csv;charset=utf-8;"
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
function exportToJson(columns, rows, filename) {
|
|
1708
|
+
triggerDownload(
|
|
1709
|
+
serializeToJson(columns, rows),
|
|
1710
|
+
filename.endsWith(".json") ? filename : `${filename}.json`,
|
|
1711
|
+
"application/json"
|
|
1712
|
+
);
|
|
1713
|
+
}
|
|
1675
1714
|
|
|
1676
1715
|
// ../../src/lib/utils/file-sort.ts
|
|
1677
1716
|
function sortFileEntries(entries, config) {
|
|
@@ -2436,6 +2475,15 @@ async function readParquetMetadata(url) {
|
|
|
2436
2475
|
name: col.name,
|
|
2437
2476
|
type: mapParquetType(col)
|
|
2438
2477
|
}));
|
|
2478
|
+
const topLevelColumns = [];
|
|
2479
|
+
const root = metadata.schema[0];
|
|
2480
|
+
const rootChildren = root?.num_children ?? 0;
|
|
2481
|
+
let cursor = 1;
|
|
2482
|
+
for (let i = 0; i < rootChildren && cursor < metadata.schema.length; i++) {
|
|
2483
|
+
const el = metadata.schema[cursor];
|
|
2484
|
+
if (el?.name) topLevelColumns.push(el.name);
|
|
2485
|
+
cursor += countSubtree(metadata.schema, cursor);
|
|
2486
|
+
}
|
|
2439
2487
|
let geo = null;
|
|
2440
2488
|
let legacyGeoParquet = false;
|
|
2441
2489
|
const geoKv = metadata.key_value_metadata?.find((kv) => kv.key === "geo");
|
|
@@ -2477,7 +2525,26 @@ async function readParquetMetadata(url) {
|
|
|
2477
2525
|
compression = [...codecs].join(", ");
|
|
2478
2526
|
}
|
|
2479
2527
|
}
|
|
2480
|
-
return {
|
|
2528
|
+
return {
|
|
2529
|
+
rowCount,
|
|
2530
|
+
schema,
|
|
2531
|
+
topLevelColumns,
|
|
2532
|
+
geo,
|
|
2533
|
+
legacyGeoParquet,
|
|
2534
|
+
createdBy,
|
|
2535
|
+
numRowGroups,
|
|
2536
|
+
compression
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
function countSubtree(schema, start) {
|
|
2540
|
+
const el = schema[start];
|
|
2541
|
+
if (!el) return 0;
|
|
2542
|
+
const n = el.num_children ?? 0;
|
|
2543
|
+
let cursor = start + 1;
|
|
2544
|
+
for (let i = 0; i < n; i++) {
|
|
2545
|
+
cursor += countSubtree(schema, cursor);
|
|
2546
|
+
}
|
|
2547
|
+
return cursor - start;
|
|
2481
2548
|
}
|
|
2482
2549
|
function extractEpsgFromGeoMeta(geo) {
|
|
2483
2550
|
const primaryCol = geo.columns[geo.primaryColumn];
|
|
@@ -2516,6 +2583,144 @@ function extractBounds(geo) {
|
|
|
2516
2583
|
return [primaryCol.bbox[0], primaryCol.bbox[1], primaryCol.bbox[2], primaryCol.bbox[3]];
|
|
2517
2584
|
}
|
|
2518
2585
|
|
|
2586
|
+
// ../../src/lib/utils/stac-geoparquet.ts
|
|
2587
|
+
var STAC_GEOPARQUET_REQUIRED_COLUMNS = [
|
|
2588
|
+
"stac_version",
|
|
2589
|
+
"type",
|
|
2590
|
+
"geometry",
|
|
2591
|
+
"assets"
|
|
2592
|
+
];
|
|
2593
|
+
function isStacGeoparquetSchema(schema) {
|
|
2594
|
+
if (!Array.isArray(schema) || schema.length === 0) return false;
|
|
2595
|
+
const names = new Set(schema.map((c) => c.name));
|
|
2596
|
+
return STAC_GEOPARQUET_REQUIRED_COLUMNS.every((c) => names.has(c));
|
|
2597
|
+
}
|
|
2598
|
+
function flattenStacBbox(bbox) {
|
|
2599
|
+
if (!bbox) return null;
|
|
2600
|
+
if (Array.isArray(bbox)) {
|
|
2601
|
+
if (bbox.length < 4) return null;
|
|
2602
|
+
const [minX, minY, maxX, maxY] = bbox;
|
|
2603
|
+
if (![minX, minY, maxX, maxY].every((v) => Number.isFinite(v))) return null;
|
|
2604
|
+
return [minX, minY, maxX, maxY];
|
|
2605
|
+
}
|
|
2606
|
+
if (typeof bbox === "object") {
|
|
2607
|
+
const { xmin, ymin, xmax, ymax } = bbox;
|
|
2608
|
+
if (![xmin, ymin, xmax, ymax].every((v) => Number.isFinite(v))) return null;
|
|
2609
|
+
return [xmin, ymin, xmax, ymax];
|
|
2610
|
+
}
|
|
2611
|
+
return null;
|
|
2612
|
+
}
|
|
2613
|
+
function resolveStacAssetHref(href, baseUrl) {
|
|
2614
|
+
if (!href) return href;
|
|
2615
|
+
if (/^[a-z][a-z0-9+\-.]*:\/\//i.test(href)) return href;
|
|
2616
|
+
try {
|
|
2617
|
+
return new URL(href, baseUrl).toString();
|
|
2618
|
+
} catch {
|
|
2619
|
+
return href;
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
function pickStacPrimaryAsset(assets, preferredKeys) {
|
|
2623
|
+
if (!assets || typeof assets !== "object") return null;
|
|
2624
|
+
const entries = Object.entries(assets).filter(
|
|
2625
|
+
([, a]) => a && typeof a === "object" && typeof a.href === "string"
|
|
2626
|
+
);
|
|
2627
|
+
if (entries.length === 0) return null;
|
|
2628
|
+
if (preferredKeys) {
|
|
2629
|
+
for (const key of preferredKeys) {
|
|
2630
|
+
const match = entries.find(([k]) => k === key);
|
|
2631
|
+
if (match) return { key: match[0], asset: match[1] };
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
const data = entries.find(([k]) => k === "data");
|
|
2635
|
+
if (data) return { key: data[0], asset: data[1] };
|
|
2636
|
+
const byRole = entries.find(([, a]) => Array.isArray(a.roles) && a.roles.includes("data"));
|
|
2637
|
+
if (byRole) return { key: byRole[0], asset: byRole[1] };
|
|
2638
|
+
return { key: entries[0][0], asset: entries[0][1] };
|
|
2639
|
+
}
|
|
2640
|
+
function normalizeAssetsField(value, baseUrl) {
|
|
2641
|
+
if (!value || typeof value !== "object") return void 0;
|
|
2642
|
+
const out = {};
|
|
2643
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
2644
|
+
if (!raw || typeof raw !== "object") continue;
|
|
2645
|
+
const asset = raw;
|
|
2646
|
+
if (typeof asset.href !== "string" || !asset.href) continue;
|
|
2647
|
+
out[key] = {
|
|
2648
|
+
...asset,
|
|
2649
|
+
href: resolveStacAssetHref(asset.href, baseUrl)
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
2653
|
+
}
|
|
2654
|
+
function normalizeLinksField(value, baseUrl) {
|
|
2655
|
+
if (!Array.isArray(value)) return void 0;
|
|
2656
|
+
const links = [];
|
|
2657
|
+
for (const raw of value) {
|
|
2658
|
+
if (!raw || typeof raw !== "object") continue;
|
|
2659
|
+
const link = raw;
|
|
2660
|
+
if (typeof link.href !== "string" || typeof link.rel !== "string") continue;
|
|
2661
|
+
links.push({ ...link, href: resolveStacAssetHref(link.href, baseUrl) });
|
|
2662
|
+
}
|
|
2663
|
+
return links.length > 0 ? links : void 0;
|
|
2664
|
+
}
|
|
2665
|
+
function stacRowToItem(row, baseUrl, opts = {}) {
|
|
2666
|
+
const { wkbParser, wkbColumn = "geom_wkb", geometryColumn = "geometry" } = opts;
|
|
2667
|
+
let geometry = row[geometryColumn];
|
|
2668
|
+
if (!geometry) {
|
|
2669
|
+
const wkb = row[wkbColumn];
|
|
2670
|
+
if (wkb && wkbParser) {
|
|
2671
|
+
const bytes = wkb instanceof Uint8Array ? wkb : toUint8Array(wkb);
|
|
2672
|
+
if (bytes) {
|
|
2673
|
+
try {
|
|
2674
|
+
geometry = wkbParser(bytes) ?? void 0;
|
|
2675
|
+
} catch {
|
|
2676
|
+
geometry = void 0;
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
const bbox = flattenStacBbox(row.bbox) ?? void 0;
|
|
2682
|
+
const assets = normalizeAssetsField(row.assets, baseUrl);
|
|
2683
|
+
const links = normalizeLinksField(row.links, baseUrl);
|
|
2684
|
+
const properties = {};
|
|
2685
|
+
for (const [key, value] of Object.entries(row)) {
|
|
2686
|
+
if (value === null || value === void 0) continue;
|
|
2687
|
+
if (key.startsWith("proj:") || key.startsWith("raster:") || key.startsWith("eo:")) {
|
|
2688
|
+
properties[key] = value;
|
|
2689
|
+
}
|
|
2690
|
+
if (key === "datetime") {
|
|
2691
|
+
properties.datetime = value instanceof Date ? value.toISOString() : String(value);
|
|
2692
|
+
}
|
|
2693
|
+
if (key === "bands") {
|
|
2694
|
+
properties.bands = value;
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
const item = {
|
|
2698
|
+
type: "Feature",
|
|
2699
|
+
stac_version: typeof row.stac_version === "string" ? row.stac_version : "1.0.0",
|
|
2700
|
+
id: typeof row.id === "string" ? row.id : String(row.id ?? ""),
|
|
2701
|
+
properties
|
|
2702
|
+
};
|
|
2703
|
+
if (typeof row.collection === "string") item.collection = row.collection;
|
|
2704
|
+
if (Array.isArray(row.stac_extensions)) {
|
|
2705
|
+
item.stac_extensions = row.stac_extensions;
|
|
2706
|
+
}
|
|
2707
|
+
if (bbox) item.bbox = bbox;
|
|
2708
|
+
if (geometry) item.geometry = geometry;
|
|
2709
|
+
if (assets) item.assets = assets;
|
|
2710
|
+
if (links) item.links = links;
|
|
2711
|
+
return item;
|
|
2712
|
+
}
|
|
2713
|
+
function toUint8Array(value) {
|
|
2714
|
+
if (value instanceof Uint8Array) return value;
|
|
2715
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
2716
|
+
if (ArrayBuffer.isView(value)) {
|
|
2717
|
+
const view = value;
|
|
2718
|
+
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
2719
|
+
}
|
|
2720
|
+
if (Array.isArray(value)) return new Uint8Array(value);
|
|
2721
|
+
return null;
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2519
2724
|
// ../../src/lib/utils/storage-url.ts
|
|
2520
2725
|
function buildSchemeMap() {
|
|
2521
2726
|
const map = {};
|
|
@@ -2529,6 +2734,32 @@ function buildSchemeMap() {
|
|
|
2529
2734
|
return map;
|
|
2530
2735
|
}
|
|
2531
2736
|
var SCHEME_MAP = buildSchemeMap();
|
|
2737
|
+
var AWS_VHOST_RE = /^(.+)\.s3[.-]([a-z0-9-]+)\.amazonaws\.com$/;
|
|
2738
|
+
var AWS_PATH_RE = /^s3[.-]([a-z0-9-]+)\.amazonaws\.com$/;
|
|
2739
|
+
var AWS_GLOBAL_HOST = "s3.amazonaws.com";
|
|
2740
|
+
var R2_RE = /^([a-z0-9]+)\.r2\.cloudflarestorage\.com$/;
|
|
2741
|
+
var GCS_GLOBAL_HOST = "storage.googleapis.com";
|
|
2742
|
+
var GCS_VHOST_RE = /^(.+)\.storage\.googleapis\.com$/;
|
|
2743
|
+
var DO_VHOST_RE = /^(.+)\.([a-z0-9-]+)\.digitaloceanspaces\.com$/;
|
|
2744
|
+
var DO_PATH_RE = /^([a-z0-9-]+)\.digitaloceanspaces\.com$/;
|
|
2745
|
+
var WASABI_RE = /^s3\.([a-z0-9-]+)\.wasabisys\.com$/;
|
|
2746
|
+
var B2_S3_RE = /^(.+)\.s3\.([a-z0-9-]+)\.backblazeb2\.com$/;
|
|
2747
|
+
var B2_NATIVE_RE = /^f[a-z0-9]+\.backblazeb2\.com$/;
|
|
2748
|
+
var OSS_RE = /^(.+)\.(oss-[a-z0-9-]+)\.aliyuncs\.com$/;
|
|
2749
|
+
var COS_RE = /^(.+)\.cos\.([a-z0-9-]+)\.myqcloud\.com$/;
|
|
2750
|
+
var YANDEX_HOST = "storage.yandexcloud.net";
|
|
2751
|
+
var CONTABO_RE = /^([a-z0-9]+)\.contabostorage\.com$/;
|
|
2752
|
+
var HETZNER_RE = /^([a-z0-9]+)\.your-objectstorage\.com$/;
|
|
2753
|
+
var LINODE_VHOST_RE = /^(.+)\.([a-z0-9-]+)\.linodeobjects\.com$/;
|
|
2754
|
+
var LINODE_PATH_RE = /^([a-z0-9-]+)\.linodeobjects\.com$/;
|
|
2755
|
+
var OVH_RE = /^s3\.([a-z0-9-]+)\.io\.cloud\.ovh\.(?:net|us)$/;
|
|
2756
|
+
var AZURE_BLOB_RE = /^([a-z0-9]+)\.blob\.core\.windows\.net$/;
|
|
2757
|
+
var STORJ_GATEWAY_RE = /^gateway\.(?:([a-z0-9]+)\.)?storjshare\.io$/;
|
|
2758
|
+
var STORJ_LINK_RE = /^link\.(?:([a-z0-9]+)\.)?storjshare\.io$/;
|
|
2759
|
+
function isMinioLikeHost(host) {
|
|
2760
|
+
return host.includes("minio") || host === "localhost" || host === "127.0.0.1" || host.startsWith("192.168.") || host.startsWith("10.");
|
|
2761
|
+
}
|
|
2762
|
+
var STAC_API_PATH_RE = /\/(collections|items|catalogs|search)(\/|\?|$)/i;
|
|
2532
2763
|
function defaultResult(defaults) {
|
|
2533
2764
|
return {
|
|
2534
2765
|
bucket: "",
|
|
@@ -2569,7 +2800,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2569
2800
|
const url = new URL(trimmed);
|
|
2570
2801
|
const host = url.hostname;
|
|
2571
2802
|
const pathParts = url.pathname.replace(/^\//, "").split("/").filter(Boolean);
|
|
2572
|
-
const awsVhost = host.match(
|
|
2803
|
+
const awsVhost = host.match(AWS_VHOST_RE);
|
|
2573
2804
|
if (awsVhost) {
|
|
2574
2805
|
return {
|
|
2575
2806
|
bucket: awsVhost[1],
|
|
@@ -2579,7 +2810,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2579
2810
|
prefix: pathParts.join("/")
|
|
2580
2811
|
};
|
|
2581
2812
|
}
|
|
2582
|
-
const awsPath = host.match(
|
|
2813
|
+
const awsPath = host.match(AWS_PATH_RE);
|
|
2583
2814
|
if (awsPath && pathParts.length > 0) {
|
|
2584
2815
|
return {
|
|
2585
2816
|
bucket: pathParts[0],
|
|
@@ -2589,7 +2820,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2589
2820
|
prefix: pathParts.slice(1).join("/")
|
|
2590
2821
|
};
|
|
2591
2822
|
}
|
|
2592
|
-
if (host ===
|
|
2823
|
+
if (host === AWS_GLOBAL_HOST && pathParts.length > 0) {
|
|
2593
2824
|
return {
|
|
2594
2825
|
bucket: pathParts[0],
|
|
2595
2826
|
region: defaults.region || "us-east-1",
|
|
@@ -2598,7 +2829,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2598
2829
|
prefix: pathParts.slice(1).join("/")
|
|
2599
2830
|
};
|
|
2600
2831
|
}
|
|
2601
|
-
const r2Match = host.match(
|
|
2832
|
+
const r2Match = host.match(R2_RE);
|
|
2602
2833
|
if (r2Match && pathParts.length > 0) {
|
|
2603
2834
|
return {
|
|
2604
2835
|
bucket: pathParts[0],
|
|
@@ -2608,7 +2839,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2608
2839
|
prefix: pathParts.slice(1).join("/")
|
|
2609
2840
|
};
|
|
2610
2841
|
}
|
|
2611
|
-
if (host ===
|
|
2842
|
+
if (host === GCS_GLOBAL_HOST && pathParts.length > 0) {
|
|
2612
2843
|
return {
|
|
2613
2844
|
bucket: pathParts[0],
|
|
2614
2845
|
region: defaults.region || "us",
|
|
@@ -2617,7 +2848,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2617
2848
|
prefix: pathParts.slice(1).join("/")
|
|
2618
2849
|
};
|
|
2619
2850
|
}
|
|
2620
|
-
const gcsVhost = host.match(
|
|
2851
|
+
const gcsVhost = host.match(GCS_VHOST_RE);
|
|
2621
2852
|
if (gcsVhost) {
|
|
2622
2853
|
return {
|
|
2623
2854
|
bucket: gcsVhost[1],
|
|
@@ -2627,7 +2858,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2627
2858
|
prefix: pathParts.join("/")
|
|
2628
2859
|
};
|
|
2629
2860
|
}
|
|
2630
|
-
const doVhost = host.match(
|
|
2861
|
+
const doVhost = host.match(DO_VHOST_RE);
|
|
2631
2862
|
if (doVhost) {
|
|
2632
2863
|
return {
|
|
2633
2864
|
bucket: doVhost[1],
|
|
@@ -2637,7 +2868,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2637
2868
|
prefix: pathParts.join("/")
|
|
2638
2869
|
};
|
|
2639
2870
|
}
|
|
2640
|
-
const doPath = host.match(
|
|
2871
|
+
const doPath = host.match(DO_PATH_RE);
|
|
2641
2872
|
if (doPath && pathParts.length > 0) {
|
|
2642
2873
|
return {
|
|
2643
2874
|
bucket: pathParts[0],
|
|
@@ -2647,7 +2878,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2647
2878
|
prefix: pathParts.slice(1).join("/")
|
|
2648
2879
|
};
|
|
2649
2880
|
}
|
|
2650
|
-
const wasabiMatch = host.match(
|
|
2881
|
+
const wasabiMatch = host.match(WASABI_RE);
|
|
2651
2882
|
if (wasabiMatch && pathParts.length > 0) {
|
|
2652
2883
|
return {
|
|
2653
2884
|
bucket: pathParts[0],
|
|
@@ -2657,7 +2888,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2657
2888
|
prefix: pathParts.slice(1).join("/")
|
|
2658
2889
|
};
|
|
2659
2890
|
}
|
|
2660
|
-
const b2S3 = host.match(
|
|
2891
|
+
const b2S3 = host.match(B2_S3_RE);
|
|
2661
2892
|
if (b2S3) {
|
|
2662
2893
|
return {
|
|
2663
2894
|
bucket: b2S3[1],
|
|
@@ -2667,7 +2898,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2667
2898
|
prefix: pathParts.join("/")
|
|
2668
2899
|
};
|
|
2669
2900
|
}
|
|
2670
|
-
const b2Native = host.match(
|
|
2901
|
+
const b2Native = host.match(B2_NATIVE_RE);
|
|
2671
2902
|
if (b2Native && pathParts[0] === "file" && pathParts.length > 1) {
|
|
2672
2903
|
return {
|
|
2673
2904
|
bucket: pathParts[1],
|
|
@@ -2677,7 +2908,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2677
2908
|
prefix: pathParts.slice(2).join("/")
|
|
2678
2909
|
};
|
|
2679
2910
|
}
|
|
2680
|
-
const ossMatch = host.match(
|
|
2911
|
+
const ossMatch = host.match(OSS_RE);
|
|
2681
2912
|
if (ossMatch) {
|
|
2682
2913
|
return {
|
|
2683
2914
|
bucket: ossMatch[1],
|
|
@@ -2687,7 +2918,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2687
2918
|
prefix: pathParts.join("/")
|
|
2688
2919
|
};
|
|
2689
2920
|
}
|
|
2690
|
-
const cosMatch = host.match(
|
|
2921
|
+
const cosMatch = host.match(COS_RE);
|
|
2691
2922
|
if (cosMatch) {
|
|
2692
2923
|
return {
|
|
2693
2924
|
bucket: cosMatch[1],
|
|
@@ -2697,7 +2928,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2697
2928
|
prefix: pathParts.join("/")
|
|
2698
2929
|
};
|
|
2699
2930
|
}
|
|
2700
|
-
if (host ===
|
|
2931
|
+
if (host === YANDEX_HOST && pathParts.length > 0) {
|
|
2701
2932
|
return {
|
|
2702
2933
|
bucket: pathParts[0],
|
|
2703
2934
|
region: defaults.region || "ru-central1",
|
|
@@ -2706,7 +2937,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2706
2937
|
prefix: pathParts.slice(1).join("/")
|
|
2707
2938
|
};
|
|
2708
2939
|
}
|
|
2709
|
-
const contaboMatch = host.match(
|
|
2940
|
+
const contaboMatch = host.match(CONTABO_RE);
|
|
2710
2941
|
if (contaboMatch && pathParts.length > 0) {
|
|
2711
2942
|
return {
|
|
2712
2943
|
bucket: pathParts[0],
|
|
@@ -2716,7 +2947,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2716
2947
|
prefix: pathParts.slice(1).join("/")
|
|
2717
2948
|
};
|
|
2718
2949
|
}
|
|
2719
|
-
const hetznerMatch = host.match(
|
|
2950
|
+
const hetznerMatch = host.match(HETZNER_RE);
|
|
2720
2951
|
if (hetznerMatch && pathParts.length > 0) {
|
|
2721
2952
|
return {
|
|
2722
2953
|
bucket: pathParts[0],
|
|
@@ -2726,7 +2957,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2726
2957
|
prefix: pathParts.slice(1).join("/")
|
|
2727
2958
|
};
|
|
2728
2959
|
}
|
|
2729
|
-
const linodeVhost = host.match(
|
|
2960
|
+
const linodeVhost = host.match(LINODE_VHOST_RE);
|
|
2730
2961
|
if (linodeVhost) {
|
|
2731
2962
|
return {
|
|
2732
2963
|
bucket: linodeVhost[1],
|
|
@@ -2736,7 +2967,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2736
2967
|
prefix: pathParts.join("/")
|
|
2737
2968
|
};
|
|
2738
2969
|
}
|
|
2739
|
-
const linodePath = host.match(
|
|
2970
|
+
const linodePath = host.match(LINODE_PATH_RE);
|
|
2740
2971
|
if (linodePath && pathParts.length > 0) {
|
|
2741
2972
|
return {
|
|
2742
2973
|
bucket: pathParts[0],
|
|
@@ -2746,7 +2977,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2746
2977
|
prefix: pathParts.slice(1).join("/")
|
|
2747
2978
|
};
|
|
2748
2979
|
}
|
|
2749
|
-
const ovhMatch = host.match(
|
|
2980
|
+
const ovhMatch = host.match(OVH_RE);
|
|
2750
2981
|
if (ovhMatch && pathParts.length > 0) {
|
|
2751
2982
|
return {
|
|
2752
2983
|
bucket: pathParts[0],
|
|
@@ -2756,8 +2987,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2756
2987
|
prefix: pathParts.slice(1).join("/")
|
|
2757
2988
|
};
|
|
2758
2989
|
}
|
|
2759
|
-
|
|
2760
|
-
if (isMinioLike && pathParts.length > 0) {
|
|
2990
|
+
if (isMinioLikeHost(host) && pathParts.length > 0) {
|
|
2761
2991
|
return {
|
|
2762
2992
|
bucket: pathParts[0],
|
|
2763
2993
|
region: defaults.region || "us-east-1",
|
|
@@ -2766,7 +2996,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2766
2996
|
prefix: pathParts.slice(1).join("/")
|
|
2767
2997
|
};
|
|
2768
2998
|
}
|
|
2769
|
-
const azureBlob = host.match(
|
|
2999
|
+
const azureBlob = host.match(AZURE_BLOB_RE);
|
|
2770
3000
|
if (azureBlob && pathParts.length > 0) {
|
|
2771
3001
|
return {
|
|
2772
3002
|
bucket: pathParts[0],
|
|
@@ -2776,7 +3006,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2776
3006
|
prefix: pathParts.slice(1).join("/")
|
|
2777
3007
|
};
|
|
2778
3008
|
}
|
|
2779
|
-
const storjGateway = host.match(
|
|
3009
|
+
const storjGateway = host.match(STORJ_GATEWAY_RE);
|
|
2780
3010
|
if (storjGateway && pathParts.length > 0) {
|
|
2781
3011
|
return {
|
|
2782
3012
|
bucket: pathParts[0],
|
|
@@ -2786,7 +3016,7 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2786
3016
|
prefix: pathParts.slice(1).join("/")
|
|
2787
3017
|
};
|
|
2788
3018
|
}
|
|
2789
|
-
const storjLink = host.match(
|
|
3019
|
+
const storjLink = host.match(STORJ_LINK_RE);
|
|
2790
3020
|
if (storjLink && pathParts.length >= 3 && (pathParts[0] === "raw" || pathParts[0] === "s")) {
|
|
2791
3021
|
return {
|
|
2792
3022
|
bucket: pathParts[2],
|
|
@@ -2796,6 +3026,12 @@ function parseStorageUrl(input, defaults = {}) {
|
|
|
2796
3026
|
prefix: pathParts.slice(3).join("/")
|
|
2797
3027
|
};
|
|
2798
3028
|
}
|
|
3029
|
+
if (STAC_API_PATH_RE.test(url.pathname)) {
|
|
3030
|
+
return {
|
|
3031
|
+
...defaultResult(defaults),
|
|
3032
|
+
endpoint: `${url.protocol}//${url.host}`
|
|
3033
|
+
};
|
|
3034
|
+
}
|
|
2799
3035
|
if (pathParts.length > 0) {
|
|
2800
3036
|
const endpoint = `${url.protocol}//${url.host}`;
|
|
2801
3037
|
return {
|
|
@@ -2998,7 +3234,10 @@ var GEO_TYPE_KEYWORDS = [
|
|
|
2998
3234
|
"geometrycollection",
|
|
2999
3235
|
"sdo_geometry"
|
|
3000
3236
|
];
|
|
3001
|
-
var GEO_NAME_HINTS = ["geom", "geometry", "
|
|
3237
|
+
var GEO_NAME_HINTS = ["geom", "geometry", "wkb", "wkt", "shape", "spatial", "geo"];
|
|
3238
|
+
function tokenizeColumnName(name) {
|
|
3239
|
+
return name.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([a-z])([0-9])/g, "$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
3240
|
+
}
|
|
3002
3241
|
var GEOJSON_TYPES = [
|
|
3003
3242
|
"Point",
|
|
3004
3243
|
"LineString",
|
|
@@ -3028,14 +3267,14 @@ function findGeoColumn(schema) {
|
|
|
3028
3267
|
if (GEO_NAMES.includes(f.name.toLowerCase())) return f.name;
|
|
3029
3268
|
}
|
|
3030
3269
|
for (const f of schema) {
|
|
3031
|
-
const
|
|
3270
|
+
const tokens = tokenizeColumnName(f.name);
|
|
3032
3271
|
const t = f.type.toLowerCase();
|
|
3033
3272
|
const isBinary = t.includes("blob") || t.includes("binary") || t.includes("bytea");
|
|
3034
|
-
if (isBinary &&
|
|
3273
|
+
if (isBinary && tokens.some((tok) => GEO_NAME_HINTS.includes(tok))) return f.name;
|
|
3035
3274
|
}
|
|
3036
3275
|
for (const f of schema) {
|
|
3037
|
-
const
|
|
3038
|
-
if (
|
|
3276
|
+
const tokens = tokenizeColumnName(f.name);
|
|
3277
|
+
if (tokens.some((tok) => GEO_NAME_HINTS.includes(tok))) return f.name;
|
|
3039
3278
|
}
|
|
3040
3279
|
return null;
|
|
3041
3280
|
}
|
|
@@ -3092,6 +3331,6 @@ function isWKT(value) {
|
|
|
3092
3331
|
return WKT_TYPES.some((t) => s.startsWith(t) || s.startsWith(`MULTI${t}`));
|
|
3093
3332
|
}
|
|
3094
3333
|
|
|
3095
|
-
export { COPY_FEEDBACK_MS, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, LAYER_HUE_MULTIPLIER, MAX_QUERY_HISTORY_ENTRIES, PROVIDERS, PROVIDER_IDS, QueryCancelledError, SF_LABELS, SQL_PREVIEW_LENGTH, STORAGE_KEYS, UrlAdapter, VIEWER_DIR_EXTENSIONS, WGS84_CODES, buildDataTypeLabel, buildDuckDbSource, buildEndpointFromTemplate, buildGeoArrowTables, buildProviderBaseUrl, clampBounds, classifyType, describeParseResult, escapeCsvField, extractBounds, extractEpsgFromGeoMeta, extractGeometryTypes, findGeoColumn, findGeoColumnFromRows, formatDate, formatFileSize, formatValue, generateHexDump, getDuckDbReadFn, getFileExtension, getFileTypeInfo, getMimeType, getNativeScheme, getProvider, getViewerKind, handleLoadError, interpolateTemplates, isCloudNativeFormat, isGcsProvider, isQueryable, jsonReplacerBigInt, loadFromStorage, looksLikeUrl, markSqlBlocks, normalizeGeomType, parseMarkdownDocument, parseStorageUrl, parseWKB, persistToStorage, readParquetMetadata, resolveCloudUrl, safeClamp, safeDecodeURIComponent, serializeToCsv, serializeToJson, sortFileEntries, toBinary, toggleSortField, typeBadgeClass, typeColor, typeLabel };
|
|
3334
|
+
export { COPY_FEEDBACK_MS, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, LAYER_HUE_MULTIPLIER, MAX_QUERY_HISTORY_ENTRIES, PROVIDERS, PROVIDER_IDS, QueryCancelledError, SF_LABELS, SQL_PREVIEW_LENGTH, STAC_GEOPARQUET_REQUIRED_COLUMNS, STORAGE_KEYS, UrlAdapter, VIEWER_DIR_EXTENSIONS, WGS84_CODES, buildDataTypeLabel, buildDuckDbSource, buildEndpointFromTemplate, buildGeoArrowTables, buildProviderBaseUrl, clampBounds, classifyType, describeParseResult, escapeCsvField, exportToCsv, exportToJson, extractBounds, extractEpsgFromGeoMeta, extractGeometryTypes, findGeoColumn, findGeoColumnFromRows, flattenStacBbox, formatDate, formatFileSize, formatValue, generateHexDump, getAccessMode, getDuckDbReadFn, getFileExtension, getFileTypeInfo, getMimeType, getNativeScheme, getProvider, getViewerKind, handleLoadError, interpolateTemplates, isCloudNativeFormat, isGcsProvider, isPubliclyStreamable, isQueryable, isStacGeoparquetSchema, jsonReplacerBigInt, loadFromStorage, looksLikeUrl, markSqlBlocks, normalizeGeomType, parseMarkdownDocument, parseStorageUrl, parseWKB, persistToStorage, pickStacPrimaryAsset, readParquetMetadata, resolveCloudUrl, resolveProviderEndpoint, resolveStacAssetHref, safeClamp, safeDecodeURIComponent, serializeToCsv, serializeToJson, sortFileEntries, stacRowToItem, toBinary, toggleSortField, typeBadgeClass, typeColor, typeLabel };
|
|
3096
3335
|
//# sourceMappingURL=index.js.map
|
|
3097
3336
|
//# sourceMappingURL=index.js.map
|