@voyantjs/availability 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAyCjE,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAgGD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCAmnB3B,CAAA;AAEJ,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAA"}
package/dist/routes.js ADDED
@@ -0,0 +1,541 @@
1
+ import { Hono } from "hono";
2
+ import { z } from "zod";
3
+ import { availabilityService } from "./service.js";
4
+ import { availabilityCloseoutListQuerySchema, availabilityPickupPointListQuerySchema, availabilityRuleListQuerySchema, availabilitySlotListQuerySchema, availabilitySlotPickupListQuerySchema, availabilityStartTimeListQuerySchema, customPickupAreaListQuerySchema, insertAvailabilityCloseoutSchema, insertAvailabilityPickupPointSchema, insertAvailabilityRuleSchema, insertAvailabilitySlotPickupSchema, insertAvailabilitySlotSchema, insertAvailabilityStartTimeSchema, insertCustomPickupAreaSchema, insertLocationPickupTimeSchema, insertPickupGroupSchema, insertPickupLocationSchema, insertProductMeetingConfigSchema, locationPickupTimeListQuerySchema, pickupGroupListQuerySchema, pickupLocationListQuerySchema, productMeetingConfigListQuerySchema, updateAvailabilityCloseoutSchema, updateAvailabilityPickupPointSchema, updateAvailabilityRuleSchema, updateAvailabilitySlotPickupSchema, updateAvailabilitySlotSchema, updateAvailabilityStartTimeSchema, updateCustomPickupAreaSchema, updateLocationPickupTimeSchema, updatePickupGroupSchema, updatePickupLocationSchema, updateProductMeetingConfigSchema, } from "./validation.js";
5
+ const batchIdsSchema = z.object({
6
+ ids: z.array(z.string()).min(1).max(200),
7
+ });
8
+ const createBatchUpdateSchema = (patchSchema) => z.object({
9
+ ids: batchIdsSchema.shape.ids,
10
+ patch: patchSchema.refine((value) => Object.keys(value).length > 0, {
11
+ message: "Patch payload is required",
12
+ }),
13
+ });
14
+ const batchUpdateAvailabilityRuleSchema = createBatchUpdateSchema(updateAvailabilityRuleSchema);
15
+ const batchUpdateAvailabilityStartTimeSchema = createBatchUpdateSchema(updateAvailabilityStartTimeSchema);
16
+ const batchUpdateAvailabilitySlotSchema = createBatchUpdateSchema(updateAvailabilitySlotSchema);
17
+ const batchUpdateAvailabilityCloseoutSchema = createBatchUpdateSchema(updateAvailabilityCloseoutSchema);
18
+ const batchUpdateAvailabilityPickupPointSchema = createBatchUpdateSchema(updateAvailabilityPickupPointSchema);
19
+ const batchUpdateAvailabilitySlotPickupSchema = createBatchUpdateSchema(updateAvailabilitySlotPickupSchema);
20
+ const batchUpdateProductMeetingConfigSchema = createBatchUpdateSchema(updateProductMeetingConfigSchema);
21
+ const batchUpdatePickupGroupSchema = createBatchUpdateSchema(updatePickupGroupSchema);
22
+ const batchUpdatePickupLocationSchema = createBatchUpdateSchema(updatePickupLocationSchema);
23
+ const batchUpdateLocationPickupTimeSchema = createBatchUpdateSchema(updateLocationPickupTimeSchema);
24
+ const batchUpdateCustomPickupAreaSchema = createBatchUpdateSchema(updateCustomPickupAreaSchema);
25
+ async function handleBatchUpdate({ db, ids, patch, update, }) {
26
+ const results = await Promise.all(ids.map(async (id) => {
27
+ const row = await update(db, id, patch);
28
+ return row ? { id, row } : { id, row: null };
29
+ }));
30
+ const data = results.flatMap((result) => (result.row ? [result.row] : []));
31
+ const failed = results
32
+ .filter((result) => result.row === null)
33
+ .map((result) => ({ id: result.id, error: "Not found" }));
34
+ return {
35
+ data,
36
+ total: ids.length,
37
+ succeeded: data.length,
38
+ failed,
39
+ };
40
+ }
41
+ async function handleBatchDelete({ db, ids, remove, }) {
42
+ const results = await Promise.all(ids.map(async (id) => {
43
+ const row = await remove(db, id);
44
+ return row ? { id } : { id, error: "Not found" };
45
+ }));
46
+ const deletedIds = results.flatMap((result) => ("error" in result ? [] : [result.id]));
47
+ const failed = results
48
+ .filter((result) => "error" in result)
49
+ .map((result) => ({ id: result.id, error: result.error }));
50
+ return {
51
+ deletedIds,
52
+ total: ids.length,
53
+ succeeded: deletedIds.length,
54
+ failed,
55
+ };
56
+ }
57
+ export const availabilityRoutes = new Hono()
58
+ .get("/rules", async (c) => {
59
+ const query = availabilityRuleListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
60
+ return c.json(await availabilityService.listRules(c.get("db"), query));
61
+ })
62
+ .post("/rules", async (c) => {
63
+ return c.json({
64
+ data: await availabilityService.createRule(c.get("db"), insertAvailabilityRuleSchema.parse(await c.req.json())),
65
+ }, 201);
66
+ })
67
+ .post("/rules/batch-update", async (c) => {
68
+ const body = batchUpdateAvailabilityRuleSchema.parse(await c.req.json());
69
+ return c.json(await handleBatchUpdate({
70
+ db: c.get("db"),
71
+ ids: body.ids,
72
+ patch: body.patch,
73
+ update: availabilityService.updateRule,
74
+ }));
75
+ })
76
+ .post("/rules/batch-delete", async (c) => {
77
+ const body = batchIdsSchema.parse(await c.req.json());
78
+ return c.json(await handleBatchDelete({
79
+ db: c.get("db"),
80
+ ids: body.ids,
81
+ remove: availabilityService.deleteRule,
82
+ }));
83
+ })
84
+ .get("/rules/:id", async (c) => {
85
+ const row = await availabilityService.getRuleById(c.get("db"), c.req.param("id"));
86
+ if (!row)
87
+ return c.json({ error: "Availability rule not found" }, 404);
88
+ return c.json({ data: row });
89
+ })
90
+ .patch("/rules/:id", async (c) => {
91
+ const row = await availabilityService.updateRule(c.get("db"), c.req.param("id"), updateAvailabilityRuleSchema.parse(await c.req.json()));
92
+ if (!row)
93
+ return c.json({ error: "Availability rule not found" }, 404);
94
+ return c.json({ data: row });
95
+ })
96
+ .delete("/rules/:id", async (c) => {
97
+ const row = await availabilityService.deleteRule(c.get("db"), c.req.param("id"));
98
+ if (!row)
99
+ return c.json({ error: "Availability rule not found" }, 404);
100
+ return c.json({ success: true });
101
+ })
102
+ .get("/start-times", async (c) => {
103
+ const query = availabilityStartTimeListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
104
+ return c.json(await availabilityService.listStartTimes(c.get("db"), query));
105
+ })
106
+ .post("/start-times", async (c) => {
107
+ return c.json({
108
+ data: await availabilityService.createStartTime(c.get("db"), insertAvailabilityStartTimeSchema.parse(await c.req.json())),
109
+ }, 201);
110
+ })
111
+ .post("/start-times/batch-update", async (c) => {
112
+ const body = batchUpdateAvailabilityStartTimeSchema.parse(await c.req.json());
113
+ return c.json(await handleBatchUpdate({
114
+ db: c.get("db"),
115
+ ids: body.ids,
116
+ patch: body.patch,
117
+ update: availabilityService.updateStartTime,
118
+ }));
119
+ })
120
+ .post("/start-times/batch-delete", async (c) => {
121
+ const body = batchIdsSchema.parse(await c.req.json());
122
+ return c.json(await handleBatchDelete({
123
+ db: c.get("db"),
124
+ ids: body.ids,
125
+ remove: availabilityService.deleteStartTime,
126
+ }));
127
+ })
128
+ .get("/start-times/:id", async (c) => {
129
+ const row = await availabilityService.getStartTimeById(c.get("db"), c.req.param("id"));
130
+ if (!row)
131
+ return c.json({ error: "Availability start time not found" }, 404);
132
+ return c.json({ data: row });
133
+ })
134
+ .patch("/start-times/:id", async (c) => {
135
+ const row = await availabilityService.updateStartTime(c.get("db"), c.req.param("id"), updateAvailabilityStartTimeSchema.parse(await c.req.json()));
136
+ if (!row)
137
+ return c.json({ error: "Availability start time not found" }, 404);
138
+ return c.json({ data: row });
139
+ })
140
+ .delete("/start-times/:id", async (c) => {
141
+ const row = await availabilityService.deleteStartTime(c.get("db"), c.req.param("id"));
142
+ if (!row)
143
+ return c.json({ error: "Availability start time not found" }, 404);
144
+ return c.json({ success: true });
145
+ })
146
+ .get("/slots", async (c) => {
147
+ const query = availabilitySlotListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
148
+ return c.json(await availabilityService.listSlots(c.get("db"), query));
149
+ })
150
+ .post("/slots", async (c) => {
151
+ return c.json({
152
+ data: await availabilityService.createSlot(c.get("db"), insertAvailabilitySlotSchema.parse(await c.req.json())),
153
+ }, 201);
154
+ })
155
+ .post("/slots/batch-update", async (c) => {
156
+ const body = batchUpdateAvailabilitySlotSchema.parse(await c.req.json());
157
+ return c.json(await handleBatchUpdate({
158
+ db: c.get("db"),
159
+ ids: body.ids,
160
+ patch: body.patch,
161
+ update: availabilityService.updateSlot,
162
+ }));
163
+ })
164
+ .post("/slots/batch-delete", async (c) => {
165
+ const body = batchIdsSchema.parse(await c.req.json());
166
+ return c.json(await handleBatchDelete({
167
+ db: c.get("db"),
168
+ ids: body.ids,
169
+ remove: availabilityService.deleteSlot,
170
+ }));
171
+ })
172
+ .get("/slots/:id", async (c) => {
173
+ const row = await availabilityService.getSlotById(c.get("db"), c.req.param("id"));
174
+ if (!row)
175
+ return c.json({ error: "Availability slot not found" }, 404);
176
+ return c.json({ data: row });
177
+ })
178
+ .patch("/slots/:id", async (c) => {
179
+ const row = await availabilityService.updateSlot(c.get("db"), c.req.param("id"), updateAvailabilitySlotSchema.parse(await c.req.json()));
180
+ if (!row)
181
+ return c.json({ error: "Availability slot not found" }, 404);
182
+ return c.json({ data: row });
183
+ })
184
+ .delete("/slots/:id", async (c) => {
185
+ const row = await availabilityService.deleteSlot(c.get("db"), c.req.param("id"));
186
+ if (!row)
187
+ return c.json({ error: "Availability slot not found" }, 404);
188
+ return c.json({ success: true });
189
+ })
190
+ .get("/closeouts", async (c) => {
191
+ const query = availabilityCloseoutListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
192
+ return c.json(await availabilityService.listCloseouts(c.get("db"), query));
193
+ })
194
+ .post("/closeouts", async (c) => {
195
+ return c.json({
196
+ data: await availabilityService.createCloseout(c.get("db"), insertAvailabilityCloseoutSchema.parse(await c.req.json())),
197
+ }, 201);
198
+ })
199
+ .post("/closeouts/batch-update", async (c) => {
200
+ const body = batchUpdateAvailabilityCloseoutSchema.parse(await c.req.json());
201
+ return c.json(await handleBatchUpdate({
202
+ db: c.get("db"),
203
+ ids: body.ids,
204
+ patch: body.patch,
205
+ update: availabilityService.updateCloseout,
206
+ }));
207
+ })
208
+ .post("/closeouts/batch-delete", async (c) => {
209
+ const body = batchIdsSchema.parse(await c.req.json());
210
+ return c.json(await handleBatchDelete({
211
+ db: c.get("db"),
212
+ ids: body.ids,
213
+ remove: availabilityService.deleteCloseout,
214
+ }));
215
+ })
216
+ .get("/closeouts/:id", async (c) => {
217
+ const row = await availabilityService.getCloseoutById(c.get("db"), c.req.param("id"));
218
+ if (!row)
219
+ return c.json({ error: "Availability closeout not found" }, 404);
220
+ return c.json({ data: row });
221
+ })
222
+ .patch("/closeouts/:id", async (c) => {
223
+ const row = await availabilityService.updateCloseout(c.get("db"), c.req.param("id"), updateAvailabilityCloseoutSchema.parse(await c.req.json()));
224
+ if (!row)
225
+ return c.json({ error: "Availability closeout not found" }, 404);
226
+ return c.json({ data: row });
227
+ })
228
+ .delete("/closeouts/:id", async (c) => {
229
+ const row = await availabilityService.deleteCloseout(c.get("db"), c.req.param("id"));
230
+ if (!row)
231
+ return c.json({ error: "Availability closeout not found" }, 404);
232
+ return c.json({ success: true });
233
+ })
234
+ .get("/pickup-points", async (c) => {
235
+ const query = availabilityPickupPointListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
236
+ return c.json(await availabilityService.listPickupPoints(c.get("db"), query));
237
+ })
238
+ .post("/pickup-points", async (c) => {
239
+ return c.json({
240
+ data: await availabilityService.createPickupPoint(c.get("db"), insertAvailabilityPickupPointSchema.parse(await c.req.json())),
241
+ }, 201);
242
+ })
243
+ .post("/pickup-points/batch-update", async (c) => {
244
+ const body = batchUpdateAvailabilityPickupPointSchema.parse(await c.req.json());
245
+ return c.json(await handleBatchUpdate({
246
+ db: c.get("db"),
247
+ ids: body.ids,
248
+ patch: body.patch,
249
+ update: availabilityService.updatePickupPoint,
250
+ }));
251
+ })
252
+ .post("/pickup-points/batch-delete", async (c) => {
253
+ const body = batchIdsSchema.parse(await c.req.json());
254
+ return c.json(await handleBatchDelete({
255
+ db: c.get("db"),
256
+ ids: body.ids,
257
+ remove: availabilityService.deletePickupPoint,
258
+ }));
259
+ })
260
+ .get("/pickup-points/:id", async (c) => {
261
+ const row = await availabilityService.getPickupPointById(c.get("db"), c.req.param("id"));
262
+ if (!row)
263
+ return c.json({ error: "Availability pickup point not found" }, 404);
264
+ return c.json({ data: row });
265
+ })
266
+ .patch("/pickup-points/:id", async (c) => {
267
+ const row = await availabilityService.updatePickupPoint(c.get("db"), c.req.param("id"), updateAvailabilityPickupPointSchema.parse(await c.req.json()));
268
+ if (!row)
269
+ return c.json({ error: "Availability pickup point not found" }, 404);
270
+ return c.json({ data: row });
271
+ })
272
+ .delete("/pickup-points/:id", async (c) => {
273
+ const row = await availabilityService.deletePickupPoint(c.get("db"), c.req.param("id"));
274
+ if (!row)
275
+ return c.json({ error: "Availability pickup point not found" }, 404);
276
+ return c.json({ success: true });
277
+ })
278
+ .get("/slot-pickups", async (c) => {
279
+ const query = availabilitySlotPickupListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
280
+ return c.json(await availabilityService.listSlotPickups(c.get("db"), query));
281
+ })
282
+ .post("/slot-pickups", async (c) => {
283
+ return c.json({
284
+ data: await availabilityService.createSlotPickup(c.get("db"), insertAvailabilitySlotPickupSchema.parse(await c.req.json())),
285
+ }, 201);
286
+ })
287
+ .post("/slot-pickups/batch-update", async (c) => {
288
+ const body = batchUpdateAvailabilitySlotPickupSchema.parse(await c.req.json());
289
+ return c.json(await handleBatchUpdate({
290
+ db: c.get("db"),
291
+ ids: body.ids,
292
+ patch: body.patch,
293
+ update: availabilityService.updateSlotPickup,
294
+ }));
295
+ })
296
+ .post("/slot-pickups/batch-delete", async (c) => {
297
+ const body = batchIdsSchema.parse(await c.req.json());
298
+ return c.json(await handleBatchDelete({
299
+ db: c.get("db"),
300
+ ids: body.ids,
301
+ remove: availabilityService.deleteSlotPickup,
302
+ }));
303
+ })
304
+ .get("/slot-pickups/:id", async (c) => {
305
+ const row = await availabilityService.getSlotPickupById(c.get("db"), c.req.param("id"));
306
+ if (!row)
307
+ return c.json({ error: "Availability slot pickup not found" }, 404);
308
+ return c.json({ data: row });
309
+ })
310
+ .patch("/slot-pickups/:id", async (c) => {
311
+ const row = await availabilityService.updateSlotPickup(c.get("db"), c.req.param("id"), updateAvailabilitySlotPickupSchema.parse(await c.req.json()));
312
+ if (!row)
313
+ return c.json({ error: "Availability slot pickup not found" }, 404);
314
+ return c.json({ data: row });
315
+ })
316
+ .delete("/slot-pickups/:id", async (c) => {
317
+ const row = await availabilityService.deleteSlotPickup(c.get("db"), c.req.param("id"));
318
+ if (!row)
319
+ return c.json({ error: "Availability slot pickup not found" }, 404);
320
+ return c.json({ success: true });
321
+ })
322
+ .get("/meeting-configs", async (c) => {
323
+ const query = productMeetingConfigListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
324
+ return c.json(await availabilityService.listMeetingConfigs(c.get("db"), query));
325
+ })
326
+ .post("/meeting-configs", async (c) => {
327
+ return c.json({
328
+ data: await availabilityService.createMeetingConfig(c.get("db"), insertProductMeetingConfigSchema.parse(await c.req.json())),
329
+ }, 201);
330
+ })
331
+ .post("/meeting-configs/batch-update", async (c) => {
332
+ const body = batchUpdateProductMeetingConfigSchema.parse(await c.req.json());
333
+ return c.json(await handleBatchUpdate({
334
+ db: c.get("db"),
335
+ ids: body.ids,
336
+ patch: body.patch,
337
+ update: availabilityService.updateMeetingConfig,
338
+ }));
339
+ })
340
+ .post("/meeting-configs/batch-delete", async (c) => {
341
+ const body = batchIdsSchema.parse(await c.req.json());
342
+ return c.json(await handleBatchDelete({
343
+ db: c.get("db"),
344
+ ids: body.ids,
345
+ remove: availabilityService.deleteMeetingConfig,
346
+ }));
347
+ })
348
+ .get("/meeting-configs/:id", async (c) => {
349
+ const row = await availabilityService.getMeetingConfigById(c.get("db"), c.req.param("id"));
350
+ if (!row)
351
+ return c.json({ error: "Product meeting config not found" }, 404);
352
+ return c.json({ data: row });
353
+ })
354
+ .patch("/meeting-configs/:id", async (c) => {
355
+ const row = await availabilityService.updateMeetingConfig(c.get("db"), c.req.param("id"), updateProductMeetingConfigSchema.parse(await c.req.json()));
356
+ if (!row)
357
+ return c.json({ error: "Product meeting config not found" }, 404);
358
+ return c.json({ data: row });
359
+ })
360
+ .delete("/meeting-configs/:id", async (c) => {
361
+ const row = await availabilityService.deleteMeetingConfig(c.get("db"), c.req.param("id"));
362
+ if (!row)
363
+ return c.json({ error: "Product meeting config not found" }, 404);
364
+ return c.json({ success: true });
365
+ })
366
+ .get("/pickup-groups", async (c) => {
367
+ const query = pickupGroupListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
368
+ return c.json(await availabilityService.listPickupGroups(c.get("db"), query));
369
+ })
370
+ .post("/pickup-groups", async (c) => {
371
+ return c.json({
372
+ data: await availabilityService.createPickupGroup(c.get("db"), insertPickupGroupSchema.parse(await c.req.json())),
373
+ }, 201);
374
+ })
375
+ .post("/pickup-groups/batch-update", async (c) => {
376
+ const body = batchUpdatePickupGroupSchema.parse(await c.req.json());
377
+ return c.json(await handleBatchUpdate({
378
+ db: c.get("db"),
379
+ ids: body.ids,
380
+ patch: body.patch,
381
+ update: availabilityService.updatePickupGroup,
382
+ }));
383
+ })
384
+ .post("/pickup-groups/batch-delete", async (c) => {
385
+ const body = batchIdsSchema.parse(await c.req.json());
386
+ return c.json(await handleBatchDelete({
387
+ db: c.get("db"),
388
+ ids: body.ids,
389
+ remove: availabilityService.deletePickupGroup,
390
+ }));
391
+ })
392
+ .get("/pickup-groups/:id", async (c) => {
393
+ const row = await availabilityService.getPickupGroupById(c.get("db"), c.req.param("id"));
394
+ if (!row)
395
+ return c.json({ error: "Pickup group not found" }, 404);
396
+ return c.json({ data: row });
397
+ })
398
+ .patch("/pickup-groups/:id", async (c) => {
399
+ const row = await availabilityService.updatePickupGroup(c.get("db"), c.req.param("id"), updatePickupGroupSchema.parse(await c.req.json()));
400
+ if (!row)
401
+ return c.json({ error: "Pickup group not found" }, 404);
402
+ return c.json({ data: row });
403
+ })
404
+ .delete("/pickup-groups/:id", async (c) => {
405
+ const row = await availabilityService.deletePickupGroup(c.get("db"), c.req.param("id"));
406
+ if (!row)
407
+ return c.json({ error: "Pickup group not found" }, 404);
408
+ return c.json({ success: true });
409
+ })
410
+ .get("/pickup-locations", async (c) => {
411
+ const query = pickupLocationListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
412
+ return c.json(await availabilityService.listPickupLocations(c.get("db"), query));
413
+ })
414
+ .post("/pickup-locations", async (c) => {
415
+ return c.json({
416
+ data: await availabilityService.createPickupLocation(c.get("db"), insertPickupLocationSchema.parse(await c.req.json())),
417
+ }, 201);
418
+ })
419
+ .post("/pickup-locations/batch-update", async (c) => {
420
+ const body = batchUpdatePickupLocationSchema.parse(await c.req.json());
421
+ return c.json(await handleBatchUpdate({
422
+ db: c.get("db"),
423
+ ids: body.ids,
424
+ patch: body.patch,
425
+ update: availabilityService.updatePickupLocation,
426
+ }));
427
+ })
428
+ .post("/pickup-locations/batch-delete", async (c) => {
429
+ const body = batchIdsSchema.parse(await c.req.json());
430
+ return c.json(await handleBatchDelete({
431
+ db: c.get("db"),
432
+ ids: body.ids,
433
+ remove: availabilityService.deletePickupLocation,
434
+ }));
435
+ })
436
+ .get("/pickup-locations/:id", async (c) => {
437
+ const row = await availabilityService.getPickupLocationById(c.get("db"), c.req.param("id"));
438
+ if (!row)
439
+ return c.json({ error: "Pickup location not found" }, 404);
440
+ return c.json({ data: row });
441
+ })
442
+ .patch("/pickup-locations/:id", async (c) => {
443
+ const row = await availabilityService.updatePickupLocation(c.get("db"), c.req.param("id"), updatePickupLocationSchema.parse(await c.req.json()));
444
+ if (!row)
445
+ return c.json({ error: "Pickup location not found" }, 404);
446
+ return c.json({ data: row });
447
+ })
448
+ .delete("/pickup-locations/:id", async (c) => {
449
+ const row = await availabilityService.deletePickupLocation(c.get("db"), c.req.param("id"));
450
+ if (!row)
451
+ return c.json({ error: "Pickup location not found" }, 404);
452
+ return c.json({ success: true });
453
+ })
454
+ .get("/location-pickup-times", async (c) => {
455
+ const query = locationPickupTimeListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
456
+ return c.json(await availabilityService.listLocationPickupTimes(c.get("db"), query));
457
+ })
458
+ .post("/location-pickup-times", async (c) => {
459
+ return c.json({
460
+ data: await availabilityService.createLocationPickupTime(c.get("db"), insertLocationPickupTimeSchema.parse(await c.req.json())),
461
+ }, 201);
462
+ })
463
+ .post("/location-pickup-times/batch-update", async (c) => {
464
+ const body = batchUpdateLocationPickupTimeSchema.parse(await c.req.json());
465
+ return c.json(await handleBatchUpdate({
466
+ db: c.get("db"),
467
+ ids: body.ids,
468
+ patch: body.patch,
469
+ update: availabilityService.updateLocationPickupTime,
470
+ }));
471
+ })
472
+ .post("/location-pickup-times/batch-delete", async (c) => {
473
+ const body = batchIdsSchema.parse(await c.req.json());
474
+ return c.json(await handleBatchDelete({
475
+ db: c.get("db"),
476
+ ids: body.ids,
477
+ remove: availabilityService.deleteLocationPickupTime,
478
+ }));
479
+ })
480
+ .get("/location-pickup-times/:id", async (c) => {
481
+ const row = await availabilityService.getLocationPickupTimeById(c.get("db"), c.req.param("id"));
482
+ if (!row)
483
+ return c.json({ error: "Location pickup time not found" }, 404);
484
+ return c.json({ data: row });
485
+ })
486
+ .patch("/location-pickup-times/:id", async (c) => {
487
+ const row = await availabilityService.updateLocationPickupTime(c.get("db"), c.req.param("id"), updateLocationPickupTimeSchema.parse(await c.req.json()));
488
+ if (!row)
489
+ return c.json({ error: "Location pickup time not found" }, 404);
490
+ return c.json({ data: row });
491
+ })
492
+ .delete("/location-pickup-times/:id", async (c) => {
493
+ const row = await availabilityService.deleteLocationPickupTime(c.get("db"), c.req.param("id"));
494
+ if (!row)
495
+ return c.json({ error: "Location pickup time not found" }, 404);
496
+ return c.json({ success: true });
497
+ })
498
+ .get("/custom-pickup-areas", async (c) => {
499
+ const query = customPickupAreaListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
500
+ return c.json(await availabilityService.listCustomPickupAreas(c.get("db"), query));
501
+ })
502
+ .post("/custom-pickup-areas", async (c) => {
503
+ return c.json({
504
+ data: await availabilityService.createCustomPickupArea(c.get("db"), insertCustomPickupAreaSchema.parse(await c.req.json())),
505
+ }, 201);
506
+ })
507
+ .post("/custom-pickup-areas/batch-update", async (c) => {
508
+ const body = batchUpdateCustomPickupAreaSchema.parse(await c.req.json());
509
+ return c.json(await handleBatchUpdate({
510
+ db: c.get("db"),
511
+ ids: body.ids,
512
+ patch: body.patch,
513
+ update: availabilityService.updateCustomPickupArea,
514
+ }));
515
+ })
516
+ .post("/custom-pickup-areas/batch-delete", async (c) => {
517
+ const body = batchIdsSchema.parse(await c.req.json());
518
+ return c.json(await handleBatchDelete({
519
+ db: c.get("db"),
520
+ ids: body.ids,
521
+ remove: availabilityService.deleteCustomPickupArea,
522
+ }));
523
+ })
524
+ .get("/custom-pickup-areas/:id", async (c) => {
525
+ const row = await availabilityService.getCustomPickupAreaById(c.get("db"), c.req.param("id"));
526
+ if (!row)
527
+ return c.json({ error: "Custom pickup area not found" }, 404);
528
+ return c.json({ data: row });
529
+ })
530
+ .patch("/custom-pickup-areas/:id", async (c) => {
531
+ const row = await availabilityService.updateCustomPickupArea(c.get("db"), c.req.param("id"), updateCustomPickupAreaSchema.parse(await c.req.json()));
532
+ if (!row)
533
+ return c.json({ error: "Custom pickup area not found" }, 404);
534
+ return c.json({ data: row });
535
+ })
536
+ .delete("/custom-pickup-areas/:id", async (c) => {
537
+ const row = await availabilityService.deleteCustomPickupArea(c.get("db"), c.req.param("id"));
538
+ if (!row)
539
+ return c.json({ error: "Custom pickup area not found" }, 404);
540
+ return c.json({ success: true });
541
+ });
@@ -0,0 +1,30 @@
1
+ export declare const WEEKDAYS: readonly ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
2
+ export type Weekday = (typeof WEEKDAYS)[number];
3
+ export declare const WEEKDAY_LABELS: Record<Weekday, string>;
4
+ export type Frequency = "DAILY" | "WEEKLY" | "MONTHLY";
5
+ export type ParsedRRule = {
6
+ frequency: Frequency;
7
+ interval: number;
8
+ byWeekdays: Weekday[];
9
+ byMonthDays: number[];
10
+ };
11
+ /**
12
+ * Parse a minimal RRULE string (subset of RFC 5545).
13
+ * Supports FREQ, INTERVAL, BYDAY, BYMONTHDAY.
14
+ */
15
+ export declare function parseRRule(rrule: string): ParsedRRule;
16
+ /**
17
+ * Build an RRULE string from structured values.
18
+ */
19
+ export declare function buildRRule(values: ParsedRRule): string;
20
+ /**
21
+ * Human-readable preview: "Every Monday" / "Every 2 weeks on Mon, Wed, Fri"
22
+ */
23
+ export declare function describeRRule(rrule: string | ParsedRRule): string;
24
+ /**
25
+ * Expand an RRULE into a sorted list of local date strings (YYYY-MM-DD).
26
+ * Operates on UTC-anchored wall-clock dates — timezone conversion is
27
+ * the caller's responsibility.
28
+ */
29
+ export declare function expandRRule(rrule: string | ParsedRRule, fromDate: Date, toDate: Date, limit?: number): string[];
30
+ //# sourceMappingURL=rrule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rrule.d.ts","sourceRoot":"","sources":["../src/rrule.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,qDAAsD,CAAA;AAC3E,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAQlD,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEtD,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,OAAO,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB,CAAA;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CA8BrD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAYtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CA+BjE;AA2CD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,WAAW,EAC3B,QAAQ,EAAE,IAAI,EACd,MAAM,EAAE,IAAI,EACZ,KAAK,SAAO,GACX,MAAM,EAAE,CA0DV"}