Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
246 lines
5.8 KiB
JavaScript
246 lines
5.8 KiB
JavaScript
import express from 'express';
|
|
import { authenticateToken } from '../middleware/auth.js';
|
|
import Project from '../models/Project.js';
|
|
import User from '../models/User.js';
|
|
|
|
const router = express.Router();
|
|
|
|
// Get all projects for user
|
|
router.get('/', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const projects = await Project.findAll({
|
|
where: { userId: req.user.id },
|
|
attributes: { exclude: ['settings'] }
|
|
});
|
|
|
|
res.status(200).json({
|
|
status: 'success',
|
|
code: 'PROJECTS_RETRIEVED',
|
|
message: 'Projects retrieved successfully',
|
|
data: { projects }
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Get single project
|
|
router.get('/:id', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const project = await Project.findOne({
|
|
where: { id: req.params.id, userId: req.user.id }
|
|
});
|
|
|
|
if (!project) {
|
|
return res.status(404).json({
|
|
status: 'error',
|
|
code: 'PROJECT_NOT_FOUND',
|
|
message: 'Project not found',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
res.status(200).json({
|
|
status: 'success',
|
|
code: 'PROJECT_RETRIEVED',
|
|
message: 'Project retrieved successfully',
|
|
data: { project }
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Create project
|
|
router.post('/', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const { name, description, key, figmaFileKey, jiraProjectKey, storybookUrl } = req.body;
|
|
|
|
if (!name || !key) {
|
|
return res.status(400).json({
|
|
status: 'error',
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Name and key are required',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
const project = await Project.create({
|
|
name,
|
|
description,
|
|
key,
|
|
userId: req.user.id,
|
|
figmaFileKey,
|
|
jiraProjectKey,
|
|
storybookUrl
|
|
});
|
|
|
|
res.status(201).json({
|
|
status: 'success',
|
|
code: 'PROJECT_CREATED',
|
|
message: 'Project created successfully',
|
|
data: { project }
|
|
});
|
|
} catch (error) {
|
|
if (error.name === 'SequelizeUniqueConstraintError') {
|
|
return res.status(409).json({
|
|
status: 'error',
|
|
code: 'DUPLICATE_KEY',
|
|
message: 'Project key already exists',
|
|
data: null
|
|
});
|
|
}
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Update project
|
|
router.put('/:id', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const project = await Project.findOne({
|
|
where: { id: req.params.id, userId: req.user.id }
|
|
});
|
|
|
|
if (!project) {
|
|
return res.status(404).json({
|
|
status: 'error',
|
|
code: 'PROJECT_NOT_FOUND',
|
|
message: 'Project not found',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
const { name, description, figmaFileKey, jiraProjectKey, storybookUrl, status, settings } = req.body;
|
|
|
|
await project.update({
|
|
name: name || project.name,
|
|
description: description !== undefined ? description : project.description,
|
|
figmaFileKey: figmaFileKey !== undefined ? figmaFileKey : project.figmaFileKey,
|
|
jiraProjectKey: jiraProjectKey !== undefined ? jiraProjectKey : project.jiraProjectKey,
|
|
storybookUrl: storybookUrl !== undefined ? storybookUrl : project.storybookUrl,
|
|
status: status || project.status,
|
|
settings: settings || project.settings
|
|
});
|
|
|
|
res.status(200).json({
|
|
status: 'success',
|
|
code: 'PROJECT_UPDATED',
|
|
message: 'Project updated successfully',
|
|
data: { project }
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Delete project
|
|
router.delete('/:id', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const project = await Project.findOne({
|
|
where: { id: req.params.id, userId: req.user.id }
|
|
});
|
|
|
|
if (!project) {
|
|
return res.status(404).json({
|
|
status: 'error',
|
|
code: 'PROJECT_NOT_FOUND',
|
|
message: 'Project not found',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
await project.destroy();
|
|
|
|
res.status(200).json({
|
|
status: 'success',
|
|
code: 'PROJECT_DELETED',
|
|
message: 'Project deleted successfully',
|
|
data: null
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Save ESRE (style requirements) for project
|
|
router.post('/:id/esre', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const project = await Project.findOne({
|
|
where: { id: req.params.id, userId: req.user.id }
|
|
});
|
|
|
|
if (!project) {
|
|
return res.status(404).json({
|
|
status: 'error',
|
|
code: 'PROJECT_NOT_FOUND',
|
|
message: 'Project not found',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
const { content } = req.body;
|
|
|
|
if (!content) {
|
|
return res.status(400).json({
|
|
status: 'error',
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'ESRE content is required',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// Update project settings with ESRE content
|
|
await project.update({
|
|
settings: {
|
|
...project.settings,
|
|
esre: content
|
|
}
|
|
});
|
|
|
|
res.status(200).json({
|
|
status: 'success',
|
|
code: 'ESRE_SAVED',
|
|
message: 'ESRE saved successfully',
|
|
data: {
|
|
success: true,
|
|
savedAt: new Date().toISOString()
|
|
}
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Get ESRE (style requirements) for project
|
|
router.get('/:id/esre', authenticateToken, async (req, res, next) => {
|
|
try {
|
|
const project = await Project.findOne({
|
|
where: { id: req.params.id, userId: req.user.id }
|
|
});
|
|
|
|
if (!project) {
|
|
return res.status(404).json({
|
|
status: 'error',
|
|
code: 'PROJECT_NOT_FOUND',
|
|
message: 'Project not found',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
const esreContent = project.settings?.esre || '';
|
|
|
|
res.status(200).json({
|
|
status: 'success',
|
|
code: 'ESRE_RETRIEVED',
|
|
message: 'ESRE retrieved successfully',
|
|
data: {
|
|
content: esreContent
|
|
}
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
export default router;
|