@walkthru-earth/objex-utils 1.1.0 → 1.2.1

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.d.cts CHANGED
@@ -11,8 +11,12 @@ declare const STORAGE_KEYS: {
11
11
  };
12
12
  /** EPSG codes considered WGS84 (no reprojection needed). */
13
13
  declare const WGS84_CODES: Set<number>;
14
- /** Default target CRS for ST_Transform. */
15
- declare const DEFAULT_TARGET_CRS = "EPSG:4326";
14
+ /**
15
+ * Default target CRS for ST_Transform. Uses OGC:CRS84 (longitude, latitude)
16
+ * to match GeoParquet 1.1+ spec and DuckDB v1.5's canonical form.
17
+ * Functionally equivalent to EPSG:4326 under `geometry_always_xy = true`.
18
+ */
19
+ declare const DEFAULT_TARGET_CRS = "OGC:CRS84";
16
20
  /** DuckDB-WASM initialization timeout in ms. */
17
21
  declare const DUCKDB_INIT_TIMEOUT_MS = 30000;
18
22
  /** Maximum entries kept in query history. */
@@ -119,15 +123,27 @@ interface SchemaField {
119
123
  type: string;
120
124
  nullable: boolean;
121
125
  }
126
+ /**
127
+ * Abstraction over a DuckDB query source. Decouples schema / CRS / count
128
+ * helpers from assuming a file-backed path. `ref` is the FROM-clause target
129
+ * inserted into generated SQL (e.g. `read_parquet('url')` for files, or
130
+ * `attached_db."schema"."table"` for attached databases). `filePath` is
131
+ * optional and only used as a shortcut for Parquet file-level metadata
132
+ * queries (`parquet_kv_metadata`, `parquet_file_metadata`), not for SQL.
133
+ */
134
+ interface QuerySource {
135
+ ref: string;
136
+ filePath?: string;
137
+ }
122
138
  interface QueryEngine {
123
139
  query(connId: string, sql: string): Promise<QueryResult>;
124
140
  queryForMap(connId: string, sql: string, geomCol: string, geomColType: string, sourceCrs?: string | null): Promise<MapQueryResult>;
125
- getSchema(connId: string, path: string): Promise<SchemaField[]>;
126
- getRowCount(connId: string, path: string): Promise<number>;
141
+ getSchema(connId: string, source: QuerySource): Promise<SchemaField[]>;
142
+ getRowCount(connId: string, source: QuerySource): Promise<number>;
127
143
  /** Detect CRS from GeoParquet metadata. Returns e.g. 'EPSG:27700' or null if WGS84/unknown. */
128
- detectCrs(connId: string, path: string, geomCol: string): Promise<string | null>;
144
+ detectCrs(connId: string, source: QuerySource, geomCol: string): Promise<string | null>;
129
145
  /** Combined schema + CRS detection in a single connection (fewer web worker round-trips). */
130
- getSchemaAndCrs?(connId: string, path: string, findGeoCol: (schema: SchemaField[]) => string | null): Promise<{
146
+ getSchemaAndCrs?(connId: string, source: QuerySource, findGeoCol: (schema: SchemaField[]) => string | null): Promise<{
131
147
  schema: SchemaField[];
132
148
  geomCol: string | null;
133
149
  crs: string | null;
@@ -135,6 +151,10 @@ interface QueryEngine {
135
151
  queryCancellable?(connId: string, sql: string): QueryHandle;
136
152
  queryForMapCancellable?(connId: string, sql: string, geomCol: string, geomColType: string, sourceCrs?: string | null): MapQueryHandle;
137
153
  forceCancel?(): Promise<void>;
154
+ /** Register a file buffer in DuckDB-WASM's virtual filesystem for ATTACH. */
155
+ registerFileBuffer?(name: string, buffer: Uint8Array): Promise<void>;
156
+ /** Drop a previously registered file from DuckDB-WASM's virtual filesystem. */
157
+ dropFile?(name: string): Promise<void>;
138
158
  releaseMemory(): Promise<void>;
139
159
  dispose(): Promise<void>;
140
160
  }
@@ -179,6 +199,17 @@ interface Tab {
179
199
  connectionId?: string;
180
200
  extension: string;
181
201
  size?: number;
202
+ /**
203
+ * When set, the tab reads data from a SQL FROM-clause target (e.g. an
204
+ * attached DuckLake/DuckDB/SQLite table) rather than a file URL. The ref
205
+ * is inserted directly into generated SQL, so it must be fully-qualified
206
+ * and pre-quoted, e.g. `__objex_db__."main"."air_quality"`.
207
+ *
208
+ * When `sourceRef` is set, file-specific loading paths (hyparquet
209
+ * metadata, `parquet_kv_metadata`, etc.) are skipped, and schema / CRS /
210
+ * row count are derived from the SQL source directly via DuckDB.
211
+ */
212
+ sourceRef?: string;
182
213
  }
183
214
  interface WriteResult {
184
215
  key: string;
@@ -254,6 +285,12 @@ declare const PROVIDER_IDS: ProviderId[];
254
285
  declare function getProvider(id: string): ProviderDef;
255
286
  /** Build endpoint URL from template + region. */
256
287
  declare function buildEndpointFromTemplate(id: ProviderId, region: string): string;
288
+ /**
289
+ * Resolve an endpoint URL for a provider using its registered template,
290
+ * falling back to the provider's default region when none is supplied.
291
+ * Returns '' when the provider has no template (e.g. plain S3 or MinIO).
292
+ */
293
+ declare function resolveProviderEndpoint(provider: string, region?: string): string;
257
294
  /**
258
295
  * Build the base URL for API requests (endpoint + bucket).
259
296
  * Used by browser-cloud adapter and url-state.
@@ -261,6 +298,33 @@ declare function buildEndpointFromTemplate(id: ProviderId, region: string): stri
261
298
  declare function buildProviderBaseUrl(provider: ProviderId, endpoint: string, bucket: string, region: string): string;
262
299
  /** Check if a provider uses the GCS JSON API (not S3 XML). */
263
300
  declare function isGcsProvider(provider: string, endpoint: string): boolean;
301
+ /**
302
+ * Minimal connection shape needed to decide access mode.
303
+ * Kept loose so callers don't need to import the full Connection type.
304
+ */
305
+ interface AccessModeInput {
306
+ provider: string;
307
+ anonymous?: boolean;
308
+ endpoint?: string;
309
+ }
310
+ /**
311
+ * How a connection's files can be read by the browser:
312
+ *
313
+ * - `public-https`: plain HTTPS via any HTTP client. No auth, no signing.
314
+ * Covers anonymous AWS/GCS/R2/Storj/Wasabi/etc.
315
+ * - `sas-https`: HTTPS with SAS token embedded in the URL. Still works with
316
+ * any HTTP client. Azure only.
317
+ * - `signed-s3`: requires SigV4 signing. DuckDB uses the `s3://` URI and
318
+ * signs it via its S3 config; other viewers must go through the storage
319
+ * adapter (which returns a blob) instead of streaming the HTTPS URL.
320
+ */
321
+ type AccessMode = 'public-https' | 'sas-https' | 'signed-s3';
322
+ declare function getAccessMode(conn: AccessModeInput): AccessMode;
323
+ /**
324
+ * True when the connection's files can be fetched by any HTTP client
325
+ * (fetch/img/video/DuckDB httpfs/COG/Zarr/etc.) without the storage adapter.
326
+ */
327
+ declare function isPubliclyStreamable(conn: AccessModeInput): boolean;
264
328
 
265
329
  /**
266
330
  * Minimal adapter for direct HTTPS URLs (source: 'url').
@@ -308,6 +372,32 @@ declare function safeDecodeURIComponent(s: string): string;
308
372
  */
309
373
  declare function resolveCloudUrl(url: string): string;
310
374
 
375
+ /** SampleFormat tag value → human label. */
376
+ declare const SF_LABELS: Record<number, string>;
377
+ interface GeoBounds {
378
+ west: number;
379
+ south: number;
380
+ east: number;
381
+ north: number;
382
+ }
383
+ interface CogInfo {
384
+ width: number;
385
+ height: number;
386
+ bandCount: number;
387
+ dataType: string;
388
+ bounds: GeoBounds;
389
+ downsampled?: boolean;
390
+ }
391
+ /** Safely clamp a number to a range, treating NaN/Infinity as the fallback. */
392
+ declare function safeClamp(v: number, lo: number, hi: number, fallback: number): number;
393
+ /** Clamp geographic bounds to valid MapLibre web-Mercator range. */
394
+ declare function clampBounds(b: GeoBounds): GeoBounds;
395
+ /**
396
+ * Build a data-type label from GeoTIFF sample format and bits per sample.
397
+ * e.g. "uint8", "float32", "int16"
398
+ */
399
+ declare function buildDataTypeLabel(sampleFormat: number, bitsPerSample: number): string;
400
+
311
401
  type TypeCategory = 'number' | 'string' | 'date' | 'boolean' | 'geo' | 'binary' | 'json' | 'other';
312
402
  declare function classifyType(duckdbType: string): TypeCategory;
313
403
  declare function typeColor(category: TypeCategory): string;
@@ -337,6 +427,14 @@ declare function serializeToCsv(columns: string[], rows: Record<string, unknown>
337
427
  * Pure function — no browser APIs, works in Node.js.
338
428
  */
339
429
  declare function serializeToJson(columns: string[], rows: Record<string, unknown>[]): string;
430
+ /**
431
+ * Export data as CSV file (triggers browser download).
432
+ */
433
+ declare function exportToCsv(columns: string[], rows: Record<string, unknown>[], filename: string): void;
434
+ /**
435
+ * Export data as JSON file (triggers browser download).
436
+ */
437
+ declare function exportToJson(columns: string[], rows: Record<string, unknown>[], filename: string): void;
340
438
 
341
439
  /**
342
440
  * Pure file entry sorting — framework-agnostic, works in Node.js.
@@ -464,7 +562,7 @@ interface ParsedMarkdownDocument {
464
562
  * SELECT * FROM table
465
563
  * ```
466
564
  */
467
- declare function parseMarkdownDocument(markdown: string): ParsedMarkdownDocument;
565
+ declare function parseMarkdownDocument(markdown: string): Promise<ParsedMarkdownDocument>;
468
566
  /**
469
567
  * Interpolate template variables in markdown text.
470
568
  * Supports {queryName.rows[0].columnName} syntax.
@@ -644,4 +742,4 @@ declare function findGeoColumnFromRows(rows: Record<string, unknown>[], schema:
644
742
  type: string;
645
743
  }[]): string | null;
646
744
 
647
- export { COPY_FEEDBACK_MS, type Connection, type ConnectionConfig, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, type Defaults, type DuckDbReadFn, type FileCategory, type FileEntry, type FileTypeInfo, type GeoArrowGeomType, type GeoArrowResult, type GeoColumnMeta, type GeoParquetMeta, type GeoType, type HexRow, LAYER_HUE_MULTIPLIER, type ListPage, MAX_QUERY_HISTORY_ENTRIES, type MapQueryHandle, type MapQueryResult, PROVIDERS, PROVIDER_IDS, type ParquetFileMetadata, type ParsedGeometry, type ParsedMarkdownDocument, type ParsedStorageUrl, type ProviderDef, type ProviderId, type ProviderRegion, QueryCancelledError, type QueryEngine, type QueryHandle, type QueryResult, SQL_PREVIEW_LENGTH, STORAGE_KEYS, type SchemaField, type SortConfig, type SortDirection, type SortField, type SqlBlock, type StorageAdapter, type StorageProvider, type Tab, type Theme, type TypeCategory, UrlAdapter, VIEWER_DIR_EXTENSIONS, type ViewerKind, WGS84_CODES, type WriteResult, buildDuckDbSource, buildEndpointFromTemplate, buildGeoArrowTables, buildProviderBaseUrl, 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, safeDecodeURIComponent, serializeToCsv, serializeToJson, sortFileEntries, toBinary, toggleSortField, typeBadgeClass, typeColor, typeLabel };
745
+ export { type AccessMode, type AccessModeInput, COPY_FEEDBACK_MS, type CogInfo, type Connection, type ConnectionConfig, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, type Defaults, type DuckDbReadFn, type FileCategory, type FileEntry, type FileTypeInfo, type GeoArrowGeomType, type GeoArrowResult, type GeoBounds, type GeoColumnMeta, type GeoParquetMeta, type GeoType, type HexRow, LAYER_HUE_MULTIPLIER, type ListPage, MAX_QUERY_HISTORY_ENTRIES, type MapQueryHandle, type MapQueryResult, PROVIDERS, PROVIDER_IDS, type ParquetFileMetadata, type ParsedGeometry, type ParsedMarkdownDocument, type ParsedStorageUrl, type ProviderDef, type ProviderId, type ProviderRegion, QueryCancelledError, type QueryEngine, type QueryHandle, type QueryResult, type QuerySource, SF_LABELS, SQL_PREVIEW_LENGTH, STORAGE_KEYS, type SchemaField, type SortConfig, type SortDirection, type SortField, type SqlBlock, type StorageAdapter, type StorageProvider, type Tab, type Theme, type TypeCategory, UrlAdapter, VIEWER_DIR_EXTENSIONS, type ViewerKind, WGS84_CODES, type WriteResult, 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 };
package/dist/index.d.ts CHANGED
@@ -11,8 +11,12 @@ declare const STORAGE_KEYS: {
11
11
  };
12
12
  /** EPSG codes considered WGS84 (no reprojection needed). */
13
13
  declare const WGS84_CODES: Set<number>;
14
- /** Default target CRS for ST_Transform. */
15
- declare const DEFAULT_TARGET_CRS = "EPSG:4326";
14
+ /**
15
+ * Default target CRS for ST_Transform. Uses OGC:CRS84 (longitude, latitude)
16
+ * to match GeoParquet 1.1+ spec and DuckDB v1.5's canonical form.
17
+ * Functionally equivalent to EPSG:4326 under `geometry_always_xy = true`.
18
+ */
19
+ declare const DEFAULT_TARGET_CRS = "OGC:CRS84";
16
20
  /** DuckDB-WASM initialization timeout in ms. */
17
21
  declare const DUCKDB_INIT_TIMEOUT_MS = 30000;
18
22
  /** Maximum entries kept in query history. */
@@ -119,15 +123,27 @@ interface SchemaField {
119
123
  type: string;
120
124
  nullable: boolean;
121
125
  }
126
+ /**
127
+ * Abstraction over a DuckDB query source. Decouples schema / CRS / count
128
+ * helpers from assuming a file-backed path. `ref` is the FROM-clause target
129
+ * inserted into generated SQL (e.g. `read_parquet('url')` for files, or
130
+ * `attached_db."schema"."table"` for attached databases). `filePath` is
131
+ * optional and only used as a shortcut for Parquet file-level metadata
132
+ * queries (`parquet_kv_metadata`, `parquet_file_metadata`), not for SQL.
133
+ */
134
+ interface QuerySource {
135
+ ref: string;
136
+ filePath?: string;
137
+ }
122
138
  interface QueryEngine {
123
139
  query(connId: string, sql: string): Promise<QueryResult>;
124
140
  queryForMap(connId: string, sql: string, geomCol: string, geomColType: string, sourceCrs?: string | null): Promise<MapQueryResult>;
125
- getSchema(connId: string, path: string): Promise<SchemaField[]>;
126
- getRowCount(connId: string, path: string): Promise<number>;
141
+ getSchema(connId: string, source: QuerySource): Promise<SchemaField[]>;
142
+ getRowCount(connId: string, source: QuerySource): Promise<number>;
127
143
  /** Detect CRS from GeoParquet metadata. Returns e.g. 'EPSG:27700' or null if WGS84/unknown. */
128
- detectCrs(connId: string, path: string, geomCol: string): Promise<string | null>;
144
+ detectCrs(connId: string, source: QuerySource, geomCol: string): Promise<string | null>;
129
145
  /** Combined schema + CRS detection in a single connection (fewer web worker round-trips). */
130
- getSchemaAndCrs?(connId: string, path: string, findGeoCol: (schema: SchemaField[]) => string | null): Promise<{
146
+ getSchemaAndCrs?(connId: string, source: QuerySource, findGeoCol: (schema: SchemaField[]) => string | null): Promise<{
131
147
  schema: SchemaField[];
132
148
  geomCol: string | null;
133
149
  crs: string | null;
@@ -135,6 +151,10 @@ interface QueryEngine {
135
151
  queryCancellable?(connId: string, sql: string): QueryHandle;
136
152
  queryForMapCancellable?(connId: string, sql: string, geomCol: string, geomColType: string, sourceCrs?: string | null): MapQueryHandle;
137
153
  forceCancel?(): Promise<void>;
154
+ /** Register a file buffer in DuckDB-WASM's virtual filesystem for ATTACH. */
155
+ registerFileBuffer?(name: string, buffer: Uint8Array): Promise<void>;
156
+ /** Drop a previously registered file from DuckDB-WASM's virtual filesystem. */
157
+ dropFile?(name: string): Promise<void>;
138
158
  releaseMemory(): Promise<void>;
139
159
  dispose(): Promise<void>;
140
160
  }
@@ -179,6 +199,17 @@ interface Tab {
179
199
  connectionId?: string;
180
200
  extension: string;
181
201
  size?: number;
202
+ /**
203
+ * When set, the tab reads data from a SQL FROM-clause target (e.g. an
204
+ * attached DuckLake/DuckDB/SQLite table) rather than a file URL. The ref
205
+ * is inserted directly into generated SQL, so it must be fully-qualified
206
+ * and pre-quoted, e.g. `__objex_db__."main"."air_quality"`.
207
+ *
208
+ * When `sourceRef` is set, file-specific loading paths (hyparquet
209
+ * metadata, `parquet_kv_metadata`, etc.) are skipped, and schema / CRS /
210
+ * row count are derived from the SQL source directly via DuckDB.
211
+ */
212
+ sourceRef?: string;
182
213
  }
183
214
  interface WriteResult {
184
215
  key: string;
@@ -254,6 +285,12 @@ declare const PROVIDER_IDS: ProviderId[];
254
285
  declare function getProvider(id: string): ProviderDef;
255
286
  /** Build endpoint URL from template + region. */
256
287
  declare function buildEndpointFromTemplate(id: ProviderId, region: string): string;
288
+ /**
289
+ * Resolve an endpoint URL for a provider using its registered template,
290
+ * falling back to the provider's default region when none is supplied.
291
+ * Returns '' when the provider has no template (e.g. plain S3 or MinIO).
292
+ */
293
+ declare function resolveProviderEndpoint(provider: string, region?: string): string;
257
294
  /**
258
295
  * Build the base URL for API requests (endpoint + bucket).
259
296
  * Used by browser-cloud adapter and url-state.
@@ -261,6 +298,33 @@ declare function buildEndpointFromTemplate(id: ProviderId, region: string): stri
261
298
  declare function buildProviderBaseUrl(provider: ProviderId, endpoint: string, bucket: string, region: string): string;
262
299
  /** Check if a provider uses the GCS JSON API (not S3 XML). */
263
300
  declare function isGcsProvider(provider: string, endpoint: string): boolean;
301
+ /**
302
+ * Minimal connection shape needed to decide access mode.
303
+ * Kept loose so callers don't need to import the full Connection type.
304
+ */
305
+ interface AccessModeInput {
306
+ provider: string;
307
+ anonymous?: boolean;
308
+ endpoint?: string;
309
+ }
310
+ /**
311
+ * How a connection's files can be read by the browser:
312
+ *
313
+ * - `public-https`: plain HTTPS via any HTTP client. No auth, no signing.
314
+ * Covers anonymous AWS/GCS/R2/Storj/Wasabi/etc.
315
+ * - `sas-https`: HTTPS with SAS token embedded in the URL. Still works with
316
+ * any HTTP client. Azure only.
317
+ * - `signed-s3`: requires SigV4 signing. DuckDB uses the `s3://` URI and
318
+ * signs it via its S3 config; other viewers must go through the storage
319
+ * adapter (which returns a blob) instead of streaming the HTTPS URL.
320
+ */
321
+ type AccessMode = 'public-https' | 'sas-https' | 'signed-s3';
322
+ declare function getAccessMode(conn: AccessModeInput): AccessMode;
323
+ /**
324
+ * True when the connection's files can be fetched by any HTTP client
325
+ * (fetch/img/video/DuckDB httpfs/COG/Zarr/etc.) without the storage adapter.
326
+ */
327
+ declare function isPubliclyStreamable(conn: AccessModeInput): boolean;
264
328
 
265
329
  /**
266
330
  * Minimal adapter for direct HTTPS URLs (source: 'url').
@@ -308,6 +372,32 @@ declare function safeDecodeURIComponent(s: string): string;
308
372
  */
309
373
  declare function resolveCloudUrl(url: string): string;
310
374
 
375
+ /** SampleFormat tag value → human label. */
376
+ declare const SF_LABELS: Record<number, string>;
377
+ interface GeoBounds {
378
+ west: number;
379
+ south: number;
380
+ east: number;
381
+ north: number;
382
+ }
383
+ interface CogInfo {
384
+ width: number;
385
+ height: number;
386
+ bandCount: number;
387
+ dataType: string;
388
+ bounds: GeoBounds;
389
+ downsampled?: boolean;
390
+ }
391
+ /** Safely clamp a number to a range, treating NaN/Infinity as the fallback. */
392
+ declare function safeClamp(v: number, lo: number, hi: number, fallback: number): number;
393
+ /** Clamp geographic bounds to valid MapLibre web-Mercator range. */
394
+ declare function clampBounds(b: GeoBounds): GeoBounds;
395
+ /**
396
+ * Build a data-type label from GeoTIFF sample format and bits per sample.
397
+ * e.g. "uint8", "float32", "int16"
398
+ */
399
+ declare function buildDataTypeLabel(sampleFormat: number, bitsPerSample: number): string;
400
+
311
401
  type TypeCategory = 'number' | 'string' | 'date' | 'boolean' | 'geo' | 'binary' | 'json' | 'other';
312
402
  declare function classifyType(duckdbType: string): TypeCategory;
313
403
  declare function typeColor(category: TypeCategory): string;
@@ -337,6 +427,14 @@ declare function serializeToCsv(columns: string[], rows: Record<string, unknown>
337
427
  * Pure function — no browser APIs, works in Node.js.
338
428
  */
339
429
  declare function serializeToJson(columns: string[], rows: Record<string, unknown>[]): string;
430
+ /**
431
+ * Export data as CSV file (triggers browser download).
432
+ */
433
+ declare function exportToCsv(columns: string[], rows: Record<string, unknown>[], filename: string): void;
434
+ /**
435
+ * Export data as JSON file (triggers browser download).
436
+ */
437
+ declare function exportToJson(columns: string[], rows: Record<string, unknown>[], filename: string): void;
340
438
 
341
439
  /**
342
440
  * Pure file entry sorting — framework-agnostic, works in Node.js.
@@ -464,7 +562,7 @@ interface ParsedMarkdownDocument {
464
562
  * SELECT * FROM table
465
563
  * ```
466
564
  */
467
- declare function parseMarkdownDocument(markdown: string): ParsedMarkdownDocument;
565
+ declare function parseMarkdownDocument(markdown: string): Promise<ParsedMarkdownDocument>;
468
566
  /**
469
567
  * Interpolate template variables in markdown text.
470
568
  * Supports {queryName.rows[0].columnName} syntax.
@@ -644,4 +742,4 @@ declare function findGeoColumnFromRows(rows: Record<string, unknown>[], schema:
644
742
  type: string;
645
743
  }[]): string | null;
646
744
 
647
- export { COPY_FEEDBACK_MS, type Connection, type ConnectionConfig, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, type Defaults, type DuckDbReadFn, type FileCategory, type FileEntry, type FileTypeInfo, type GeoArrowGeomType, type GeoArrowResult, type GeoColumnMeta, type GeoParquetMeta, type GeoType, type HexRow, LAYER_HUE_MULTIPLIER, type ListPage, MAX_QUERY_HISTORY_ENTRIES, type MapQueryHandle, type MapQueryResult, PROVIDERS, PROVIDER_IDS, type ParquetFileMetadata, type ParsedGeometry, type ParsedMarkdownDocument, type ParsedStorageUrl, type ProviderDef, type ProviderId, type ProviderRegion, QueryCancelledError, type QueryEngine, type QueryHandle, type QueryResult, SQL_PREVIEW_LENGTH, STORAGE_KEYS, type SchemaField, type SortConfig, type SortDirection, type SortField, type SqlBlock, type StorageAdapter, type StorageProvider, type Tab, type Theme, type TypeCategory, UrlAdapter, VIEWER_DIR_EXTENSIONS, type ViewerKind, WGS84_CODES, type WriteResult, buildDuckDbSource, buildEndpointFromTemplate, buildGeoArrowTables, buildProviderBaseUrl, 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, safeDecodeURIComponent, serializeToCsv, serializeToJson, sortFileEntries, toBinary, toggleSortField, typeBadgeClass, typeColor, typeLabel };
745
+ export { type AccessMode, type AccessModeInput, COPY_FEEDBACK_MS, type CogInfo, type Connection, type ConnectionConfig, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, type Defaults, type DuckDbReadFn, type FileCategory, type FileEntry, type FileTypeInfo, type GeoArrowGeomType, type GeoArrowResult, type GeoBounds, type GeoColumnMeta, type GeoParquetMeta, type GeoType, type HexRow, LAYER_HUE_MULTIPLIER, type ListPage, MAX_QUERY_HISTORY_ENTRIES, type MapQueryHandle, type MapQueryResult, PROVIDERS, PROVIDER_IDS, type ParquetFileMetadata, type ParsedGeometry, type ParsedMarkdownDocument, type ParsedStorageUrl, type ProviderDef, type ProviderId, type ProviderRegion, QueryCancelledError, type QueryEngine, type QueryHandle, type QueryResult, type QuerySource, SF_LABELS, SQL_PREVIEW_LENGTH, STORAGE_KEYS, type SchemaField, type SortConfig, type SortDirection, type SortField, type SqlBlock, type StorageAdapter, type StorageProvider, type Tab, type Theme, type TypeCategory, UrlAdapter, VIEWER_DIR_EXTENSIONS, type ViewerKind, WGS84_CODES, type WriteResult, 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 };
package/dist/index.js CHANGED
@@ -1,5 +1,9 @@
1
+ import '@developmentseed/epsg/all';
2
+ import '@developmentseed/epsg/all.csv.gz?url';
3
+ import '@developmentseed/geotiff';
4
+ import '@developmentseed/proj';
5
+ import 'proj4';
1
6
  import { Field, Float64, FixedSizeList, Schema, Struct, makeData, RecordBatch, Table, List, Utf8 } from 'apache-arrow';
2
- import YAML from 'yaml';
3
7
 
4
8
  // ../../src/lib/constants.ts
5
9
  var STORAGE_KEYS = {
@@ -8,7 +12,7 @@ var STORAGE_KEYS = {
8
12
  QUERY_HISTORY: "obstore-explore-query-history"
9
13
  };
10
14
  var WGS84_CODES = /* @__PURE__ */ new Set([4326, 4979]);
11
- var DEFAULT_TARGET_CRS = "EPSG:4326";
15
+ var DEFAULT_TARGET_CRS = "OGC:CRS84";
12
16
  var DUCKDB_INIT_TIMEOUT_MS = 3e4;
13
17
  var MAX_QUERY_HISTORY_ENTRIES = 200;
14
18
  var SQL_PREVIEW_LENGTH = 120;
@@ -888,6 +892,16 @@ var EXTENSIONS = {
888
892
  duckdbReadFn: null,
889
893
  mimeType: "application/octet-stream"
890
894
  },
895
+ ".ducklake": {
896
+ icon: "Database",
897
+ color: "text-teal-600 dark:text-teal-400",
898
+ label: "DuckLake",
899
+ category: "database",
900
+ viewer: "database",
901
+ queryable: true,
902
+ duckdbReadFn: null,
903
+ mimeType: "application/octet-stream"
904
+ },
891
905
  ".sqlite": {
892
906
  icon: "Database",
893
907
  color: "text-sky-600 dark:text-sky-400",
@@ -1035,7 +1049,7 @@ function buildDuckDbSource(pathOrExt, url) {
1035
1049
  const readFn = EXTENSIONS[ext]?.duckdbReadFn ?? "read_parquet";
1036
1050
  return `${readFn}('${url}')`;
1037
1051
  }
1038
- var CLOUD_NATIVE_EXTS = /* @__PURE__ */ new Set([".parquet", ".geoparquet", ".gpq", ".gparquet"]);
1052
+ var CLOUD_NATIVE_EXTS = /* @__PURE__ */ new Set([".parquet", ".geoparquet", ".gpq", ".gparquet", ".ducklake"]);
1039
1053
  function isCloudNativeFormat(pathOrExt) {
1040
1054
  const ext = pathOrExt.includes(".") ? `.${pathOrExt.split(".").pop().toLowerCase()}` : "";
1041
1055
  return CLOUD_NATIVE_EXTS.has(ext);
@@ -1341,6 +1355,11 @@ function buildEndpointFromTemplate(id, region) {
1341
1355
  if (!def?.endpointTemplate) return "";
1342
1356
  return def.endpointTemplate.replace("{region}", region);
1343
1357
  }
1358
+ function resolveProviderEndpoint(provider, region) {
1359
+ const def = PROVIDERS[provider];
1360
+ if (!def?.endpointTemplate) return "";
1361
+ return buildEndpointFromTemplate(provider, region || def.defaultRegion);
1362
+ }
1344
1363
  function buildProviderBaseUrl(provider, endpoint, bucket, region) {
1345
1364
  if (endpoint) {
1346
1365
  return `${endpoint.replace(/\/$/, "")}/${bucket}`;
@@ -1355,6 +1374,15 @@ function buildProviderBaseUrl(provider, endpoint, bucket, region) {
1355
1374
  function isGcsProvider(provider, endpoint) {
1356
1375
  return provider === "gcs" || !!endpoint && /storage\.googleapis\.com/i.test(endpoint);
1357
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
+ }
1358
1386
 
1359
1387
  // ../../src/lib/storage/url-adapter.ts
1360
1388
  var UrlAdapter = class {
@@ -1432,6 +1460,28 @@ function resolveCloudUrl(url) {
1432
1460
  }
1433
1461
  return url;
1434
1462
  }
1463
+ var SF_LABELS = {
1464
+ 1: "uint",
1465
+ 2: "int",
1466
+ 3: "float",
1467
+ 4: "void",
1468
+ 5: "complex int",
1469
+ 6: "complex float"
1470
+ };
1471
+ function safeClamp(v, lo, hi, fallback) {
1472
+ return Number.isFinite(v) ? Math.max(lo, Math.min(hi, v)) : fallback;
1473
+ }
1474
+ function clampBounds(b) {
1475
+ return {
1476
+ west: safeClamp(b.west, -180, 180, -180),
1477
+ south: safeClamp(b.south, -85.051129, 85.051129, -85.051129),
1478
+ east: safeClamp(b.east, -180, 180, 180),
1479
+ north: safeClamp(b.north, -85.051129, 85.051129, 85.051129)
1480
+ };
1481
+ }
1482
+ function buildDataTypeLabel(sampleFormat, bitsPerSample) {
1483
+ return `${SF_LABELS[sampleFormat] ?? `sf${sampleFormat}`}${bitsPerSample ?? ""}`;
1484
+ }
1435
1485
 
1436
1486
  // ../../src/lib/utils/column-types.ts
1437
1487
  var NUMBER_TYPES = [
@@ -1602,6 +1652,17 @@ function formatValue(value) {
1602
1652
  }
1603
1653
 
1604
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
+ }
1605
1666
  function formatCellValue(value) {
1606
1667
  if (value === null || value === void 0) return "";
1607
1668
  if (value instanceof Date) return value.toISOString();
@@ -1636,6 +1697,20 @@ function serializeToJson(columns, rows) {
1636
1697
  });
1637
1698
  return JSON.stringify(data, jsonReplacerBigInt, 2);
1638
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
+ }
1639
1714
 
1640
1715
  // ../../src/lib/utils/file-sort.ts
1641
1716
  function sortFileEntries(entries, config) {
@@ -2283,12 +2358,15 @@ function persistToStorage(key, value) {
2283
2358
  } catch {
2284
2359
  }
2285
2360
  }
2286
- function parseMarkdownDocument(markdown) {
2361
+
2362
+ // ../../src/lib/utils/markdown-sql.ts
2363
+ async function parseMarkdownDocument(markdown) {
2287
2364
  let frontmatter = {};
2288
2365
  let content = markdown;
2289
2366
  const fmMatch = markdown.match(/^---\n([\s\S]*?)\n---\n/);
2290
2367
  if (fmMatch) {
2291
2368
  try {
2369
+ const { default: YAML } = await import('yaml');
2292
2370
  frontmatter = YAML.parse(fmMatch[1]) || {};
2293
2371
  } catch {
2294
2372
  }
@@ -2959,7 +3037,10 @@ var GEO_TYPE_KEYWORDS = [
2959
3037
  "geometrycollection",
2960
3038
  "sdo_geometry"
2961
3039
  ];
2962
- var GEO_NAME_HINTS = ["geom", "geometry", "geo_", "_geo", "wkb", "wkt", "shape", "spatial"];
3040
+ var GEO_NAME_HINTS = ["geom", "geometry", "wkb", "wkt", "shape", "spatial", "geo"];
3041
+ function tokenizeColumnName(name) {
3042
+ 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);
3043
+ }
2963
3044
  var GEOJSON_TYPES = [
2964
3045
  "Point",
2965
3046
  "LineString",
@@ -2989,14 +3070,14 @@ function findGeoColumn(schema) {
2989
3070
  if (GEO_NAMES.includes(f.name.toLowerCase())) return f.name;
2990
3071
  }
2991
3072
  for (const f of schema) {
2992
- const n = f.name.toLowerCase();
3073
+ const tokens = tokenizeColumnName(f.name);
2993
3074
  const t = f.type.toLowerCase();
2994
3075
  const isBinary = t.includes("blob") || t.includes("binary") || t.includes("bytea");
2995
- if (isBinary && GEO_NAME_HINTS.some((hint) => n.includes(hint))) return f.name;
3076
+ if (isBinary && tokens.some((tok) => GEO_NAME_HINTS.includes(tok))) return f.name;
2996
3077
  }
2997
3078
  for (const f of schema) {
2998
- const n = f.name.toLowerCase();
2999
- if (GEO_NAME_HINTS.some((hint) => n.includes(hint))) return f.name;
3079
+ const tokens = tokenizeColumnName(f.name);
3080
+ if (tokens.some((tok) => GEO_NAME_HINTS.includes(tok))) return f.name;
3000
3081
  }
3001
3082
  return null;
3002
3083
  }
@@ -3053,6 +3134,6 @@ function isWKT(value) {
3053
3134
  return WKT_TYPES.some((t) => s.startsWith(t) || s.startsWith(`MULTI${t}`));
3054
3135
  }
3055
3136
 
3056
- export { COPY_FEEDBACK_MS, DEFAULT_TARGET_CRS, DUCKDB_INIT_TIMEOUT_MS, LAYER_HUE_MULTIPLIER, MAX_QUERY_HISTORY_ENTRIES, PROVIDERS, PROVIDER_IDS, QueryCancelledError, SQL_PREVIEW_LENGTH, STORAGE_KEYS, UrlAdapter, VIEWER_DIR_EXTENSIONS, WGS84_CODES, buildDuckDbSource, buildEndpointFromTemplate, buildGeoArrowTables, buildProviderBaseUrl, 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, safeDecodeURIComponent, serializeToCsv, serializeToJson, sortFileEntries, toBinary, toggleSortField, typeBadgeClass, typeColor, typeLabel };
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 };
3057
3138
  //# sourceMappingURL=index.js.map
3058
3139
  //# sourceMappingURL=index.js.map