All files / routes/pro social-studio-templates.routes.ts

100% Statements 22/22
100% Branches 8/8
100% Functions 3/3
100% Lines 22/22

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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                                                  1x     1x       4x 4x 4x     4x                                             3x 4x     3x   1x           1x       5x 5x 5x 5x   5x                                     4x 1x       3x 1x     2x   3x            
// Pro Social Studio Templates Routes - List and fetch reel templates
 
import { eq } from "drizzle-orm";
import { Hono } from "hono";
import type { Dal } from "../../dal";
import type { getDb } from "../../db";
import * as schema from "../../db/schema";
import { NotFoundError } from "../../lib/errors";
import { handleError, success } from "../../lib/response";
import { requireProAccess } from "../../middleware";
import type { Services } from "../../services";
 
type Env = {
	Bindings: CloudflareBindings;
	Variables: {
		user: { id: string; name: string; email: string } | null;
		session: unknown;
		dal: Dal;
		services: Services;
		db: ReturnType<typeof getDb>;
		proId: string;
		proRole: string;
	};
};
 
const socialStudioTemplates = new Hono<Env>();
 
// GET /:proId/social-studio/templates — list active system + pro-specific templates
socialStudioTemplates.get(
	"/:proId/social-studio/templates",
	requireProAccess,
	async (c) => {
		try {
			const db = c.get("db");
			const proId = c.get("proId");
 
			// Fetch all active templates; filter client-side to system OR this pro's own
			const allTemplates = await db
				.select({
					id: schema.socialStudioTemplates.id,
					name: schema.socialStudioTemplates.name,
					description: schema.socialStudioTemplates.description,
					thumbnailR2Key: schema.socialStudioTemplates.thumbnailR2Key,
					category: schema.socialStudioTemplates.category,
					slots: schema.socialStudioTemplates.slots,
					defaultMusicId: schema.socialStudioTemplates.defaultMusicId,
					defaultOverlay: schema.socialStudioTemplates.defaultOverlay,
					brandingRequired: schema.socialStudioTemplates.brandingRequired,
					isSystem: schema.socialStudioTemplates.isSystem,
					createdByProId: schema.socialStudioTemplates.createdByProId,
					dateCreated: schema.socialStudioTemplates.dateCreated,
				})
				.from(schema.socialStudioTemplates)
				.where(eq(schema.socialStudioTemplates.isActive, true))
				.orderBy(
					schema.socialStudioTemplates.isSystem,
					schema.socialStudioTemplates.name,
				);
 
			// System templates visible to all; non-system only to the creating pro
			const templates = allTemplates.filter(
				(t) => t.isSystem || t.createdByProId === proId,
			);
 
			return success(c, { templates });
		} catch (err) {
			return handleError(c, err);
		}
	},
);
 
// GET /:proId/social-studio/templates/:templateId — get single template
socialStudioTemplates.get(
	"/:proId/social-studio/templates/:templateId",
	requireProAccess,
	async (c) => {
		try {
			const db = c.get("db");
			const proId = c.get("proId");
			const templateId = c.req.param("templateId");
 
			const [template] = await db
				.select({
					id: schema.socialStudioTemplates.id,
					name: schema.socialStudioTemplates.name,
					description: schema.socialStudioTemplates.description,
					thumbnailR2Key: schema.socialStudioTemplates.thumbnailR2Key,
					category: schema.socialStudioTemplates.category,
					slots: schema.socialStudioTemplates.slots,
					defaultMusicId: schema.socialStudioTemplates.defaultMusicId,
					defaultOverlay: schema.socialStudioTemplates.defaultOverlay,
					brandingRequired: schema.socialStudioTemplates.brandingRequired,
					isSystem: schema.socialStudioTemplates.isSystem,
					createdByProId: schema.socialStudioTemplates.createdByProId,
					dateCreated: schema.socialStudioTemplates.dateCreated,
				})
				.from(schema.socialStudioTemplates)
				.where(eq(schema.socialStudioTemplates.id, templateId))
				.limit(1);
 
			if (!template) {
				throw new NotFoundError("Template not found");
			}
 
			// Access check: system templates are public; pro templates only accessible by creating pro
			if (!template.isSystem && template.createdByProId !== proId) {
				throw new NotFoundError("Template not found");
			}
 
			return success(c, { template });
		} catch (err) {
			return handleError(c, err);
		}
	},
);
 
export default socialStudioTemplates;