@izak0s/spacebring-api 1.1.0 → 1.3.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 CHANGED
@@ -17,7 +17,8 @@ A fully-typed TypeScript client for the [Spacebring](https://www.spacebring.com)
17
17
  - **Nested, discoverable API** — `sb.billing.invoices.pay(id)`, `sb.visitors.visits.checkIn(body)`
18
18
  - **Auto-pagination** — every paginated list endpoint has an `iterate()` async generator that walks `nextPageToken` for you
19
19
  - **Ergonomic returns** — single-property response envelopes are unwrapped: entities and plain arrays come back directly
20
- - **Rich error handling** — non-2xx responses throw a typed `SpacebringError`; malformed 2xx bodies and stuck pagination tokens throw instead of failing silently
20
+ - **Rich error handling** — non-2xx responses throw a typed `SpacebringError` carrying the status, parsed body, and the operation that failed; malformed 2xx bodies and stuck pagination tokens throw instead of failing silently
21
+ - **Resilient by default** — automatic retries for rate limits, gateway errors, and network failures (never replaying non-idempotent requests); optional per-attempt timeouts and `AbortSignal` cancellation on every method
21
22
  - **Zero runtime dependencies** — Node ≥ 20, `fetch`-based
22
23
  - **Dual module** — ships both ESM and CommonJS builds with type declarations for each
23
24
 
@@ -85,6 +86,8 @@ Values are passed through exactly as the API sends them — no runtime conversio
85
86
 
86
87
  HTTP Basic with your **Client ID** and **Client Secret** from **Spacebring → [Network] → Network Settings → Developers**. The client builds the `Authorization: Basic …` header for you. The API's OAuth2 flow is not currently supported.
87
88
 
89
+ For development without touching live data, Spacebring offers a [test environment](https://www.spacebring.com/docs/administration/test-environment) (Network settings → Billing add-on) with free sandbox API credentials that work with this client unchanged.
90
+
88
91
  ---
89
92
 
90
93
  ## Error handling
@@ -99,12 +102,31 @@ try {
99
102
  } catch (error) {
100
103
  if (error instanceof SpacebringError) {
101
104
  console.error(error.status, error.body?.message);
105
+ console.error(error.operation); // "GET /benefits/v1/{benefitId}"
106
+ console.error(error.url); // the full request URL
102
107
  }
103
108
  }
104
109
  ```
105
110
 
106
111
  Malformed successes are covered too: a 2xx with an empty or incomplete body throws a `SpacebringError` (never a bare `TypeError`), and `iterate()` throws instead of looping forever if the API repeats a page token.
107
112
 
113
+ ### Rate limits & retries
114
+
115
+ The API allows **10 requests per second**. Rate-limited requests (429) are retried automatically — up to 3 times, honoring `Retry-After` (seconds or HTTP-date) or backing off exponentially — so `iterate()` survives the limit out of the box. Gateway errors (502/503/504), network failures, and timeouts are retried the same way, but only for idempotent methods (`GET`/`PUT`/`DELETE`) — a `POST` is never replayed, since the request may have reached the API. Tune or disable via `maxRetries` in the config (`maxRetries: 0` turns it off); an error that persists past the retries is thrown as-is.
116
+
117
+ ### Timeouts & cancellation
118
+
119
+ Every method accepts a trailing options argument with an `AbortSignal`; aborting cancels the in-flight request and any pending retry wait. A client-wide per-attempt timeout is available via `timeoutMs`:
120
+
121
+ ```ts
122
+ const sb = new Spacebring({ clientId, clientSecret, timeoutMs: 15_000 });
123
+
124
+ const controller = new AbortController();
125
+ const benefits = await sb.benefits.list({ locationRef }, { signal: controller.signal });
126
+ ```
127
+
128
+ `timeoutMs` uses `AbortSignal.timeout`; combining it with your own signal relies on `AbortSignal.any` (Node ≥ 20.3, all modern browsers/workers/edge runtimes).
129
+
108
130
  ---
109
131
 
110
132
  ## Escape hatch