@voyantjs/products 0.4.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/booking-extension.d.ts +4 -4
- package/dist/booking-extension.d.ts.map +1 -1
- package/dist/booking-extension.js +3 -2
- package/dist/routes-public.d.ts +4 -4
- package/dist/routes-public.d.ts.map +1 -1
- package/dist/routes-public.js +8 -7
- package/dist/routes.d.ts +92 -114
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +90 -82
- package/dist/schema-core.d.ts +1 -1
- package/dist/schema-settings.d.ts +3 -3
- package/dist/service-catalog.d.ts +2 -2
- package/dist/service-public.d.ts +4 -4
- package/dist/service.d.ts +86 -86
- package/dist/tasks/brochures.d.ts +2 -2
- package/dist/validation-catalog.d.ts +2 -2
- package/dist/validation-config.d.ts +5 -5
- package/dist/validation-content.d.ts +3 -3
- package/dist/validation-core.d.ts +6 -6
- package/dist/validation-public.d.ts +5 -5
- package/dist/validation-shared.d.ts +4 -4
- package/package.json +6 -6
package/dist/routes.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { parseJsonBody, parseQuery, RequestValidationError, requireUserId } from "@voyantjs/hono";
|
|
1
2
|
import { Hono } from "hono";
|
|
3
|
+
import { z } from "zod";
|
|
2
4
|
import { productsService } from "./service.js";
|
|
3
5
|
import { destinationListQuerySchema, destinationTranslationListQuerySchema, insertDaySchema, insertDayServiceSchema, insertDestinationSchema, insertDestinationTranslationSchema, insertOptionUnitSchema, insertOptionUnitTranslationSchema, insertProductActivationSettingSchema, insertProductCapabilitySchema, insertProductCategorySchema, insertProductDeliveryFormatSchema, insertProductDestinationSchema, insertProductFaqSchema, insertProductFeatureSchema, insertProductLocationSchema, insertProductMediaSchema, insertProductNoteSchema, insertProductOptionSchema, insertProductOptionTranslationSchema, insertProductSchema, insertProductTagSchema, insertProductTicketSettingSchema, insertProductTranslationSchema, insertProductTypeSchema, insertProductVisibilitySettingSchema, insertVersionSchema, optionUnitListQuerySchema, optionUnitTranslationListQuerySchema, productActivationSettingListQuerySchema, productCapabilityListQuerySchema, productCategoryListQuerySchema, productDeliveryFormatListQuerySchema, productDestinationListQuerySchema, productFaqListQuerySchema, productFeatureListQuerySchema, productListQuerySchema, productLocationListQuerySchema, productMediaListQuerySchema, productOptionListQuerySchema, productOptionTranslationListQuerySchema, productTagListQuerySchema, productTicketSettingListQuerySchema, productTranslationListQuerySchema, productTypeListQuerySchema, productVisibilitySettingListQuerySchema, reorderProductMediaSchema, updateDaySchema, updateDayServiceSchema, updateDestinationSchema, updateDestinationTranslationSchema, updateOptionUnitSchema, updateOptionUnitTranslationSchema, updateProductActivationSettingSchema, updateProductCapabilitySchema, updateProductCategorySchema, updateProductDeliveryFormatSchema, updateProductFaqSchema, updateProductFeatureSchema, updateProductLocationSchema, updateProductMediaSchema, updateProductOptionSchema, updateProductOptionTranslationSchema, updateProductSchema, updateProductTagSchema, updateProductTicketSettingSchema, updateProductTranslationSchema, updateProductTypeSchema, updateProductVisibilitySettingSchema, upsertProductBrochureSchema, } from "./validation.js";
|
|
4
6
|
// ==========================================================================
|
|
@@ -7,20 +9,20 @@ import { destinationListQuerySchema, destinationTranslationListQuerySchema, inse
|
|
|
7
9
|
export const productRoutes = new Hono()
|
|
8
10
|
// GET / — List products
|
|
9
11
|
.get("/", async (c) => {
|
|
10
|
-
const query =
|
|
12
|
+
const query = parseQuery(c, productListQuerySchema);
|
|
11
13
|
return c.json(await productsService.listProducts(c.get("db"), query));
|
|
12
14
|
})
|
|
13
15
|
// POST / — Create product
|
|
14
16
|
.post("/", async (c) => {
|
|
15
17
|
return c.json({
|
|
16
|
-
data: await productsService.createProduct(c.get("db"),
|
|
18
|
+
data: await productsService.createProduct(c.get("db"), await parseJsonBody(c, insertProductSchema)),
|
|
17
19
|
}, 201);
|
|
18
20
|
})
|
|
19
21
|
// ==========================================================================
|
|
20
22
|
// Product operating configuration
|
|
21
23
|
// ==========================================================================
|
|
22
24
|
.get("/activation-settings", async (c) => {
|
|
23
|
-
const query =
|
|
25
|
+
const query = parseQuery(c, productActivationSettingListQuerySchema);
|
|
24
26
|
return c.json(await productsService.listActivationSettings(c.get("db"), query));
|
|
25
27
|
})
|
|
26
28
|
.get("/activation-settings/:id", async (c) => {
|
|
@@ -31,14 +33,14 @@ export const productRoutes = new Hono()
|
|
|
31
33
|
return c.json({ data: row });
|
|
32
34
|
})
|
|
33
35
|
.post("/:id/activation-settings", async (c) => {
|
|
34
|
-
const row = await productsService.upsertActivationSetting(c.get("db"), c.req.param("id"),
|
|
36
|
+
const row = await productsService.upsertActivationSetting(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductActivationSettingSchema));
|
|
35
37
|
if (!row) {
|
|
36
38
|
return c.json({ error: "Product not found" }, 404);
|
|
37
39
|
}
|
|
38
40
|
return c.json({ data: row }, 201);
|
|
39
41
|
})
|
|
40
42
|
.patch("/activation-settings/:id", async (c) => {
|
|
41
|
-
const row = await productsService.updateActivationSetting(c.get("db"), c.req.param("id"),
|
|
43
|
+
const row = await productsService.updateActivationSetting(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductActivationSettingSchema));
|
|
42
44
|
if (!row) {
|
|
43
45
|
return c.json({ error: "Product activation setting not found" }, 404);
|
|
44
46
|
}
|
|
@@ -52,7 +54,7 @@ export const productRoutes = new Hono()
|
|
|
52
54
|
return c.json({ success: true }, 200);
|
|
53
55
|
})
|
|
54
56
|
.get("/ticket-settings", async (c) => {
|
|
55
|
-
const query =
|
|
57
|
+
const query = parseQuery(c, productTicketSettingListQuerySchema);
|
|
56
58
|
return c.json(await productsService.listTicketSettings(c.get("db"), query));
|
|
57
59
|
})
|
|
58
60
|
.get("/ticket-settings/:id", async (c) => {
|
|
@@ -63,14 +65,14 @@ export const productRoutes = new Hono()
|
|
|
63
65
|
return c.json({ data: row });
|
|
64
66
|
})
|
|
65
67
|
.post("/:id/ticket-settings", async (c) => {
|
|
66
|
-
const row = await productsService.upsertTicketSetting(c.get("db"), c.req.param("id"),
|
|
68
|
+
const row = await productsService.upsertTicketSetting(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductTicketSettingSchema));
|
|
67
69
|
if (!row) {
|
|
68
70
|
return c.json({ error: "Product not found" }, 404);
|
|
69
71
|
}
|
|
70
72
|
return c.json({ data: row }, 201);
|
|
71
73
|
})
|
|
72
74
|
.patch("/ticket-settings/:id", async (c) => {
|
|
73
|
-
const row = await productsService.updateTicketSetting(c.get("db"), c.req.param("id"),
|
|
75
|
+
const row = await productsService.updateTicketSetting(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductTicketSettingSchema));
|
|
74
76
|
if (!row) {
|
|
75
77
|
return c.json({ error: "Product ticket setting not found" }, 404);
|
|
76
78
|
}
|
|
@@ -84,7 +86,7 @@ export const productRoutes = new Hono()
|
|
|
84
86
|
return c.json({ success: true }, 200);
|
|
85
87
|
})
|
|
86
88
|
.get("/visibility-settings", async (c) => {
|
|
87
|
-
const query =
|
|
89
|
+
const query = parseQuery(c, productVisibilitySettingListQuerySchema);
|
|
88
90
|
return c.json(await productsService.listVisibilitySettings(c.get("db"), query));
|
|
89
91
|
})
|
|
90
92
|
.get("/visibility-settings/:id", async (c) => {
|
|
@@ -95,14 +97,14 @@ export const productRoutes = new Hono()
|
|
|
95
97
|
return c.json({ data: row });
|
|
96
98
|
})
|
|
97
99
|
.post("/:id/visibility-settings", async (c) => {
|
|
98
|
-
const row = await productsService.upsertVisibilitySetting(c.get("db"), c.req.param("id"),
|
|
100
|
+
const row = await productsService.upsertVisibilitySetting(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductVisibilitySettingSchema));
|
|
99
101
|
if (!row) {
|
|
100
102
|
return c.json({ error: "Product not found" }, 404);
|
|
101
103
|
}
|
|
102
104
|
return c.json({ data: row }, 201);
|
|
103
105
|
})
|
|
104
106
|
.patch("/visibility-settings/:id", async (c) => {
|
|
105
|
-
const row = await productsService.updateVisibilitySetting(c.get("db"), c.req.param("id"),
|
|
107
|
+
const row = await productsService.updateVisibilitySetting(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductVisibilitySettingSchema));
|
|
106
108
|
if (!row) {
|
|
107
109
|
return c.json({ error: "Product visibility setting not found" }, 404);
|
|
108
110
|
}
|
|
@@ -116,7 +118,7 @@ export const productRoutes = new Hono()
|
|
|
116
118
|
return c.json({ success: true }, 200);
|
|
117
119
|
})
|
|
118
120
|
.get("/capabilities", async (c) => {
|
|
119
|
-
const query =
|
|
121
|
+
const query = parseQuery(c, productCapabilityListQuerySchema);
|
|
120
122
|
return c.json(await productsService.listCapabilities(c.get("db"), query));
|
|
121
123
|
})
|
|
122
124
|
.get("/capabilities/:id", async (c) => {
|
|
@@ -127,14 +129,14 @@ export const productRoutes = new Hono()
|
|
|
127
129
|
return c.json({ data: row });
|
|
128
130
|
})
|
|
129
131
|
.post("/:id/capabilities", async (c) => {
|
|
130
|
-
const row = await productsService.createCapability(c.get("db"), c.req.param("id"),
|
|
132
|
+
const row = await productsService.createCapability(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductCapabilitySchema));
|
|
131
133
|
if (!row) {
|
|
132
134
|
return c.json({ error: "Product not found" }, 404);
|
|
133
135
|
}
|
|
134
136
|
return c.json({ data: row }, 201);
|
|
135
137
|
})
|
|
136
138
|
.patch("/capabilities/:id", async (c) => {
|
|
137
|
-
const row = await productsService.updateCapability(c.get("db"), c.req.param("id"),
|
|
139
|
+
const row = await productsService.updateCapability(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductCapabilitySchema));
|
|
138
140
|
if (!row) {
|
|
139
141
|
return c.json({ error: "Product capability not found" }, 404);
|
|
140
142
|
}
|
|
@@ -148,7 +150,7 @@ export const productRoutes = new Hono()
|
|
|
148
150
|
return c.json({ success: true }, 200);
|
|
149
151
|
})
|
|
150
152
|
.get("/delivery-formats", async (c) => {
|
|
151
|
-
const query =
|
|
153
|
+
const query = parseQuery(c, productDeliveryFormatListQuerySchema);
|
|
152
154
|
return c.json(await productsService.listDeliveryFormats(c.get("db"), query));
|
|
153
155
|
})
|
|
154
156
|
.get("/delivery-formats/:id", async (c) => {
|
|
@@ -159,14 +161,14 @@ export const productRoutes = new Hono()
|
|
|
159
161
|
return c.json({ data: row });
|
|
160
162
|
})
|
|
161
163
|
.post("/:id/delivery-formats", async (c) => {
|
|
162
|
-
const row = await productsService.createDeliveryFormat(c.get("db"), c.req.param("id"),
|
|
164
|
+
const row = await productsService.createDeliveryFormat(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductDeliveryFormatSchema));
|
|
163
165
|
if (!row) {
|
|
164
166
|
return c.json({ error: "Product not found" }, 404);
|
|
165
167
|
}
|
|
166
168
|
return c.json({ data: row }, 201);
|
|
167
169
|
})
|
|
168
170
|
.patch("/delivery-formats/:id", async (c) => {
|
|
169
|
-
const row = await productsService.updateDeliveryFormat(c.get("db"), c.req.param("id"),
|
|
171
|
+
const row = await productsService.updateDeliveryFormat(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductDeliveryFormatSchema));
|
|
170
172
|
if (!row) {
|
|
171
173
|
return c.json({ error: "Product delivery format not found" }, 404);
|
|
172
174
|
}
|
|
@@ -180,7 +182,7 @@ export const productRoutes = new Hono()
|
|
|
180
182
|
return c.json({ success: true }, 200);
|
|
181
183
|
})
|
|
182
184
|
.get("/features", async (c) => {
|
|
183
|
-
const query =
|
|
185
|
+
const query = parseQuery(c, productFeatureListQuerySchema);
|
|
184
186
|
return c.json(await productsService.listFeatures(c.get("db"), query));
|
|
185
187
|
})
|
|
186
188
|
.get("/features/:id", async (c) => {
|
|
@@ -191,14 +193,14 @@ export const productRoutes = new Hono()
|
|
|
191
193
|
return c.json({ data: row });
|
|
192
194
|
})
|
|
193
195
|
.post("/:id/features", async (c) => {
|
|
194
|
-
const row = await productsService.createFeature(c.get("db"), c.req.param("id"),
|
|
196
|
+
const row = await productsService.createFeature(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductFeatureSchema));
|
|
195
197
|
if (!row) {
|
|
196
198
|
return c.json({ error: "Product not found" }, 404);
|
|
197
199
|
}
|
|
198
200
|
return c.json({ data: row }, 201);
|
|
199
201
|
})
|
|
200
202
|
.patch("/features/:id", async (c) => {
|
|
201
|
-
const row = await productsService.updateFeature(c.get("db"), c.req.param("id"),
|
|
203
|
+
const row = await productsService.updateFeature(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductFeatureSchema));
|
|
202
204
|
if (!row) {
|
|
203
205
|
return c.json({ error: "Product feature not found" }, 404);
|
|
204
206
|
}
|
|
@@ -212,7 +214,7 @@ export const productRoutes = new Hono()
|
|
|
212
214
|
return c.json({ success: true }, 200);
|
|
213
215
|
})
|
|
214
216
|
.get("/faqs", async (c) => {
|
|
215
|
-
const query =
|
|
217
|
+
const query = parseQuery(c, productFaqListQuerySchema);
|
|
216
218
|
return c.json(await productsService.listFaqs(c.get("db"), query));
|
|
217
219
|
})
|
|
218
220
|
.get("/faqs/:id", async (c) => {
|
|
@@ -223,14 +225,14 @@ export const productRoutes = new Hono()
|
|
|
223
225
|
return c.json({ data: row });
|
|
224
226
|
})
|
|
225
227
|
.post("/:id/faqs", async (c) => {
|
|
226
|
-
const row = await productsService.createFaq(c.get("db"), c.req.param("id"),
|
|
228
|
+
const row = await productsService.createFaq(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductFaqSchema));
|
|
227
229
|
if (!row) {
|
|
228
230
|
return c.json({ error: "Product not found" }, 404);
|
|
229
231
|
}
|
|
230
232
|
return c.json({ data: row }, 201);
|
|
231
233
|
})
|
|
232
234
|
.patch("/faqs/:id", async (c) => {
|
|
233
|
-
const row = await productsService.updateFaq(c.get("db"), c.req.param("id"),
|
|
235
|
+
const row = await productsService.updateFaq(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductFaqSchema));
|
|
234
236
|
if (!row) {
|
|
235
237
|
return c.json({ error: "Product FAQ not found" }, 404);
|
|
236
238
|
}
|
|
@@ -244,7 +246,7 @@ export const productRoutes = new Hono()
|
|
|
244
246
|
return c.json({ success: true }, 200);
|
|
245
247
|
})
|
|
246
248
|
.get("/locations", async (c) => {
|
|
247
|
-
const query =
|
|
249
|
+
const query = parseQuery(c, productLocationListQuerySchema);
|
|
248
250
|
return c.json(await productsService.listLocations(c.get("db"), query));
|
|
249
251
|
})
|
|
250
252
|
.get("/locations/:id", async (c) => {
|
|
@@ -255,14 +257,14 @@ export const productRoutes = new Hono()
|
|
|
255
257
|
return c.json({ data: row });
|
|
256
258
|
})
|
|
257
259
|
.post("/:id/locations", async (c) => {
|
|
258
|
-
const row = await productsService.createLocation(c.get("db"), c.req.param("id"),
|
|
260
|
+
const row = await productsService.createLocation(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductLocationSchema));
|
|
259
261
|
if (!row) {
|
|
260
262
|
return c.json({ error: "Product not found" }, 404);
|
|
261
263
|
}
|
|
262
264
|
return c.json({ data: row }, 201);
|
|
263
265
|
})
|
|
264
266
|
.patch("/locations/:id", async (c) => {
|
|
265
|
-
const row = await productsService.updateLocation(c.get("db"), c.req.param("id"),
|
|
267
|
+
const row = await productsService.updateLocation(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductLocationSchema));
|
|
266
268
|
if (!row) {
|
|
267
269
|
return c.json({ error: "Product location not found" }, 404);
|
|
268
270
|
}
|
|
@@ -276,7 +278,7 @@ export const productRoutes = new Hono()
|
|
|
276
278
|
return c.json({ success: true }, 200);
|
|
277
279
|
})
|
|
278
280
|
.get("/destinations", async (c) => {
|
|
279
|
-
const query =
|
|
281
|
+
const query = parseQuery(c, destinationListQuerySchema);
|
|
280
282
|
return c.json(await productsService.listDestinations(c.get("db"), query));
|
|
281
283
|
})
|
|
282
284
|
.get("/destinations/:id", async (c) => {
|
|
@@ -287,11 +289,11 @@ export const productRoutes = new Hono()
|
|
|
287
289
|
return c.json({ data: row });
|
|
288
290
|
})
|
|
289
291
|
.post("/destinations", async (c) => {
|
|
290
|
-
const row = await productsService.createDestination(c.get("db"),
|
|
292
|
+
const row = await productsService.createDestination(c.get("db"), await parseJsonBody(c, insertDestinationSchema));
|
|
291
293
|
return c.json({ data: row }, 201);
|
|
292
294
|
})
|
|
293
295
|
.patch("/destinations/:id", async (c) => {
|
|
294
|
-
const row = await productsService.updateDestination(c.get("db"), c.req.param("id"),
|
|
296
|
+
const row = await productsService.updateDestination(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateDestinationSchema));
|
|
295
297
|
if (!row) {
|
|
296
298
|
return c.json({ error: "Destination not found" }, 404);
|
|
297
299
|
}
|
|
@@ -305,18 +307,18 @@ export const productRoutes = new Hono()
|
|
|
305
307
|
return c.json({ success: true }, 200);
|
|
306
308
|
})
|
|
307
309
|
.get("/destination-translations", async (c) => {
|
|
308
|
-
const query =
|
|
310
|
+
const query = parseQuery(c, destinationTranslationListQuerySchema);
|
|
309
311
|
return c.json(await productsService.listDestinationTranslations(c.get("db"), query));
|
|
310
312
|
})
|
|
311
313
|
.post("/destinations/:id/translations", async (c) => {
|
|
312
|
-
const row = await productsService.upsertDestinationTranslation(c.get("db"), c.req.param("id"),
|
|
314
|
+
const row = await productsService.upsertDestinationTranslation(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertDestinationTranslationSchema));
|
|
313
315
|
if (!row) {
|
|
314
316
|
return c.json({ error: "Destination not found" }, 404);
|
|
315
317
|
}
|
|
316
318
|
return c.json({ data: row }, 201);
|
|
317
319
|
})
|
|
318
320
|
.patch("/destination-translations/:id", async (c) => {
|
|
319
|
-
const row = await productsService.updateDestinationTranslation(c.get("db"), c.req.param("id"),
|
|
321
|
+
const row = await productsService.updateDestinationTranslation(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateDestinationTranslationSchema));
|
|
320
322
|
if (!row) {
|
|
321
323
|
return c.json({ error: "Destination translation not found" }, 404);
|
|
322
324
|
}
|
|
@@ -330,11 +332,11 @@ export const productRoutes = new Hono()
|
|
|
330
332
|
return c.json({ success: true }, 200);
|
|
331
333
|
})
|
|
332
334
|
.get("/destination-links", async (c) => {
|
|
333
|
-
const query =
|
|
335
|
+
const query = parseQuery(c, productDestinationListQuerySchema);
|
|
334
336
|
return c.json(await productsService.listProductDestinations(c.get("db"), query));
|
|
335
337
|
})
|
|
336
338
|
.post("/:id/destinations", async (c) => {
|
|
337
|
-
const row = await productsService.assignProductDestination(c.get("db"), c.req.param("id"),
|
|
339
|
+
const row = await productsService.assignProductDestination(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductDestinationSchema));
|
|
338
340
|
if (!row) {
|
|
339
341
|
return c.json({ error: "Product or destination not found" }, 404);
|
|
340
342
|
}
|
|
@@ -352,7 +354,7 @@ export const productRoutes = new Hono()
|
|
|
352
354
|
// ==========================================================================
|
|
353
355
|
// GET /options — List options
|
|
354
356
|
.get("/options", async (c) => {
|
|
355
|
-
const query =
|
|
357
|
+
const query = parseQuery(c, productOptionListQuerySchema);
|
|
356
358
|
return c.json(await productsService.listOptions(c.get("db"), query));
|
|
357
359
|
})
|
|
358
360
|
// GET /options/:optionId — Get single option
|
|
@@ -365,7 +367,7 @@ export const productRoutes = new Hono()
|
|
|
365
367
|
})
|
|
366
368
|
// POST /:id/options — Create option for product
|
|
367
369
|
.post("/:id/options", async (c) => {
|
|
368
|
-
const row = await productsService.createOption(c.get("db"), c.req.param("id"),
|
|
370
|
+
const row = await productsService.createOption(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductOptionSchema));
|
|
369
371
|
if (!row) {
|
|
370
372
|
return c.json({ error: "Product not found" }, 404);
|
|
371
373
|
}
|
|
@@ -373,7 +375,7 @@ export const productRoutes = new Hono()
|
|
|
373
375
|
})
|
|
374
376
|
// PATCH /options/:optionId — Update option
|
|
375
377
|
.patch("/options/:optionId", async (c) => {
|
|
376
|
-
const row = await productsService.updateOption(c.get("db"), c.req.param("optionId"),
|
|
378
|
+
const row = await productsService.updateOption(c.get("db"), c.req.param("optionId"), await parseJsonBody(c, updateProductOptionSchema));
|
|
377
379
|
if (!row) {
|
|
378
380
|
return c.json({ error: "Product option not found" }, 404);
|
|
379
381
|
}
|
|
@@ -392,7 +394,7 @@ export const productRoutes = new Hono()
|
|
|
392
394
|
// ==========================================================================
|
|
393
395
|
// GET /units — List units
|
|
394
396
|
.get("/units", async (c) => {
|
|
395
|
-
const query =
|
|
397
|
+
const query = parseQuery(c, optionUnitListQuerySchema);
|
|
396
398
|
return c.json(await productsService.listUnits(c.get("db"), query));
|
|
397
399
|
})
|
|
398
400
|
// GET /units/:unitId — Get single unit
|
|
@@ -405,7 +407,7 @@ export const productRoutes = new Hono()
|
|
|
405
407
|
})
|
|
406
408
|
// POST /options/:optionId/units — Create unit for option
|
|
407
409
|
.post("/options/:optionId/units", async (c) => {
|
|
408
|
-
const row = await productsService.createUnit(c.get("db"), c.req.param("optionId"),
|
|
410
|
+
const row = await productsService.createUnit(c.get("db"), c.req.param("optionId"), await parseJsonBody(c, insertOptionUnitSchema));
|
|
409
411
|
if (!row) {
|
|
410
412
|
return c.json({ error: "Product option not found" }, 404);
|
|
411
413
|
}
|
|
@@ -413,7 +415,7 @@ export const productRoutes = new Hono()
|
|
|
413
415
|
})
|
|
414
416
|
// PATCH /units/:unitId — Update unit
|
|
415
417
|
.patch("/units/:unitId", async (c) => {
|
|
416
|
-
const row = await productsService.updateUnit(c.get("db"), c.req.param("unitId"),
|
|
418
|
+
const row = await productsService.updateUnit(c.get("db"), c.req.param("unitId"), await parseJsonBody(c, updateOptionUnitSchema));
|
|
417
419
|
if (!row) {
|
|
418
420
|
return c.json({ error: "Option unit not found" }, 404);
|
|
419
421
|
}
|
|
@@ -431,7 +433,7 @@ export const productRoutes = new Hono()
|
|
|
431
433
|
// Translations
|
|
432
434
|
// ==========================================================================
|
|
433
435
|
.get("/translations", async (c) => {
|
|
434
|
-
const query =
|
|
436
|
+
const query = parseQuery(c, productTranslationListQuerySchema);
|
|
435
437
|
return c.json(await productsService.listProductTranslations(c.get("db"), query));
|
|
436
438
|
})
|
|
437
439
|
.get("/translations/:translationId", async (c) => {
|
|
@@ -442,14 +444,14 @@ export const productRoutes = new Hono()
|
|
|
442
444
|
return c.json({ data: row });
|
|
443
445
|
})
|
|
444
446
|
.post("/:id/translations", async (c) => {
|
|
445
|
-
const row = await productsService.createProductTranslation(c.get("db"), c.req.param("id"),
|
|
447
|
+
const row = await productsService.createProductTranslation(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductTranslationSchema));
|
|
446
448
|
if (!row) {
|
|
447
449
|
return c.json({ error: "Product not found" }, 404);
|
|
448
450
|
}
|
|
449
451
|
return c.json({ data: row }, 201);
|
|
450
452
|
})
|
|
451
453
|
.patch("/translations/:translationId", async (c) => {
|
|
452
|
-
const row = await productsService.updateProductTranslation(c.get("db"), c.req.param("translationId"),
|
|
454
|
+
const row = await productsService.updateProductTranslation(c.get("db"), c.req.param("translationId"), await parseJsonBody(c, updateProductTranslationSchema));
|
|
453
455
|
if (!row) {
|
|
454
456
|
return c.json({ error: "Product translation not found" }, 404);
|
|
455
457
|
}
|
|
@@ -463,7 +465,7 @@ export const productRoutes = new Hono()
|
|
|
463
465
|
return c.json({ success: true }, 200);
|
|
464
466
|
})
|
|
465
467
|
.get("/option-translations", async (c) => {
|
|
466
|
-
const query =
|
|
468
|
+
const query = parseQuery(c, productOptionTranslationListQuerySchema);
|
|
467
469
|
return c.json(await productsService.listOptionTranslations(c.get("db"), query));
|
|
468
470
|
})
|
|
469
471
|
.get("/option-translations/:translationId", async (c) => {
|
|
@@ -474,14 +476,14 @@ export const productRoutes = new Hono()
|
|
|
474
476
|
return c.json({ data: row });
|
|
475
477
|
})
|
|
476
478
|
.post("/options/:optionId/translations", async (c) => {
|
|
477
|
-
const row = await productsService.createOptionTranslation(c.get("db"), c.req.param("optionId"),
|
|
479
|
+
const row = await productsService.createOptionTranslation(c.get("db"), c.req.param("optionId"), await parseJsonBody(c, insertProductOptionTranslationSchema));
|
|
478
480
|
if (!row) {
|
|
479
481
|
return c.json({ error: "Product option not found" }, 404);
|
|
480
482
|
}
|
|
481
483
|
return c.json({ data: row }, 201);
|
|
482
484
|
})
|
|
483
485
|
.patch("/option-translations/:translationId", async (c) => {
|
|
484
|
-
const row = await productsService.updateOptionTranslation(c.get("db"), c.req.param("translationId"),
|
|
486
|
+
const row = await productsService.updateOptionTranslation(c.get("db"), c.req.param("translationId"), await parseJsonBody(c, updateProductOptionTranslationSchema));
|
|
485
487
|
if (!row) {
|
|
486
488
|
return c.json({ error: "Option translation not found" }, 404);
|
|
487
489
|
}
|
|
@@ -495,7 +497,7 @@ export const productRoutes = new Hono()
|
|
|
495
497
|
return c.json({ success: true }, 200);
|
|
496
498
|
})
|
|
497
499
|
.get("/unit-translations", async (c) => {
|
|
498
|
-
const query =
|
|
500
|
+
const query = parseQuery(c, optionUnitTranslationListQuerySchema);
|
|
499
501
|
return c.json(await productsService.listUnitTranslations(c.get("db"), query));
|
|
500
502
|
})
|
|
501
503
|
.get("/unit-translations/:translationId", async (c) => {
|
|
@@ -506,14 +508,14 @@ export const productRoutes = new Hono()
|
|
|
506
508
|
return c.json({ data: row });
|
|
507
509
|
})
|
|
508
510
|
.post("/units/:unitId/translations", async (c) => {
|
|
509
|
-
const row = await productsService.createUnitTranslation(c.get("db"), c.req.param("unitId"),
|
|
511
|
+
const row = await productsService.createUnitTranslation(c.get("db"), c.req.param("unitId"), await parseJsonBody(c, insertOptionUnitTranslationSchema));
|
|
510
512
|
if (!row) {
|
|
511
513
|
return c.json({ error: "Option unit not found" }, 404);
|
|
512
514
|
}
|
|
513
515
|
return c.json({ data: row }, 201);
|
|
514
516
|
})
|
|
515
517
|
.patch("/unit-translations/:translationId", async (c) => {
|
|
516
|
-
const row = await productsService.updateUnitTranslation(c.get("db"), c.req.param("translationId"),
|
|
518
|
+
const row = await productsService.updateUnitTranslation(c.get("db"), c.req.param("translationId"), await parseJsonBody(c, updateOptionUnitTranslationSchema));
|
|
517
519
|
if (!row) {
|
|
518
520
|
return c.json({ error: "Unit translation not found" }, 404);
|
|
519
521
|
}
|
|
@@ -530,7 +532,7 @@ export const productRoutes = new Hono()
|
|
|
530
532
|
// Product Types
|
|
531
533
|
// ==========================================================================
|
|
532
534
|
.get("/product-types", async (c) => {
|
|
533
|
-
const query =
|
|
535
|
+
const query = parseQuery(c, productTypeListQuerySchema);
|
|
534
536
|
return c.json(await productsService.listProductTypes(c.get("db"), query));
|
|
535
537
|
})
|
|
536
538
|
.get("/product-types/:typeId", async (c) => {
|
|
@@ -542,11 +544,11 @@ export const productRoutes = new Hono()
|
|
|
542
544
|
})
|
|
543
545
|
.post("/product-types", async (c) => {
|
|
544
546
|
return c.json({
|
|
545
|
-
data: await productsService.createProductType(c.get("db"),
|
|
547
|
+
data: await productsService.createProductType(c.get("db"), await parseJsonBody(c, insertProductTypeSchema)),
|
|
546
548
|
}, 201);
|
|
547
549
|
})
|
|
548
550
|
.patch("/product-types/:typeId", async (c) => {
|
|
549
|
-
const row = await productsService.updateProductType(c.get("db"), c.req.param("typeId"),
|
|
551
|
+
const row = await productsService.updateProductType(c.get("db"), c.req.param("typeId"), await parseJsonBody(c, updateProductTypeSchema));
|
|
550
552
|
if (!row) {
|
|
551
553
|
return c.json({ error: "Product type not found" }, 404);
|
|
552
554
|
}
|
|
@@ -563,7 +565,7 @@ export const productRoutes = new Hono()
|
|
|
563
565
|
// Product Categories
|
|
564
566
|
// ==========================================================================
|
|
565
567
|
.get("/product-categories", async (c) => {
|
|
566
|
-
const query =
|
|
568
|
+
const query = parseQuery(c, productCategoryListQuerySchema);
|
|
567
569
|
return c.json(await productsService.listProductCategories(c.get("db"), query));
|
|
568
570
|
})
|
|
569
571
|
.get("/product-categories/:categoryId", async (c) => {
|
|
@@ -575,11 +577,11 @@ export const productRoutes = new Hono()
|
|
|
575
577
|
})
|
|
576
578
|
.post("/product-categories", async (c) => {
|
|
577
579
|
return c.json({
|
|
578
|
-
data: await productsService.createProductCategory(c.get("db"),
|
|
580
|
+
data: await productsService.createProductCategory(c.get("db"), await parseJsonBody(c, insertProductCategorySchema)),
|
|
579
581
|
}, 201);
|
|
580
582
|
})
|
|
581
583
|
.patch("/product-categories/:categoryId", async (c) => {
|
|
582
|
-
const row = await productsService.updateProductCategory(c.get("db"), c.req.param("categoryId"),
|
|
584
|
+
const row = await productsService.updateProductCategory(c.get("db"), c.req.param("categoryId"), await parseJsonBody(c, updateProductCategorySchema));
|
|
583
585
|
if (!row) {
|
|
584
586
|
return c.json({ error: "Product category not found" }, 404);
|
|
585
587
|
}
|
|
@@ -596,7 +598,7 @@ export const productRoutes = new Hono()
|
|
|
596
598
|
// Product Tags
|
|
597
599
|
// ==========================================================================
|
|
598
600
|
.get("/product-tags", async (c) => {
|
|
599
|
-
const query =
|
|
601
|
+
const query = parseQuery(c, productTagListQuerySchema);
|
|
600
602
|
return c.json(await productsService.listProductTags(c.get("db"), query));
|
|
601
603
|
})
|
|
602
604
|
.get("/product-tags/:tagId", async (c) => {
|
|
@@ -608,11 +610,11 @@ export const productRoutes = new Hono()
|
|
|
608
610
|
})
|
|
609
611
|
.post("/product-tags", async (c) => {
|
|
610
612
|
return c.json({
|
|
611
|
-
data: await productsService.createProductTag(c.get("db"),
|
|
613
|
+
data: await productsService.createProductTag(c.get("db"), await parseJsonBody(c, insertProductTagSchema)),
|
|
612
614
|
}, 201);
|
|
613
615
|
})
|
|
614
616
|
.patch("/product-tags/:tagId", async (c) => {
|
|
615
|
-
const row = await productsService.updateProductTag(c.get("db"), c.req.param("tagId"),
|
|
617
|
+
const row = await productsService.updateProductTag(c.get("db"), c.req.param("tagId"), await parseJsonBody(c, updateProductTagSchema));
|
|
616
618
|
if (!row) {
|
|
617
619
|
return c.json({ error: "Product tag not found" }, 404);
|
|
618
620
|
}
|
|
@@ -638,7 +640,7 @@ export const productRoutes = new Hono()
|
|
|
638
640
|
})
|
|
639
641
|
// PATCH /media/:mediaId — Update media metadata
|
|
640
642
|
.patch("/media/:mediaId", async (c) => {
|
|
641
|
-
const row = await productsService.updateMedia(c.get("db"), c.req.param("mediaId"),
|
|
643
|
+
const row = await productsService.updateMedia(c.get("db"), c.req.param("mediaId"), await parseJsonBody(c, updateProductMediaSchema));
|
|
642
644
|
if (!row) {
|
|
643
645
|
return c.json({ error: "Media not found" }, 404);
|
|
644
646
|
}
|
|
@@ -678,7 +680,7 @@ export const productRoutes = new Hono()
|
|
|
678
680
|
})
|
|
679
681
|
// PUT /:id/brochure — Upsert canonical brochure for product
|
|
680
682
|
.put("/:id/brochure", async (c) => {
|
|
681
|
-
const row = await productsService.upsertBrochure(c.get("db"), c.req.param("id"),
|
|
683
|
+
const row = await productsService.upsertBrochure(c.get("db"), c.req.param("id"), await parseJsonBody(c, upsertProductBrochureSchema));
|
|
682
684
|
if (!row) {
|
|
683
685
|
return c.json({ error: "Product not found" }, 404);
|
|
684
686
|
}
|
|
@@ -718,7 +720,7 @@ export const productRoutes = new Hono()
|
|
|
718
720
|
})
|
|
719
721
|
// PATCH /:id — Update product
|
|
720
722
|
.patch("/:id", async (c) => {
|
|
721
|
-
const row = await productsService.updateProduct(c.get("db"), c.req.param("id"),
|
|
723
|
+
const row = await productsService.updateProduct(c.get("db"), c.req.param("id"), await parseJsonBody(c, updateProductSchema));
|
|
722
724
|
if (!row) {
|
|
723
725
|
return c.json({ error: "Product not found" }, 404);
|
|
724
726
|
}
|
|
@@ -741,7 +743,7 @@ export const productRoutes = new Hono()
|
|
|
741
743
|
})
|
|
742
744
|
// POST /:id/days — Add day to product
|
|
743
745
|
.post("/:id/days", async (c) => {
|
|
744
|
-
const row = await productsService.createDay(c.get("db"), c.req.param("id"),
|
|
746
|
+
const row = await productsService.createDay(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertDaySchema));
|
|
745
747
|
if (!row) {
|
|
746
748
|
return c.json({ error: "Product not found" }, 404);
|
|
747
749
|
}
|
|
@@ -749,7 +751,7 @@ export const productRoutes = new Hono()
|
|
|
749
751
|
})
|
|
750
752
|
// PATCH /:id/days/:dayId — Update day
|
|
751
753
|
.patch("/:id/days/:dayId", async (c) => {
|
|
752
|
-
const row = await productsService.updateDay(c.get("db"), c.req.param("dayId"),
|
|
754
|
+
const row = await productsService.updateDay(c.get("db"), c.req.param("dayId"), await parseJsonBody(c, updateDaySchema));
|
|
753
755
|
if (!row) {
|
|
754
756
|
return c.json({ error: "Day not found" }, 404);
|
|
755
757
|
}
|
|
@@ -774,7 +776,7 @@ export const productRoutes = new Hono()
|
|
|
774
776
|
})
|
|
775
777
|
// POST /:id/days/:dayId/services — Add service to day
|
|
776
778
|
.post("/:id/days/:dayId/services", async (c) => {
|
|
777
|
-
const row = await productsService.createDayService(c.get("db"), c.req.param("id"), c.req.param("dayId"),
|
|
779
|
+
const row = await productsService.createDayService(c.get("db"), c.req.param("id"), c.req.param("dayId"), await parseJsonBody(c, insertDayServiceSchema));
|
|
778
780
|
if (!row) {
|
|
779
781
|
return c.json({ error: "Day not found" }, 404);
|
|
780
782
|
}
|
|
@@ -782,7 +784,7 @@ export const productRoutes = new Hono()
|
|
|
782
784
|
})
|
|
783
785
|
// PATCH /:id/days/:dayId/services/:serviceId — Update service
|
|
784
786
|
.patch("/:id/days/:dayId/services/:serviceId", async (c) => {
|
|
785
|
-
const row = await productsService.updateDayService(c.get("db"), c.req.param("id"), c.req.param("serviceId"),
|
|
787
|
+
const row = await productsService.updateDayService(c.get("db"), c.req.param("id"), c.req.param("serviceId"), await parseJsonBody(c, updateDayServiceSchema));
|
|
786
788
|
if (!row) {
|
|
787
789
|
return c.json({ error: "Service not found" }, 404);
|
|
788
790
|
}
|
|
@@ -805,11 +807,15 @@ export const productRoutes = new Hono()
|
|
|
805
807
|
})
|
|
806
808
|
// POST /:id/versions — Create version snapshot
|
|
807
809
|
.post("/:id/versions", async (c) => {
|
|
808
|
-
const userId = c
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
|
|
810
|
+
const userId = requireUserId(c);
|
|
811
|
+
const row = await productsService.createVersion(c.get("db"), c.req.param("id"), userId, await parseJsonBody(c, insertVersionSchema, {
|
|
812
|
+
invalidJsonMessage: "Invalid JSON body",
|
|
813
|
+
}).catch((error) => {
|
|
814
|
+
if (error instanceof RequestValidationError && error.message === "Invalid JSON body") {
|
|
815
|
+
return {};
|
|
816
|
+
}
|
|
817
|
+
throw error;
|
|
818
|
+
}));
|
|
813
819
|
if (!row) {
|
|
814
820
|
return c.json({ error: "Product not found" }, 404);
|
|
815
821
|
}
|
|
@@ -824,11 +830,8 @@ export const productRoutes = new Hono()
|
|
|
824
830
|
})
|
|
825
831
|
// POST /:id/notes — Add note to product
|
|
826
832
|
.post("/:id/notes", async (c) => {
|
|
827
|
-
const userId = c
|
|
828
|
-
|
|
829
|
-
return c.json({ error: "User ID required to create notes" }, 400);
|
|
830
|
-
}
|
|
831
|
-
const row = await productsService.createNote(c.get("db"), c.req.param("id"), userId, insertProductNoteSchema.parse(await c.req.json()));
|
|
833
|
+
const userId = requireUserId(c);
|
|
834
|
+
const row = await productsService.createNote(c.get("db"), c.req.param("id"), userId, await parseJsonBody(c, insertProductNoteSchema));
|
|
832
835
|
if (!row) {
|
|
833
836
|
return c.json({ error: "Product not found" }, 404);
|
|
834
837
|
}
|
|
@@ -843,7 +846,10 @@ export const productRoutes = new Hono()
|
|
|
843
846
|
});
|
|
844
847
|
})
|
|
845
848
|
.post("/:id/categories", async (c) => {
|
|
846
|
-
const { categoryId, sortOrder } =
|
|
849
|
+
const { categoryId, sortOrder } = await parseJsonBody(c, z.object({
|
|
850
|
+
categoryId: z.string(),
|
|
851
|
+
sortOrder: z.number().optional(),
|
|
852
|
+
}));
|
|
847
853
|
const row = await productsService.addProductToCategory(c.get("db"), c.req.param("id"), categoryId, sortOrder);
|
|
848
854
|
if (!row) {
|
|
849
855
|
return c.json({ error: "Already assigned or not found" }, 409);
|
|
@@ -866,7 +872,9 @@ export const productRoutes = new Hono()
|
|
|
866
872
|
});
|
|
867
873
|
})
|
|
868
874
|
.post("/:id/tags", async (c) => {
|
|
869
|
-
const { tagId } =
|
|
875
|
+
const { tagId } = await parseJsonBody(c, z.object({
|
|
876
|
+
tagId: z.string(),
|
|
877
|
+
}));
|
|
870
878
|
const row = await productsService.addProductTag(c.get("db"), c.req.param("id"), tagId);
|
|
871
879
|
if (!row) {
|
|
872
880
|
return c.json({ error: "Already assigned or not found" }, 409);
|
|
@@ -885,12 +893,12 @@ export const productRoutes = new Hono()
|
|
|
885
893
|
// ==========================================================================
|
|
886
894
|
// GET /:id/media — List product-level media
|
|
887
895
|
.get("/:id/media", async (c) => {
|
|
888
|
-
const query =
|
|
896
|
+
const query = parseQuery(c, productMediaListQuerySchema);
|
|
889
897
|
return c.json(await productsService.listProductLevelMedia(c.get("db"), c.req.param("id"), query));
|
|
890
898
|
})
|
|
891
899
|
// POST /:id/media — Create media for product
|
|
892
900
|
.post("/:id/media", async (c) => {
|
|
893
|
-
const row = await productsService.createMedia(c.get("db"), c.req.param("id"),
|
|
901
|
+
const row = await productsService.createMedia(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertProductMediaSchema));
|
|
894
902
|
if (!row) {
|
|
895
903
|
return c.json({ error: "Product not found or invalid dayId" }, 404);
|
|
896
904
|
}
|
|
@@ -898,13 +906,13 @@ export const productRoutes = new Hono()
|
|
|
898
906
|
})
|
|
899
907
|
// POST /:id/media/reorder — Batch reorder media
|
|
900
908
|
.post("/:id/media/reorder", async (c) => {
|
|
901
|
-
const data =
|
|
909
|
+
const data = await parseJsonBody(c, reorderProductMediaSchema);
|
|
902
910
|
const results = await productsService.reorderMedia(c.get("db"), data);
|
|
903
911
|
return c.json({ data: results });
|
|
904
912
|
})
|
|
905
913
|
// GET /:id/days/:dayId/media — List day media
|
|
906
914
|
.get("/:id/days/:dayId/media", async (c) => {
|
|
907
|
-
const query =
|
|
915
|
+
const query = parseQuery(c, productMediaListQuerySchema);
|
|
908
916
|
return c.json(await productsService.listMedia(c.get("db"), c.req.param("id"), {
|
|
909
917
|
...query,
|
|
910
918
|
dayId: c.req.param("dayId"),
|
|
@@ -912,7 +920,7 @@ export const productRoutes = new Hono()
|
|
|
912
920
|
})
|
|
913
921
|
// POST /:id/days/:dayId/media — Create day media
|
|
914
922
|
.post("/:id/days/:dayId/media", async (c) => {
|
|
915
|
-
const body =
|
|
923
|
+
const body = await parseJsonBody(c, insertProductMediaSchema);
|
|
916
924
|
const row = await productsService.createMedia(c.get("db"), c.req.param("id"), {
|
|
917
925
|
...body,
|
|
918
926
|
dayId: c.req.param("dayId"),
|