@izak0s/spacebring-api 0.2.0 → 1.1.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 +27 -15
- package/dist/index.cjs +34 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +358 -7418
- package/dist/index.d.ts +358 -7418
- package/dist/index.js +34 -20
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -46,26 +46,38 @@ const sb = new Spacebring({
|
|
|
46
46
|
// fetch: customFetch, // inject your own fetch (tests, proxies)
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
await sb.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
async function main() {
|
|
50
|
+
// Single-property envelopes are unwrapped: entities and plain arrays come back directly
|
|
51
|
+
const invoice = await sb.billing.invoices.get(invoiceId);
|
|
52
|
+
const locations = await sb.locations.list();
|
|
53
|
+
await sb.visitors.visits.checkIn({ locationRef, visitRef });
|
|
54
|
+
|
|
55
|
+
// Paginated lists return the page envelope, so nextPageToken stays available
|
|
56
|
+
const { benefits, nextPageToken } = await sb.benefits.list({ locationRef });
|
|
57
|
+
|
|
58
|
+
// ...or let iterate() walk nextPageToken for you; breaking early stops fetching
|
|
59
|
+
for await (const booking of sb.resources.bookings.iterate({ locationRef })) {
|
|
60
|
+
console.log(booking.id);
|
|
61
|
+
}
|
|
56
62
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
// Endpoints returning multiple payloads keep the envelope
|
|
64
|
+
const { invoice: paid, payment } = await sb.billing.invoices.pay(invoiceId, {
|
|
65
|
+
paymentMethod: { type: "stripe" },
|
|
66
|
+
});
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
const { invoice: paid, payment } = await sb.billing.invoices.pay(invoiceId, {
|
|
64
|
-
paymentMethod: { type: "stripe" },
|
|
65
|
-
});
|
|
69
|
+
main().catch(console.error);
|
|
66
70
|
```
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
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). Lower-level helpers too: `SpacebringConfig`, `SpacebringResources`, and the raw spec types `paths` / `components` / `operations`.
|
|
73
|
+
|
|
74
|
+
### Data formats
|
|
75
|
+
|
|
76
|
+
Values are passed through exactly as the API sends them — no runtime conversion:
|
|
77
|
+
|
|
78
|
+
- **Dates** (`createDate`, `startDate`, …) are ISO 8601 strings — wrap in `new Date(booking.startDate)` when you need a `Date`.
|
|
79
|
+
- **Money** (`amount`, `price`, …) arrives as decimal floats. Fine for display; for accounting arithmetic convert to integer cents first to avoid floating-point drift.
|
|
80
|
+
- **IDs** (`id`, `*Ref`) are UUID strings.
|
|
69
81
|
|
|
70
82
|
---
|
|
71
83
|
|
package/dist/index.cjs
CHANGED
|
@@ -40,13 +40,14 @@ function createClient(clientOptions) {
|
|
|
40
40
|
fetch: baseFetch = globalThis.fetch,
|
|
41
41
|
querySerializer: globalQuerySerializer,
|
|
42
42
|
bodySerializer: globalBodySerializer,
|
|
43
|
+
pathSerializer: globalPathSerializer,
|
|
43
44
|
headers: baseHeaders,
|
|
44
45
|
requestInitExt = void 0,
|
|
45
46
|
...baseOptions
|
|
46
47
|
} = { ...clientOptions };
|
|
47
48
|
requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
|
|
48
49
|
baseUrl = removeTrailingSlash(baseUrl);
|
|
49
|
-
const
|
|
50
|
+
const globalMiddlewares = [];
|
|
50
51
|
async function coreFetch(schemaPath, fetchOptions) {
|
|
51
52
|
const {
|
|
52
53
|
baseUrl: localBaseUrl,
|
|
@@ -57,7 +58,9 @@ function createClient(clientOptions) {
|
|
|
57
58
|
parseAs = "json",
|
|
58
59
|
querySerializer: requestQuerySerializer,
|
|
59
60
|
bodySerializer = globalBodySerializer ?? defaultBodySerializer,
|
|
61
|
+
pathSerializer: requestPathSerializer,
|
|
60
62
|
body,
|
|
63
|
+
middleware: requestMiddlewares = [],
|
|
61
64
|
...init
|
|
62
65
|
} = fetchOptions || {};
|
|
63
66
|
let finalBaseUrl = baseUrl;
|
|
@@ -71,6 +74,7 @@ function createClient(clientOptions) {
|
|
|
71
74
|
...requestQuerySerializer
|
|
72
75
|
});
|
|
73
76
|
}
|
|
77
|
+
const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;
|
|
74
78
|
const serializedBody = body === void 0 ? void 0 : bodySerializer(
|
|
75
79
|
body,
|
|
76
80
|
// Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation:
|
|
@@ -90,6 +94,7 @@ function createClient(clientOptions) {
|
|
|
90
94
|
headers,
|
|
91
95
|
params.header
|
|
92
96
|
);
|
|
97
|
+
const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];
|
|
93
98
|
const requestInit = {
|
|
94
99
|
redirect: "follow",
|
|
95
100
|
...baseOptions,
|
|
@@ -100,7 +105,7 @@ function createClient(clientOptions) {
|
|
|
100
105
|
let id;
|
|
101
106
|
let options;
|
|
102
107
|
let request = new Request(
|
|
103
|
-
createFinalURL(schemaPath, { baseUrl: finalBaseUrl, params, querySerializer }),
|
|
108
|
+
createFinalURL(schemaPath, { baseUrl: finalBaseUrl, params, querySerializer, pathSerializer }),
|
|
104
109
|
requestInit
|
|
105
110
|
);
|
|
106
111
|
let response;
|
|
@@ -109,16 +114,17 @@ function createClient(clientOptions) {
|
|
|
109
114
|
request[key] = init[key];
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
|
-
if (
|
|
117
|
+
if (finalMiddlewares.length) {
|
|
113
118
|
id = randomID();
|
|
114
119
|
options = Object.freeze({
|
|
115
120
|
baseUrl: finalBaseUrl,
|
|
116
121
|
fetch,
|
|
117
122
|
parseAs,
|
|
118
123
|
querySerializer,
|
|
119
|
-
bodySerializer
|
|
124
|
+
bodySerializer,
|
|
125
|
+
pathSerializer
|
|
120
126
|
});
|
|
121
|
-
for (const m of
|
|
127
|
+
for (const m of finalMiddlewares) {
|
|
122
128
|
if (m && typeof m === "object" && typeof m.onRequest === "function") {
|
|
123
129
|
const result = await m.onRequest({
|
|
124
130
|
request,
|
|
@@ -145,9 +151,9 @@ function createClient(clientOptions) {
|
|
|
145
151
|
response = await fetch(request, requestInitExt);
|
|
146
152
|
} catch (error2) {
|
|
147
153
|
let errorAfterMiddleware = error2;
|
|
148
|
-
if (
|
|
149
|
-
for (let i =
|
|
150
|
-
const m =
|
|
154
|
+
if (finalMiddlewares.length) {
|
|
155
|
+
for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
156
|
+
const m = finalMiddlewares[i];
|
|
151
157
|
if (m && typeof m === "object" && typeof m.onError === "function") {
|
|
152
158
|
const result = await m.onError({
|
|
153
159
|
request,
|
|
@@ -176,9 +182,9 @@ function createClient(clientOptions) {
|
|
|
176
182
|
throw errorAfterMiddleware;
|
|
177
183
|
}
|
|
178
184
|
}
|
|
179
|
-
if (
|
|
180
|
-
for (let i =
|
|
181
|
-
const m =
|
|
185
|
+
if (finalMiddlewares.length) {
|
|
186
|
+
for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
187
|
+
const m = finalMiddlewares[i];
|
|
182
188
|
if (m && typeof m === "object" && typeof m.onResponse === "function") {
|
|
183
189
|
const result = await m.onResponse({
|
|
184
190
|
request,
|
|
@@ -198,14 +204,22 @@ function createClient(clientOptions) {
|
|
|
198
204
|
}
|
|
199
205
|
}
|
|
200
206
|
}
|
|
201
|
-
|
|
207
|
+
const contentLength = response.headers.get("Content-Length");
|
|
208
|
+
if (response.status === 204 || request.method === "HEAD" || contentLength === "0" && !response.headers.get("Transfer-Encoding")?.includes("chunked")) {
|
|
202
209
|
return response.ok ? { data: void 0, response } : { error: void 0, response };
|
|
203
210
|
}
|
|
204
211
|
if (response.ok) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
212
|
+
const getResponseData = async () => {
|
|
213
|
+
if (parseAs === "stream") {
|
|
214
|
+
return response.body;
|
|
215
|
+
}
|
|
216
|
+
if (parseAs === "json" && !contentLength) {
|
|
217
|
+
const raw = await response.text();
|
|
218
|
+
return raw ? JSON.parse(raw) : void 0;
|
|
219
|
+
}
|
|
220
|
+
return await response[parseAs]();
|
|
221
|
+
};
|
|
222
|
+
return { data: await getResponseData(), response };
|
|
209
223
|
}
|
|
210
224
|
let error = await response.text();
|
|
211
225
|
try {
|
|
@@ -259,15 +273,15 @@ function createClient(clientOptions) {
|
|
|
259
273
|
if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) {
|
|
260
274
|
throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
|
|
261
275
|
}
|
|
262
|
-
|
|
276
|
+
globalMiddlewares.push(m);
|
|
263
277
|
}
|
|
264
278
|
},
|
|
265
279
|
/** Unregister middleware */
|
|
266
280
|
eject(...middleware) {
|
|
267
281
|
for (const m of middleware) {
|
|
268
|
-
const i =
|
|
282
|
+
const i = globalMiddlewares.indexOf(m);
|
|
269
283
|
if (i !== -1) {
|
|
270
|
-
|
|
284
|
+
globalMiddlewares.splice(i, 1);
|
|
271
285
|
}
|
|
272
286
|
}
|
|
273
287
|
}
|
|
@@ -448,7 +462,7 @@ function defaultBodySerializer(body, headers) {
|
|
|
448
462
|
function createFinalURL(pathname, options) {
|
|
449
463
|
let finalURL = `${options.baseUrl}${pathname}`;
|
|
450
464
|
if (options.params?.path) {
|
|
451
|
-
finalURL =
|
|
465
|
+
finalURL = options.pathSerializer(finalURL, options.params.path);
|
|
452
466
|
}
|
|
453
467
|
let search = options.querySerializer(options.params.query ?? {});
|
|
454
468
|
if (search.startsWith("?")) {
|