"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const zod_1 = require("zod"); const auth_middleware_1 = require("../middleware/auth.middleware"); const client_1 = require("@prisma/client"); const logger_1 = require("../lib/logger"); const router = express_1.default.Router(); const prisma = new client_1.PrismaClient(); const createProjectSchema = zod_1.z.object({ name: zod_1.z.string().min(1, 'Project name is required').max(100, 'Project name too long'), description: zod_1.z.string().optional(), settings: zod_1.z.object({ defaultMethod: zod_1.z.enum(['GET', 'POST', 'HEAD']).default('GET'), defaultTimeout: zod_1.z.number().min(1000).max(30000).default(15000), defaultMaxHops: zod_1.z.number().min(1).max(20).default(10), enableSSLAnalysis: zod_1.z.boolean().default(true), enableSEOAnalysis: zod_1.z.boolean().default(true), enableSecurityAnalysis: zod_1.z.boolean().default(true), }).optional(), }); const updateProjectSchema = zod_1.z.object({ name: zod_1.z.string().min(1).max(100).optional(), description: zod_1.z.string().optional(), settings: zod_1.z.object({ defaultMethod: zod_1.z.enum(['GET', 'POST', 'HEAD']).optional(), defaultTimeout: zod_1.z.number().min(1000).max(30000).optional(), defaultMaxHops: zod_1.z.number().min(1).max(20).optional(), enableSSLAnalysis: zod_1.z.boolean().optional(), enableSEOAnalysis: zod_1.z.boolean().optional(), enableSecurityAnalysis: zod_1.z.boolean().optional(), }).optional(), }); const projectParamsSchema = zod_1.z.object({ projectId: zod_1.z.string().min(1), }); router.get('/', auth_middleware_1.requireAuth, async (req, res) => { try { const user = req.user; const orgId = user.memberships[0]?.orgId; if (!orgId) { return res.status(404).json({ success: false, error: 'No organization found', message: 'User must belong to an organization to access projects' }); } const projects = await prisma.project.findMany({ where: { orgId: orgId, }, include: { _count: { select: { checks: true, }, }, }, orderBy: { createdAt: 'desc', }, }); res.json({ success: true, data: { projects: projects.map(project => ({ id: project.id, name: project.name, description: project.settingsJson?.description || null, settings: project.settingsJson, trackingCount: project._count.checks, createdAt: project.createdAt, })), }, }); } catch (error) { logger_1.logger.error('Failed to get projects:', error); res.status(500).json({ success: false, error: 'Failed to get projects', message: error instanceof Error ? error.message : 'Unknown error', }); } }); router.post('/', auth_middleware_1.requireAuth, async (req, res) => { try { const user = req.user; const orgId = user.memberships[0]?.orgId; if (!orgId) { return res.status(404).json({ success: false, error: 'No organization found', message: 'User must belong to an organization to create projects' }); } const validatedData = createProjectSchema.parse(req.body); const project = await prisma.project.create({ data: { name: validatedData.name, orgId: orgId, settingsJson: { description: validatedData.description || '', ...validatedData.settings, }, }, }); logger_1.logger.info(`Project created: ${project.id}`, { userId: user.id, orgId, projectName: project.name, }); res.status(201).json({ success: true, data: { project: { id: project.id, name: project.name, description: validatedData.description || null, settings: project.settingsJson, trackingCount: 0, createdAt: project.createdAt, }, }, message: 'Project created successfully', }); } catch (error) { logger_1.logger.error('Failed to create project:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Validation failed', details: error.errors, }); } res.status(500).json({ success: false, error: 'Failed to create project', message: error instanceof Error ? error.message : 'Unknown error', }); } }); router.get('/:projectId', auth_middleware_1.requireAuth, async (req, res) => { try { const user = req.user; const { projectId } = projectParamsSchema.parse(req.params); const orgId = user.memberships[0]?.orgId; if (!orgId) { return res.status(404).json({ success: false, error: 'No organization found', }); } const project = await prisma.project.findFirst({ where: { id: projectId, orgId: orgId, }, include: { _count: { select: { checks: true, }, }, checks: { take: 10, orderBy: { startedAt: 'desc', }, include: { hops: { select: { url: true, statusCode: true, redirectType: true, }, }, }, }, }, }); if (!project) { return res.status(404).json({ success: false, error: 'Project not found', message: 'Project does not exist or you do not have access to it', }); } res.json({ success: true, data: { project: { id: project.id, name: project.name, description: project.settingsJson?.description || null, settings: project.settingsJson, trackingCount: project._count.checks, recentChecks: project.checks.map(check => ({ id: check.id, inputUrl: check.inputUrl, finalUrl: check.finalUrl, status: check.status, startedAt: check.startedAt, hopCount: check.hops.length, })), createdAt: project.createdAt, }, }, }); } catch (error) { logger_1.logger.error('Failed to get project:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Invalid project ID', }); } res.status(500).json({ success: false, error: 'Failed to get project', message: error instanceof Error ? error.message : 'Unknown error', }); } }); router.put('/:projectId', auth_middleware_1.requireAuth, async (req, res) => { try { const user = req.user; const { projectId } = projectParamsSchema.parse(req.params); const orgId = user.memberships[0]?.orgId; if (!orgId) { return res.status(404).json({ success: false, error: 'No organization found', }); } const validatedData = updateProjectSchema.parse(req.body); const existingProject = await prisma.project.findFirst({ where: { id: projectId, orgId: orgId, }, }); if (!existingProject) { return res.status(404).json({ success: false, error: 'Project not found', message: 'Project does not exist or you do not have access to it', }); } const currentSettings = existingProject.settingsJson || {}; const project = await prisma.project.update({ where: { id: projectId, }, data: { ...(validatedData.name && { name: validatedData.name }), settingsJson: { ...currentSettings, ...(validatedData.description !== undefined && { description: validatedData.description }), ...validatedData.settings, }, }, }); logger_1.logger.info(`Project updated: ${project.id}`, { userId: user.id, orgId, changes: validatedData, }); res.json({ success: true, data: { project: { id: project.id, name: project.name, description: project.settingsJson?.description || null, settings: project.settingsJson, createdAt: project.createdAt, }, }, message: 'Project updated successfully', }); } catch (error) { logger_1.logger.error('Failed to update project:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Validation failed', details: error.errors, }); } res.status(500).json({ success: false, error: 'Failed to update project', message: error instanceof Error ? error.message : 'Unknown error', }); } }); router.delete('/:projectId', auth_middleware_1.requireAuth, async (req, res) => { try { const user = req.user; const { projectId } = projectParamsSchema.parse(req.params); const orgId = user.memberships[0]?.orgId; if (!orgId) { return res.status(404).json({ success: false, error: 'No organization found', }); } const existingProject = await prisma.project.findFirst({ where: { id: projectId, orgId: orgId, }, include: { _count: { select: { checks: true, }, }, }, }); if (!existingProject) { return res.status(404).json({ success: false, error: 'Project not found', message: 'Project does not exist or you do not have access to it', }); } if (existingProject._count.checks > 0) { return res.status(400).json({ success: false, error: 'Cannot delete project with tracking data', message: `This project has ${existingProject._count.checks} tracking records. Please archive or move the data first.`, }); } await prisma.project.delete({ where: { id: projectId, }, }); logger_1.logger.info(`Project deleted: ${projectId}`, { userId: user.id, orgId, projectName: existingProject.name, }); res.json({ success: true, message: 'Project deleted successfully', }); } catch (error) { logger_1.logger.error('Failed to delete project:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Invalid project ID', }); } res.status(500).json({ success: false, error: 'Failed to delete project', message: error instanceof Error ? error.message : 'Unknown error', }); } }); exports.default = router; //# sourceMappingURL=projects.routes.js.map