@walkthru-earth/objex-utils 1.2.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/docs/cog.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Cloud-Optimized GeoTIFF (COG) helpers
2
2
 
3
- Pure helpers plus lazy wrappers for rendering Cloud-Optimized GeoTIFFs with [`@developmentseed/deck.gl-geotiff`](https://github.com/developmentseed/deck.gl-geotiff) v0.5 and MapLibre GL.
4
-
5
- The "pure" subset (types, safe-math, data-type labels, color ramps) has no native dependencies. The rendering-oriented functions pull in `@developmentseed/geotiff`, `@developmentseed/deck.gl-geotiff`, `maplibre-gl`, `proj4`, and `@developmentseed/proj` — treat all of those as **optional** peers.
3
+ Pure, framework-agnostic helpers for working with Cloud-Optimized GeoTIFF metadata and bounds. No Svelte, MapLibre, deck.gl, or GeoTIFF library dependency.
6
4
 
7
5
  Source: `src/lib/utils/cog.ts`.
8
6
 
7
+ > The render-pipeline helpers (`selectCogPipeline`, `createConfigurableGetTileData`, `normalizeCogGeotiff`, `createEpsgResolver`, `fitCogBounds`, `renderNonTiledBitmap`, etc.) live in the same source file but are **not** re-exported from `@walkthru-earth/objex-utils` because they pull in `@developmentseed/deck.gl-geotiff`, `@developmentseed/geotiff`, `@developmentseed/proj`, `proj4`, and `maplibre-gl`. If you need them, depend on the full Svelte package [`@walkthru-earth/objex`](https://www.npmjs.com/package/@walkthru-earth/objex) (they are re-exported from `src/lib/index.ts`) and install those optional peers yourself.
8
+
9
9
  ## Types
10
10
 
11
11
  ### `GeoBounds`
@@ -32,33 +32,7 @@ interface CogInfo {
32
32
  }
33
33
  ```
34
34
 
35
- ### `BandConfig`
36
-
37
- ```ts
38
- interface BandConfig {
39
- mode: 'rgb' | 'single';
40
- rBand: number; // 0-indexed
41
- gBand: number;
42
- bBand: number;
43
- band: number; // single-band mode selection
44
- colorRamp: ColorRampId;
45
- }
46
- ```
47
-
48
- ### `RescaleConfig`
49
-
50
- ```ts
51
- interface RescaleConfig {
52
- min: number;
53
- max: number;
54
- }
55
- ```
56
-
57
- ### `CogTagInfo` / `ResolvedCogPipeline`
58
-
59
- Internal-but-exported descriptors returned by `inspectCogTags` / `selectCogPipeline`. See source for the full field list; the common shape is "metadata about which rendering pipeline should be used and why."
60
-
61
- ## Pure helpers (no peer deps)
35
+ ## Constants
62
36
 
63
37
  ### `SF_LABELS`
64
38
 
@@ -71,6 +45,8 @@ const SF_LABELS: Record<number, string> = {
71
45
 
72
46
  Human labels for the GeoTIFF SampleFormat tag.
73
47
 
48
+ ## Functions
49
+
74
50
  ### `safeClamp(v, lo, hi, fallback)`
75
51
 
76
52
  ```ts
@@ -98,206 +74,19 @@ function buildDataTypeLabel(
98
74
 
99
75
  Combine the GeoTIFF `SampleFormat` tag with `BitsPerSample` into `'uint8'`, `'int16'`, `'float32'`, etc.
100
76
 
101
- ### `defaultBandConfig(bandCount, sampleFormat)`
102
-
103
- ```ts
104
- function defaultBandConfig(bandCount: number, sampleFormat: number): BandConfig
105
- ```
106
-
107
- Sensible initial band config: RGB mode for ≥3 bands, single-band with a terrain ramp for int/float single-band imagery.
108
-
109
- ### `isDefaultBandConfig(config, bandCount, sampleFormat)`
110
-
111
- ```ts
112
- function isDefaultBandConfig(
113
- config: BandConfig,
114
- bandCount: number,
115
- sampleFormat: number
116
- ): boolean
117
- ```
118
-
119
- `true` when `config` equals the default for this COG — used to short-circuit custom-pipeline selection.
120
-
121
- ### Color ramps
122
-
123
- ```ts
124
- type ColorRampId = 'grayscale' | 'terrain' | 'viridis' | 'magma' | 'turbo' | 'spectral';
125
-
126
- const COLOR_RAMP_STOPS: Record<ColorRampId, [number, number, number][]>;
127
-
128
- function interpolateRamp(
129
- stops: [number, number, number][],
130
- t: number
131
- ): [number, number, number];
132
-
133
- function rampToGradientCss(id: ColorRampId): string;
134
- ```
135
-
136
- `interpolateRamp(stops, t)` returns an RGB triple for normalized `t ∈ [0, 1]` (clamped). `rampToGradientCss` produces a CSS `linear-gradient(...)` string for UI previews.
137
-
138
- ## Pipeline helpers (require peer deps)
139
-
140
- ### `inspectCogTags(geotiff)`
141
-
142
- ```ts
143
- function inspectCogTags(geotiff: GeoTIFF): CogTagInfo
144
- ```
145
-
146
- Centralized reader for the TIFF tags that determine which render pipeline to use (Photometric.Palette, SampleFormat, ColorMap, etc.).
147
-
148
- ### `needsCustomPipeline(geotiff)`
149
-
150
- ```ts
151
- function needsCustomPipeline(geotiff: GeoTIFF): boolean
152
- ```
153
-
154
- `true` when the library's `inferRenderPipeline` can't handle this COG (non-uint sample formats). Triggers the custom JS pipeline.
155
-
156
- ### `needsCustomPipelineForConfig(geotiff, config)`
157
-
158
- ```ts
159
- function needsCustomPipelineForConfig(
160
- geotiff: GeoTIFF,
161
- config: BandConfig
162
- ): boolean
163
- ```
164
-
165
- `true` when `config` deviates from what the library default pipeline supports (non-standard RGB band order, single-band mode, non-uint, non-palette).
166
-
167
- ### `createCustomGetTileData(geotiff)` / `customRenderTile(data)`
168
-
169
- ```ts
170
- function createCustomGetTileData(
171
- geotiff: GeoTIFF
172
- ): (image, options) => Promise<CustomTileData>;
173
-
174
- function customRenderTile(data: CustomTileData): { image: ImageData };
175
- ```
176
-
177
- Band-0-only fallback path for non-uint COGs. Uses GDAL statistics when available, otherwise per-tile adaptive stretch, and applies the `terrain` color ramp.
178
-
179
- ### `createConfigurableGetTileData(geotiff, config)`
180
-
181
- ```ts
182
- function createConfigurableGetTileData(
183
- geotiff: GeoTIFF,
184
- config: BandConfig
185
- ): (image, options) => Promise<CustomTileData>
186
- ```
187
-
188
- Band-selectable variant. Honors `BandConfig.mode` (`'rgb'` vs `'single'`) and `colorRamp`.
189
-
190
- ### `isRescaleActive(cfg)` / `createRescaledPipeline(geotiff, rescale)`
191
-
192
- ```ts
193
- function isRescaleActive(cfg: RescaleConfig): boolean;
194
-
195
- function createRescaledPipeline(
196
- geotiff: GeoTIFF,
197
- rescale: RescaleConfig
198
- ): { getTileData: Function; renderTile: Function };
199
- ```
200
-
201
- GPU-side LinearRescale module appended to the library default uint pipeline. Only meaningful for uint COGs whose shape / colormap falls inside the library default — see `selectCogPipeline` for the dispatch rules.
202
-
203
- ### `selectCogPipeline(geotiff, opts?)`
204
-
205
- ```ts
206
- function selectCogPipeline(
207
- geotiff: GeoTIFF,
208
- opts?: SelectCogPipelineOptions
209
- ): ResolvedCogPipeline
210
- ```
211
-
212
- Single entry point that returns the correct `{ getTileData, renderTile }` pair for a given COG + config. Four outcomes in priority order:
213
-
214
- 1. Custom configurable — band swap or color ramp change is active and the config is non-default.
215
- 2. Custom non-uint — Int/Float COG without an explicit config yet.
216
- 3. Library default + LinearRescale — uint COG with `rescale` active.
217
- 4. Library default — everything else (empty object is returned; `COGLayer` uses its built-ins).
218
-
219
- ### `normalizeCogGeotiff(geotiff)`
220
-
221
- ```ts
222
- function normalizeCogGeotiff(geotiff: GeoTIFF): void
223
- ```
224
-
225
- Apply in-place upstream workarounds:
226
-
227
- - Drop overview IFDs smaller than one tile (cause proj4 NaN on polar projections).
228
- - Clamp EPSG:4326 bbox to ±85.051129° latitude (Web Mercator safe range).
229
-
230
- Idempotent — safe to call repeatedly.
231
-
232
- ### `createEpsgResolver()`
233
-
234
- ```ts
235
- function createEpsgResolver(): (code: number) => Promise<ProjectionDefinition>
236
- ```
237
-
238
- Async factory returning an `epsgResolver` compatible with `@developmentseed/deck.gl-geotiff`'s `COGLayer` prop of the same name. Looks up numeric EPSG codes in the bundled `@developmentseed/epsg` gzipped CSV and parses each WKT with `parseWkt()` from `@developmentseed/proj`. Throws a clear `Error` if the code is not present.
239
-
240
- Replaces runtime `epsg.io` fetches — first COG per session pulls the CSV (~200 KB gzipped) once.
241
-
242
- ### Pixel / CRS helpers
243
-
244
- ```ts
245
- function readPixelAtLngLat(
246
- geotiff: GeoTIFF,
247
- lng: number,
248
- lat: number,
249
- proj4Def: string | null,
250
- pool: any,
251
- signal?: AbortSignal
252
- ): Promise<PixelValue | null>;
253
-
254
- function resolveProj4Def(
255
- crs: number | unknown,
256
- signal: AbortSignal
257
- ): Promise<string | null>;
258
- ```
259
-
260
- `readPixelAtLngLat` converts `(lng, lat)` into source CRS, then pixel coords, and reads every band. Returns `null` when outside the raster.
261
-
262
- `resolveProj4Def` returns a proj4-compatible WKT/ProjJSON string for a CRS identifier, or `null` for WGS84 / unknown.
263
-
264
- ### MapLibre helpers
265
-
266
- ```ts
267
- function getMaxTextureSize(map: maplibregl.Map): number; // fallback 4096
268
-
269
- function fitCogBounds(map: maplibregl.Map, b: GeoBounds): void;
270
-
271
- function cleanupNativeBitmap(map: maplibregl.Map): void; // idempotent
272
-
273
- function renderNonTiledBitmap(options: {
274
- url: string;
275
- map: maplibregl.Map;
276
- signal?: AbortSignal;
277
- geotiff?: GeoTIFF;
278
- }): Promise<CogInfo>;
279
- ```
280
-
281
- `renderNonTiledBitmap` is the fallback path for non-tiled GeoTIFFs: opens the file, reads band 0, normalizes to grayscale RGBA (terrain ramp for single-band int/float), adds a MapLibre native `image` source. Throws when the raster exceeds 100 M pixels or projection bounds cannot be computed.
282
-
283
77
  ## Usage outline
284
78
 
285
79
  ```ts
286
80
  import {
287
- defaultBandConfig,
288
- selectCogPipeline,
289
- normalizeCogGeotiff,
290
- createEpsgResolver,
291
- fitCogBounds,
81
+ buildDataTypeLabel,
292
82
  clampBounds,
83
+ safeClamp,
84
+ SF_LABELS,
85
+ type CogInfo,
86
+ type GeoBounds,
293
87
  } from '@walkthru-earth/objex-utils';
294
88
 
295
- normalizeCogGeotiff(geotiff);
296
- const config = defaultBandConfig(geotiff.bandCount, sampleFormat);
297
- const pipeline = selectCogPipeline(geotiff, { bandConfig: config });
298
- const resolver = createEpsgResolver();
299
-
300
- // feed into COGLayer({ ...pipeline, epsgResolver: resolver })
301
-
302
- fitCogBounds(map, clampBounds(bounds));
89
+ const label = buildDataTypeLabel(sampleFormat, bitsPerSample); // 'float32'
90
+ const safeBounds = clampBounds(bounds);
91
+ const nice = safeClamp(value, 0, 1, 0);
303
92
  ```
package/docs/storage.md CHANGED
@@ -154,6 +154,7 @@ const PROVIDER_IDS: ProviderId[];
154
154
  ```ts
155
155
  function getProvider(id: string): ProviderDef;
156
156
  function buildEndpointFromTemplate(id: ProviderId, region: string): string;
157
+ function resolveProviderEndpoint(provider: string, region?: string): string;
157
158
  function buildProviderBaseUrl(
158
159
  provider: ProviderId,
159
160
  endpoint: string,
@@ -167,6 +168,7 @@ function isGcsProvider(provider: string, endpoint: string): boolean;
167
168
  |----------|-----------|
168
169
  | `getProvider` | Unknown IDs fall back to the S3 entry (never throws). |
169
170
  | `buildEndpointFromTemplate` | Substitute `{region}` in the provider's template. |
171
+ | `resolveProviderEndpoint` | Same as `buildEndpointFromTemplate` but accepts an untyped `provider` string and falls back to the provider's `defaultRegion` when `region` is omitted. Returns `''` for providers without a template (plain S3, MinIO). |
170
172
  | `buildProviderBaseUrl` | Produce the HTTPS base URL for API requests (endpoint + bucket, correctly interleaved for virtual-host vs path-style). |
171
173
  | `isGcsProvider` | `true` when the connection uses the GCS JSON API rather than S3 XML — used to pick adapter implementation. |
172
174
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walkthru-earth/objex-utils",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Pure TypeScript utilities from objex — WKB parser, GeoArrow builder, storage URL parser, file type registry",
5
5
  "author": "Youssef Harby <yharby@walkthru.earth>",
6
6
  "license": "CC-BY-4.0",
@@ -15,9 +15,14 @@
15
15
  "types": "./dist/index.d.ts",
16
16
  "exports": {
17
17
  ".": {
18
- "types": "./dist/index.d.ts",
19
- "import": "./dist/index.js",
20
- "require": "./dist/index.cjs"
18
+ "import": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/index.d.cts",
24
+ "default": "./dist/index.cjs"
25
+ }
21
26
  }
22
27
  },
23
28
  "files": [