@walkthru-earth/objex 1.3.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +28 -20
- package/dist/components/browser/FileTreeSidebar.svelte +32 -17
- package/dist/components/layout/AboutSheet.svelte +5 -2
- package/dist/components/layout/ConnectionDialog.svelte +7 -2
- package/dist/components/layout/SettingsSheet.svelte +238 -0
- package/dist/components/layout/SettingsSheet.svelte.d.ts +6 -0
- package/dist/components/layout/Sidebar.svelte +73 -6
- package/dist/components/layout/Sidebar.svelte.d.ts +4 -1
- package/dist/components/layout/StatusBar.svelte +17 -14
- package/dist/components/layout/TabBar.svelte +4 -4
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +1 -1
- package/dist/components/ui/input/input.svelte.d.ts +1 -1
- package/dist/components/ui/resizable/index.d.ts +1 -1
- package/dist/components/ui/resizable/index.js +2 -2
- package/dist/components/ui/slider/index.d.ts +3 -0
- package/dist/components/ui/slider/index.js +5 -0
- package/dist/components/ui/slider/range-slider.svelte +94 -0
- package/dist/components/ui/slider/range-slider.svelte.d.ts +21 -0
- package/dist/components/ui/slider/slider.svelte +83 -0
- package/dist/components/ui/slider/slider.svelte.d.ts +7 -0
- package/dist/components/viewers/ArchiveViewer.svelte +140 -113
- package/dist/components/viewers/CodeViewer.svelte +45 -48
- package/dist/components/viewers/CodeViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/CogControls.svelte +338 -184
- package/dist/components/viewers/CogControls.svelte.d.ts +33 -10
- package/dist/components/viewers/CogViewer.svelte +269 -116
- package/dist/components/viewers/CopcViewer.svelte +8 -15
- package/dist/components/viewers/DatabaseViewer.svelte +22 -21
- package/dist/components/viewers/FileInfo.svelte +16 -16
- package/dist/components/viewers/FlatGeobufViewer.svelte +16 -46
- package/dist/components/viewers/GeoParquetMapViewer.svelte +11 -9
- package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/ImageViewer.svelte +12 -14
- package/dist/components/viewers/LoadProgress.svelte +6 -6
- package/dist/components/viewers/MarkdownViewer.svelte +29 -30
- package/dist/components/viewers/MediaViewer.svelte +13 -14
- package/dist/components/viewers/ModelViewer.svelte +18 -21
- package/dist/components/viewers/MultiCogViewer.svelte +474 -106
- package/dist/components/viewers/MultiCogViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/NotebookViewer.svelte +28 -29
- package/dist/components/viewers/PdfViewer.svelte +24 -33
- package/dist/components/viewers/PmtilesViewer.svelte +13 -15
- package/dist/components/viewers/QueryHistoryPanel.svelte +18 -18
- package/dist/components/viewers/RawViewer.svelte +27 -21
- package/dist/components/viewers/StacMapViewer.svelte +6 -13
- package/dist/components/viewers/StacMosaicViewer.svelte +1764 -410
- package/dist/components/viewers/StacMosaicViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/StacTabViewer.svelte +26 -15
- package/dist/components/viewers/StacTabViewer.svelte.d.ts +1 -1
- package/dist/components/viewers/TableGrid.svelte +38 -34
- package/dist/components/viewers/TableStatusBar.svelte +7 -7
- package/dist/components/viewers/TableToolbar.svelte +10 -9
- package/dist/components/viewers/TableViewer.svelte +47 -30
- package/dist/components/viewers/TableViewer.svelte.d.ts +1 -0
- package/dist/components/viewers/ViewerHeader.svelte +18 -0
- package/dist/components/viewers/ViewerHeader.svelte.d.ts +10 -0
- package/dist/components/viewers/ViewerRouter.svelte +16 -8
- package/dist/components/viewers/ViewerStatus.svelte +19 -0
- package/dist/components/viewers/ViewerStatus.svelte.d.ts +7 -0
- package/dist/components/viewers/ZarrMapViewer.svelte +24 -21
- package/dist/components/viewers/ZarrViewer.svelte +98 -65
- package/dist/components/viewers/cog/ChannelPicker.svelte +83 -0
- package/dist/components/viewers/cog/ChannelPicker.svelte.d.ts +13 -0
- package/dist/components/viewers/cog/PixelInspectorPanel.svelte +87 -0
- package/dist/components/viewers/cog/PixelInspectorPanel.svelte.d.ts +17 -0
- package/dist/components/viewers/cog/buildRgbLayer.d.ts +78 -0
- package/dist/components/viewers/cog/buildRgbLayer.js +176 -0
- package/dist/components/viewers/map/AttributeTable.svelte +7 -7
- package/dist/components/viewers/map/MapContainer.svelte +38 -12
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +109 -83
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +16 -16
- package/dist/components/viewers/stac/StacDatetimeBar.svelte +175 -0
- package/dist/components/viewers/stac/StacDatetimeBar.svelte.d.ts +10 -0
- package/dist/components/viewers/stac/StacFilterPanel.svelte +243 -0
- package/dist/components/viewers/stac/StacFilterPanel.svelte.d.ts +14 -0
- package/dist/components/viewers/stac/StacItemInspector.svelte +223 -0
- package/dist/components/viewers/stac/StacItemInspector.svelte.d.ts +10 -0
- package/dist/components/viewers/stac/StacItemStrip.svelte +228 -0
- package/dist/components/viewers/stac/StacItemStrip.svelte.d.ts +12 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.js +8 -0
- package/dist/file-icons/index.d.ts +1 -1
- package/dist/file-icons/index.js +1 -1
- package/dist/i18n/ar.js +113 -2
- package/dist/i18n/en.js +113 -2
- package/dist/index.d.ts +2 -28
- package/dist/index.js +7 -23
- package/dist/query/engine.d.ts +10 -0
- package/dist/query/source.js +1 -1
- package/dist/query/stac-source-factory.d.ts +65 -0
- package/dist/query/stac-source-factory.js +77 -0
- package/dist/query/stac-source-parquet.d.ts +135 -0
- package/dist/query/stac-source-parquet.js +468 -0
- package/dist/query/wasm.d.ts +8 -0
- package/dist/query/wasm.js +310 -65
- package/dist/storage/presign.js +3 -2
- package/dist/storage/providers.js +7 -6
- package/dist/stores/config.svelte.d.ts +15 -0
- package/dist/stores/config.svelte.js +46 -0
- package/dist/stores/connections.svelte.d.ts +2 -2
- package/dist/stores/connections.svelte.js +1 -2
- package/dist/stores/files.svelte.d.ts +1 -1
- package/dist/stores/files.svelte.js +1 -1
- package/dist/stores/query-history.svelte.js +1 -1
- package/dist/stores/settings.svelte.d.ts +16 -1
- package/dist/stores/settings.svelte.js +104 -48
- package/dist/stores/tabs.svelte.d.ts +3 -0
- package/dist/stores/tabs.svelte.js +17 -0
- package/dist/utils/cog-histogram.d.ts +121 -0
- package/dist/utils/cog-histogram.js +424 -0
- package/dist/utils/cog.d.ts +177 -20
- package/dist/utils/cog.js +361 -76
- package/dist/utils/colormap-sprite.d.ts +0 -9
- package/dist/utils/colormap-sprite.js +0 -21
- package/dist/utils/deck.d.ts +18 -12
- package/dist/utils/deck.js +15 -7
- package/dist/utils/media-query.svelte.d.ts +14 -0
- package/dist/utils/media-query.svelte.js +29 -0
- package/dist/utils/pmtiles-tile.js +2 -2
- package/dist/utils/signed-url-effect.d.ts +7 -0
- package/dist/utils/signed-url-effect.js +19 -0
- package/dist/utils/{url.d.ts → signed-url.d.ts} +15 -1
- package/dist/utils/{url.js → signed-url.js} +32 -10
- package/dist/utils/url-state.d.ts +36 -0
- package/dist/utils/url-state.js +72 -2
- package/dist/utils/zarr-tab.d.ts +1 -2
- package/dist/utils/zarr-tab.js +1 -2
- package/dist/utils/zarr.d.ts +0 -17
- package/dist/utils/zarr.js +1 -45
- package/package.json +55 -84
- package/dist/components/browser/Breadcrumb.svelte +0 -50
- package/dist/components/browser/Breadcrumb.svelte.d.ts +0 -7
- package/dist/components/browser/CreateFolderDialog.svelte +0 -98
- package/dist/components/browser/CreateFolderDialog.svelte.d.ts +0 -6
- package/dist/components/browser/DeleteConfirmDialog.svelte +0 -90
- package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +0 -8
- package/dist/components/browser/DropZone.svelte +0 -83
- package/dist/components/browser/DropZone.svelte.d.ts +0 -7
- package/dist/components/browser/FileBrowser.svelte +0 -252
- package/dist/components/browser/FileBrowser.svelte.d.ts +0 -3
- package/dist/components/browser/FileRow.svelte +0 -117
- package/dist/components/browser/FileRow.svelte.d.ts +0 -9
- package/dist/components/browser/RenameDialog.svelte +0 -101
- package/dist/components/browser/RenameDialog.svelte.d.ts +0 -8
- package/dist/components/browser/SearchBar.svelte +0 -40
- package/dist/components/browser/SearchBar.svelte.d.ts +0 -6
- package/dist/components/browser/UploadButton.svelte +0 -65
- package/dist/components/browser/UploadButton.svelte.d.ts +0 -3
- package/dist/query/stac-geoparquet.d.ts +0 -31
- package/dist/query/stac-geoparquet.js +0 -136
- package/dist/utils/clipboard.d.ts +0 -13
- package/dist/utils/clipboard.js +0 -38
- package/dist/utils/cloud-url.d.ts +0 -27
- package/dist/utils/cloud-url.js +0 -61
- package/dist/utils/cog-pure.d.ts +0 -25
- package/dist/utils/cog-pure.js +0 -35
- package/dist/utils/column-types.d.ts +0 -5
- package/dist/utils/column-types.js +0 -137
- package/dist/utils/connection-identity.d.ts +0 -51
- package/dist/utils/connection-identity.js +0 -97
- package/dist/utils/error.d.ts +0 -8
- package/dist/utils/error.js +0 -12
- package/dist/utils/evidence-context.d.ts +0 -22
- package/dist/utils/evidence-context.js +0 -56
- package/dist/utils/export.d.ts +0 -22
- package/dist/utils/export.js +0 -76
- package/dist/utils/file-sort.d.ts +0 -20
- package/dist/utils/file-sort.js +0 -41
- package/dist/utils/format.d.ts +0 -24
- package/dist/utils/format.js +0 -78
- package/dist/utils/geoarrow.d.ts +0 -32
- package/dist/utils/geoarrow.js +0 -672
- package/dist/utils/geometry-type.d.ts +0 -52
- package/dist/utils/geometry-type.js +0 -76
- package/dist/utils/hex.d.ts +0 -10
- package/dist/utils/hex.js +0 -27
- package/dist/utils/host-detection.d.ts +0 -23
- package/dist/utils/host-detection.js +0 -95
- package/dist/utils/local-storage.d.ts +0 -16
- package/dist/utils/local-storage.js +0 -37
- package/dist/utils/markdown-sql.d.ts +0 -30
- package/dist/utils/markdown-sql.js +0 -72
- package/dist/utils/notebook.d.ts +0 -59
- package/dist/utils/notebook.js +0 -211
- package/dist/utils/parquet-metadata.d.ts +0 -64
- package/dist/utils/parquet-metadata.js +0 -262
- package/dist/utils/stac-geoparquet.d.ts +0 -90
- package/dist/utils/stac-geoparquet.js +0 -223
- package/dist/utils/stac-hydrate.d.ts +0 -38
- package/dist/utils/stac-hydrate.js +0 -243
- package/dist/utils/stac.d.ts +0 -136
- package/dist/utils/stac.js +0 -176
- package/dist/utils/storage-url.d.ts +0 -90
- package/dist/utils/storage-url.js +0 -568
- package/dist/utils/wkb.d.ts +0 -43
- package/dist/utils/wkb.js +0 -359
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Read a stac-geoparquet file through the existing DuckDB-WASM engine and
|
|
3
|
-
* materialize a standard STAC FeatureCollection in memory.
|
|
4
|
-
*
|
|
5
|
-
* Reuses:
|
|
6
|
-
* - `getQueryEngine()` + `queryCancellable`/`query` for the single worker
|
|
7
|
-
* - `resolveTableSourceAsync(tab)` for presigned `signed-s3` URL handling
|
|
8
|
-
* - `stacRowToItem` from `utils/stac-geoparquet.js` for the pure transform
|
|
9
|
-
* - `parseWKB` from `utils/wkb.js` for geometry decoding
|
|
10
|
-
*
|
|
11
|
-
* The returned `FeatureCollection` is the same shape `classifyStac()` returns
|
|
12
|
-
* as `{ kind: 'item-collection', fc }`, so downstream viewers
|
|
13
|
-
* (`StacMosaicViewer`, `MultiCogViewer`) consume it unchanged.
|
|
14
|
-
*/
|
|
15
|
-
import { stacRowToItem } from '../utils/stac-geoparquet.js';
|
|
16
|
-
import { parseWKB } from '../utils/wkb.js';
|
|
17
|
-
import { QueryCancelledError } from './engine.js';
|
|
18
|
-
import { getQueryEngine } from './index.js';
|
|
19
|
-
import { resolveTableSourceAsync } from './source.js';
|
|
20
|
-
const DEFAULT_LIMIT = 2000;
|
|
21
|
-
/**
|
|
22
|
-
* Build the SELECT list. All columns are optional in the stac-geoparquet
|
|
23
|
-
* spec, so we only project what we know we'll use and the spec requires.
|
|
24
|
-
* The optional `proj:*` / `raster:*` / `bands` columns are sniffed from the
|
|
25
|
-
* schema so missing columns don't trigger a DuckDB binder error.
|
|
26
|
-
*/
|
|
27
|
-
function buildSelectList(availableColumns) {
|
|
28
|
-
const required = [
|
|
29
|
-
'id',
|
|
30
|
-
'collection',
|
|
31
|
-
'type',
|
|
32
|
-
'stac_version',
|
|
33
|
-
'stac_extensions',
|
|
34
|
-
'assets',
|
|
35
|
-
'bbox',
|
|
36
|
-
'links'
|
|
37
|
-
];
|
|
38
|
-
const optional = [
|
|
39
|
-
'datetime',
|
|
40
|
-
'proj:code',
|
|
41
|
-
'proj:bbox',
|
|
42
|
-
'proj:transform',
|
|
43
|
-
'proj:shape',
|
|
44
|
-
'raster:spatial_resolution',
|
|
45
|
-
'bands'
|
|
46
|
-
];
|
|
47
|
-
const cols = [];
|
|
48
|
-
for (const name of required) {
|
|
49
|
-
if (availableColumns.has(name))
|
|
50
|
-
cols.push(quoteIdent(name));
|
|
51
|
-
}
|
|
52
|
-
for (const name of optional) {
|
|
53
|
-
if (availableColumns.has(name))
|
|
54
|
-
cols.push(quoteIdent(name));
|
|
55
|
-
}
|
|
56
|
-
// Always project geometry as WKB so parseWKB can decode it regardless of
|
|
57
|
-
// whether DuckDB presents it as the v1.5 GEOMETRY type or a plain BLOB.
|
|
58
|
-
if (availableColumns.has('geometry')) {
|
|
59
|
-
cols.push('ST_AsWKB(geometry) AS geom_wkb');
|
|
60
|
-
}
|
|
61
|
-
return cols.join(', ');
|
|
62
|
-
}
|
|
63
|
-
function quoteIdent(name) {
|
|
64
|
-
return `"${name.replace(/"/g, '""')}"`;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Query a stac-geoparquet tab and return a STAC FeatureCollection whose
|
|
68
|
-
* features are proper STAC Items (assets absolutized, WKB decoded, bbox
|
|
69
|
-
* flattened).
|
|
70
|
-
*
|
|
71
|
-
* @param tab - the tab pointing at the `.parquet` file
|
|
72
|
-
* @param connId - connection id used for DuckDB's httpfs S3 config; pass
|
|
73
|
-
* an empty string for URL-source tabs (DuckDB will use anonymous httpfs)
|
|
74
|
-
*/
|
|
75
|
-
export async function queryStacGeoparquetFeatureCollection(tab, connId, opts = {}) {
|
|
76
|
-
const { signal, limit = DEFAULT_LIMIT } = opts;
|
|
77
|
-
if (signal?.aborted)
|
|
78
|
-
throw new QueryCancelledError();
|
|
79
|
-
const engine = await getQueryEngine();
|
|
80
|
-
const resolved = await resolveTableSourceAsync(tab);
|
|
81
|
-
if (signal?.aborted)
|
|
82
|
-
throw new QueryCancelledError();
|
|
83
|
-
// Discover which optional columns are present so the SELECT list doesn't
|
|
84
|
-
// reference missing columns.
|
|
85
|
-
const schema = await engine.getSchema(connId, resolved);
|
|
86
|
-
if (signal?.aborted)
|
|
87
|
-
throw new QueryCancelledError();
|
|
88
|
-
const available = new Set(schema.map((f) => f.name));
|
|
89
|
-
const selectList = buildSelectList(available);
|
|
90
|
-
if (!available.has('geometry') || !available.has('assets')) {
|
|
91
|
-
throw new Error('Not a stac-geoparquet file (missing geometry or assets column)');
|
|
92
|
-
}
|
|
93
|
-
const sql = `SELECT ${selectList} FROM ${resolved.ref} LIMIT ${limit}`;
|
|
94
|
-
// Prefer cancellable path when the engine exposes it.
|
|
95
|
-
let resultPromise;
|
|
96
|
-
let cancel = null;
|
|
97
|
-
if (engine.queryCancellable) {
|
|
98
|
-
const handle = engine.queryCancellable(connId, sql);
|
|
99
|
-
cancel = handle.cancel;
|
|
100
|
-
resultPromise = handle.result;
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
resultPromise = engine.query(connId, sql);
|
|
104
|
-
}
|
|
105
|
-
const onAbort = () => {
|
|
106
|
-
cancel?.().catch(() => { });
|
|
107
|
-
};
|
|
108
|
-
signal?.addEventListener('abort', onAbort, { once: true });
|
|
109
|
-
let rows;
|
|
110
|
-
try {
|
|
111
|
-
const result = await resultPromise;
|
|
112
|
-
rows = result.rows ?? [];
|
|
113
|
-
}
|
|
114
|
-
finally {
|
|
115
|
-
signal?.removeEventListener('abort', onAbort);
|
|
116
|
-
}
|
|
117
|
-
if (signal?.aborted)
|
|
118
|
-
throw new QueryCancelledError();
|
|
119
|
-
// Asset hrefs in stac-geoparquet are typically written relative to each
|
|
120
|
-
// item's original `self` URL, not the parquet URL. The stactools default
|
|
121
|
-
// layout places each item JSON at `{catalog_dir}/{item.id}/{item.id}.json`,
|
|
122
|
-
// so a per-row base of `{parquet_dir}/{item.id}/` resolves `./foo.tif` to
|
|
123
|
-
// `{parquet_dir}/{item.id}/foo.tif`. Absolute hrefs pass through unchanged
|
|
124
|
-
// via `resolveStacAssetHref`.
|
|
125
|
-
const parquetUrl = resolved.fileUrl ?? tab.path;
|
|
126
|
-
const parquetDir = parquetUrl.replace(/[^/]*(?:\?.*)?$/, '');
|
|
127
|
-
const features = rows.map((row) => {
|
|
128
|
-
const id = typeof row.id === 'string' ? row.id : String(row.id ?? '');
|
|
129
|
-
const itemBase = id ? `${parquetDir}${id}/` : parquetUrl;
|
|
130
|
-
return stacRowToItem(row, itemBase, { wkbParser: parseWKB });
|
|
131
|
-
});
|
|
132
|
-
return {
|
|
133
|
-
type: 'FeatureCollection',
|
|
134
|
-
features
|
|
135
|
-
};
|
|
136
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copy text to clipboard and run a feedback callback for COPY_FEEDBACK_MS.
|
|
3
|
-
* Silently catches clipboard errors (e.g. insecure context).
|
|
4
|
-
*
|
|
5
|
-
* @returns true if copy succeeded, false otherwise.
|
|
6
|
-
*/
|
|
7
|
-
export declare function copyToClipboard(text: string, onFeedback?: (copied: boolean) => void): Promise<boolean>;
|
|
8
|
-
/**
|
|
9
|
-
* Wire click-to-copy on all elements matching `selector` inside `root`.
|
|
10
|
-
* Each element must have `data-code` (URI-encoded) with the text to copy.
|
|
11
|
-
* Adds/removes a `copied` CSS class for visual feedback.
|
|
12
|
-
*/
|
|
13
|
-
export declare function wireCodeCopyButtons(root: Element, selector: string): void;
|
package/dist/utils/clipboard.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { COPY_FEEDBACK_MS } from '../constants.js';
|
|
2
|
-
/**
|
|
3
|
-
* Copy text to clipboard and run a feedback callback for COPY_FEEDBACK_MS.
|
|
4
|
-
* Silently catches clipboard errors (e.g. insecure context).
|
|
5
|
-
*
|
|
6
|
-
* @returns true if copy succeeded, false otherwise.
|
|
7
|
-
*/
|
|
8
|
-
export async function copyToClipboard(text, onFeedback) {
|
|
9
|
-
try {
|
|
10
|
-
await navigator.clipboard.writeText(text);
|
|
11
|
-
onFeedback?.(true);
|
|
12
|
-
setTimeout(() => onFeedback?.(false), COPY_FEEDBACK_MS);
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Wire click-to-copy on all elements matching `selector` inside `root`.
|
|
21
|
-
* Each element must have `data-code` (URI-encoded) with the text to copy.
|
|
22
|
-
* Adds/removes a `copied` CSS class for visual feedback.
|
|
23
|
-
*/
|
|
24
|
-
export function wireCodeCopyButtons(root, selector) {
|
|
25
|
-
for (const btn of root.querySelectorAll(selector)) {
|
|
26
|
-
btn.addEventListener('click', async () => {
|
|
27
|
-
const code = decodeURIComponent(btn.dataset.code ?? '');
|
|
28
|
-
try {
|
|
29
|
-
await navigator.clipboard.writeText(code);
|
|
30
|
-
btn.classList.add('copied');
|
|
31
|
-
setTimeout(() => btn.classList.remove('copied'), COPY_FEEDBACK_MS);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
// clipboard not available
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cloud storage protocol URL utilities — pure TS, no Svelte dependency.
|
|
3
|
-
*
|
|
4
|
-
* Converts cloud protocol URLs (s3://, gs://) to HTTPS URLs for browser access.
|
|
5
|
-
* Provider-aware native scheme lookup.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Map provider to its native URI scheme prefix.
|
|
9
|
-
* Derived from the registry's `schemes` array (first entry is the primary scheme).
|
|
10
|
-
* Falls back to 's3' for providers without a scheme (S3-compatible).
|
|
11
|
-
*/
|
|
12
|
-
export declare function getNativeScheme(provider: string): string;
|
|
13
|
-
/**
|
|
14
|
-
* Safely decode a percent-encoded URI component.
|
|
15
|
-
* Returns the original string if decoding fails (malformed sequences).
|
|
16
|
-
*/
|
|
17
|
-
export declare function safeDecodeURIComponent(s: string): string;
|
|
18
|
-
/**
|
|
19
|
-
* Convert a cloud storage protocol URL (s3://, gs://) to an HTTPS URL
|
|
20
|
-
* for browser access. Returns the original URL if already HTTP(S) or unknown.
|
|
21
|
-
*
|
|
22
|
-
* Supported:
|
|
23
|
-
* - `s3://bucket/key` → `https://s3.{region}.amazonaws.com/{bucket}/{key}`
|
|
24
|
-
* (region auto-detected from bucket name when possible)
|
|
25
|
-
* - `gs://bucket/key` → `https://storage.googleapis.com/{bucket}/{key}`
|
|
26
|
-
*/
|
|
27
|
-
export declare function resolveCloudUrl(url: string): string;
|
package/dist/utils/cloud-url.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cloud storage protocol URL utilities — pure TS, no Svelte dependency.
|
|
3
|
-
*
|
|
4
|
-
* Converts cloud protocol URLs (s3://, gs://) to HTTPS URLs for browser access.
|
|
5
|
-
* Provider-aware native scheme lookup.
|
|
6
|
-
*/
|
|
7
|
-
import { buildProviderBaseUrl, PROVIDERS } from '../storage/providers.js';
|
|
8
|
-
/** AWS region pattern — matches prefixes like "us-west-2", "eu-central-1", etc. */
|
|
9
|
-
const AWS_REGION_RE = /^(us|eu|ap|sa|ca|me|af|il)-(north|south|east|west|central|northeast|southeast|northwest|southwest)-\d+/;
|
|
10
|
-
/**
|
|
11
|
-
* Map provider to its native URI scheme prefix.
|
|
12
|
-
* Derived from the registry's `schemes` array (first entry is the primary scheme).
|
|
13
|
-
* Falls back to 's3' for providers without a scheme (S3-compatible).
|
|
14
|
-
*/
|
|
15
|
-
export function getNativeScheme(provider) {
|
|
16
|
-
const def = PROVIDERS[provider];
|
|
17
|
-
if (def?.schemes.length)
|
|
18
|
-
return def.schemes[0];
|
|
19
|
-
return 's3';
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Safely decode a percent-encoded URI component.
|
|
23
|
-
* Returns the original string if decoding fails (malformed sequences).
|
|
24
|
-
*/
|
|
25
|
-
export function safeDecodeURIComponent(s) {
|
|
26
|
-
try {
|
|
27
|
-
return decodeURIComponent(s);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return s;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Convert a cloud storage protocol URL (s3://, gs://) to an HTTPS URL
|
|
35
|
-
* for browser access. Returns the original URL if already HTTP(S) or unknown.
|
|
36
|
-
*
|
|
37
|
-
* Supported:
|
|
38
|
-
* - `s3://bucket/key` → `https://s3.{region}.amazonaws.com/{bucket}/{key}`
|
|
39
|
-
* (region auto-detected from bucket name when possible)
|
|
40
|
-
* - `gs://bucket/key` → `https://storage.googleapis.com/{bucket}/{key}`
|
|
41
|
-
*/
|
|
42
|
-
export function resolveCloudUrl(url) {
|
|
43
|
-
// S3 / S3-compatible: s3://, s3a://, s3n://
|
|
44
|
-
const s3Match = url.match(/^s3[an]?:\/\/([^/]+)\/?(.*)$/);
|
|
45
|
-
if (s3Match) {
|
|
46
|
-
const [, bucket, key] = s3Match;
|
|
47
|
-
// Detect region from bucket name (e.g. "us-west-2.opendata.source.coop")
|
|
48
|
-
const regionMatch = bucket.match(AWS_REGION_RE);
|
|
49
|
-
const region = regionMatch ? regionMatch[0] : 'us-east-1';
|
|
50
|
-
const base = buildProviderBaseUrl('s3', '', bucket, region);
|
|
51
|
-
return key ? `${base}/${key}` : base;
|
|
52
|
-
}
|
|
53
|
-
// Google Cloud Storage: gs://, gcs://
|
|
54
|
-
const gcsMatch = url.match(/^gcs?:\/\/([^/]+)\/?(.*)$/);
|
|
55
|
-
if (gcsMatch) {
|
|
56
|
-
const [, bucket, key] = gcsMatch;
|
|
57
|
-
const base = buildProviderBaseUrl('gcs', '', bucket, '');
|
|
58
|
-
return key ? `${base}/${key}` : base;
|
|
59
|
-
}
|
|
60
|
-
return url;
|
|
61
|
-
}
|
package/dist/utils/cog-pure.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/** SampleFormat tag value → human label. */
|
|
2
|
-
export declare const SF_LABELS: Record<number, string>;
|
|
3
|
-
export interface GeoBounds {
|
|
4
|
-
west: number;
|
|
5
|
-
south: number;
|
|
6
|
-
east: number;
|
|
7
|
-
north: number;
|
|
8
|
-
}
|
|
9
|
-
export interface CogInfo {
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
bandCount: number;
|
|
13
|
-
dataType: string;
|
|
14
|
-
bounds: GeoBounds;
|
|
15
|
-
downsampled?: boolean;
|
|
16
|
-
}
|
|
17
|
-
/** Safely clamp a number to a range, treating NaN/Infinity as the fallback. */
|
|
18
|
-
export declare function safeClamp(v: number, lo: number, hi: number, fallback: number): number;
|
|
19
|
-
/** Clamp geographic bounds to valid MapLibre web-Mercator range. */
|
|
20
|
-
export declare function clampBounds(b: GeoBounds): GeoBounds;
|
|
21
|
-
/**
|
|
22
|
-
* Build a data-type label from GeoTIFF sample format and bits per sample.
|
|
23
|
-
* e.g. "uint8", "float32", "int16"
|
|
24
|
-
*/
|
|
25
|
-
export declare function buildDataTypeLabel(sampleFormat: number, bitsPerSample: number): string;
|
package/dist/utils/cog-pure.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Dependency-free subset of `cog.ts` so that `@walkthru-earth/objex-utils`
|
|
2
|
-
// can re-export these helpers without dragging in `@developmentseed/epsg`,
|
|
3
|
-
// `@developmentseed/geotiff`, `@developmentseed/proj`, `proj4`, or
|
|
4
|
-
// `maplibre-gl`. tsup preserves bare side-effect imports from externalized
|
|
5
|
-
// modules even when all named bindings are tree-shaken, so the pure surface
|
|
6
|
-
// MUST live in a module that has zero heavy imports.
|
|
7
|
-
/** SampleFormat tag value → human label. */
|
|
8
|
-
export const SF_LABELS = {
|
|
9
|
-
1: 'uint',
|
|
10
|
-
2: 'int',
|
|
11
|
-
3: 'float',
|
|
12
|
-
4: 'void',
|
|
13
|
-
5: 'complex int',
|
|
14
|
-
6: 'complex float'
|
|
15
|
-
};
|
|
16
|
-
/** Safely clamp a number to a range, treating NaN/Infinity as the fallback. */
|
|
17
|
-
export function safeClamp(v, lo, hi, fallback) {
|
|
18
|
-
return Number.isFinite(v) ? Math.max(lo, Math.min(hi, v)) : fallback;
|
|
19
|
-
}
|
|
20
|
-
/** Clamp geographic bounds to valid MapLibre web-Mercator range. */
|
|
21
|
-
export function clampBounds(b) {
|
|
22
|
-
return {
|
|
23
|
-
west: safeClamp(b.west, -180, 180, -180),
|
|
24
|
-
south: safeClamp(b.south, -85.051129, 85.051129, -85.051129),
|
|
25
|
-
east: safeClamp(b.east, -180, 180, 180),
|
|
26
|
-
north: safeClamp(b.north, -85.051129, 85.051129, 85.051129)
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Build a data-type label from GeoTIFF sample format and bits per sample.
|
|
31
|
-
* e.g. "uint8", "float32", "int16"
|
|
32
|
-
*/
|
|
33
|
-
export function buildDataTypeLabel(sampleFormat, bitsPerSample) {
|
|
34
|
-
return `${SF_LABELS[sampleFormat] ?? `sf${sampleFormat}`}${bitsPerSample ?? ''}`;
|
|
35
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export type TypeCategory = 'number' | 'string' | 'date' | 'boolean' | 'geo' | 'binary' | 'json' | 'other';
|
|
2
|
-
export declare function classifyType(duckdbType: string): TypeCategory;
|
|
3
|
-
export declare function typeColor(category: TypeCategory): string;
|
|
4
|
-
export declare function typeBadgeClass(category: TypeCategory): string;
|
|
5
|
-
export declare function typeLabel(category: TypeCategory): string;
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
const NUMBER_TYPES = [
|
|
2
|
-
'TINYINT',
|
|
3
|
-
'SMALLINT',
|
|
4
|
-
'INTEGER',
|
|
5
|
-
'BIGINT',
|
|
6
|
-
'HUGEINT',
|
|
7
|
-
'UTINYINT',
|
|
8
|
-
'USMALLINT',
|
|
9
|
-
'UINTEGER',
|
|
10
|
-
'UBIGINT',
|
|
11
|
-
'FLOAT',
|
|
12
|
-
'DOUBLE',
|
|
13
|
-
'DECIMAL',
|
|
14
|
-
'NUMERIC',
|
|
15
|
-
'REAL',
|
|
16
|
-
'INT',
|
|
17
|
-
'INT1',
|
|
18
|
-
'INT2',
|
|
19
|
-
'INT4',
|
|
20
|
-
'INT8',
|
|
21
|
-
'SIGNED',
|
|
22
|
-
'SHORT',
|
|
23
|
-
'LONG'
|
|
24
|
-
];
|
|
25
|
-
const STRING_TYPES = ['VARCHAR', 'TEXT', 'STRING', 'CHAR', 'BPCHAR', 'NAME', 'UUID', 'ENUM'];
|
|
26
|
-
const DATE_TYPES = [
|
|
27
|
-
'DATE',
|
|
28
|
-
'TIME',
|
|
29
|
-
'TIMESTAMP',
|
|
30
|
-
'TIMESTAMP_S',
|
|
31
|
-
'TIMESTAMP_MS',
|
|
32
|
-
'TIMESTAMP_NS',
|
|
33
|
-
'TIMESTAMP WITH TIME ZONE',
|
|
34
|
-
'TIMESTAMPTZ',
|
|
35
|
-
'INTERVAL',
|
|
36
|
-
'TIMESTAMP_TZ'
|
|
37
|
-
];
|
|
38
|
-
const BOOLEAN_TYPES = ['BOOLEAN', 'BOOL', 'LOGICAL'];
|
|
39
|
-
const GEO_TYPES = [
|
|
40
|
-
'GEOMETRY',
|
|
41
|
-
'POINT',
|
|
42
|
-
'LINESTRING',
|
|
43
|
-
'POLYGON',
|
|
44
|
-
'MULTIPOINT',
|
|
45
|
-
'MULTILINESTRING',
|
|
46
|
-
'MULTIPOLYGON',
|
|
47
|
-
'GEOMETRYCOLLECTION',
|
|
48
|
-
'WKB_GEOMETRY'
|
|
49
|
-
];
|
|
50
|
-
const BINARY_TYPES = ['BLOB', 'BYTEA', 'BINARY', 'VARBINARY'];
|
|
51
|
-
const JSON_TYPES = ['JSON', 'JSONB'];
|
|
52
|
-
export function classifyType(duckdbType) {
|
|
53
|
-
const upper = duckdbType.toUpperCase().trim();
|
|
54
|
-
// Handle parameterized types like DECIMAL(18,3), VARCHAR(100)
|
|
55
|
-
const base = upper.replace(/\(.*\)/, '').trim();
|
|
56
|
-
if (NUMBER_TYPES.includes(base))
|
|
57
|
-
return 'number';
|
|
58
|
-
if (STRING_TYPES.includes(base))
|
|
59
|
-
return 'string';
|
|
60
|
-
if (DATE_TYPES.includes(base))
|
|
61
|
-
return 'date';
|
|
62
|
-
if (BOOLEAN_TYPES.includes(base))
|
|
63
|
-
return 'boolean';
|
|
64
|
-
if (GEO_TYPES.includes(base))
|
|
65
|
-
return 'geo';
|
|
66
|
-
if (BINARY_TYPES.includes(base))
|
|
67
|
-
return 'binary';
|
|
68
|
-
if (JSON_TYPES.includes(base))
|
|
69
|
-
return 'json';
|
|
70
|
-
// Compound types
|
|
71
|
-
if (base.startsWith('STRUCT') || base.startsWith('MAP') || base.startsWith('UNION'))
|
|
72
|
-
return 'json';
|
|
73
|
-
if (base.endsWith('[]') || base.startsWith('LIST'))
|
|
74
|
-
return 'json';
|
|
75
|
-
// Fallback checks
|
|
76
|
-
if (upper.includes('INT') ||
|
|
77
|
-
upper.includes('FLOAT') ||
|
|
78
|
-
upper.includes('DOUBLE') ||
|
|
79
|
-
upper.includes('DECIMAL') ||
|
|
80
|
-
upper.includes('NUMERIC'))
|
|
81
|
-
return 'number';
|
|
82
|
-
if (upper.includes('CHAR') || upper.includes('TEXT') || upper.includes('STRING'))
|
|
83
|
-
return 'string';
|
|
84
|
-
if (upper.includes('TIME') || upper.includes('DATE'))
|
|
85
|
-
return 'date';
|
|
86
|
-
if (upper.includes('BOOL'))
|
|
87
|
-
return 'boolean';
|
|
88
|
-
if (upper.includes('GEOMETRY') || upper.includes('GEO') || upper.includes('WKB'))
|
|
89
|
-
return 'geo';
|
|
90
|
-
if (upper.includes('BLOB') || upper.includes('BINARY'))
|
|
91
|
-
return 'binary';
|
|
92
|
-
if (upper.includes('JSON') ||
|
|
93
|
-
upper.includes('STRUCT') ||
|
|
94
|
-
upper.includes('MAP') ||
|
|
95
|
-
upper.includes('LIST'))
|
|
96
|
-
return 'json';
|
|
97
|
-
return 'other';
|
|
98
|
-
}
|
|
99
|
-
const TYPE_COLORS = {
|
|
100
|
-
number: 'text-blue-500',
|
|
101
|
-
string: 'text-green-500',
|
|
102
|
-
date: 'text-amber-500',
|
|
103
|
-
boolean: 'text-purple-500',
|
|
104
|
-
geo: 'text-teal-500',
|
|
105
|
-
binary: 'text-zinc-500',
|
|
106
|
-
json: 'text-orange-500',
|
|
107
|
-
other: 'text-zinc-400'
|
|
108
|
-
};
|
|
109
|
-
const TYPE_BADGE_CLASSES = {
|
|
110
|
-
number: 'bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/20',
|
|
111
|
-
string: 'bg-green-500/10 text-green-600 dark:text-green-400 border-green-500/20',
|
|
112
|
-
date: 'bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20',
|
|
113
|
-
boolean: 'bg-purple-500/10 text-purple-600 dark:text-purple-400 border-purple-500/20',
|
|
114
|
-
geo: 'bg-teal-500/10 text-teal-600 dark:text-teal-400 border-teal-500/20',
|
|
115
|
-
binary: 'bg-zinc-500/10 text-zinc-600 dark:text-zinc-400 border-zinc-500/20',
|
|
116
|
-
json: 'bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/20',
|
|
117
|
-
other: 'bg-zinc-500/10 text-zinc-500 dark:text-zinc-400 border-zinc-500/20'
|
|
118
|
-
};
|
|
119
|
-
const TYPE_LABELS = {
|
|
120
|
-
number: '#',
|
|
121
|
-
string: 'Aa',
|
|
122
|
-
date: 'dt',
|
|
123
|
-
boolean: 'T/F',
|
|
124
|
-
geo: 'geo',
|
|
125
|
-
binary: '01',
|
|
126
|
-
json: '{}',
|
|
127
|
-
other: '?'
|
|
128
|
-
};
|
|
129
|
-
export function typeColor(category) {
|
|
130
|
-
return TYPE_COLORS[category];
|
|
131
|
-
}
|
|
132
|
-
export function typeBadgeClass(category) {
|
|
133
|
-
return TYPE_BADGE_CLASSES[category];
|
|
134
|
-
}
|
|
135
|
-
export function typeLabel(category) {
|
|
136
|
-
return TYPE_LABELS[category];
|
|
137
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical connection identity.
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for deciding when two connection configs point at
|
|
5
|
-
* the same bucket. Used by the connections store to deduplicate auto-detect,
|
|
6
|
-
* manual add, and edit flows, so one physical bucket never ends up with
|
|
7
|
-
* multiple competing local records.
|
|
8
|
-
*
|
|
9
|
-
* Identity rules, per provider:
|
|
10
|
-
*
|
|
11
|
-
* azure → (provider, endpoint, bucket) endpoint carries the account
|
|
12
|
-
* gcs → (provider, bucket) GCS bucket names are global
|
|
13
|
-
* s3 → (provider, bucket, region) AWS native: same bucket name
|
|
14
|
-
* can exist in exactly one region,
|
|
15
|
-
* but the region is load-bearing
|
|
16
|
-
* for signing, so a paste with a
|
|
17
|
-
* different region is a distinct
|
|
18
|
-
* connection until the user merges
|
|
19
|
-
* other → (provider, endpoint, bucket) r2, b2, minio, wasabi, storj,
|
|
20
|
-
* digitalocean, contabo, hetzner,
|
|
21
|
-
* linode, ovhcloud, custom
|
|
22
|
-
*
|
|
23
|
-
* Endpoint normalization is aggressive: scheme + host + non-default port +
|
|
24
|
-
* pathname, with trailing slashes and default ports stripped, host lowercased.
|
|
25
|
-
* That collapses the common trip hazards — http vs https, :443 vs empty,
|
|
26
|
-
* trailing slash drift, mixed case host.
|
|
27
|
-
*/
|
|
28
|
-
import type { ProviderId } from '../storage/providers.js';
|
|
29
|
-
export interface ConnectionIdentityInput {
|
|
30
|
-
provider: string;
|
|
31
|
-
endpoint: string;
|
|
32
|
-
bucket: string;
|
|
33
|
-
region: string;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Normalize an endpoint URL to a canonical form suitable for equality checks.
|
|
37
|
-
* Empty / whitespace-only input returns `''` (the "no endpoint" sentinel).
|
|
38
|
-
* Non-URL strings are lowercased and stripped of trailing slashes as a best
|
|
39
|
-
* effort so the comparison is still deterministic.
|
|
40
|
-
*/
|
|
41
|
-
export declare function normalizeEndpoint(raw: string | undefined | null): string;
|
|
42
|
-
/** Collapse unknown / empty providers to `'s3'`; otherwise lowercase. */
|
|
43
|
-
export declare function normalizeProvider(provider: string | undefined | null): ProviderId;
|
|
44
|
-
/**
|
|
45
|
-
* Produce a canonical key for a connection's identity. Two connection
|
|
46
|
-
* configs with the same identity key point at the same physical bucket.
|
|
47
|
-
* Returns `''` when the config is too incomplete to identify a bucket.
|
|
48
|
-
*/
|
|
49
|
-
export declare function connectionIdentityKey(input: ConnectionIdentityInput): string;
|
|
50
|
-
/** Convenience: true when both inputs share the same non-empty identity. */
|
|
51
|
-
export declare function isSameConnectionIdentity(a: ConnectionIdentityInput, b: ConnectionIdentityInput): boolean;
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical connection identity.
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for deciding when two connection configs point at
|
|
5
|
-
* the same bucket. Used by the connections store to deduplicate auto-detect,
|
|
6
|
-
* manual add, and edit flows, so one physical bucket never ends up with
|
|
7
|
-
* multiple competing local records.
|
|
8
|
-
*
|
|
9
|
-
* Identity rules, per provider:
|
|
10
|
-
*
|
|
11
|
-
* azure → (provider, endpoint, bucket) endpoint carries the account
|
|
12
|
-
* gcs → (provider, bucket) GCS bucket names are global
|
|
13
|
-
* s3 → (provider, bucket, region) AWS native: same bucket name
|
|
14
|
-
* can exist in exactly one region,
|
|
15
|
-
* but the region is load-bearing
|
|
16
|
-
* for signing, so a paste with a
|
|
17
|
-
* different region is a distinct
|
|
18
|
-
* connection until the user merges
|
|
19
|
-
* other → (provider, endpoint, bucket) r2, b2, minio, wasabi, storj,
|
|
20
|
-
* digitalocean, contabo, hetzner,
|
|
21
|
-
* linode, ovhcloud, custom
|
|
22
|
-
*
|
|
23
|
-
* Endpoint normalization is aggressive: scheme + host + non-default port +
|
|
24
|
-
* pathname, with trailing slashes and default ports stripped, host lowercased.
|
|
25
|
-
* That collapses the common trip hazards — http vs https, :443 vs empty,
|
|
26
|
-
* trailing slash drift, mixed case host.
|
|
27
|
-
*/
|
|
28
|
-
const DEFAULT_PORTS = {
|
|
29
|
-
'https:': '443',
|
|
30
|
-
'http:': '80'
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Normalize an endpoint URL to a canonical form suitable for equality checks.
|
|
34
|
-
* Empty / whitespace-only input returns `''` (the "no endpoint" sentinel).
|
|
35
|
-
* Non-URL strings are lowercased and stripped of trailing slashes as a best
|
|
36
|
-
* effort so the comparison is still deterministic.
|
|
37
|
-
*/
|
|
38
|
-
export function normalizeEndpoint(raw) {
|
|
39
|
-
if (!raw)
|
|
40
|
-
return '';
|
|
41
|
-
const trimmed = raw.trim();
|
|
42
|
-
if (!trimmed)
|
|
43
|
-
return '';
|
|
44
|
-
try {
|
|
45
|
-
const url = new URL(trimmed);
|
|
46
|
-
const scheme = url.protocol.toLowerCase();
|
|
47
|
-
const host = url.hostname.toLowerCase();
|
|
48
|
-
const defaultPort = DEFAULT_PORTS[scheme] ?? '';
|
|
49
|
-
const port = url.port && url.port !== defaultPort ? `:${url.port}` : '';
|
|
50
|
-
const path = url.pathname.replace(/\/+$/, '');
|
|
51
|
-
return `${scheme}//${host}${port}${path}`;
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return trimmed.toLowerCase().replace(/\/+$/, '');
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
/** Collapse unknown / empty providers to `'s3'`; otherwise lowercase. */
|
|
58
|
-
export function normalizeProvider(provider) {
|
|
59
|
-
if (!provider)
|
|
60
|
-
return 's3';
|
|
61
|
-
const p = provider.trim().toLowerCase();
|
|
62
|
-
if (!p || p === 'unknown')
|
|
63
|
-
return 's3';
|
|
64
|
-
return p;
|
|
65
|
-
}
|
|
66
|
-
/** Bucket names are case-sensitive on some backends, so preserve case. */
|
|
67
|
-
function normalizeBucket(bucket) {
|
|
68
|
-
return (bucket ?? '').trim().replace(/^\/+|\/+$/g, '');
|
|
69
|
-
}
|
|
70
|
-
function normalizeRegion(region) {
|
|
71
|
-
return (region ?? '').trim().toLowerCase();
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Produce a canonical key for a connection's identity. Two connection
|
|
75
|
-
* configs with the same identity key point at the same physical bucket.
|
|
76
|
-
* Returns `''` when the config is too incomplete to identify a bucket.
|
|
77
|
-
*/
|
|
78
|
-
export function connectionIdentityKey(input) {
|
|
79
|
-
const provider = normalizeProvider(input.provider);
|
|
80
|
-
const bucket = normalizeBucket(input.bucket);
|
|
81
|
-
if (!bucket)
|
|
82
|
-
return '';
|
|
83
|
-
const endpoint = normalizeEndpoint(input.endpoint);
|
|
84
|
-
const region = normalizeRegion(input.region);
|
|
85
|
-
if (provider === 'azure')
|
|
86
|
-
return `azure|${endpoint}|${bucket}`;
|
|
87
|
-
if (provider === 'gcs')
|
|
88
|
-
return `gcs|${bucket}`;
|
|
89
|
-
if (provider === 's3' && !endpoint)
|
|
90
|
-
return `s3|${bucket}|${region}`;
|
|
91
|
-
return `${provider}|${endpoint}|${bucket}`;
|
|
92
|
-
}
|
|
93
|
-
/** Convenience: true when both inputs share the same non-empty identity. */
|
|
94
|
-
export function isSameConnectionIdentity(a, b) {
|
|
95
|
-
const key = connectionIdentityKey(a);
|
|
96
|
-
return key !== '' && key === connectionIdentityKey(b);
|
|
97
|
-
}
|
package/dist/utils/error.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared error handling for async viewer load operations.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Extract an error message from an unknown caught value.
|
|
6
|
-
* Returns null for AbortError (caller should silently return).
|
|
7
|
-
*/
|
|
8
|
-
export declare function handleLoadError(err: unknown): string | null;
|
package/dist/utils/error.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared error handling for async viewer load operations.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Extract an error message from an unknown caught value.
|
|
6
|
-
* Returns null for AbortError (caller should silently return).
|
|
7
|
-
*/
|
|
8
|
-
export function handleLoadError(err) {
|
|
9
|
-
if (err instanceof DOMException && err.name === 'AbortError')
|
|
10
|
-
return null;
|
|
11
|
-
return err instanceof Error ? err.message : String(err);
|
|
12
|
-
}
|