townshipamerica 1.0.2 → 2.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/README.md +159 -0
- package/dist/index.cjs +157 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +831 -7
- package/dist/index.d.ts +831 -7
- package/dist/index.js +157 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -194,6 +194,131 @@ const fc = await client.raw("NW 25 24N 1E 6th Meridian");
|
|
|
194
194
|
|
|
195
195
|
---
|
|
196
196
|
|
|
197
|
+
### `client.energyReport(legalLocation, options?)`
|
|
198
|
+
|
|
199
|
+
Energy parcel report for a PLSS section — state-regulator wells, operators,
|
|
200
|
+
BLM federal leases, ONRR county royalties, orphaned wells, pipelines,
|
|
201
|
+
FracFocus disclosures, and development constraints.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
const report = await client.energyReport("25 24N 1E 6th Meridian");
|
|
205
|
+
console.log(report.summary.wells_in_section);
|
|
206
|
+
console.log(report.wells?.in_section.rows[0]?.api_number);
|
|
207
|
+
|
|
208
|
+
// Only the sections you need — the rest are never queried
|
|
209
|
+
const slim = await client.energyReport("25 24N 1E 6th Meridian", {
|
|
210
|
+
include: ["wells", "pipelines"]
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Attach the parcel boundary under parcel.geometry
|
|
214
|
+
const withGeometry = await client.energyReport("25 24N 1E 6th Meridian", {
|
|
215
|
+
include: ["geometry"]
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Options:** `include` — any of `wells`, `operators`, `leases`, `royalties`,
|
|
220
|
+
`orphaned_wells`, `pipelines`, `fracfocus`, `constraints`, `geometry`.
|
|
221
|
+
|
|
222
|
+
**Returns:** `EnergyReport`. Array sections are
|
|
223
|
+
`{total, returned, truncated, more, rows}` envelopes; a failed section lands
|
|
224
|
+
in `meta.unavailable` instead of failing the report.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
### `client.federalLandReport(legalLocation, options?)`
|
|
229
|
+
|
|
230
|
+
Federal-land parcel report for a PLSS tract — surface management, BLM O&G and
|
|
231
|
+
geothermal leases, rights-of-way, flood zones, mining claims, wetlands,
|
|
232
|
+
firesheds, soils, crop history, orphaned wells, critical habitat, public
|
|
233
|
+
access, wildfire risk, and elevation.
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const report = await client.federalLandReport("NW 25 24N 1E 6th Meridian");
|
|
237
|
+
console.log(report.surface_management?.rows[0]?.agency);
|
|
238
|
+
|
|
239
|
+
const slim = await client.federalLandReport("NW 25 24N 1E 6th Meridian", {
|
|
240
|
+
include: ["og_leases", "flood_zones"]
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Options:** `include` — any of `surface_management`, `og_leases`,
|
|
245
|
+
`geothermal_leases`, `rights_of_way`, `flood_zones`, `mining_claims`,
|
|
246
|
+
`wetlands`, `fireshed`, `soils`, `crop_history`, `orphaned_wells`,
|
|
247
|
+
`critical_habitat`, `public_access`, `wildfire_risk_communities`,
|
|
248
|
+
`elevation`, `geometry`.
|
|
249
|
+
|
|
250
|
+
**Returns:** `FederalLandReport`. `report_scope` is `"containing_section"`
|
|
251
|
+
when the tract is finer than the stored grid (the section is named by
|
|
252
|
+
`report_section`); a layer the state has no data for is listed in
|
|
253
|
+
`meta.unavailable` with reason `no_state_coverage`.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
### `client.texasReport(legalLocation, options?)`
|
|
258
|
+
|
|
259
|
+
Texas abstract report for a TXSS legal description — GLO state leases and
|
|
260
|
+
pooled units, PSF lands, state-agency lands, upland leases, RRC wells and T-4
|
|
261
|
+
pipelines, pending permits, coastal erosion, federal overlays (flood zones,
|
|
262
|
+
wetlands, firesheds, soils, orphaned wells, critical habitat, wildfire risk),
|
|
263
|
+
elevation, and RRC lease production.
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
const report = await client.texasReport("A-175 Reeves County");
|
|
267
|
+
console.log(report.active_wells?.rows[0]?.api_number);
|
|
268
|
+
console.log(report.production?.summary.total_cum_boe);
|
|
269
|
+
|
|
270
|
+
const slim = await client.texasReport("A-175 Reeves County", {
|
|
271
|
+
include: ["state_leases", "production"]
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Options:** `include` — any of `state_leases`, `state_units`, `psf_lands`,
|
|
276
|
+
`state_agency_lands`, `upland_leases`, `active_wells`, `pipelines`,
|
|
277
|
+
`pending_permits`, `coastal_erosion`, `flood_zones`, `wetlands`, `fireshed`,
|
|
278
|
+
`soils`, `orphaned_wells`, `critical_habitat`, `wildfire_risk_communities`,
|
|
279
|
+
`elevation`, `production`, `geometry`.
|
|
280
|
+
|
|
281
|
+
**Returns:** `TexasReport`
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### `client.texasProduction(options)`
|
|
286
|
+
|
|
287
|
+
RRC lease production for a Texas abstract — per-lease lifetime totals,
|
|
288
|
+
trailing-12-month volumes, and the 60-month monthly series. Key by a legal
|
|
289
|
+
description OR the registry ids.
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
const byLocation = await client.texasProduction({ legalLocation: "A-175 Reeves County" });
|
|
293
|
+
const byKeys = await client.texasProduction({ countyFips: "48389", abstractNo: "175" });
|
|
294
|
+
console.log(byKeys.summary.total_cum_boe);
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Options:** `{ legalLocation }` or `{ countyFips, abstractNo, blockNo? }`
|
|
298
|
+
|
|
299
|
+
**Returns:** `TexasProduction`. Production is reported by RRC at the lease
|
|
300
|
+
level — rows are the leases whose wells fall on the abstract, never
|
|
301
|
+
sub-allocated to the tract.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### `client.texasWell(api)`
|
|
306
|
+
|
|
307
|
+
Per-well allocated production for a Texas well by API number (API-8 or
|
|
308
|
+
API-14) — summary scalars for every lease edge, the monthly series (when
|
|
309
|
+
provisioned), and an Arps decline fit.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
const well = await client.texasWell("42-389-32345");
|
|
313
|
+
console.log(well.units[0]?.cum_boe);
|
|
314
|
+
if (well.decline.available) console.log(well.decline.value?.di);
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Returns:** `TexasWell`. Volumes are allocated estimates — RRC reports
|
|
318
|
+
production by lease, never by well.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
197
322
|
## Error Handling
|
|
198
323
|
|
|
199
324
|
All errors extend `TownshipError`:
|
|
@@ -224,6 +349,40 @@ try {
|
|
|
224
349
|
}
|
|
225
350
|
```
|
|
226
351
|
|
|
352
|
+
Errors from the Energy, Federal Land, and Texas APIs also carry a
|
|
353
|
+
machine-readable `code` (e.g. `invalid_parameter`, `plss_not_supported`,
|
|
354
|
+
`ambiguous_location`, `not_found`, `rate_limit_exceeded`); it is `null` for
|
|
355
|
+
endpoints that do not send one:
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
try {
|
|
359
|
+
await client.texasReport("NW 25 24N 1E 6th Meridian");
|
|
360
|
+
} catch (error) {
|
|
361
|
+
if (error instanceof ValidationError && error.code === "plss_not_supported") {
|
|
362
|
+
// Use federalLandReport or energyReport for PLSS descriptions
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## What's new in v2.0.0
|
|
368
|
+
|
|
369
|
+
v2.0.0 adds the parcel-report APIs:
|
|
370
|
+
|
|
371
|
+
- `client.energyReport(legalLocation, { include? })` — Energy API report
|
|
372
|
+
- `client.federalLandReport(legalLocation, { include? })` — Federal Land API report
|
|
373
|
+
- `client.texasReport(legalLocation, { include? })` — Texas abstract report
|
|
374
|
+
- `client.texasProduction({ legalLocation } | { countyFips, abstractNo, blockNo? })` — RRC lease production
|
|
375
|
+
- `client.texasWell(api)` — per-well allocated production + Arps decline fit
|
|
376
|
+
|
|
377
|
+
Breaking changes:
|
|
378
|
+
|
|
379
|
+
- Error classes gained a third constructor parameter and a readonly `code`
|
|
380
|
+
property (`string | null`). If you subclass or construct SDK errors
|
|
381
|
+
directly, update the constructor calls; `instanceof` checks are unaffected.
|
|
382
|
+
- Error bodies of the form `{"error": {"code", "message"}}` (Energy, Federal
|
|
383
|
+
Land, and Texas APIs) are now parsed into `error.message`/`error.code`.
|
|
384
|
+
Legacy `{"error": "..."}` / `{"message": "..."}` bodies parse as before.
|
|
385
|
+
|
|
227
386
|
## Format Examples
|
|
228
387
|
|
|
229
388
|
### PLSS (30 states)
|
package/dist/index.cjs
CHANGED
|
@@ -32,39 +32,40 @@ module.exports = __toCommonJS(index_exports);
|
|
|
32
32
|
|
|
33
33
|
// src/errors.ts
|
|
34
34
|
var TownshipError = class extends Error {
|
|
35
|
-
constructor(message, statusCode = null) {
|
|
35
|
+
constructor(message, statusCode = null, code = null) {
|
|
36
36
|
super(message);
|
|
37
37
|
this.statusCode = statusCode;
|
|
38
|
+
this.code = code;
|
|
38
39
|
this.name = "TownshipError";
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
42
|
var AuthenticationError = class extends TownshipError {
|
|
42
|
-
constructor(message = "Invalid or missing API key") {
|
|
43
|
-
super(message, 401);
|
|
43
|
+
constructor(message = "Invalid or missing API key", code = null) {
|
|
44
|
+
super(message, 401, code);
|
|
44
45
|
this.name = "AuthenticationError";
|
|
45
46
|
}
|
|
46
47
|
};
|
|
47
48
|
var NotFoundError = class extends TownshipError {
|
|
48
|
-
constructor(message = "Location not found") {
|
|
49
|
-
super(message, 404);
|
|
49
|
+
constructor(message = "Location not found", code = null) {
|
|
50
|
+
super(message, 404, code);
|
|
50
51
|
this.name = "NotFoundError";
|
|
51
52
|
}
|
|
52
53
|
};
|
|
53
54
|
var RateLimitError = class extends TownshipError {
|
|
54
|
-
constructor(message = "Rate limit exceeded. Please slow down your requests.") {
|
|
55
|
-
super(message, 429);
|
|
55
|
+
constructor(message = "Rate limit exceeded. Please slow down your requests.", code = null) {
|
|
56
|
+
super(message, 429, code);
|
|
56
57
|
this.name = "RateLimitError";
|
|
57
58
|
}
|
|
58
59
|
};
|
|
59
60
|
var ValidationError = class extends TownshipError {
|
|
60
|
-
constructor(message = "Invalid request") {
|
|
61
|
-
super(message, 400);
|
|
61
|
+
constructor(message = "Invalid request", code = null) {
|
|
62
|
+
super(message, 400, code);
|
|
62
63
|
this.name = "ValidationError";
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
var PayloadTooLargeError = class extends TownshipError {
|
|
66
|
-
constructor(message = "Batch payload exceeds the maximum of 100 records per request") {
|
|
67
|
-
super(message, 413);
|
|
67
|
+
constructor(message = "Batch payload exceeds the maximum of 100 records per request", code = null) {
|
|
68
|
+
super(message, 413, code);
|
|
68
69
|
this.name = "PayloadTooLargeError";
|
|
69
70
|
}
|
|
70
71
|
};
|
|
@@ -116,7 +117,7 @@ var TownshipClient = class {
|
|
|
116
117
|
...init,
|
|
117
118
|
headers: {
|
|
118
119
|
"X-API-Key": this.apiKey,
|
|
119
|
-
"User-Agent": "townshipamerica-js/
|
|
120
|
+
"User-Agent": "townshipamerica-js/2.0.0",
|
|
120
121
|
...init?.headers ?? {}
|
|
121
122
|
},
|
|
122
123
|
signal: controller.signal
|
|
@@ -137,19 +138,25 @@ var TownshipClient = class {
|
|
|
137
138
|
}
|
|
138
139
|
async handleError(response) {
|
|
139
140
|
let message;
|
|
141
|
+
let code = null;
|
|
140
142
|
try {
|
|
141
143
|
const body = await response.json();
|
|
142
|
-
|
|
144
|
+
if (body.error && typeof body.error === "object") {
|
|
145
|
+
message = body.error.message ?? response.statusText;
|
|
146
|
+
code = body.error.code ?? null;
|
|
147
|
+
} else {
|
|
148
|
+
message = (typeof body.error === "string" ? body.error : void 0) ?? body.message ?? response.statusText;
|
|
149
|
+
}
|
|
143
150
|
} catch {
|
|
144
151
|
message = response.statusText;
|
|
145
152
|
}
|
|
146
153
|
const status = response.status;
|
|
147
|
-
if (status === 400) throw new ValidationError(message);
|
|
148
|
-
if (status === 401) throw new AuthenticationError(message);
|
|
149
|
-
if (status === 404) throw new NotFoundError(message);
|
|
150
|
-
if (status === 413) throw new PayloadTooLargeError(message);
|
|
151
|
-
if (status === 429) throw new RateLimitError(message);
|
|
152
|
-
throw new TownshipError(message, status);
|
|
154
|
+
if (status === 400) throw new ValidationError(message, code);
|
|
155
|
+
if (status === 401) throw new AuthenticationError(message, code);
|
|
156
|
+
if (status === 404) throw new NotFoundError(message, code);
|
|
157
|
+
if (status === 413) throw new PayloadTooLargeError(message, code);
|
|
158
|
+
if (status === 429) throw new RateLimitError(message, code);
|
|
159
|
+
throw new TownshipError(message, status, code);
|
|
153
160
|
}
|
|
154
161
|
// --- Search ---
|
|
155
162
|
/**
|
|
@@ -326,6 +333,137 @@ var TownshipClient = class {
|
|
|
326
333
|
}
|
|
327
334
|
return data;
|
|
328
335
|
}
|
|
336
|
+
// --- Energy API ---
|
|
337
|
+
/**
|
|
338
|
+
* Get the energy parcel report for a PLSS section. Covers state-regulator
|
|
339
|
+
* wells, operators, federal leases, county royalties, orphaned wells,
|
|
340
|
+
* pipelines, FracFocus disclosures, and development constraints.
|
|
341
|
+
*
|
|
342
|
+
* @param legalLocation - A PLSS legal description, e.g. "NW 25 24N 1E 6th Meridian"
|
|
343
|
+
* @param options - Optional section projection (`include`)
|
|
344
|
+
* @returns The energy report
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* const report = await client.energyReport('25 24N 1E 6th Meridian')
|
|
349
|
+
* console.log(report.summary.wells_in_section)
|
|
350
|
+
* console.log(report.wells?.in_section.rows[0]?.api_number)
|
|
351
|
+
*
|
|
352
|
+
* // Only the sections you need — the rest are never queried
|
|
353
|
+
* const slim = await client.energyReport('25 24N 1E 6th Meridian', {
|
|
354
|
+
* include: ['wells', 'pipelines']
|
|
355
|
+
* })
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
async energyReport(legalLocation, options) {
|
|
359
|
+
const params = new URLSearchParams({ legal_location: legalLocation });
|
|
360
|
+
if (options?.include?.length) params.set("include", options.include.join(","));
|
|
361
|
+
return this.request(`/energy/report?${params}`);
|
|
362
|
+
}
|
|
363
|
+
// --- Federal Land API ---
|
|
364
|
+
/**
|
|
365
|
+
* Get the federal-land parcel report for a PLSS tract. Covers surface
|
|
366
|
+
* management, BLM leases and rights-of-way, flood zones, mining claims,
|
|
367
|
+
* wetlands, firesheds, soils, crop history, orphaned wells, critical
|
|
368
|
+
* habitat, public access, wildfire risk, and elevation.
|
|
369
|
+
*
|
|
370
|
+
* @param legalLocation - A PLSS legal description, e.g. "NW 25 24N 1E 6th Meridian"
|
|
371
|
+
* @param options - Optional section projection (`include`)
|
|
372
|
+
* @returns The federal-land report
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```ts
|
|
376
|
+
* const report = await client.federalLandReport('NW 25 24N 1E 6th Meridian')
|
|
377
|
+
* console.log(report.surface_management?.rows[0]?.agency)
|
|
378
|
+
*
|
|
379
|
+
* // Only the sections you need — the pruned layers' queries never run
|
|
380
|
+
* const slim = await client.federalLandReport('NW 25 24N 1E 6th Meridian', {
|
|
381
|
+
* include: ['og_leases', 'flood_zones']
|
|
382
|
+
* })
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
async federalLandReport(legalLocation, options) {
|
|
386
|
+
const params = new URLSearchParams({ legal_location: legalLocation });
|
|
387
|
+
if (options?.include?.length) params.set("include", options.include.join(","));
|
|
388
|
+
return this.request(`/federal-land/report?${params}`);
|
|
389
|
+
}
|
|
390
|
+
// --- Texas API ---
|
|
391
|
+
/**
|
|
392
|
+
* Get the Texas abstract report for a TXSS legal description. Covers GLO
|
|
393
|
+
* state leases and units, PSF lands, RRC wells and pipelines, pending
|
|
394
|
+
* permits, coastal erosion, federal overlays, and RRC lease production.
|
|
395
|
+
*
|
|
396
|
+
* @param legalLocation - A Texas legal description, e.g. "A-175 Reeves County"
|
|
397
|
+
* @param options - Optional section projection (`include`)
|
|
398
|
+
* @returns The Texas report
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```ts
|
|
402
|
+
* const report = await client.texasReport('A-175 Reeves County')
|
|
403
|
+
* console.log(report.active_wells?.rows[0]?.api_number)
|
|
404
|
+
* console.log(report.production?.summary.total_cum_boe)
|
|
405
|
+
*
|
|
406
|
+
* // Only the sections you need — the rest are never queried
|
|
407
|
+
* const slim = await client.texasReport('A-175 Reeves County', {
|
|
408
|
+
* include: ['state_leases', 'production']
|
|
409
|
+
* })
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
async texasReport(legalLocation, options) {
|
|
413
|
+
const params = new URLSearchParams({ legal_location: legalLocation });
|
|
414
|
+
if (options?.include?.length) params.set("include", options.include.join(","));
|
|
415
|
+
return this.request(`/texas/report?${params}`);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get RRC lease production for a Texas abstract — per-lease lifetime
|
|
419
|
+
* totals, trailing-12-month volumes, and the 60-month monthly series.
|
|
420
|
+
* Production is reported by RRC at the LEASE level: rows are the leases
|
|
421
|
+
* whose wells fall on the abstract, never sub-allocated to the tract.
|
|
422
|
+
*
|
|
423
|
+
* @param options - Either `{legalLocation}` or `{countyFips, abstractNo, blockNo?}`
|
|
424
|
+
* @returns The abstract production rollup
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* const byLocation = await client.texasProduction({ legalLocation: 'A-175 Reeves County' })
|
|
429
|
+
* const byKeys = await client.texasProduction({ countyFips: '48389', abstractNo: '175' })
|
|
430
|
+
* console.log(byKeys.summary.total_cum_boe)
|
|
431
|
+
* ```
|
|
432
|
+
*/
|
|
433
|
+
async texasProduction(options) {
|
|
434
|
+
const params = new URLSearchParams();
|
|
435
|
+
if (options.legalLocation != null) {
|
|
436
|
+
params.set("legal_location", options.legalLocation);
|
|
437
|
+
} else if (options.countyFips != null && options.abstractNo != null) {
|
|
438
|
+
params.set("county_fips", options.countyFips);
|
|
439
|
+
params.set("abstract_no", options.abstractNo);
|
|
440
|
+
if (options.blockNo != null) params.set("block_no", options.blockNo);
|
|
441
|
+
} else {
|
|
442
|
+
throw new TownshipError(
|
|
443
|
+
"texasProduction requires either legalLocation or countyFips + abstractNo"
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
return this.request(`/texas/production?${params}`);
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Get per-well allocated production for a Texas well by API number —
|
|
450
|
+
* summary scalars for every lease edge, the monthly series (when
|
|
451
|
+
* provisioned), and an Arps decline fit. Volumes are allocated estimates:
|
|
452
|
+
* RRC reports production by lease, never by well.
|
|
453
|
+
*
|
|
454
|
+
* @param api - API-8 or API-14 number (e.g. "42-389-32345" or "42389323450000")
|
|
455
|
+
* @returns The well's units, series, and decline analysis
|
|
456
|
+
*
|
|
457
|
+
* @example
|
|
458
|
+
* ```ts
|
|
459
|
+
* const well = await client.texasWell('42-389-32345')
|
|
460
|
+
* console.log(well.units[0]?.cum_boe)
|
|
461
|
+
* console.log(well.decline.available && well.decline.value?.di)
|
|
462
|
+
* ```
|
|
463
|
+
*/
|
|
464
|
+
async texasWell(api) {
|
|
465
|
+
return this.request(`/texas/wells/${encodeURIComponent(api)}`);
|
|
466
|
+
}
|
|
329
467
|
};
|
|
330
468
|
// Annotate the CommonJS export names for ESM import in node:
|
|
331
469
|
0 && (module.exports = {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { TownshipClient } from \"./client.js\";\nexport {\n TownshipError,\n AuthenticationError,\n NotFoundError,\n RateLimitError,\n ValidationError,\n PayloadTooLargeError\n} from \"./errors.js\";\nexport type {\n TownshipClientOptions,\n GeoJSONPoint,\n GeoJSONPolygon,\n GeoJSONMultiPolygon,\n GeoJSONBoundary,\n GeoJSONFeature,\n GeoJSONFeatureCollection,\n FeatureProperties,\n Unit,\n SurveySystem,\n SearchResult,\n ReverseOptions,\n AutocompleteOptions,\n BatchSearchOptions,\n BatchReverseOptions\n} from \"./types.js\";\n","/**\n * Base error class for all Township SDK errors.\n */\nexport class TownshipError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number | null = null\n ) {\n super(message);\n this.name = \"TownshipError\";\n }\n}\n\n/**\n * Thrown when the API key is missing or invalid (HTTP 401).\n */\nexport class AuthenticationError extends TownshipError {\n constructor(message = \"Invalid or missing API key\") {\n super(message, 401);\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Thrown when no result is found for the given input.\n */\nexport class NotFoundError extends TownshipError {\n constructor(message = \"Location not found\") {\n super(message, 404);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Thrown when the API rate limit is exceeded (HTTP 429).\n */\nexport class RateLimitError extends TownshipError {\n constructor(message = \"Rate limit exceeded. Please slow down your requests.\") {\n super(message, 429);\n this.name = \"RateLimitError\";\n }\n}\n\n/**\n * Thrown when the request is malformed (HTTP 400).\n */\nexport class ValidationError extends TownshipError {\n constructor(message = \"Invalid request\") {\n super(message, 400);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Thrown when the batch payload exceeds the maximum size (HTTP 413).\n */\nexport class PayloadTooLargeError extends TownshipError {\n constructor(message = \"Batch payload exceeds the maximum of 100 records per request\") {\n super(message, 413);\n this.name = \"PayloadTooLargeError\";\n }\n}\n","import {\n AuthenticationError,\n NotFoundError,\n PayloadTooLargeError,\n RateLimitError,\n TownshipError,\n ValidationError\n} from \"./errors.js\";\nimport type {\n AutocompleteOptions,\n BatchReverseOptions,\n BatchSearchOptions,\n GeoJSONBoundary,\n GeoJSONFeatureCollection,\n ReverseOptions,\n SearchResult,\n TownshipClientOptions\n} from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://developer.townshipamerica.com\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst MAX_BATCH_SIZE = 100;\n\nfunction toSearchResult(fc: GeoJSONFeatureCollection): SearchResult {\n const centroid = fc.features.find((f) => f.properties.shape === \"centroid\");\n const grid = fc.features.find((f) => f.properties.shape === \"grid\");\n\n const props = centroid?.properties ?? grid?.properties;\n if (!props) {\n throw new TownshipError(\"Unexpected API response: no features returned\");\n }\n\n const [lng, lat] = centroid ? (centroid.geometry.coordinates as [number, number]) : [0, 0];\n\n return {\n legalLocation: props.legal_location,\n latitude: lat,\n longitude: lng,\n state: props.state,\n county: props.county,\n unit: props.unit,\n surveySystem: props.survey_system,\n alternateLegalLocation: props.alternate_legal_location,\n boundary: grid ? (grid.geometry as GeoJSONBoundary) : null,\n raw: fc\n };\n}\n\nexport class TownshipClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n constructor(options: TownshipClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n\n if (!this.apiKey) {\n throw new TownshipError(\"apiKey is required\");\n }\n }\n\n // --- Internal ---\n\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...init,\n headers: {\n \"X-API-Key\": this.apiKey,\n \"User-Agent\": \"townshipamerica-js/1.0.0\",\n ...(init?.headers ?? {})\n },\n signal: controller.signal\n });\n\n if (!response.ok) {\n await this.handleError(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof TownshipError) throw error;\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new TownshipError(\"Request timed out\");\n }\n throw new TownshipError(error instanceof Error ? error.message : \"Unknown error\");\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async handleError(response: Response): Promise<never> {\n let message: string;\n try {\n const body = (await response.json()) as Record<string, unknown>;\n message = (body.error ?? body.message ?? response.statusText) as string;\n } catch {\n message = response.statusText;\n }\n\n const status = response.status;\n if (status === 400) throw new ValidationError(message);\n if (status === 401) throw new AuthenticationError(message);\n if (status === 404) throw new NotFoundError(message);\n if (status === 413) throw new PayloadTooLargeError(message);\n if (status === 429) throw new RateLimitError(message);\n throw new TownshipError(message, status);\n }\n\n // --- Search ---\n\n /**\n * Convert a PLSS or Texas TXSS legal land description to GPS coordinates.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\" or \"A-175 Reeves County\"\n * @returns A SearchResult with coordinates, boundary, and metadata.\n * @throws {ValidationError} If the location string is invalid.\n * @throws {NotFoundError} If no match is found.\n */\n async search(legalLocation: string): Promise<SearchResult> {\n const params = new URLSearchParams({ location: legalLocation });\n const data = await this.request<GeoJSONFeatureCollection | Record<string, never>>(\n `/search/legal-location?${params}`\n );\n\n if (!(\"features\" in data) || !data.features?.length) {\n throw new NotFoundError(`No results found for \"${legalLocation}\"`);\n }\n\n return toSearchResult(data as GeoJSONFeatureCollection);\n }\n\n /**\n * Find the legal land description at the given GPS coordinates (PLSS or Texas TXSS).\n *\n * @param longitude - Longitude (x) coordinate.\n * @param latitude - Latitude (y) coordinate.\n * @param options - Optional PLSS unit filter (ignored for TXSS results).\n * @returns A SearchResult or array of SearchResults (when unit is 'all').\n */\n async reverse(\n longitude: number,\n latitude: number,\n options?: ReverseOptions\n ): Promise<SearchResult | SearchResult[]> {\n const params = new URLSearchParams({\n location: `${longitude},${latitude}`\n });\n if (options?.unit) {\n params.set(\"unit\", options.unit);\n }\n\n const data = await this.request<GeoJSONFeatureCollection | Record<string, never>>(\n `/search/coordinates?${params}`\n );\n\n if (!(\"features\" in data) || !data.features?.length) {\n throw new NotFoundError(`No results found for coordinates [${longitude}, ${latitude}]`);\n }\n\n const fc = data as GeoJSONFeatureCollection;\n\n if (options?.unit === \"all\") {\n const groups = new Map<string, typeof fc.features>();\n for (const feature of fc.features) {\n const key = feature.properties.legal_location;\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(feature);\n }\n\n return Array.from(groups.values()).map((features) => {\n return toSearchResult({ type: \"FeatureCollection\", features });\n });\n }\n\n return toSearchResult(fc);\n }\n\n // --- Autocomplete ---\n\n /**\n * Get autocomplete suggestions for a partial PLSS or Texas TXSS description.\n *\n * @param query - Partial search query (minimum 2 characters).\n * @param options - Optional limit (1–10, default 3) and proximity.\n * @returns Raw GeoJSON FeatureCollection with suggestion features.\n */\n async autocomplete(\n query: string,\n options?: AutocompleteOptions\n ): Promise<GeoJSONFeatureCollection> {\n const params = new URLSearchParams({ location: query });\n if (options?.limit != null) {\n params.set(\"limit\", String(options.limit));\n }\n if (options?.proximity) {\n params.set(\"proximity\", `${options.proximity[0]},${options.proximity[1]}`);\n }\n\n return this.request<GeoJSONFeatureCollection>(`/autocomplete/legal-location?${params}`);\n }\n\n // --- Batch ---\n\n /**\n * Convert multiple legal land descriptions to GPS coordinates in one request.\n * Auto-chunks if more than 100 items. Mix PLSS and Texas TXSS inputs freely.\n *\n * @param locations - Array of legal land descriptions.\n * @param options - Optional chunk size.\n * @returns Array of SearchResult or null for each input.\n */\n async batchSearch(\n locations: string[],\n options?: BatchSearchOptions\n ): Promise<(SearchResult | null)[]> {\n const chunkSize = Math.min(options?.chunkSize ?? MAX_BATCH_SIZE, MAX_BATCH_SIZE);\n const results: (SearchResult | null)[] = [];\n\n for (let i = 0; i < locations.length; i += chunkSize) {\n const chunk = locations.slice(i, i + chunkSize);\n const data = await this.request<(GeoJSONFeatureCollection | null)[]>(\n \"/batch/legal-location\",\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(chunk)\n }\n );\n\n for (const fc of data) {\n if (!fc || !fc.features?.length) {\n results.push(null);\n } else {\n results.push(toSearchResult(fc));\n }\n }\n }\n\n return results;\n }\n\n /**\n * Find legal land descriptions for multiple coordinate pairs in one request.\n * Auto-chunks if more than 100 items.\n *\n * @param coordinates - Array of [longitude, latitude] pairs.\n * @param options - Optional PLSS unit filter and chunk size.\n * @returns Array of SearchResult or null for each input.\n */\n async batchReverse(\n coordinates: [number, number][],\n options?: BatchReverseOptions\n ): Promise<(SearchResult | null)[]> {\n const chunkSize = Math.min(options?.chunkSize ?? MAX_BATCH_SIZE, MAX_BATCH_SIZE);\n const results: (SearchResult | null)[] = [];\n\n for (let i = 0; i < coordinates.length; i += chunkSize) {\n const chunk = coordinates.slice(i, i + chunkSize);\n const body: Record<string, unknown> = { coordinates: chunk };\n if (options?.unit) {\n body.unit = options.unit;\n }\n\n const data = await this.request<\n (GeoJSONFeatureCollection | null)[] | GeoJSONFeatureCollection\n >(\"/batch/coordinates\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body)\n });\n\n if (Array.isArray(data)) {\n for (const fc of data) {\n if (!fc || !fc.features?.length) {\n results.push(null);\n } else {\n results.push(toSearchResult(fc));\n }\n }\n } else if (data && \"features\" in data) {\n // unit=all returns a single FeatureCollection — split by legal_location\n const groups = new Map<string, typeof data.features>();\n for (const feature of data.features) {\n const key = JSON.stringify(feature.properties.search_term);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(feature);\n }\n for (const features of groups.values()) {\n results.push(toSearchResult({ type: \"FeatureCollection\", features }));\n }\n }\n }\n\n return results;\n }\n\n // --- Convenience ---\n\n /**\n * Get the boundary polygon for a legal land description.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\"\n * @returns The boundary GeoJSON Polygon, or null if not found.\n */\n async boundary(legalLocation: string): Promise<GeoJSONBoundary | null> {\n const result = await this.search(legalLocation);\n return result.boundary;\n }\n\n /**\n * Get the raw GeoJSON FeatureCollection for a legal land description.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\"\n * @returns The raw GeoJSON FeatureCollection from the API.\n */\n async raw(legalLocation: string): Promise<GeoJSONFeatureCollection> {\n const params = new URLSearchParams({ location: legalLocation });\n const data = await this.request<GeoJSONFeatureCollection | Record<string, never>>(\n `/search/legal-location?${params}`\n );\n\n if (!(\"features\" in data)) {\n return { type: \"FeatureCollection\", features: [] };\n }\n\n return data as GeoJSONFeatureCollection;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { TownshipClient } from \"./client.js\";\nexport {\n TownshipError,\n AuthenticationError,\n NotFoundError,\n RateLimitError,\n ValidationError,\n PayloadTooLargeError\n} from \"./errors.js\";\nexport type {\n TownshipClientOptions,\n GeoJSONPoint,\n GeoJSONPolygon,\n GeoJSONMultiPolygon,\n GeoJSONBoundary,\n GeoJSONFeature,\n GeoJSONFeatureCollection,\n FeatureProperties,\n Unit,\n SurveySystem,\n SearchResult,\n ReverseOptions,\n AutocompleteOptions,\n BatchSearchOptions,\n BatchReverseOptions,\n // Shared report types\n LatLng,\n EntityRef,\n SectionEnvelope,\n UnavailableSection,\n SectionSource,\n ReportMeta,\n ReportParcel,\n // Energy API\n EnergyReportSection,\n EnergyReportOptions,\n EnergyWellRow,\n EnergyOrphanedWellRow,\n EnergyLeaseRow,\n EnergyOperatorRow,\n EnergyRoyaltyItem,\n EnergyRoyalties,\n EnergyPipelineRow,\n FracFocusRow,\n EnergySplitEstateSide,\n EnergySplitEstate,\n EnergySageGrouseHabitat,\n EnergySageGrouse,\n EnergyRenewableSiting,\n EnergyConstraints,\n EnergySummary,\n EnergyWells,\n EnergyReport,\n // Federal Land API\n FederalLandReportSection,\n FederalLandReportOptions,\n SurfaceManagementRow,\n FederalLeaseRow,\n RightOfWayRow,\n FloodZoneRow,\n MiningClaimRow,\n WetlandRow,\n FireshedRow,\n SoilRow,\n OrphanedWellRow,\n CriticalHabitatRow,\n PublicAccessRow,\n WildfireRiskRow,\n CropHistory,\n Elevation,\n FederalLandReport,\n // Texas API\n TexasReportSection,\n TexasReportOptions,\n TexasStateLeaseRow,\n TexasStateUnitRow,\n TexasPsfLandRow,\n TexasStateAgencyLandRow,\n TexasUplandLeaseRow,\n TexasActiveWellRow,\n TexasPipelineRow,\n TexasPendingPermitRow,\n TexasCoastalErosionRow,\n TexasMonthlyVolume,\n TexasProductionLease,\n TexasAbstractRef,\n TexasProductionSummary,\n TexasProductionBlock,\n TexasProduction,\n TexasReport,\n TexasProductionOptions,\n TexasWellLocation,\n TexasWellUnit,\n TexasWellSeriesPoint,\n TexasDeclineFit,\n TexasDecline,\n TexasDeclineCurvePoint,\n TexasWellSeriesUnit,\n TexasWell\n} from \"./types.js\";\n","/**\n * Base error class for all Township SDK errors.\n *\n * `code` carries the machine-readable error code the Energy, Federal Land,\n * and Texas APIs return in v1 error bodies (`{\"error\": {\"code\", \"message\"}}`),\n * e.g. `invalid_parameter`, `missing_parameter`, `plss_not_supported`,\n * `ambiguous_location`, `not_found`, `rate_limit_exceeded`. It is null for\n * endpoints that do not send one.\n */\nexport class TownshipError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number | null = null,\n public readonly code: string | null = null\n ) {\n super(message);\n this.name = \"TownshipError\";\n }\n}\n\n/**\n * Thrown when the API key is missing or invalid (HTTP 401).\n */\nexport class AuthenticationError extends TownshipError {\n constructor(message = \"Invalid or missing API key\", code: string | null = null) {\n super(message, 401, code);\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Thrown when no result is found for the given input.\n */\nexport class NotFoundError extends TownshipError {\n constructor(message = \"Location not found\", code: string | null = null) {\n super(message, 404, code);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Thrown when the API rate limit is exceeded (HTTP 429).\n */\nexport class RateLimitError extends TownshipError {\n constructor(\n message = \"Rate limit exceeded. Please slow down your requests.\",\n code: string | null = null\n ) {\n super(message, 429, code);\n this.name = \"RateLimitError\";\n }\n}\n\n/**\n * Thrown when the request is malformed (HTTP 400).\n */\nexport class ValidationError extends TownshipError {\n constructor(message = \"Invalid request\", code: string | null = null) {\n super(message, 400, code);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Thrown when the batch payload exceeds the maximum size (HTTP 413).\n */\nexport class PayloadTooLargeError extends TownshipError {\n constructor(\n message = \"Batch payload exceeds the maximum of 100 records per request\",\n code: string | null = null\n ) {\n super(message, 413, code);\n this.name = \"PayloadTooLargeError\";\n }\n}\n","import {\n AuthenticationError,\n NotFoundError,\n PayloadTooLargeError,\n RateLimitError,\n TownshipError,\n ValidationError\n} from \"./errors.js\";\nimport type {\n AutocompleteOptions,\n BatchReverseOptions,\n BatchSearchOptions,\n EnergyReport,\n EnergyReportOptions,\n FederalLandReport,\n FederalLandReportOptions,\n GeoJSONBoundary,\n GeoJSONFeatureCollection,\n ReverseOptions,\n SearchResult,\n TexasProduction,\n TexasProductionOptions,\n TexasReport,\n TexasReportOptions,\n TexasWell,\n TownshipClientOptions\n} from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://developer.townshipamerica.com\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst MAX_BATCH_SIZE = 100;\n\nfunction toSearchResult(fc: GeoJSONFeatureCollection): SearchResult {\n const centroid = fc.features.find((f) => f.properties.shape === \"centroid\");\n const grid = fc.features.find((f) => f.properties.shape === \"grid\");\n\n const props = centroid?.properties ?? grid?.properties;\n if (!props) {\n throw new TownshipError(\"Unexpected API response: no features returned\");\n }\n\n const [lng, lat] = centroid ? (centroid.geometry.coordinates as [number, number]) : [0, 0];\n\n return {\n legalLocation: props.legal_location,\n latitude: lat,\n longitude: lng,\n state: props.state,\n county: props.county,\n unit: props.unit,\n surveySystem: props.survey_system,\n alternateLegalLocation: props.alternate_legal_location,\n boundary: grid ? (grid.geometry as GeoJSONBoundary) : null,\n raw: fc\n };\n}\n\nexport class TownshipClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n constructor(options: TownshipClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n\n if (!this.apiKey) {\n throw new TownshipError(\"apiKey is required\");\n }\n }\n\n // --- Internal ---\n\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...init,\n headers: {\n \"X-API-Key\": this.apiKey,\n \"User-Agent\": \"townshipamerica-js/2.0.0\",\n ...(init?.headers ?? {})\n },\n signal: controller.signal\n });\n\n if (!response.ok) {\n await this.handleError(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof TownshipError) throw error;\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new TownshipError(\"Request timed out\");\n }\n throw new TownshipError(error instanceof Error ? error.message : \"Unknown error\");\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async handleError(response: Response): Promise<never> {\n let message: string;\n let code: string | null = null;\n try {\n const body = (await response.json()) as {\n error?: { code?: string; message?: string } | string;\n message?: string;\n };\n // Energy/Federal Land/Texas v1 error bodies are {\"error\": {\"code\", \"message\"}}\n if (body.error && typeof body.error === \"object\") {\n message = body.error.message ?? response.statusText;\n code = body.error.code ?? null;\n } else {\n message =\n (typeof body.error === \"string\" ? body.error : undefined) ??\n body.message ??\n response.statusText;\n }\n } catch {\n message = response.statusText;\n }\n\n const status = response.status;\n if (status === 400) throw new ValidationError(message, code);\n if (status === 401) throw new AuthenticationError(message, code);\n if (status === 404) throw new NotFoundError(message, code);\n if (status === 413) throw new PayloadTooLargeError(message, code);\n if (status === 429) throw new RateLimitError(message, code);\n throw new TownshipError(message, status, code);\n }\n\n // --- Search ---\n\n /**\n * Convert a PLSS or Texas TXSS legal land description to GPS coordinates.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\" or \"A-175 Reeves County\"\n * @returns A SearchResult with coordinates, boundary, and metadata.\n * @throws {ValidationError} If the location string is invalid.\n * @throws {NotFoundError} If no match is found.\n */\n async search(legalLocation: string): Promise<SearchResult> {\n const params = new URLSearchParams({ location: legalLocation });\n const data = await this.request<GeoJSONFeatureCollection | Record<string, never>>(\n `/search/legal-location?${params}`\n );\n\n if (!(\"features\" in data) || !data.features?.length) {\n throw new NotFoundError(`No results found for \"${legalLocation}\"`);\n }\n\n return toSearchResult(data as GeoJSONFeatureCollection);\n }\n\n /**\n * Find the legal land description at the given GPS coordinates (PLSS or Texas TXSS).\n *\n * @param longitude - Longitude (x) coordinate.\n * @param latitude - Latitude (y) coordinate.\n * @param options - Optional PLSS unit filter (ignored for TXSS results).\n * @returns A SearchResult or array of SearchResults (when unit is 'all').\n */\n async reverse(\n longitude: number,\n latitude: number,\n options?: ReverseOptions\n ): Promise<SearchResult | SearchResult[]> {\n const params = new URLSearchParams({\n location: `${longitude},${latitude}`\n });\n if (options?.unit) {\n params.set(\"unit\", options.unit);\n }\n\n const data = await this.request<GeoJSONFeatureCollection | Record<string, never>>(\n `/search/coordinates?${params}`\n );\n\n if (!(\"features\" in data) || !data.features?.length) {\n throw new NotFoundError(`No results found for coordinates [${longitude}, ${latitude}]`);\n }\n\n const fc = data as GeoJSONFeatureCollection;\n\n if (options?.unit === \"all\") {\n const groups = new Map<string, typeof fc.features>();\n for (const feature of fc.features) {\n const key = feature.properties.legal_location;\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(feature);\n }\n\n return Array.from(groups.values()).map((features) => {\n return toSearchResult({ type: \"FeatureCollection\", features });\n });\n }\n\n return toSearchResult(fc);\n }\n\n // --- Autocomplete ---\n\n /**\n * Get autocomplete suggestions for a partial PLSS or Texas TXSS description.\n *\n * @param query - Partial search query (minimum 2 characters).\n * @param options - Optional limit (1–10, default 3) and proximity.\n * @returns Raw GeoJSON FeatureCollection with suggestion features.\n */\n async autocomplete(\n query: string,\n options?: AutocompleteOptions\n ): Promise<GeoJSONFeatureCollection> {\n const params = new URLSearchParams({ location: query });\n if (options?.limit != null) {\n params.set(\"limit\", String(options.limit));\n }\n if (options?.proximity) {\n params.set(\"proximity\", `${options.proximity[0]},${options.proximity[1]}`);\n }\n\n return this.request<GeoJSONFeatureCollection>(`/autocomplete/legal-location?${params}`);\n }\n\n // --- Batch ---\n\n /**\n * Convert multiple legal land descriptions to GPS coordinates in one request.\n * Auto-chunks if more than 100 items. Mix PLSS and Texas TXSS inputs freely.\n *\n * @param locations - Array of legal land descriptions.\n * @param options - Optional chunk size.\n * @returns Array of SearchResult or null for each input.\n */\n async batchSearch(\n locations: string[],\n options?: BatchSearchOptions\n ): Promise<(SearchResult | null)[]> {\n const chunkSize = Math.min(options?.chunkSize ?? MAX_BATCH_SIZE, MAX_BATCH_SIZE);\n const results: (SearchResult | null)[] = [];\n\n for (let i = 0; i < locations.length; i += chunkSize) {\n const chunk = locations.slice(i, i + chunkSize);\n const data = await this.request<(GeoJSONFeatureCollection | null)[]>(\n \"/batch/legal-location\",\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(chunk)\n }\n );\n\n for (const fc of data) {\n if (!fc || !fc.features?.length) {\n results.push(null);\n } else {\n results.push(toSearchResult(fc));\n }\n }\n }\n\n return results;\n }\n\n /**\n * Find legal land descriptions for multiple coordinate pairs in one request.\n * Auto-chunks if more than 100 items.\n *\n * @param coordinates - Array of [longitude, latitude] pairs.\n * @param options - Optional PLSS unit filter and chunk size.\n * @returns Array of SearchResult or null for each input.\n */\n async batchReverse(\n coordinates: [number, number][],\n options?: BatchReverseOptions\n ): Promise<(SearchResult | null)[]> {\n const chunkSize = Math.min(options?.chunkSize ?? MAX_BATCH_SIZE, MAX_BATCH_SIZE);\n const results: (SearchResult | null)[] = [];\n\n for (let i = 0; i < coordinates.length; i += chunkSize) {\n const chunk = coordinates.slice(i, i + chunkSize);\n const body: Record<string, unknown> = { coordinates: chunk };\n if (options?.unit) {\n body.unit = options.unit;\n }\n\n const data = await this.request<\n (GeoJSONFeatureCollection | null)[] | GeoJSONFeatureCollection\n >(\"/batch/coordinates\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body)\n });\n\n if (Array.isArray(data)) {\n for (const fc of data) {\n if (!fc || !fc.features?.length) {\n results.push(null);\n } else {\n results.push(toSearchResult(fc));\n }\n }\n } else if (data && \"features\" in data) {\n // unit=all returns a single FeatureCollection — split by legal_location\n const groups = new Map<string, typeof data.features>();\n for (const feature of data.features) {\n const key = JSON.stringify(feature.properties.search_term);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(feature);\n }\n for (const features of groups.values()) {\n results.push(toSearchResult({ type: \"FeatureCollection\", features }));\n }\n }\n }\n\n return results;\n }\n\n // --- Convenience ---\n\n /**\n * Get the boundary polygon for a legal land description.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\"\n * @returns The boundary GeoJSON Polygon, or null if not found.\n */\n async boundary(legalLocation: string): Promise<GeoJSONBoundary | null> {\n const result = await this.search(legalLocation);\n return result.boundary;\n }\n\n /**\n * Get the raw GeoJSON FeatureCollection for a legal land description.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\"\n * @returns The raw GeoJSON FeatureCollection from the API.\n */\n async raw(legalLocation: string): Promise<GeoJSONFeatureCollection> {\n const params = new URLSearchParams({ location: legalLocation });\n const data = await this.request<GeoJSONFeatureCollection | Record<string, never>>(\n `/search/legal-location?${params}`\n );\n\n if (!(\"features\" in data)) {\n return { type: \"FeatureCollection\", features: [] };\n }\n\n return data as GeoJSONFeatureCollection;\n }\n\n // --- Energy API ---\n\n /**\n * Get the energy parcel report for a PLSS section. Covers state-regulator\n * wells, operators, federal leases, county royalties, orphaned wells,\n * pipelines, FracFocus disclosures, and development constraints.\n *\n * @param legalLocation - A PLSS legal description, e.g. \"NW 25 24N 1E 6th Meridian\"\n * @param options - Optional section projection (`include`)\n * @returns The energy report\n *\n * @example\n * ```ts\n * const report = await client.energyReport('25 24N 1E 6th Meridian')\n * console.log(report.summary.wells_in_section)\n * console.log(report.wells?.in_section.rows[0]?.api_number)\n *\n * // Only the sections you need — the rest are never queried\n * const slim = await client.energyReport('25 24N 1E 6th Meridian', {\n * include: ['wells', 'pipelines']\n * })\n * ```\n */\n async energyReport(legalLocation: string, options?: EnergyReportOptions): Promise<EnergyReport> {\n const params = new URLSearchParams({ legal_location: legalLocation });\n if (options?.include?.length) params.set(\"include\", options.include.join(\",\"));\n return this.request<EnergyReport>(`/energy/report?${params}`);\n }\n\n // --- Federal Land API ---\n\n /**\n * Get the federal-land parcel report for a PLSS tract. Covers surface\n * management, BLM leases and rights-of-way, flood zones, mining claims,\n * wetlands, firesheds, soils, crop history, orphaned wells, critical\n * habitat, public access, wildfire risk, and elevation.\n *\n * @param legalLocation - A PLSS legal description, e.g. \"NW 25 24N 1E 6th Meridian\"\n * @param options - Optional section projection (`include`)\n * @returns The federal-land report\n *\n * @example\n * ```ts\n * const report = await client.federalLandReport('NW 25 24N 1E 6th Meridian')\n * console.log(report.surface_management?.rows[0]?.agency)\n *\n * // Only the sections you need — the pruned layers' queries never run\n * const slim = await client.federalLandReport('NW 25 24N 1E 6th Meridian', {\n * include: ['og_leases', 'flood_zones']\n * })\n * ```\n */\n async federalLandReport(\n legalLocation: string,\n options?: FederalLandReportOptions\n ): Promise<FederalLandReport> {\n const params = new URLSearchParams({ legal_location: legalLocation });\n if (options?.include?.length) params.set(\"include\", options.include.join(\",\"));\n return this.request<FederalLandReport>(`/federal-land/report?${params}`);\n }\n\n // --- Texas API ---\n\n /**\n * Get the Texas abstract report for a TXSS legal description. Covers GLO\n * state leases and units, PSF lands, RRC wells and pipelines, pending\n * permits, coastal erosion, federal overlays, and RRC lease production.\n *\n * @param legalLocation - A Texas legal description, e.g. \"A-175 Reeves County\"\n * @param options - Optional section projection (`include`)\n * @returns The Texas report\n *\n * @example\n * ```ts\n * const report = await client.texasReport('A-175 Reeves County')\n * console.log(report.active_wells?.rows[0]?.api_number)\n * console.log(report.production?.summary.total_cum_boe)\n *\n * // Only the sections you need — the rest are never queried\n * const slim = await client.texasReport('A-175 Reeves County', {\n * include: ['state_leases', 'production']\n * })\n * ```\n */\n async texasReport(legalLocation: string, options?: TexasReportOptions): Promise<TexasReport> {\n const params = new URLSearchParams({ legal_location: legalLocation });\n if (options?.include?.length) params.set(\"include\", options.include.join(\",\"));\n return this.request<TexasReport>(`/texas/report?${params}`);\n }\n\n /**\n * Get RRC lease production for a Texas abstract — per-lease lifetime\n * totals, trailing-12-month volumes, and the 60-month monthly series.\n * Production is reported by RRC at the LEASE level: rows are the leases\n * whose wells fall on the abstract, never sub-allocated to the tract.\n *\n * @param options - Either `{legalLocation}` or `{countyFips, abstractNo, blockNo?}`\n * @returns The abstract production rollup\n *\n * @example\n * ```ts\n * const byLocation = await client.texasProduction({ legalLocation: 'A-175 Reeves County' })\n * const byKeys = await client.texasProduction({ countyFips: '48389', abstractNo: '175' })\n * console.log(byKeys.summary.total_cum_boe)\n * ```\n */\n async texasProduction(options: TexasProductionOptions): Promise<TexasProduction> {\n const params = new URLSearchParams();\n if (options.legalLocation != null) {\n params.set(\"legal_location\", options.legalLocation);\n } else if (options.countyFips != null && options.abstractNo != null) {\n params.set(\"county_fips\", options.countyFips);\n params.set(\"abstract_no\", options.abstractNo);\n if (options.blockNo != null) params.set(\"block_no\", options.blockNo);\n } else {\n throw new TownshipError(\n \"texasProduction requires either legalLocation or countyFips + abstractNo\"\n );\n }\n return this.request<TexasProduction>(`/texas/production?${params}`);\n }\n\n /**\n * Get per-well allocated production for a Texas well by API number —\n * summary scalars for every lease edge, the monthly series (when\n * provisioned), and an Arps decline fit. Volumes are allocated estimates:\n * RRC reports production by lease, never by well.\n *\n * @param api - API-8 or API-14 number (e.g. \"42-389-32345\" or \"42389323450000\")\n * @returns The well's units, series, and decline analysis\n *\n * @example\n * ```ts\n * const well = await client.texasWell('42-389-32345')\n * console.log(well.units[0]?.cum_boe)\n * console.log(well.decline.available && well.decline.value?.di)\n * ```\n */\n async texasWell(api: string): Promise<TexasWell> {\n return this.request<TexasWell>(`/texas/wells/${encodeURIComponent(api)}`);\n }\n}\n"],"mappings":"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","names":[]}
|