recal-sdk 0.3.2 → 1.0.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 +24 -792
- package/dist/client/client/client.gen.d.ts +3 -0
- package/dist/client/client/client.gen.d.ts.map +1 -0
- package/dist/client/client/client.gen.js +205 -0
- package/dist/client/client/client.gen.js.map +1 -0
- package/dist/client/client/index.d.ts +9 -0
- package/dist/client/client/index.d.ts.map +1 -0
- package/dist/client/client/index.js +7 -0
- package/dist/client/client/index.js.map +1 -0
- package/dist/client/client/types.gen.d.ts +125 -0
- package/dist/client/client/types.gen.d.ts.map +1 -0
- package/dist/client/client/types.gen.js +3 -0
- package/dist/client/client/types.gen.js.map +1 -0
- package/dist/client/client/utils.gen.d.ts +34 -0
- package/dist/client/client/utils.gen.d.ts.map +1 -0
- package/dist/client/client/utils.gen.js +232 -0
- package/dist/client/client/utils.gen.js.map +1 -0
- package/dist/client/client.gen.d.ts +13 -0
- package/dist/client/client.gen.d.ts.map +1 -0
- package/dist/client/client.gen.js +6 -0
- package/dist/client/client.gen.js.map +1 -0
- package/dist/client/core/auth.gen.d.ts +19 -0
- package/dist/client/core/auth.gen.d.ts.map +1 -0
- package/dist/client/core/auth.gen.js +15 -0
- package/dist/client/core/auth.gen.js.map +1 -0
- package/dist/client/core/bodySerializer.gen.d.ts +26 -0
- package/dist/client/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/client/core/bodySerializer.gen.js +58 -0
- package/dist/client/core/bodySerializer.gen.js.map +1 -0
- package/dist/client/core/params.gen.d.ts +34 -0
- package/dist/client/core/params.gen.d.ts.map +1 -0
- package/dist/client/core/params.gen.js +89 -0
- package/dist/client/core/params.gen.js.map +1 -0
- package/dist/client/core/pathSerializer.gen.d.ts +34 -0
- package/dist/client/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/client/core/pathSerializer.gen.js +115 -0
- package/dist/client/core/pathSerializer.gen.js.map +1 -0
- package/dist/client/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/client/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/client/core/queryKeySerializer.gen.js +100 -0
- package/dist/client/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/client/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/client/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/client/core/serverSentEvents.gen.js +136 -0
- package/dist/client/core/serverSentEvents.gen.js.map +1 -0
- package/dist/client/core/types.gen.d.ts +79 -0
- package/dist/client/core/types.gen.d.ts.map +1 -0
- package/dist/client/core/types.gen.js +3 -0
- package/dist/client/core/types.gen.js.map +1 -0
- package/dist/client/core/utils.gen.d.ts +20 -0
- package/dist/client/core/utils.gen.d.ts.map +1 -0
- package/dist/client/core/utils.gen.js +88 -0
- package/dist/client/core/utils.gen.js.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/sdk.gen.d.ts +170 -0
- package/dist/client/sdk.gen.d.ts.map +1 -0
- package/dist/client/sdk.gen.js +884 -0
- package/dist/client/sdk.gen.js.map +1 -0
- package/dist/client/transformers.gen.d.ts +31 -0
- package/dist/client/transformers.gen.d.ts.map +1 -0
- package/dist/client/transformers.gen.js +263 -0
- package/dist/client/transformers.gen.js.map +1 -0
- package/dist/client/types.gen.d.ts +1765 -0
- package/dist/client/types.gen.d.ts.map +1 -0
- package/dist/client/types.gen.js +3 -0
- package/dist/client/types.gen.js.map +1 -0
- package/dist/client/zod.gen.d.ts +1457 -0
- package/dist/client/zod.gen.d.ts.map +1 -0
- package/dist/client/zod.gen.js +1214 -0
- package/dist/client/zod.gen.js.map +1 -0
- package/dist/index.d.ts +5 -33
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -55
- package/dist/index.js.map +1 -1
- package/dist/recal.d.ts +64 -0
- package/dist/recal.d.ts.map +1 -0
- package/dist/recal.js +81 -0
- package/dist/recal.js.map +1 -0
- package/dist/services/calendar.service.d.ts +55 -167
- package/dist/services/calendar.service.d.ts.map +1 -1
- package/dist/services/calendar.service.js +68 -301
- package/dist/services/calendar.service.js.map +1 -1
- package/dist/services/events.service.d.ts +167 -0
- package/dist/services/events.service.d.ts.map +1 -0
- package/dist/services/events.service.js +215 -0
- package/dist/services/events.service.js.map +1 -0
- package/dist/services/oauth.service.d.ts +123 -60
- package/dist/services/oauth.service.d.ts.map +1 -1
- package/dist/services/oauth.service.js +166 -142
- package/dist/services/oauth.service.js.map +1 -1
- package/dist/services/organizations.service.d.ts +137 -36
- package/dist/services/organizations.service.d.ts.map +1 -1
- package/dist/services/organizations.service.js +164 -90
- package/dist/services/organizations.service.js.map +1 -1
- package/dist/services/scheduling.service.d.ts +121 -58
- package/dist/services/scheduling.service.d.ts.map +1 -1
- package/dist/services/scheduling.service.js +98 -140
- package/dist/services/scheduling.service.js.map +1 -1
- package/dist/services/users.service.d.ts +87 -27
- package/dist/services/users.service.d.ts.map +1 -1
- package/dist/services/users.service.js +94 -69
- package/dist/services/users.service.js.map +1 -1
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/response.d.ts +33 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +54 -0
- package/dist/utils/response.js.map +1 -0
- package/package.json +5 -2
- package/dist/entities/organization.d.ts +0 -21
- package/dist/entities/organization.d.ts.map +0 -1
- package/dist/entities/organization.js +0 -32
- package/dist/entities/organization.js.map +0 -1
- package/dist/entities/user.d.ts +0 -23
- package/dist/entities/user.d.ts.map +0 -1
- package/dist/entities/user.js +0 -45
- package/dist/entities/user.js.map +0 -1
- package/dist/errors.d.ts +0 -22
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -36
- package/dist/errors.js.map +0 -1
- package/dist/typebox/calendar.tb.d.ts +0 -113
- package/dist/typebox/calendar.tb.d.ts.map +0 -1
- package/dist/typebox/calendar.tb.js +0 -92
- package/dist/typebox/calendar.tb.js.map +0 -1
- package/dist/typebox/oauth.tb.d.ts +0 -14
- package/dist/typebox/oauth.tb.d.ts.map +0 -1
- package/dist/typebox/oauth.tb.js +0 -16
- package/dist/typebox/oauth.tb.js.map +0 -1
- package/dist/typebox/organization.stripped.tb.d.ts +0 -6
- package/dist/typebox/organization.stripped.tb.d.ts.map +0 -1
- package/dist/typebox/organization.stripped.tb.js +0 -7
- package/dist/typebox/organization.stripped.tb.js.map +0 -1
- package/dist/typebox/organization.tb.d.ts +0 -10
- package/dist/typebox/organization.tb.d.ts.map +0 -1
- package/dist/typebox/organization.tb.js +0 -8
- package/dist/typebox/organization.tb.js.map +0 -1
- package/dist/typebox/scheduling.tb.d.ts +0 -107
- package/dist/typebox/scheduling.tb.d.ts.map +0 -1
- package/dist/typebox/scheduling.tb.js +0 -105
- package/dist/typebox/scheduling.tb.js.map +0 -1
- package/dist/typebox/timeString.tb.d.ts +0 -3
- package/dist/typebox/timeString.tb.d.ts.map +0 -1
- package/dist/typebox/timeString.tb.js +0 -7
- package/dist/typebox/timeString.tb.js.map +0 -1
- package/dist/typebox/user.stripped.tb.d.ts +0 -5
- package/dist/typebox/user.stripped.tb.d.ts.map +0 -1
- package/dist/typebox/user.stripped.tb.js +0 -6
- package/dist/typebox/user.stripped.tb.js.map +0 -1
- package/dist/typebox/user.tb.d.ts +0 -19
- package/dist/typebox/user.tb.d.ts.map +0 -1
- package/dist/typebox/user.tb.js +0 -10
- package/dist/typebox/user.tb.js.map +0 -1
- package/dist/types/calendar.types.d.ts +0 -124
- package/dist/types/calendar.types.d.ts.map +0 -1
- package/dist/types/calendar.types.js +0 -27
- package/dist/types/calendar.types.js.map +0 -1
- package/dist/types/internal.types.d.ts +0 -7
- package/dist/types/internal.types.d.ts.map +0 -1
- package/dist/types/internal.types.js +0 -2
- package/dist/types/internal.types.js.map +0 -1
- package/dist/types/oauth.types.d.ts +0 -22
- package/dist/types/oauth.types.d.ts.map +0 -1
- package/dist/types/oauth.types.js +0 -2
- package/dist/types/oauth.types.js.map +0 -1
- package/dist/types/organization.types.d.ts +0 -18
- package/dist/types/organization.types.d.ts.map +0 -1
- package/dist/types/organization.types.js +0 -2
- package/dist/types/organization.types.js.map +0 -1
- package/dist/types/scheduling.types.d.ts +0 -50
- package/dist/types/scheduling.types.d.ts.map +0 -1
- package/dist/types/scheduling.types.js +0 -2
- package/dist/types/scheduling.types.js.map +0 -1
- package/dist/types/user.types.d.ts +0 -11
- package/dist/types/user.types.d.ts.map +0 -1
- package/dist/types/user.types.js +0 -2
- package/dist/types/user.types.js.map +0 -1
- package/dist/utils/fetch.helper.d.ts +0 -62
- package/dist/utils/fetch.helper.d.ts.map +0 -1
- package/dist/utils/fetch.helper.js +0 -116
- package/dist/utils/fetch.helper.js.map +0 -1
- package/dist/utils/fetchErrorHandler.d.ts +0 -22
- package/dist/utils/fetchErrorHandler.d.ts.map +0 -1
- package/dist/utils/fetchErrorHandler.js +0 -35
- package/dist/utils/fetchErrorHandler.js.map +0 -1
- package/dist/utils/includes.helper.d.ts +0 -4
- package/dist/utils/includes.helper.d.ts.map +0 -1
- package/dist/utils/includes.helper.js +0 -10
- package/dist/utils/includes.helper.js.map +0 -1
- package/dist/utils/omit.d.ts +0 -2
- package/dist/utils/omit.d.ts.map +0 -1
- package/dist/utils/omit.js +0 -4
- package/dist/utils/omit.js.map +0 -1
package/README.md
CHANGED
|
@@ -59,781 +59,11 @@ The SDK is organized into logical service modules:
|
|
|
59
59
|
- **`organizations`** - Team and organization management
|
|
60
60
|
- **`oauth`** - Calendar provider authentication
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
## Documentation
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
Full documentation for the SDK, including usage, API schemas, and integration guides, is available at [docs.recal.dev](https://docs.recal.dev). Refer to the official docs for up-to-date examples and advanced configuration options.
|
|
65
65
|
|
|
66
|
-
## API Reference
|
|
67
66
|
|
|
68
|
-
> TypeScript note
|
|
69
|
-
>
|
|
70
|
-
> - Use the exported `Provider` enum for provider arguments.
|
|
71
|
-
> - Date/time fields in responses are parsed into `Date` objects at runtime.
|
|
72
|
-
>
|
|
73
|
-
> ```typescript
|
|
74
|
-
> import { Provider } from 'recal-sdk'
|
|
75
|
-
> ```
|
|
76
|
-
|
|
77
|
-
### Calendar Service
|
|
78
|
-
|
|
79
|
-
#### List Calendars
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
// Get all calendars for a user
|
|
83
|
-
const calendars = await recal.calendar.listCalendars('user_id')
|
|
84
|
-
|
|
85
|
-
// Or filter by provider
|
|
86
|
-
const googleCalendars = await recal.calendar.listCalendars(
|
|
87
|
-
'user_id',
|
|
88
|
-
'google' // optional: filter by provider
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
// Or filter by multiple providers
|
|
92
|
-
const multiProviderCalendars = await recal.calendar.listCalendars(
|
|
93
|
-
'user_id',
|
|
94
|
-
['google', 'microsoft'] // optional: filter by multiple providers
|
|
95
|
-
)
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
#### Get Busy Information
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
// Get user's availability (simplest form)
|
|
102
|
-
const busy = await recal.calendar.getBusy(
|
|
103
|
-
'user_id',
|
|
104
|
-
new Date('2024-01-01'),
|
|
105
|
-
new Date('2024-01-07')
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
// Or with optional filters
|
|
109
|
-
const busyFiltered = await recal.calendar.getBusy(
|
|
110
|
-
'user_id',
|
|
111
|
-
new Date('2024-01-01'),
|
|
112
|
-
new Date('2024-01-07'),
|
|
113
|
-
{
|
|
114
|
-
provider: 'google', // optional: filter by provider
|
|
115
|
-
calendarIds: ["calendar_id"] // optional: filter by calendarIds
|
|
116
|
-
timeZone: 'America/New_York', // optional: timezone
|
|
117
|
-
}
|
|
118
|
-
)
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
#### List Events
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
// Get all events in a date range (simplest form)
|
|
125
|
-
const events = await recal.calendar.getEvents(
|
|
126
|
-
'user_id',
|
|
127
|
-
new Date('2024-01-01'),
|
|
128
|
-
new Date('2024-01-31')
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
// Or with optional filters
|
|
132
|
-
const eventsFiltered = await recal.calendar.getEvents(
|
|
133
|
-
'user_id',
|
|
134
|
-
new Date('2024-01-01'),
|
|
135
|
-
new Date('2024-01-31'),
|
|
136
|
-
{
|
|
137
|
-
provider: 'google', // optional: filter by provider
|
|
138
|
-
calendarIds: ["calendar_id"] // optional: filter by calendarIds
|
|
139
|
-
timeZone: 'Europe/London' // optional: timezone
|
|
140
|
-
}
|
|
141
|
-
)
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
#### Create Event
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
// Create a new event (without optional timezone)
|
|
148
|
-
const event = await recal.calendar.createEvent({
|
|
149
|
-
userId: 'user_id',
|
|
150
|
-
provider: 'google',
|
|
151
|
-
calendarId: 'calendar_id',
|
|
152
|
-
event: {
|
|
153
|
-
subject: 'Team Meeting',
|
|
154
|
-
description: 'Weekly sync',
|
|
155
|
-
start: new Date('2024-01-15T10:00:00Z'),
|
|
156
|
-
end: new Date('2024-01-15T11:00:00Z'),
|
|
157
|
-
attendees: [
|
|
158
|
-
{ email: 'colleague@company.com' }
|
|
159
|
-
]
|
|
160
|
-
}
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
// Or with timezone option
|
|
164
|
-
const eventWithTZ = await recal.calendar.createEvent({
|
|
165
|
-
userId: 'user_id',
|
|
166
|
-
provider: 'google',
|
|
167
|
-
calendarId: 'calendar_id',
|
|
168
|
-
event: {
|
|
169
|
-
subject: 'Team Meeting',
|
|
170
|
-
description: 'Weekly sync',
|
|
171
|
-
start: new Date('2024-01-15T10:00:00Z'),
|
|
172
|
-
end: new Date('2024-01-15T11:00:00Z'),
|
|
173
|
-
attendees: [
|
|
174
|
-
{ email: 'colleague@company.com' }
|
|
175
|
-
]
|
|
176
|
-
},
|
|
177
|
-
options: { timeZone: 'Europe/Berlin' } // optional
|
|
178
|
-
})
|
|
179
|
-
```
|
|
180
|
-
#### Get Event
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
// Get an existing event
|
|
184
|
-
const event = await recal.calendar.getEvent({
|
|
185
|
-
userId: 'user_id',
|
|
186
|
-
provider: 'google',
|
|
187
|
-
calendarId: 'calendar_id',
|
|
188
|
-
eventId: 'event_id',
|
|
189
|
-
options: { timeZone: 'Europe/Berlin' } // optional
|
|
190
|
-
})
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
#### Update Event
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
// Update an existing event (simplest form)
|
|
197
|
-
const updated = await recal.calendar.updateEvent({
|
|
198
|
-
userId: 'user_id',
|
|
199
|
-
provider: 'google',
|
|
200
|
-
calendarId: 'calendar_id',
|
|
201
|
-
eventId: 'event_id',
|
|
202
|
-
event: {
|
|
203
|
-
subject: 'Updated Meeting Title',
|
|
204
|
-
start: new Date('2024-01-15T14:00:00Z'),
|
|
205
|
-
end: new Date('2024-01-15T15:00:00Z')
|
|
206
|
-
}
|
|
207
|
-
})
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
// or with more options
|
|
212
|
-
const updated = await recal.calendar.updateEvent({
|
|
213
|
-
userId: 'user_id',
|
|
214
|
-
provider: 'google',
|
|
215
|
-
calendarId: 'calendar_id',
|
|
216
|
-
eventId: 'event_id',
|
|
217
|
-
event: {
|
|
218
|
-
subject: 'Updated Meeting title',
|
|
219
|
-
description: 'Updated description',
|
|
220
|
-
start: new Date('2024-01-15T11:00:00Z'),
|
|
221
|
-
end: new Date('2024-01-15T12:00:00Z'),
|
|
222
|
-
attendees: [
|
|
223
|
-
{ email: 'colleague@company.com' }
|
|
224
|
-
]
|
|
225
|
-
},
|
|
226
|
-
options: { timeZone: 'Europe/Berlin' } // optional
|
|
227
|
-
})
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
#### Delete Event
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
// Delete an event
|
|
234
|
-
await recal.calendar.deleteEvent({
|
|
235
|
-
userId: 'user_id',
|
|
236
|
-
provider: 'google',
|
|
237
|
-
calendarId: 'calendar_id',
|
|
238
|
-
eventId: 'event_id'
|
|
239
|
-
})
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
#### Cross-Calendar Operations (Meta Events)
|
|
243
|
-
|
|
244
|
-
Meta events allow you to work with events across multiple calendar providers:
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
// Create event across all connected calendars (default behavior)
|
|
248
|
-
const metaEvent = await recal.calendar.createEventByMetaId(
|
|
249
|
-
'user_id',
|
|
250
|
-
{
|
|
251
|
-
subject: 'Cross-platform meeting',
|
|
252
|
-
start: new Date('2024-01-20T15:00:00Z'),
|
|
253
|
-
end: new Date('2024-01-20T16:00:00Z')
|
|
254
|
-
}
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
// Or specify which providers and timezone to use
|
|
258
|
-
const metaEventSpecific = await recal.calendar.createEventByMetaId(
|
|
259
|
-
'user_id',
|
|
260
|
-
{
|
|
261
|
-
subject: 'Cross-platform meeting',
|
|
262
|
-
start: new Date('2024-01-20T15:00:00Z'),
|
|
263
|
-
end: new Date('2024-01-20T16:00:00Z')
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
provider: ['google', 'microsoft'], // Create on specific providers
|
|
267
|
-
timeZone: 'Europe/Berlin' // optional
|
|
268
|
-
}
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
// Get event across all connected calendars (default behavior)
|
|
272
|
-
const metaEventGet = await recal.calendar.getEventByMetaId(
|
|
273
|
-
'user_id',
|
|
274
|
-
metaEvent.metaId
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
// Update across all calendars using meta ID
|
|
278
|
-
await recal.calendar.updateEventByMetaId(
|
|
279
|
-
'user_id',
|
|
280
|
-
metaEvent.metaId,
|
|
281
|
-
{ subject: 'Updated title' }
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
// Delete from all calendars
|
|
285
|
-
await recal.calendar.deleteEventByMetaId(
|
|
286
|
-
'user_id',
|
|
287
|
-
metaEvent.metaId
|
|
288
|
-
)
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
### Scheduling Service
|
|
292
|
-
|
|
293
|
-
#### Get User Availability (Basic)
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
// Find available time slots (minimal config)
|
|
297
|
-
const availability = await recal.scheduling.user(
|
|
298
|
-
'user_id',
|
|
299
|
-
new Date('2024-01-15'),
|
|
300
|
-
new Date('2024-01-20'),
|
|
301
|
-
{
|
|
302
|
-
slotDuration: 30 // Only required: slot duration in minutes
|
|
303
|
-
}
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
// Or with more options
|
|
307
|
-
const availabilityDetailed = await recal.scheduling.user(
|
|
308
|
-
'user_id',
|
|
309
|
-
new Date('2024-01-15'),
|
|
310
|
-
new Date('2024-01-20'),
|
|
311
|
-
{
|
|
312
|
-
slotDuration: 30, // Duration of each slot in minutes
|
|
313
|
-
padding: 0, // Padding between slots
|
|
314
|
-
earliestTimeEachDay: '09:00', // Format: HH:mm
|
|
315
|
-
latestTimeEachDay: '17:00', // Format: HH:mm
|
|
316
|
-
provider: 'google', // optional: filter by provider
|
|
317
|
-
timeZone: 'America/New_York' // optional
|
|
318
|
-
}
|
|
319
|
-
)
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
#### Allow Overlapping Events
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
// Find availability even when user already has events scheduled
|
|
326
|
-
const availabilityWithOverlaps = await recal.scheduling.user(
|
|
327
|
-
'user_id',
|
|
328
|
-
new Date('2024-01-15'),
|
|
329
|
-
new Date('2024-01-20'),
|
|
330
|
-
{
|
|
331
|
-
slotDuration: 30,
|
|
332
|
-
maxOverlaps: 2, // Allow up to 2 overlapping events per slot
|
|
333
|
-
timeZone: 'America/New_York'
|
|
334
|
-
}
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
// maxOverlaps: 2, means 1 slot is still available even if the user has 2 existing events at the same time.
|
|
338
|
-
// This enables booking a n concurrent events - useful for optional meetings,
|
|
339
|
-
// tentative invites, or users who can handle multiple events simultaneous, like a team that has just one calendar.
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
#### Get User Availability (Advanced)
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
// Find available time slots with custom schedules
|
|
346
|
-
const schedules = [
|
|
347
|
-
{
|
|
348
|
-
days: ['monday'], // Monday
|
|
349
|
-
start: '09:00',
|
|
350
|
-
end: '17:00'
|
|
351
|
-
},
|
|
352
|
-
// ... more schedule rules
|
|
353
|
-
]
|
|
354
|
-
|
|
355
|
-
// Minimal config
|
|
356
|
-
const availability = await recal.scheduling.userAdvanced(
|
|
357
|
-
'user_id',
|
|
358
|
-
schedules,
|
|
359
|
-
new Date('2024-01-15'),
|
|
360
|
-
new Date('2024-01-20'),
|
|
361
|
-
{ slotDuration: 30 } // Only required option
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
// Or with more options
|
|
365
|
-
const availabilityDetailed = await recal.scheduling.userAdvanced(
|
|
366
|
-
'user_id',
|
|
367
|
-
schedules,
|
|
368
|
-
new Date('2024-01-15'),
|
|
369
|
-
new Date('2024-01-20'),
|
|
370
|
-
{
|
|
371
|
-
slotDuration: 30,
|
|
372
|
-
padding: 15,
|
|
373
|
-
provider: 'google', // optional
|
|
374
|
-
timeZone: 'America/New_York' // optional
|
|
375
|
-
}
|
|
376
|
-
)
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
#### Get Organization-Wide Availability
|
|
380
|
-
|
|
381
|
-
```typescript
|
|
382
|
-
// Find organization-wide available time slots (minimal)
|
|
383
|
-
const orgAvailability = await recal.scheduling.organization(
|
|
384
|
-
'org-slug',
|
|
385
|
-
new Date('2024-01-15'),
|
|
386
|
-
new Date('2024-01-20'),
|
|
387
|
-
{ slotDuration: 60 } // Only required option
|
|
388
|
-
)
|
|
389
|
-
|
|
390
|
-
// Or with constraints
|
|
391
|
-
const orgAvailabilityConstrained = await recal.scheduling.organization(
|
|
392
|
-
'org-slug',
|
|
393
|
-
new Date('2024-01-15'),
|
|
394
|
-
new Date('2024-01-20'),
|
|
395
|
-
{
|
|
396
|
-
slotDuration: 60,
|
|
397
|
-
padding: 0,
|
|
398
|
-
earliestTimeEachDay: '09:00',
|
|
399
|
-
latestTimeEachDay: '17:00',
|
|
400
|
-
provider: ['google', 'microsoft'], // optional
|
|
401
|
-
timeZone: 'America/New_York' // optional
|
|
402
|
-
}
|
|
403
|
-
)
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
### Users Service
|
|
407
|
-
|
|
408
|
-
#### Get User
|
|
409
|
-
|
|
410
|
-
```typescript
|
|
411
|
-
// Get user information (basic)
|
|
412
|
-
const user = await recal.users.get('user_id', {})
|
|
413
|
-
|
|
414
|
-
// Or with additional data
|
|
415
|
-
const userWithDetails = await recal.users.get('user_id', {
|
|
416
|
-
includeOrgs: true, // Include organizations
|
|
417
|
-
includeOAuth: true // Include OAuth connections
|
|
418
|
-
})
|
|
419
|
-
console.log(user.id)
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
#### List All Users
|
|
423
|
-
|
|
424
|
-
```typescript
|
|
425
|
-
// Get all users
|
|
426
|
-
const users = await recal.users.listAll()
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
#### Create User
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
// Create a new user (without organizations)
|
|
433
|
-
const user = await recal.users.create('user_id')
|
|
434
|
-
|
|
435
|
-
// Or with organization memberships
|
|
436
|
-
const userWithOrgs = await recal.users.create(
|
|
437
|
-
'user_id',
|
|
438
|
-
['org-slug-1', 'org-slug-2'] // optional: organization slugs
|
|
439
|
-
)
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
#### Update User
|
|
443
|
-
|
|
444
|
-
```typescript
|
|
445
|
-
// Update user ID
|
|
446
|
-
const updatedUser = await recal.users.update('old_user_id', {
|
|
447
|
-
id: 'new_user_id'
|
|
448
|
-
})
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
#### Delete User
|
|
452
|
-
|
|
453
|
-
```typescript
|
|
454
|
-
// Delete a user
|
|
455
|
-
const deletedUser = await recal.users.delete('user_id')
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
### Organizations Service
|
|
459
|
-
|
|
460
|
-
#### Get Organization
|
|
461
|
-
|
|
462
|
-
```typescript
|
|
463
|
-
// Get organization by slug
|
|
464
|
-
const org = await recal.organizations.get('acme-corp')
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
#### List All Organizations
|
|
468
|
-
|
|
469
|
-
```typescript
|
|
470
|
-
// Get all organizations
|
|
471
|
-
const orgs = await recal.organizations.listAll()
|
|
472
|
-
|
|
473
|
-
// Get organizations for a specific user
|
|
474
|
-
const userOrgs = await recal.organizations.listAllFromUser('user_id')
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
#### Create Organization
|
|
478
|
-
|
|
479
|
-
```typescript
|
|
480
|
-
// Create a new organization
|
|
481
|
-
const org = await recal.organizations.create(
|
|
482
|
-
'acme-corp', // slug
|
|
483
|
-
'Acme Corporation' // name
|
|
484
|
-
)
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
#### Update Organization
|
|
488
|
-
|
|
489
|
-
```typescript
|
|
490
|
-
// Update organization
|
|
491
|
-
const updated = await recal.organizations.update('acme-corp', {
|
|
492
|
-
slug: 'new-slug',
|
|
493
|
-
name: 'New Name'
|
|
494
|
-
})
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
#### Manage Members
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
// Get all members
|
|
501
|
-
const members = await recal.organizations.getMembers('acme-corp')
|
|
502
|
-
|
|
503
|
-
// Add members
|
|
504
|
-
await recal.organizations.addMembers(
|
|
505
|
-
'acme-corp',
|
|
506
|
-
['user_id_1', 'user_id_2']
|
|
507
|
-
)
|
|
508
|
-
|
|
509
|
-
// Remove members
|
|
510
|
-
await recal.organizations.removeMembers(
|
|
511
|
-
'acme-corp',
|
|
512
|
-
['user_id_1', 'user_id_2']
|
|
513
|
-
)
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
#### Organization-Wide Busy
|
|
517
|
-
|
|
518
|
-
```typescript
|
|
519
|
-
// Get team availability (simplest form)
|
|
520
|
-
const teamBusy = await recal.calendar.getOrgWideBusy(
|
|
521
|
-
'acme-corp',
|
|
522
|
-
new Date('2024-01-15'),
|
|
523
|
-
new Date('2024-01-20'),
|
|
524
|
-
true // primaryOnly: only check primary calendars
|
|
525
|
-
)
|
|
526
|
-
|
|
527
|
-
// Or with optional filters
|
|
528
|
-
const teamBusyFiltered = await recal.calendar.getOrgWideBusy(
|
|
529
|
-
'acme-corp',
|
|
530
|
-
new Date('2024-01-15'),
|
|
531
|
-
new Date('2024-01-20'),
|
|
532
|
-
true, // primaryOnly: only check primary calendars
|
|
533
|
-
{
|
|
534
|
-
provider: 'google', // optional: filter by provider
|
|
535
|
-
timeZone: 'America/New_York' // optional
|
|
536
|
-
}
|
|
537
|
-
)
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
### OAuth Service
|
|
541
|
-
|
|
542
|
-
#### Get OAuth Link
|
|
543
|
-
|
|
544
|
-
```typescript
|
|
545
|
-
// Get OAuth authorization URL (with defaults)
|
|
546
|
-
const link = await recal.oauth.getLink(
|
|
547
|
-
'user_id',
|
|
548
|
-
'google'
|
|
549
|
-
)
|
|
550
|
-
|
|
551
|
-
// Or with custom options
|
|
552
|
-
const linkWithOptions = await recal.oauth.getLink(
|
|
553
|
-
'user_id',
|
|
554
|
-
'google',
|
|
555
|
-
{
|
|
556
|
-
scope: ['edit'], // 'edit' or 'free-busy' (for OAuth scopes)
|
|
557
|
-
accessType: 'offline', // 'offline' or 'online'
|
|
558
|
-
redirectUrl: 'https://app.example.com/callback' // optional
|
|
559
|
-
}
|
|
560
|
-
)
|
|
561
|
-
console.log(link.url) // Use this URL to redirect user
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
#### Get Multiple OAuth Links
|
|
565
|
-
|
|
566
|
-
```typescript
|
|
567
|
-
// Get OAuth URLs for all providers (simplest)
|
|
568
|
-
const links = await recal.oauth.getBulkLinks('user_id')
|
|
569
|
-
|
|
570
|
-
// Or with specific providers and options
|
|
571
|
-
const linksFiltered = await recal.oauth.getBulkLinks(
|
|
572
|
-
'user_id',
|
|
573
|
-
{
|
|
574
|
-
provider: ['google', 'microsoft'],
|
|
575
|
-
scope: ['edit'],
|
|
576
|
-
accessType: 'offline'
|
|
577
|
-
}
|
|
578
|
-
)
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
#### Manage OAuth Connections
|
|
582
|
-
|
|
583
|
-
```typescript
|
|
584
|
-
// Get all OAuth connections for a user
|
|
585
|
-
const connections = await recal.oauth.getAllConnections(
|
|
586
|
-
'user_id',
|
|
587
|
-
true // redacted (default: true)
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
// Get specific provider connection
|
|
591
|
-
const googleConnection = await recal.oauth.getConnection(
|
|
592
|
-
'user_id',
|
|
593
|
-
'google',
|
|
594
|
-
false // redacted
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
// Set OAuth tokens manually
|
|
598
|
-
const connection = await recal.oauth.setConnection(
|
|
599
|
-
'user_id',
|
|
600
|
-
'google',
|
|
601
|
-
{
|
|
602
|
-
accessToken: 'access_token',
|
|
603
|
-
refreshToken: 'refresh_token', // optional
|
|
604
|
-
scope: ['edit'],
|
|
605
|
-
expiresAt: new Date('2024-12-31'), // optional
|
|
606
|
-
email: 'user@example.com' // optional
|
|
607
|
-
}
|
|
608
|
-
)
|
|
609
|
-
|
|
610
|
-
// Disconnect a provider
|
|
611
|
-
await recal.oauth.disconnect('user_id', 'google')
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
#### Verify OAuth Callback
|
|
615
|
-
|
|
616
|
-
```typescript
|
|
617
|
-
// Verify OAuth code from callback
|
|
618
|
-
const result = await recal.oauth.verify(
|
|
619
|
-
'google',
|
|
620
|
-
'auth_code_from_callback',
|
|
621
|
-
['edit'], // 'edit' or 'free-busy' - single scope, not array
|
|
622
|
-
'state_parameter',
|
|
623
|
-
'https://app.example.com/callback' // optional
|
|
624
|
-
)
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
## Advanced Usage
|
|
628
|
-
|
|
629
|
-
### Error Handling
|
|
630
|
-
|
|
631
|
-
The SDK provides specific error types for different scenarios:
|
|
632
|
-
|
|
633
|
-
```typescript
|
|
634
|
-
import {
|
|
635
|
-
UserNotFoundError,
|
|
636
|
-
EventNotFoundError,
|
|
637
|
-
OAuthConnectionNotFoundError,
|
|
638
|
-
OrganizationNotFoundError
|
|
639
|
-
} from 'recal-sdk'
|
|
640
|
-
|
|
641
|
-
try {
|
|
642
|
-
const event = await recal.calendar.getEvent({
|
|
643
|
-
userId: 'user_id',
|
|
644
|
-
provider: 'google',
|
|
645
|
-
calendarId: 'calendar_id',
|
|
646
|
-
eventId: 'event_id'
|
|
647
|
-
})
|
|
648
|
-
} catch (error) {
|
|
649
|
-
if (error instanceof UserNotFoundError) {
|
|
650
|
-
console.log('User does not exist:', error.userId)
|
|
651
|
-
} else if (error instanceof EventNotFoundError) {
|
|
652
|
-
console.log('Event not found:', error.eventId)
|
|
653
|
-
} else if (error instanceof OAuthConnectionNotFoundError) {
|
|
654
|
-
console.log('Calendar not connected:', error.provider)
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
### Batch Operations
|
|
660
|
-
|
|
661
|
-
```typescript
|
|
662
|
-
// Process multiple users' calendars (simplest form)
|
|
663
|
-
const userIds = ['user1', 'user2', 'user3']
|
|
664
|
-
const allEvents = await Promise.all(
|
|
665
|
-
userIds.map(userId =>
|
|
666
|
-
recal.calendar.getEvents(
|
|
667
|
-
userId,
|
|
668
|
-
new Date('2024-01-01'),
|
|
669
|
-
new Date('2024-01-31')
|
|
670
|
-
)
|
|
671
|
-
)
|
|
672
|
-
)
|
|
673
|
-
```
|
|
674
|
-
|
|
675
|
-
### Working with Multiple Providers
|
|
676
|
-
|
|
677
|
-
```typescript
|
|
678
|
-
// Get all busy data (without filtering)
|
|
679
|
-
const startDate = new Date('2024-01-01')
|
|
680
|
-
const endDate = new Date('2024-01-31')
|
|
681
|
-
|
|
682
|
-
const allBusy = await recal.calendar.getBusy(
|
|
683
|
-
'user_id',
|
|
684
|
-
startDate,
|
|
685
|
-
endDate
|
|
686
|
-
)
|
|
687
|
-
|
|
688
|
-
// Or aggregate by specific providers
|
|
689
|
-
const providers: Provider[] = ['google', 'microsoft']
|
|
690
|
-
const busyTimes = await Promise.all(
|
|
691
|
-
providers.map(provider =>
|
|
692
|
-
recal.calendar.getBusy(
|
|
693
|
-
'user_id',
|
|
694
|
-
startDate,
|
|
695
|
-
endDate,
|
|
696
|
-
{ provider } // filter by specific provider
|
|
697
|
-
)
|
|
698
|
-
)
|
|
699
|
-
)
|
|
700
|
-
|
|
701
|
-
// Process the busy times as needed for your application
|
|
702
|
-
// Each element is Busy = TimeRange[]; flatten into a single array of TimeRange
|
|
703
|
-
const allBusyPeriods = busyTimes.flat()
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
### Custom Request Configuration
|
|
707
|
-
|
|
708
|
-
```typescript
|
|
709
|
-
// Use custom base URL
|
|
710
|
-
const recal = new RecalClient({
|
|
711
|
-
token: 'recal_token',
|
|
712
|
-
url: 'https://api.recal.dev' // optional, this is the default
|
|
713
|
-
})
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
## Examples
|
|
717
|
-
|
|
718
|
-
### Building a Booking System
|
|
719
|
-
|
|
720
|
-
```typescript
|
|
721
|
-
// 1. Check availability
|
|
722
|
-
const availability = await recal.scheduling.user(
|
|
723
|
-
'consultant_id',
|
|
724
|
-
new Date(),
|
|
725
|
-
new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // Next 7 days
|
|
726
|
-
{
|
|
727
|
-
slotDuration: 60, // 60-minute slots
|
|
728
|
-
padding: 15, // 15-minute padding between slots
|
|
729
|
-
earliestTimeEachDay: '09:00',
|
|
730
|
-
latestTimeEachDay: '17:00',
|
|
731
|
-
timeZone: 'America/New_York'
|
|
732
|
-
}
|
|
733
|
-
)
|
|
734
|
-
|
|
735
|
-
// 2. Display available slots to user
|
|
736
|
-
const availableSlots = availability.availableSlots // Already filtered for availability
|
|
737
|
-
|
|
738
|
-
// 3. User selects a slot and provides their information
|
|
739
|
-
const selectedSlot = availableSlots[0] // Example: first available slot
|
|
740
|
-
const clientName = 'John Doe'
|
|
741
|
-
const clientEmail = 'john@example.com'
|
|
742
|
-
|
|
743
|
-
// 4. Create an event for the selected slot (using calendar service)
|
|
744
|
-
const booking = await recal.calendar.createEvent({
|
|
745
|
-
userId: 'consultant_id',
|
|
746
|
-
provider: 'google',
|
|
747
|
-
calendarId: 'primary',
|
|
748
|
-
event: {
|
|
749
|
-
subject: 'Consultation with ' + clientName,
|
|
750
|
-
description: 'Initial consultation',
|
|
751
|
-
start: selectedSlot.start,
|
|
752
|
-
end: selectedSlot.end,
|
|
753
|
-
attendees: [{ email: clientEmail }]
|
|
754
|
-
}
|
|
755
|
-
})
|
|
756
|
-
|
|
757
|
-
// 5. Send confirmation
|
|
758
|
-
console.log('Booking confirmed:', booking.id)
|
|
759
|
-
```
|
|
760
|
-
|
|
761
|
-
### Syncing Calendars
|
|
762
|
-
|
|
763
|
-
```typescript
|
|
764
|
-
// Sync events between providers
|
|
765
|
-
async function syncCalendars(userId: string) {
|
|
766
|
-
// Get all events from all providers
|
|
767
|
-
const allEvents = await recal.calendar.getEvents(
|
|
768
|
-
userId,
|
|
769
|
-
new Date(),
|
|
770
|
-
new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)
|
|
771
|
-
)
|
|
772
|
-
|
|
773
|
-
// Or get events from Google only
|
|
774
|
-
const googleEvents = await recal.calendar.getEvents(
|
|
775
|
-
userId,
|
|
776
|
-
new Date(),
|
|
777
|
-
new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
|
|
778
|
-
{ provider: 'google' }
|
|
779
|
-
)
|
|
780
|
-
|
|
781
|
-
// Copy to Microsoft calendar
|
|
782
|
-
for (const event of googleEvents) {
|
|
783
|
-
if (!event.metaId) { // Not already synced
|
|
784
|
-
await recal.calendar.createEvent({
|
|
785
|
-
userId,
|
|
786
|
-
provider: 'microsoft',
|
|
787
|
-
calendarId: 'primary',
|
|
788
|
-
event: {
|
|
789
|
-
subject: event.subject,
|
|
790
|
-
description: event.description,
|
|
791
|
-
start: event.start,
|
|
792
|
-
end: event.end,
|
|
793
|
-
attendees: event.attendees
|
|
794
|
-
}
|
|
795
|
-
})
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
```
|
|
800
|
-
|
|
801
|
-
### Team Scheduling
|
|
802
|
-
|
|
803
|
-
```typescript
|
|
804
|
-
// Find time when entire team is available
|
|
805
|
-
async function findTeamSlot(
|
|
806
|
-
orgSlug: string,
|
|
807
|
-
duration: number,
|
|
808
|
-
startDate: Date,
|
|
809
|
-
endDate: Date
|
|
810
|
-
) {
|
|
811
|
-
// Option 1: Get raw busy times for manual processing
|
|
812
|
-
const busyTimes = await recal.calendar.getOrgWideBusy(
|
|
813
|
-
orgSlug,
|
|
814
|
-
startDate,
|
|
815
|
-
endDate,
|
|
816
|
-
true // Only check primary calendars
|
|
817
|
-
)
|
|
818
|
-
// Process busyTimes array to find gaps for your needs
|
|
819
|
-
|
|
820
|
-
// Option 2: Use the scheduling service (recommended)
|
|
821
|
-
const availability = await recal.scheduling.getOrgWideAvailability(
|
|
822
|
-
orgSlug,
|
|
823
|
-
startDate,
|
|
824
|
-
endDate,
|
|
825
|
-
{
|
|
826
|
-
slotDuration: duration,
|
|
827
|
-
padding: 0,
|
|
828
|
-
earliestTimeEachDay: '09:00',
|
|
829
|
-
latestTimeEachDay: '17:00'
|
|
830
|
-
}
|
|
831
|
-
)
|
|
832
|
-
|
|
833
|
-
// Returns ready-to-use available time slots
|
|
834
|
-
return availability.availableSlots
|
|
835
|
-
}
|
|
836
|
-
```
|
|
837
67
|
|
|
838
68
|
## SDK Development
|
|
839
69
|
|
|
@@ -864,37 +94,39 @@ bun run build
|
|
|
864
94
|
|
|
865
95
|
```
|
|
866
96
|
src/
|
|
867
|
-
├──
|
|
97
|
+
├── entities/
|
|
98
|
+
│ ├── organization.ts # Domain models
|
|
99
|
+
│ └── user.ts
|
|
868
100
|
├── services/ # Service implementations
|
|
869
101
|
│ ├── calendar.service.ts
|
|
870
|
-
│ ├──
|
|
871
|
-
│ ├── users.service.ts
|
|
102
|
+
│ ├── oauth.service.ts
|
|
872
103
|
│ ├── organizations.service.ts
|
|
873
|
-
│
|
|
874
|
-
|
|
875
|
-
│ ├── user.ts
|
|
876
|
-
│ └── organization.ts
|
|
877
|
-
├── types/ # TypeScript type definitions
|
|
878
|
-
│ ├── calendar.types.ts
|
|
879
|
-
│ ├── scheduling.types.ts
|
|
880
|
-
│ ├── internal.types.ts
|
|
881
|
-
│ └── oauth.types.ts
|
|
104
|
+
│ ├── scheduling.service.ts
|
|
105
|
+
│ └── users.service.ts
|
|
882
106
|
├── typebox/ # Runtime validation schemas (auto-generated)
|
|
883
107
|
│ ├── calendar.tb.ts
|
|
884
|
-
│ ├── scheduling.tb.ts
|
|
885
108
|
│ ├── oauth.tb.ts
|
|
109
|
+
│ ├── organization.stripped.tb.ts
|
|
886
110
|
│ ├── organization.tb.ts
|
|
887
|
-
│ ├──
|
|
111
|
+
│ ├── scheduling.tb.ts
|
|
888
112
|
│ ├── timeString.tb.ts
|
|
889
|
-
│ ├──
|
|
890
|
-
│ └── user.
|
|
113
|
+
│ ├── user.stripped.tb.ts
|
|
114
|
+
│ └── user.tb.ts
|
|
115
|
+
├── types/ # TypeScript type definitions
|
|
116
|
+
│ ├── calendar.types.ts
|
|
117
|
+
│ ├── internal.types.ts
|
|
118
|
+
│ ├── oauth.types.ts
|
|
119
|
+
│ ├── organization.types.ts
|
|
120
|
+
│ ├── scheduling.types.ts
|
|
121
|
+
│ └── user.types.ts
|
|
891
122
|
├── utils/ # Helper utilities
|
|
892
123
|
│ ├── fetch.helper.ts
|
|
893
124
|
│ ├── fetchErrorHandler.ts
|
|
894
|
-
│ ├── includes.helper.ts
|
|
895
125
|
│ ├── functionize.ts
|
|
126
|
+
│ ├── includes.helper.ts
|
|
896
127
|
│ └── omit.ts
|
|
897
|
-
|
|
128
|
+
├── errors.ts # Custom error classes
|
|
129
|
+
└── index.ts # Main client and exports
|
|
898
130
|
```
|
|
899
131
|
|
|
900
132
|
### Code Style
|
|
@@ -951,9 +183,9 @@ Found a bug or have a feature request? Please [open an issue](https://github.com
|
|
|
951
183
|
## Support
|
|
952
184
|
|
|
953
185
|
- **Documentation**: [https://docs.recal.dev](https://docs.recal.dev)
|
|
954
|
-
- **API Reference**: [https://api.recal.dev/docs](https://api.recal.dev/
|
|
186
|
+
- **API Reference**: [https://api.recal.dev/docs](https://api.recal.dev/v1/swagger)
|
|
955
187
|
- **Email**: team@recal.dev
|
|
956
|
-
- **
|
|
188
|
+
- **Slack**: [Join our community](https://join.slack.com/t/recal-workspace/shared_invite/zt-394r5j23n-WDr_tz753Cf8lQljrK_0Mw)
|
|
957
189
|
|
|
958
190
|
## License
|
|
959
191
|
|