@resira/sdk 0.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 +179 -0
- package/dist/index.cjs +556 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +662 -0
- package/dist/index.d.ts +662 -0
- package/dist/index.js +550 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @resira/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the Resira public reservation API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @resira/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Resira } from "@resira/sdk";
|
|
15
|
+
|
|
16
|
+
const resira = new Resira({
|
|
17
|
+
apiKey: "resira_live_your_api_key_here",
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## API reference
|
|
22
|
+
|
|
23
|
+
### `new Resira(config)`
|
|
24
|
+
|
|
25
|
+
| Option | Type | Default | Description |
|
|
26
|
+
| ---------------- | ---------- | --------------------------- | ------------------------------------------------- |
|
|
27
|
+
| `apiKey` | `string` | **(required)** | API key (`resira_live_…`) |
|
|
28
|
+
| `baseUrl` | `string` | `https://api.resira.io` | Base URL of the API |
|
|
29
|
+
| `maxRetries` | `number` | `3` | Max retry attempts for 429 / 5xx |
|
|
30
|
+
| `retryBaseDelay` | `number` | `500` | Base delay (ms) for exponential backoff |
|
|
31
|
+
| `fetch` | `function` | `globalThis.fetch` | Custom fetch implementation |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### `resira.getAvailability(resourceId, params?)`
|
|
36
|
+
|
|
37
|
+
Query availability for a resource.
|
|
38
|
+
|
|
39
|
+
**Property (date-based):**
|
|
40
|
+
```typescript
|
|
41
|
+
const avail = await resira.getAvailability("prop-1", {
|
|
42
|
+
startDate: "2026-07-01",
|
|
43
|
+
endDate: "2026-07-07",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(avail.dates?.available); // true
|
|
47
|
+
console.log(avail.dates?.totalPrice); // 85000 (cents)
|
|
48
|
+
console.log(avail.dates?.blockedDates); // ["2026-07-15", …]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Restaurant (time-slot):**
|
|
52
|
+
```typescript
|
|
53
|
+
const avail = await resira.getAvailability("table-5", {
|
|
54
|
+
date: "2026-07-01",
|
|
55
|
+
partySize: 4,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
for (const slot of avail.timeSlots ?? []) {
|
|
59
|
+
console.log(`${slot.start} → ${slot.end}: ${slot.remaining} seats`);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### `resira.createReservation(payload, options?)`
|
|
66
|
+
|
|
67
|
+
Create a reservation. The `resourceId` is included in the request body.
|
|
68
|
+
An `Idempotency-Key` header is automatically generated to prevent
|
|
69
|
+
duplicate bookings on retries.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const { reservation } = await resira.createReservation({
|
|
73
|
+
resourceId: "prop-1",
|
|
74
|
+
guestName: "Jane Doe",
|
|
75
|
+
guestEmail: "jane@example.com",
|
|
76
|
+
startDate: "2026-07-01",
|
|
77
|
+
endDate: "2026-07-07",
|
|
78
|
+
partySize: 3,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
console.log(reservation.id); // "uuid-…"
|
|
82
|
+
console.log(reservation.status); // "pending"
|
|
83
|
+
console.log(reservation.totalPrice);// 85000
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Custom idempotency key:**
|
|
87
|
+
```typescript
|
|
88
|
+
const { reservation } = await resira.createReservation(
|
|
89
|
+
payload,
|
|
90
|
+
{ idempotencyKey: "form-submit-abc123" },
|
|
91
|
+
);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### `resira.listReservations(resourceId, params?)`
|
|
97
|
+
|
|
98
|
+
List reservations (paginated).
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const page = await resira.listReservations("prop-1", {
|
|
102
|
+
status: "confirmed",
|
|
103
|
+
page: 1,
|
|
104
|
+
limit: 50,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log(page.data); // Reservation[]
|
|
108
|
+
console.log(page.total); // 142
|
|
109
|
+
console.log(page.totalPages); // 3
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### `resira.getReservation(resourceId, reservationId)`
|
|
115
|
+
|
|
116
|
+
Get a single reservation by ID.
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const { reservation } = await resira.getReservation("prop-1", "res-uuid");
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Error handling
|
|
125
|
+
|
|
126
|
+
All errors extend `ResiraError`. Use `instanceof` to discriminate:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import {
|
|
130
|
+
Resira,
|
|
131
|
+
ResiraApiError,
|
|
132
|
+
ResiraRateLimitError,
|
|
133
|
+
ResiraNetworkError,
|
|
134
|
+
} from "@resira/sdk";
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await resira.createReservation(payload);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (error instanceof ResiraRateLimitError) {
|
|
140
|
+
// 429 — SDK already retried `maxRetries` times
|
|
141
|
+
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
|
|
142
|
+
} else if (error instanceof ResiraApiError) {
|
|
143
|
+
// 4xx / 5xx
|
|
144
|
+
console.log(`${error.status}: ${error.message}`);
|
|
145
|
+
console.log(error.retryable); // true for 5xx
|
|
146
|
+
} else if (error instanceof ResiraNetworkError) {
|
|
147
|
+
// DNS / TLS / offline
|
|
148
|
+
console.log("Network error:", error.message);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
| Error class | When | Retried automatically? |
|
|
154
|
+
| ---------------------- | ----------------------------- | ---------------------- |
|
|
155
|
+
| `ResiraRateLimitError` | 429 Too Many Requests | ✓ (respects Retry-After) |
|
|
156
|
+
| `ResiraApiError` | Any non-2xx | ✓ for 5xx only |
|
|
157
|
+
| `ResiraNetworkError` | fetch failed (DNS, offline…) | ✓ |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Retry behaviour
|
|
162
|
+
|
|
163
|
+
The SDK retries failed requests with **exponential backoff + jitter**:
|
|
164
|
+
|
|
165
|
+
- **Attempt 1**: 0 – 500 ms
|
|
166
|
+
- **Attempt 2**: 0 – 1 000 ms
|
|
167
|
+
- **Attempt 3**: 0 – 2 000 ms
|
|
168
|
+
|
|
169
|
+
For 429 responses, the `Retry-After` header value is used as a minimum delay.
|
|
170
|
+
|
|
171
|
+
Idempotency keys ensure that retried POST requests don't create
|
|
172
|
+
duplicate reservations.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Requirements
|
|
177
|
+
|
|
178
|
+
- Node.js ≥ 18 (uses native `fetch`)
|
|
179
|
+
- No runtime dependencies
|