geoai 1.0.3 → 1.0.4

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/CHANGELOG.md CHANGED
@@ -7,24 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Changed
11
- - Removed OpenCV.js dependency across all AI models for improved performance and reduced bundle size
12
- - Migrated building-footprint-segmentation and landcover-classification to use d3-contours for contour processing
13
- - Replaced OpenCV implementations with native JavaScript solutions
10
+ ## [1.0.4] - 2026-07-11
14
11
 
15
12
  ### Added
16
- - Tile stitching method to GeoRawImage for improved image handling capabilities
17
- - GeoJSON output option for landcover classification results
18
- - Result layer type selector for better visualization control
13
+ - TMS map provider with `{z}/{x}/{y}` URL templates and WebMercator/TMS tile schemes
14
+ - `examples/05-tms-quickstart` and TMS / serving-raster-tiles documentation
19
15
 
20
16
  ### Fixed
21
- - Mask generation post-processing improvements
22
- - Multipolygon issues in mask generation
23
- - Landcover classification mask to polygon conversion accuracy
17
+ - `dts-bundle-generator` config for ESM package type (`build:types` in CI)
18
+ - CI test stability: Geobase tile mocks, ONNX cache cleanup, and zero-shot test isolation
19
+ - Test gist uploads no longer log errors when GitHub credentials are missing or invalid
20
+
21
+ ### Changed
22
+ - Gist uploads in tests are opt-in via `GEOAI_SAVE_GISTS=1`
23
+
24
+ ## [1.0.3] - 2025-08-28
24
25
 
25
- ### Improved
26
- - Overall library performance with removal of heavy OpenCV dependency
27
- - Memory usage optimization in geospatial processing tasks
26
+ ### Fixed
27
+ - Landuse classification vectorisation bug fix
28
28
 
29
29
  ## [1.0.0-rc.1] - 2024-01-XX
30
30
 
@@ -125,12 +125,6 @@ To migrate from the old package:
125
125
 
126
126
  ## [1.0.1] - 2025-08-28
127
127
 
128
- ### Release Candidate
128
+ ### Changed
129
129
  - Removed OpenCV.js dependency across all AI models for improved performance and reduced bundle size.
130
130
 
131
-
132
- ## [1.0.3] - 2025-08-28
133
-
134
- ### Release Candidate
135
- - Landuse classification vectorisation bug fix
136
-
package/README.md CHANGED
@@ -133,7 +133,7 @@ function MyComponent() {
133
133
  ## Features
134
134
 
135
135
  - **Multiple AI Tasks**: Object detection, segmentation, classification, and more
136
- - **Map Provider Support**: Geobase, Mapbox, ESRI, and Google Maps
136
+ - **Map Provider Support**: Geobase, Mapbox, ESRI, TMS, and Google Maps
137
137
  - **React Integration**: Hooks for easy React integration
138
138
  - **TypeScript Support**: Full TypeScript definitions
139
139
  - **Web Worker Support**: Run AI models in background threads
@@ -158,6 +158,79 @@ function MyComponent() {
158
158
 
159
159
  For more see the [supported tasks](https://docs.geobase.app/geoai/supported-tasks)
160
160
 
161
+ ## Map Providers
162
+
163
+ GeoAI.js supports multiple map tile providers:
164
+
165
+ ### TMS (Tile Map Service)
166
+ TMS is a tile-based map specification that uses a bottom-left origin coordinate system. Perfect for custom tile servers and OpenAerialMap.
167
+
168
+ ```javascript
169
+ // Option 1: Using URL template with placeholders (recommended)
170
+ const pipeline = await geoai.pipeline([{ task: "object-detection" }], {
171
+ provider: "tms",
172
+ baseUrl: "https://tile.example.com/tiles/{z}/{x}/{y}.png",
173
+ apiKey: "your-api-key", // optional
174
+ tileSize: 256, // optional, defaults to 256
175
+ attribution: "Custom TMS Provider", // optional
176
+ });
177
+
178
+ // Option 2: Using base URL (legacy format, still supported)
179
+ const pipeline = await geoai.pipeline([{ task: "object-detection" }], {
180
+ provider: "tms",
181
+ baseUrl: "https://tile.example.com/tiles",
182
+ extension: "png", // optional, defaults to "png"
183
+ apiKey: "your-api-key", // optional
184
+ tileSize: 256, // optional, defaults to 256
185
+ attribution: "Custom TMS Provider", // optional
186
+ });
187
+ ```
188
+
189
+ ### ESRI
190
+ ESRI World Imagery - no API key required.
191
+
192
+ ```javascript
193
+ const pipeline = await geoai.pipeline([{ task: "object-detection" }], {
194
+ provider: "esri",
195
+ });
196
+ ```
197
+
198
+ ### Mapbox
199
+ Requires a Mapbox API key.
200
+
201
+ ```javascript
202
+ const pipeline = await geoai.pipeline([{ task: "object-detection" }], {
203
+ provider: "mapbox",
204
+ apiKey: "your-mapbox-api-key",
205
+ style: "mapbox://styles/mapbox/satellite-v9",
206
+ });
207
+ ```
208
+
209
+ ### Geobase
210
+ Requires Geobase project credentials.
211
+
212
+ ```javascript
213
+ const pipeline = await geoai.pipeline([{ task: "object-detection" }], {
214
+ provider: "geobase",
215
+ projectRef: "your-project-ref",
216
+ apikey: "your-api-key",
217
+ cogImagery: "https://path-to-your-cog.tif",
218
+ });
219
+ ```
220
+
221
+ ## Talk
222
+
223
+ **[Bringing Earth Observation AI to the Browser with WebGPU](talks/lightning-talk-webgpu-geoai.md)** — lightning talk at Big Data from Space 2025 (Decision Labs).
224
+
225
+ <div align="center">
226
+ <a href="https://geobase-docs.s3.amazonaws.com/geobase-ai-assets/talks/lightning-talk-webgpu-geoai.pdf">
227
+ <img src="https://geobase-docs.s3.amazonaws.com/geobase-ai-assets/talks/geoaijs.png" alt="GeoAI.js talk preview" width="480">
228
+ </a>
229
+ </div>
230
+
231
+ - [Slides (PDF)](https://geobase-docs.s3.amazonaws.com/geobase-ai-assets/talks/lightning-talk-webgpu-geoai.pdf)
232
+ - [Slide source (Marp)](talks/lightning-talk-webgpu-geoai.md)
233
+
161
234
  ## Links
162
235
 
163
236
  - **Documentation**: [docs.geobase.app/geoai](https://docs.geobase.app/geoai) - Comprehensive documentation, examples, and API reference
package/geoai.js CHANGED
@@ -390,7 +390,7 @@ const postProcessYoloOutput = (model_outputs, pixel_values, rawImage, id2label)
390
390
  return model_output;
391
391
  };
392
392
  const parametersChanged = (instance, model_id, providerParams, modelParams) => {
393
- var _a, _b, _c, _d, _e, _f, _g;
393
+ var _a, _b, _c, _d, _e, _f, _g, _h;
394
394
  if (instance.model_id !== model_id) {
395
395
  return true;
396
396
  }
@@ -415,6 +415,10 @@ const parametersChanged = (instance, model_id, providerParams, modelParams) => {
415
415
  return true;
416
416
  }
417
417
  break;
418
+ case "tms":
419
+ if (((_h = instance.providerParams) == null ? void 0 : _h.baseUrl) !== (providerParams == null ? void 0 : providerParams.baseUrl)) {
420
+ return true;
421
+ }
418
422
  }
419
423
  if (modelParams) {
420
424
  const instanceModelParams = instance.modelParams || {};
@@ -984,6 +988,7 @@ var ErrorType = /* @__PURE__ */ ((ErrorType2) => {
984
988
  ErrorType2["MaximumTileCountExceeded"] = "MaximumTileCountExceeded";
985
989
  ErrorType2["UnknownTask"] = "UnknownTask";
986
990
  ErrorType2["MissingInputField"] = "MissingInputField";
991
+ ErrorType2["ImageLoadFailed"] = "ImageLoadFailed";
987
992
  return ErrorType2;
988
993
  })(ErrorType || {});
989
994
  const ErrorCodes = {
@@ -998,7 +1003,11 @@ const ErrorCodes = {
998
1003
  [
999
1004
  "MissingInputField"
1000
1005
  /* MissingInputField */
1001
- ]: 1003
1006
+ ]: 1003,
1007
+ [
1008
+ "ImageLoadFailed"
1009
+ /* ImageLoadFailed */
1010
+ ]: 1004
1002
1011
  // Add more error codes here as needed
1003
1012
  };
1004
1013
  class GeobaseError extends Error {
@@ -1241,6 +1250,39 @@ class Esri extends MapSource {
1241
1250
  return `${instance.serviceUrl}/${instance.serviceName}/MapServer/tile/${z}/${y}/${x}`;
1242
1251
  }
1243
1252
  }
1253
+ class Tms extends MapSource {
1254
+ constructor(config) {
1255
+ super();
1256
+ __publicField(this, "baseUrl");
1257
+ __publicField(this, "extension");
1258
+ __publicField(this, "apiKey");
1259
+ __publicField(this, "attribution");
1260
+ __publicField(this, "tileSize");
1261
+ __publicField(this, "headers");
1262
+ __publicField(this, "scheme");
1263
+ this.baseUrl = config.baseUrl;
1264
+ this.extension = config.extension || "png";
1265
+ this.apiKey = config.apiKey;
1266
+ this.attribution = config.attribution || "TMS Provider";
1267
+ this.tileSize = config.tileSize || 256;
1268
+ this.headers = config.headers;
1269
+ this.scheme = config.scheme || "WebMercator";
1270
+ }
1271
+ getTileUrlFromTileCoords(tileCoords, instance) {
1272
+ const [x, originalY, z] = tileCoords;
1273
+ const y = instance.scheme === "TMS" ? Math.pow(2, z) - 1 - originalY : originalY;
1274
+ let url;
1275
+ if (instance.baseUrl.includes("{x}") || instance.baseUrl.includes("{y}") || instance.baseUrl.includes("{z}")) {
1276
+ url = instance.baseUrl.replaceAll("{z}", z.toString()).replaceAll("{x}", x.toString()).replaceAll("{y}", y.toString());
1277
+ } else {
1278
+ url = `${instance.baseUrl}/${z}/${x}/${y}.${instance.extension}`;
1279
+ }
1280
+ if (instance.apiKey) {
1281
+ url += `?apikey=${instance.apiKey}`;
1282
+ }
1283
+ return url;
1284
+ }
1285
+ }
1244
1286
  class BaseModel {
1245
1287
  constructor(model_id, providerParams, modelParams) {
1246
1288
  __publicField(this, "providerParams");
@@ -1284,6 +1326,17 @@ class BaseModel {
1284
1326
  attribution: this.providerParams.attribution
1285
1327
  });
1286
1328
  break;
1329
+ case "tms":
1330
+ this.dataProvider = new Tms({
1331
+ baseUrl: this.providerParams.baseUrl,
1332
+ extension: this.providerParams.extension,
1333
+ apiKey: this.providerParams.apiKey,
1334
+ attribution: this.providerParams.attribution,
1335
+ tileSize: this.providerParams.tileSize,
1336
+ headers: this.providerParams.headers,
1337
+ scheme: this.providerParams.scheme
1338
+ });
1339
+ break;
1287
1340
  case "sentinel":
1288
1341
  throw new Error("Sentinel provider not implemented yet");
1289
1342
  default:
package/index.d.ts CHANGED
@@ -132,10 +132,40 @@ declare class Esri extends MapSource {
132
132
  number
133
133
  ], instance: Esri): string;
134
134
  }
135
+ export interface TmsConfig {
136
+ baseUrl: string;
137
+ extension?: string;
138
+ apiKey?: string;
139
+ attribution?: string;
140
+ tileSize?: number;
141
+ headers?: Record<string, string>;
142
+ /**
143
+ * Tile scheme to use.
144
+ * - 'WebMercator': Web Mercator/XYZ (top-left origin, Y increases downward) - default for most modern services including Cesium
145
+ * - 'TMS': TMS standard (bottom-left origin, Y increases upward) - traditional TMS
146
+ * @default 'WebMercator'
147
+ */
148
+ scheme?: "WebMercator" | "TMS";
149
+ }
150
+ declare class Tms extends MapSource {
151
+ baseUrl: string;
152
+ extension: string;
153
+ apiKey?: string;
154
+ attribution: string;
155
+ tileSize: number;
156
+ headers?: Record<string, string>;
157
+ scheme: "WebMercator" | "TMS";
158
+ constructor(config: TmsConfig);
159
+ protected getTileUrlFromTileCoords(tileCoords: [
160
+ number,
161
+ number,
162
+ number
163
+ ], instance: Tms): string;
164
+ }
135
165
  declare abstract class BaseModel {
136
166
  protected static instance: BaseModel | null;
137
167
  protected providerParams: ProviderParams;
138
- protected dataProvider: Mapbox | Geobase | Esri | undefined;
168
+ protected dataProvider: Mapbox | Geobase | Esri | Tms | undefined;
139
169
  protected model_id: string;
140
170
  protected initialized: boolean;
141
171
  protected modelParams?: PretrainedModelOptions;
@@ -430,6 +460,16 @@ export type EsriParams = {
430
460
  tileSize?: number;
431
461
  attribution?: string;
432
462
  };
463
+ export type TmsParams = {
464
+ provider: "tms";
465
+ baseUrl: string;
466
+ extension?: string;
467
+ apiKey?: string;
468
+ attribution?: string;
469
+ tileSize?: number;
470
+ headers?: Record<string, string>;
471
+ scheme?: "WebMercator" | "TMS";
472
+ };
433
473
  export interface InferenceInputs {
434
474
  polygon: GeoJSON.Feature;
435
475
  classLabel?: string;
@@ -448,7 +488,7 @@ export interface InferenceParams {
448
488
  postProcessingParams?: PostProcessingParams;
449
489
  mapSourceParams?: MapSourceParams;
450
490
  }
451
- export type ProviderParams = MapboxParams | SentinelParams | GeobaseParams | EsriParams;
491
+ export type ProviderParams = MapboxParams | SentinelParams | GeobaseParams | EsriParams | TmsParams;
452
492
  export type HuggingFaceModelTask = "mask-generation" | "zero-shot-object-detection" | "zero-shot-image-classification" | "object-detection" | "oriented-object-detection" | "image-feature-extraction";
453
493
  export type GeobaseAiModelTask = "damage-assessment" | "vegetation-classification" | "land-cover-classification" | "land-use-classification" | "land-cover-change-detection" | "land-use-change-detection" | "solar-panel-detection" | "ship-detection" | "car-detection" | "wetland-segmentation" | "building-detection" | "oil-storage-tank-detection" | "building-footprint-segmentation";
454
494
  export type ModelInstance = MaskGeneration | ZeroShotObjectDetection | ObjectDetection | OrientedObjectDetection | LandCoverClassification | SolarPanelDetection | ShipDetection | CarDetection | WetLandSegmentation | BuildingDetection | OilStorageTankDetection | BuildingFootPrintSegmentation | ImageFeatureExtraction;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geoai",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "A JavaScript library for running Geo AI models in frontend applications",
5
5
  "keywords": [
6
6
  "geoai",
@@ -57,7 +57,7 @@
57
57
  "publish:build": "cd build && npm publish --access public --ignore-scripts",
58
58
  "publish:pkg": "pnpm prepublish:prep && pnpm publish:build",
59
59
  "build:core": "tsc && vite build",
60
- "build:types": "dts-bundle-generator --config ./dts-bundle-generator.config.ts",
60
+ "build:types": "dts-bundle-generator --config ./dts-bundle-generator.config.cjs",
61
61
  "build:package": "copyfiles ./package.json build",
62
62
  "build:examples": "pnpm build && cp -r ./build ./examples/codepen-geobase",
63
63
  "test": "vitest",