All files / routes/pro/blogs suggestions.routes.ts

100% Statements 28/28
100% Branches 10/10
100% Functions 2/2
100% Lines 28/28

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                  1x     1x     1x 6x 6x 6x   6x 1x     5x     5x 1x     4x             3x   3x         1x 9x 9x 9x   9x 1x     8x 9x   9x 9x   9x         9x         7x           2x          
// Pro Blog Suggestion Routes
import { Hono } from "hono";
import type { Dal } from "../../../dal";
import type { Services } from "../../../services";
import {
	success,
	successWithPagination,
	handleError,
} from "../../../lib/response";
import { buildPaginationMeta, generateId } from "../../../lib/utils";
import { ValidationError, ForbiddenError } from "../../../lib/errors";
import { requireProManager } from "../../../middleware";
 
type Env = {
	Bindings: CloudflareBindings;
	Variables: {
		user: { id: string; name: string; email: string } | null;
		session: unknown;
		dal: Dal;
		services: Services;
		proId: string;
		proRole: string;
	};
};
 
const suggestions = new Hono<Env>();
 
// Apply pro access middleware to all routes
suggestions.use("*", requireProManager);
 
// Submit topic suggestion
suggestions.post("/suggestions", async (c) => {
	try {
		const dal = c.get("dal");
		const proId = c.get("proId");
 
		if (!proId) {
			throw new ForbiddenError("Pro ID required");
		}
 
		const body = await c.req.json();
 
		// Validate required fields
		if (!body.topicDescription) {
			throw new ValidationError("Missing required field: topicDescription");
		}
 
		const suggestion = await dal.proBlogSuggestions.create({
			id: generateId(),
			proId,
			topicDescription: body.topicDescription,
			status: "pending",
		});
 
		return success(c, suggestion, 201);
	} catch (err) {
		return handleError(c, err);
	}
});
 
// Get my suggestions
suggestions.get("/suggestions", async (c) => {
	try {
		const dal = c.get("dal");
		const proId = c.get("proId");
 
		if (!proId) {
			throw new ForbiddenError("Pro ID required");
		}
 
		const limitParam = Number(c.req.query("limit") || 50);
		const safeLimit = Math.min(100, Math.max(1, limitParam));
 
		const page = Math.max(1, Number(c.req.query("page") || 1));
		const offset = (page - 1) * safeLimit;
 
		const filters = {
			proId,
			status: c.req.query("status")?.split(","),
		};
 
		const [data, total] = await Promise.all([
			dal.proBlogSuggestions.findAll(filters, offset, safeLimit),
			dal.proBlogSuggestions.count(filters),
		]);
 
		return successWithPagination(
			c,
			data,
			buildPaginationMeta(total, page, safeLimit),
		);
	} catch (err) {
		return handleError(c, err);
	}
});
 
export default suggestions;