@soulbatical/tetra-core 0.1.39 → 0.1.41

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.

Potentially problematic release.


This version of @soulbatical/tetra-core might be problematic. Click here for more details.

Files changed (56) hide show
  1. package/dist/core/dualWriteProxy.d.ts +11 -0
  2. package/dist/core/dualWriteProxy.d.ts.map +1 -1
  3. package/dist/core/dualWriteProxy.js +142 -198
  4. package/dist/core/dualWriteProxy.js.map +1 -1
  5. package/dist/index.d.ts +4 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/shared/email/EmailService.d.ts +9 -1
  10. package/dist/shared/email/EmailService.d.ts.map +1 -1
  11. package/dist/shared/email/EmailService.js +83 -7
  12. package/dist/shared/email/EmailService.js.map +1 -1
  13. package/dist/shared/email/adminRoutes.d.ts +30 -0
  14. package/dist/shared/email/adminRoutes.d.ts.map +1 -0
  15. package/dist/shared/email/adminRoutes.js +227 -0
  16. package/dist/shared/email/adminRoutes.js.map +1 -0
  17. package/dist/shared/email/index.d.ts +3 -1
  18. package/dist/shared/email/index.d.ts.map +1 -1
  19. package/dist/shared/email/index.js +3 -0
  20. package/dist/shared/email/index.js.map +1 -1
  21. package/dist/shared/email/mailgun.d.ts +4 -1
  22. package/dist/shared/email/mailgun.d.ts.map +1 -1
  23. package/dist/shared/email/mailgun.js +41 -10
  24. package/dist/shared/email/mailgun.js.map +1 -1
  25. package/dist/shared/email/smtp.d.ts +4 -1
  26. package/dist/shared/email/smtp.d.ts.map +1 -1
  27. package/dist/shared/email/smtp.js +14 -2
  28. package/dist/shared/email/smtp.js.map +1 -1
  29. package/dist/shared/email/types.d.ts +23 -1
  30. package/dist/shared/email/types.d.ts.map +1 -1
  31. package/dist/shared/email/webhookRoutes.d.ts +29 -0
  32. package/dist/shared/email/webhookRoutes.d.ts.map +1 -0
  33. package/dist/shared/email/webhookRoutes.js +125 -0
  34. package/dist/shared/email/webhookRoutes.js.map +1 -0
  35. package/dist/shared/planner/GoogleCalendarService.d.ts +103 -0
  36. package/dist/shared/planner/GoogleCalendarService.d.ts.map +1 -0
  37. package/dist/shared/planner/GoogleCalendarService.js +365 -0
  38. package/dist/shared/planner/GoogleCalendarService.js.map +1 -0
  39. package/dist/shared/planner/PlannerService.d.ts +170 -0
  40. package/dist/shared/planner/PlannerService.d.ts.map +1 -0
  41. package/dist/shared/planner/PlannerService.js +860 -0
  42. package/dist/shared/planner/PlannerService.js.map +1 -0
  43. package/dist/shared/planner/index.d.ts +35 -0
  44. package/dist/shared/planner/index.d.ts.map +1 -0
  45. package/dist/shared/planner/index.js +34 -0
  46. package/dist/shared/planner/index.js.map +1 -0
  47. package/dist/shared/planner/routes.d.ts +67 -0
  48. package/dist/shared/planner/routes.d.ts.map +1 -0
  49. package/dist/shared/planner/routes.js +524 -0
  50. package/dist/shared/planner/routes.js.map +1 -0
  51. package/dist/shared/planner/types.d.ts +262 -0
  52. package/dist/shared/planner/types.d.ts.map +1 -0
  53. package/dist/shared/planner/types.js +9 -0
  54. package/dist/shared/planner/types.js.map +1 -0
  55. package/package.json +1 -1
  56. package/src/shared/email/migrations/004_add_email_logs_tracking_columns.sql +15 -0
@@ -0,0 +1,365 @@
1
+ /**
2
+ * GoogleCalendarService — Google Calendar OAuth + event sync
3
+ *
4
+ * Handles:
5
+ * - OAuth2 consent URL generation
6
+ * - Token exchange and storage
7
+ * - Token auto-refresh
8
+ * - Calendar event CRUD (create, update, delete)
9
+ * - Calendar listing and selection
10
+ * - Connection status check
11
+ *
12
+ * Uses lazy import for googleapis to avoid requiring it in projects that don't use calendar sync.
13
+ *
14
+ * Usage:
15
+ * ```typescript
16
+ * import { GoogleCalendarService } from '@soulbatical/tetra-core';
17
+ *
18
+ * const calService = new GoogleCalendarService({
19
+ * google: { clientId, clientSecret, redirectUri },
20
+ * });
21
+ * const url = calService.getAuthUrl(userId);
22
+ * ```
23
+ */
24
+ import { createLogger } from '../../utils/logger.js';
25
+ import { systemDB as defaultSystemDB } from '../../core/systemDb.js';
26
+ const logger = createLogger('planner:google-calendar');
27
+ const DEFAULT_SCOPES = [
28
+ 'https://www.googleapis.com/auth/calendar.events',
29
+ 'https://www.googleapis.com/auth/calendar.readonly',
30
+ ];
31
+ export class GoogleCalendarService {
32
+ config;
33
+ googleModule = null;
34
+ constructor(config) {
35
+ this.config = config;
36
+ }
37
+ // ─── Lazy googleapis import ───────────────────────────────
38
+ async getGoogle() {
39
+ if (!this.googleModule) {
40
+ try {
41
+ // Dynamic import to avoid requiring googleapis as a hard dependency.
42
+ // Projects that use Google Calendar must install googleapis themselves.
43
+ const moduleName = 'googleapis';
44
+ this.googleModule = await (Function('moduleName', 'return import(moduleName)')(moduleName));
45
+ }
46
+ catch {
47
+ throw new Error('googleapis package is required for Google Calendar integration. Install it: npm install googleapis');
48
+ }
49
+ }
50
+ return this.googleModule.google;
51
+ }
52
+ async getSystemDB() {
53
+ if (this.config.getSystemDB) {
54
+ return this.config.getSystemDB();
55
+ }
56
+ return defaultSystemDB('planner:calendar');
57
+ }
58
+ get scopes() {
59
+ return this.config.scopes || DEFAULT_SCOPES;
60
+ }
61
+ get timezone() {
62
+ return this.config.timezone || 'Europe/Amsterdam';
63
+ }
64
+ async createOAuth2Client() {
65
+ const google = await this.getGoogle();
66
+ const { clientId, clientSecret, redirectUri } = this.config.google;
67
+ return new google.auth.OAuth2(clientId, clientSecret, redirectUri);
68
+ }
69
+ /**
70
+ * Get an authenticated OAuth2 client for a user.
71
+ * Auto-refreshes expired tokens and persists new ones.
72
+ */
73
+ async getAuthenticatedClient(userId) {
74
+ const google = await this.getGoogle();
75
+ const db = await this.getSystemDB();
76
+ const { clientId, clientSecret, redirectUri } = this.config.google;
77
+ const { data: tokenRow, error } = await db
78
+ .from('planner_calendar_tokens')
79
+ .select('*')
80
+ .eq('user_id', userId)
81
+ .eq('is_active', true)
82
+ .single();
83
+ if (error || !tokenRow) {
84
+ logger.debug({ userId }, 'No calendar tokens found');
85
+ return null;
86
+ }
87
+ const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);
88
+ oauth2Client.setCredentials({
89
+ access_token: tokenRow.access_token,
90
+ refresh_token: tokenRow.refresh_token,
91
+ expiry_date: new Date(tokenRow.token_expiry).getTime(),
92
+ });
93
+ // Auto-refresh if expired or expiring within 5 minutes
94
+ const now = Date.now();
95
+ const expiry = new Date(tokenRow.token_expiry).getTime();
96
+ if (now >= expiry - 5 * 60 * 1000) {
97
+ try {
98
+ const { credentials } = await oauth2Client.refreshAccessToken();
99
+ oauth2Client.setCredentials(credentials);
100
+ await db
101
+ .from('planner_calendar_tokens')
102
+ .update({
103
+ access_token: credentials.access_token,
104
+ refresh_token: credentials.refresh_token || tokenRow.refresh_token,
105
+ token_expiry: credentials.expiry_date
106
+ ? new Date(credentials.expiry_date).toISOString()
107
+ : tokenRow.token_expiry,
108
+ updated_at: new Date().toISOString(),
109
+ })
110
+ .eq('user_id', userId);
111
+ logger.debug({ userId }, 'Calendar token refreshed');
112
+ }
113
+ catch (refreshError) {
114
+ logger.error({ error: refreshError, userId }, 'Failed to refresh calendar token');
115
+ await db
116
+ .from('planner_calendar_tokens')
117
+ .update({ is_active: false, updated_at: new Date().toISOString() })
118
+ .eq('user_id', userId);
119
+ return null;
120
+ }
121
+ }
122
+ return oauth2Client;
123
+ }
124
+ /**
125
+ * Get the user's selected calendar ID.
126
+ */
127
+ async getCalendarId(userId) {
128
+ const db = await this.getSystemDB();
129
+ const { data } = await db
130
+ .from('planner_calendar_tokens')
131
+ .select('calendar_id')
132
+ .eq('user_id', userId)
133
+ .single();
134
+ return data?.calendar_id || 'primary';
135
+ }
136
+ // ─── Public API ───────────────────────────────────────────
137
+ /**
138
+ * Generate Google OAuth2 consent URL.
139
+ */
140
+ async getAuthUrl(userId, state) {
141
+ const oauth2Client = await this.createOAuth2Client();
142
+ const statePayload = JSON.stringify({ userId, custom: state });
143
+ return oauth2Client.generateAuthUrl({
144
+ access_type: 'offline',
145
+ prompt: 'consent',
146
+ scope: this.scopes,
147
+ state: Buffer.from(statePayload).toString('base64'),
148
+ });
149
+ }
150
+ /**
151
+ * Exchange authorization code for tokens and store them.
152
+ */
153
+ async handleCallback(code, userId, organizationId) {
154
+ const oauth2Client = await this.createOAuth2Client();
155
+ const { tokens } = await oauth2Client.getToken(code);
156
+ if (!tokens.access_token || !tokens.refresh_token) {
157
+ throw new Error('Failed to obtain tokens from Google');
158
+ }
159
+ const db = await this.getSystemDB();
160
+ const { error } = await db
161
+ .from('planner_calendar_tokens')
162
+ .upsert({
163
+ user_id: userId,
164
+ organization_id: organizationId,
165
+ access_token: tokens.access_token,
166
+ refresh_token: tokens.refresh_token,
167
+ token_expiry: tokens.expiry_date
168
+ ? new Date(tokens.expiry_date).toISOString()
169
+ : new Date(Date.now() + 3600 * 1000).toISOString(),
170
+ is_active: true,
171
+ updated_at: new Date().toISOString(),
172
+ }, { onConflict: 'user_id' });
173
+ if (error) {
174
+ logger.error({ error, userId }, 'Failed to store calendar tokens');
175
+ throw new Error('Failed to store calendar tokens');
176
+ }
177
+ logger.info({ userId }, 'Google Calendar connected');
178
+ }
179
+ /**
180
+ * Create a Google Calendar event. Returns event ID or null.
181
+ */
182
+ async createEvent(userId, data) {
183
+ try {
184
+ const oauth2Client = await this.getAuthenticatedClient(userId);
185
+ if (!oauth2Client)
186
+ return null;
187
+ const google = await this.getGoogle();
188
+ const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
189
+ const calendarId = await this.getCalendarId(userId);
190
+ const response = await calendar.events.insert({
191
+ calendarId,
192
+ requestBody: {
193
+ summary: data.title,
194
+ description: data.description || undefined,
195
+ location: data.location || undefined,
196
+ start: { dateTime: data.startTime, timeZone: this.timezone },
197
+ end: { dateTime: data.endTime, timeZone: this.timezone },
198
+ },
199
+ });
200
+ logger.info({ userId, eventId: response.data.id }, 'Calendar event created');
201
+ return response.data.id || null;
202
+ }
203
+ catch (error) {
204
+ logger.error({ error, userId }, 'Failed to create calendar event');
205
+ return null;
206
+ }
207
+ }
208
+ /**
209
+ * Update a Google Calendar event.
210
+ */
211
+ async updateEvent(userId, eventId, data) {
212
+ try {
213
+ const oauth2Client = await this.getAuthenticatedClient(userId);
214
+ if (!oauth2Client)
215
+ return;
216
+ const google = await this.getGoogle();
217
+ const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
218
+ const calendarId = await this.getCalendarId(userId);
219
+ await calendar.events.update({
220
+ calendarId,
221
+ eventId,
222
+ requestBody: {
223
+ summary: data.title,
224
+ description: data.description || undefined,
225
+ location: data.location || undefined,
226
+ start: { dateTime: data.startTime, timeZone: this.timezone },
227
+ end: { dateTime: data.endTime, timeZone: this.timezone },
228
+ },
229
+ });
230
+ logger.info({ userId, eventId }, 'Calendar event updated');
231
+ }
232
+ catch (error) {
233
+ logger.error({ error, userId, eventId }, 'Failed to update calendar event');
234
+ }
235
+ }
236
+ /**
237
+ * Delete a Google Calendar event.
238
+ */
239
+ async deleteEvent(userId, eventId) {
240
+ try {
241
+ const oauth2Client = await this.getAuthenticatedClient(userId);
242
+ if (!oauth2Client)
243
+ return;
244
+ const google = await this.getGoogle();
245
+ const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
246
+ const calendarId = await this.getCalendarId(userId);
247
+ await calendar.events.delete({ calendarId, eventId });
248
+ logger.info({ userId, eventId }, 'Calendar event deleted');
249
+ }
250
+ catch (error) {
251
+ logger.error({ error, userId, eventId }, 'Failed to delete calendar event');
252
+ }
253
+ }
254
+ /**
255
+ * List all calendars the user has write access to.
256
+ */
257
+ async listCalendars(userId) {
258
+ try {
259
+ const oauth2Client = await this.getAuthenticatedClient(userId);
260
+ if (!oauth2Client)
261
+ return null;
262
+ const google = await this.getGoogle();
263
+ const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
264
+ const response = await calendar.calendarList.list({ minAccessRole: 'writer' });
265
+ const items = response.data.items || [];
266
+ const selectedId = await this.getCalendarId(userId);
267
+ return items.map((cal) => ({
268
+ id: cal.id || 'primary',
269
+ name: cal.summary || 'Unnamed',
270
+ isPrimary: cal.primary === true,
271
+ color: cal.backgroundColor || '#4285f4',
272
+ isSelected: (cal.primary && selectedId === 'primary') || cal.id === selectedId,
273
+ }));
274
+ }
275
+ catch (error) {
276
+ logger.error({ error, userId }, 'Failed to list calendars');
277
+ return null;
278
+ }
279
+ }
280
+ /**
281
+ * Set which Google Calendar to sync to.
282
+ */
283
+ async selectCalendar(userId, calendarId) {
284
+ try {
285
+ const db = await this.getSystemDB();
286
+ const { error } = await db
287
+ .from('planner_calendar_tokens')
288
+ .update({ calendar_id: calendarId, updated_at: new Date().toISOString() })
289
+ .eq('user_id', userId)
290
+ .eq('is_active', true);
291
+ if (error) {
292
+ logger.error({ error, userId, calendarId }, 'Failed to select calendar');
293
+ return false;
294
+ }
295
+ logger.info({ userId, calendarId }, 'Calendar selected');
296
+ return true;
297
+ }
298
+ catch (error) {
299
+ logger.error({ error, userId }, 'Failed to select calendar');
300
+ return false;
301
+ }
302
+ }
303
+ /**
304
+ * Check if a user has an active Google Calendar connection.
305
+ */
306
+ async isConnected(userId) {
307
+ try {
308
+ const db = await this.getSystemDB();
309
+ const { data, error } = await db
310
+ .from('planner_calendar_tokens')
311
+ .select('id')
312
+ .eq('user_id', userId)
313
+ .eq('is_active', true)
314
+ .single();
315
+ return !error && !!data;
316
+ }
317
+ catch {
318
+ return false;
319
+ }
320
+ }
321
+ /**
322
+ * Disconnect Google Calendar for a user.
323
+ */
324
+ async disconnect(userId) {
325
+ const db = await this.getSystemDB();
326
+ await db
327
+ .from('planner_calendar_tokens')
328
+ .update({ is_active: false, updated_at: new Date().toISOString() })
329
+ .eq('user_id', userId);
330
+ logger.info({ userId }, 'Calendar disconnected');
331
+ }
332
+ /**
333
+ * Fetch events from Google Calendar for a date range (for bidirectional sync).
334
+ * Returns busy time blocks.
335
+ */
336
+ async getBusySlots(userId, dateStart, dateEnd) {
337
+ try {
338
+ const oauth2Client = await this.getAuthenticatedClient(userId);
339
+ if (!oauth2Client)
340
+ return [];
341
+ const google = await this.getGoogle();
342
+ const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
343
+ const calendarId = await this.getCalendarId(userId);
344
+ const response = await calendar.events.list({
345
+ calendarId,
346
+ timeMin: `${dateStart}T00:00:00Z`,
347
+ timeMax: `${dateEnd}T23:59:59Z`,
348
+ singleEvents: true,
349
+ orderBy: 'startTime',
350
+ });
351
+ const events = response.data.items || [];
352
+ return events
353
+ .filter((e) => e.start?.dateTime && e.end?.dateTime && e.status !== 'cancelled')
354
+ .map((e) => ({
355
+ start_time: e.start.dateTime,
356
+ end_time: e.end.dateTime,
357
+ }));
358
+ }
359
+ catch (error) {
360
+ logger.error({ error, userId }, 'Failed to fetch busy slots from Google Calendar');
361
+ return [];
362
+ }
363
+ }
364
+ }
365
+ //# sourceMappingURL=GoogleCalendarService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleCalendarService.js","sourceRoot":"","sources":["../../../src/shared/planner/GoogleCalendarService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * PlannerService — Core scheduling logic
3
+ *
4
+ * Handles:
5
+ * - Availability CRUD (multiple blocks per day)
6
+ * - Appointment CRUD with conflict detection
7
+ * - Vacation-aware slot computation
8
+ * - Team availability aggregation
9
+ * - Scheduler settings management
10
+ *
11
+ * Usage:
12
+ * ```typescript
13
+ * import { PlannerService } from '@soulbatical/tetra-core';
14
+ *
15
+ * const planner = new PlannerService(config);
16
+ * const slots = await planner.getAvailableSlots(db, ownerId, '2026-03-20');
17
+ * ```
18
+ */
19
+ import type { SupabaseClient } from '@supabase/supabase-js';
20
+ import type { PlannerConfig, AvailabilitySlotInput, AppointmentRecord, TimeSlot, DayAvailability, TeamAvailability, PublicSchedulerData, PublicBookingInput } from './types.js';
21
+ export declare function timeToMinutes(time: string): number;
22
+ export declare function minutesToTime(minutes: number): string;
23
+ /**
24
+ * Compute bookable time slots from availability windows, minus existing appointments.
25
+ * Pure function — no DB access.
26
+ */
27
+ export declare function computeAvailableSlots(availabilitySlots: Array<{
28
+ start_time: string;
29
+ end_time: string;
30
+ is_available: boolean;
31
+ }>, existingAppointments: Array<{
32
+ start_time: string;
33
+ end_time: string;
34
+ }>, date: string, slotDurationMinutes?: number): TimeSlot[];
35
+ export declare class PlannerService {
36
+ private config;
37
+ constructor(config: PlannerConfig);
38
+ get ownerRole(): string;
39
+ get ownerTable(): string;
40
+ get timezone(): string;
41
+ get appointmentTypes(): string[];
42
+ get appointmentStatuses(): string[];
43
+ /**
44
+ * Get an owner's recurring availability slots.
45
+ */
46
+ getAvailability(db: SupabaseClient, ownerId: string): Promise<{
47
+ id: any;
48
+ organizationId: any;
49
+ ownerId: any;
50
+ dayOfWeek: any;
51
+ startTime: any;
52
+ endTime: any;
53
+ isAvailable: any;
54
+ createdAt: any;
55
+ updatedAt: any;
56
+ }[]>;
57
+ /**
58
+ * Replace all availability slots for an owner.
59
+ */
60
+ setAvailability(db: SupabaseClient, ownerId: string, organizationId: string, slots: AvailabilitySlotInput[]): Promise<any[]>;
61
+ /**
62
+ * Check if a date falls within any vacation for an owner.
63
+ */
64
+ isOnVacation(db: SupabaseClient, ownerId: string, date: string): Promise<boolean>;
65
+ /**
66
+ * Get all vacations for an owner.
67
+ */
68
+ getVacations(db: SupabaseClient, ownerId: string): Promise<{
69
+ id: any;
70
+ organizationId: any;
71
+ ownerId: any;
72
+ startDate: any;
73
+ endDate: any;
74
+ description: any;
75
+ createdAt: any;
76
+ updatedAt: any;
77
+ }[]>;
78
+ /**
79
+ * Create a vacation period.
80
+ */
81
+ createVacation(db: SupabaseClient, ownerId: string, organizationId: string, startDate: string, endDate: string, description?: string): Promise<any>;
82
+ /**
83
+ * Delete a vacation.
84
+ */
85
+ deleteVacation(db: SupabaseClient, vacationId: string): Promise<void>;
86
+ /**
87
+ * Get scheduler settings for an owner.
88
+ */
89
+ getSettings(db: SupabaseClient, ownerId: string): Promise<{
90
+ eventName: any;
91
+ zoomLink: any;
92
+ description: any;
93
+ sessionDurationMinutes: any;
94
+ maxDaysAhead: any;
95
+ minLeadTimeHours: any;
96
+ timeIncrementMinutes: any;
97
+ }>;
98
+ /**
99
+ * Upsert scheduler settings for an owner.
100
+ */
101
+ updateSettings(db: SupabaseClient, ownerId: string, organizationId: string, settings: Partial<{
102
+ eventName: string;
103
+ zoomLink: string | null;
104
+ description: string | null;
105
+ sessionDurationMinutes: number;
106
+ maxDaysAhead: number;
107
+ minLeadTimeHours: number;
108
+ timeIncrementMinutes: number;
109
+ }>): Promise<any>;
110
+ /**
111
+ * Compute available booking slots for a specific date.
112
+ * Checks: availability, vacations, existing appointments, booking window, lead time.
113
+ */
114
+ getAvailableSlots(db: SupabaseClient, ownerId: string, date: string): Promise<DayAvailability>;
115
+ /**
116
+ * Get existing scheduled appointments for an owner on a date.
117
+ */
118
+ private getExistingAppointments;
119
+ /**
120
+ * Get availability for all owners in an organization for a specific date.
121
+ */
122
+ getTeamAvailability(db: SupabaseClient, organizationId: string, date: string): Promise<TeamAvailability>;
123
+ /**
124
+ * List all appointments for a user (as organizer or via parent resources).
125
+ */
126
+ listAppointments(db: SupabaseClient, userId: string, options?: {
127
+ status?: string;
128
+ }): Promise<AppointmentRecord[]>;
129
+ /**
130
+ * Create an appointment.
131
+ */
132
+ createAppointment(db: SupabaseClient, organizerId: string, organizationId: string, input: {
133
+ title: string;
134
+ parentId?: string;
135
+ description?: string;
136
+ startTime: string;
137
+ endTime: string;
138
+ location?: string;
139
+ type?: string;
140
+ attendeeIds?: string[];
141
+ }): Promise<AppointmentRecord>;
142
+ /**
143
+ * Update an appointment.
144
+ */
145
+ updateAppointment(db: SupabaseClient, appointmentId: string, updates: Partial<{
146
+ title: string;
147
+ description: string;
148
+ startTime: string;
149
+ endTime: string;
150
+ location: string;
151
+ type: string;
152
+ }>): Promise<AppointmentRecord>;
153
+ /**
154
+ * Cancel an appointment (soft delete).
155
+ */
156
+ cancelAppointment(db: SupabaseClient, appointmentId: string, organizationId: string): Promise<AppointmentRecord>;
157
+ /**
158
+ * Complete an appointment.
159
+ */
160
+ completeAppointment(db: SupabaseClient, appointmentId: string, organizationId: string): Promise<AppointmentRecord>;
161
+ /**
162
+ * Get public scheduler page data (no auth).
163
+ */
164
+ getPublicSchedulerData(db: SupabaseClient, ownerId: string): Promise<PublicSchedulerData | null>;
165
+ /**
166
+ * Book a slot via public booking (no auth).
167
+ */
168
+ publicBook(db: SupabaseClient, ownerId: string, input: PublicBookingInput): Promise<AppointmentRecord>;
169
+ }
170
+ //# sourceMappingURL=PlannerService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlannerService.d.ts","sourceRoot":"","sources":["../../../src/shared/planner/PlannerService.ts"],"names":[],"mappings":"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"}