Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 24x 2x 2x 2x 2x 24x 2x 2x 2x 2x 24x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 24x 5x 5x 5x 4x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | // src/routes/stats.routes.ts
import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import * as db from '../services/db/index.db';
import { validateRequest } from '../middleware/validation.middleware';
import { optionalNumeric } from '../utils/zodUtils';
import { publicReadLimiter } from '../config/rateLimiters';
import { sendSuccess } from '../utils/apiResponse';
const router = Router();
// --- Zod Schema for Stats Routes (as per ADR-003) ---
// Define the query schema separately so we can use it to parse req.query in the handler
const statsQuerySchema = z.object({
days: optionalNumeric({ default: 30, min: 1, max: 365, integer: true }),
limit: optionalNumeric({ default: 10, min: 1, max: 50, integer: true }),
});
const mostFrequentSalesSchema = z.object({
query: statsQuerySchema,
});
/**
* @openapi
* /stats/most-frequent-sales:
* get:
* tags: [Stats]
* summary: Get most frequent sale items
* description: Get a list of items that have been on sale most frequently. Public endpoint for data analysis.
* parameters:
* - in: query
* name: days
* schema:
* type: integer
* minimum: 1
* maximum: 365
* default: 30
* description: Number of days to look back
* - in: query
* name: limit
* schema:
* type: integer
* minimum: 1
* maximum: 50
* default: 10
* description: Maximum number of items to return
* responses:
* 200:
* description: List of most frequently on-sale items
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SuccessResponse'
*/
router.get(
'/most-frequent-sales',
publicReadLimiter,
validateRequest(mostFrequentSalesSchema),
async (req: Request, res: Response, next: NextFunction) => {
try {
// The `validateRequest` middleware ensures `req.query` is valid.
// We parse it here to apply Zod's coercions (string to number) and defaults.
const { days, limit } = statsQuerySchema.parse(req.query);
const items = await db.adminRepo.getMostFrequentSaleItems(days!, limit!, req.log);
sendSuccess(res, items);
} catch (error) {
req.log.error(
{ error },
'Error fetching most frequent sale items in /api/stats/most-frequent-sales:',
);
next(error);
}
},
);
export default router;
|