townshipamerica 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 +227 -0
- package/dist/index.cjs +340 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +185 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +307 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\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 GeoJSONFeatureCollection,\n GeoJSONPolygon,\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 GeoJSONPolygon) : 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 legal land description to GPS coordinates.\n *\n * @param legalLocation - e.g. \"NW 25 24N 1E 6th Meridian\"\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 PLSS legal land description at the given GPS coordinates.\n *\n * @param longitude - Longitude (x) coordinate.\n * @param latitude - Latitude (y) coordinate.\n * @param options - Optional unit filter.\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 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 PLSS descriptions to GPS coordinates in one request.\n * Auto-chunks if more than 100 items.\n *\n * @param locations - Array of PLSS 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 PLSS 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 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<GeoJSONPolygon | 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":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "townshipamerica",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official TypeScript SDK for the Township America API — convert PLSS legal land descriptions to GPS coordinates and back.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"township",
|
|
35
|
+
"america",
|
|
36
|
+
"plss",
|
|
37
|
+
"gps",
|
|
38
|
+
"coordinates",
|
|
39
|
+
"legal-land-description",
|
|
40
|
+
"public-land-survey-system",
|
|
41
|
+
"geocoding",
|
|
42
|
+
"geospatial",
|
|
43
|
+
"survey",
|
|
44
|
+
"land",
|
|
45
|
+
"section",
|
|
46
|
+
"township-range",
|
|
47
|
+
"meridian"
|
|
48
|
+
],
|
|
49
|
+
"author": "Maps & Apps Inc.",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/mepa1363/townshipamerica-web",
|
|
54
|
+
"directory": "sdk/typescript"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://townshipamerica.com/api",
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=18"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"tsup": "^8.4.0",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"vitest": "^3.2.4"
|
|
64
|
+
}
|
|
65
|
+
}
|