@izak0s/spacebring-api 1.8.0 → 1.10.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 +32 -21
- package/dist/index.cjs +17 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +225 -105
- package/dist/index.d.ts +225 -105
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/izak0s/spacebring-api/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@izak0s/spacebring-api)
|
|
5
|
+
[](https://izak0s.github.io/spacebring-api/)
|
|
5
6
|
[](LICENSE)
|
|
6
7
|
|
|
7
8
|
A fully-typed TypeScript client for the [Spacebring](https://www.spacebring.com) coworking space management API, auto-generated from the official OpenAPI spec.
|
|
@@ -10,6 +11,8 @@ A fully-typed TypeScript client for the [Spacebring](https://www.spacebring.com)
|
|
|
10
11
|
|
|
11
12
|
---
|
|
12
13
|
|
|
14
|
+
📖 **[Full API reference](https://izak0s.github.io/spacebring-api/)** — every resource, method, and type, generated from the source.
|
|
15
|
+
|
|
13
16
|
## Features
|
|
14
17
|
|
|
15
18
|
- **<!-- coverage -->162 operations across 20 resource groups<!-- /coverage -->** — the full Spacebring API surface
|
|
@@ -38,40 +41,46 @@ No runtime dependencies — HTTP uses the built-in `fetch`.
|
|
|
38
41
|
## Quick Start
|
|
39
42
|
|
|
40
43
|
```ts
|
|
41
|
-
import { Spacebring } from "@izak0s/spacebring-api";
|
|
44
|
+
import { Spacebring, SpacebringError } from "@izak0s/spacebring-api";
|
|
42
45
|
|
|
43
46
|
const sb = new Spacebring({
|
|
44
47
|
clientId: process.env.SPACEBRING_CLIENT_ID!,
|
|
45
48
|
clientSecret: process.env.SPACEBRING_CLIENT_SECRET!,
|
|
46
|
-
networkId:
|
|
47
|
-
// baseUrl: "https://api.spacebring.com", // default
|
|
48
|
-
// fetch: customFetch, // inject your own fetch (tests, proxies)
|
|
49
|
+
networkId: process.env.SPACEBRING_NETWORK_ID, // optional — sent as the spacebring-network-id header
|
|
49
50
|
});
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const locations = await sb.locations.list();
|
|
55
|
-
await sb.visitors.visits.checkIn({ locationRef, visitRef });
|
|
52
|
+
// Single-property envelopes are unwrapped — list() gives you Location[] directly.
|
|
53
|
+
const locations = await sb.locations.list();
|
|
54
|
+
const locationRef = locations[0].id;
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
// Paginated lists return the page envelope, so nextPageToken stays available…
|
|
57
|
+
const { benefits, nextPageToken } = await sb.benefits.list({ locationRef });
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
59
|
+
// …or hand it to iterate(), which follows nextPageToken across pages.
|
|
60
|
+
// Break out early and it simply stops fetching — no wasted requests.
|
|
61
|
+
for await (const booking of sb.resources.bookings.iterate({ locationRef })) {
|
|
62
|
+
console.log(`${booking.startDate} → ${booking.endDate}`);
|
|
63
|
+
}
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
// Non-2xx responses throw a typed SpacebringError.
|
|
66
|
+
try {
|
|
67
|
+
await sb.billing.invoices.get("does-not-exist");
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error instanceof SpacebringError) {
|
|
70
|
+
console.error(`${error.status} on ${error.operation}: ${error.body?.message}`);
|
|
71
|
+
}
|
|
69
72
|
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Writes read the same, and endpoints that return more than one payload keep the envelope intact:
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
```ts
|
|
78
|
+
const { invoice, payment } = await sb.billing.invoices.pay(invoiceId, {
|
|
79
|
+
paymentMethod: { type: "stripe" },
|
|
80
|
+
});
|
|
72
81
|
```
|
|
73
82
|
|
|
74
|
-
Entity types are exported by name — `import type { Booking, Invoice, Membership } from "@izak0s/spacebring-api"` — matching what the methods return (`get`/`create`/`update` resolve to the entity, `iterate()` yields it). Query parameters get named interfaces too (`GetBookingsQuery`, `GetInvoicesQuery`), with per-field docs from the spec and enum filters as literal unions. Lower-level helpers too: `SpacebringConfig`, `SpacebringResources`, and the raw spec types `paths` / `components` / `operations`.
|
|
83
|
+
Entity types are exported by name — `import type { Booking, Invoice, Membership } from "@izak0s/spacebring-api"` — matching what the methods return (`get`/`create`/`update` resolve to the entity, `iterate()` yields it). Query parameters get named interfaces too (`GetBookingsQuery`, `GetInvoicesQuery`), with per-field docs from the spec and enum filters as literal unions, and request bodies get named types (`CreateBookingBody`, `UpdateInvoiceBody`). Lower-level helpers too: `SpacebringConfig`, `SpacebringResources`, and the raw spec types `paths` / `components` / `operations`.
|
|
75
84
|
|
|
76
85
|
### Data formats
|
|
77
86
|
|
|
@@ -87,6 +96,8 @@ Values are passed through exactly as the API sends them — no runtime conversio
|
|
|
87
96
|
|
|
88
97
|
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.
|
|
89
98
|
|
|
99
|
+
Because those credentials ride on every request, the client rejects a non-`https` `baseUrl` at construction — `http` is allowed only for loopback hosts (local proxies or mock servers). The default `baseUrl` is `https://api.spacebring.com`.
|
|
100
|
+
|
|
90
101
|
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.
|
|
91
102
|
|
|
92
103
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -2107,6 +2107,8 @@ var Spacebring = class {
|
|
|
2107
2107
|
/** Typed openapi-fetch client — escape hatch for endpoints or options the facade does not cover. */
|
|
2108
2108
|
raw;
|
|
2109
2109
|
constructor(config) {
|
|
2110
|
+
const baseUrl = config.baseUrl ?? "https://api.spacebring.com";
|
|
2111
|
+
assertSecureBaseUrl(baseUrl);
|
|
2110
2112
|
const headers = {
|
|
2111
2113
|
Authorization: `Basic ${toBase64(`${config.clientId}:${config.clientSecret}`)}`
|
|
2112
2114
|
};
|
|
@@ -2114,7 +2116,7 @@ var Spacebring = class {
|
|
|
2114
2116
|
headers["spacebring-network-id"] = config.networkId;
|
|
2115
2117
|
}
|
|
2116
2118
|
this.raw = createClient({
|
|
2117
|
-
baseUrl
|
|
2119
|
+
baseUrl,
|
|
2118
2120
|
headers,
|
|
2119
2121
|
fetch: withRetry(config.fetch ?? globalThis.fetch, config.maxRetries ?? 3, config.timeoutMs)
|
|
2120
2122
|
});
|
|
@@ -2183,6 +2185,20 @@ function sleep(ms, signal) {
|
|
|
2183
2185
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
2184
2186
|
});
|
|
2185
2187
|
}
|
|
2188
|
+
function assertSecureBaseUrl(baseUrl) {
|
|
2189
|
+
let url;
|
|
2190
|
+
try {
|
|
2191
|
+
url = new URL(baseUrl);
|
|
2192
|
+
} catch {
|
|
2193
|
+
throw new Error(`Spacebring baseUrl is not a valid URL: ${baseUrl}`);
|
|
2194
|
+
}
|
|
2195
|
+
if (url.protocol === "https:") return;
|
|
2196
|
+
const isLoopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]" || url.hostname === "::1";
|
|
2197
|
+
if (url.protocol === "http:" && isLoopback) return;
|
|
2198
|
+
throw new Error(
|
|
2199
|
+
`Spacebring baseUrl must use https (got "${url.protocol}//"): Basic-auth credentials would otherwise be sent in cleartext. Use https, or http only for a loopback host.`
|
|
2200
|
+
);
|
|
2201
|
+
}
|
|
2186
2202
|
function toBase64(value) {
|
|
2187
2203
|
if (typeof Buffer !== "undefined") {
|
|
2188
2204
|
return Buffer.from(value, "utf8").toString("base64");
|