@liftitinc/geocoding 0.2.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 +323 -0
- package/dist/index.cjs +4800 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +204 -0
- package/dist/index.d.ts +204 -0
- package/dist/index.js +4782 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# @liftit/geocoding
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
JavaScript/TypeScript SDK for the Liftit Geocoding API.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @liftit/geocoding
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @liftit/geocoding
|
|
15
|
+
# or
|
|
16
|
+
yarn add @liftit/geocoding
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { GeocodingClient } from '@liftit/geocoding';
|
|
23
|
+
|
|
24
|
+
const client = new GeocodingClient({
|
|
25
|
+
apiKey: 'your-api-key',
|
|
26
|
+
// Optional configuration:
|
|
27
|
+
// baseUrl: 'https://geocoding.liftit.co',
|
|
28
|
+
// timeout: 10000,
|
|
29
|
+
// maxRetries: 3,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Forward geocoding - convert address to coordinates
|
|
33
|
+
const result = await client.geocode({
|
|
34
|
+
country: 'co',
|
|
35
|
+
city: 'Bogota',
|
|
36
|
+
address: 'Calle 100 # 19-61',
|
|
37
|
+
// Optional parameters:
|
|
38
|
+
// region: 'Cundinamarca',
|
|
39
|
+
// custom_zone: true,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
console.log(result.location); // { lat: 4.6097, lng: -74.0817 }
|
|
43
|
+
console.log(result.geocode.formatted_address);
|
|
44
|
+
|
|
45
|
+
// Reverse geocoding - convert coordinates to address
|
|
46
|
+
const address = await client.reverseGeocode({
|
|
47
|
+
lat: 4.6097,
|
|
48
|
+
lng: -74.0817,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(address.geocode.formatted_address);
|
|
52
|
+
console.log(address.address_components?.city);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- **TypeScript Support**: Full type definitions with comprehensive type safety
|
|
58
|
+
- **Zero Dependencies**: Uses native `fetch` API (Node.js 18+ required)
|
|
59
|
+
- **Automatic Retry**: Exponential backoff with full jitter for transient errors
|
|
60
|
+
- **Rate Limit Handling**: Respects `Retry-After` headers automatically
|
|
61
|
+
- **Error Hierarchy**: Typed error classes for precise error handling
|
|
62
|
+
- **Zod Schemas**: Exported schemas for request/response validation
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
| Parameter | Type | Default | Description |
|
|
67
|
+
|-----------|------|---------|-------------|
|
|
68
|
+
| `apiKey` | `string` | Required | Your Liftit Geocoding API key |
|
|
69
|
+
| `baseUrl` | `string` | `"https://geocoding.liftit.co"` | API base URL |
|
|
70
|
+
| `timeout` | `number` | `10000` | Request timeout in milliseconds |
|
|
71
|
+
| `maxRetries` | `number` | `3` | Maximum retry attempts for transient errors |
|
|
72
|
+
| `baseDelay` | `number` | `1000` | Initial retry delay in milliseconds |
|
|
73
|
+
| `maxDelay` | `number` | `30000` | Maximum retry delay cap in milliseconds |
|
|
74
|
+
|
|
75
|
+
**Example:**
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const client = new GeocodingClient({
|
|
79
|
+
apiKey: 'your-api-key',
|
|
80
|
+
timeout: 15000,
|
|
81
|
+
maxRetries: 5,
|
|
82
|
+
baseDelay: 2000,
|
|
83
|
+
maxDelay: 60000,
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Retry Behavior
|
|
88
|
+
|
|
89
|
+
The SDK automatically retries requests for transient errors:
|
|
90
|
+
|
|
91
|
+
| Error Type | Retryable | Strategy |
|
|
92
|
+
|------------|-----------|----------|
|
|
93
|
+
| Rate limit (429) | Yes | Uses `Retry-After` header if present |
|
|
94
|
+
| Server error (500, 502, 503, 504) | Yes | Exponential backoff with full jitter |
|
|
95
|
+
| Timeout | Yes | Exponential backoff with full jitter |
|
|
96
|
+
| Network errors | Yes | Exponential backoff with full jitter |
|
|
97
|
+
| Validation (400) | No | Fails immediately |
|
|
98
|
+
| Authentication (401) | No | Fails immediately |
|
|
99
|
+
| User abort | No | Fails immediately |
|
|
100
|
+
|
|
101
|
+
### Retry Timing
|
|
102
|
+
|
|
103
|
+
- **Initial delay**: 1 second (configurable via `baseDelay`)
|
|
104
|
+
- **Maximum delay**: 30 seconds (configurable via `maxDelay`)
|
|
105
|
+
- **Multiplier**: 2x exponential growth
|
|
106
|
+
- **Jitter**: Full random jitter (0 to calculated delay)
|
|
107
|
+
- **Default attempts**: 3 retries (configurable via `maxRetries`)
|
|
108
|
+
|
|
109
|
+
**Formula:** `delay = min(baseDelay * 2^attempt * random(), maxDelay)`
|
|
110
|
+
|
|
111
|
+
### Disabling Retries
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Disable retries for testing or special cases
|
|
115
|
+
const client = new GeocodingClient({
|
|
116
|
+
apiKey: 'your-api-key',
|
|
117
|
+
maxRetries: 0,
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Error Handling
|
|
122
|
+
|
|
123
|
+
The SDK provides a comprehensive error hierarchy:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import {
|
|
127
|
+
GeocodingClient,
|
|
128
|
+
GeocodeError,
|
|
129
|
+
ValidationError,
|
|
130
|
+
AuthenticationError,
|
|
131
|
+
RateLimitError,
|
|
132
|
+
UpstreamError,
|
|
133
|
+
} from '@liftit/geocoding';
|
|
134
|
+
|
|
135
|
+
const client = new GeocodingClient({ apiKey: 'your-api-key' });
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const result = await client.geocode({
|
|
139
|
+
country: 'co',
|
|
140
|
+
city: 'Bogota',
|
|
141
|
+
address: 'Calle 100 # 19-61',
|
|
142
|
+
});
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error instanceof ValidationError) {
|
|
145
|
+
// Invalid request parameters (400)
|
|
146
|
+
console.error(`Validation error: ${error.message}`);
|
|
147
|
+
console.error(`Request ID: ${error.requestId}`);
|
|
148
|
+
} else if (error instanceof AuthenticationError) {
|
|
149
|
+
// Invalid API key (401)
|
|
150
|
+
console.error(`Authentication failed: ${error.message}`);
|
|
151
|
+
} else if (error instanceof RateLimitError) {
|
|
152
|
+
// Rate limit exceeded (429)
|
|
153
|
+
console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
|
|
154
|
+
console.error(`Limit: ${error.limit}, Remaining: ${error.remaining}`);
|
|
155
|
+
|
|
156
|
+
// Calculate optimal retry delay
|
|
157
|
+
const delayMs = error.getRetryDelay();
|
|
158
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
159
|
+
// Retry request...
|
|
160
|
+
} else if (error instanceof UpstreamError) {
|
|
161
|
+
// API server error (500-599)
|
|
162
|
+
console.error(`Upstream error: ${error.message}`);
|
|
163
|
+
console.error(`Status code: ${error.statusCode}`);
|
|
164
|
+
} else if (error instanceof GeocodeError) {
|
|
165
|
+
// Base class catches all SDK errors
|
|
166
|
+
console.error(`Geocoding error [${error.code}]: ${error.message}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Error Properties:**
|
|
172
|
+
|
|
173
|
+
| Error Class | Properties |
|
|
174
|
+
|-------------|------------|
|
|
175
|
+
| `GeocodeError` | `message`, `code`, `requestId` |
|
|
176
|
+
| `ValidationError` | Inherits from `GeocodeError` |
|
|
177
|
+
| `AuthenticationError` | Inherits from `GeocodeError` |
|
|
178
|
+
| `RateLimitError` | Inherits + `retryAfter`, `limit`, `remaining`, `getRetryDelay()` |
|
|
179
|
+
| `UpstreamError` | Inherits + `statusCode` |
|
|
180
|
+
|
|
181
|
+
## API Reference
|
|
182
|
+
|
|
183
|
+
### Forward Geocoding
|
|
184
|
+
|
|
185
|
+
Convert an address to geographic coordinates.
|
|
186
|
+
|
|
187
|
+
**Method:** `client.geocode(request, options?)`
|
|
188
|
+
|
|
189
|
+
**Parameters:**
|
|
190
|
+
|
|
191
|
+
| Parameter | Type | Required | Description |
|
|
192
|
+
|-----------|------|----------|-------------|
|
|
193
|
+
| `request.country` | `string` | Yes | ISO 3166-1 alpha-2 country code (ar, br, cl, co, ec, mx, pe) |
|
|
194
|
+
| `request.address` | `string` | Yes | Street address to geocode |
|
|
195
|
+
| `request.city` | `string` | No | City name (recommended for accuracy) |
|
|
196
|
+
| `request.region` | `string` | No | State/department name |
|
|
197
|
+
| `request.custom_zone` | `boolean` | No | Include zone information (default: false) |
|
|
198
|
+
| `options.signal` | `AbortSignal` | No | AbortSignal for request cancellation |
|
|
199
|
+
|
|
200
|
+
**Response:**
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
{
|
|
204
|
+
success: true,
|
|
205
|
+
data: {
|
|
206
|
+
location: { lat: number, lng: number },
|
|
207
|
+
geocode: { formatted_address: string },
|
|
208
|
+
cleaned_address: boolean,
|
|
209
|
+
zone?: { id: number, name: string, type: string }
|
|
210
|
+
},
|
|
211
|
+
requestId: string
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Example:**
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const result = await client.geocode({
|
|
219
|
+
country: 'co',
|
|
220
|
+
city: 'Bogota',
|
|
221
|
+
address: 'Calle 100 # 19-61',
|
|
222
|
+
custom_zone: true,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
console.log(result.location); // { lat: 4.6097, lng: -74.0817 }
|
|
226
|
+
console.log(result.zone?.name); // "Zone 1"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Reverse Geocoding
|
|
230
|
+
|
|
231
|
+
Convert geographic coordinates to an address.
|
|
232
|
+
|
|
233
|
+
**Method:** `client.reverseGeocode(request, options?)`
|
|
234
|
+
|
|
235
|
+
**Parameters:**
|
|
236
|
+
|
|
237
|
+
| Parameter | Type | Required | Description |
|
|
238
|
+
|-----------|------|----------|-------------|
|
|
239
|
+
| `request.lat` | `number` | Yes | Latitude (-90 to 90) |
|
|
240
|
+
| `request.lng` | `number` | Yes | Longitude (-180 to 180) |
|
|
241
|
+
| `options.signal` | `AbortSignal` | No | AbortSignal for request cancellation |
|
|
242
|
+
|
|
243
|
+
**Response:**
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
{
|
|
247
|
+
success: true,
|
|
248
|
+
data: {
|
|
249
|
+
geocode: { formatted_address: string },
|
|
250
|
+
location: { lat: number, lng: number },
|
|
251
|
+
address_components: {
|
|
252
|
+
city: string,
|
|
253
|
+
country: string
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
requestId: string
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Example:**
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const address = await client.reverseGeocode({
|
|
264
|
+
lat: 4.6097,
|
|
265
|
+
lng: -74.0817,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
console.log(address.geocode.formatted_address);
|
|
269
|
+
console.log(address.address_components?.city); // "Bogota"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Supported Countries
|
|
273
|
+
|
|
274
|
+
The SDK supports geocoding in the following countries:
|
|
275
|
+
|
|
276
|
+
| Country | Code | Example City |
|
|
277
|
+
|---------|------|--------------|
|
|
278
|
+
| Argentina | `ar` | Buenos Aires |
|
|
279
|
+
| Brazil | `br` | Sao Paulo |
|
|
280
|
+
| Chile | `cl` | Santiago |
|
|
281
|
+
| Colombia | `co` | Bogota |
|
|
282
|
+
| Ecuador | `ec` | Quito |
|
|
283
|
+
| Mexico | `mx` | Mexico City |
|
|
284
|
+
| Peru | `pe` | Lima |
|
|
285
|
+
|
|
286
|
+
## Requirements
|
|
287
|
+
|
|
288
|
+
- **Node.js**: >= 18.0.0 (required for native `fetch` API)
|
|
289
|
+
- **Runtime Dependencies**: None (zero dependencies)
|
|
290
|
+
- **TypeScript**: >= 5.0 (for TypeScript projects)
|
|
291
|
+
|
|
292
|
+
## Development
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Clone the repository
|
|
296
|
+
git clone https://github.com/Liftitapp/geocoding-enterprise.git
|
|
297
|
+
cd geocoding-enterprise
|
|
298
|
+
|
|
299
|
+
# Install dependencies
|
|
300
|
+
pnpm install
|
|
301
|
+
|
|
302
|
+
# Build the SDK
|
|
303
|
+
pnpm --filter @liftit/geocoding build
|
|
304
|
+
|
|
305
|
+
# Run tests
|
|
306
|
+
pnpm --filter @liftit/geocoding test
|
|
307
|
+
|
|
308
|
+
# Type checking
|
|
309
|
+
pnpm --filter @liftit/geocoding typecheck
|
|
310
|
+
|
|
311
|
+
# Lint
|
|
312
|
+
pnpm --filter @liftit/geocoding lint
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## License
|
|
316
|
+
|
|
317
|
+
MIT - see [LICENSE](./LICENSE) for details.
|
|
318
|
+
|
|
319
|
+
## Support
|
|
320
|
+
|
|
321
|
+
- **GitHub Issues**: [Report bugs and request features](https://github.com/Liftitapp/geocoding-enterprise/issues)
|
|
322
|
+
- **API Reference**: [View API documentation](https://geocoding.liftit.co/docs)
|
|
323
|
+
- **Homepage**: [https://geocoding.liftit.co](https://geocoding.liftit.co)
|