@withaevum/sdk 0.0.1
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 +621 -0
- package/dist/analytics.d.ts +17 -0
- package/dist/analytics.js +46 -0
- package/dist/availability.d.ts +39 -0
- package/dist/availability.js +164 -0
- package/dist/bookings.d.ts +42 -0
- package/dist/bookings.js +148 -0
- package/dist/calendar.d.ts +13 -0
- package/dist/calendar.js +65 -0
- package/dist/client.d.ts +44 -0
- package/dist/client.js +162 -0
- package/dist/customers.d.ts +33 -0
- package/dist/customers.js +83 -0
- package/dist/errors.d.ts +42 -0
- package/dist/errors.js +54 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/offerings.d.ts +107 -0
- package/dist/offerings.js +437 -0
- package/dist/orgs.d.ts +24 -0
- package/dist/orgs.js +30 -0
- package/dist/payments.d.ts +33 -0
- package/dist/payments.js +26 -0
- package/dist/providers.d.ts +57 -0
- package/dist/providers.js +108 -0
- package/dist/types.d.ts +687 -0
- package/dist/types.js +2 -0
- package/dist/webhooks.d.ts +176 -0
- package/dist/webhooks.js +153 -0
- package/package.json +52 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AevumClient } from './client';
|
|
2
|
+
import type { GetSlotsParams, GetSlotsResponse, CheckAvailabilityParams, CheckAvailabilityResponse, GetAvailabilitySchedulesParams, CreateAvailabilityScheduleParams, UpdateAvailabilityScheduleParams, AvailabilitySchedule, GetAvailabilitySlotsParams } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Availability API methods
|
|
5
|
+
*/
|
|
6
|
+
export declare class AvailabilityAPI {
|
|
7
|
+
private client;
|
|
8
|
+
constructor(client: AevumClient);
|
|
9
|
+
/**
|
|
10
|
+
* Get available time slots for a provider within a date range
|
|
11
|
+
* Enhanced version that supports offeringId and limit
|
|
12
|
+
*/
|
|
13
|
+
getSlots(params: GetSlotsParams | GetAvailabilitySlotsParams): Promise<GetSlotsResponse>;
|
|
14
|
+
/**
|
|
15
|
+
* Get availability schedules
|
|
16
|
+
*/
|
|
17
|
+
getSchedules(params?: GetAvailabilitySchedulesParams): Promise<AvailabilitySchedule[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Create an availability schedule for a provider
|
|
20
|
+
*/
|
|
21
|
+
createSchedule(params: CreateAvailabilityScheduleParams): Promise<AvailabilitySchedule>;
|
|
22
|
+
/**
|
|
23
|
+
* Get a single availability schedule by ID
|
|
24
|
+
*/
|
|
25
|
+
getSchedule(scheduleId: string): Promise<AvailabilitySchedule>;
|
|
26
|
+
/**
|
|
27
|
+
* Update an availability schedule (partial update)
|
|
28
|
+
*/
|
|
29
|
+
updateSchedule(scheduleId: string, params: UpdateAvailabilityScheduleParams): Promise<AvailabilitySchedule>;
|
|
30
|
+
/**
|
|
31
|
+
* Delete an availability schedule
|
|
32
|
+
*/
|
|
33
|
+
deleteSchedule(scheduleId: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a specific time slot is available
|
|
36
|
+
* This is a client-side implementation that uses getSlots()
|
|
37
|
+
*/
|
|
38
|
+
check(params: CheckAvailabilityParams): Promise<CheckAvailabilityResponse>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Availability API methods
|
|
3
|
+
*/
|
|
4
|
+
export class AvailabilityAPI {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get available time slots for a provider within a date range
|
|
10
|
+
* Enhanced version that supports offeringId and limit
|
|
11
|
+
*/
|
|
12
|
+
async getSlots(params) {
|
|
13
|
+
const query = {};
|
|
14
|
+
// Support both old and new parameter formats
|
|
15
|
+
if ('providerId' in params && params.providerId) {
|
|
16
|
+
query.providerId = params.providerId;
|
|
17
|
+
}
|
|
18
|
+
if ('offeringId' in params && params.offeringId) {
|
|
19
|
+
query.offeringId = params.offeringId;
|
|
20
|
+
}
|
|
21
|
+
if ('start' in params && params.start) {
|
|
22
|
+
query.start = params.start;
|
|
23
|
+
}
|
|
24
|
+
else if ('startDate' in params && params.startDate) {
|
|
25
|
+
query.start = params.startDate;
|
|
26
|
+
}
|
|
27
|
+
if ('end' in params && params.end) {
|
|
28
|
+
query.end = params.end;
|
|
29
|
+
}
|
|
30
|
+
else if ('endDate' in params && params.endDate) {
|
|
31
|
+
query.end = params.endDate;
|
|
32
|
+
}
|
|
33
|
+
if ('limit' in params && params.limit !== undefined) {
|
|
34
|
+
query.limit = params.limit;
|
|
35
|
+
}
|
|
36
|
+
// For backward compatibility with GetSlotsParams
|
|
37
|
+
if ('startDate' in params && 'endDate' in params) {
|
|
38
|
+
if (!params.startDate || !params.endDate) {
|
|
39
|
+
throw new Error('startDate and endDate are required');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (!query.start || !query.end) {
|
|
43
|
+
throw new Error('start/startDate and end/endDate are required');
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
return await this.client.request('GET', '/api/v1/orgs/{orgId}/availability/slots', { query });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
// Handle 404 gracefully - endpoint might not exist yet
|
|
50
|
+
if (error?.status === 404 || error?.message?.includes('404')) {
|
|
51
|
+
console.warn('Availability slots endpoint not found, returning empty slots');
|
|
52
|
+
return { slots: [] };
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get availability schedules
|
|
59
|
+
*/
|
|
60
|
+
async getSchedules(params) {
|
|
61
|
+
const query = {};
|
|
62
|
+
if (params?.providerId) {
|
|
63
|
+
query.providerId = params.providerId;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const response = await this.client.request('GET', '/api/v1/orgs/{orgId}/availability/schedules', { query });
|
|
67
|
+
return response || [];
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
// Handle 404 gracefully - endpoint might not exist yet
|
|
71
|
+
if (error?.status === 404 || error?.message?.includes('404')) {
|
|
72
|
+
console.warn('Availability schedules endpoint not found, returning empty array');
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create an availability schedule for a provider
|
|
80
|
+
*/
|
|
81
|
+
async createSchedule(params) {
|
|
82
|
+
return this.client.request('POST', '/api/v1/orgs/{orgId}/availability/schedules', {
|
|
83
|
+
body: {
|
|
84
|
+
providerId: params.providerId,
|
|
85
|
+
name: params.name,
|
|
86
|
+
timezone: params.timezone,
|
|
87
|
+
weekly_hours: params.weekly_hours,
|
|
88
|
+
recurrence_preset: params.recurrence_preset,
|
|
89
|
+
recurrence_end_mode: params.recurrence_end_mode,
|
|
90
|
+
recurrence_end_date: params.recurrence_end_date,
|
|
91
|
+
recurrence_end_count: params.recurrence_end_count,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get a single availability schedule by ID
|
|
97
|
+
*/
|
|
98
|
+
async getSchedule(scheduleId) {
|
|
99
|
+
return this.client.request('GET', `/api/v1/orgs/{orgId}/availability/schedules/${scheduleId}`);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Update an availability schedule (partial update)
|
|
103
|
+
*/
|
|
104
|
+
async updateSchedule(scheduleId, params) {
|
|
105
|
+
const body = {};
|
|
106
|
+
if (params.name !== undefined)
|
|
107
|
+
body.name = params.name;
|
|
108
|
+
if (params.timezone !== undefined)
|
|
109
|
+
body.timezone = params.timezone;
|
|
110
|
+
if (params.weekly_hours !== undefined)
|
|
111
|
+
body.weekly_hours = params.weekly_hours;
|
|
112
|
+
if (params.recurrence_preset !== undefined)
|
|
113
|
+
body.recurrence_preset = params.recurrence_preset;
|
|
114
|
+
if (params.recurrence_end_mode !== undefined)
|
|
115
|
+
body.recurrence_end_mode = params.recurrence_end_mode;
|
|
116
|
+
if (params.recurrence_end_date !== undefined)
|
|
117
|
+
body.recurrence_end_date = params.recurrence_end_date;
|
|
118
|
+
if (params.recurrence_end_count !== undefined)
|
|
119
|
+
body.recurrence_end_count = params.recurrence_end_count;
|
|
120
|
+
return this.client.request('PATCH', `/api/v1/orgs/{orgId}/availability/schedules/${scheduleId}`, { body });
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Delete an availability schedule
|
|
124
|
+
*/
|
|
125
|
+
async deleteSchedule(scheduleId) {
|
|
126
|
+
await this.client.request('DELETE', `/api/v1/orgs/{orgId}/availability/schedules/${scheduleId}`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if a specific time slot is available
|
|
130
|
+
* This is a client-side implementation that uses getSlots()
|
|
131
|
+
*/
|
|
132
|
+
async check(params) {
|
|
133
|
+
const { providerId, startTime, duration } = params;
|
|
134
|
+
// Parse start time
|
|
135
|
+
const start = new Date(startTime);
|
|
136
|
+
if (isNaN(start.getTime())) {
|
|
137
|
+
throw new Error('Invalid startTime format. Expected ISO 8601 datetime with timezone');
|
|
138
|
+
}
|
|
139
|
+
// Calculate end time
|
|
140
|
+
const end = new Date(start.getTime() + duration * 60 * 1000);
|
|
141
|
+
// Get slots for a window around the requested time (1 day before and after)
|
|
142
|
+
const windowStart = new Date(start.getTime() - 24 * 60 * 60 * 1000);
|
|
143
|
+
const windowEnd = new Date(end.getTime() + 24 * 60 * 60 * 1000);
|
|
144
|
+
// Format as ISO strings with timezone
|
|
145
|
+
const startDate = windowStart.toISOString();
|
|
146
|
+
const endDate = windowEnd.toISOString();
|
|
147
|
+
// Get available slots
|
|
148
|
+
const { slots } = await this.getSlots({
|
|
149
|
+
providerId,
|
|
150
|
+
startDate,
|
|
151
|
+
endDate,
|
|
152
|
+
});
|
|
153
|
+
// Check if requested time falls within any available slot
|
|
154
|
+
const requestedStart = start.getTime();
|
|
155
|
+
const requestedEnd = end.getTime();
|
|
156
|
+
const isAvailable = slots.some((slot) => {
|
|
157
|
+
const slotStart = new Date(slot.start_time_utc).getTime();
|
|
158
|
+
const slotEnd = new Date(slot.end_time_utc).getTime();
|
|
159
|
+
// Check if requested time is completely within the slot
|
|
160
|
+
return requestedStart >= slotStart && requestedEnd <= slotEnd;
|
|
161
|
+
});
|
|
162
|
+
return { available: isAvailable };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AevumClient } from './client';
|
|
2
|
+
import type { Booking, CreateBookingParams, ListBookingsParams, ListBookingsResponse, RescheduleBookingParams } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Bookings API methods
|
|
5
|
+
*/
|
|
6
|
+
export declare class BookingsAPI {
|
|
7
|
+
private client;
|
|
8
|
+
constructor(client: AevumClient);
|
|
9
|
+
/**
|
|
10
|
+
* Create a new booking
|
|
11
|
+
*/
|
|
12
|
+
create(params: CreateBookingParams): Promise<Booking>;
|
|
13
|
+
/**
|
|
14
|
+
* Get a booking by ID
|
|
15
|
+
*/
|
|
16
|
+
get(bookingId: string): Promise<Booking>;
|
|
17
|
+
/**
|
|
18
|
+
* List bookings with optional filters
|
|
19
|
+
*/
|
|
20
|
+
list(params?: ListBookingsParams): Promise<ListBookingsResponse>;
|
|
21
|
+
/**
|
|
22
|
+
* Cancel a booking
|
|
23
|
+
*/
|
|
24
|
+
cancel(bookingId: string, reason?: string): Promise<Booking>;
|
|
25
|
+
/**
|
|
26
|
+
* Reschedule a booking
|
|
27
|
+
*/
|
|
28
|
+
reschedule(bookingId: string, params: RescheduleBookingParams): Promise<Booking>;
|
|
29
|
+
/**
|
|
30
|
+
* Confirm a booking
|
|
31
|
+
*/
|
|
32
|
+
confirm(bookingId: string, params?: {
|
|
33
|
+
sendNotification?: boolean;
|
|
34
|
+
}): Promise<Booking>;
|
|
35
|
+
/**
|
|
36
|
+
* Update a booking (status and/or notes)
|
|
37
|
+
*/
|
|
38
|
+
update(bookingId: string, params: {
|
|
39
|
+
status?: string;
|
|
40
|
+
notes?: string;
|
|
41
|
+
}): Promise<Booking>;
|
|
42
|
+
}
|
package/dist/bookings.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bookings API methods
|
|
3
|
+
*/
|
|
4
|
+
export class BookingsAPI {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Create a new booking
|
|
10
|
+
*/
|
|
11
|
+
async create(params) {
|
|
12
|
+
// Map SDK params to API format
|
|
13
|
+
const providerIds = params.providerIds || (params.providerId ? [params.providerId] : []);
|
|
14
|
+
const offeringIds = params.offeringIds || (params.offeringId ? [params.offeringId] : []);
|
|
15
|
+
if (providerIds.length === 0) {
|
|
16
|
+
throw new Error('At least one providerId or providerIds is required');
|
|
17
|
+
}
|
|
18
|
+
if (offeringIds.length === 0) {
|
|
19
|
+
throw new Error('At least one offeringId or offeringIds is required');
|
|
20
|
+
}
|
|
21
|
+
// Calculate endTime if not provided (assuming we can infer from offering duration)
|
|
22
|
+
// For now, require endTime to be provided
|
|
23
|
+
if (!params.endTime) {
|
|
24
|
+
throw new Error('endTime is required');
|
|
25
|
+
}
|
|
26
|
+
// Build request body
|
|
27
|
+
const body = {
|
|
28
|
+
providerIds,
|
|
29
|
+
offeringIds,
|
|
30
|
+
start_time: params.startTime,
|
|
31
|
+
end_time: params.endTime,
|
|
32
|
+
kind: params.kind || 'standard',
|
|
33
|
+
status: params.status || 'pending',
|
|
34
|
+
};
|
|
35
|
+
// Handle customer
|
|
36
|
+
if (params.customerId) {
|
|
37
|
+
body.customerId = params.customerId;
|
|
38
|
+
}
|
|
39
|
+
else if (params.customerEmail || params.customer) {
|
|
40
|
+
body.customer = {
|
|
41
|
+
email: params.customerEmail || params.customer?.email,
|
|
42
|
+
name: params.customer?.name,
|
|
43
|
+
phone: params.customer?.phone,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error('Either customerId, customerEmail, or customer object is required');
|
|
48
|
+
}
|
|
49
|
+
// Add optional fields
|
|
50
|
+
if (params.price_cents !== undefined) {
|
|
51
|
+
body.price_cents = params.price_cents;
|
|
52
|
+
}
|
|
53
|
+
if (params.notes) {
|
|
54
|
+
body.notes = params.notes;
|
|
55
|
+
}
|
|
56
|
+
const response = await this.client.request('POST', '/api/v1/orgs/{orgId}/bookings', { body });
|
|
57
|
+
// The API returns a partial booking, so we need to fetch the full booking
|
|
58
|
+
if (response.id) {
|
|
59
|
+
return this.get(response.id);
|
|
60
|
+
}
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get a booking by ID
|
|
65
|
+
*/
|
|
66
|
+
async get(bookingId) {
|
|
67
|
+
return this.client.request('GET', `/api/v1/orgs/{orgId}/bookings/${bookingId}`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* List bookings with optional filters
|
|
71
|
+
*/
|
|
72
|
+
async list(params) {
|
|
73
|
+
const query = {};
|
|
74
|
+
if (params?.status) {
|
|
75
|
+
query.status = params.status;
|
|
76
|
+
}
|
|
77
|
+
if (params?.providerId) {
|
|
78
|
+
query.providerId = params.providerId;
|
|
79
|
+
}
|
|
80
|
+
if (params?.customerId) {
|
|
81
|
+
query.customerId = params.customerId;
|
|
82
|
+
}
|
|
83
|
+
if (params?.startDate) {
|
|
84
|
+
query.start = params.startDate;
|
|
85
|
+
}
|
|
86
|
+
if (params?.endDate) {
|
|
87
|
+
query.end = params.endDate;
|
|
88
|
+
}
|
|
89
|
+
if (params?.page !== undefined) {
|
|
90
|
+
query.page = params.page;
|
|
91
|
+
}
|
|
92
|
+
if (params?.pageSize !== undefined) {
|
|
93
|
+
query.pageSize = params.pageSize;
|
|
94
|
+
}
|
|
95
|
+
return this.client.request('GET', '/api/v1/orgs/{orgId}/bookings', { query });
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Cancel a booking
|
|
99
|
+
*/
|
|
100
|
+
async cancel(bookingId, reason) {
|
|
101
|
+
const body = {};
|
|
102
|
+
if (reason) {
|
|
103
|
+
body.reason = reason;
|
|
104
|
+
}
|
|
105
|
+
await this.client.request('PATCH', `/api/v1/orgs/{orgId}/bookings/${bookingId}/cancel`, { body });
|
|
106
|
+
// Return updated booking
|
|
107
|
+
return this.get(bookingId);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Reschedule a booking
|
|
111
|
+
*/
|
|
112
|
+
async reschedule(bookingId, params) {
|
|
113
|
+
const body = {
|
|
114
|
+
start_time: params.start_time,
|
|
115
|
+
end_time: params.end_time,
|
|
116
|
+
sendNotification: params.sendNotification ?? false,
|
|
117
|
+
};
|
|
118
|
+
await this.client.request('PATCH', `/api/v1/orgs/{orgId}/bookings/${bookingId}/reschedule`, { body });
|
|
119
|
+
// Return updated booking
|
|
120
|
+
return this.get(bookingId);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Confirm a booking
|
|
124
|
+
*/
|
|
125
|
+
async confirm(bookingId, params) {
|
|
126
|
+
const body = {
|
|
127
|
+
sendNotification: params?.sendNotification ?? false,
|
|
128
|
+
};
|
|
129
|
+
await this.client.request('PATCH', `/api/v1/orgs/{orgId}/bookings/${bookingId}/confirm`, { body });
|
|
130
|
+
// Return updated booking
|
|
131
|
+
return this.get(bookingId);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Update a booking (status and/or notes)
|
|
135
|
+
*/
|
|
136
|
+
async update(bookingId, params) {
|
|
137
|
+
const body = {};
|
|
138
|
+
if (params.status !== undefined) {
|
|
139
|
+
body.status = params.status;
|
|
140
|
+
}
|
|
141
|
+
if (params.notes !== undefined) {
|
|
142
|
+
body.notes = params.notes;
|
|
143
|
+
}
|
|
144
|
+
await this.client.request('PATCH', `/api/v1/orgs/{orgId}/bookings/${bookingId}`, { body });
|
|
145
|
+
// Return updated booking
|
|
146
|
+
return this.get(bookingId);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AevumClient } from './client';
|
|
2
|
+
import type { GetCalendarEventsParams, GetCalendarEventsResponse } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Calendar API methods
|
|
5
|
+
*/
|
|
6
|
+
export declare class CalendarAPI {
|
|
7
|
+
private client;
|
|
8
|
+
constructor(client: AevumClient);
|
|
9
|
+
/**
|
|
10
|
+
* Get calendar events (bookings and events) for a date range
|
|
11
|
+
*/
|
|
12
|
+
getEvents(params?: GetCalendarEventsParams): Promise<GetCalendarEventsResponse>;
|
|
13
|
+
}
|
package/dist/calendar.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar API methods
|
|
3
|
+
*/
|
|
4
|
+
export class CalendarAPI {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get calendar events (bookings and events) for a date range
|
|
10
|
+
*/
|
|
11
|
+
async getEvents(params) {
|
|
12
|
+
const orgId = await this.client.resolveOrgId();
|
|
13
|
+
// Get bookings for calendar
|
|
14
|
+
const bookingsQuery = {};
|
|
15
|
+
if (params?.providerId) {
|
|
16
|
+
bookingsQuery.providerId = params.providerId;
|
|
17
|
+
}
|
|
18
|
+
if (params?.start) {
|
|
19
|
+
bookingsQuery.start = params.start;
|
|
20
|
+
}
|
|
21
|
+
if (params?.end) {
|
|
22
|
+
bookingsQuery.end = params.end;
|
|
23
|
+
}
|
|
24
|
+
const bookings = await this.client.request('GET', '/api/v1/orgs/{orgId}/bookings', {
|
|
25
|
+
query: bookingsQuery,
|
|
26
|
+
});
|
|
27
|
+
// Get events for calendar
|
|
28
|
+
const eventsQuery = {};
|
|
29
|
+
if (params?.providerId) {
|
|
30
|
+
eventsQuery.providerId = params.providerId;
|
|
31
|
+
}
|
|
32
|
+
if (params?.start) {
|
|
33
|
+
eventsQuery.start = params.start;
|
|
34
|
+
}
|
|
35
|
+
if (params?.end) {
|
|
36
|
+
eventsQuery.end = params.end;
|
|
37
|
+
}
|
|
38
|
+
let events = [];
|
|
39
|
+
try {
|
|
40
|
+
const eventsResponse = await this.client.request('GET', `/api/v1/orgs/${orgId}/events`, { query: eventsQuery });
|
|
41
|
+
// Handle paginated response - extract events/offerings array
|
|
42
|
+
if (Array.isArray(eventsResponse)) {
|
|
43
|
+
events = eventsResponse;
|
|
44
|
+
}
|
|
45
|
+
else if (eventsResponse?.events) {
|
|
46
|
+
events = eventsResponse.events;
|
|
47
|
+
}
|
|
48
|
+
else if (eventsResponse?.offerings) {
|
|
49
|
+
// Events endpoint returns 'offerings' property
|
|
50
|
+
events = eventsResponse.offerings;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
events = [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
// Events endpoint might not be available, continue without it
|
|
58
|
+
console.warn('Failed to fetch events:', error);
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
bookings: bookings.bookings || [],
|
|
62
|
+
events: events || [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AvailabilityAPI } from './availability';
|
|
2
|
+
import { BookingsAPI } from './bookings';
|
|
3
|
+
import { OfferingsAPI } from './offerings';
|
|
4
|
+
import { CustomersAPI } from './customers';
|
|
5
|
+
import { ProvidersAPI } from './providers';
|
|
6
|
+
import { OrgsAPI } from './orgs';
|
|
7
|
+
import { CalendarAPI } from './calendar';
|
|
8
|
+
import { AnalyticsAPI } from './analytics';
|
|
9
|
+
import { PaymentsAPI } from './payments';
|
|
10
|
+
import type { AevumClientConfig } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* Main client class for interacting with the Aevum API
|
|
13
|
+
*/
|
|
14
|
+
export declare class AevumClient {
|
|
15
|
+
private readonly apiKey;
|
|
16
|
+
private readonly baseUrl;
|
|
17
|
+
private orgId;
|
|
18
|
+
private orgIdPromise;
|
|
19
|
+
readonly bookings: BookingsAPI;
|
|
20
|
+
readonly availability: AvailabilityAPI;
|
|
21
|
+
readonly offerings: OfferingsAPI;
|
|
22
|
+
readonly customers: CustomersAPI;
|
|
23
|
+
readonly providers: ProvidersAPI;
|
|
24
|
+
readonly orgs: OrgsAPI;
|
|
25
|
+
readonly calendar: CalendarAPI;
|
|
26
|
+
readonly analytics: AnalyticsAPI;
|
|
27
|
+
readonly payments: PaymentsAPI;
|
|
28
|
+
constructor(config: AevumClientConfig);
|
|
29
|
+
/**
|
|
30
|
+
* Resolve organization ID from API key (cached after first call)
|
|
31
|
+
*/
|
|
32
|
+
resolveOrgId(): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Internal method to fetch orgId from API
|
|
35
|
+
*/
|
|
36
|
+
private _fetchOrgId;
|
|
37
|
+
/**
|
|
38
|
+
* Make an authenticated HTTP request to the API
|
|
39
|
+
*/
|
|
40
|
+
request<T>(method: string, path: string, options?: {
|
|
41
|
+
body?: unknown;
|
|
42
|
+
query?: Record<string, string | number | undefined>;
|
|
43
|
+
}): Promise<T>;
|
|
44
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// packages/sdk/src/client.ts
|
|
2
|
+
import { AvailabilityAPI } from './availability';
|
|
3
|
+
import { BookingsAPI } from './bookings';
|
|
4
|
+
import { OfferingsAPI } from './offerings';
|
|
5
|
+
import { CustomersAPI } from './customers';
|
|
6
|
+
import { ProvidersAPI } from './providers';
|
|
7
|
+
import { OrgsAPI } from './orgs';
|
|
8
|
+
import { CalendarAPI } from './calendar';
|
|
9
|
+
import { AnalyticsAPI } from './analytics';
|
|
10
|
+
import { PaymentsAPI } from './payments';
|
|
11
|
+
import { AevumAPIError, AevumAuthenticationError, AevumNotFoundError, AevumValidationError, } from './errors';
|
|
12
|
+
/**
|
|
13
|
+
* Main client class for interacting with the Aevum API
|
|
14
|
+
*/
|
|
15
|
+
export class AevumClient {
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.orgId = null;
|
|
18
|
+
this.orgIdPromise = null;
|
|
19
|
+
if (!config.apiKey) {
|
|
20
|
+
throw new Error('API key is required');
|
|
21
|
+
}
|
|
22
|
+
this.apiKey = config.apiKey;
|
|
23
|
+
// Default baseUrl: use provided, or check env var (Node.js only), or use production
|
|
24
|
+
if (config.baseUrl) {
|
|
25
|
+
this.baseUrl = config.baseUrl;
|
|
26
|
+
}
|
|
27
|
+
else if (typeof process !== 'undefined' && process.env?.AEVUM_API_BASE_URL) {
|
|
28
|
+
// Check environment variable if in Node.js
|
|
29
|
+
this.baseUrl = process.env.AEVUM_API_BASE_URL;
|
|
30
|
+
}
|
|
31
|
+
else if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {
|
|
32
|
+
// Default to localhost in development
|
|
33
|
+
this.baseUrl = 'http://localhost:3000';
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Production default
|
|
37
|
+
this.baseUrl = 'https://withaevum.com';
|
|
38
|
+
}
|
|
39
|
+
// Set orgId if provided in config (avoids extra API call)
|
|
40
|
+
if (config.orgId) {
|
|
41
|
+
this.orgId = config.orgId;
|
|
42
|
+
}
|
|
43
|
+
// Initialize API namespaces
|
|
44
|
+
this.bookings = new BookingsAPI(this);
|
|
45
|
+
this.availability = new AvailabilityAPI(this);
|
|
46
|
+
this.offerings = new OfferingsAPI(this);
|
|
47
|
+
this.customers = new CustomersAPI(this);
|
|
48
|
+
this.providers = new ProvidersAPI(this);
|
|
49
|
+
this.orgs = new OrgsAPI(this);
|
|
50
|
+
this.calendar = new CalendarAPI(this);
|
|
51
|
+
this.analytics = new AnalyticsAPI(this);
|
|
52
|
+
this.payments = new PaymentsAPI(this);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve organization ID from API key (cached after first call)
|
|
56
|
+
*/
|
|
57
|
+
async resolveOrgId() {
|
|
58
|
+
// Return cached orgId if available
|
|
59
|
+
if (this.orgId) {
|
|
60
|
+
return this.orgId;
|
|
61
|
+
}
|
|
62
|
+
// Return existing promise if resolution is in progress
|
|
63
|
+
if (this.orgIdPromise) {
|
|
64
|
+
return this.orgIdPromise;
|
|
65
|
+
}
|
|
66
|
+
// Start resolution
|
|
67
|
+
this.orgIdPromise = this._fetchOrgId();
|
|
68
|
+
this.orgId = await this.orgIdPromise;
|
|
69
|
+
return this.orgId;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Internal method to fetch orgId from API
|
|
73
|
+
*/
|
|
74
|
+
async _fetchOrgId() {
|
|
75
|
+
const response = await fetch(`${this.baseUrl}/api/v1/session/org-from-key`, {
|
|
76
|
+
method: 'GET',
|
|
77
|
+
headers: {
|
|
78
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
79
|
+
'Content-Type': 'application/json',
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
if (response.status === 401 || response.status === 403) {
|
|
84
|
+
throw new AevumAuthenticationError('Invalid or missing API key', response.status);
|
|
85
|
+
}
|
|
86
|
+
const errorText = await response.text().catch(() => '');
|
|
87
|
+
throw new AevumAPIError(`Failed to resolve organization ID: ${errorText}`, response.status);
|
|
88
|
+
}
|
|
89
|
+
const data = await response.json();
|
|
90
|
+
if (!data.orgId) {
|
|
91
|
+
throw new AevumAPIError('Invalid response: missing orgId', response.status);
|
|
92
|
+
}
|
|
93
|
+
return data.orgId;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Make an authenticated HTTP request to the API
|
|
97
|
+
*/
|
|
98
|
+
async request(method, path, options = {}) {
|
|
99
|
+
// Ensure orgId is resolved (will use cache if already resolved)
|
|
100
|
+
const orgId = await this.resolveOrgId();
|
|
101
|
+
// Replace {orgId} placeholder in path if present
|
|
102
|
+
const resolvedPath = path.replace('{orgId}', orgId);
|
|
103
|
+
// Build URL with query parameters
|
|
104
|
+
const url = new URL(resolvedPath, this.baseUrl);
|
|
105
|
+
if (options.query) {
|
|
106
|
+
Object.entries(options.query).forEach(([key, value]) => {
|
|
107
|
+
if (value !== undefined && value !== null) {
|
|
108
|
+
url.searchParams.append(key, String(value));
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
// Prepare headers
|
|
113
|
+
const headers = {
|
|
114
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
};
|
|
117
|
+
// Prepare request options
|
|
118
|
+
const requestOptions = {
|
|
119
|
+
method,
|
|
120
|
+
headers,
|
|
121
|
+
};
|
|
122
|
+
// Add body if present
|
|
123
|
+
if (options.body !== undefined) {
|
|
124
|
+
requestOptions.body = JSON.stringify(options.body);
|
|
125
|
+
}
|
|
126
|
+
// Make the request
|
|
127
|
+
const response = await fetch(url.toString(), requestOptions);
|
|
128
|
+
// Handle empty responses (204 No Content)
|
|
129
|
+
if (response.status === 204 ||
|
|
130
|
+
response.headers.get('content-length') === '0') {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
// Parse response body
|
|
134
|
+
const text = await response.text();
|
|
135
|
+
let data;
|
|
136
|
+
try {
|
|
137
|
+
data = text ? JSON.parse(text) : null;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
throw new AevumAPIError(`Invalid JSON response: ${text}`, response.status);
|
|
141
|
+
}
|
|
142
|
+
// Handle errors
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
// Safely extract error data, handling null/undefined cases
|
|
145
|
+
const errorData = (data && typeof data === 'object') ? data : null;
|
|
146
|
+
const errorMessage = errorData?.error || `API request failed with status ${response.status}`;
|
|
147
|
+
const errorCode = errorData?.code;
|
|
148
|
+
const errorIssues = errorData?.issues;
|
|
149
|
+
if (response.status === 401 || response.status === 403) {
|
|
150
|
+
throw new AevumAuthenticationError(errorMessage, response.status);
|
|
151
|
+
}
|
|
152
|
+
if (response.status === 404) {
|
|
153
|
+
throw new AevumNotFoundError(errorMessage);
|
|
154
|
+
}
|
|
155
|
+
if (response.status === 400) {
|
|
156
|
+
throw new AevumValidationError(errorMessage, errorIssues);
|
|
157
|
+
}
|
|
158
|
+
throw new AevumAPIError(errorMessage, response.status, errorCode, errorIssues);
|
|
159
|
+
}
|
|
160
|
+
return data;
|
|
161
|
+
}
|
|
162
|
+
}
|