@walkthru-earth/objex-utils 1.2.1 → 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/dist/index.js CHANGED
@@ -2475,6 +2475,15 @@ async function readParquetMetadata(url) {
2475
2475
  name: col.name,
2476
2476
  type: mapParquetType(col)
2477
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
+ }
2478
2487
  let geo = null;
2479
2488
  let legacyGeoParquet = false;
2480
2489
  const geoKv = metadata.key_value_metadata?.find((kv) => kv.key === "geo");
@@ -2516,7 +2525,26 @@ async function readParquetMetadata(url) {
2516
2525
  compression = [...codecs].join(", ");
2517
2526
  }
2518
2527
  }
2519
- return { rowCount, schema, geo, legacyGeoParquet, createdBy, numRowGroups, compression };
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;
2520
2548
  }
2521
2549
  function extractEpsgFromGeoMeta(geo) {
2522
2550
  const primaryCol = geo.columns[geo.primaryColumn];
@@ -2555,6 +2583,144 @@ function extractBounds(geo) {
2555
2583
  return [primaryCol.bbox[0], primaryCol.bbox[1], primaryCol.bbox[2], primaryCol.bbox[3]];
2556
2584
  }
2557
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
+
2558
2724
  // ../../src/lib/utils/storage-url.ts
2559
2725
  function buildSchemeMap() {
2560
2726
  const map = {};
@@ -2568,6 +2734,32 @@ function buildSchemeMap() {
2568
2734
  return map;
2569
2735
  }
2570
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;
2571
2763
  function defaultResult(defaults) {
2572
2764
  return {
2573
2765
  bucket: "",
@@ -2608,7 +2800,7 @@ function parseStorageUrl(input, defaults = {}) {
2608
2800
  const url = new URL(trimmed);
2609
2801
  const host = url.hostname;
2610
2802
  const pathParts = url.pathname.replace(/^\//, "").split("/").filter(Boolean);
2611
- const awsVhost = host.match(/^(.+)\.s3[.-]([a-z0-9-]+)\.amazonaws\.com$/);
2803
+ const awsVhost = host.match(AWS_VHOST_RE);
2612
2804
  if (awsVhost) {
2613
2805
  return {
2614
2806
  bucket: awsVhost[1],
@@ -2618,7 +2810,7 @@ function parseStorageUrl(input, defaults = {}) {
2618
2810
  prefix: pathParts.join("/")
2619
2811
  };
2620
2812
  }
2621
- const awsPath = host.match(/^s3[.-]([a-z0-9-]+)\.amazonaws\.com$/);
2813
+ const awsPath = host.match(AWS_PATH_RE);
2622
2814
  if (awsPath && pathParts.length > 0) {
2623
2815
  return {
2624
2816
  bucket: pathParts[0],
@@ -2628,7 +2820,7 @@ function parseStorageUrl(input, defaults = {}) {
2628
2820
  prefix: pathParts.slice(1).join("/")
2629
2821
  };
2630
2822
  }
2631
- if (host === "s3.amazonaws.com" && pathParts.length > 0) {
2823
+ if (host === AWS_GLOBAL_HOST && pathParts.length > 0) {
2632
2824
  return {
2633
2825
  bucket: pathParts[0],
2634
2826
  region: defaults.region || "us-east-1",
@@ -2637,7 +2829,7 @@ function parseStorageUrl(input, defaults = {}) {
2637
2829
  prefix: pathParts.slice(1).join("/")
2638
2830
  };
2639
2831
  }
2640
- const r2Match = host.match(/^([a-z0-9]+)\.r2\.cloudflarestorage\.com$/);
2832
+ const r2Match = host.match(R2_RE);
2641
2833
  if (r2Match && pathParts.length > 0) {
2642
2834
  return {
2643
2835
  bucket: pathParts[0],
@@ -2647,7 +2839,7 @@ function parseStorageUrl(input, defaults = {}) {
2647
2839
  prefix: pathParts.slice(1).join("/")
2648
2840
  };
2649
2841
  }
2650
- if (host === "storage.googleapis.com" && pathParts.length > 0) {
2842
+ if (host === GCS_GLOBAL_HOST && pathParts.length > 0) {
2651
2843
  return {
2652
2844
  bucket: pathParts[0],
2653
2845
  region: defaults.region || "us",
@@ -2656,7 +2848,7 @@ function parseStorageUrl(input, defaults = {}) {
2656
2848
  prefix: pathParts.slice(1).join("/")
2657
2849
  };
2658
2850
  }
2659
- const gcsVhost = host.match(/^(.+)\.storage\.googleapis\.com$/);
2851
+ const gcsVhost = host.match(GCS_VHOST_RE);
2660
2852
  if (gcsVhost) {
2661
2853
  return {
2662
2854
  bucket: gcsVhost[1],
@@ -2666,7 +2858,7 @@ function parseStorageUrl(input, defaults = {}) {
2666
2858
  prefix: pathParts.join("/")
2667
2859
  };
2668
2860
  }
2669
- const doVhost = host.match(/^(.+)\.([a-z0-9-]+)\.digitaloceanspaces\.com$/);
2861
+ const doVhost = host.match(DO_VHOST_RE);
2670
2862
  if (doVhost) {
2671
2863
  return {
2672
2864
  bucket: doVhost[1],
@@ -2676,7 +2868,7 @@ function parseStorageUrl(input, defaults = {}) {
2676
2868
  prefix: pathParts.join("/")
2677
2869
  };
2678
2870
  }
2679
- const doPath = host.match(/^([a-z0-9-]+)\.digitaloceanspaces\.com$/);
2871
+ const doPath = host.match(DO_PATH_RE);
2680
2872
  if (doPath && pathParts.length > 0) {
2681
2873
  return {
2682
2874
  bucket: pathParts[0],
@@ -2686,7 +2878,7 @@ function parseStorageUrl(input, defaults = {}) {
2686
2878
  prefix: pathParts.slice(1).join("/")
2687
2879
  };
2688
2880
  }
2689
- const wasabiMatch = host.match(/^s3\.([a-z0-9-]+)\.wasabisys\.com$/);
2881
+ const wasabiMatch = host.match(WASABI_RE);
2690
2882
  if (wasabiMatch && pathParts.length > 0) {
2691
2883
  return {
2692
2884
  bucket: pathParts[0],
@@ -2696,7 +2888,7 @@ function parseStorageUrl(input, defaults = {}) {
2696
2888
  prefix: pathParts.slice(1).join("/")
2697
2889
  };
2698
2890
  }
2699
- const b2S3 = host.match(/^(.+)\.s3\.([a-z0-9-]+)\.backblazeb2\.com$/);
2891
+ const b2S3 = host.match(B2_S3_RE);
2700
2892
  if (b2S3) {
2701
2893
  return {
2702
2894
  bucket: b2S3[1],
@@ -2706,7 +2898,7 @@ function parseStorageUrl(input, defaults = {}) {
2706
2898
  prefix: pathParts.join("/")
2707
2899
  };
2708
2900
  }
2709
- const b2Native = host.match(/^f[a-z0-9]+\.backblazeb2\.com$/);
2901
+ const b2Native = host.match(B2_NATIVE_RE);
2710
2902
  if (b2Native && pathParts[0] === "file" && pathParts.length > 1) {
2711
2903
  return {
2712
2904
  bucket: pathParts[1],
@@ -2716,7 +2908,7 @@ function parseStorageUrl(input, defaults = {}) {
2716
2908
  prefix: pathParts.slice(2).join("/")
2717
2909
  };
2718
2910
  }
2719
- const ossMatch = host.match(/^(.+)\.(oss-[a-z0-9-]+)\.aliyuncs\.com$/);
2911
+ const ossMatch = host.match(OSS_RE);
2720
2912
  if (ossMatch) {
2721
2913
  return {
2722
2914
  bucket: ossMatch[1],
@@ -2726,7 +2918,7 @@ function parseStorageUrl(input, defaults = {}) {
2726
2918
  prefix: pathParts.join("/")
2727
2919
  };
2728
2920
  }
2729
- const cosMatch = host.match(/^(.+)\.cos\.([a-z0-9-]+)\.myqcloud\.com$/);
2921
+ const cosMatch = host.match(COS_RE);
2730
2922
  if (cosMatch) {
2731
2923
  return {
2732
2924
  bucket: cosMatch[1],
@@ -2736,7 +2928,7 @@ function parseStorageUrl(input, defaults = {}) {
2736
2928
  prefix: pathParts.join("/")
2737
2929
  };
2738
2930
  }
2739
- if (host === "storage.yandexcloud.net" && pathParts.length > 0) {
2931
+ if (host === YANDEX_HOST && pathParts.length > 0) {
2740
2932
  return {
2741
2933
  bucket: pathParts[0],
2742
2934
  region: defaults.region || "ru-central1",
@@ -2745,7 +2937,7 @@ function parseStorageUrl(input, defaults = {}) {
2745
2937
  prefix: pathParts.slice(1).join("/")
2746
2938
  };
2747
2939
  }
2748
- const contaboMatch = host.match(/^([a-z0-9]+)\.contabostorage\.com$/);
2940
+ const contaboMatch = host.match(CONTABO_RE);
2749
2941
  if (contaboMatch && pathParts.length > 0) {
2750
2942
  return {
2751
2943
  bucket: pathParts[0],
@@ -2755,7 +2947,7 @@ function parseStorageUrl(input, defaults = {}) {
2755
2947
  prefix: pathParts.slice(1).join("/")
2756
2948
  };
2757
2949
  }
2758
- const hetznerMatch = host.match(/^([a-z0-9]+)\.your-objectstorage\.com$/);
2950
+ const hetznerMatch = host.match(HETZNER_RE);
2759
2951
  if (hetznerMatch && pathParts.length > 0) {
2760
2952
  return {
2761
2953
  bucket: pathParts[0],
@@ -2765,7 +2957,7 @@ function parseStorageUrl(input, defaults = {}) {
2765
2957
  prefix: pathParts.slice(1).join("/")
2766
2958
  };
2767
2959
  }
2768
- const linodeVhost = host.match(/^(.+)\.([a-z0-9-]+)\.linodeobjects\.com$/);
2960
+ const linodeVhost = host.match(LINODE_VHOST_RE);
2769
2961
  if (linodeVhost) {
2770
2962
  return {
2771
2963
  bucket: linodeVhost[1],
@@ -2775,7 +2967,7 @@ function parseStorageUrl(input, defaults = {}) {
2775
2967
  prefix: pathParts.join("/")
2776
2968
  };
2777
2969
  }
2778
- const linodePath = host.match(/^([a-z0-9-]+)\.linodeobjects\.com$/);
2970
+ const linodePath = host.match(LINODE_PATH_RE);
2779
2971
  if (linodePath && pathParts.length > 0) {
2780
2972
  return {
2781
2973
  bucket: pathParts[0],
@@ -2785,7 +2977,7 @@ function parseStorageUrl(input, defaults = {}) {
2785
2977
  prefix: pathParts.slice(1).join("/")
2786
2978
  };
2787
2979
  }
2788
- const ovhMatch = host.match(/^s3\.([a-z0-9-]+)\.io\.cloud\.ovh\.(?:net|us)$/);
2980
+ const ovhMatch = host.match(OVH_RE);
2789
2981
  if (ovhMatch && pathParts.length > 0) {
2790
2982
  return {
2791
2983
  bucket: pathParts[0],
@@ -2795,8 +2987,7 @@ function parseStorageUrl(input, defaults = {}) {
2795
2987
  prefix: pathParts.slice(1).join("/")
2796
2988
  };
2797
2989
  }
2798
- const isMinioLike = host.includes("minio") || host === "localhost" || host === "127.0.0.1" || host.startsWith("192.168.") || host.startsWith("10.");
2799
- if (isMinioLike && pathParts.length > 0) {
2990
+ if (isMinioLikeHost(host) && pathParts.length > 0) {
2800
2991
  return {
2801
2992
  bucket: pathParts[0],
2802
2993
  region: defaults.region || "us-east-1",
@@ -2805,7 +2996,7 @@ function parseStorageUrl(input, defaults = {}) {
2805
2996
  prefix: pathParts.slice(1).join("/")
2806
2997
  };
2807
2998
  }
2808
- const azureBlob = host.match(/^([a-z0-9]+)\.blob\.core\.windows\.net$/);
2999
+ const azureBlob = host.match(AZURE_BLOB_RE);
2809
3000
  if (azureBlob && pathParts.length > 0) {
2810
3001
  return {
2811
3002
  bucket: pathParts[0],
@@ -2815,7 +3006,7 @@ function parseStorageUrl(input, defaults = {}) {
2815
3006
  prefix: pathParts.slice(1).join("/")
2816
3007
  };
2817
3008
  }
2818
- const storjGateway = host.match(/^gateway\.(?:([a-z0-9]+)\.)?storjshare\.io$/);
3009
+ const storjGateway = host.match(STORJ_GATEWAY_RE);
2819
3010
  if (storjGateway && pathParts.length > 0) {
2820
3011
  return {
2821
3012
  bucket: pathParts[0],
@@ -2825,7 +3016,7 @@ function parseStorageUrl(input, defaults = {}) {
2825
3016
  prefix: pathParts.slice(1).join("/")
2826
3017
  };
2827
3018
  }
2828
- const storjLink = host.match(/^link\.(?:([a-z0-9]+)\.)?storjshare\.io$/);
3019
+ const storjLink = host.match(STORJ_LINK_RE);
2829
3020
  if (storjLink && pathParts.length >= 3 && (pathParts[0] === "raw" || pathParts[0] === "s")) {
2830
3021
  return {
2831
3022
  bucket: pathParts[2],
@@ -2835,6 +3026,12 @@ function parseStorageUrl(input, defaults = {}) {
2835
3026
  prefix: pathParts.slice(3).join("/")
2836
3027
  };
2837
3028
  }
3029
+ if (STAC_API_PATH_RE.test(url.pathname)) {
3030
+ return {
3031
+ ...defaultResult(defaults),
3032
+ endpoint: `${url.protocol}//${url.host}`
3033
+ };
3034
+ }
2838
3035
  if (pathParts.length > 0) {
2839
3036
  const endpoint = `${url.protocol}//${url.host}`;
2840
3037
  return {
@@ -3134,6 +3331,6 @@ function isWKT(value) {
3134
3331
  return WKT_TYPES.some((t) => s.startsWith(t) || s.startsWith(`MULTI${t}`));
3135
3332
  }
3136
3333
 
3137
- 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, exportToCsv, exportToJson, extractBounds, extractEpsgFromGeoMeta, extractGeometryTypes, findGeoColumn, findGeoColumnFromRows, formatDate, formatFileSize, formatValue, generateHexDump, getAccessMode, getDuckDbReadFn, getFileExtension, getFileTypeInfo, getMimeType, getNativeScheme, getProvider, getViewerKind, handleLoadError, interpolateTemplates, isCloudNativeFormat, isGcsProvider, isPubliclyStreamable, isQueryable, jsonReplacerBigInt, loadFromStorage, looksLikeUrl, markSqlBlocks, normalizeGeomType, parseMarkdownDocument, parseStorageUrl, parseWKB, persistToStorage, readParquetMetadata, resolveCloudUrl, resolveProviderEndpoint, 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 };
3138
3335
  //# sourceMappingURL=index.js.map
3139
3336
  //# sourceMappingURL=index.js.map