@hestia-earth/caching-api 0.1.1 → 0.1.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/README.md CHANGED
@@ -2,4 +2,68 @@
2
2
 
3
3
  ## Getting started
4
4
 
5
- TODO
5
+ To use this API and querying the raster files, you need to download the assets first:
6
+
7
+ ### 1. Download the HESTIA assets (~1.9 GB, required)
8
+
9
+ ```bash
10
+ mkdir -p assets
11
+ curl -O https://hestia.earth/data/hestia-geospatial-assets.zip
12
+ unzip hestia-geospatial-assets.zip -d assets
13
+ ```
14
+
15
+ ### 2. Download GADM boundaries (only for `gadm-ids` queries)
16
+
17
+ **HESTIA cannot redistribute GADM**, so it comes from the source. Below is a script to run in your terminal to download the files:
18
+ ```bash
19
+ mkdir -p assets/gadm
20
+
21
+ for country in \
22
+ ABW AFG AGO AIA ALA ALB AND ARE ARG ARM ASM ATA ATF ATG AUS AUT AZE \
23
+ BDI BEL BEN BES BFA BGD BGR BHR BHS BIH BLM BLR BLZ BMU BOL BRA BRB \
24
+ BRN BTN BVT BWA CAF CAN CCK CHE CHL CHN CIV CMR COD COG COK COL COM \
25
+ CPV CRI CUB CUW CXR CYM CYP CZE DEU DJI DMA DNK DOM DZA ECU EGY ERI \
26
+ ESH ESP EST ETH FIN FJI FLK FRA FRO FSM GAB GBR GEO GGY GHA GIB GIN \
27
+ GLP GMB GNB GNQ GRC GRD GRL GTM GUF GUM GUY HKG HMD HND HRV HTI HUN \
28
+ IDN IMN IND IOT IRL IRN IRQ ISL ISR ITA JAM JEY JOR JPN KAZ KEN KGZ \
29
+ KHM KIR KNA KOR KWT LAO LBN LBR LBY LCA LIE LKA LSO LTU LUX LVA MAC \
30
+ MAF MAR MCO MDA MDG MDV MEX MHL MKD MLI MLT MMR MNE MNG MNP MOZ MRT \
31
+ MSR MTQ MUS MWI MYS MYT NAM NCL NER NFK NGA NIC NIU NLD NOR NPL NRU \
32
+ NZL OMN PAK PAN PCN PER PHL PLW PNG POL PRI PRK PRT PRY PSE PYF QAT \
33
+ REU ROU RUS RWA SAU SDN SEN SGP SGS SHN SJM SLB SLE SLV SMR SOM SPM \
34
+ SRB SSD STP SUR SVK SVN SWE SWZ SXM SYC SYR TCA TCD TGO THA TJK TKL \
35
+ TKM TLS TON TTO TUN TUR TUV TWN TZA UGA UKR UMI URY USA UZB VAT VCT \
36
+ VEN VGB VIR VNM VUT WLF WSM XAD XCA XCL XKO XNC XPI XSP YEM ZAF ZMB \
37
+ ZWE
38
+ do
39
+ archive="assets/gadm/gadm36_${country}_shp.zip"
40
+ [ -f "$archive" ] && continue
41
+ curl -fsS -o "$archive" \
42
+ "https://geodata.ucdavis.edu/gadm/gadm3.6/shp/gadm36_${country}_shp.zip" \
43
+ || echo "failed: $country"
44
+ done
45
+ ```
46
+
47
+ You can also download the files on https://gadm.org/download_country36.html (the "Shapefile").
48
+
49
+ ### 3. Run the container
50
+
51
+ ```bash
52
+ docker run -p 8000:80 \
53
+ -e API_TOKEN=<token> \
54
+ -e DATABASE_URL=<postgres-url> \
55
+ -v "$(pwd)/assets:/app/assets:ro" \
56
+ hestiae/hestia-caching-api
57
+ ```
58
+
59
+ Allow ~800 MB of memory.
60
+
61
+ | Variable | Default | Purpose |
62
+ | --- | --- | --- |
63
+ | `API_TOKEN` | — | Admin token. Used to limit access to the whole API. Sent as the `X-API-KEY` header |
64
+ | `DATABASE_URL` | — | PostgreSQL connection string |
65
+ | `GEOSPATIAL_FOLDER` | `assets/ee` | Where the rasters are |
66
+ | `GADM_FOLDER` | `assets/gadm` | Where the GADM archives are |
67
+ | `GDAL_CACHEMAX` | `64` | Tile cache, MB. Left unset, GDAL takes 5% of *host* RAM and ignores the container limit |
68
+
69
+ Note: the `docker-compose.yml` file is available to get started locally quicker.
package/index.d.ts CHANGED
@@ -102,6 +102,136 @@ export interface paths {
102
102
  patch?: never;
103
103
  trace?: never;
104
104
  };
105
+ "/tokens": {
106
+ parameters: {
107
+ query?: never;
108
+ header?: never;
109
+ path?: never;
110
+ cookie?: never;
111
+ };
112
+ /**
113
+ * Read All
114
+ * @description Lists all API tokens. Secrets are never returned.
115
+ */
116
+ get: operations["read_all_tokens_get"];
117
+ put?: never;
118
+ /**
119
+ * Create
120
+ * @description Creates a new API token. The plaintext token is returned once and is not
121
+ * stored — save it now, it cannot be retrieved later.
122
+ */
123
+ post: operations["create_tokens_post"];
124
+ delete?: never;
125
+ options?: never;
126
+ head?: never;
127
+ patch?: never;
128
+ trace?: never;
129
+ };
130
+ "/tokens/{token_id}": {
131
+ parameters: {
132
+ query?: never;
133
+ header?: never;
134
+ path?: never;
135
+ cookie?: never;
136
+ };
137
+ /**
138
+ * Read One
139
+ * @description Retrieves a single API token by its id.
140
+ */
141
+ get: operations["read_one_tokens__token_id__get"];
142
+ put?: never;
143
+ post?: never;
144
+ /**
145
+ * Remove
146
+ * @description Deletes an API token.
147
+ */
148
+ delete: operations["remove_tokens__token_id__delete"];
149
+ options?: never;
150
+ head?: never;
151
+ /**
152
+ * Update
153
+ * @description Updates a token: rename, re-scope, renew (change expiry) or (de)activate it.
154
+ * Does not rotate the secret.
155
+ */
156
+ patch: operations["update_tokens__token_id__patch"];
157
+ trace?: never;
158
+ };
159
+ "/tokens/{token_id}/reactivate": {
160
+ parameters: {
161
+ query?: never;
162
+ header?: never;
163
+ path?: never;
164
+ cookie?: never;
165
+ };
166
+ get?: never;
167
+ put?: never;
168
+ /**
169
+ * Reactivate
170
+ * @description Reactivates a token, rotating its secret and returning the new plaintext.
171
+ * The previous secret is invalidated immediately.
172
+ */
173
+ post: operations["reactivate_tokens__token_id__reactivate_post"];
174
+ delete?: never;
175
+ options?: never;
176
+ head?: never;
177
+ patch?: never;
178
+ trace?: never;
179
+ };
180
+ "/geospatial/collections": {
181
+ parameters: {
182
+ query?: never;
183
+ header?: never;
184
+ path?: never;
185
+ cookie?: never;
186
+ };
187
+ /**
188
+ * List Collections
189
+ * @description The collections this API can answer for.
190
+ *
191
+ * Callers hold a mix: the ones HESTIA owns are served here, the public Earth
192
+ * Engine ones are not. Since `/run` rejects a query it cannot answer *in
193
+ * full*, a caller batching collections together needs to know the split up
194
+ * front rather than discovering it from a 422.
195
+ */
196
+ get: operations["list_collections_geospatial_collections_get"];
197
+ put?: never;
198
+ post?: never;
199
+ delete?: never;
200
+ options?: never;
201
+ head?: never;
202
+ patch?: never;
203
+ trace?: never;
204
+ };
205
+ "/geospatial/run": {
206
+ parameters: {
207
+ query?: never;
208
+ header?: never;
209
+ path?: never;
210
+ cookie?: never;
211
+ };
212
+ get?: never;
213
+ put?: never;
214
+ /**
215
+ * Run Query
216
+ * @description Samples the exported geospatial assets at coordinates, or reduces them over
217
+ * boundaries or GADM regions.
218
+ *
219
+ * Accepts the same payload as ``hestia_earth.earth_engine.run`` so the models
220
+ * can call this instead, and returns the values in the same order:
221
+ * geometry-major, one value per collection.
222
+ *
223
+ * Only collections HESTIA owns are served here. Public Earth Engine
224
+ * collections (ERA5, TERRACLIMATE, GMTED2010) are rejected rather than
225
+ * silently returning nothing -- the caller is expected to route those to
226
+ * Earth Engine.
227
+ */
228
+ post: operations["run_query_geospatial_run_post"];
229
+ delete?: never;
230
+ options?: never;
231
+ head?: never;
232
+ patch?: never;
233
+ trace?: never;
234
+ };
105
235
  "/version": {
106
236
  parameters: {
107
237
  query?: never;
@@ -140,6 +270,61 @@ export interface paths {
140
270
  export type webhooks = Record<string, never>;
141
271
  export interface components {
142
272
  schemas: {
273
+ /**
274
+ * Collection
275
+ * @description One collection to sample.
276
+ *
277
+ * Mirrors the payload ``hestia_earth.earth_engine`` accepts so the models can
278
+ * swap one for the other without reshaping the query. Fields beyond
279
+ * ``collection`` (``band_name``, ``reducer``, ``name``, depth bounds) are
280
+ * carried for compatibility and ignored when sampling by coordinates -- a
281
+ * point needs no reduction, and the soil depth is already encoded in the
282
+ * collection name.
283
+ */
284
+ Collection: {
285
+ /** Collection */
286
+ collection: string;
287
+ } & {
288
+ [key: string]: unknown;
289
+ };
290
+ /** Coordinate */
291
+ Coordinate: {
292
+ /** Latitude */
293
+ latitude: number;
294
+ /** Longitude */
295
+ longitude: number;
296
+ };
297
+ /**
298
+ * GeospatialQuery
299
+ * @description One of ``coordinates``, ``boundaries`` or ``gadm-ids``.
300
+ *
301
+ * ``hestia_earth.earth_engine.run`` picks its mode from whichever key is
302
+ * present, so the same payload works against either backend.
303
+ */
304
+ GeospatialQuery: {
305
+ /** Ee Type */
306
+ ee_type?: string | null;
307
+ /** Collections */
308
+ collections: components["schemas"]["Collection"][];
309
+ /** Coordinates */
310
+ coordinates?: components["schemas"]["Coordinate"][] | null;
311
+ /** Boundaries */
312
+ boundaries?: {
313
+ [key: string]: unknown;
314
+ }[] | null;
315
+ /** Gadm-Ids */
316
+ "gadm-ids"?: string[] | null;
317
+ /** Scale */
318
+ scale?: number | null;
319
+ };
320
+ /**
321
+ * GeospatialResults
322
+ * @description Values ordered coordinate-major: per coordinate, one per collection.
323
+ */
324
+ GeospatialResults: {
325
+ /** Results */
326
+ results: (number | null)[];
327
+ };
143
328
  /** HTTPValidationError */
144
329
  HTTPValidationError: {
145
330
  /** Detail */
@@ -190,6 +375,98 @@ export interface components {
190
375
  /** Offset */
191
376
  offset: number;
192
377
  };
378
+ /** TokenCreate */
379
+ TokenCreate: {
380
+ /** Name */
381
+ name: string;
382
+ /** Scopes */
383
+ scopes: string[];
384
+ /** Expires At */
385
+ expires_at?: string | null;
386
+ };
387
+ /** TokenOut */
388
+ TokenOut: {
389
+ /** Id */
390
+ id: string;
391
+ /** Name */
392
+ name: string;
393
+ /** Prefix */
394
+ prefix: string;
395
+ /** Scopes */
396
+ scopes: string[];
397
+ /** Is Active */
398
+ is_active: boolean;
399
+ /** Active */
400
+ active: boolean;
401
+ /** Expires At */
402
+ expires_at?: string | null;
403
+ /** Last Used At */
404
+ last_used_at?: string | null;
405
+ /**
406
+ * Created At
407
+ * Format: date-time
408
+ */
409
+ created_at: string;
410
+ /** Updated At */
411
+ updated_at?: string | null;
412
+ };
413
+ /**
414
+ * TokenReactivate
415
+ * @description Reactivation rotates the secret; an optional new expiry may be set
416
+ * (null clears the expiry so the token never expires).
417
+ */
418
+ TokenReactivate: {
419
+ /** Expires At */
420
+ expires_at?: string | null;
421
+ };
422
+ /**
423
+ * TokenUpdate
424
+ * @description Partial update (rename, re-scope, renew expiry, (de)activate).
425
+ *
426
+ * Does not rotate the secret; use the reactivate endpoint for that.
427
+ */
428
+ TokenUpdate: {
429
+ /** Name */
430
+ name?: string | null;
431
+ /** Scopes */
432
+ scopes?: string[] | null;
433
+ /** Expires At */
434
+ expires_at?: string | null;
435
+ /** Is Active */
436
+ is_active?: boolean | null;
437
+ };
438
+ /**
439
+ * TokenWithSecret
440
+ * @description Returned only on creation and reactivation: carries the plaintext token,
441
+ * which is never stored and cannot be retrieved again.
442
+ */
443
+ TokenWithSecret: {
444
+ /** Id */
445
+ id: string;
446
+ /** Name */
447
+ name: string;
448
+ /** Prefix */
449
+ prefix: string;
450
+ /** Scopes */
451
+ scopes: string[];
452
+ /** Is Active */
453
+ is_active: boolean;
454
+ /** Active */
455
+ active: boolean;
456
+ /** Expires At */
457
+ expires_at?: string | null;
458
+ /** Last Used At */
459
+ last_used_at?: string | null;
460
+ /**
461
+ * Created At
462
+ * Format: date-time
463
+ */
464
+ created_at: string;
465
+ /** Updated At */
466
+ updated_at?: string | null;
467
+ /** Token */
468
+ token: string;
469
+ };
193
470
  /** ValidationError */
194
471
  ValidationError: {
195
472
  /** Location */
@@ -470,6 +747,244 @@ export interface operations {
470
747
  };
471
748
  };
472
749
  };
750
+ read_all_tokens_get: {
751
+ parameters: {
752
+ query?: never;
753
+ header?: never;
754
+ path?: never;
755
+ cookie?: never;
756
+ };
757
+ requestBody?: never;
758
+ responses: {
759
+ /** @description Successful Response */
760
+ 200: {
761
+ headers: {
762
+ [name: string]: unknown;
763
+ };
764
+ content: {
765
+ "application/json": components["schemas"]["TokenOut"][];
766
+ };
767
+ };
768
+ };
769
+ };
770
+ create_tokens_post: {
771
+ parameters: {
772
+ query?: never;
773
+ header?: never;
774
+ path?: never;
775
+ cookie?: never;
776
+ };
777
+ requestBody: {
778
+ content: {
779
+ "application/json": components["schemas"]["TokenCreate"];
780
+ };
781
+ };
782
+ responses: {
783
+ /** @description Successful Response */
784
+ 201: {
785
+ headers: {
786
+ [name: string]: unknown;
787
+ };
788
+ content: {
789
+ "application/json": components["schemas"]["TokenWithSecret"];
790
+ };
791
+ };
792
+ /** @description Validation Error */
793
+ 422: {
794
+ headers: {
795
+ [name: string]: unknown;
796
+ };
797
+ content: {
798
+ "application/json": components["schemas"]["HTTPValidationError"];
799
+ };
800
+ };
801
+ };
802
+ };
803
+ read_one_tokens__token_id__get: {
804
+ parameters: {
805
+ query?: never;
806
+ header?: never;
807
+ path: {
808
+ token_id: string;
809
+ };
810
+ cookie?: never;
811
+ };
812
+ requestBody?: never;
813
+ responses: {
814
+ /** @description Successful Response */
815
+ 200: {
816
+ headers: {
817
+ [name: string]: unknown;
818
+ };
819
+ content: {
820
+ "application/json": components["schemas"]["TokenOut"];
821
+ };
822
+ };
823
+ /** @description Validation Error */
824
+ 422: {
825
+ headers: {
826
+ [name: string]: unknown;
827
+ };
828
+ content: {
829
+ "application/json": components["schemas"]["HTTPValidationError"];
830
+ };
831
+ };
832
+ };
833
+ };
834
+ remove_tokens__token_id__delete: {
835
+ parameters: {
836
+ query?: never;
837
+ header?: never;
838
+ path: {
839
+ token_id: string;
840
+ };
841
+ cookie?: never;
842
+ };
843
+ requestBody?: never;
844
+ responses: {
845
+ /** @description Successful Response */
846
+ 200: {
847
+ headers: {
848
+ [name: string]: unknown;
849
+ };
850
+ content: {
851
+ "application/json": unknown;
852
+ };
853
+ };
854
+ /** @description Validation Error */
855
+ 422: {
856
+ headers: {
857
+ [name: string]: unknown;
858
+ };
859
+ content: {
860
+ "application/json": components["schemas"]["HTTPValidationError"];
861
+ };
862
+ };
863
+ };
864
+ };
865
+ update_tokens__token_id__patch: {
866
+ parameters: {
867
+ query?: never;
868
+ header?: never;
869
+ path: {
870
+ token_id: string;
871
+ };
872
+ cookie?: never;
873
+ };
874
+ requestBody: {
875
+ content: {
876
+ "application/json": components["schemas"]["TokenUpdate"];
877
+ };
878
+ };
879
+ responses: {
880
+ /** @description Successful Response */
881
+ 200: {
882
+ headers: {
883
+ [name: string]: unknown;
884
+ };
885
+ content: {
886
+ "application/json": components["schemas"]["TokenOut"];
887
+ };
888
+ };
889
+ /** @description Validation Error */
890
+ 422: {
891
+ headers: {
892
+ [name: string]: unknown;
893
+ };
894
+ content: {
895
+ "application/json": components["schemas"]["HTTPValidationError"];
896
+ };
897
+ };
898
+ };
899
+ };
900
+ reactivate_tokens__token_id__reactivate_post: {
901
+ parameters: {
902
+ query?: never;
903
+ header?: never;
904
+ path: {
905
+ token_id: string;
906
+ };
907
+ cookie?: never;
908
+ };
909
+ requestBody?: {
910
+ content: {
911
+ "application/json": components["schemas"]["TokenReactivate"];
912
+ };
913
+ };
914
+ responses: {
915
+ /** @description Successful Response */
916
+ 200: {
917
+ headers: {
918
+ [name: string]: unknown;
919
+ };
920
+ content: {
921
+ "application/json": components["schemas"]["TokenWithSecret"];
922
+ };
923
+ };
924
+ /** @description Validation Error */
925
+ 422: {
926
+ headers: {
927
+ [name: string]: unknown;
928
+ };
929
+ content: {
930
+ "application/json": components["schemas"]["HTTPValidationError"];
931
+ };
932
+ };
933
+ };
934
+ };
935
+ list_collections_geospatial_collections_get: {
936
+ parameters: {
937
+ query?: never;
938
+ header?: never;
939
+ path?: never;
940
+ cookie?: never;
941
+ };
942
+ requestBody?: never;
943
+ responses: {
944
+ /** @description Successful Response */
945
+ 200: {
946
+ headers: {
947
+ [name: string]: unknown;
948
+ };
949
+ content: {
950
+ "application/json": unknown;
951
+ };
952
+ };
953
+ };
954
+ };
955
+ run_query_geospatial_run_post: {
956
+ parameters: {
957
+ query?: never;
958
+ header?: never;
959
+ path?: never;
960
+ cookie?: never;
961
+ };
962
+ requestBody: {
963
+ content: {
964
+ "application/json": components["schemas"]["GeospatialQuery"];
965
+ };
966
+ };
967
+ responses: {
968
+ /** @description Successful Response */
969
+ 200: {
970
+ headers: {
971
+ [name: string]: unknown;
972
+ };
973
+ content: {
974
+ "application/json": components["schemas"]["GeospatialResults"];
975
+ };
976
+ };
977
+ /** @description Validation Error */
978
+ 422: {
979
+ headers: {
980
+ [name: string]: unknown;
981
+ };
982
+ content: {
983
+ "application/json": components["schemas"]["HTTPValidationError"];
984
+ };
985
+ };
986
+ };
987
+ };
473
988
  version_version_get: {
474
989
  parameters: {
475
990
  query?: never;