@unmap/elevation 0.15.0 → 0.17.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/dist/index.d.ts +3 -3
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ interface ElevationOptions {
|
|
|
13
13
|
* Retry policy for `429`, `502`, `503` and transport failures. `false` disables it.
|
|
14
14
|
*
|
|
15
15
|
* On by default. `Retry-After` is on a `429` other than `billing_required`, and on a container
|
|
16
|
-
* `503`. A `502` has none: routing
|
|
16
|
+
* `503`. A `502` has none: routing and `/elevation` both use
|
|
17
17
|
* `upstream_error`. With no header the client backs off itself. A wait longer than
|
|
18
18
|
* `maxDelayMs` (10 s) is not slept through; the error carries `retryAfterSeconds` instead.
|
|
19
19
|
* See `RetryPolicy` in `@unmap/core`.
|
|
@@ -37,8 +37,8 @@ declare const MAX_REQUEST_URL_BYTES = 16384;
|
|
|
37
37
|
* An elevation failure.
|
|
38
38
|
*
|
|
39
39
|
* Extends `UnmapError`, so `catch (e) { if (e instanceof UnmapError) }` catches this alongside
|
|
40
|
-
* every other unmap client's errors. `
|
|
41
|
-
*
|
|
40
|
+
* every other unmap client's errors. `status` and `code` carry the HTTP status and the
|
|
41
|
+
* gateway's error code, and `retryAfterSeconds` comes from the `Retry-After` header.
|
|
42
42
|
*/
|
|
43
43
|
declare class ElevationError extends UnmapError {
|
|
44
44
|
constructor(status: number, message: string, code?: string, retryAfterSeconds?: number);
|
package/dist/index.js
CHANGED
|
@@ -37,9 +37,8 @@ var Elevation = class {
|
|
|
37
37
|
}
|
|
38
38
|
const q = new URLSearchParams({ key: this.key });
|
|
39
39
|
if (list.length === 1) {
|
|
40
|
-
const [
|
|
41
|
-
q.set("
|
|
42
|
-
q.set("lat", String(lat));
|
|
40
|
+
const [lng, lat] = list[0];
|
|
41
|
+
q.set("near", `${lng},${lat}`);
|
|
43
42
|
} else {
|
|
44
43
|
q.set("points", list.map(([lng, lat]) => `${lng},${lat}`).join("|"));
|
|
45
44
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { DEFAULT_GATEWAY, UnmapError, fetchWithRetry, parseRetryAfter, type RetryPolicy } from \"@unmap/core\";\n\n/** [longitude, latitude]. Longitude first, everywhere in unmap. Not exported: `@unmap/routing`\n * already exports a `LngLat` of the same shape, and both packages land in `@unmap/sdk`'s star\n * exports, where two same-named exports would be a type error. */\ntype LngLat = [number, number];\n\nexport interface ElevationOptions {\n key: string;\n gateway?: string;\n fetch?: typeof fetch;\n /**\n * Retry policy for `429`, `502`, `503` and transport failures. `false` disables it.\n *\n * On by default. `Retry-After` is on a `429` other than `billing_required`, and on a container\n * `503`. A `502` has none: routing
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { DEFAULT_GATEWAY, UnmapError, fetchWithRetry, parseRetryAfter, type RetryPolicy } from \"@unmap/core\";\n\n/** [longitude, latitude]. Longitude first, everywhere in unmap. Not exported: `@unmap/routing`\n * already exports a `LngLat` of the same shape, and both packages land in `@unmap/sdk`'s star\n * exports, where two same-named exports would be a type error. */\ntype LngLat = [number, number];\n\nexport interface ElevationOptions {\n key: string;\n gateway?: string;\n fetch?: typeof fetch;\n /**\n * Retry policy for `429`, `502`, `503` and transport failures. `false` disables it.\n *\n * On by default. `Retry-After` is on a `429` other than `billing_required`, and on a container\n * `503`. A `502` has none: routing and `/elevation` both use\n * `upstream_error`. With no header the client backs off itself. A wait longer than\n * `maxDelayMs` (10 s) is not slept through; the error carries `retryAfterSeconds` instead.\n * See `RetryPolicy` in `@unmap/core`.\n */\n retry?: RetryPolicy | false;\n}\n\n/** The gateway's own cap. Checked here so an over-long batch fails without spending a call. */\nexport const MAX_ELEVATION_POINTS = 1000;\n\n/**\n * Cloudflare refuses a request URL longer than this at the edge, before the Worker runs.\n *\n * It bites well before `MAX_ELEVATION_POINTS` does. `URLSearchParams` percent-encodes both of\n * the batch separators (`,` becomes `%2C`, `|` becomes `%7C`), so a coordinate costs about six\n * bytes more than it reads, and a thousand six-decimal points is roughly 22 KB of URL. Past the\n * limit the request never reaches the gateway: the caller gets an edge 414 with no error\n * envelope to explain it, which is the least legible failure in the system. So the check is\n * here, against the real encoded URL, and the message says what actually fits.\n */\nexport const MAX_REQUEST_URL_BYTES = 16384;\n\n/** Headroom under the edge limit, so a proxy that appends a parameter cannot tip a request over. */\nconst URL_HEADROOM_BYTES = 256;\n\n/**\n * An elevation failure.\n *\n * Extends `UnmapError`, so `catch (e) { if (e instanceof UnmapError) }` catches this alongside\n * every other unmap client's errors. `status` and `code` carry the HTTP status and the\n * gateway's error code, and `retryAfterSeconds` comes from the `Retry-After` header.\n */\nexport class ElevationError extends UnmapError {\n constructor(status: number, message: string, code?: string, retryAfterSeconds?: number) {\n super(status, message, code, retryAfterSeconds);\n this.name = \"ElevationError\";\n }\n}\n\ninterface ElevationResponse {\n elevations: (number | null)[];\n units: \"m\";\n datum: string;\n resolution: number | null;\n model?: \"mixed\";\n sampling?: { zoom: number; tile_size: number; height_increment_m: number; interpolation: \"bilinear\" };\n}\n\n/**\n * Typed client for the unmap elevation API (gateway `/elevation`).\n *\n * Heights are metres in the active DEM's vertical datum. The global Mapterhorn mosaic mixes\n * terrain/surface models and vertical datums; Canadian rollback uses CGVD2013. `null` means\n * missing data, and the client does not substitute a number for it. See /coverage.json and\n * the HTTP response's metadata for the active release and its limitations.\n */\nexport class Elevation {\n private readonly key: string;\n private readonly base: string;\n private readonly fetchImpl: typeof fetch;\n private readonly retry: RetryPolicy | false | undefined;\n\n constructor(opts: ElevationOptions) {\n this.retry = opts.retry;\n this.key = opts.key;\n this.base = (opts.gateway ?? DEFAULT_GATEWAY).replace(/\\/+$/, \"\");\n // Bound to globalThis for the same reason Router does it: a bare `fetch` stored on an\n // instance is invoked with that instance as its receiver, which browsers reject.\n this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * DEM elevation in metres, one entry per coordinate, in the order asked.\n *\n * Always an array, whether you passed one coordinate or a thousand, so the single and batch\n * cases are the same call:\n *\n * const [metres] = await unmap.elevation.get([-114.0719, 51.0447]);\n */\n async get(\n points: LngLat | LngLat[],\n opts: { signal?: AbortSignal } = {},\n ): Promise<(number | null)[]> {\n const list: LngLat[] = isSingle(points) ? [points] : points;\n if (list.length === 0) return [];\n if (list.length > MAX_ELEVATION_POINTS) {\n throw new ElevationError(400, `elevation.get takes at most ${MAX_ELEVATION_POINTS} coordinates`);\n }\n\n const q = new URLSearchParams({ key: this.key });\n if (list.length === 1) {\n // Safe: the length check above guarantees index 0 exists. Only lng,lat go on the wire, as in\n // the batch branch, so a GeoJSON position with an altitude still works.\n const [lng, lat] = list[0]!;\n q.set(\"near\", `${lng},${lat}`);\n } else {\n q.set(\"points\", list.map(([lng, lat]) => `${lng},${lat}`).join(\"|\"));\n }\n\n const target = `${this.base}/elevation?${q}`;\n const bytes = new TextEncoder().encode(target).length;\n const budget = MAX_REQUEST_URL_BYTES - URL_HEADROOM_BYTES;\n if (bytes > budget) {\n // Scaled from the URL actually built, so the number quoted reflects this caller's own\n // coordinate precision rather than an average of somebody else's.\n const fits = Math.max(1, Math.floor((list.length * budget) / bytes));\n throw new ElevationError(\n 414,\n `elevation.get built a ${bytes} byte request URL; this client sends at most ${budget} ` +\n `bytes, keeping headroom under the edge's ${MAX_REQUEST_URL_BYTES} byte limit. Send ` +\n `at most about ${fits} of these coordinates per request (roughly 700 at six decimal ` +\n `places).`,\n );\n }\n\n const res = await fetchWithRetry(\n this.fetchImpl,\n target,\n { signal: opts.signal, headers: { accept: \"application/json\" } },\n this.retry,\n );\n if (!res.ok) throw await errorFrom(res);\n const body = (await res.json()) as ElevationResponse;\n return body.elevations;\n }\n}\n\n/** `[number, number]` is a coordinate; `[[number, number], ...]` is a list of them. */\nfunction isSingle(points: LngLat | LngLat[]): points is LngLat {\n return typeof points[0] === \"number\";\n}\n\nasync function errorFrom(res: { status: number; headers?: Headers; json(): Promise<unknown> }): Promise<ElevationError> {\n const fallback = `elevation ${res.status}`;\n let body: { error?: unknown; code?: unknown } | undefined;\n try {\n body = (await res.json()) as { error?: unknown; code?: unknown };\n } catch {\n body = undefined;\n }\n const reason = typeof body?.error === \"string\" ? body.error : undefined;\n const code = typeof body?.code === \"string\" ? body.code : undefined;\n const retryAfter = parseRetryAfter(res.headers?.get(\"retry-after\") ?? null) ?? undefined;\n return new ElevationError(res.status, reason ? `${reason} (${fallback})` : fallback, code, retryAfter);\n}\n\n// The shared error type and retry policy, re-exported so a caller who installed only this\n// package can `catch (e) { if (e instanceof UnmapError) }` without adding @unmap/core.\nexport { UnmapError, parseRetryAfter, type RetryPolicy } from \"@unmap/core\";\n"],"mappings":";AAAA,SAAS,iBAAiB,YAAY,gBAAgB,uBAAyC;AAoK/F,SAAS,cAAAA,aAAY,mBAAAC,wBAAyC;AA5IvD,IAAM,uBAAuB;AAY7B,IAAM,wBAAwB;AAGrC,IAAM,qBAAqB;AASpB,IAAM,iBAAN,cAA6B,WAAW;AAAA,EAC7C,YAAY,QAAgB,SAAiB,MAAe,mBAA4B;AACtF,UAAM,QAAQ,SAAS,MAAM,iBAAiB;AAC9C,SAAK,OAAO;AAAA,EACd;AACF;AAmBO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAwB;AAClC,SAAK,QAAQ,KAAK;AAClB,SAAK,MAAM,KAAK;AAChB,SAAK,QAAQ,KAAK,WAAW,iBAAiB,QAAQ,QAAQ,EAAE;AAGhE,SAAK,YAAY,KAAK,SAAS,WAAW,MAAM,KAAK,UAAU;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,IACJ,QACA,OAAiC,CAAC,GACN;AAC5B,UAAM,OAAiB,SAAS,MAAM,IAAI,CAAC,MAAM,IAAI;AACrD,QAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAC/B,QAAI,KAAK,SAAS,sBAAsB;AACtC,YAAM,IAAI,eAAe,KAAK,+BAA+B,oBAAoB,cAAc;AAAA,IACjG;AAEA,UAAM,IAAI,IAAI,gBAAgB,EAAE,KAAK,KAAK,IAAI,CAAC;AAC/C,QAAI,KAAK,WAAW,GAAG;AAGrB,YAAM,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC;AACzB,QAAE,IAAI,QAAQ,GAAG,GAAG,IAAI,GAAG,EAAE;AAAA,IAC/B,OAAO;AACL,QAAE,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,GAAG,IAAI,GAAG,EAAE,EAAE,KAAK,GAAG,CAAC;AAAA,IACrE;AAEA,UAAM,SAAS,GAAG,KAAK,IAAI,cAAc,CAAC;AAC1C,UAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,MAAM,EAAE;AAC/C,UAAM,SAAS,wBAAwB;AACvC,QAAI,QAAQ,QAAQ;AAGlB,YAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,KAAK,SAAS,SAAU,KAAK,CAAC;AACnE,YAAM,IAAI;AAAA,QACR;AAAA,QACA,yBAAyB,KAAK,gDAAgD,MAAM,6CACtC,qBAAqB,mCAChD,IAAI;AAAA,MAEzB;AAAA,IACF;AAEA,UAAM,MAAM,MAAM;AAAA,MAChB,KAAK;AAAA,MACL;AAAA,MACA,EAAE,QAAQ,KAAK,QAAQ,SAAS,EAAE,QAAQ,mBAAmB,EAAE;AAAA,MAC/D,KAAK;AAAA,IACP;AACA,QAAI,CAAC,IAAI,GAAI,OAAM,MAAM,UAAU,GAAG;AACtC,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAGA,SAAS,SAAS,QAA6C;AAC7D,SAAO,OAAO,OAAO,CAAC,MAAM;AAC9B;AAEA,eAAe,UAAU,KAA+F;AACtH,QAAM,WAAW,aAAa,IAAI,MAAM;AACxC,MAAI;AACJ,MAAI;AACF,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ;AAC9D,QAAM,OAAO,OAAO,MAAM,SAAS,WAAW,KAAK,OAAO;AAC1D,QAAM,aAAa,gBAAgB,IAAI,SAAS,IAAI,aAAa,KAAK,IAAI,KAAK;AAC/E,SAAO,IAAI,eAAe,IAAI,QAAQ,SAAS,GAAG,MAAM,KAAK,QAAQ,MAAM,UAAU,MAAM,UAAU;AACvG;","names":["UnmapError","parseRetryAfter"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unmap/elevation",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Typed client for the unmap DEM elevation API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@unmap/core": "0.
|
|
40
|
+
"@unmap/core": "0.17.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"tsup": "^8.3.0",
|