@vizzly-testing/cli
Version:
Visual review platform for UI developers and designers
168 lines (160 loc) • 5.19 kB
JavaScript
/**
* Projects Router
* Handles project management and builds endpoints
*/
import { parseJsonBody } from '../middleware/json-parser.js';
import { sendSuccess, sendError, sendServiceUnavailable } from '../middleware/response.js';
import * as output from '../../utils/output.js';
/**
* Create projects router
* @param {Object} context - Router context
* @param {Object} context.projectService - Project service
* @returns {Function} Route handler
*/
export function createProjectsRouter({
projectService
}) {
return async function handleProjectsRoute(req, res, pathname, parsedUrl) {
// Check if project service is available for all project routes
if (pathname.startsWith('/api/projects') && !projectService) {
sendServiceUnavailable(res, 'Project service');
return true;
}
// List all projects from API
if (req.method === 'GET' && pathname === '/api/projects') {
try {
let projects = await projectService.listProjects();
sendSuccess(res, {
projects
});
return true;
} catch (error) {
output.debug('Error listing projects:', {
error: error.message
});
sendError(res, 500, error.message);
return true;
}
}
// List project directory mappings
if (req.method === 'GET' && pathname === '/api/projects/mappings') {
try {
let mappings = await projectService.listMappings();
sendSuccess(res, {
mappings
});
return true;
} catch (error) {
output.debug('Error listing project mappings:', {
error: error.message
});
sendError(res, 500, error.message);
return true;
}
}
// Create or update project mapping
if (req.method === 'POST' && pathname === '/api/projects/mappings') {
try {
let body = await parseJsonBody(req);
let {
directory,
projectSlug,
organizationSlug,
token,
projectName
} = body;
let mapping = await projectService.createMapping(directory, {
projectSlug,
organizationSlug,
token,
projectName
});
sendSuccess(res, {
success: true,
mapping
});
return true;
} catch (error) {
output.debug('Error creating project mapping:', {
error: error.message
});
sendError(res, 500, error.message);
return true;
}
}
// Delete project mapping
if (req.method === 'DELETE' && pathname.startsWith('/api/projects/mappings/')) {
try {
let directory = decodeURIComponent(pathname.replace('/api/projects/mappings/', ''));
await projectService.removeMapping(directory);
sendSuccess(res, {
success: true,
message: 'Mapping deleted'
});
return true;
} catch (error) {
output.debug('Error deleting project mapping:', {
error: error.message
});
sendError(res, 500, error.message);
return true;
}
}
// Get recent builds for current project
if (req.method === 'GET' && pathname === '/api/builds/recent') {
if (!projectService) {
sendServiceUnavailable(res, 'Project service');
return true;
}
try {
let currentDir = process.cwd();
let mapping = await projectService.getMapping(currentDir);
if (!mapping || !mapping.projectSlug || !mapping.organizationSlug) {
sendError(res, 400, 'No project configured for this directory');
return true;
}
let limit = parseInt(parsedUrl.searchParams.get('limit') || '10', 10);
let branch = parsedUrl.searchParams.get('branch') || undefined;
let builds = await projectService.getRecentBuilds(mapping.projectSlug, mapping.organizationSlug, {
limit,
branch
});
sendSuccess(res, {
builds
});
return true;
} catch (error) {
output.debug('Error fetching recent builds:', {
error: error.message
});
sendError(res, 500, error.message);
return true;
}
}
// Get builds for a specific project (used by /builds page)
let projectBuildsMatch = pathname.match(/^\/api\/projects\/([^/]+)\/([^/]+)\/builds$/);
if (req.method === 'GET' && projectBuildsMatch) {
try {
let organizationSlug = decodeURIComponent(projectBuildsMatch[1]);
let projectSlug = decodeURIComponent(projectBuildsMatch[2]);
let limit = parseInt(parsedUrl.searchParams.get('limit') || '20', 10);
let branch = parsedUrl.searchParams.get('branch') || undefined;
let builds = await projectService.getRecentBuilds(projectSlug, organizationSlug, {
limit,
branch
});
sendSuccess(res, {
builds
});
return true;
} catch (error) {
output.debug('Error fetching project builds:', {
error: error.message
});
sendError(res, 500, error.message);
return true;
}
}
return false;
};
}