catastrogps 1.0.0 → 1.1.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/README.md +33 -1
- package/dist/index.d.mts +126 -2
- package/dist/index.d.ts +126 -2
- package/dist/index.js +112 -14
- package/dist/index.mjs +112 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,8 +55,40 @@ guess.candidates;
|
|
|
55
55
|
client.lastQuota;
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
`client.lastQuota` is the monthly quota of your plan as of the last response: `{ plan, limit, remaining, resetsAt }`, read from the `X-Quota-Tier`, `X-Quota-Limit`, `X-Quota-Remaining` and `X-Quota-Reset` headers. The `X-RateLimit-*` headers are a different thing: a per-key burst limit per minute that depends on your plan (Free 10, Developer 60, Startup 120, Growth 300; a global per-IP guard also applies) that the client handles by retrying.
|
|
59
|
+
|
|
58
60
|
Responses are the API's `data` object, with the field names the API uses (`refCatastral`, `municipio`, `superficieParcela`…). See the [API reference](https://www.catastrogps.es/developers).
|
|
59
61
|
|
|
62
|
+
## Importar una comunidad de propietarios (Spain)
|
|
63
|
+
|
|
64
|
+
Address → finca (14-character reference) → every unit, with use, area, participation coefficient, stair, floor and door.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const { candidatos } = await client.searchAddressCandidates('Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas');
|
|
68
|
+
const finca = candidatos[0];
|
|
69
|
+
finca.refCatastral;
|
|
70
|
+
finca.confianza;
|
|
71
|
+
finca.pais;
|
|
72
|
+
|
|
73
|
+
const comunidad = await client.getUnits(finca.refCatastral);
|
|
74
|
+
comunidad.totalUnidadesFinca;
|
|
75
|
+
for (const u of comunidad.unidades) {
|
|
76
|
+
console.log(u.refCatastral, u.uso, u.superficie, u.participacion, u.escalera, u.planta, u.puerta);
|
|
77
|
+
}
|
|
78
|
+
comunidad.dataSource;
|
|
79
|
+
comunidad.dataDate;
|
|
80
|
+
comunidad.attribution;
|
|
81
|
+
|
|
82
|
+
const refreshed = await client.getUnits(finca.refCatastral, { previous: comunidad });
|
|
83
|
+
refreshed.changed;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `searchAddressCandidates` also takes `{ street, number, municipality, postcode, limit }`. Candidates come ranked by `confianza` (0.75 or more: number and municipality match). It costs 1 quota unit.
|
|
87
|
+
- `getUnits` follows `nextCursor` for you (200 units per page) and costs one quota unit per 50 units, minimum one per page. `iterUnitPages(ref)` yields page by page.
|
|
88
|
+
- Pass the previous result as `previous` to re-import: pages that did not change come back as `304 Not Modified`, cost nothing, and are reused; `changed` tells you if anything moved.
|
|
89
|
+
- Fincas in the Basque Country or Navarra (`pais: 'PV' | 'NA'`) throw `CoverageError`: their foral cadastres are not served per finca.
|
|
90
|
+
- A `ServiceUnavailableError` carries `retryAfterSeconds`; the client already waits for it (up to 60 s) before its retries.
|
|
91
|
+
|
|
60
92
|
## Errors
|
|
61
93
|
|
|
62
94
|
Every error is a `CatastroGPSError` with `status`, `code` and `details`. Subclasses let you branch cleanly:
|
|
@@ -82,7 +114,7 @@ try {
|
|
|
82
114
|
|
|
83
115
|
Also available: `AuthenticationError`, `ValidationError`, `RateLimitError`, `ServiceUnavailableError`, `ServerError`, `TimeoutError`, `NetworkError`.
|
|
84
116
|
|
|
85
|
-
Timeouts, network errors, 429 rate limits and 502/503/504 are retried up to `maxRetries` times (default 2) with exponential backoff. An exhausted monthly quota is never retried.
|
|
117
|
+
Timeouts, network errors, 429 rate limits and 502/503/504 are retried up to `maxRetries` times (default 2) with exponential backoff. An exhausted monthly quota is never retried. Only 2xx responses spend quota; failed attempts and `304 Not Modified` are free.
|
|
86
118
|
|
|
87
119
|
## Options
|
|
88
120
|
|
package/dist/index.d.mts
CHANGED
|
@@ -117,6 +117,110 @@ interface ResolveResult {
|
|
|
117
117
|
candidates: ResolveCandidate[];
|
|
118
118
|
ambiguous: boolean;
|
|
119
119
|
}
|
|
120
|
+
interface AddressCandidatesQuery {
|
|
121
|
+
q?: string;
|
|
122
|
+
street?: string;
|
|
123
|
+
number?: number;
|
|
124
|
+
municipality?: string;
|
|
125
|
+
postcode?: string;
|
|
126
|
+
limit?: number;
|
|
127
|
+
}
|
|
128
|
+
interface AddressCandidate {
|
|
129
|
+
refCatastral: string;
|
|
130
|
+
pais: 'ES' | 'PV' | 'NA' | string;
|
|
131
|
+
direccion: string;
|
|
132
|
+
numero?: number;
|
|
133
|
+
codigoPostal?: string;
|
|
134
|
+
municipio: string;
|
|
135
|
+
provincia: string;
|
|
136
|
+
latitud: number;
|
|
137
|
+
longitud: number;
|
|
138
|
+
confianza: number;
|
|
139
|
+
coincideNumero: boolean;
|
|
140
|
+
coincideMunicipio: boolean;
|
|
141
|
+
enCopia: boolean;
|
|
142
|
+
direccionCatastro?: string;
|
|
143
|
+
uso?: string;
|
|
144
|
+
viviendas?: number;
|
|
145
|
+
anioConstruccion?: number;
|
|
146
|
+
}
|
|
147
|
+
interface AddressCandidatesResult {
|
|
148
|
+
consulta: {
|
|
149
|
+
texto: string;
|
|
150
|
+
calle?: string;
|
|
151
|
+
numero?: number;
|
|
152
|
+
municipio?: string;
|
|
153
|
+
codigoPostal?: string;
|
|
154
|
+
};
|
|
155
|
+
candidatos: AddressCandidate[];
|
|
156
|
+
attribution: string;
|
|
157
|
+
}
|
|
158
|
+
interface Unit {
|
|
159
|
+
refCatastral: string;
|
|
160
|
+
escalera: string;
|
|
161
|
+
planta: string;
|
|
162
|
+
puerta: string;
|
|
163
|
+
uso: string;
|
|
164
|
+
superficie: number;
|
|
165
|
+
descripcion: string;
|
|
166
|
+
participacion?: number;
|
|
167
|
+
anio?: number;
|
|
168
|
+
direccion?: string;
|
|
169
|
+
}
|
|
170
|
+
interface Construction {
|
|
171
|
+
escalera: string;
|
|
172
|
+
planta: string;
|
|
173
|
+
puerta: string;
|
|
174
|
+
uso: string;
|
|
175
|
+
superficie: number;
|
|
176
|
+
descripcion: string;
|
|
177
|
+
}
|
|
178
|
+
interface UnitsPageData {
|
|
179
|
+
refCatastral: string;
|
|
180
|
+
direccion?: string;
|
|
181
|
+
codigoPostal?: string;
|
|
182
|
+
municipio?: string;
|
|
183
|
+
provincia?: string;
|
|
184
|
+
usoGeneral?: string;
|
|
185
|
+
superficieTotal?: number;
|
|
186
|
+
anioConstruccion?: number;
|
|
187
|
+
participacion?: string;
|
|
188
|
+
totalUnidades: number;
|
|
189
|
+
totalUnidadesFinca: number;
|
|
190
|
+
unidades: Unit[];
|
|
191
|
+
construcciones?: Construction[];
|
|
192
|
+
truncated: boolean;
|
|
193
|
+
nextCursor?: string;
|
|
194
|
+
dataSource: 'clone' | 'catastro' | string;
|
|
195
|
+
dataDate: string;
|
|
196
|
+
attribution: string;
|
|
197
|
+
}
|
|
198
|
+
interface UnitsPage {
|
|
199
|
+
cursor?: string;
|
|
200
|
+
etag?: string;
|
|
201
|
+
notModified: boolean;
|
|
202
|
+
data: UnitsPageData;
|
|
203
|
+
}
|
|
204
|
+
interface UnitsResult {
|
|
205
|
+
refCatastral: string;
|
|
206
|
+
direccion?: string;
|
|
207
|
+
codigoPostal?: string;
|
|
208
|
+
municipio?: string;
|
|
209
|
+
provincia?: string;
|
|
210
|
+
usoGeneral?: string;
|
|
211
|
+
anioConstruccion?: number;
|
|
212
|
+
totalUnidadesFinca: number;
|
|
213
|
+
unidades: Unit[];
|
|
214
|
+
construcciones: Construction[];
|
|
215
|
+
dataSource: string;
|
|
216
|
+
dataDate: string;
|
|
217
|
+
attribution: string;
|
|
218
|
+
changed: boolean;
|
|
219
|
+
pages: UnitsPage[];
|
|
220
|
+
}
|
|
221
|
+
interface GetUnitsOptions {
|
|
222
|
+
previous?: UnitsResult;
|
|
223
|
+
}
|
|
120
224
|
|
|
121
225
|
declare class ExportResource {
|
|
122
226
|
private readonly client;
|
|
@@ -124,6 +228,14 @@ declare class ExportResource {
|
|
|
124
228
|
file(reference: string, format: ExportFormat, options?: CountryOption): Promise<ArrayBuffer>;
|
|
125
229
|
}
|
|
126
230
|
|
|
231
|
+
declare class FincasResource {
|
|
232
|
+
private readonly client;
|
|
233
|
+
constructor(client: CatastroGPS);
|
|
234
|
+
searchAddress(query: string | AddressCandidatesQuery): Promise<AddressCandidatesResult>;
|
|
235
|
+
pages(refcat14: string, options?: GetUnitsOptions): AsyncGenerator<UnitsPage>;
|
|
236
|
+
units(refcat14: string, options?: GetUnitsOptions): Promise<UnitsResult>;
|
|
237
|
+
}
|
|
238
|
+
|
|
127
239
|
interface PointQuery extends CountryOption {
|
|
128
240
|
lat: number;
|
|
129
241
|
lng: number;
|
|
@@ -147,10 +259,17 @@ interface RequestOptions {
|
|
|
147
259
|
query?: Query;
|
|
148
260
|
body?: unknown;
|
|
149
261
|
raw?: boolean;
|
|
262
|
+
ifNoneMatch?: string;
|
|
263
|
+
}
|
|
264
|
+
interface ConditionalResponse<T> {
|
|
265
|
+
data?: T;
|
|
266
|
+
etag?: string;
|
|
267
|
+
notModified: boolean;
|
|
150
268
|
}
|
|
151
269
|
declare class CatastroGPS {
|
|
152
270
|
readonly parcels: ParcelsResource;
|
|
153
271
|
readonly export: ExportResource;
|
|
272
|
+
readonly fincas: FincasResource;
|
|
154
273
|
lastQuota?: Quota;
|
|
155
274
|
private readonly apiKey;
|
|
156
275
|
private readonly baseUrl;
|
|
@@ -158,10 +277,14 @@ declare class CatastroGPS {
|
|
|
158
277
|
private readonly maxRetries;
|
|
159
278
|
private readonly fetchImpl;
|
|
160
279
|
constructor(options?: CatastroGPSOptions);
|
|
280
|
+
searchAddressCandidates(query: string | AddressCandidatesQuery): Promise<AddressCandidatesResult>;
|
|
281
|
+
getUnits(refcat14: string, options?: GetUnitsOptions): Promise<UnitsResult>;
|
|
282
|
+
iterUnitPages(refcat14: string, options?: GetUnitsOptions): AsyncGenerator<UnitsPage>;
|
|
161
283
|
resolve(text: string, options?: {
|
|
162
284
|
hint?: string;
|
|
163
285
|
}): Promise<ResolveResult>;
|
|
164
286
|
request<T>(method: 'GET' | 'POST', path: string, options?: RequestOptions): Promise<T>;
|
|
287
|
+
conditionalRequest<T>(method: 'GET' | 'POST', path: string, options?: RequestOptions): Promise<ConditionalResponse<T>>;
|
|
165
288
|
private once;
|
|
166
289
|
private buildUrl;
|
|
167
290
|
private shouldRetry;
|
|
@@ -169,7 +292,7 @@ declare class CatastroGPS {
|
|
|
169
292
|
private captureQuota;
|
|
170
293
|
}
|
|
171
294
|
|
|
172
|
-
declare const VERSION = "1.
|
|
295
|
+
declare const VERSION = "1.1.0";
|
|
173
296
|
|
|
174
297
|
declare class CatastroGPSError extends Error {
|
|
175
298
|
readonly status?: number;
|
|
@@ -215,6 +338,7 @@ declare class RateLimitError extends CatastroGPSError {
|
|
|
215
338
|
}
|
|
216
339
|
declare class ServiceUnavailableError extends CatastroGPSError {
|
|
217
340
|
name: string;
|
|
341
|
+
retryAfterSeconds?: number;
|
|
218
342
|
}
|
|
219
343
|
declare class ServerError extends CatastroGPSError {
|
|
220
344
|
name: string;
|
|
@@ -226,4 +350,4 @@ declare class NetworkError extends CatastroGPSError {
|
|
|
226
350
|
name: string;
|
|
227
351
|
}
|
|
228
352
|
|
|
229
|
-
export { type AddressMatch, type AgricultureData, AmbiguousReferenceError, AuthenticationError, COUNTRY_CODES, CatastroGPS, CatastroGPSError, type CatastroGPSOptions, type CountryCode, type CountryOption, CoverageError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, ENRICHMENT_COUNTRY_CODES, type EnrichmentCountryCode, type ExportFormat, type FetchLike, ForbiddenError, NetworkError, NotFoundError, type Parcel, type ParcelGeometry, type PointMatch, type PointQuery, type Quota, QuotaExceededError, RateLimitError, type ResolveCandidate, type ResolveResult, ServerError, ServiceUnavailableError, type SolarEstimate, TimeoutError, VERSION, ValidationError };
|
|
353
|
+
export { type AddressCandidate, type AddressCandidatesQuery, type AddressCandidatesResult, type AddressMatch, type AgricultureData, AmbiguousReferenceError, AuthenticationError, COUNTRY_CODES, CatastroGPS, CatastroGPSError, type CatastroGPSOptions, type ConditionalResponse, type Construction, type CountryCode, type CountryOption, CoverageError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, ENRICHMENT_COUNTRY_CODES, type EnrichmentCountryCode, type ExportFormat, type FetchLike, ForbiddenError, type GetUnitsOptions, NetworkError, NotFoundError, type Parcel, type ParcelGeometry, type PointMatch, type PointQuery, type Quota, QuotaExceededError, RateLimitError, type ResolveCandidate, type ResolveResult, ServerError, ServiceUnavailableError, type SolarEstimate, TimeoutError, type Unit, type UnitsPage, type UnitsPageData, type UnitsResult, VERSION, ValidationError };
|
package/dist/index.d.ts
CHANGED
|
@@ -117,6 +117,110 @@ interface ResolveResult {
|
|
|
117
117
|
candidates: ResolveCandidate[];
|
|
118
118
|
ambiguous: boolean;
|
|
119
119
|
}
|
|
120
|
+
interface AddressCandidatesQuery {
|
|
121
|
+
q?: string;
|
|
122
|
+
street?: string;
|
|
123
|
+
number?: number;
|
|
124
|
+
municipality?: string;
|
|
125
|
+
postcode?: string;
|
|
126
|
+
limit?: number;
|
|
127
|
+
}
|
|
128
|
+
interface AddressCandidate {
|
|
129
|
+
refCatastral: string;
|
|
130
|
+
pais: 'ES' | 'PV' | 'NA' | string;
|
|
131
|
+
direccion: string;
|
|
132
|
+
numero?: number;
|
|
133
|
+
codigoPostal?: string;
|
|
134
|
+
municipio: string;
|
|
135
|
+
provincia: string;
|
|
136
|
+
latitud: number;
|
|
137
|
+
longitud: number;
|
|
138
|
+
confianza: number;
|
|
139
|
+
coincideNumero: boolean;
|
|
140
|
+
coincideMunicipio: boolean;
|
|
141
|
+
enCopia: boolean;
|
|
142
|
+
direccionCatastro?: string;
|
|
143
|
+
uso?: string;
|
|
144
|
+
viviendas?: number;
|
|
145
|
+
anioConstruccion?: number;
|
|
146
|
+
}
|
|
147
|
+
interface AddressCandidatesResult {
|
|
148
|
+
consulta: {
|
|
149
|
+
texto: string;
|
|
150
|
+
calle?: string;
|
|
151
|
+
numero?: number;
|
|
152
|
+
municipio?: string;
|
|
153
|
+
codigoPostal?: string;
|
|
154
|
+
};
|
|
155
|
+
candidatos: AddressCandidate[];
|
|
156
|
+
attribution: string;
|
|
157
|
+
}
|
|
158
|
+
interface Unit {
|
|
159
|
+
refCatastral: string;
|
|
160
|
+
escalera: string;
|
|
161
|
+
planta: string;
|
|
162
|
+
puerta: string;
|
|
163
|
+
uso: string;
|
|
164
|
+
superficie: number;
|
|
165
|
+
descripcion: string;
|
|
166
|
+
participacion?: number;
|
|
167
|
+
anio?: number;
|
|
168
|
+
direccion?: string;
|
|
169
|
+
}
|
|
170
|
+
interface Construction {
|
|
171
|
+
escalera: string;
|
|
172
|
+
planta: string;
|
|
173
|
+
puerta: string;
|
|
174
|
+
uso: string;
|
|
175
|
+
superficie: number;
|
|
176
|
+
descripcion: string;
|
|
177
|
+
}
|
|
178
|
+
interface UnitsPageData {
|
|
179
|
+
refCatastral: string;
|
|
180
|
+
direccion?: string;
|
|
181
|
+
codigoPostal?: string;
|
|
182
|
+
municipio?: string;
|
|
183
|
+
provincia?: string;
|
|
184
|
+
usoGeneral?: string;
|
|
185
|
+
superficieTotal?: number;
|
|
186
|
+
anioConstruccion?: number;
|
|
187
|
+
participacion?: string;
|
|
188
|
+
totalUnidades: number;
|
|
189
|
+
totalUnidadesFinca: number;
|
|
190
|
+
unidades: Unit[];
|
|
191
|
+
construcciones?: Construction[];
|
|
192
|
+
truncated: boolean;
|
|
193
|
+
nextCursor?: string;
|
|
194
|
+
dataSource: 'clone' | 'catastro' | string;
|
|
195
|
+
dataDate: string;
|
|
196
|
+
attribution: string;
|
|
197
|
+
}
|
|
198
|
+
interface UnitsPage {
|
|
199
|
+
cursor?: string;
|
|
200
|
+
etag?: string;
|
|
201
|
+
notModified: boolean;
|
|
202
|
+
data: UnitsPageData;
|
|
203
|
+
}
|
|
204
|
+
interface UnitsResult {
|
|
205
|
+
refCatastral: string;
|
|
206
|
+
direccion?: string;
|
|
207
|
+
codigoPostal?: string;
|
|
208
|
+
municipio?: string;
|
|
209
|
+
provincia?: string;
|
|
210
|
+
usoGeneral?: string;
|
|
211
|
+
anioConstruccion?: number;
|
|
212
|
+
totalUnidadesFinca: number;
|
|
213
|
+
unidades: Unit[];
|
|
214
|
+
construcciones: Construction[];
|
|
215
|
+
dataSource: string;
|
|
216
|
+
dataDate: string;
|
|
217
|
+
attribution: string;
|
|
218
|
+
changed: boolean;
|
|
219
|
+
pages: UnitsPage[];
|
|
220
|
+
}
|
|
221
|
+
interface GetUnitsOptions {
|
|
222
|
+
previous?: UnitsResult;
|
|
223
|
+
}
|
|
120
224
|
|
|
121
225
|
declare class ExportResource {
|
|
122
226
|
private readonly client;
|
|
@@ -124,6 +228,14 @@ declare class ExportResource {
|
|
|
124
228
|
file(reference: string, format: ExportFormat, options?: CountryOption): Promise<ArrayBuffer>;
|
|
125
229
|
}
|
|
126
230
|
|
|
231
|
+
declare class FincasResource {
|
|
232
|
+
private readonly client;
|
|
233
|
+
constructor(client: CatastroGPS);
|
|
234
|
+
searchAddress(query: string | AddressCandidatesQuery): Promise<AddressCandidatesResult>;
|
|
235
|
+
pages(refcat14: string, options?: GetUnitsOptions): AsyncGenerator<UnitsPage>;
|
|
236
|
+
units(refcat14: string, options?: GetUnitsOptions): Promise<UnitsResult>;
|
|
237
|
+
}
|
|
238
|
+
|
|
127
239
|
interface PointQuery extends CountryOption {
|
|
128
240
|
lat: number;
|
|
129
241
|
lng: number;
|
|
@@ -147,10 +259,17 @@ interface RequestOptions {
|
|
|
147
259
|
query?: Query;
|
|
148
260
|
body?: unknown;
|
|
149
261
|
raw?: boolean;
|
|
262
|
+
ifNoneMatch?: string;
|
|
263
|
+
}
|
|
264
|
+
interface ConditionalResponse<T> {
|
|
265
|
+
data?: T;
|
|
266
|
+
etag?: string;
|
|
267
|
+
notModified: boolean;
|
|
150
268
|
}
|
|
151
269
|
declare class CatastroGPS {
|
|
152
270
|
readonly parcels: ParcelsResource;
|
|
153
271
|
readonly export: ExportResource;
|
|
272
|
+
readonly fincas: FincasResource;
|
|
154
273
|
lastQuota?: Quota;
|
|
155
274
|
private readonly apiKey;
|
|
156
275
|
private readonly baseUrl;
|
|
@@ -158,10 +277,14 @@ declare class CatastroGPS {
|
|
|
158
277
|
private readonly maxRetries;
|
|
159
278
|
private readonly fetchImpl;
|
|
160
279
|
constructor(options?: CatastroGPSOptions);
|
|
280
|
+
searchAddressCandidates(query: string | AddressCandidatesQuery): Promise<AddressCandidatesResult>;
|
|
281
|
+
getUnits(refcat14: string, options?: GetUnitsOptions): Promise<UnitsResult>;
|
|
282
|
+
iterUnitPages(refcat14: string, options?: GetUnitsOptions): AsyncGenerator<UnitsPage>;
|
|
161
283
|
resolve(text: string, options?: {
|
|
162
284
|
hint?: string;
|
|
163
285
|
}): Promise<ResolveResult>;
|
|
164
286
|
request<T>(method: 'GET' | 'POST', path: string, options?: RequestOptions): Promise<T>;
|
|
287
|
+
conditionalRequest<T>(method: 'GET' | 'POST', path: string, options?: RequestOptions): Promise<ConditionalResponse<T>>;
|
|
165
288
|
private once;
|
|
166
289
|
private buildUrl;
|
|
167
290
|
private shouldRetry;
|
|
@@ -169,7 +292,7 @@ declare class CatastroGPS {
|
|
|
169
292
|
private captureQuota;
|
|
170
293
|
}
|
|
171
294
|
|
|
172
|
-
declare const VERSION = "1.
|
|
295
|
+
declare const VERSION = "1.1.0";
|
|
173
296
|
|
|
174
297
|
declare class CatastroGPSError extends Error {
|
|
175
298
|
readonly status?: number;
|
|
@@ -215,6 +338,7 @@ declare class RateLimitError extends CatastroGPSError {
|
|
|
215
338
|
}
|
|
216
339
|
declare class ServiceUnavailableError extends CatastroGPSError {
|
|
217
340
|
name: string;
|
|
341
|
+
retryAfterSeconds?: number;
|
|
218
342
|
}
|
|
219
343
|
declare class ServerError extends CatastroGPSError {
|
|
220
344
|
name: string;
|
|
@@ -226,4 +350,4 @@ declare class NetworkError extends CatastroGPSError {
|
|
|
226
350
|
name: string;
|
|
227
351
|
}
|
|
228
352
|
|
|
229
|
-
export { type AddressMatch, type AgricultureData, AmbiguousReferenceError, AuthenticationError, COUNTRY_CODES, CatastroGPS, CatastroGPSError, type CatastroGPSOptions, type CountryCode, type CountryOption, CoverageError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, ENRICHMENT_COUNTRY_CODES, type EnrichmentCountryCode, type ExportFormat, type FetchLike, ForbiddenError, NetworkError, NotFoundError, type Parcel, type ParcelGeometry, type PointMatch, type PointQuery, type Quota, QuotaExceededError, RateLimitError, type ResolveCandidate, type ResolveResult, ServerError, ServiceUnavailableError, type SolarEstimate, TimeoutError, VERSION, ValidationError };
|
|
353
|
+
export { type AddressCandidate, type AddressCandidatesQuery, type AddressCandidatesResult, type AddressMatch, type AgricultureData, AmbiguousReferenceError, AuthenticationError, COUNTRY_CODES, CatastroGPS, CatastroGPSError, type CatastroGPSOptions, type ConditionalResponse, type Construction, type CountryCode, type CountryOption, CoverageError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, ENRICHMENT_COUNTRY_CODES, type EnrichmentCountryCode, type ExportFormat, type FetchLike, ForbiddenError, type GetUnitsOptions, NetworkError, NotFoundError, type Parcel, type ParcelGeometry, type PointMatch, type PointQuery, type Quota, QuotaExceededError, RateLimitError, type ResolveCandidate, type ResolveResult, ServerError, ServiceUnavailableError, type SolarEstimate, TimeoutError, type Unit, type UnitsPage, type UnitsPageData, type UnitsResult, VERSION, ValidationError };
|
package/dist/index.js
CHANGED
|
@@ -89,6 +89,7 @@ var RateLimitError = class extends CatastroGPSError {
|
|
|
89
89
|
};
|
|
90
90
|
var ServiceUnavailableError = class extends CatastroGPSError {
|
|
91
91
|
name = "ServiceUnavailableError";
|
|
92
|
+
retryAfterSeconds;
|
|
92
93
|
};
|
|
93
94
|
var ServerError = class extends CatastroGPSError {
|
|
94
95
|
name = "ServerError";
|
|
@@ -116,7 +117,11 @@ function errorFromResponse(status, body, retryAfter) {
|
|
|
116
117
|
if (status === 403) return new ForbiddenError(message, options);
|
|
117
118
|
if (status === 404) return new NotFoundError(message, options);
|
|
118
119
|
if (status === 400 || status === 422) return new ValidationError(message, options);
|
|
119
|
-
if (status === 503)
|
|
120
|
+
if (status === 503) {
|
|
121
|
+
const error = new ServiceUnavailableError(message, options);
|
|
122
|
+
error.retryAfterSeconds = retryAfter;
|
|
123
|
+
return error;
|
|
124
|
+
}
|
|
120
125
|
if (status >= 500) return new ServerError(message, options);
|
|
121
126
|
return new CatastroGPSError(message, options);
|
|
122
127
|
}
|
|
@@ -179,8 +184,73 @@ function parcelPath(reference, suffix = "") {
|
|
|
179
184
|
return `/api/catastro/${encodeURIComponent(reference.trim())}${suffix}`;
|
|
180
185
|
}
|
|
181
186
|
|
|
187
|
+
// src/resources/fincas.ts
|
|
188
|
+
var MAX_PAGES = 1e3;
|
|
189
|
+
var FincasResource = class {
|
|
190
|
+
constructor(client) {
|
|
191
|
+
this.client = client;
|
|
192
|
+
}
|
|
193
|
+
client;
|
|
194
|
+
async searchAddress(query) {
|
|
195
|
+
const params = typeof query === "string" ? { q: query } : query;
|
|
196
|
+
if (!params.q?.trim() && !params.street?.trim()) throw new CatastroGPSError("q or street is required");
|
|
197
|
+
return this.client.request("GET", "/api/search/address/candidates", {
|
|
198
|
+
query: {
|
|
199
|
+
q: params.q?.trim(),
|
|
200
|
+
street: params.street?.trim(),
|
|
201
|
+
number: params.number,
|
|
202
|
+
municipality: params.municipality?.trim(),
|
|
203
|
+
postcode: params.postcode?.trim(),
|
|
204
|
+
limit: params.limit
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async *pages(refcat14, options = {}) {
|
|
209
|
+
const path = parcelPath(refcat14, "/units");
|
|
210
|
+
const previousByCursor = new Map((options.previous?.pages ?? []).map((page) => [page.cursor ?? "", page]));
|
|
211
|
+
let cursor;
|
|
212
|
+
for (let count = 0; count < MAX_PAGES; count += 1) {
|
|
213
|
+
const previous = previousByCursor.get(cursor ?? "");
|
|
214
|
+
const response = await this.client.conditionalRequest("GET", path, {
|
|
215
|
+
query: { cursor },
|
|
216
|
+
ifNoneMatch: previous?.etag
|
|
217
|
+
});
|
|
218
|
+
const data = response.notModified && previous ? previous.data : response.data;
|
|
219
|
+
if (!data) throw new CatastroGPSError("The API answered 304 for a page that was not in the previous import");
|
|
220
|
+
const page = { cursor, etag: response.etag, notModified: response.notModified, data };
|
|
221
|
+
yield page;
|
|
222
|
+
if (!data.truncated || !data.nextCursor) return;
|
|
223
|
+
cursor = data.nextCursor;
|
|
224
|
+
}
|
|
225
|
+
throw new CatastroGPSError(`Stopped after ${MAX_PAGES} pages`);
|
|
226
|
+
}
|
|
227
|
+
async units(refcat14, options = {}) {
|
|
228
|
+
const pages = [];
|
|
229
|
+
for await (const page of this.pages(refcat14, options)) pages.push(page);
|
|
230
|
+
const first = pages[0].data;
|
|
231
|
+
const last = pages[pages.length - 1].data;
|
|
232
|
+
return {
|
|
233
|
+
refCatastral: first.refCatastral,
|
|
234
|
+
direccion: first.direccion,
|
|
235
|
+
codigoPostal: first.codigoPostal,
|
|
236
|
+
municipio: first.municipio,
|
|
237
|
+
provincia: first.provincia,
|
|
238
|
+
usoGeneral: first.usoGeneral,
|
|
239
|
+
anioConstruccion: first.anioConstruccion,
|
|
240
|
+
totalUnidadesFinca: last.totalUnidadesFinca ?? pages.reduce((sum, p) => sum + p.data.unidades.length, 0),
|
|
241
|
+
unidades: pages.flatMap((page) => page.data.unidades),
|
|
242
|
+
construcciones: pages.flatMap((page) => page.data.construcciones ?? []),
|
|
243
|
+
dataSource: first.dataSource,
|
|
244
|
+
dataDate: first.dataDate,
|
|
245
|
+
attribution: first.attribution,
|
|
246
|
+
changed: !pages.every((page) => page.notModified) || pages.length !== (options.previous?.pages.length ?? -1),
|
|
247
|
+
pages
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
182
252
|
// src/version.ts
|
|
183
|
-
var VERSION = "1.
|
|
253
|
+
var VERSION = "1.1.0";
|
|
184
254
|
|
|
185
255
|
// src/client.ts
|
|
186
256
|
var DEFAULT_BASE_URL = "https://api.catastrogps.es";
|
|
@@ -188,9 +258,12 @@ var DEFAULT_TIMEOUT_MS = 3e4;
|
|
|
188
258
|
var DEFAULT_MAX_RETRIES = 2;
|
|
189
259
|
var BACKOFF_BASE_MS = 500;
|
|
190
260
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([502, 503, 504]);
|
|
261
|
+
var NOT_MODIFIED = 304;
|
|
262
|
+
var MAX_RETRY_AFTER_SECONDS = 60;
|
|
191
263
|
var CatastroGPS = class {
|
|
192
264
|
parcels;
|
|
193
265
|
export;
|
|
266
|
+
fincas;
|
|
194
267
|
lastQuota;
|
|
195
268
|
apiKey;
|
|
196
269
|
baseUrl;
|
|
@@ -215,11 +288,25 @@ var CatastroGPS = class {
|
|
|
215
288
|
this.fetchImpl = fetchImpl;
|
|
216
289
|
this.parcels = new ParcelsResource(this);
|
|
217
290
|
this.export = new ExportResource(this);
|
|
291
|
+
this.fincas = new FincasResource(this);
|
|
292
|
+
}
|
|
293
|
+
async searchAddressCandidates(query) {
|
|
294
|
+
return this.fincas.searchAddress(query);
|
|
295
|
+
}
|
|
296
|
+
async getUnits(refcat14, options = {}) {
|
|
297
|
+
return this.fincas.units(refcat14, options);
|
|
298
|
+
}
|
|
299
|
+
iterUnitPages(refcat14, options = {}) {
|
|
300
|
+
return this.fincas.pages(refcat14, options);
|
|
218
301
|
}
|
|
219
302
|
async resolve(text, options = {}) {
|
|
220
303
|
return this.request("GET", "/api/resolve", { query: { q: text, hint: options.hint } });
|
|
221
304
|
}
|
|
222
305
|
async request(method, path, options = {}) {
|
|
306
|
+
const result = await this.conditionalRequest(method, path, options);
|
|
307
|
+
return result.data;
|
|
308
|
+
}
|
|
309
|
+
async conditionalRequest(method, path, options = {}) {
|
|
223
310
|
const url = this.buildUrl(path, options.query);
|
|
224
311
|
let attempt = 0;
|
|
225
312
|
for (; ; ) {
|
|
@@ -241,6 +328,7 @@ var CatastroGPS = class {
|
|
|
241
328
|
"User-Agent": `catastrogps-js/${VERSION}`
|
|
242
329
|
};
|
|
243
330
|
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
331
|
+
if (options.ifNoneMatch) headers["If-None-Match"] = options.ifNoneMatch;
|
|
244
332
|
let response;
|
|
245
333
|
try {
|
|
246
334
|
response = await this.fetchImpl(url, {
|
|
@@ -258,14 +346,16 @@ var CatastroGPS = class {
|
|
|
258
346
|
clearTimeout(timer);
|
|
259
347
|
}
|
|
260
348
|
this.captureQuota(response.headers);
|
|
349
|
+
const etag = response.headers.get("ETag") ?? void 0;
|
|
350
|
+
if (response.status === NOT_MODIFIED) return { etag: etag ?? options.ifNoneMatch, notModified: true };
|
|
261
351
|
if (!response.ok) {
|
|
262
352
|
const body2 = await readJson(response);
|
|
263
353
|
const retryAfter = Number(response.headers.get("Retry-After"));
|
|
264
354
|
throw errorFromResponse(response.status, body2, Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : void 0);
|
|
265
355
|
}
|
|
266
|
-
if (options.raw) return await response.arrayBuffer();
|
|
356
|
+
if (options.raw) return { data: await response.arrayBuffer(), etag, notModified: false };
|
|
267
357
|
const body = await readJson(response);
|
|
268
|
-
return "data" in body ? body.data : body;
|
|
358
|
+
return { data: "data" in body ? body.data : body, etag, notModified: false };
|
|
269
359
|
}
|
|
270
360
|
buildUrl(path, query) {
|
|
271
361
|
const url = new URL(`${this.baseUrl}${path}`);
|
|
@@ -281,21 +371,29 @@ var CatastroGPS = class {
|
|
|
281
371
|
return error instanceof CatastroGPSError && error.status !== void 0 && RETRYABLE_STATUS.has(error.status);
|
|
282
372
|
}
|
|
283
373
|
retryDelayMs(error, attempt) {
|
|
284
|
-
if (error instanceof RateLimitError
|
|
374
|
+
if ((error instanceof RateLimitError || error instanceof ServiceUnavailableError) && error.retryAfterSeconds) {
|
|
375
|
+
return Math.min(error.retryAfterSeconds, MAX_RETRY_AFTER_SECONDS) * 1e3;
|
|
376
|
+
}
|
|
285
377
|
return BACKOFF_BASE_MS * 2 ** attempt;
|
|
286
378
|
}
|
|
287
379
|
captureQuota(headers) {
|
|
288
|
-
const
|
|
289
|
-
if (
|
|
290
|
-
const remaining = headers.get("X-RateLimit-Remaining");
|
|
291
|
-
this.lastQuota = {
|
|
292
|
-
plan: headers.get("X-Quota-Tier") ?? void 0,
|
|
293
|
-
limit: Number(limit),
|
|
294
|
-
remaining: remaining === null ? void 0 : Number(remaining),
|
|
295
|
-
resetsAt: headers.get("X-RateLimit-Reset") ?? void 0
|
|
296
|
-
};
|
|
380
|
+
const quota = readQuota(headers);
|
|
381
|
+
if (quota) this.lastQuota = quota;
|
|
297
382
|
}
|
|
298
383
|
};
|
|
384
|
+
function readQuota(headers) {
|
|
385
|
+
const plan = headers.get("X-Quota-Tier") ?? void 0;
|
|
386
|
+
const family = headers.has("X-Quota-Limit") ? "X-Quota" : plan ? "X-RateLimit" : void 0;
|
|
387
|
+
if (!family) return void 0;
|
|
388
|
+
const limit = headers.get(`${family}-Limit`);
|
|
389
|
+
const remaining = headers.get(`${family}-Remaining`);
|
|
390
|
+
return {
|
|
391
|
+
plan,
|
|
392
|
+
limit: limit === null ? void 0 : Number(limit),
|
|
393
|
+
remaining: remaining === null ? void 0 : Number(remaining),
|
|
394
|
+
resetsAt: headers.get(`${family}-Reset`) ?? void 0
|
|
395
|
+
};
|
|
396
|
+
}
|
|
299
397
|
async function readJson(response) {
|
|
300
398
|
try {
|
|
301
399
|
const parsed = await response.json();
|
package/dist/index.mjs
CHANGED
|
@@ -44,6 +44,7 @@ var RateLimitError = class extends CatastroGPSError {
|
|
|
44
44
|
};
|
|
45
45
|
var ServiceUnavailableError = class extends CatastroGPSError {
|
|
46
46
|
name = "ServiceUnavailableError";
|
|
47
|
+
retryAfterSeconds;
|
|
47
48
|
};
|
|
48
49
|
var ServerError = class extends CatastroGPSError {
|
|
49
50
|
name = "ServerError";
|
|
@@ -71,7 +72,11 @@ function errorFromResponse(status, body, retryAfter) {
|
|
|
71
72
|
if (status === 403) return new ForbiddenError(message, options);
|
|
72
73
|
if (status === 404) return new NotFoundError(message, options);
|
|
73
74
|
if (status === 400 || status === 422) return new ValidationError(message, options);
|
|
74
|
-
if (status === 503)
|
|
75
|
+
if (status === 503) {
|
|
76
|
+
const error = new ServiceUnavailableError(message, options);
|
|
77
|
+
error.retryAfterSeconds = retryAfter;
|
|
78
|
+
return error;
|
|
79
|
+
}
|
|
75
80
|
if (status >= 500) return new ServerError(message, options);
|
|
76
81
|
return new CatastroGPSError(message, options);
|
|
77
82
|
}
|
|
@@ -134,8 +139,73 @@ function parcelPath(reference, suffix = "") {
|
|
|
134
139
|
return `/api/catastro/${encodeURIComponent(reference.trim())}${suffix}`;
|
|
135
140
|
}
|
|
136
141
|
|
|
142
|
+
// src/resources/fincas.ts
|
|
143
|
+
var MAX_PAGES = 1e3;
|
|
144
|
+
var FincasResource = class {
|
|
145
|
+
constructor(client) {
|
|
146
|
+
this.client = client;
|
|
147
|
+
}
|
|
148
|
+
client;
|
|
149
|
+
async searchAddress(query) {
|
|
150
|
+
const params = typeof query === "string" ? { q: query } : query;
|
|
151
|
+
if (!params.q?.trim() && !params.street?.trim()) throw new CatastroGPSError("q or street is required");
|
|
152
|
+
return this.client.request("GET", "/api/search/address/candidates", {
|
|
153
|
+
query: {
|
|
154
|
+
q: params.q?.trim(),
|
|
155
|
+
street: params.street?.trim(),
|
|
156
|
+
number: params.number,
|
|
157
|
+
municipality: params.municipality?.trim(),
|
|
158
|
+
postcode: params.postcode?.trim(),
|
|
159
|
+
limit: params.limit
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
async *pages(refcat14, options = {}) {
|
|
164
|
+
const path = parcelPath(refcat14, "/units");
|
|
165
|
+
const previousByCursor = new Map((options.previous?.pages ?? []).map((page) => [page.cursor ?? "", page]));
|
|
166
|
+
let cursor;
|
|
167
|
+
for (let count = 0; count < MAX_PAGES; count += 1) {
|
|
168
|
+
const previous = previousByCursor.get(cursor ?? "");
|
|
169
|
+
const response = await this.client.conditionalRequest("GET", path, {
|
|
170
|
+
query: { cursor },
|
|
171
|
+
ifNoneMatch: previous?.etag
|
|
172
|
+
});
|
|
173
|
+
const data = response.notModified && previous ? previous.data : response.data;
|
|
174
|
+
if (!data) throw new CatastroGPSError("The API answered 304 for a page that was not in the previous import");
|
|
175
|
+
const page = { cursor, etag: response.etag, notModified: response.notModified, data };
|
|
176
|
+
yield page;
|
|
177
|
+
if (!data.truncated || !data.nextCursor) return;
|
|
178
|
+
cursor = data.nextCursor;
|
|
179
|
+
}
|
|
180
|
+
throw new CatastroGPSError(`Stopped after ${MAX_PAGES} pages`);
|
|
181
|
+
}
|
|
182
|
+
async units(refcat14, options = {}) {
|
|
183
|
+
const pages = [];
|
|
184
|
+
for await (const page of this.pages(refcat14, options)) pages.push(page);
|
|
185
|
+
const first = pages[0].data;
|
|
186
|
+
const last = pages[pages.length - 1].data;
|
|
187
|
+
return {
|
|
188
|
+
refCatastral: first.refCatastral,
|
|
189
|
+
direccion: first.direccion,
|
|
190
|
+
codigoPostal: first.codigoPostal,
|
|
191
|
+
municipio: first.municipio,
|
|
192
|
+
provincia: first.provincia,
|
|
193
|
+
usoGeneral: first.usoGeneral,
|
|
194
|
+
anioConstruccion: first.anioConstruccion,
|
|
195
|
+
totalUnidadesFinca: last.totalUnidadesFinca ?? pages.reduce((sum, p) => sum + p.data.unidades.length, 0),
|
|
196
|
+
unidades: pages.flatMap((page) => page.data.unidades),
|
|
197
|
+
construcciones: pages.flatMap((page) => page.data.construcciones ?? []),
|
|
198
|
+
dataSource: first.dataSource,
|
|
199
|
+
dataDate: first.dataDate,
|
|
200
|
+
attribution: first.attribution,
|
|
201
|
+
changed: !pages.every((page) => page.notModified) || pages.length !== (options.previous?.pages.length ?? -1),
|
|
202
|
+
pages
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
137
207
|
// src/version.ts
|
|
138
|
-
var VERSION = "1.
|
|
208
|
+
var VERSION = "1.1.0";
|
|
139
209
|
|
|
140
210
|
// src/client.ts
|
|
141
211
|
var DEFAULT_BASE_URL = "https://api.catastrogps.es";
|
|
@@ -143,9 +213,12 @@ var DEFAULT_TIMEOUT_MS = 3e4;
|
|
|
143
213
|
var DEFAULT_MAX_RETRIES = 2;
|
|
144
214
|
var BACKOFF_BASE_MS = 500;
|
|
145
215
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([502, 503, 504]);
|
|
216
|
+
var NOT_MODIFIED = 304;
|
|
217
|
+
var MAX_RETRY_AFTER_SECONDS = 60;
|
|
146
218
|
var CatastroGPS = class {
|
|
147
219
|
parcels;
|
|
148
220
|
export;
|
|
221
|
+
fincas;
|
|
149
222
|
lastQuota;
|
|
150
223
|
apiKey;
|
|
151
224
|
baseUrl;
|
|
@@ -170,11 +243,25 @@ var CatastroGPS = class {
|
|
|
170
243
|
this.fetchImpl = fetchImpl;
|
|
171
244
|
this.parcels = new ParcelsResource(this);
|
|
172
245
|
this.export = new ExportResource(this);
|
|
246
|
+
this.fincas = new FincasResource(this);
|
|
247
|
+
}
|
|
248
|
+
async searchAddressCandidates(query) {
|
|
249
|
+
return this.fincas.searchAddress(query);
|
|
250
|
+
}
|
|
251
|
+
async getUnits(refcat14, options = {}) {
|
|
252
|
+
return this.fincas.units(refcat14, options);
|
|
253
|
+
}
|
|
254
|
+
iterUnitPages(refcat14, options = {}) {
|
|
255
|
+
return this.fincas.pages(refcat14, options);
|
|
173
256
|
}
|
|
174
257
|
async resolve(text, options = {}) {
|
|
175
258
|
return this.request("GET", "/api/resolve", { query: { q: text, hint: options.hint } });
|
|
176
259
|
}
|
|
177
260
|
async request(method, path, options = {}) {
|
|
261
|
+
const result = await this.conditionalRequest(method, path, options);
|
|
262
|
+
return result.data;
|
|
263
|
+
}
|
|
264
|
+
async conditionalRequest(method, path, options = {}) {
|
|
178
265
|
const url = this.buildUrl(path, options.query);
|
|
179
266
|
let attempt = 0;
|
|
180
267
|
for (; ; ) {
|
|
@@ -196,6 +283,7 @@ var CatastroGPS = class {
|
|
|
196
283
|
"User-Agent": `catastrogps-js/${VERSION}`
|
|
197
284
|
};
|
|
198
285
|
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
286
|
+
if (options.ifNoneMatch) headers["If-None-Match"] = options.ifNoneMatch;
|
|
199
287
|
let response;
|
|
200
288
|
try {
|
|
201
289
|
response = await this.fetchImpl(url, {
|
|
@@ -213,14 +301,16 @@ var CatastroGPS = class {
|
|
|
213
301
|
clearTimeout(timer);
|
|
214
302
|
}
|
|
215
303
|
this.captureQuota(response.headers);
|
|
304
|
+
const etag = response.headers.get("ETag") ?? void 0;
|
|
305
|
+
if (response.status === NOT_MODIFIED) return { etag: etag ?? options.ifNoneMatch, notModified: true };
|
|
216
306
|
if (!response.ok) {
|
|
217
307
|
const body2 = await readJson(response);
|
|
218
308
|
const retryAfter = Number(response.headers.get("Retry-After"));
|
|
219
309
|
throw errorFromResponse(response.status, body2, Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : void 0);
|
|
220
310
|
}
|
|
221
|
-
if (options.raw) return await response.arrayBuffer();
|
|
311
|
+
if (options.raw) return { data: await response.arrayBuffer(), etag, notModified: false };
|
|
222
312
|
const body = await readJson(response);
|
|
223
|
-
return "data" in body ? body.data : body;
|
|
313
|
+
return { data: "data" in body ? body.data : body, etag, notModified: false };
|
|
224
314
|
}
|
|
225
315
|
buildUrl(path, query) {
|
|
226
316
|
const url = new URL(`${this.baseUrl}${path}`);
|
|
@@ -236,21 +326,29 @@ var CatastroGPS = class {
|
|
|
236
326
|
return error instanceof CatastroGPSError && error.status !== void 0 && RETRYABLE_STATUS.has(error.status);
|
|
237
327
|
}
|
|
238
328
|
retryDelayMs(error, attempt) {
|
|
239
|
-
if (error instanceof RateLimitError
|
|
329
|
+
if ((error instanceof RateLimitError || error instanceof ServiceUnavailableError) && error.retryAfterSeconds) {
|
|
330
|
+
return Math.min(error.retryAfterSeconds, MAX_RETRY_AFTER_SECONDS) * 1e3;
|
|
331
|
+
}
|
|
240
332
|
return BACKOFF_BASE_MS * 2 ** attempt;
|
|
241
333
|
}
|
|
242
334
|
captureQuota(headers) {
|
|
243
|
-
const
|
|
244
|
-
if (
|
|
245
|
-
const remaining = headers.get("X-RateLimit-Remaining");
|
|
246
|
-
this.lastQuota = {
|
|
247
|
-
plan: headers.get("X-Quota-Tier") ?? void 0,
|
|
248
|
-
limit: Number(limit),
|
|
249
|
-
remaining: remaining === null ? void 0 : Number(remaining),
|
|
250
|
-
resetsAt: headers.get("X-RateLimit-Reset") ?? void 0
|
|
251
|
-
};
|
|
335
|
+
const quota = readQuota(headers);
|
|
336
|
+
if (quota) this.lastQuota = quota;
|
|
252
337
|
}
|
|
253
338
|
};
|
|
339
|
+
function readQuota(headers) {
|
|
340
|
+
const plan = headers.get("X-Quota-Tier") ?? void 0;
|
|
341
|
+
const family = headers.has("X-Quota-Limit") ? "X-Quota" : plan ? "X-RateLimit" : void 0;
|
|
342
|
+
if (!family) return void 0;
|
|
343
|
+
const limit = headers.get(`${family}-Limit`);
|
|
344
|
+
const remaining = headers.get(`${family}-Remaining`);
|
|
345
|
+
return {
|
|
346
|
+
plan,
|
|
347
|
+
limit: limit === null ? void 0 : Number(limit),
|
|
348
|
+
remaining: remaining === null ? void 0 : Number(remaining),
|
|
349
|
+
resetsAt: headers.get(`${family}-Reset`) ?? void 0
|
|
350
|
+
};
|
|
351
|
+
}
|
|
254
352
|
async function readJson(response) {
|
|
255
353
|
try {
|
|
256
354
|
const parsed = await response.json();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "catastrogps",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Official JavaScript/TypeScript client for the Catastro GPS API: cadastral parcels in 31 European countries and regions by reference, coordinates or Spanish address",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|