catastrogps 1.0.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/LICENSE +21 -0
- package/README.md +127 -0
- package/dist/index.d.mts +229 -0
- package/dist/index.d.ts +229 -0
- package/dist/index.js +372 -0
- package/dist/index.mjs +326 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TheHiddenPanda
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# catastrogps
|
|
2
|
+
|
|
3
|
+
Official JavaScript and TypeScript client for the [Catastro GPS API](https://www.catastrogps.es/developers): cadastral parcels in **29 European countries plus the Basque Country and Navarre** (31 country and region codes) with one API key.
|
|
4
|
+
|
|
5
|
+
- Look up a parcel by its **official cadastral reference** or by **coordinates**, with the country detected for you.
|
|
6
|
+
- Turn a **Spanish postal address in free text** into a cadastral reference.
|
|
7
|
+
- Get the **parcel outline** (GeoJSON or a `[lat, lng]` ring), and **KML / GPX / DXF** exports.
|
|
8
|
+
- **Solar** (PVGIS) and **agricultural** context for parcels in Spain, Portugal, France, Italy and Germany.
|
|
9
|
+
- Zero runtime dependencies. Node.js 18+, Deno, Bun and edge runtimes with `fetch`. ESM and CommonJS, fully typed.
|
|
10
|
+
|
|
11
|
+
**Free tier: 250 calls a month, forever. Failed lookups are not charged.** Get a key at [catastrogps.es/developers](https://www.catastrogps.es/developers).
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install catastrogps
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { CatastroGPS } from 'catastrogps';
|
|
23
|
+
|
|
24
|
+
const client = new CatastroGPS({ apiKey: process.env.CATASTROGPS_API_KEY });
|
|
25
|
+
|
|
26
|
+
const parcel = await client.parcels.get('9872023VH5797S0001WX');
|
|
27
|
+
console.log(parcel.municipio, parcel.superficieParcela, parcel.latitud, parcel.longitud);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`new CatastroGPS()` with no arguments reads `CATASTROGPS_API_KEY` from the environment.
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const fromAddress = await client.parcels.findByAddress('Calle Mallorca 213, Barcelona');
|
|
36
|
+
fromAddress.referenciaCatastral;
|
|
37
|
+
|
|
38
|
+
const inWarsaw = await client.parcels.atPoint({ lat: 52.2297, lng: 21.0122 });
|
|
39
|
+
inWarsaw.referenciaCatastral;
|
|
40
|
+
inWarsaw.pais;
|
|
41
|
+
|
|
42
|
+
const foral = await client.parcels.get('<Navarre reference>', { country: 'NA' });
|
|
43
|
+
|
|
44
|
+
const outline = await client.parcels.geometry('9872023VH5797S', { country: 'ES' });
|
|
45
|
+
outline.geojson;
|
|
46
|
+
|
|
47
|
+
const solar = await client.parcels.solar('9872023VH5797S0001WX');
|
|
48
|
+
solar.kwh_year;
|
|
49
|
+
|
|
50
|
+
const kml = await client.export.file('9872023VH5797S0001WX', 'kml');
|
|
51
|
+
|
|
52
|
+
const guess = await client.resolve('05102200100005');
|
|
53
|
+
guess.candidates;
|
|
54
|
+
|
|
55
|
+
client.lastQuota;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
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
|
+
|
|
60
|
+
## Errors
|
|
61
|
+
|
|
62
|
+
Every error is a `CatastroGPSError` with `status`, `code` and `details`. Subclasses let you branch cleanly:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { AmbiguousReferenceError, CoverageError, NotFoundError, QuotaExceededError } from 'catastrogps';
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
await client.parcels.get('05102200100005');
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error instanceof AmbiguousReferenceError) {
|
|
71
|
+
const [first] = error.candidates;
|
|
72
|
+
await client.parcels.get('05102200100005', { country: first.country as 'DE' });
|
|
73
|
+
} else if (error instanceof NotFoundError || error instanceof CoverageError) {
|
|
74
|
+
console.log(error.message);
|
|
75
|
+
} else if (error instanceof QuotaExceededError) {
|
|
76
|
+
console.log('Monthly quota used up');
|
|
77
|
+
} else {
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Also available: `AuthenticationError`, `ValidationError`, `RateLimitError`, `ServiceUnavailableError`, `ServerError`, `TimeoutError`, `NetworkError`.
|
|
84
|
+
|
|
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. Each attempt that reaches the API counts as a call.
|
|
86
|
+
|
|
87
|
+
## Options
|
|
88
|
+
|
|
89
|
+
| Option | Default | |
|
|
90
|
+
|--------|---------|---|
|
|
91
|
+
| `apiKey` | `process.env.CATASTROGPS_API_KEY` | Required |
|
|
92
|
+
| `baseUrl` | `https://api.catastrogps.es` | |
|
|
93
|
+
| `timeoutMs` | `30000` | Official cadastres can be slow |
|
|
94
|
+
| `maxRetries` | `2` | |
|
|
95
|
+
| `fetch` | `globalThis.fetch` | Inject your own for tests or proxies |
|
|
96
|
+
|
|
97
|
+
## Coverage
|
|
98
|
+
|
|
99
|
+
| Code | Country / region | Reference | Coordinates | Notes |
|
|
100
|
+
|------|------------------|:---:|:---:|-------|
|
|
101
|
+
| `ES` | Spain | ✅ | ✅ | Free-text address search |
|
|
102
|
+
| `PV` · `NA` | Basque Country · Navarre | ✅ | ✅ | Foral cadastres |
|
|
103
|
+
| `PT` | Portugal | Partial | ✅ | Digital cadastre is partial |
|
|
104
|
+
| `FR` · `IT` | France · Italy | ✅ | ✅ | |
|
|
105
|
+
| `DE` | Germany | Partial | Partial | All Länder except Bavaria |
|
|
106
|
+
| `AT` `CH` `LI` `BE` `NL` `LU` | Austria, Switzerland, Liechtenstein, Belgium, Netherlands, Luxembourg | ✅ | ✅ | |
|
|
107
|
+
| `PL` `CZ` `SK` `SI` `HR` `BG` `GR` `CY` | Poland, Czechia, Slovakia, Slovenia, Croatia, Bulgaria, Greece, Cyprus | ✅ | ✅ | |
|
|
108
|
+
| `DK` `NO` `FI` `IS` `EE` `LV` `LT` `IE` | Denmark, Norway, Finland, Iceland, Estonia, Latvia, Lithuania, Ireland | ✅ | ✅ | |
|
|
109
|
+
| `SE` | Sweden | ✅ | ✅ | Agricultural blocks, not property units |
|
|
110
|
+
| `UK` | United Kingdom | — | Scotland | England, Wales and Northern Ireland not yet |
|
|
111
|
+
|
|
112
|
+
Geometry is available wherever a reference works. Solar and agriculture: `ES`, `PV`, `NA`, `PT`, `FR`, `IT`, `DE`. Data comes live from each official source, so availability follows theirs.
|
|
113
|
+
|
|
114
|
+
## Pricing
|
|
115
|
+
|
|
116
|
+
| Plan | Price | Calls / month |
|
|
117
|
+
|------|-------|---------------|
|
|
118
|
+
| Free | €0, forever | 100 |
|
|
119
|
+
| Developer | €19 / month | 5,000 |
|
|
120
|
+
| Startup | €49 / month | 15,000 |
|
|
121
|
+
| Growth | €99 / month | 50,000 |
|
|
122
|
+
|
|
123
|
+
The same key works with the Python SDK (`pip install catastrogps`) and the MCP server for AI agents ([`catastro-gps-mcp`](https://www.npmjs.com/package/catastro-gps-mcp)).
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
declare const COUNTRY_CODES: readonly ["ES", "PV", "NA", "PT", "FR", "IT", "DE", "AT", "CH", "LI", "BE", "NL", "LU", "PL", "CZ", "SK", "SI", "HR", "BG", "GR", "CY", "DK", "SE", "NO", "FI", "IS", "EE", "LV", "LT", "IE", "UK"];
|
|
2
|
+
type CountryCode = (typeof COUNTRY_CODES)[number];
|
|
3
|
+
declare const ENRICHMENT_COUNTRY_CODES: readonly ["ES", "PV", "NA", "PT", "FR", "IT", "DE"];
|
|
4
|
+
type EnrichmentCountryCode = (typeof ENRICHMENT_COUNTRY_CODES)[number];
|
|
5
|
+
type ExportFormat = 'kml' | 'gpx' | 'dxf';
|
|
6
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
7
|
+
interface CatastroGPSOptions {
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
maxRetries?: number;
|
|
12
|
+
fetch?: FetchLike;
|
|
13
|
+
}
|
|
14
|
+
interface CountryOption<C extends string = CountryCode> {
|
|
15
|
+
country?: C;
|
|
16
|
+
}
|
|
17
|
+
interface Quota {
|
|
18
|
+
plan?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
remaining?: number;
|
|
21
|
+
resetsAt?: string;
|
|
22
|
+
}
|
|
23
|
+
interface Parcel {
|
|
24
|
+
refCatastral: string;
|
|
25
|
+
pais?: string;
|
|
26
|
+
direccion?: string;
|
|
27
|
+
codigoPostal?: string;
|
|
28
|
+
municipio?: string;
|
|
29
|
+
provincia?: string;
|
|
30
|
+
latitud: number;
|
|
31
|
+
longitud: number;
|
|
32
|
+
googleMapsUrl?: string;
|
|
33
|
+
uso?: string;
|
|
34
|
+
clase?: string;
|
|
35
|
+
superficieConstruida?: number;
|
|
36
|
+
superficieParcela?: number;
|
|
37
|
+
anioConstruccion?: number;
|
|
38
|
+
viviendas?: number;
|
|
39
|
+
plantas?: number;
|
|
40
|
+
fuenteDatos?: string;
|
|
41
|
+
dataSource?: string;
|
|
42
|
+
poligono?: number[][];
|
|
43
|
+
availableFields?: Record<string, boolean>;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
interface PointMatch {
|
|
47
|
+
referenciaCatastral: string;
|
|
48
|
+
refCat14?: string;
|
|
49
|
+
pais?: string;
|
|
50
|
+
direccion?: string;
|
|
51
|
+
codigoPostal?: string;
|
|
52
|
+
municipio?: string;
|
|
53
|
+
provincia?: string;
|
|
54
|
+
tipoInmueble?: string;
|
|
55
|
+
coordenadas: {
|
|
56
|
+
latitud: number;
|
|
57
|
+
longitud: number;
|
|
58
|
+
};
|
|
59
|
+
googleMapsUrl?: string;
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
}
|
|
62
|
+
interface AddressMatch {
|
|
63
|
+
referenciaCatastral: string;
|
|
64
|
+
refCat14?: string;
|
|
65
|
+
direccion?: string;
|
|
66
|
+
provincia?: string;
|
|
67
|
+
municipio?: string;
|
|
68
|
+
tipoVia?: string;
|
|
69
|
+
nombreVia?: string;
|
|
70
|
+
numero?: number;
|
|
71
|
+
planta?: string;
|
|
72
|
+
puerta?: string;
|
|
73
|
+
codigoPostal?: string;
|
|
74
|
+
}
|
|
75
|
+
interface ParcelGeometry {
|
|
76
|
+
refcat?: string;
|
|
77
|
+
refCatastral?: string;
|
|
78
|
+
pais?: string;
|
|
79
|
+
geojson?: unknown;
|
|
80
|
+
centroid?: {
|
|
81
|
+
latitude: number;
|
|
82
|
+
longitude: number;
|
|
83
|
+
};
|
|
84
|
+
latitud?: number;
|
|
85
|
+
longitud?: number;
|
|
86
|
+
area?: number;
|
|
87
|
+
superficieParcela?: number;
|
|
88
|
+
poligono?: number[][];
|
|
89
|
+
[key: string]: unknown;
|
|
90
|
+
}
|
|
91
|
+
interface SolarEstimate {
|
|
92
|
+
kwh_year: number;
|
|
93
|
+
kw_instalables: number;
|
|
94
|
+
ahorro_anual_eur: number;
|
|
95
|
+
amortizacion_anos: number;
|
|
96
|
+
co2_evitado_kg: number;
|
|
97
|
+
irradiacion_media: number;
|
|
98
|
+
nota_solar: number;
|
|
99
|
+
orientacion_optima?: string;
|
|
100
|
+
angulo_inclinacion?: number;
|
|
101
|
+
costo_instalacion_eur?: number;
|
|
102
|
+
disponible: boolean;
|
|
103
|
+
estado: string;
|
|
104
|
+
fuente?: string;
|
|
105
|
+
[key: string]: unknown;
|
|
106
|
+
}
|
|
107
|
+
type AgricultureData = Record<string, unknown>;
|
|
108
|
+
interface ResolveCandidate {
|
|
109
|
+
country: string;
|
|
110
|
+
kind: 'reference' | 'coordinates' | 'place_name' | string;
|
|
111
|
+
normalized: string;
|
|
112
|
+
confidence: number;
|
|
113
|
+
supported: boolean;
|
|
114
|
+
}
|
|
115
|
+
interface ResolveResult {
|
|
116
|
+
input: string;
|
|
117
|
+
candidates: ResolveCandidate[];
|
|
118
|
+
ambiguous: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
declare class ExportResource {
|
|
122
|
+
private readonly client;
|
|
123
|
+
constructor(client: CatastroGPS);
|
|
124
|
+
file(reference: string, format: ExportFormat, options?: CountryOption): Promise<ArrayBuffer>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface PointQuery extends CountryOption {
|
|
128
|
+
lat: number;
|
|
129
|
+
lng: number;
|
|
130
|
+
}
|
|
131
|
+
declare class ParcelsResource {
|
|
132
|
+
private readonly client;
|
|
133
|
+
constructor(client: CatastroGPS);
|
|
134
|
+
get(reference: string, options?: CountryOption): Promise<Parcel>;
|
|
135
|
+
atPoint(point: PointQuery): Promise<PointMatch>;
|
|
136
|
+
findByAddress(address: string): Promise<AddressMatch>;
|
|
137
|
+
geometry(reference: string, options?: CountryOption<Exclude<CountryCode, 'UK'>>): Promise<ParcelGeometry>;
|
|
138
|
+
solar(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<SolarEstimate>;
|
|
139
|
+
agriculture(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<AgricultureData>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
declare const DEFAULT_BASE_URL = "https://api.catastrogps.es";
|
|
143
|
+
declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
144
|
+
declare const DEFAULT_MAX_RETRIES = 2;
|
|
145
|
+
type Query = Record<string, string | number | undefined>;
|
|
146
|
+
interface RequestOptions {
|
|
147
|
+
query?: Query;
|
|
148
|
+
body?: unknown;
|
|
149
|
+
raw?: boolean;
|
|
150
|
+
}
|
|
151
|
+
declare class CatastroGPS {
|
|
152
|
+
readonly parcels: ParcelsResource;
|
|
153
|
+
readonly export: ExportResource;
|
|
154
|
+
lastQuota?: Quota;
|
|
155
|
+
private readonly apiKey;
|
|
156
|
+
private readonly baseUrl;
|
|
157
|
+
private readonly timeoutMs;
|
|
158
|
+
private readonly maxRetries;
|
|
159
|
+
private readonly fetchImpl;
|
|
160
|
+
constructor(options?: CatastroGPSOptions);
|
|
161
|
+
resolve(text: string, options?: {
|
|
162
|
+
hint?: string;
|
|
163
|
+
}): Promise<ResolveResult>;
|
|
164
|
+
request<T>(method: 'GET' | 'POST', path: string, options?: RequestOptions): Promise<T>;
|
|
165
|
+
private once;
|
|
166
|
+
private buildUrl;
|
|
167
|
+
private shouldRetry;
|
|
168
|
+
private retryDelayMs;
|
|
169
|
+
private captureQuota;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
declare const VERSION = "1.0.0";
|
|
173
|
+
|
|
174
|
+
declare class CatastroGPSError extends Error {
|
|
175
|
+
readonly status?: number;
|
|
176
|
+
readonly code?: string;
|
|
177
|
+
readonly details?: unknown;
|
|
178
|
+
readonly body: Record<string, unknown>;
|
|
179
|
+
constructor(message: string, options?: {
|
|
180
|
+
status?: number;
|
|
181
|
+
code?: string;
|
|
182
|
+
details?: unknown;
|
|
183
|
+
body?: Record<string, unknown>;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
declare class AuthenticationError extends CatastroGPSError {
|
|
187
|
+
name: string;
|
|
188
|
+
}
|
|
189
|
+
declare class ForbiddenError extends CatastroGPSError {
|
|
190
|
+
name: string;
|
|
191
|
+
}
|
|
192
|
+
declare class NotFoundError extends CatastroGPSError {
|
|
193
|
+
name: string;
|
|
194
|
+
}
|
|
195
|
+
declare class ValidationError extends CatastroGPSError {
|
|
196
|
+
name: string;
|
|
197
|
+
}
|
|
198
|
+
declare class CoverageError extends CatastroGPSError {
|
|
199
|
+
name: string;
|
|
200
|
+
}
|
|
201
|
+
declare class AmbiguousReferenceError extends CatastroGPSError {
|
|
202
|
+
name: string;
|
|
203
|
+
get candidates(): Array<{
|
|
204
|
+
country: string;
|
|
205
|
+
confidence?: number;
|
|
206
|
+
supported?: boolean;
|
|
207
|
+
}>;
|
|
208
|
+
}
|
|
209
|
+
declare class QuotaExceededError extends CatastroGPSError {
|
|
210
|
+
name: string;
|
|
211
|
+
}
|
|
212
|
+
declare class RateLimitError extends CatastroGPSError {
|
|
213
|
+
name: string;
|
|
214
|
+
retryAfterSeconds?: number;
|
|
215
|
+
}
|
|
216
|
+
declare class ServiceUnavailableError extends CatastroGPSError {
|
|
217
|
+
name: string;
|
|
218
|
+
}
|
|
219
|
+
declare class ServerError extends CatastroGPSError {
|
|
220
|
+
name: string;
|
|
221
|
+
}
|
|
222
|
+
declare class TimeoutError extends CatastroGPSError {
|
|
223
|
+
name: string;
|
|
224
|
+
}
|
|
225
|
+
declare class NetworkError extends CatastroGPSError {
|
|
226
|
+
name: string;
|
|
227
|
+
}
|
|
228
|
+
|
|
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 };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
declare const COUNTRY_CODES: readonly ["ES", "PV", "NA", "PT", "FR", "IT", "DE", "AT", "CH", "LI", "BE", "NL", "LU", "PL", "CZ", "SK", "SI", "HR", "BG", "GR", "CY", "DK", "SE", "NO", "FI", "IS", "EE", "LV", "LT", "IE", "UK"];
|
|
2
|
+
type CountryCode = (typeof COUNTRY_CODES)[number];
|
|
3
|
+
declare const ENRICHMENT_COUNTRY_CODES: readonly ["ES", "PV", "NA", "PT", "FR", "IT", "DE"];
|
|
4
|
+
type EnrichmentCountryCode = (typeof ENRICHMENT_COUNTRY_CODES)[number];
|
|
5
|
+
type ExportFormat = 'kml' | 'gpx' | 'dxf';
|
|
6
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
7
|
+
interface CatastroGPSOptions {
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
maxRetries?: number;
|
|
12
|
+
fetch?: FetchLike;
|
|
13
|
+
}
|
|
14
|
+
interface CountryOption<C extends string = CountryCode> {
|
|
15
|
+
country?: C;
|
|
16
|
+
}
|
|
17
|
+
interface Quota {
|
|
18
|
+
plan?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
remaining?: number;
|
|
21
|
+
resetsAt?: string;
|
|
22
|
+
}
|
|
23
|
+
interface Parcel {
|
|
24
|
+
refCatastral: string;
|
|
25
|
+
pais?: string;
|
|
26
|
+
direccion?: string;
|
|
27
|
+
codigoPostal?: string;
|
|
28
|
+
municipio?: string;
|
|
29
|
+
provincia?: string;
|
|
30
|
+
latitud: number;
|
|
31
|
+
longitud: number;
|
|
32
|
+
googleMapsUrl?: string;
|
|
33
|
+
uso?: string;
|
|
34
|
+
clase?: string;
|
|
35
|
+
superficieConstruida?: number;
|
|
36
|
+
superficieParcela?: number;
|
|
37
|
+
anioConstruccion?: number;
|
|
38
|
+
viviendas?: number;
|
|
39
|
+
plantas?: number;
|
|
40
|
+
fuenteDatos?: string;
|
|
41
|
+
dataSource?: string;
|
|
42
|
+
poligono?: number[][];
|
|
43
|
+
availableFields?: Record<string, boolean>;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
interface PointMatch {
|
|
47
|
+
referenciaCatastral: string;
|
|
48
|
+
refCat14?: string;
|
|
49
|
+
pais?: string;
|
|
50
|
+
direccion?: string;
|
|
51
|
+
codigoPostal?: string;
|
|
52
|
+
municipio?: string;
|
|
53
|
+
provincia?: string;
|
|
54
|
+
tipoInmueble?: string;
|
|
55
|
+
coordenadas: {
|
|
56
|
+
latitud: number;
|
|
57
|
+
longitud: number;
|
|
58
|
+
};
|
|
59
|
+
googleMapsUrl?: string;
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
}
|
|
62
|
+
interface AddressMatch {
|
|
63
|
+
referenciaCatastral: string;
|
|
64
|
+
refCat14?: string;
|
|
65
|
+
direccion?: string;
|
|
66
|
+
provincia?: string;
|
|
67
|
+
municipio?: string;
|
|
68
|
+
tipoVia?: string;
|
|
69
|
+
nombreVia?: string;
|
|
70
|
+
numero?: number;
|
|
71
|
+
planta?: string;
|
|
72
|
+
puerta?: string;
|
|
73
|
+
codigoPostal?: string;
|
|
74
|
+
}
|
|
75
|
+
interface ParcelGeometry {
|
|
76
|
+
refcat?: string;
|
|
77
|
+
refCatastral?: string;
|
|
78
|
+
pais?: string;
|
|
79
|
+
geojson?: unknown;
|
|
80
|
+
centroid?: {
|
|
81
|
+
latitude: number;
|
|
82
|
+
longitude: number;
|
|
83
|
+
};
|
|
84
|
+
latitud?: number;
|
|
85
|
+
longitud?: number;
|
|
86
|
+
area?: number;
|
|
87
|
+
superficieParcela?: number;
|
|
88
|
+
poligono?: number[][];
|
|
89
|
+
[key: string]: unknown;
|
|
90
|
+
}
|
|
91
|
+
interface SolarEstimate {
|
|
92
|
+
kwh_year: number;
|
|
93
|
+
kw_instalables: number;
|
|
94
|
+
ahorro_anual_eur: number;
|
|
95
|
+
amortizacion_anos: number;
|
|
96
|
+
co2_evitado_kg: number;
|
|
97
|
+
irradiacion_media: number;
|
|
98
|
+
nota_solar: number;
|
|
99
|
+
orientacion_optima?: string;
|
|
100
|
+
angulo_inclinacion?: number;
|
|
101
|
+
costo_instalacion_eur?: number;
|
|
102
|
+
disponible: boolean;
|
|
103
|
+
estado: string;
|
|
104
|
+
fuente?: string;
|
|
105
|
+
[key: string]: unknown;
|
|
106
|
+
}
|
|
107
|
+
type AgricultureData = Record<string, unknown>;
|
|
108
|
+
interface ResolveCandidate {
|
|
109
|
+
country: string;
|
|
110
|
+
kind: 'reference' | 'coordinates' | 'place_name' | string;
|
|
111
|
+
normalized: string;
|
|
112
|
+
confidence: number;
|
|
113
|
+
supported: boolean;
|
|
114
|
+
}
|
|
115
|
+
interface ResolveResult {
|
|
116
|
+
input: string;
|
|
117
|
+
candidates: ResolveCandidate[];
|
|
118
|
+
ambiguous: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
declare class ExportResource {
|
|
122
|
+
private readonly client;
|
|
123
|
+
constructor(client: CatastroGPS);
|
|
124
|
+
file(reference: string, format: ExportFormat, options?: CountryOption): Promise<ArrayBuffer>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface PointQuery extends CountryOption {
|
|
128
|
+
lat: number;
|
|
129
|
+
lng: number;
|
|
130
|
+
}
|
|
131
|
+
declare class ParcelsResource {
|
|
132
|
+
private readonly client;
|
|
133
|
+
constructor(client: CatastroGPS);
|
|
134
|
+
get(reference: string, options?: CountryOption): Promise<Parcel>;
|
|
135
|
+
atPoint(point: PointQuery): Promise<PointMatch>;
|
|
136
|
+
findByAddress(address: string): Promise<AddressMatch>;
|
|
137
|
+
geometry(reference: string, options?: CountryOption<Exclude<CountryCode, 'UK'>>): Promise<ParcelGeometry>;
|
|
138
|
+
solar(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<SolarEstimate>;
|
|
139
|
+
agriculture(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<AgricultureData>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
declare const DEFAULT_BASE_URL = "https://api.catastrogps.es";
|
|
143
|
+
declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
144
|
+
declare const DEFAULT_MAX_RETRIES = 2;
|
|
145
|
+
type Query = Record<string, string | number | undefined>;
|
|
146
|
+
interface RequestOptions {
|
|
147
|
+
query?: Query;
|
|
148
|
+
body?: unknown;
|
|
149
|
+
raw?: boolean;
|
|
150
|
+
}
|
|
151
|
+
declare class CatastroGPS {
|
|
152
|
+
readonly parcels: ParcelsResource;
|
|
153
|
+
readonly export: ExportResource;
|
|
154
|
+
lastQuota?: Quota;
|
|
155
|
+
private readonly apiKey;
|
|
156
|
+
private readonly baseUrl;
|
|
157
|
+
private readonly timeoutMs;
|
|
158
|
+
private readonly maxRetries;
|
|
159
|
+
private readonly fetchImpl;
|
|
160
|
+
constructor(options?: CatastroGPSOptions);
|
|
161
|
+
resolve(text: string, options?: {
|
|
162
|
+
hint?: string;
|
|
163
|
+
}): Promise<ResolveResult>;
|
|
164
|
+
request<T>(method: 'GET' | 'POST', path: string, options?: RequestOptions): Promise<T>;
|
|
165
|
+
private once;
|
|
166
|
+
private buildUrl;
|
|
167
|
+
private shouldRetry;
|
|
168
|
+
private retryDelayMs;
|
|
169
|
+
private captureQuota;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
declare const VERSION = "1.0.0";
|
|
173
|
+
|
|
174
|
+
declare class CatastroGPSError extends Error {
|
|
175
|
+
readonly status?: number;
|
|
176
|
+
readonly code?: string;
|
|
177
|
+
readonly details?: unknown;
|
|
178
|
+
readonly body: Record<string, unknown>;
|
|
179
|
+
constructor(message: string, options?: {
|
|
180
|
+
status?: number;
|
|
181
|
+
code?: string;
|
|
182
|
+
details?: unknown;
|
|
183
|
+
body?: Record<string, unknown>;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
declare class AuthenticationError extends CatastroGPSError {
|
|
187
|
+
name: string;
|
|
188
|
+
}
|
|
189
|
+
declare class ForbiddenError extends CatastroGPSError {
|
|
190
|
+
name: string;
|
|
191
|
+
}
|
|
192
|
+
declare class NotFoundError extends CatastroGPSError {
|
|
193
|
+
name: string;
|
|
194
|
+
}
|
|
195
|
+
declare class ValidationError extends CatastroGPSError {
|
|
196
|
+
name: string;
|
|
197
|
+
}
|
|
198
|
+
declare class CoverageError extends CatastroGPSError {
|
|
199
|
+
name: string;
|
|
200
|
+
}
|
|
201
|
+
declare class AmbiguousReferenceError extends CatastroGPSError {
|
|
202
|
+
name: string;
|
|
203
|
+
get candidates(): Array<{
|
|
204
|
+
country: string;
|
|
205
|
+
confidence?: number;
|
|
206
|
+
supported?: boolean;
|
|
207
|
+
}>;
|
|
208
|
+
}
|
|
209
|
+
declare class QuotaExceededError extends CatastroGPSError {
|
|
210
|
+
name: string;
|
|
211
|
+
}
|
|
212
|
+
declare class RateLimitError extends CatastroGPSError {
|
|
213
|
+
name: string;
|
|
214
|
+
retryAfterSeconds?: number;
|
|
215
|
+
}
|
|
216
|
+
declare class ServiceUnavailableError extends CatastroGPSError {
|
|
217
|
+
name: string;
|
|
218
|
+
}
|
|
219
|
+
declare class ServerError extends CatastroGPSError {
|
|
220
|
+
name: string;
|
|
221
|
+
}
|
|
222
|
+
declare class TimeoutError extends CatastroGPSError {
|
|
223
|
+
name: string;
|
|
224
|
+
}
|
|
225
|
+
declare class NetworkError extends CatastroGPSError {
|
|
226
|
+
name: string;
|
|
227
|
+
}
|
|
228
|
+
|
|
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 };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AmbiguousReferenceError: () => AmbiguousReferenceError,
|
|
24
|
+
AuthenticationError: () => AuthenticationError,
|
|
25
|
+
COUNTRY_CODES: () => COUNTRY_CODES,
|
|
26
|
+
CatastroGPS: () => CatastroGPS,
|
|
27
|
+
CatastroGPSError: () => CatastroGPSError,
|
|
28
|
+
CoverageError: () => CoverageError,
|
|
29
|
+
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
30
|
+
DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES,
|
|
31
|
+
DEFAULT_TIMEOUT_MS: () => DEFAULT_TIMEOUT_MS,
|
|
32
|
+
ENRICHMENT_COUNTRY_CODES: () => ENRICHMENT_COUNTRY_CODES,
|
|
33
|
+
ForbiddenError: () => ForbiddenError,
|
|
34
|
+
NetworkError: () => NetworkError,
|
|
35
|
+
NotFoundError: () => NotFoundError,
|
|
36
|
+
QuotaExceededError: () => QuotaExceededError,
|
|
37
|
+
RateLimitError: () => RateLimitError,
|
|
38
|
+
ServerError: () => ServerError,
|
|
39
|
+
ServiceUnavailableError: () => ServiceUnavailableError,
|
|
40
|
+
TimeoutError: () => TimeoutError,
|
|
41
|
+
VERSION: () => VERSION,
|
|
42
|
+
ValidationError: () => ValidationError
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(index_exports);
|
|
45
|
+
|
|
46
|
+
// src/errors.ts
|
|
47
|
+
var CatastroGPSError = class extends Error {
|
|
48
|
+
status;
|
|
49
|
+
code;
|
|
50
|
+
details;
|
|
51
|
+
body;
|
|
52
|
+
constructor(message, options = {}) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = "CatastroGPSError";
|
|
55
|
+
this.status = options.status;
|
|
56
|
+
this.code = options.code;
|
|
57
|
+
this.details = options.details;
|
|
58
|
+
this.body = options.body ?? {};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var AuthenticationError = class extends CatastroGPSError {
|
|
62
|
+
name = "AuthenticationError";
|
|
63
|
+
};
|
|
64
|
+
var ForbiddenError = class extends CatastroGPSError {
|
|
65
|
+
name = "ForbiddenError";
|
|
66
|
+
};
|
|
67
|
+
var NotFoundError = class extends CatastroGPSError {
|
|
68
|
+
name = "NotFoundError";
|
|
69
|
+
};
|
|
70
|
+
var ValidationError = class extends CatastroGPSError {
|
|
71
|
+
name = "ValidationError";
|
|
72
|
+
};
|
|
73
|
+
var CoverageError = class extends CatastroGPSError {
|
|
74
|
+
name = "CoverageError";
|
|
75
|
+
};
|
|
76
|
+
var AmbiguousReferenceError = class extends CatastroGPSError {
|
|
77
|
+
name = "AmbiguousReferenceError";
|
|
78
|
+
get candidates() {
|
|
79
|
+
const details = this.details;
|
|
80
|
+
return details?.candidates ?? [];
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
var QuotaExceededError = class extends CatastroGPSError {
|
|
84
|
+
name = "QuotaExceededError";
|
|
85
|
+
};
|
|
86
|
+
var RateLimitError = class extends CatastroGPSError {
|
|
87
|
+
name = "RateLimitError";
|
|
88
|
+
retryAfterSeconds;
|
|
89
|
+
};
|
|
90
|
+
var ServiceUnavailableError = class extends CatastroGPSError {
|
|
91
|
+
name = "ServiceUnavailableError";
|
|
92
|
+
};
|
|
93
|
+
var ServerError = class extends CatastroGPSError {
|
|
94
|
+
name = "ServerError";
|
|
95
|
+
};
|
|
96
|
+
var TimeoutError = class extends CatastroGPSError {
|
|
97
|
+
name = "TimeoutError";
|
|
98
|
+
};
|
|
99
|
+
var NetworkError = class extends CatastroGPSError {
|
|
100
|
+
name = "NetworkError";
|
|
101
|
+
};
|
|
102
|
+
function errorFromResponse(status, body, retryAfter) {
|
|
103
|
+
const code = typeof body.code === "string" ? body.code : void 0;
|
|
104
|
+
const message = typeof body.error === "string" && body.error || typeof body.message === "string" && body.message || `HTTP ${status}`;
|
|
105
|
+
const details = body.data ?? body.parsed;
|
|
106
|
+
const options = { status, code, details, body };
|
|
107
|
+
if (code === "CNV_AMBIGUOUS" || status === 300) return new AmbiguousReferenceError(message, options);
|
|
108
|
+
if (code === "CNV_COVERAGE") return new CoverageError(message, options);
|
|
109
|
+
if (code === "KEY_AUTH_004") return new QuotaExceededError(message, options);
|
|
110
|
+
if (status === 429) {
|
|
111
|
+
const error = new RateLimitError(message, options);
|
|
112
|
+
error.retryAfterSeconds = retryAfter;
|
|
113
|
+
return error;
|
|
114
|
+
}
|
|
115
|
+
if (status === 401) return new AuthenticationError(message, options);
|
|
116
|
+
if (status === 403) return new ForbiddenError(message, options);
|
|
117
|
+
if (status === 404) return new NotFoundError(message, options);
|
|
118
|
+
if (status === 400 || status === 422) return new ValidationError(message, options);
|
|
119
|
+
if (status === 503) return new ServiceUnavailableError(message, options);
|
|
120
|
+
if (status >= 500) return new ServerError(message, options);
|
|
121
|
+
return new CatastroGPSError(message, options);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/resources/export.ts
|
|
125
|
+
var FORMATS = ["kml", "gpx", "dxf"];
|
|
126
|
+
var ExportResource = class {
|
|
127
|
+
constructor(client) {
|
|
128
|
+
this.client = client;
|
|
129
|
+
}
|
|
130
|
+
client;
|
|
131
|
+
async file(reference, format, options = {}) {
|
|
132
|
+
if (!FORMATS.includes(format)) {
|
|
133
|
+
throw new CatastroGPSError(`format must be one of ${FORMATS.join(", ")}`);
|
|
134
|
+
}
|
|
135
|
+
if (!reference.trim()) throw new CatastroGPSError("reference must not be empty");
|
|
136
|
+
return this.client.request("GET", `/api/export/${format}`, {
|
|
137
|
+
query: { refcat: reference.trim(), country: options.country },
|
|
138
|
+
raw: true
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/resources/parcels.ts
|
|
144
|
+
var ParcelsResource = class {
|
|
145
|
+
constructor(client) {
|
|
146
|
+
this.client = client;
|
|
147
|
+
}
|
|
148
|
+
client;
|
|
149
|
+
async get(reference, options = {}) {
|
|
150
|
+
return this.client.request("GET", parcelPath(reference), { query: { country: options.country } });
|
|
151
|
+
}
|
|
152
|
+
async atPoint(point) {
|
|
153
|
+
if (!Number.isFinite(point.lat) || !Number.isFinite(point.lng)) {
|
|
154
|
+
throw new CatastroGPSError("lat and lng must be finite numbers");
|
|
155
|
+
}
|
|
156
|
+
return this.client.request("GET", "/api/search/coordinates", {
|
|
157
|
+
query: { lat: point.lat, lng: point.lng, country: point.country }
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async findByAddress(address) {
|
|
161
|
+
if (!address.trim()) throw new CatastroGPSError("address must not be empty");
|
|
162
|
+
return this.client.request("POST", "/api/search/address/parse", { body: { direccion: address } });
|
|
163
|
+
}
|
|
164
|
+
async geometry(reference, options = {}) {
|
|
165
|
+
return this.client.request("GET", parcelPath(reference, "/polygon"), { query: { country: options.country } });
|
|
166
|
+
}
|
|
167
|
+
async solar(reference, options = {}) {
|
|
168
|
+
return this.client.request("GET", parcelPath(reference, "/solar"), { query: { country: options.country } });
|
|
169
|
+
}
|
|
170
|
+
async agriculture(reference, options = {}) {
|
|
171
|
+
const data = await this.client.request("GET", parcelPath(reference, "/agro"), {
|
|
172
|
+
query: { country: options.country }
|
|
173
|
+
});
|
|
174
|
+
return data.agro ?? data;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
function parcelPath(reference, suffix = "") {
|
|
178
|
+
if (!reference.trim()) throw new CatastroGPSError("reference must not be empty");
|
|
179
|
+
return `/api/catastro/${encodeURIComponent(reference.trim())}${suffix}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/version.ts
|
|
183
|
+
var VERSION = "1.0.0";
|
|
184
|
+
|
|
185
|
+
// src/client.ts
|
|
186
|
+
var DEFAULT_BASE_URL = "https://api.catastrogps.es";
|
|
187
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
188
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
189
|
+
var BACKOFF_BASE_MS = 500;
|
|
190
|
+
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([502, 503, 504]);
|
|
191
|
+
var CatastroGPS = class {
|
|
192
|
+
parcels;
|
|
193
|
+
export;
|
|
194
|
+
lastQuota;
|
|
195
|
+
apiKey;
|
|
196
|
+
baseUrl;
|
|
197
|
+
timeoutMs;
|
|
198
|
+
maxRetries;
|
|
199
|
+
fetchImpl;
|
|
200
|
+
constructor(options = {}) {
|
|
201
|
+
const apiKey = options.apiKey ?? readEnv("CATASTROGPS_API_KEY");
|
|
202
|
+
if (!apiKey) {
|
|
203
|
+
throw new CatastroGPSError(
|
|
204
|
+
"An API key is required: pass { apiKey } or set CATASTROGPS_API_KEY. Get a free key at https://www.catastrogps.es/developers"
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
208
|
+
if (!fetchImpl) {
|
|
209
|
+
throw new CatastroGPSError("No fetch implementation found. Use Node.js 18+ or pass { fetch }.");
|
|
210
|
+
}
|
|
211
|
+
this.apiKey = apiKey;
|
|
212
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
213
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
214
|
+
this.maxRetries = Math.max(0, options.maxRetries ?? DEFAULT_MAX_RETRIES);
|
|
215
|
+
this.fetchImpl = fetchImpl;
|
|
216
|
+
this.parcels = new ParcelsResource(this);
|
|
217
|
+
this.export = new ExportResource(this);
|
|
218
|
+
}
|
|
219
|
+
async resolve(text, options = {}) {
|
|
220
|
+
return this.request("GET", "/api/resolve", { query: { q: text, hint: options.hint } });
|
|
221
|
+
}
|
|
222
|
+
async request(method, path, options = {}) {
|
|
223
|
+
const url = this.buildUrl(path, options.query);
|
|
224
|
+
let attempt = 0;
|
|
225
|
+
for (; ; ) {
|
|
226
|
+
try {
|
|
227
|
+
return await this.once(method, url, options);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (!this.shouldRetry(error, attempt)) throw error;
|
|
230
|
+
await sleep(this.retryDelayMs(error, attempt));
|
|
231
|
+
attempt += 1;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async once(method, url, options) {
|
|
236
|
+
const controller = new AbortController();
|
|
237
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
238
|
+
const headers = {
|
|
239
|
+
"X-API-Key": this.apiKey,
|
|
240
|
+
Accept: options.raw ? "*/*" : "application/json",
|
|
241
|
+
"User-Agent": `catastrogps-js/${VERSION}`
|
|
242
|
+
};
|
|
243
|
+
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
244
|
+
let response;
|
|
245
|
+
try {
|
|
246
|
+
response = await this.fetchImpl(url, {
|
|
247
|
+
method,
|
|
248
|
+
headers,
|
|
249
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
250
|
+
signal: controller.signal
|
|
251
|
+
});
|
|
252
|
+
} catch (error) {
|
|
253
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
254
|
+
throw new TimeoutError(`Request timed out after ${this.timeoutMs} ms`);
|
|
255
|
+
}
|
|
256
|
+
throw new NetworkError(`Network error: ${error instanceof Error ? error.message : String(error)}`);
|
|
257
|
+
} finally {
|
|
258
|
+
clearTimeout(timer);
|
|
259
|
+
}
|
|
260
|
+
this.captureQuota(response.headers);
|
|
261
|
+
if (!response.ok) {
|
|
262
|
+
const body2 = await readJson(response);
|
|
263
|
+
const retryAfter = Number(response.headers.get("Retry-After"));
|
|
264
|
+
throw errorFromResponse(response.status, body2, Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : void 0);
|
|
265
|
+
}
|
|
266
|
+
if (options.raw) return await response.arrayBuffer();
|
|
267
|
+
const body = await readJson(response);
|
|
268
|
+
return "data" in body ? body.data : body;
|
|
269
|
+
}
|
|
270
|
+
buildUrl(path, query) {
|
|
271
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
272
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
273
|
+
if (value !== void 0 && value !== "") url.searchParams.set(key, String(value));
|
|
274
|
+
}
|
|
275
|
+
return url.toString();
|
|
276
|
+
}
|
|
277
|
+
shouldRetry(error, attempt) {
|
|
278
|
+
if (attempt >= this.maxRetries) return false;
|
|
279
|
+
if (error instanceof TimeoutError || error instanceof NetworkError) return true;
|
|
280
|
+
if (error instanceof RateLimitError) return true;
|
|
281
|
+
return error instanceof CatastroGPSError && error.status !== void 0 && RETRYABLE_STATUS.has(error.status);
|
|
282
|
+
}
|
|
283
|
+
retryDelayMs(error, attempt) {
|
|
284
|
+
if (error instanceof RateLimitError && error.retryAfterSeconds) return error.retryAfterSeconds * 1e3;
|
|
285
|
+
return BACKOFF_BASE_MS * 2 ** attempt;
|
|
286
|
+
}
|
|
287
|
+
captureQuota(headers) {
|
|
288
|
+
const limit = headers.get("X-RateLimit-Limit");
|
|
289
|
+
if (limit === null) return;
|
|
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
|
+
};
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
async function readJson(response) {
|
|
300
|
+
try {
|
|
301
|
+
const parsed = await response.json();
|
|
302
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
303
|
+
} catch {
|
|
304
|
+
return {};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function readEnv(name) {
|
|
308
|
+
const env = globalThis.process?.env;
|
|
309
|
+
return env?.[name] || void 0;
|
|
310
|
+
}
|
|
311
|
+
function sleep(ms) {
|
|
312
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// src/types.ts
|
|
316
|
+
var COUNTRY_CODES = [
|
|
317
|
+
"ES",
|
|
318
|
+
"PV",
|
|
319
|
+
"NA",
|
|
320
|
+
"PT",
|
|
321
|
+
"FR",
|
|
322
|
+
"IT",
|
|
323
|
+
"DE",
|
|
324
|
+
"AT",
|
|
325
|
+
"CH",
|
|
326
|
+
"LI",
|
|
327
|
+
"BE",
|
|
328
|
+
"NL",
|
|
329
|
+
"LU",
|
|
330
|
+
"PL",
|
|
331
|
+
"CZ",
|
|
332
|
+
"SK",
|
|
333
|
+
"SI",
|
|
334
|
+
"HR",
|
|
335
|
+
"BG",
|
|
336
|
+
"GR",
|
|
337
|
+
"CY",
|
|
338
|
+
"DK",
|
|
339
|
+
"SE",
|
|
340
|
+
"NO",
|
|
341
|
+
"FI",
|
|
342
|
+
"IS",
|
|
343
|
+
"EE",
|
|
344
|
+
"LV",
|
|
345
|
+
"LT",
|
|
346
|
+
"IE",
|
|
347
|
+
"UK"
|
|
348
|
+
];
|
|
349
|
+
var ENRICHMENT_COUNTRY_CODES = ["ES", "PV", "NA", "PT", "FR", "IT", "DE"];
|
|
350
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
351
|
+
0 && (module.exports = {
|
|
352
|
+
AmbiguousReferenceError,
|
|
353
|
+
AuthenticationError,
|
|
354
|
+
COUNTRY_CODES,
|
|
355
|
+
CatastroGPS,
|
|
356
|
+
CatastroGPSError,
|
|
357
|
+
CoverageError,
|
|
358
|
+
DEFAULT_BASE_URL,
|
|
359
|
+
DEFAULT_MAX_RETRIES,
|
|
360
|
+
DEFAULT_TIMEOUT_MS,
|
|
361
|
+
ENRICHMENT_COUNTRY_CODES,
|
|
362
|
+
ForbiddenError,
|
|
363
|
+
NetworkError,
|
|
364
|
+
NotFoundError,
|
|
365
|
+
QuotaExceededError,
|
|
366
|
+
RateLimitError,
|
|
367
|
+
ServerError,
|
|
368
|
+
ServiceUnavailableError,
|
|
369
|
+
TimeoutError,
|
|
370
|
+
VERSION,
|
|
371
|
+
ValidationError
|
|
372
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var CatastroGPSError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
details;
|
|
6
|
+
body;
|
|
7
|
+
constructor(message, options = {}) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "CatastroGPSError";
|
|
10
|
+
this.status = options.status;
|
|
11
|
+
this.code = options.code;
|
|
12
|
+
this.details = options.details;
|
|
13
|
+
this.body = options.body ?? {};
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var AuthenticationError = class extends CatastroGPSError {
|
|
17
|
+
name = "AuthenticationError";
|
|
18
|
+
};
|
|
19
|
+
var ForbiddenError = class extends CatastroGPSError {
|
|
20
|
+
name = "ForbiddenError";
|
|
21
|
+
};
|
|
22
|
+
var NotFoundError = class extends CatastroGPSError {
|
|
23
|
+
name = "NotFoundError";
|
|
24
|
+
};
|
|
25
|
+
var ValidationError = class extends CatastroGPSError {
|
|
26
|
+
name = "ValidationError";
|
|
27
|
+
};
|
|
28
|
+
var CoverageError = class extends CatastroGPSError {
|
|
29
|
+
name = "CoverageError";
|
|
30
|
+
};
|
|
31
|
+
var AmbiguousReferenceError = class extends CatastroGPSError {
|
|
32
|
+
name = "AmbiguousReferenceError";
|
|
33
|
+
get candidates() {
|
|
34
|
+
const details = this.details;
|
|
35
|
+
return details?.candidates ?? [];
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var QuotaExceededError = class extends CatastroGPSError {
|
|
39
|
+
name = "QuotaExceededError";
|
|
40
|
+
};
|
|
41
|
+
var RateLimitError = class extends CatastroGPSError {
|
|
42
|
+
name = "RateLimitError";
|
|
43
|
+
retryAfterSeconds;
|
|
44
|
+
};
|
|
45
|
+
var ServiceUnavailableError = class extends CatastroGPSError {
|
|
46
|
+
name = "ServiceUnavailableError";
|
|
47
|
+
};
|
|
48
|
+
var ServerError = class extends CatastroGPSError {
|
|
49
|
+
name = "ServerError";
|
|
50
|
+
};
|
|
51
|
+
var TimeoutError = class extends CatastroGPSError {
|
|
52
|
+
name = "TimeoutError";
|
|
53
|
+
};
|
|
54
|
+
var NetworkError = class extends CatastroGPSError {
|
|
55
|
+
name = "NetworkError";
|
|
56
|
+
};
|
|
57
|
+
function errorFromResponse(status, body, retryAfter) {
|
|
58
|
+
const code = typeof body.code === "string" ? body.code : void 0;
|
|
59
|
+
const message = typeof body.error === "string" && body.error || typeof body.message === "string" && body.message || `HTTP ${status}`;
|
|
60
|
+
const details = body.data ?? body.parsed;
|
|
61
|
+
const options = { status, code, details, body };
|
|
62
|
+
if (code === "CNV_AMBIGUOUS" || status === 300) return new AmbiguousReferenceError(message, options);
|
|
63
|
+
if (code === "CNV_COVERAGE") return new CoverageError(message, options);
|
|
64
|
+
if (code === "KEY_AUTH_004") return new QuotaExceededError(message, options);
|
|
65
|
+
if (status === 429) {
|
|
66
|
+
const error = new RateLimitError(message, options);
|
|
67
|
+
error.retryAfterSeconds = retryAfter;
|
|
68
|
+
return error;
|
|
69
|
+
}
|
|
70
|
+
if (status === 401) return new AuthenticationError(message, options);
|
|
71
|
+
if (status === 403) return new ForbiddenError(message, options);
|
|
72
|
+
if (status === 404) return new NotFoundError(message, options);
|
|
73
|
+
if (status === 400 || status === 422) return new ValidationError(message, options);
|
|
74
|
+
if (status === 503) return new ServiceUnavailableError(message, options);
|
|
75
|
+
if (status >= 500) return new ServerError(message, options);
|
|
76
|
+
return new CatastroGPSError(message, options);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/resources/export.ts
|
|
80
|
+
var FORMATS = ["kml", "gpx", "dxf"];
|
|
81
|
+
var ExportResource = class {
|
|
82
|
+
constructor(client) {
|
|
83
|
+
this.client = client;
|
|
84
|
+
}
|
|
85
|
+
client;
|
|
86
|
+
async file(reference, format, options = {}) {
|
|
87
|
+
if (!FORMATS.includes(format)) {
|
|
88
|
+
throw new CatastroGPSError(`format must be one of ${FORMATS.join(", ")}`);
|
|
89
|
+
}
|
|
90
|
+
if (!reference.trim()) throw new CatastroGPSError("reference must not be empty");
|
|
91
|
+
return this.client.request("GET", `/api/export/${format}`, {
|
|
92
|
+
query: { refcat: reference.trim(), country: options.country },
|
|
93
|
+
raw: true
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/resources/parcels.ts
|
|
99
|
+
var ParcelsResource = class {
|
|
100
|
+
constructor(client) {
|
|
101
|
+
this.client = client;
|
|
102
|
+
}
|
|
103
|
+
client;
|
|
104
|
+
async get(reference, options = {}) {
|
|
105
|
+
return this.client.request("GET", parcelPath(reference), { query: { country: options.country } });
|
|
106
|
+
}
|
|
107
|
+
async atPoint(point) {
|
|
108
|
+
if (!Number.isFinite(point.lat) || !Number.isFinite(point.lng)) {
|
|
109
|
+
throw new CatastroGPSError("lat and lng must be finite numbers");
|
|
110
|
+
}
|
|
111
|
+
return this.client.request("GET", "/api/search/coordinates", {
|
|
112
|
+
query: { lat: point.lat, lng: point.lng, country: point.country }
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async findByAddress(address) {
|
|
116
|
+
if (!address.trim()) throw new CatastroGPSError("address must not be empty");
|
|
117
|
+
return this.client.request("POST", "/api/search/address/parse", { body: { direccion: address } });
|
|
118
|
+
}
|
|
119
|
+
async geometry(reference, options = {}) {
|
|
120
|
+
return this.client.request("GET", parcelPath(reference, "/polygon"), { query: { country: options.country } });
|
|
121
|
+
}
|
|
122
|
+
async solar(reference, options = {}) {
|
|
123
|
+
return this.client.request("GET", parcelPath(reference, "/solar"), { query: { country: options.country } });
|
|
124
|
+
}
|
|
125
|
+
async agriculture(reference, options = {}) {
|
|
126
|
+
const data = await this.client.request("GET", parcelPath(reference, "/agro"), {
|
|
127
|
+
query: { country: options.country }
|
|
128
|
+
});
|
|
129
|
+
return data.agro ?? data;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
function parcelPath(reference, suffix = "") {
|
|
133
|
+
if (!reference.trim()) throw new CatastroGPSError("reference must not be empty");
|
|
134
|
+
return `/api/catastro/${encodeURIComponent(reference.trim())}${suffix}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/version.ts
|
|
138
|
+
var VERSION = "1.0.0";
|
|
139
|
+
|
|
140
|
+
// src/client.ts
|
|
141
|
+
var DEFAULT_BASE_URL = "https://api.catastrogps.es";
|
|
142
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
143
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
144
|
+
var BACKOFF_BASE_MS = 500;
|
|
145
|
+
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([502, 503, 504]);
|
|
146
|
+
var CatastroGPS = class {
|
|
147
|
+
parcels;
|
|
148
|
+
export;
|
|
149
|
+
lastQuota;
|
|
150
|
+
apiKey;
|
|
151
|
+
baseUrl;
|
|
152
|
+
timeoutMs;
|
|
153
|
+
maxRetries;
|
|
154
|
+
fetchImpl;
|
|
155
|
+
constructor(options = {}) {
|
|
156
|
+
const apiKey = options.apiKey ?? readEnv("CATASTROGPS_API_KEY");
|
|
157
|
+
if (!apiKey) {
|
|
158
|
+
throw new CatastroGPSError(
|
|
159
|
+
"An API key is required: pass { apiKey } or set CATASTROGPS_API_KEY. Get a free key at https://www.catastrogps.es/developers"
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
163
|
+
if (!fetchImpl) {
|
|
164
|
+
throw new CatastroGPSError("No fetch implementation found. Use Node.js 18+ or pass { fetch }.");
|
|
165
|
+
}
|
|
166
|
+
this.apiKey = apiKey;
|
|
167
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
168
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
169
|
+
this.maxRetries = Math.max(0, options.maxRetries ?? DEFAULT_MAX_RETRIES);
|
|
170
|
+
this.fetchImpl = fetchImpl;
|
|
171
|
+
this.parcels = new ParcelsResource(this);
|
|
172
|
+
this.export = new ExportResource(this);
|
|
173
|
+
}
|
|
174
|
+
async resolve(text, options = {}) {
|
|
175
|
+
return this.request("GET", "/api/resolve", { query: { q: text, hint: options.hint } });
|
|
176
|
+
}
|
|
177
|
+
async request(method, path, options = {}) {
|
|
178
|
+
const url = this.buildUrl(path, options.query);
|
|
179
|
+
let attempt = 0;
|
|
180
|
+
for (; ; ) {
|
|
181
|
+
try {
|
|
182
|
+
return await this.once(method, url, options);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
if (!this.shouldRetry(error, attempt)) throw error;
|
|
185
|
+
await sleep(this.retryDelayMs(error, attempt));
|
|
186
|
+
attempt += 1;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async once(method, url, options) {
|
|
191
|
+
const controller = new AbortController();
|
|
192
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
193
|
+
const headers = {
|
|
194
|
+
"X-API-Key": this.apiKey,
|
|
195
|
+
Accept: options.raw ? "*/*" : "application/json",
|
|
196
|
+
"User-Agent": `catastrogps-js/${VERSION}`
|
|
197
|
+
};
|
|
198
|
+
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
199
|
+
let response;
|
|
200
|
+
try {
|
|
201
|
+
response = await this.fetchImpl(url, {
|
|
202
|
+
method,
|
|
203
|
+
headers,
|
|
204
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
205
|
+
signal: controller.signal
|
|
206
|
+
});
|
|
207
|
+
} catch (error) {
|
|
208
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
209
|
+
throw new TimeoutError(`Request timed out after ${this.timeoutMs} ms`);
|
|
210
|
+
}
|
|
211
|
+
throw new NetworkError(`Network error: ${error instanceof Error ? error.message : String(error)}`);
|
|
212
|
+
} finally {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
}
|
|
215
|
+
this.captureQuota(response.headers);
|
|
216
|
+
if (!response.ok) {
|
|
217
|
+
const body2 = await readJson(response);
|
|
218
|
+
const retryAfter = Number(response.headers.get("Retry-After"));
|
|
219
|
+
throw errorFromResponse(response.status, body2, Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : void 0);
|
|
220
|
+
}
|
|
221
|
+
if (options.raw) return await response.arrayBuffer();
|
|
222
|
+
const body = await readJson(response);
|
|
223
|
+
return "data" in body ? body.data : body;
|
|
224
|
+
}
|
|
225
|
+
buildUrl(path, query) {
|
|
226
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
227
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
228
|
+
if (value !== void 0 && value !== "") url.searchParams.set(key, String(value));
|
|
229
|
+
}
|
|
230
|
+
return url.toString();
|
|
231
|
+
}
|
|
232
|
+
shouldRetry(error, attempt) {
|
|
233
|
+
if (attempt >= this.maxRetries) return false;
|
|
234
|
+
if (error instanceof TimeoutError || error instanceof NetworkError) return true;
|
|
235
|
+
if (error instanceof RateLimitError) return true;
|
|
236
|
+
return error instanceof CatastroGPSError && error.status !== void 0 && RETRYABLE_STATUS.has(error.status);
|
|
237
|
+
}
|
|
238
|
+
retryDelayMs(error, attempt) {
|
|
239
|
+
if (error instanceof RateLimitError && error.retryAfterSeconds) return error.retryAfterSeconds * 1e3;
|
|
240
|
+
return BACKOFF_BASE_MS * 2 ** attempt;
|
|
241
|
+
}
|
|
242
|
+
captureQuota(headers) {
|
|
243
|
+
const limit = headers.get("X-RateLimit-Limit");
|
|
244
|
+
if (limit === null) return;
|
|
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
|
+
};
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
async function readJson(response) {
|
|
255
|
+
try {
|
|
256
|
+
const parsed = await response.json();
|
|
257
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
258
|
+
} catch {
|
|
259
|
+
return {};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function readEnv(name) {
|
|
263
|
+
const env = globalThis.process?.env;
|
|
264
|
+
return env?.[name] || void 0;
|
|
265
|
+
}
|
|
266
|
+
function sleep(ms) {
|
|
267
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/types.ts
|
|
271
|
+
var COUNTRY_CODES = [
|
|
272
|
+
"ES",
|
|
273
|
+
"PV",
|
|
274
|
+
"NA",
|
|
275
|
+
"PT",
|
|
276
|
+
"FR",
|
|
277
|
+
"IT",
|
|
278
|
+
"DE",
|
|
279
|
+
"AT",
|
|
280
|
+
"CH",
|
|
281
|
+
"LI",
|
|
282
|
+
"BE",
|
|
283
|
+
"NL",
|
|
284
|
+
"LU",
|
|
285
|
+
"PL",
|
|
286
|
+
"CZ",
|
|
287
|
+
"SK",
|
|
288
|
+
"SI",
|
|
289
|
+
"HR",
|
|
290
|
+
"BG",
|
|
291
|
+
"GR",
|
|
292
|
+
"CY",
|
|
293
|
+
"DK",
|
|
294
|
+
"SE",
|
|
295
|
+
"NO",
|
|
296
|
+
"FI",
|
|
297
|
+
"IS",
|
|
298
|
+
"EE",
|
|
299
|
+
"LV",
|
|
300
|
+
"LT",
|
|
301
|
+
"IE",
|
|
302
|
+
"UK"
|
|
303
|
+
];
|
|
304
|
+
var ENRICHMENT_COUNTRY_CODES = ["ES", "PV", "NA", "PT", "FR", "IT", "DE"];
|
|
305
|
+
export {
|
|
306
|
+
AmbiguousReferenceError,
|
|
307
|
+
AuthenticationError,
|
|
308
|
+
COUNTRY_CODES,
|
|
309
|
+
CatastroGPS,
|
|
310
|
+
CatastroGPSError,
|
|
311
|
+
CoverageError,
|
|
312
|
+
DEFAULT_BASE_URL,
|
|
313
|
+
DEFAULT_MAX_RETRIES,
|
|
314
|
+
DEFAULT_TIMEOUT_MS,
|
|
315
|
+
ENRICHMENT_COUNTRY_CODES,
|
|
316
|
+
ForbiddenError,
|
|
317
|
+
NetworkError,
|
|
318
|
+
NotFoundError,
|
|
319
|
+
QuotaExceededError,
|
|
320
|
+
RateLimitError,
|
|
321
|
+
ServerError,
|
|
322
|
+
ServiceUnavailableError,
|
|
323
|
+
TimeoutError,
|
|
324
|
+
VERSION,
|
|
325
|
+
ValidationError
|
|
326
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "catastrogps",
|
|
3
|
+
"version": "1.0.0",
|
|
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
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"cadastre",
|
|
35
|
+
"cadastral",
|
|
36
|
+
"catastro",
|
|
37
|
+
"cadastre-api",
|
|
38
|
+
"catastro-api",
|
|
39
|
+
"parcel",
|
|
40
|
+
"land-registry",
|
|
41
|
+
"gis",
|
|
42
|
+
"geojson",
|
|
43
|
+
"europe",
|
|
44
|
+
"spain",
|
|
45
|
+
"portugal",
|
|
46
|
+
"france",
|
|
47
|
+
"italy",
|
|
48
|
+
"germany",
|
|
49
|
+
"real-estate",
|
|
50
|
+
"proptech",
|
|
51
|
+
"sdk"
|
|
52
|
+
],
|
|
53
|
+
"author": "The Hidden Panda <soporte@catastrogps.es>",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"homepage": "https://www.catastrogps.es/developers",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"email": "soporte@catastrogps.es"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"tsup": "^8.0.0",
|
|
61
|
+
"typescript": "^5.4.0",
|
|
62
|
+
"vitest": "^3.0.0",
|
|
63
|
+
"@types/node": "^22.0.0"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=18.0.0"
|
|
67
|
+
}
|
|
68
|
+
}
|