@maschinenlesbar.org/ladesaeulenregister-cli 0.0.1

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.
Files changed (61) hide show
  1. package/CONTRIBUTING.md +25 -0
  2. package/LICENSE +661 -0
  3. package/LICENSING.md +47 -0
  4. package/README.md +69 -0
  5. package/dist/src/cli/commands/stations.d.ts +4 -0
  6. package/dist/src/cli/commands/stations.d.ts.map +1 -0
  7. package/dist/src/cli/commands/stations.js +91 -0
  8. package/dist/src/cli/commands/stations.js.map +1 -0
  9. package/dist/src/cli/index.d.ts +3 -0
  10. package/dist/src/cli/index.d.ts.map +1 -0
  11. package/dist/src/cli/index.js +11 -0
  12. package/dist/src/cli/index.js.map +1 -0
  13. package/dist/src/cli/io.d.ts +12 -0
  14. package/dist/src/cli/io.d.ts.map +1 -0
  15. package/dist/src/cli/io.js +7 -0
  16. package/dist/src/cli/io.js.map +1 -0
  17. package/dist/src/cli/program.d.ts +7 -0
  18. package/dist/src/cli/program.d.ts.map +1 -0
  19. package/dist/src/cli/program.js +53 -0
  20. package/dist/src/cli/program.js.map +1 -0
  21. package/dist/src/cli/run.d.ts +3 -0
  22. package/dist/src/cli/run.d.ts.map +1 -0
  23. package/dist/src/cli/run.js +85 -0
  24. package/dist/src/cli/run.js.map +1 -0
  25. package/dist/src/cli/shared.d.ts +56 -0
  26. package/dist/src/cli/shared.d.ts.map +1 -0
  27. package/dist/src/cli/shared.js +112 -0
  28. package/dist/src/cli/shared.js.map +1 -0
  29. package/dist/src/client/client.d.ts +32 -0
  30. package/dist/src/client/client.d.ts.map +1 -0
  31. package/dist/src/client/client.js +128 -0
  32. package/dist/src/client/client.js.map +1 -0
  33. package/dist/src/client/engine.d.ts +55 -0
  34. package/dist/src/client/engine.d.ts.map +1 -0
  35. package/dist/src/client/engine.js +111 -0
  36. package/dist/src/client/engine.js.map +1 -0
  37. package/dist/src/client/errors.d.ts +45 -0
  38. package/dist/src/client/errors.d.ts.map +1 -0
  39. package/dist/src/client/errors.js +57 -0
  40. package/dist/src/client/errors.js.map +1 -0
  41. package/dist/src/client/http.d.ts +26 -0
  42. package/dist/src/client/http.d.ts.map +1 -0
  43. package/dist/src/client/http.js +80 -0
  44. package/dist/src/client/http.js.map +1 -0
  45. package/dist/src/client/index.d.ts +11 -0
  46. package/dist/src/client/index.d.ts.map +1 -0
  47. package/dist/src/client/index.js +8 -0
  48. package/dist/src/client/index.js.map +1 -0
  49. package/dist/src/client/query.d.ts +9 -0
  50. package/dist/src/client/query.d.ts.map +1 -0
  51. package/dist/src/client/query.js +33 -0
  52. package/dist/src/client/query.js.map +1 -0
  53. package/dist/src/client/types.d.ts +108 -0
  54. package/dist/src/client/types.d.ts.map +1 -0
  55. package/dist/src/client/types.js +4 -0
  56. package/dist/src/client/types.js.map +1 -0
  57. package/dist/src/index.d.ts +2 -0
  58. package/dist/src/index.d.ts.map +1 -0
  59. package/dist/src/index.js +3 -0
  60. package/dist/src/index.js.map +1 -0
  61. package/package.json +69 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type EngineOptions } from "./engine.js";
2
+ import type { CountByRow, FieldInfo, StationPage, StationQuery } from "./types.js";
3
+ /**
4
+ * Default `outFields` — a curated, broadly-useful subset. The layer has ~60 columns
5
+ * including a large `F_response_body` JSON blob per row; `--fields '*'` returns
6
+ * everything.
7
+ */
8
+ export declare const DEFAULT_FIELDS: string;
9
+ /** Options for the client (engine options only — the API needs no auth). */
10
+ export type LadesaeulenClientOptions = EngineOptions;
11
+ export declare class LadesaeulenClient {
12
+ private readonly engine;
13
+ constructor(options?: LadesaeulenClientOptions);
14
+ /** GET a query path, then throw if the ArcGIS `error` envelope is present. */
15
+ private get;
16
+ /** Build the shared feature-query params (where / outFields / paging / near). */
17
+ private buildParams;
18
+ /** A page of charging stations (ArcGIS `f=json`). */
19
+ stations(q?: StationQuery): Promise<StationPage>;
20
+ /** The number of stations matching the query (`returnCountOnly`). */
21
+ count(q?: StationQuery): Promise<number>;
22
+ /** The matching stations as a GeoJSON FeatureCollection (`f=geojson`). */
23
+ geojson(q?: StationQuery): Promise<unknown>;
24
+ /**
25
+ * Grouped station counts by a field (ArcGIS `outStatistics` group-by), e.g.
26
+ * `countBy("state")` for stations per Bundesland. Sorted descending by count.
27
+ */
28
+ countBy(field: string, where?: string): Promise<CountByRow[]>;
29
+ /** The layer's field metadata (names/types/aliases) — for building queries. */
30
+ fields(): Promise<FieldInfo[]>;
31
+ }
32
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client/client.ts"],"names":[],"mappings":"AAYA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,KAAK,EAEV,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAC;AAKpB;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAkBhB,CAAC;AAEZ,4EAA4E;AAC5E,MAAM,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAErD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3B,OAAO,GAAE,wBAA6B;IAIlD,8EAA8E;YAChE,GAAG;IAqBjB,iFAAiF;IACjF,OAAO,CAAC,WAAW;IAiBnB,qDAAqD;IAC/C,QAAQ,CAAC,CAAC,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IAS1D,qEAAqE;IAC/D,KAAK,CAAC,CAAC,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAOlD,0EAA0E;IACpE,OAAO,CAAC,CAAC,GAAE,YAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrD;;;OAGG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAiBlE,+EAA+E;IACzE,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CAOrC"}
@@ -0,0 +1,128 @@
1
+ // LadesaeulenClient — a typed client over the Ladesäulenregister of the
2
+ // Bundesnetzagentur, a public ArcGIS FeatureServer of German EV charging stations
3
+ // (~111k Ladeeinrichtungen; layer 0). No auth.
4
+ //
5
+ // The ArcGIS server answers HTTP 200 even for logical errors, carrying them in an
6
+ // `error` object — the client checks for it and throws.
7
+ //
8
+ // const c = new LadesaeulenClient();
9
+ // await c.count({ where: "Ort='Berlin' AND Typ='Schnellladeeinrichtung'" }); // 660
10
+ // await c.countBy("state"); // stations per Bundesland
11
+ // await c.stations({ near: { lat: 52.52, lon: 13.405, radiusKm: 1 } });
12
+ import { RequestEngine } from "./engine.js";
13
+ import { LadesaeulenApiError } from "./errors.js";
14
+ /** The layer holding the charging stations (Ladeeinrichtungen). */
15
+ const LAYER = "/0";
16
+ /**
17
+ * Default `outFields` — a curated, broadly-useful subset. The layer has ~60 columns
18
+ * including a large `F_response_body` JSON blob per row; `--fields '*'` returns
19
+ * everything.
20
+ */
21
+ export const DEFAULT_FIELDS = [
22
+ "ID",
23
+ "Betreiber",
24
+ "operator_companyName",
25
+ "Straße",
26
+ "Hausnummer",
27
+ "Postleitzahl",
28
+ "Ort",
29
+ "district_independent_city",
30
+ "state",
31
+ "Typ",
32
+ "Status",
33
+ "max_electric_power_station",
34
+ "Anzahl_Ladepunkte",
35
+ "coordinates_latitude",
36
+ "coordinates_longitude",
37
+ "go_live_date",
38
+ "Bezahlsystem",
39
+ ].join(",");
40
+ export class LadesaeulenClient {
41
+ engine;
42
+ constructor(options = {}) {
43
+ this.engine = new RequestEngine(options);
44
+ }
45
+ /** GET a query path, then throw if the ArcGIS `error` envelope is present. */
46
+ async get(path, params) {
47
+ const res = await this.engine.getJson(path, params);
48
+ const err = res?.error;
49
+ if (err && typeof err === "object") {
50
+ const detail = [err.message, ...(Array.isArray(err.details) ? err.details : [])]
51
+ .filter((s) => typeof s === "string" && s.length > 0)
52
+ .join("; ");
53
+ throw new LadesaeulenApiError({
54
+ url: this.engine.buildUrl(path, params),
55
+ method: "GET",
56
+ body: JSON.stringify(res),
57
+ arcgisCode: typeof err.code === "number" ? err.code : undefined,
58
+ detail: detail || undefined,
59
+ });
60
+ }
61
+ return res;
62
+ }
63
+ /** Build the shared feature-query params (where / outFields / paging / near). */
64
+ buildParams(q, extra) {
65
+ const p = { where: q.where ?? "1=1", ...extra };
66
+ if (q.outFields !== undefined)
67
+ p.outFields = q.outFields;
68
+ if (q.limit !== undefined)
69
+ p.resultRecordCount = q.limit;
70
+ if (q.offset !== undefined)
71
+ p.resultOffset = q.offset;
72
+ if (q.orderBy !== undefined)
73
+ p.orderByFields = q.orderBy;
74
+ if (q.near) {
75
+ p.geometry = `${q.near.lon},${q.near.lat}`;
76
+ p.geometryType = "esriGeometryPoint";
77
+ p.inSR = 4326;
78
+ p.distance = Math.round(q.near.radiusKm * 1000);
79
+ p.units = "esriSRUnit_Meter";
80
+ p.spatialRel = "esriSpatialRelIntersects";
81
+ }
82
+ return p;
83
+ }
84
+ /** A page of charging stations (ArcGIS `f=json`). */
85
+ async stations(q = {}) {
86
+ const params = this.buildParams({ ...q, outFields: q.outFields ?? DEFAULT_FIELDS }, { f: "json", returnGeometry: false });
87
+ const res = await this.get(`${LAYER}/query`, params);
88
+ return { features: res.features ?? [], exceededTransferLimit: res.exceededTransferLimit ?? false };
89
+ }
90
+ /** The number of stations matching the query (`returnCountOnly`). */
91
+ async count(q = {}) {
92
+ const params = this.buildParams(q, { f: "json", returnCountOnly: true });
93
+ delete params["outFields"];
94
+ const res = await this.get(`${LAYER}/query`, params);
95
+ return res.count ?? 0;
96
+ }
97
+ /** The matching stations as a GeoJSON FeatureCollection (`f=geojson`). */
98
+ async geojson(q = {}) {
99
+ const params = this.buildParams({ ...q, outFields: q.outFields ?? DEFAULT_FIELDS }, { f: "geojson" });
100
+ return this.get(`${LAYER}/query`, params);
101
+ }
102
+ /**
103
+ * Grouped station counts by a field (ArcGIS `outStatistics` group-by), e.g.
104
+ * `countBy("state")` for stations per Bundesland. Sorted descending by count.
105
+ */
106
+ async countBy(field, where = "1=1") {
107
+ const params = {
108
+ where,
109
+ f: "json",
110
+ groupByFieldsForStatistics: field,
111
+ outStatistics: JSON.stringify([
112
+ { statisticType: "count", onStatisticField: "OBJECTID", outStatisticFieldName: "count" },
113
+ ]),
114
+ orderByFields: "count DESC",
115
+ };
116
+ const res = await this.get(`${LAYER}/query`, params);
117
+ return (res.features ?? []).map((f) => ({
118
+ value: f.attributes[field] ?? null,
119
+ count: Number(f.attributes["count"] ?? 0),
120
+ }));
121
+ }
122
+ /** The layer's field metadata (names/types/aliases) — for building queries. */
123
+ async fields() {
124
+ const res = await this.get(LAYER, { f: "json" });
125
+ return res.fields ?? [];
126
+ }
127
+ }
128
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/client/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { type Transport } from "./http.js";
2
+ import { type QueryParams } from "./query.js";
3
+ export declare const DEFAULT_BASE_URL = "https://services-eu1.arcgis.com/TJm8oSvOdJUQvQT5/arcgis/rest/services/Ladesaeulen/FeatureServer";
4
+ export interface RawResponse {
5
+ data: Buffer;
6
+ contentType: string;
7
+ status: number;
8
+ }
9
+ export interface EngineOptions {
10
+ /** Base URL of the API. Defaults to the public Ladesäulen ArcGIS FeatureServer. */
11
+ baseUrl?: string;
12
+ /** Swappable transport. Defaults to the built-in node http/https transport. */
13
+ transport?: Transport;
14
+ /** Value of the User-Agent header. */
15
+ userAgent?: string;
16
+ /** Extra headers sent on every request. */
17
+ defaultHeaders?: Record<string, string>;
18
+ /** Per-request timeout in milliseconds (0 disables). */
19
+ timeoutMs?: number;
20
+ /** Number of automatic retries for transient (429/503) responses. */
21
+ maxRetries?: number;
22
+ /** Base backoff between retries in milliseconds (grows linearly). */
23
+ retryDelayMs?: number;
24
+ /**
25
+ * Hard cap on response body size in bytes (defends against memory exhaustion
26
+ * from a hostile/buggy endpoint). Defaults to 100 MiB; set to 0 for no limit.
27
+ */
28
+ maxResponseBytes?: number;
29
+ /** Injectable sleep, primarily for deterministic tests. */
30
+ sleep?: (ms: number) => Promise<void>;
31
+ }
32
+ export declare class RequestEngine {
33
+ private readonly baseUrl;
34
+ private readonly transport;
35
+ private readonly userAgent;
36
+ private readonly defaultHeaders;
37
+ private readonly timeoutMs;
38
+ private readonly maxRetries;
39
+ private readonly retryDelayMs;
40
+ private readonly maxResponseBytes;
41
+ private readonly sleep;
42
+ constructor(options?: EngineOptions);
43
+ /** Build a fully-qualified URL from a path and optional query parameters. */
44
+ buildUrl(path: string, query?: QueryParams): string;
45
+ /**
46
+ * Perform a GET with Accept negotiation and transient-error retries. Redirects
47
+ * are NOT followed — the canonical host answers directly, so a 3xx surfaces as
48
+ * an error.
49
+ */
50
+ request(path: string, query?: QueryParams, accept?: string): Promise<RawResponse>;
51
+ /** GET a path with query params and parse the JSON reply into `T`. */
52
+ getJson<T>(path: string, query?: QueryParams): Promise<T>;
53
+ private toApiError;
54
+ }
55
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAGhE,eAAO,MAAM,gBAAgB,oGACsE,CAAC;AAGpG,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAOD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;gBAE1C,OAAO,GAAE,aAAkB;IAYvC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM;IAMnD;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,EAAE,MAAM,SAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;IAmCnG,sEAAsE;IAChE,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAa/D,OAAO,CAAC,UAAU;CAsBnB"}
@@ -0,0 +1,111 @@
1
+ // The request engine: turns logical (path, query) calls into HTTP GET requests via
2
+ // a Transport, applies retry/backoff for transient statuses (429, 503), and decodes
3
+ // JSON responses. The Ladesäulenregister is a public ArcGIS FeatureServer — an
4
+ // unauthenticated GET API whose parameters travel in the query string.
5
+ import { nodeHttpTransport } from "./http.js";
6
+ import { buildQueryString } from "./query.js";
7
+ import { LadesaeulenApiError, LadesaeulenParseError } from "./errors.js";
8
+ export const DEFAULT_BASE_URL = "https://services-eu1.arcgis.com/TJm8oSvOdJUQvQT5/arcgis/rest/services/Ladesaeulen/FeatureServer";
9
+ const DEFAULT_USER_AGENT = "ladesaeulenregister-cli";
10
+ const DEFAULT_MAX_RESPONSE_BYTES = 100 * 1024 * 1024;
11
+ const realSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
12
+ export class RequestEngine {
13
+ baseUrl;
14
+ transport;
15
+ userAgent;
16
+ defaultHeaders;
17
+ timeoutMs;
18
+ maxRetries;
19
+ retryDelayMs;
20
+ maxResponseBytes;
21
+ sleep;
22
+ constructor(options = {}) {
23
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
24
+ this.transport = options.transport ?? nodeHttpTransport;
25
+ this.userAgent = options.userAgent ?? DEFAULT_USER_AGENT;
26
+ this.defaultHeaders = options.defaultHeaders ?? {};
27
+ this.timeoutMs = options.timeoutMs ?? 30_000;
28
+ this.maxRetries = options.maxRetries ?? 2;
29
+ this.retryDelayMs = options.retryDelayMs ?? 200;
30
+ this.maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
31
+ this.sleep = options.sleep ?? realSleep;
32
+ }
33
+ /** Build a fully-qualified URL from a path and optional query parameters. */
34
+ buildUrl(path, query) {
35
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
36
+ const qs = query ? buildQueryString(query) : "";
37
+ return `${this.baseUrl}${normalizedPath}${qs ? `?${qs}` : ""}`;
38
+ }
39
+ /**
40
+ * Perform a GET with Accept negotiation and transient-error retries. Redirects
41
+ * are NOT followed — the canonical host answers directly, so a 3xx surfaces as
42
+ * an error.
43
+ */
44
+ async request(path, query, accept = "application/json") {
45
+ const url = this.buildUrl(path, query);
46
+ const headers = {
47
+ ...this.defaultHeaders,
48
+ Accept: accept,
49
+ "User-Agent": this.userAgent,
50
+ };
51
+ let attempt = 0;
52
+ for (;;) {
53
+ const response = await this.transport({
54
+ method: "GET",
55
+ url,
56
+ headers,
57
+ timeoutMs: this.timeoutMs,
58
+ ...(this.maxResponseBytes > 0 ? { maxResponseBytes: this.maxResponseBytes } : {}),
59
+ });
60
+ const status = response.status;
61
+ const retryable = status === 429 || status === 503;
62
+ if (retryable && attempt < this.maxRetries) {
63
+ attempt += 1;
64
+ await this.sleep(this.retryDelayMs * attempt);
65
+ continue;
66
+ }
67
+ const contentType = String(response.headers["content-type"] ?? "");
68
+ if (status < 200 || status >= 300) {
69
+ throw this.toApiError(url, status, response.body);
70
+ }
71
+ return { data: response.body, contentType, status };
72
+ }
73
+ }
74
+ /** GET a path with query params and parse the JSON reply into `T`. */
75
+ async getJson(path, query) {
76
+ const res = await this.request(path, query);
77
+ const text = res.data.toString("utf8");
78
+ if (res.status === 204 || text.trim().length === 0) {
79
+ return null;
80
+ }
81
+ try {
82
+ return JSON.parse(text);
83
+ }
84
+ catch (cause) {
85
+ throw new LadesaeulenParseError(`Failed to parse JSON response from ${path}`, { cause });
86
+ }
87
+ }
88
+ toApiError(url, status, body) {
89
+ const text = body.toString("utf8");
90
+ let detail;
91
+ try {
92
+ const parsed = JSON.parse(text);
93
+ if (parsed?.error && typeof parsed.error.message === "string")
94
+ detail = parsed.error.message;
95
+ else if (typeof parsed?.message === "string")
96
+ detail = parsed.message;
97
+ else if (typeof parsed?.detail === "string")
98
+ detail = parsed.detail;
99
+ }
100
+ catch {
101
+ // Not JSON (e.g. an HTML error page). Surface a short, whitespace-collapsed
102
+ // snippet of a textual body; skip HTML pages (start with "<").
103
+ const snippet = text.trim().replace(/\s+/g, " ");
104
+ if (snippet.length > 0 && !snippet.startsWith("<")) {
105
+ detail = snippet.length > 200 ? `${snippet.slice(0, 200)}…` : snippet;
106
+ }
107
+ }
108
+ return new LadesaeulenApiError({ status, url, method: "GET", body: text, detail });
109
+ }
110
+ }
111
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /** Base class for every error originating from this client. */
2
+ export declare class LadesaeulenError extends Error {
3
+ constructor(message: string, options?: {
4
+ cause?: unknown;
5
+ });
6
+ }
7
+ /**
8
+ * The API signalled a failure. The ArcGIS FeatureServer is unusual: it answers
9
+ * HTTP 200 even for logical errors, carrying the message in an `error` object
10
+ * (`{code, message, details}`) — e.g. a bad `where` clause or "Token Required".
11
+ * This error models both worlds:
12
+ * - `status` is set for a genuine transport/HTTP failure (non-2xx);
13
+ * - `arcgisCode` is set for a logical ArcGIS error (from `error.code`).
14
+ * `detail` holds the human-readable message in either case.
15
+ */
16
+ export declare class LadesaeulenApiError extends LadesaeulenError {
17
+ readonly status: number | undefined;
18
+ readonly arcgisCode: number | undefined;
19
+ readonly detail: string | undefined;
20
+ readonly url: string;
21
+ readonly method: string;
22
+ readonly body: string;
23
+ constructor(args: {
24
+ url: string;
25
+ method: string;
26
+ body: string;
27
+ status?: number;
28
+ arcgisCode?: number;
29
+ detail?: string;
30
+ });
31
+ /** True for HTTP statuses the API treats as transient and retry-able. */
32
+ get isRetryable(): boolean;
33
+ /** True for a transport-level HTTP 404. */
34
+ get isNotFound(): boolean;
35
+ }
36
+ /** A transport-level failure (DNS, connection reset, timeout, ...). */
37
+ export declare class LadesaeulenNetworkError extends LadesaeulenError {
38
+ }
39
+ /** A client-side validation error (e.g. a bad --near) — no request made. */
40
+ export declare class LadesaeulenValidationError extends LadesaeulenError {
41
+ }
42
+ /** The response body could not be parsed as the expected JSON shape. */
43
+ export declare class LadesaeulenParseError extends LadesaeulenError {
44
+ }
45
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/client/errors.ts"],"names":[],"mappings":"AAGA,+DAA+D;AAC/D,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAoB,SAAQ,gBAAgB;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAeD,yEAAyE;IACzE,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,2CAA2C;IAC3C,IAAI,UAAU,IAAI,OAAO,CAExB;CACF;AAED,uEAAuE;AACvE,qBAAa,uBAAwB,SAAQ,gBAAgB;CAAG;AAEhE,4EAA4E;AAC5E,qBAAa,0BAA2B,SAAQ,gBAAgB;CAAG;AAEnE,wEAAwE;AACxE,qBAAa,qBAAsB,SAAQ,gBAAgB;CAAG"}
@@ -0,0 +1,57 @@
1
+ // Error types raised by the client. Kept free of any I/O so they are trivial to
2
+ // construct in tests and to `instanceof`-check by consumers.
3
+ /** Base class for every error originating from this client. */
4
+ export class LadesaeulenError extends Error {
5
+ constructor(message, options) {
6
+ super(message, options);
7
+ this.name = new.target.name;
8
+ }
9
+ }
10
+ /**
11
+ * The API signalled a failure. The ArcGIS FeatureServer is unusual: it answers
12
+ * HTTP 200 even for logical errors, carrying the message in an `error` object
13
+ * (`{code, message, details}`) — e.g. a bad `where` clause or "Token Required".
14
+ * This error models both worlds:
15
+ * - `status` is set for a genuine transport/HTTP failure (non-2xx);
16
+ * - `arcgisCode` is set for a logical ArcGIS error (from `error.code`).
17
+ * `detail` holds the human-readable message in either case.
18
+ */
19
+ export class LadesaeulenApiError extends LadesaeulenError {
20
+ status;
21
+ arcgisCode;
22
+ detail;
23
+ url;
24
+ method;
25
+ body;
26
+ constructor(args) {
27
+ const detailPart = args.detail ? `: ${args.detail}` : "";
28
+ const head = args.status !== undefined
29
+ ? `HTTP ${args.status}`
30
+ : `ArcGIS error${args.arcgisCode !== undefined ? ` ${args.arcgisCode}` : ""}`;
31
+ super(`${head} for ${args.method} ${args.url}${detailPart}`);
32
+ this.status = args.status;
33
+ this.arcgisCode = args.arcgisCode;
34
+ this.url = args.url;
35
+ this.method = args.method;
36
+ this.body = args.body;
37
+ this.detail = args.detail;
38
+ }
39
+ /** True for HTTP statuses the API treats as transient and retry-able. */
40
+ get isRetryable() {
41
+ return this.status === 429 || this.status === 503;
42
+ }
43
+ /** True for a transport-level HTTP 404. */
44
+ get isNotFound() {
45
+ return this.status === 404;
46
+ }
47
+ }
48
+ /** A transport-level failure (DNS, connection reset, timeout, ...). */
49
+ export class LadesaeulenNetworkError extends LadesaeulenError {
50
+ }
51
+ /** A client-side validation error (e.g. a bad --near) — no request made. */
52
+ export class LadesaeulenValidationError extends LadesaeulenError {
53
+ }
54
+ /** The response body could not be parsed as the expected JSON shape. */
55
+ export class LadesaeulenParseError extends LadesaeulenError {
56
+ }
57
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/client/errors.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,6DAA6D;AAE7D,+DAA+D;AAC/D,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAoB,SAAQ,gBAAgB;IAC9C,MAAM,CAAqB;IAC3B,UAAU,CAAqB;IAC/B,MAAM,CAAqB;IAC3B,GAAG,CAAS;IACZ,MAAM,CAAS;IACf,IAAI,CAAS;IAEtB,YAAY,IAOX;QACC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,GACR,IAAI,CAAC,MAAM,KAAK,SAAS;YACvB,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE;YACvB,CAAC,CAAC,eAAe,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAClF,KAAK,CAAC,GAAG,IAAI,QAAQ,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,GAAG,UAAU,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,yEAAyE;IACzE,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC;IACpD,CAAC;IAED,2CAA2C;IAC3C,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC;IAC7B,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,OAAO,uBAAwB,SAAQ,gBAAgB;CAAG;AAEhE,4EAA4E;AAC5E,MAAM,OAAO,0BAA2B,SAAQ,gBAAgB;CAAG;AAEnE,wEAAwE;AACxE,MAAM,OAAO,qBAAsB,SAAQ,gBAAgB;CAAG"}
@@ -0,0 +1,26 @@
1
+ import http from "node:http";
2
+ export interface HttpRequest {
3
+ method: string;
4
+ /** Fully-qualified absolute URL. */
5
+ url: string;
6
+ headers?: Record<string, string>;
7
+ /** Optional request body (already serialised). */
8
+ body?: string | Buffer;
9
+ /** Per-request timeout in milliseconds. */
10
+ timeoutMs?: number;
11
+ /** Hard cap on the response body size in bytes; the request aborts if exceeded. */
12
+ maxResponseBytes?: number;
13
+ }
14
+ export interface HttpResponse {
15
+ status: number;
16
+ headers: http.IncomingHttpHeaders;
17
+ body: Buffer;
18
+ }
19
+ export type Transport = (request: HttpRequest) => Promise<HttpResponse>;
20
+ /**
21
+ * Default transport. Resolves with the raw response (including non-2xx) — status
22
+ * interpretation is the client's job. Rejects only on transport-level failures
23
+ * (connection errors, timeouts, malformed URLs).
24
+ */
25
+ export declare const nodeHttpTransport: Transport;
26
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"AAQA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAwE5B,CAAC"}
@@ -0,0 +1,80 @@
1
+ // HTTP transport built on Node's built-in `http`/`https` modules — no axios,
2
+ // no fetch polyfill, no third-party HTTP client.
3
+ //
4
+ // The transport is a plain function so it can be trivially swapped out in tests
5
+ // (inject a `mock.fn()` returning a canned HttpResponse) without touching the
6
+ // network. The default implementation below is exercised against a real local
7
+ // `http.createServer` in the test-suite.
8
+ import http from "node:http";
9
+ import https from "node:https";
10
+ import { LadesaeulenNetworkError } from "./errors.js";
11
+ /**
12
+ * Default transport. Resolves with the raw response (including non-2xx) — status
13
+ * interpretation is the client's job. Rejects only on transport-level failures
14
+ * (connection errors, timeouts, malformed URLs).
15
+ */
16
+ export const nodeHttpTransport = (request) => new Promise((resolve, reject) => {
17
+ let url;
18
+ try {
19
+ url = new URL(request.url);
20
+ }
21
+ catch {
22
+ reject(new LadesaeulenNetworkError(`Invalid URL: ${request.url}`));
23
+ return;
24
+ }
25
+ // Only http/https are supported. Reject anything else up front with a clear,
26
+ // typed error instead of letting Node throw an opaque ERR_INVALID_PROTOCOL.
27
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
28
+ reject(new LadesaeulenNetworkError(`Unsupported protocol "${url.protocol}" in URL: ${request.url}`));
29
+ return;
30
+ }
31
+ const isHttps = url.protocol === "https:";
32
+ const driver = isHttps ? https : http;
33
+ const maxBytes = request.maxResponseBytes;
34
+ const req = driver.request(url, {
35
+ method: request.method,
36
+ headers: request.headers,
37
+ }, (res) => {
38
+ const chunks = [];
39
+ let received = 0;
40
+ let aborted = false;
41
+ res.on("data", (chunk) => {
42
+ if (aborted)
43
+ return;
44
+ received += chunk.length;
45
+ if (maxBytes !== undefined && received > maxBytes) {
46
+ aborted = true;
47
+ res.destroy();
48
+ reject(new LadesaeulenNetworkError(`Response exceeded maxResponseBytes (${maxBytes})`));
49
+ return;
50
+ }
51
+ chunks.push(chunk);
52
+ });
53
+ res.on("end", () => {
54
+ if (aborted)
55
+ return;
56
+ resolve({
57
+ status: res.statusCode ?? 0,
58
+ headers: res.headers,
59
+ body: Buffer.concat(chunks),
60
+ });
61
+ });
62
+ res.on("error", (err) => {
63
+ if (aborted)
64
+ return; // we already rejected with the size-cap error
65
+ reject(new LadesaeulenNetworkError(`Response stream error: ${err.message}`, { cause: err }));
66
+ });
67
+ });
68
+ if (request.timeoutMs && request.timeoutMs > 0) {
69
+ req.setTimeout(request.timeoutMs, () => {
70
+ req.destroy(new LadesaeulenNetworkError(`Request timed out after ${request.timeoutMs}ms`));
71
+ });
72
+ }
73
+ req.on("error", (err) => {
74
+ reject(err instanceof LadesaeulenNetworkError ? err : new LadesaeulenNetworkError(err.message, { cause: err }));
75
+ });
76
+ if (request.body !== undefined)
77
+ req.write(request.body);
78
+ req.end();
79
+ });
80
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { LadesaeulenClient, DEFAULT_FIELDS } from "./client.js";
2
+ export type { LadesaeulenClientOptions } from "./client.js";
3
+ export { RequestEngine, DEFAULT_BASE_URL } from "./engine.js";
4
+ export type { EngineOptions, RawResponse } from "./engine.js";
5
+ export { nodeHttpTransport } from "./http.js";
6
+ export type { Transport, HttpRequest, HttpResponse } from "./http.js";
7
+ export { buildQueryString } from "./query.js";
8
+ export type { QueryParams, QueryValue } from "./query.js";
9
+ export { LadesaeulenError, LadesaeulenApiError, LadesaeulenNetworkError, LadesaeulenValidationError, LadesaeulenParseError, } from "./errors.js";
10
+ export * from "./types.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ // Public entry point for the API client library.
2
+ export { LadesaeulenClient, DEFAULT_FIELDS } from "./client.js";
3
+ export { RequestEngine, DEFAULT_BASE_URL } from "./engine.js";
4
+ export { nodeHttpTransport } from "./http.js";
5
+ export { buildQueryString } from "./query.js";
6
+ export { LadesaeulenError, LadesaeulenApiError, LadesaeulenNetworkError, LadesaeulenValidationError, LadesaeulenParseError, } from "./errors.js";
7
+ export * from "./types.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type QueryPrimitive = string | number | boolean | Date | null | undefined;
2
+ export type QueryValue = QueryPrimitive | QueryPrimitive[];
3
+ export type QueryParams = Record<string, QueryValue>;
4
+ /**
5
+ * Build a query string (without a leading `?`) from a params object.
6
+ * Returns an empty string when no parameters survive filtering.
7
+ */
8
+ export declare function buildQueryString(params: QueryParams): string;
9
+ //# sourceMappingURL=query.d.ts.map