@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.
- package/dist/core/dualWriteProxy.d.ts +11 -0
- package/dist/core/dualWriteProxy.d.ts.map +1 -1
- package/dist/core/dualWriteProxy.js +142 -198
- package/dist/core/dualWriteProxy.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/email/EmailService.d.ts +9 -1
- package/dist/shared/email/EmailService.d.ts.map +1 -1
- package/dist/shared/email/EmailService.js +83 -7
- package/dist/shared/email/EmailService.js.map +1 -1
- package/dist/shared/email/adminRoutes.d.ts +30 -0
- package/dist/shared/email/adminRoutes.d.ts.map +1 -0
- package/dist/shared/email/adminRoutes.js +227 -0
- package/dist/shared/email/adminRoutes.js.map +1 -0
- package/dist/shared/email/index.d.ts +3 -1
- package/dist/shared/email/index.d.ts.map +1 -1
- package/dist/shared/email/index.js +3 -0
- package/dist/shared/email/index.js.map +1 -1
- package/dist/shared/email/mailgun.d.ts +4 -1
- package/dist/shared/email/mailgun.d.ts.map +1 -1
- package/dist/shared/email/mailgun.js +41 -10
- package/dist/shared/email/mailgun.js.map +1 -1
- package/dist/shared/email/smtp.d.ts +4 -1
- package/dist/shared/email/smtp.d.ts.map +1 -1
- package/dist/shared/email/smtp.js +14 -2
- package/dist/shared/email/smtp.js.map +1 -1
- package/dist/shared/email/types.d.ts +23 -1
- package/dist/shared/email/types.d.ts.map +1 -1
- package/dist/shared/email/webhookRoutes.d.ts +29 -0
- package/dist/shared/email/webhookRoutes.d.ts.map +1 -0
- package/dist/shared/email/webhookRoutes.js +125 -0
- package/dist/shared/email/webhookRoutes.js.map +1 -0
- package/dist/shared/planner/GoogleCalendarService.d.ts +103 -0
- package/dist/shared/planner/GoogleCalendarService.d.ts.map +1 -0
- package/dist/shared/planner/GoogleCalendarService.js +365 -0
- package/dist/shared/planner/GoogleCalendarService.js.map +1 -0
- package/dist/shared/planner/PlannerService.d.ts +170 -0
- package/dist/shared/planner/PlannerService.d.ts.map +1 -0
- package/dist/shared/planner/PlannerService.js +860 -0
- package/dist/shared/planner/PlannerService.js.map +1 -0
- package/dist/shared/planner/index.d.ts +35 -0
- package/dist/shared/planner/index.d.ts.map +1 -0
- package/dist/shared/planner/index.js +34 -0
- package/dist/shared/planner/index.js.map +1 -0
- package/dist/shared/planner/routes.d.ts +67 -0
- package/dist/shared/planner/routes.d.ts.map +1 -0
- package/dist/shared/planner/routes.js +524 -0
- package/dist/shared/planner/routes.js.map +1 -0
- package/dist/shared/planner/types.d.ts +262 -0
- package/dist/shared/planner/types.d.ts.map +1 -0
- package/dist/shared/planner/types.js +9 -0
- package/dist/shared/planner/types.js.map +1 -0
- package/package.json +1 -1
- package/src/shared/email/migrations/004_add_email_logs_tracking_columns.sql +15 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Planner Route Factories — standard scheduling endpoints
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { addPlannerRoutes, addPlannerPublicRoutes, addPlannerCalendarRoutes } from '@soulbatical/tetra-core';
|
|
7
|
+
*
|
|
8
|
+
* // Authenticated (behind auth middleware)
|
|
9
|
+
* addPlannerRoutes(router, { config });
|
|
10
|
+
*
|
|
11
|
+
* // Public booking (no auth)
|
|
12
|
+
* addPlannerPublicRoutes(publicRouter, { config, getSystemDB });
|
|
13
|
+
*
|
|
14
|
+
* // Google Calendar OAuth (behind auth middleware)
|
|
15
|
+
* addPlannerCalendarRoutes(calendarRouter, { google: {...} });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import { PlannerService } from './PlannerService.js';
|
|
19
|
+
import { GoogleCalendarService } from './GoogleCalendarService.js';
|
|
20
|
+
import { RFC7807ErrorResponse } from '../rfc7807ErrorResponse.js';
|
|
21
|
+
import { createLogger } from '../../utils/logger.js';
|
|
22
|
+
const logger = createLogger('planner:routes');
|
|
23
|
+
const TIME_REGEX = /^\d{2}:\d{2}(:\d{2})?$/;
|
|
24
|
+
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
25
|
+
// ─── Authenticated Planner Routes ───────────────────────────
|
|
26
|
+
/**
|
|
27
|
+
* Add authenticated planner routes to a router.
|
|
28
|
+
*
|
|
29
|
+
* Adds:
|
|
30
|
+
* - GET /availability — Get own availability
|
|
31
|
+
* - PUT /availability — Set own availability
|
|
32
|
+
* - GET /owners/:ownerId/availability — Get an owner's availability
|
|
33
|
+
* - GET /owners/:ownerId/available-slots — Get bookable slots for a date
|
|
34
|
+
* - POST /owners/:ownerId/book — Book a slot with an owner
|
|
35
|
+
* - GET /vacations — List own vacations
|
|
36
|
+
* - POST /vacations — Create vacation
|
|
37
|
+
* - DELETE /vacations/:id — Delete vacation
|
|
38
|
+
* - GET /scheduler-settings — Get own scheduler settings
|
|
39
|
+
* - PUT /scheduler-settings — Update own scheduler settings
|
|
40
|
+
* - GET /appointments — List own appointments
|
|
41
|
+
* - POST /appointments — Create appointment
|
|
42
|
+
* - PUT /appointments/:id — Update appointment
|
|
43
|
+
* - DELETE /appointments/:id — Cancel appointment
|
|
44
|
+
* - POST /appointments/:id/complete — Complete appointment
|
|
45
|
+
* - GET /team-availability — Team availability for a date (admin)
|
|
46
|
+
*
|
|
47
|
+
* Returns the PlannerService instance for external use.
|
|
48
|
+
*/
|
|
49
|
+
export function addPlannerRoutes(router, options) {
|
|
50
|
+
const service = new PlannerService(options.config);
|
|
51
|
+
// ── Availability ────────────────────────────────────────
|
|
52
|
+
// GET /availability — own
|
|
53
|
+
router.get('/availability', async (req, res) => {
|
|
54
|
+
try {
|
|
55
|
+
const user = req.user;
|
|
56
|
+
if (!user?.id)
|
|
57
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
58
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
59
|
+
const db = await adminDB(req);
|
|
60
|
+
const slots = await service.getAvailability(db, user.id);
|
|
61
|
+
res.json({ success: true, data: slots });
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
logger.error({ error: err }, 'Get availability error');
|
|
65
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// PUT /availability — set own
|
|
69
|
+
router.put('/availability', async (req, res) => {
|
|
70
|
+
try {
|
|
71
|
+
const user = req.user;
|
|
72
|
+
if (!user?.id || !user?.organizationId)
|
|
73
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
74
|
+
const { slots } = req.body;
|
|
75
|
+
if (!Array.isArray(slots))
|
|
76
|
+
return RFC7807ErrorResponse.badRequest(res, 'slots must be an array');
|
|
77
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
78
|
+
const db = await adminDB(req);
|
|
79
|
+
const result = await service.setAvailability(db, user.id, user.organizationId, slots);
|
|
80
|
+
res.json({ success: true, data: result });
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
logger.error({ error: err }, 'Set availability error');
|
|
84
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
// GET /owners/:ownerId/availability
|
|
88
|
+
router.get('/owners/:ownerId/availability', async (req, res) => {
|
|
89
|
+
try {
|
|
90
|
+
const user = req.user;
|
|
91
|
+
if (!user?.id)
|
|
92
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
93
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
94
|
+
const db = await adminDB(req);
|
|
95
|
+
const slots = await service.getAvailability(db, req.params.ownerId);
|
|
96
|
+
res.json({ success: true, data: slots });
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
logger.error({ error: err }, 'Get owner availability error');
|
|
100
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// GET /owners/:ownerId/available-slots?date=YYYY-MM-DD
|
|
104
|
+
router.get('/owners/:ownerId/available-slots', async (req, res) => {
|
|
105
|
+
try {
|
|
106
|
+
const user = req.user;
|
|
107
|
+
if (!user?.id)
|
|
108
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
109
|
+
const date = req.query.date;
|
|
110
|
+
if (!date || !DATE_REGEX.test(date))
|
|
111
|
+
return RFC7807ErrorResponse.badRequest(res, 'date query parameter required (YYYY-MM-DD)');
|
|
112
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
113
|
+
const db = await adminDB(req);
|
|
114
|
+
const result = await service.getAvailableSlots(db, req.params.ownerId, date);
|
|
115
|
+
res.json({ success: true, data: result });
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
logger.error({ error: err }, 'Get available slots error');
|
|
119
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// POST /owners/:ownerId/book
|
|
123
|
+
router.post('/owners/:ownerId/book', async (req, res) => {
|
|
124
|
+
try {
|
|
125
|
+
const user = req.user;
|
|
126
|
+
if (!user?.id || !user?.organizationId)
|
|
127
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
128
|
+
const { parentId, date, startTime, endTime, title } = req.body;
|
|
129
|
+
if (!date || !startTime || !endTime)
|
|
130
|
+
return RFC7807ErrorResponse.badRequest(res, 'date, startTime, and endTime are required');
|
|
131
|
+
const startISO = `${date}T${startTime.length === 5 ? startTime + ':00' : startTime}Z`;
|
|
132
|
+
const endISO = `${date}T${endTime.length === 5 ? endTime + ':00' : endTime}Z`;
|
|
133
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
134
|
+
const db = await adminDB(req);
|
|
135
|
+
const appointment = await service.createAppointment(db, user.id, user.organizationId, {
|
|
136
|
+
title: title || 'Session',
|
|
137
|
+
parentId,
|
|
138
|
+
startTime: startISO,
|
|
139
|
+
endTime: endISO,
|
|
140
|
+
});
|
|
141
|
+
res.status(201).json({ success: true, data: appointment });
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
logger.error({ error: err }, 'Book slot error');
|
|
145
|
+
if (err.message.includes('conflict') || err.message.includes('outside')) {
|
|
146
|
+
RFC7807ErrorResponse.conflict(res, err.message);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
// ── Vacations ───────────────────────────────────────────
|
|
154
|
+
router.get('/vacations', async (req, res) => {
|
|
155
|
+
try {
|
|
156
|
+
const user = req.user;
|
|
157
|
+
if (!user?.id)
|
|
158
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
159
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
160
|
+
const db = await adminDB(req);
|
|
161
|
+
const vacations = await service.getVacations(db, user.id);
|
|
162
|
+
res.json({ success: true, data: vacations });
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
router.post('/vacations', async (req, res) => {
|
|
169
|
+
try {
|
|
170
|
+
const user = req.user;
|
|
171
|
+
if (!user?.id || !user?.organizationId)
|
|
172
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
173
|
+
const { startDate, endDate, description } = req.body;
|
|
174
|
+
if (!startDate || !endDate)
|
|
175
|
+
return RFC7807ErrorResponse.badRequest(res, 'startDate and endDate are required');
|
|
176
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
177
|
+
const db = await adminDB(req);
|
|
178
|
+
const vacation = await service.createVacation(db, user.id, user.organizationId, startDate, endDate, description);
|
|
179
|
+
res.status(201).json({ success: true, data: vacation });
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
router.delete('/vacations/:id', async (req, res) => {
|
|
186
|
+
try {
|
|
187
|
+
const user = req.user;
|
|
188
|
+
if (!user?.id)
|
|
189
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
190
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
191
|
+
const db = await adminDB(req);
|
|
192
|
+
await service.deleteVacation(db, req.params.id);
|
|
193
|
+
res.json({ success: true });
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
// ── Scheduler Settings ──────────────────────────────────
|
|
200
|
+
router.get('/scheduler-settings', async (req, res) => {
|
|
201
|
+
try {
|
|
202
|
+
const user = req.user;
|
|
203
|
+
if (!user?.id)
|
|
204
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
205
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
206
|
+
const db = await adminDB(req);
|
|
207
|
+
const settings = await service.getSettings(db, user.id);
|
|
208
|
+
res.json({ success: true, data: settings });
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
router.put('/scheduler-settings', async (req, res) => {
|
|
215
|
+
try {
|
|
216
|
+
const user = req.user;
|
|
217
|
+
if (!user?.id || !user?.organizationId)
|
|
218
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
219
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
220
|
+
const db = await adminDB(req);
|
|
221
|
+
const result = await service.updateSettings(db, user.id, user.organizationId, req.body);
|
|
222
|
+
res.json({ success: true, data: result });
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
// ── Appointments ────────────────────────────────────────
|
|
229
|
+
router.get('/appointments', async (req, res) => {
|
|
230
|
+
try {
|
|
231
|
+
const user = req.user;
|
|
232
|
+
if (!user?.id)
|
|
233
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
234
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
235
|
+
const db = await adminDB(req);
|
|
236
|
+
const appointments = await service.listAppointments(db, user.id, {
|
|
237
|
+
status: req.query.status,
|
|
238
|
+
});
|
|
239
|
+
res.json({ success: true, data: appointments });
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
router.post('/appointments', async (req, res) => {
|
|
246
|
+
try {
|
|
247
|
+
const user = req.user;
|
|
248
|
+
if (!user?.id || !user?.organizationId)
|
|
249
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
250
|
+
const { title, parentId, description, startTime, endTime, location, type, attendeeIds } = req.body;
|
|
251
|
+
if (!title || !startTime || !endTime)
|
|
252
|
+
return RFC7807ErrorResponse.badRequest(res, 'title, startTime, and endTime are required');
|
|
253
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
254
|
+
const db = await adminDB(req);
|
|
255
|
+
const appointment = await service.createAppointment(db, user.id, user.organizationId, {
|
|
256
|
+
title, parentId, description, startTime, endTime, location, type, attendeeIds,
|
|
257
|
+
});
|
|
258
|
+
res.status(201).json({ success: true, data: appointment });
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
if (err.message.includes('Invalid'))
|
|
262
|
+
RFC7807ErrorResponse.badRequest(res, err.message);
|
|
263
|
+
else
|
|
264
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
router.put('/appointments/:id', async (req, res) => {
|
|
268
|
+
try {
|
|
269
|
+
const user = req.user;
|
|
270
|
+
if (!user?.id)
|
|
271
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
272
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
273
|
+
const db = await adminDB(req);
|
|
274
|
+
const appointment = await service.updateAppointment(db, req.params.id, req.body);
|
|
275
|
+
res.json({ success: true, data: appointment });
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
if (err.message === 'Appointment not found')
|
|
279
|
+
RFC7807ErrorResponse.notFound(res, 'Appointment');
|
|
280
|
+
else
|
|
281
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
router.delete('/appointments/:id', async (req, res) => {
|
|
285
|
+
try {
|
|
286
|
+
const user = req.user;
|
|
287
|
+
if (!user?.id || !user?.organizationId)
|
|
288
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
289
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
290
|
+
const db = await adminDB(req);
|
|
291
|
+
const appointment = await service.cancelAppointment(db, req.params.id, user.organizationId);
|
|
292
|
+
res.json({ success: true, data: appointment });
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
if (err.message === 'Appointment not found')
|
|
296
|
+
RFC7807ErrorResponse.notFound(res, 'Appointment');
|
|
297
|
+
else
|
|
298
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
router.post('/appointments/:id/complete', async (req, res) => {
|
|
302
|
+
try {
|
|
303
|
+
const user = req.user;
|
|
304
|
+
if (!user?.id || !user?.organizationId)
|
|
305
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
306
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
307
|
+
const db = await adminDB(req);
|
|
308
|
+
const appointment = await service.completeAppointment(db, req.params.id, user.organizationId);
|
|
309
|
+
res.json({ success: true, data: appointment });
|
|
310
|
+
}
|
|
311
|
+
catch (err) {
|
|
312
|
+
if (err.message === 'Appointment not found')
|
|
313
|
+
RFC7807ErrorResponse.notFound(res, 'Appointment');
|
|
314
|
+
else
|
|
315
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
// ── Team Availability ───────────────────────────────────
|
|
319
|
+
router.get('/team-availability', async (req, res) => {
|
|
320
|
+
try {
|
|
321
|
+
const user = req.user;
|
|
322
|
+
if (!user?.id || !user?.organizationId)
|
|
323
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
324
|
+
const date = req.query.date;
|
|
325
|
+
if (!date || !DATE_REGEX.test(date))
|
|
326
|
+
return RFC7807ErrorResponse.badRequest(res, 'date query parameter required (YYYY-MM-DD)');
|
|
327
|
+
const { adminDB } = await import('../../core/adminDb.js');
|
|
328
|
+
const db = await adminDB(req);
|
|
329
|
+
const result = await service.getTeamAvailability(db, user.organizationId, date);
|
|
330
|
+
res.json({ success: true, data: result });
|
|
331
|
+
}
|
|
332
|
+
catch (err) {
|
|
333
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
return service;
|
|
337
|
+
}
|
|
338
|
+
// ─── Public Planner Routes (no auth) ────────────────────────
|
|
339
|
+
/**
|
|
340
|
+
* Add public booking routes (Calendly-style, no authentication).
|
|
341
|
+
*
|
|
342
|
+
* Adds:
|
|
343
|
+
* - GET /scheduler/:ownerId — Scheduler page data
|
|
344
|
+
* - GET /scheduler/:ownerId/slots — Available slots for a date
|
|
345
|
+
* - POST /scheduler/:ownerId/book — Book a slot
|
|
346
|
+
*/
|
|
347
|
+
export function addPlannerPublicRoutes(router, options) {
|
|
348
|
+
const service = new PlannerService(options.config);
|
|
349
|
+
const getDB = async () => {
|
|
350
|
+
if (options.getSystemDB)
|
|
351
|
+
return options.getSystemDB();
|
|
352
|
+
const { systemDB } = await import('../../core/systemDb.js');
|
|
353
|
+
return systemDB('planner:public');
|
|
354
|
+
};
|
|
355
|
+
// GET /scheduler/:ownerId
|
|
356
|
+
router.get('/scheduler/:ownerId', async (req, res) => {
|
|
357
|
+
try {
|
|
358
|
+
const db = await getDB();
|
|
359
|
+
const data = await service.getPublicSchedulerData(db, req.params.ownerId);
|
|
360
|
+
if (!data)
|
|
361
|
+
return RFC7807ErrorResponse.notFound(res, 'Owner');
|
|
362
|
+
res.json({ success: true, data });
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
// GET /scheduler/:ownerId/slots?date=YYYY-MM-DD
|
|
369
|
+
router.get('/scheduler/:ownerId/slots', async (req, res) => {
|
|
370
|
+
try {
|
|
371
|
+
const date = req.query.date;
|
|
372
|
+
if (!date || !DATE_REGEX.test(date))
|
|
373
|
+
return RFC7807ErrorResponse.badRequest(res, 'date required (YYYY-MM-DD)');
|
|
374
|
+
const db = await getDB();
|
|
375
|
+
const result = await service.getAvailableSlots(db, req.params.ownerId, date);
|
|
376
|
+
res.json({ success: true, data: result });
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
// POST /scheduler/:ownerId/book
|
|
383
|
+
router.post('/scheduler/:ownerId/book', async (req, res) => {
|
|
384
|
+
try {
|
|
385
|
+
const db = await getDB();
|
|
386
|
+
const appointment = await service.publicBook(db, req.params.ownerId, req.body);
|
|
387
|
+
res.status(201).json({ success: true, data: appointment });
|
|
388
|
+
}
|
|
389
|
+
catch (err) {
|
|
390
|
+
if (err.message.includes('outside') || err.message.includes('no longer') || err.message.includes('vacation')) {
|
|
391
|
+
RFC7807ErrorResponse.conflict(res, err.message);
|
|
392
|
+
}
|
|
393
|
+
else if (err.message.includes('required') || err.message.includes('Invalid')) {
|
|
394
|
+
RFC7807ErrorResponse.badRequest(res, err.message);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
return service;
|
|
402
|
+
}
|
|
403
|
+
// ─── Google Calendar Routes ─────────────────────────────────
|
|
404
|
+
/**
|
|
405
|
+
* Add Google Calendar OAuth routes.
|
|
406
|
+
*
|
|
407
|
+
* Adds:
|
|
408
|
+
* - GET /auth-url — Generate OAuth URL
|
|
409
|
+
* - GET /callback — Handle OAuth callback
|
|
410
|
+
* - GET /status — Connection status
|
|
411
|
+
* - GET /calendars — List available calendars
|
|
412
|
+
* - PUT /calendar-id — Select calendar
|
|
413
|
+
* - POST /disconnect — Remove connection
|
|
414
|
+
*/
|
|
415
|
+
export function addPlannerCalendarRoutes(router, config) {
|
|
416
|
+
const calService = new GoogleCalendarService(config);
|
|
417
|
+
// GET /auth-url
|
|
418
|
+
router.get('/auth-url', async (req, res) => {
|
|
419
|
+
try {
|
|
420
|
+
const user = req.user;
|
|
421
|
+
if (!user?.id)
|
|
422
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
423
|
+
const url = await calService.getAuthUrl(user.id);
|
|
424
|
+
res.json({ success: true, data: { url } });
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
// GET /callback
|
|
431
|
+
router.get('/callback', async (req, res) => {
|
|
432
|
+
try {
|
|
433
|
+
const code = req.query.code;
|
|
434
|
+
const stateRaw = req.query.state;
|
|
435
|
+
if (!code || !stateRaw)
|
|
436
|
+
return RFC7807ErrorResponse.badRequest(res, 'Missing code or state');
|
|
437
|
+
let state;
|
|
438
|
+
try {
|
|
439
|
+
state = JSON.parse(Buffer.from(stateRaw, 'base64').toString());
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
return RFC7807ErrorResponse.badRequest(res, 'Invalid state');
|
|
443
|
+
}
|
|
444
|
+
// Look up org for user
|
|
445
|
+
const { systemDB } = await import('../../core/systemDb.js');
|
|
446
|
+
const db = await systemDB('planner:calendar-callback');
|
|
447
|
+
const { data: userData } = await db
|
|
448
|
+
.from('users_public')
|
|
449
|
+
.select('active_organization_id')
|
|
450
|
+
.eq('id', state.userId)
|
|
451
|
+
.single();
|
|
452
|
+
if (!userData)
|
|
453
|
+
return RFC7807ErrorResponse.notFound(res, 'User');
|
|
454
|
+
await calService.handleCallback(code, state.userId, userData.active_organization_id);
|
|
455
|
+
// Redirect to frontend settings
|
|
456
|
+
const frontendUrl = process.env.FRONTEND_URL || '';
|
|
457
|
+
res.redirect(`${frontendUrl}/settings?calendar=connected`);
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
logger.error({ error: err }, 'Calendar callback error');
|
|
461
|
+
const frontendUrl = process.env.FRONTEND_URL || '';
|
|
462
|
+
res.redirect(`${frontendUrl}/settings?calendar=error&reason=exchange_failed`);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
// GET /status
|
|
466
|
+
router.get('/status', async (req, res) => {
|
|
467
|
+
try {
|
|
468
|
+
const user = req.user;
|
|
469
|
+
if (!user?.id)
|
|
470
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
471
|
+
const connected = await calService.isConnected(user.id);
|
|
472
|
+
res.json({ success: true, data: { connected } });
|
|
473
|
+
}
|
|
474
|
+
catch (err) {
|
|
475
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
// GET /calendars
|
|
479
|
+
router.get('/calendars', async (req, res) => {
|
|
480
|
+
try {
|
|
481
|
+
const user = req.user;
|
|
482
|
+
if (!user?.id)
|
|
483
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
484
|
+
const calendars = await calService.listCalendars(user.id);
|
|
485
|
+
res.json({ success: true, data: calendars || [] });
|
|
486
|
+
}
|
|
487
|
+
catch (err) {
|
|
488
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
// PUT /calendar-id
|
|
492
|
+
router.put('/calendar-id', async (req, res) => {
|
|
493
|
+
try {
|
|
494
|
+
const user = req.user;
|
|
495
|
+
if (!user?.id)
|
|
496
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
497
|
+
const { calendarId } = req.body;
|
|
498
|
+
if (!calendarId)
|
|
499
|
+
return RFC7807ErrorResponse.badRequest(res, 'calendarId is required');
|
|
500
|
+
const success = await calService.selectCalendar(user.id, calendarId);
|
|
501
|
+
if (!success)
|
|
502
|
+
return RFC7807ErrorResponse.internalError(res, 'Failed to select calendar');
|
|
503
|
+
res.json({ success: true });
|
|
504
|
+
}
|
|
505
|
+
catch (err) {
|
|
506
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
// POST /disconnect
|
|
510
|
+
router.post('/disconnect', async (req, res) => {
|
|
511
|
+
try {
|
|
512
|
+
const user = req.user;
|
|
513
|
+
if (!user?.id)
|
|
514
|
+
return RFC7807ErrorResponse.unauthorized(res, 'Authentication required');
|
|
515
|
+
await calService.disconnect(user.id);
|
|
516
|
+
res.json({ success: true });
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
RFC7807ErrorResponse.internalError(res, err.message || 'Failed');
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
return calService;
|
|
523
|
+
}
|
|
524
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/shared/planner/routes.ts"],"names":[],"mappings":"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"}
|