@seta-labs/geo 0.2.0 → 0.4.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/CHANGELOG.md +17 -0
- package/README.md +8 -0
- package/dist/index.d.ts +155 -11
- package/dist/index.js +20 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @seta-labs/geo
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
- New `cadastreParcels(query?)` on `GET /cadastre/parcels`: the stored
|
|
6
|
+
cadastral answers, newest first, filtered by `codComune`, `foglio`,
|
|
7
|
+
`particella` and `tipologia` (exact match), paginated with `page` and
|
|
8
|
+
`pageSize`. A read of the store: it never asks the cadastral map.
|
|
9
|
+
- New types `CadastreParcelsQuery`, `CadastreParcelsPage` and `CadastreParcelRow`.
|
|
10
|
+
|
|
11
|
+
## 0.3.0
|
|
12
|
+
|
|
13
|
+
- `geocode`, `geocodeBatch`, `reverseGeocode` and `cadastreParcel` take
|
|
14
|
+
`cache: { refresh, noStore, maxAge, onlyIfCached }`, sent as
|
|
15
|
+
`Cache-Control` (`no-cache`, `no-store`, `max-age`, `only-if-cached`).
|
|
16
|
+
Without it nothing changes. New types `LookupCache` and `LookupOptions`.
|
|
17
|
+
- A lookup refused by `onlyIfCached` rejects with `ApiError` 504
|
|
18
|
+
(`code: 'NOT_CACHED'`); a batch item has `status: 'NOT_CACHED'`.
|
|
19
|
+
|
|
3
20
|
## 0.2.0
|
|
4
21
|
|
|
5
22
|
- New `cadastreParcel({ lat, lng })` on `POST /cadastre/parcel`: what the AdE
|
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ retain their own concurrency and retry policy.
|
|
|
50
50
|
| `geocodeBatch` | `GeocodeBatchRequest` |
|
|
51
51
|
| `reverseGeocode` | `ReverseGeocodeRequest` |
|
|
52
52
|
| `cadastreParcel` | `CadastreParcelRequest` |
|
|
53
|
+
| `cadastreParcels` | optional `CadastreParcelsQuery` |
|
|
53
54
|
| `territory.status`, `territory.datasets` | options only |
|
|
54
55
|
| `territory.comuni` | optional `TerritoryComuniQuery` |
|
|
55
56
|
| `territory.quotazioni` | optional `TerritoryQuotazioniQuery` |
|
|
@@ -64,6 +65,13 @@ OpenAPI remains authoritative: TypeScript provides static types, not runtime
|
|
|
64
65
|
validation of received data. `include` may be omitted and defaults to `best`
|
|
65
66
|
on the service.
|
|
66
67
|
|
|
68
|
+
The four lookups (`geocode`, `geocodeBatch`, `reverseGeocode`,
|
|
69
|
+
`cadastreParcel`) take `cache` in their options, sent as `Cache-Control`:
|
|
70
|
+
`{ refresh: true }` asks the provider again and stores the new answer,
|
|
71
|
+
`{ refresh: true, noStore: true }` bypasses the store entirely, `{ maxAge }`
|
|
72
|
+
asks again past that many seconds, `{ onlyIfCached: true }` never asks the
|
|
73
|
+
provider (504 `NOT_CACHED`, or `status: 'NOT_CACHED'` for a batch item).
|
|
74
|
+
|
|
67
75
|
HTTP errors are `ApiError`; their body is JSON when parseable, otherwise text,
|
|
68
76
|
or `undefined` for an empty response. A `503` from `cadastreParcel` with
|
|
69
77
|
`code: 'CADASTRE_BLOCKED'` means the cadastral map is refusing calls: its
|
package/dist/index.d.ts
CHANGED
|
@@ -127,6 +127,22 @@ interface paths {
|
|
|
127
127
|
patch?: never;
|
|
128
128
|
trace?: never;
|
|
129
129
|
};
|
|
130
|
+
'/cadastre/parcels': {
|
|
131
|
+
parameters: {
|
|
132
|
+
query?: never;
|
|
133
|
+
header?: never;
|
|
134
|
+
path?: never;
|
|
135
|
+
cookie?: never;
|
|
136
|
+
};
|
|
137
|
+
get: operations['CadastreController_listParcels'];
|
|
138
|
+
put?: never;
|
|
139
|
+
post?: never;
|
|
140
|
+
delete?: never;
|
|
141
|
+
options?: never;
|
|
142
|
+
head?: never;
|
|
143
|
+
patch?: never;
|
|
144
|
+
trace?: never;
|
|
145
|
+
};
|
|
130
146
|
'/territory/status': {
|
|
131
147
|
parameters: {
|
|
132
148
|
query?: never;
|
|
@@ -355,8 +371,11 @@ interface components {
|
|
|
355
371
|
include?: 'best' | 'full';
|
|
356
372
|
};
|
|
357
373
|
GeocodeResultDto: {
|
|
358
|
-
/**
|
|
359
|
-
|
|
374
|
+
/**
|
|
375
|
+
* @description NOT_CACHED: a batch item refused by Cache-Control only-if-cached.
|
|
376
|
+
* @enum {string}
|
|
377
|
+
*/
|
|
378
|
+
status: 'OK' | 'NO_RESULT' | 'INVALID_QUERY' | 'NOT_CACHED';
|
|
360
379
|
/** @description The normalized query actually used as cache key and provider input. */
|
|
361
380
|
query: string | null;
|
|
362
381
|
lat: number | null;
|
|
@@ -436,6 +455,39 @@ interface components {
|
|
|
436
455
|
/** @description True when the answer came from the cache, no map call. */
|
|
437
456
|
cached: boolean;
|
|
438
457
|
};
|
|
458
|
+
CadastreParcelRowDto: {
|
|
459
|
+
/** @description Canonical cache key: "lat,lng" rounded to 5 decimals. */
|
|
460
|
+
query: string;
|
|
461
|
+
lat: number;
|
|
462
|
+
lng: number;
|
|
463
|
+
/** @example PARTICELLA */
|
|
464
|
+
tipologia: string;
|
|
465
|
+
/** @example B885 */
|
|
466
|
+
codComune: string | null;
|
|
467
|
+
/** @description Municipality name; null when the code is not in the registry. */
|
|
468
|
+
comune: string | null;
|
|
469
|
+
/** @example AL */
|
|
470
|
+
provincia: string | null;
|
|
471
|
+
sezione: string | null;
|
|
472
|
+
/** @example 36 */
|
|
473
|
+
foglio: string | null;
|
|
474
|
+
/** @example G */
|
|
475
|
+
allegato: string | null;
|
|
476
|
+
sviluppo: string | null;
|
|
477
|
+
/** @example 5101 */
|
|
478
|
+
particella: string | null;
|
|
479
|
+
/**
|
|
480
|
+
* Format: date-time
|
|
481
|
+
* @description When the map last gave this answer.
|
|
482
|
+
*/
|
|
483
|
+
updatedAt: string;
|
|
484
|
+
};
|
|
485
|
+
CadastreParcelsPageDto: {
|
|
486
|
+
page: number;
|
|
487
|
+
pageSize: number;
|
|
488
|
+
total: number;
|
|
489
|
+
items: components['schemas']['CadastreParcelRowDto'][];
|
|
490
|
+
};
|
|
439
491
|
TerritoryStatusDto: {
|
|
440
492
|
/** @description Latest OMI publication loaded (`YYYY-S`), null while no supply is loaded. */
|
|
441
493
|
semestre: string | null;
|
|
@@ -652,7 +704,10 @@ interface operations {
|
|
|
652
704
|
GeocodeController_geocode: {
|
|
653
705
|
parameters: {
|
|
654
706
|
query?: never;
|
|
655
|
-
header?:
|
|
707
|
+
header?: {
|
|
708
|
+
/** @description no-cache: ask the provider and store its answer; no-store: never write the store; max-age=N: a stored answer older than N seconds is asked again; only-if-cached: never ask the provider. The response says what happened in Cache-Status (hit, fwd=miss|request|stale, stored) and, on a hit, Age. */
|
|
709
|
+
'Cache-Control'?: string;
|
|
710
|
+
};
|
|
656
711
|
path?: never;
|
|
657
712
|
cookie?: never;
|
|
658
713
|
};
|
|
@@ -684,12 +739,22 @@ interface operations {
|
|
|
684
739
|
};
|
|
685
740
|
content?: never;
|
|
686
741
|
};
|
|
742
|
+
/** @description NOT_CACHED: only-if-cached and no usable stored answer. */
|
|
743
|
+
504: {
|
|
744
|
+
headers: {
|
|
745
|
+
[name: string]: unknown;
|
|
746
|
+
};
|
|
747
|
+
content?: never;
|
|
748
|
+
};
|
|
687
749
|
};
|
|
688
750
|
};
|
|
689
751
|
GeocodeController_geocodeBatch: {
|
|
690
752
|
parameters: {
|
|
691
753
|
query?: never;
|
|
692
|
-
header?:
|
|
754
|
+
header?: {
|
|
755
|
+
/** @description Applies to every item: no-cache, no-store, max-age=N, only-if-cached. An item only-if-cached refuses has status NOT_CACHED; the batch still answers 200. */
|
|
756
|
+
'Cache-Control'?: string;
|
|
757
|
+
};
|
|
693
758
|
path?: never;
|
|
694
759
|
cookie?: never;
|
|
695
760
|
};
|
|
@@ -726,7 +791,10 @@ interface operations {
|
|
|
726
791
|
GeocodeController_reverseGeocode: {
|
|
727
792
|
parameters: {
|
|
728
793
|
query?: never;
|
|
729
|
-
header?:
|
|
794
|
+
header?: {
|
|
795
|
+
/** @description no-cache: ask the provider and store its answer; no-store: never write the store; max-age=N: a stored answer older than N seconds is asked again; only-if-cached: never ask the provider. The response says what happened in Cache-Status (hit, fwd=miss|request|stale, stored) and, on a hit, Age. */
|
|
796
|
+
'Cache-Control'?: string;
|
|
797
|
+
};
|
|
730
798
|
path?: never;
|
|
731
799
|
cookie?: never;
|
|
732
800
|
};
|
|
@@ -758,12 +826,22 @@ interface operations {
|
|
|
758
826
|
};
|
|
759
827
|
content?: never;
|
|
760
828
|
};
|
|
829
|
+
/** @description NOT_CACHED: only-if-cached and no usable stored answer. */
|
|
830
|
+
504: {
|
|
831
|
+
headers: {
|
|
832
|
+
[name: string]: unknown;
|
|
833
|
+
};
|
|
834
|
+
content?: never;
|
|
835
|
+
};
|
|
761
836
|
};
|
|
762
837
|
};
|
|
763
838
|
CadastreController_parcel: {
|
|
764
839
|
parameters: {
|
|
765
840
|
query?: never;
|
|
766
|
-
header?:
|
|
841
|
+
header?: {
|
|
842
|
+
/** @description no-cache: ask the provider and store its answer; no-store: never write the store; max-age=N: a stored answer older than N seconds is asked again; only-if-cached: never ask the provider. The response says what happened in Cache-Status (hit, fwd=miss|request|stale, stored) and, on a hit, Age. */
|
|
843
|
+
'Cache-Control'?: string;
|
|
844
|
+
};
|
|
767
845
|
path?: never;
|
|
768
846
|
cookie?: never;
|
|
769
847
|
};
|
|
@@ -803,6 +881,49 @@ interface operations {
|
|
|
803
881
|
};
|
|
804
882
|
content?: never;
|
|
805
883
|
};
|
|
884
|
+
/** @description NOT_CACHED: only-if-cached and no usable stored answer. */
|
|
885
|
+
504: {
|
|
886
|
+
headers: {
|
|
887
|
+
[name: string]: unknown;
|
|
888
|
+
};
|
|
889
|
+
content?: never;
|
|
890
|
+
};
|
|
891
|
+
};
|
|
892
|
+
};
|
|
893
|
+
CadastreController_listParcels: {
|
|
894
|
+
parameters: {
|
|
895
|
+
query?: {
|
|
896
|
+
page?: number;
|
|
897
|
+
pageSize?: number;
|
|
898
|
+
/** @description Cadastral municipality code. */
|
|
899
|
+
codComune?: string;
|
|
900
|
+
foglio?: string;
|
|
901
|
+
particella?: string;
|
|
902
|
+
/** @description What lies under the point. */
|
|
903
|
+
tipologia?: string;
|
|
904
|
+
};
|
|
905
|
+
header?: never;
|
|
906
|
+
path?: never;
|
|
907
|
+
cookie?: never;
|
|
908
|
+
};
|
|
909
|
+
requestBody?: never;
|
|
910
|
+
responses: {
|
|
911
|
+
/** @description The stored map answers, newest first; never a map call. */
|
|
912
|
+
200: {
|
|
913
|
+
headers: {
|
|
914
|
+
[name: string]: unknown;
|
|
915
|
+
};
|
|
916
|
+
content: {
|
|
917
|
+
'application/json': components['schemas']['CadastreParcelsPageDto'];
|
|
918
|
+
};
|
|
919
|
+
};
|
|
920
|
+
/** @description Missing or invalid API key. */
|
|
921
|
+
401: {
|
|
922
|
+
headers: {
|
|
923
|
+
[name: string]: unknown;
|
|
924
|
+
};
|
|
925
|
+
content?: never;
|
|
926
|
+
};
|
|
806
927
|
};
|
|
807
928
|
};
|
|
808
929
|
TerritoryController_status: {
|
|
@@ -1044,6 +1165,8 @@ type ReverseGeocodeRequest = ApiSchemas['ReverseGeocodeRequestDto'];
|
|
|
1044
1165
|
type ReverseGeocodeResult = ApiSchemas['ReverseGeocodeResultDto'];
|
|
1045
1166
|
type CadastreParcelRequest = ApiSchemas['CadastreParcelRequestDto'];
|
|
1046
1167
|
type CadastreParcelResult = ApiSchemas['CadastreParcelResultDto'];
|
|
1168
|
+
type CadastreParcelsPage = ApiSchemas['CadastreParcelsPageDto'];
|
|
1169
|
+
type CadastreParcelRow = ApiSchemas['CadastreParcelRowDto'];
|
|
1047
1170
|
type TerritoryStatus = ApiSchemas['TerritoryStatusDto'];
|
|
1048
1171
|
type TerritoryResolveRequest = ApiSchemas['TerritoryResolveRequestDto'];
|
|
1049
1172
|
type TerritoryResolveResponse = ApiSchemas['TerritoryResolveResponseDto'];
|
|
@@ -1062,9 +1185,27 @@ type TerritoryCompravendita = ApiSchemas['TerritoryCompravenditaDto'];
|
|
|
1062
1185
|
type TerritoryComuniQuery = NonNullable<ApiPaths['/territory/comuni']['get']['parameters']['query']>;
|
|
1063
1186
|
type TerritoryQuotazioniQuery = NonNullable<ApiPaths['/territory/quotazioni']['get']['parameters']['query']>;
|
|
1064
1187
|
type TerritoryCompravenditeQuery = NonNullable<ApiPaths['/territory/compravendite']['get']['parameters']['query']>;
|
|
1188
|
+
type CadastreParcelsQuery = NonNullable<ApiPaths['/cadastre/parcels']['get']['parameters']['query']>;
|
|
1065
1189
|
interface RequestOptions {
|
|
1066
1190
|
signal?: AbortSignal;
|
|
1067
1191
|
}
|
|
1192
|
+
/**
|
|
1193
|
+
* How a lookup may use seta-geo's store, sent as `Cache-Control` (RFC 9111).
|
|
1194
|
+
* Without it the store answers when it can and the provider otherwise.
|
|
1195
|
+
*/
|
|
1196
|
+
interface LookupCache {
|
|
1197
|
+
/** `no-cache`: ask the provider even with a stored answer, and store the new one. */
|
|
1198
|
+
refresh?: boolean;
|
|
1199
|
+
/** `no-store`: never write the provider's answer (with `refresh`: a pure bypass). */
|
|
1200
|
+
noStore?: boolean;
|
|
1201
|
+
/** `max-age`: a stored answer older than this many seconds is asked again. */
|
|
1202
|
+
maxAge?: number;
|
|
1203
|
+
/** `only-if-cached`: never ask the provider; 504 `NOT_CACHED` without a stored answer. */
|
|
1204
|
+
onlyIfCached?: boolean;
|
|
1205
|
+
}
|
|
1206
|
+
interface LookupOptions extends RequestOptions {
|
|
1207
|
+
cache?: LookupCache;
|
|
1208
|
+
}
|
|
1068
1209
|
interface GeoClientOptions {
|
|
1069
1210
|
/** Complete API root, including /api. Relative roots are supported in browsers. */
|
|
1070
1211
|
baseUrl: string;
|
|
@@ -1083,15 +1224,18 @@ interface TerritoryClient {
|
|
|
1083
1224
|
resolve(input: TerritoryResolveRequest, options?: RequestOptions): Promise<TerritoryResolveResponse>;
|
|
1084
1225
|
}
|
|
1085
1226
|
interface GeoClient {
|
|
1086
|
-
geocode(input: GeocodeRequest, options?:
|
|
1087
|
-
|
|
1088
|
-
|
|
1227
|
+
geocode(input: GeocodeRequest, options?: LookupOptions): Promise<GeocodeResult>;
|
|
1228
|
+
/** `cache` applies to every item; an item only-if-cached refuses has status NOT_CACHED. */
|
|
1229
|
+
geocodeBatch(input: GeocodeBatchRequest, options?: LookupOptions): Promise<GeocodeBatchResponse>;
|
|
1230
|
+
reverseGeocode(input: ReverseGeocodeRequest, options?: LookupOptions): Promise<ReverseGeocodeResult>;
|
|
1089
1231
|
/** What the AdE cadastral map finds under a point; 503 `CADASTRE_BLOCKED` carries Retry-After. */
|
|
1090
|
-
cadastreParcel(input: CadastreParcelRequest, options?:
|
|
1232
|
+
cadastreParcel(input: CadastreParcelRequest, options?: LookupOptions): Promise<CadastreParcelResult>;
|
|
1233
|
+
/** The stored cadastral answers, newest first: a read of the store, never a map call. */
|
|
1234
|
+
cadastreParcels(query?: CadastreParcelsQuery, options?: RequestOptions): Promise<CadastreParcelsPage>;
|
|
1091
1235
|
territory: TerritoryClient;
|
|
1092
1236
|
}
|
|
1093
1237
|
|
|
1094
1238
|
declare function createGeoClient(options: GeoClientOptions): GeoClient;
|
|
1095
1239
|
|
|
1096
1240
|
export { ApiError, createGeoClient };
|
|
1097
|
-
export type { CadastreParcelRequest, CadastreParcelResult, GeoClient, GeoClientOptions, GeocodeBatchRequest, GeocodeBatchResponse, GeocodeRequest, GeocodeResult, RequestOptions, ReverseGeocodeRequest, ReverseGeocodeResult, TerritoryClient, TerritoryCompravendita, TerritoryCompravenditePage, TerritoryCompravenditeQuery, TerritoryComune, TerritoryComuneDetail, TerritoryComuneRiga, TerritoryComuniPage, TerritoryComuniQuery, TerritoryDatasets, TerritoryOmi, TerritoryPointResult, TerritoryQuotazione, TerritoryQuotazioniPage, TerritoryQuotazioniQuery, TerritoryResolveRequest, TerritoryResolveResponse, TerritoryStatus };
|
|
1241
|
+
export type { CadastreParcelRequest, CadastreParcelResult, CadastreParcelRow, CadastreParcelsPage, CadastreParcelsQuery, GeoClient, GeoClientOptions, GeocodeBatchRequest, GeocodeBatchResponse, GeocodeRequest, GeocodeResult, LookupCache, LookupOptions, RequestOptions, ReverseGeocodeRequest, ReverseGeocodeResult, TerritoryClient, TerritoryCompravendita, TerritoryCompravenditePage, TerritoryCompravenditeQuery, TerritoryComune, TerritoryComuneDetail, TerritoryComuneRiga, TerritoryComuniPage, TerritoryComuniQuery, TerritoryDatasets, TerritoryOmi, TerritoryPointResult, TerritoryQuotazione, TerritoryQuotazioniPage, TerritoryQuotazioniQuery, TerritoryResolveRequest, TerritoryResolveResponse, TerritoryStatus };
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,21 @@ async function data(request) {
|
|
|
39
39
|
if (result.data === void 0) throw new SyntaxError("Geo API returned an empty JSON response");
|
|
40
40
|
return result.data;
|
|
41
41
|
}
|
|
42
|
+
function cacheControl(cache) {
|
|
43
|
+
if (!cache) return void 0;
|
|
44
|
+
const directives = [
|
|
45
|
+
cache.refresh ? "no-cache" : void 0,
|
|
46
|
+
cache.noStore ? "no-store" : void 0,
|
|
47
|
+
cache.maxAge === void 0 ? void 0 : `max-age=${Math.max(0, Math.floor(cache.maxAge))}`,
|
|
48
|
+
cache.onlyIfCached ? "only-if-cached" : void 0
|
|
49
|
+
].filter((directive) => directive !== void 0);
|
|
50
|
+
return directives.length > 0 ? directives.join(", ") : void 0;
|
|
51
|
+
}
|
|
52
|
+
function lookupInit(options) {
|
|
53
|
+
const { cache, ...request } = options ?? {};
|
|
54
|
+
const header = cacheControl(cache);
|
|
55
|
+
return header ? { ...request, headers: { "cache-control": header } } : request;
|
|
56
|
+
}
|
|
42
57
|
function territory(client) {
|
|
43
58
|
return {
|
|
44
59
|
status: (options) => data(client.GET("/territory/status", { ...options })),
|
|
@@ -67,10 +82,11 @@ function createGeoClient(options) {
|
|
|
67
82
|
}
|
|
68
83
|
});
|
|
69
84
|
return {
|
|
70
|
-
geocode: (input, request) => data(client.POST("/geocode", { ...request, body: input })),
|
|
71
|
-
geocodeBatch: (input, request) => data(client.POST("/geocode/batch", { ...request, body: input })),
|
|
72
|
-
reverseGeocode: (input, request) => data(client.POST("/geocode/reverse", { ...request, body: input })),
|
|
73
|
-
cadastreParcel: (input, request) => data(client.POST("/cadastre/parcel", { ...request, body: input })),
|
|
85
|
+
geocode: (input, request) => data(client.POST("/geocode", { ...lookupInit(request), body: input })),
|
|
86
|
+
geocodeBatch: (input, request) => data(client.POST("/geocode/batch", { ...lookupInit(request), body: input })),
|
|
87
|
+
reverseGeocode: (input, request) => data(client.POST("/geocode/reverse", { ...lookupInit(request), body: input })),
|
|
88
|
+
cadastreParcel: (input, request) => data(client.POST("/cadastre/parcel", { ...lookupInit(request), body: input })),
|
|
89
|
+
cadastreParcels: (query, options2) => data(client.GET("/cadastre/parcels", { ...options2, params: { query } })),
|
|
74
90
|
territory: territory(client)
|
|
75
91
|
};
|
|
76
92
|
}
|