@walkthru-earth/objex-utils 1.1.0 → 1.2.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 CHANGED
@@ -3,51 +3,50 @@
3
3
  [![npm](https://img.shields.io/npm/v/@walkthru-earth/objex-utils?color=cb3837)](https://www.npmjs.com/package/@walkthru-earth/objex-utils)
4
4
  [![License: CC BY 4.0](https://img.shields.io/badge/license-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/)
5
5
 
6
- Pure TypeScript utilities extracted from [objex](https://github.com/walkthru-earth/objex) zero Svelte dependency. Works with any JS framework or Node.js.
6
+ Pure TypeScript utilities extracted from [objex](https://github.com/walkthru-earth/objex). Zero Svelte dependency. Works with any JS framework or Node 18+.
7
+
8
+ Built for high-performance geospatial pipelines: WKB parsing, GeoArrow table construction, GeoParquet footer reading via range requests, cloud URL parsing, and a 200+ extension file-type registry.
7
9
 
8
10
  ## Install
9
11
 
10
12
  ```bash
11
13
  pnpm add @walkthru-earth/objex-utils
14
+ # or
15
+ npm install @walkthru-earth/objex-utils
12
16
  ```
13
17
 
14
- ## Usage
18
+ ## At a glance
15
19
 
16
20
  ```ts
17
21
  import {
18
- // WKB / Geometry
22
+ // WKB / GeoArrow
19
23
  parseWKB,
20
24
  findGeoColumn,
21
25
  buildGeoArrowTables,
22
26
 
23
- // Storage URLs
24
- parseStorageUrl,
25
- looksLikeUrl,
26
-
27
- // Parquet metadata
27
+ // Parquet metadata (hyparquet, range requests)
28
28
  readParquetMetadata,
29
29
  extractEpsgFromGeoMeta,
30
30
  extractBounds,
31
31
 
32
- // File type registry
32
+ // Storage URLs
33
+ parseStorageUrl,
34
+ resolveCloudUrl,
35
+ looksLikeUrl,
36
+
37
+ // File-type registry
33
38
  getFileTypeInfo,
34
39
  getViewerKind,
35
- getMimeType,
40
+ getDuckDbReadFn,
36
41
  isQueryable,
37
42
 
38
- // Formatting
43
+ // Formatting / classification / hex / CSV / JSON
39
44
  formatFileSize,
40
- formatDate,
41
45
  formatValue,
42
- jsonReplacerBigInt,
43
-
44
- // Column types
45
46
  classifyType,
46
- typeColor,
47
- typeLabel,
48
-
49
- // Hex dump
50
47
  generateHexDump,
48
+ serializeToCsv,
49
+ serializeToJson,
51
50
 
52
51
  // Error handling
53
52
  handleLoadError,
@@ -59,33 +58,41 @@ import {
59
58
  } from '@walkthru-earth/objex-utils';
60
59
  ```
61
60
 
62
- ## Exports
61
+ ## Documentation
62
+
63
+ Full per-module developer reference lives in [`docs/`](./docs/README.md). Each page lists the exact TypeScript signature, parameter semantics, return shape, peer-dependency requirements, and non-obvious behavior.
64
+
65
+ | Page | Covers |
66
+ |------|--------|
67
+ | [`docs/geometry.md`](./docs/geometry.md) | WKB parser, GeoArrow builder, geometry-column detection |
68
+ | [`docs/cog.md`](./docs/cog.md) | Cloud-Optimized GeoTIFF pipeline helpers, band configs, color ramps |
69
+ | [`docs/parquet-metadata.md`](./docs/parquet-metadata.md) | `readParquetMetadata` + CRS / bounds / geometry-type extractors |
70
+ | [`docs/storage.md`](./docs/storage.md) | URL parsing, provider registry, `StorageAdapter`, `UrlAdapter` |
71
+ | [`docs/query-engine.md`](./docs/query-engine.md) | `QueryEngine` interface + handle / result types |
72
+ | [`docs/file-types.md`](./docs/file-types.md) | File-type registry: `getFileTypeInfo`, `getViewerKind`, `getDuckDbReadFn`, … |
73
+ | [`docs/formatting.md`](./docs/formatting.md) | Display formatters, column-type classification, hex dump, CSV/JSON export |
74
+ | [`docs/file-sort.md`](./docs/file-sort.md) | `sortFileEntries`, `toggleSortField` |
75
+ | [`docs/markdown-sql.md`](./docs/markdown-sql.md) | Markdown + SQL block parsing (Evidence-compatible) |
76
+ | [`docs/local-storage.md`](./docs/local-storage.md) | SSR-safe `loadFromStorage` / `persistToStorage` |
77
+ | [`docs/errors.md`](./docs/errors.md) | `handleLoadError` |
78
+ | [`docs/types-constants.md`](./docs/types-constants.md) | `Connection`, `Tab`, `FileEntry`, `WriteResult`, `Theme`, shared constants |
63
79
 
64
- | Export | Description |
65
- |--------|-------------|
66
- | `parseWKB()` | Parse WKB binary into coordinates with geometry type classification |
67
- | `findGeoColumn()` | 5-priority heuristic to detect geometry columns in tabular data |
68
- | `buildGeoArrowTables()` | Convert WKB arrays to GeoArrow tables for deck.gl rendering |
69
- | `parseStorageUrl()` | Parse S3/GCS/Azure/R2 URLs into provider, bucket, key |
70
- | `readParquetMetadata()` | Read Parquet file metadata via HTTP range requests (hyparquet) |
71
- | `getFileTypeInfo()` | Map file extensions to viewer kind, category, icon, and MIME type |
72
- | `formatFileSize()` | Human-readable file sizes (1024-based: KB, MB, GB) |
73
- | `formatValue()` | Format any value for display (handles BigInt, Date, objects, null) |
74
- | `generateHexDump()` | Generate hex dump rows from binary data |
75
- | `classifyType()` | Classify SQL/Arrow column types into categories |
76
- | `handleLoadError()` | Normalize errors, silently skip AbortError |
77
- | `WGS84_CODES` | Set of EPSG codes considered WGS84 (4326, 4979) |
80
+ ## Optional peer dependencies
78
81
 
79
- ## Optional Peer Dependencies
82
+ Heavy dependencies are **optional** peers. Install only what you use.
80
83
 
81
- Heavy dependencies are optional only install what you use:
84
+ | Peer | Required by |
85
+ |------|-------------|
86
+ | `apache-arrow >=14` | `buildGeoArrowTables` |
87
+ | `hyparquet >=1.25` | `readParquetMetadata` and friends |
88
+ | `hyparquet-compressors >=1.1` | SNAPPY / ZSTD / GZIP / LZ4 / BROTLI support in `readParquetMetadata` |
89
+ | `yaml >=2` | `parseMarkdownDocument` (lazy-loaded — only when frontmatter is present) |
82
90
 
83
- - `apache-arrow` required for `buildGeoArrowTables()`
84
- - `hyparquet` + `hyparquet-compressors` — required for `readParquetMetadata()`
91
+ As of v1.2 the `yaml` dependency is imported dynamically inside `parseMarkdownDocument`. Consumers who never call that function do not need `yaml` at all. Before v1.2 the bundle failed to load without `yaml` even for unrelated imports.
85
92
 
86
93
  ## Related
87
94
 
88
- - [`@walkthru-earth/objex`](https://www.npmjs.com/package/@walkthru-earth/objex) — Full Svelte 5 component library with viewers, stores, and query engine
95
+ - [`@walkthru-earth/objex`](https://www.npmjs.com/package/@walkthru-earth/objex) — Full Svelte 5 component library with viewers, stores, and query engine.
89
96
 
90
97
  ## License
91
98
 
package/dist/index.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ require('@developmentseed/epsg/all');
4
+ require('@developmentseed/epsg/all.csv.gz?url');
5
+ require('@developmentseed/geotiff');
6
+ require('@developmentseed/proj');
7
+ require('proj4');
3
8
  var apacheArrow = require('apache-arrow');
4
- var YAML = require('yaml');
5
-
6
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
-
8
- var YAML__default = /*#__PURE__*/_interopDefault(YAML);
9
9
 
10
10
  // ../../src/lib/constants.ts
11
11
  var STORAGE_KEYS = {
@@ -14,7 +14,7 @@ var STORAGE_KEYS = {
14
14
  QUERY_HISTORY: "obstore-explore-query-history"
15
15
  };
16
16
  var WGS84_CODES = /* @__PURE__ */ new Set([4326, 4979]);
17
- var DEFAULT_TARGET_CRS = "EPSG:4326";
17
+ var DEFAULT_TARGET_CRS = "OGC:CRS84";
18
18
  var DUCKDB_INIT_TIMEOUT_MS = 3e4;
19
19
  var MAX_QUERY_HISTORY_ENTRIES = 200;
20
20
  var SQL_PREVIEW_LENGTH = 120;
@@ -894,6 +894,16 @@ var EXTENSIONS = {
894
894
  duckdbReadFn: null,
895
895
  mimeType: "application/octet-stream"
896
896
  },
897
+ ".ducklake": {
898
+ icon: "Database",
899
+ color: "text-teal-600 dark:text-teal-400",
900
+ label: "DuckLake",
901
+ category: "database",
902
+ viewer: "database",
903
+ queryable: true,
904
+ duckdbReadFn: null,
905
+ mimeType: "application/octet-stream"
906
+ },
897
907
  ".sqlite": {
898
908
  icon: "Database",
899
909
  color: "text-sky-600 dark:text-sky-400",
@@ -1041,7 +1051,7 @@ function buildDuckDbSource(pathOrExt, url) {
1041
1051
  const readFn = EXTENSIONS[ext]?.duckdbReadFn ?? "read_parquet";
1042
1052
  return `${readFn}('${url}')`;
1043
1053
  }
1044
- var CLOUD_NATIVE_EXTS = /* @__PURE__ */ new Set([".parquet", ".geoparquet", ".gpq", ".gparquet"]);
1054
+ var CLOUD_NATIVE_EXTS = /* @__PURE__ */ new Set([".parquet", ".geoparquet", ".gpq", ".gparquet", ".ducklake"]);
1045
1055
  function isCloudNativeFormat(pathOrExt) {
1046
1056
  const ext = pathOrExt.includes(".") ? `.${pathOrExt.split(".").pop().toLowerCase()}` : "";
1047
1057
  return CLOUD_NATIVE_EXTS.has(ext);
@@ -1438,6 +1448,28 @@ function resolveCloudUrl(url) {
1438
1448
  }
1439
1449
  return url;
1440
1450
  }
1451
+ var SF_LABELS = {
1452
+ 1: "uint",
1453
+ 2: "int",
1454
+ 3: "float",
1455
+ 4: "void",
1456
+ 5: "complex int",
1457
+ 6: "complex float"
1458
+ };
1459
+ function safeClamp(v, lo, hi, fallback) {
1460
+ return Number.isFinite(v) ? Math.max(lo, Math.min(hi, v)) : fallback;
1461
+ }
1462
+ function clampBounds(b) {
1463
+ return {
1464
+ west: safeClamp(b.west, -180, 180, -180),
1465
+ south: safeClamp(b.south, -85.051129, 85.051129, -85.051129),
1466
+ east: safeClamp(b.east, -180, 180, 180),
1467
+ north: safeClamp(b.north, -85.051129, 85.051129, 85.051129)
1468
+ };
1469
+ }
1470
+ function buildDataTypeLabel(sampleFormat, bitsPerSample) {
1471
+ return `${SF_LABELS[sampleFormat] ?? `sf${sampleFormat}`}${bitsPerSample ?? ""}`;
1472
+ }
1441
1473
 
1442
1474
  // ../../src/lib/utils/column-types.ts
1443
1475
  var NUMBER_TYPES = [
@@ -2289,13 +2321,16 @@ function persistToStorage(key, value) {
2289
2321
  } catch {
2290
2322
  }
2291
2323
  }
2292
- function parseMarkdownDocument(markdown) {
2324
+
2325
+ // ../../src/lib/utils/markdown-sql.ts
2326
+ async function parseMarkdownDocument(markdown) {
2293
2327
  let frontmatter = {};
2294
2328
  let content = markdown;
2295
2329
  const fmMatch = markdown.match(/^---\n([\s\S]*?)\n---\n/);
2296
2330
  if (fmMatch) {
2297
2331
  try {
2298
- frontmatter = YAML__default.default.parse(fmMatch[1]) || {};
2332
+ const { default: YAML } = await import('yaml');
2333
+ frontmatter = YAML.parse(fmMatch[1]) || {};
2299
2334
  } catch {
2300
2335
  }
2301
2336
  content = markdown.slice(fmMatch[0].length);
@@ -3067,15 +3102,18 @@ exports.MAX_QUERY_HISTORY_ENTRIES = MAX_QUERY_HISTORY_ENTRIES;
3067
3102
  exports.PROVIDERS = PROVIDERS;
3068
3103
  exports.PROVIDER_IDS = PROVIDER_IDS;
3069
3104
  exports.QueryCancelledError = QueryCancelledError;
3105
+ exports.SF_LABELS = SF_LABELS;
3070
3106
  exports.SQL_PREVIEW_LENGTH = SQL_PREVIEW_LENGTH;
3071
3107
  exports.STORAGE_KEYS = STORAGE_KEYS;
3072
3108
  exports.UrlAdapter = UrlAdapter;
3073
3109
  exports.VIEWER_DIR_EXTENSIONS = VIEWER_DIR_EXTENSIONS;
3074
3110
  exports.WGS84_CODES = WGS84_CODES;
3111
+ exports.buildDataTypeLabel = buildDataTypeLabel;
3075
3112
  exports.buildDuckDbSource = buildDuckDbSource;
3076
3113
  exports.buildEndpointFromTemplate = buildEndpointFromTemplate;
3077
3114
  exports.buildGeoArrowTables = buildGeoArrowTables;
3078
3115
  exports.buildProviderBaseUrl = buildProviderBaseUrl;
3116
+ exports.clampBounds = clampBounds;
3079
3117
  exports.classifyType = classifyType;
3080
3118
  exports.describeParseResult = describeParseResult;
3081
3119
  exports.escapeCsvField = escapeCsvField;
@@ -3111,6 +3149,7 @@ exports.parseWKB = parseWKB;
3111
3149
  exports.persistToStorage = persistToStorage;
3112
3150
  exports.readParquetMetadata = readParquetMetadata;
3113
3151
  exports.resolveCloudUrl = resolveCloudUrl;
3152
+ exports.safeClamp = safeClamp;
3114
3153
  exports.safeDecodeURIComponent = safeDecodeURIComponent;
3115
3154
  exports.serializeToCsv = serializeToCsv;
3116
3155
  exports.serializeToJson = serializeToJson;