feat: implement block management API endpoints
This commit is contained in:
@@ -1,5 +1,122 @@
|
|||||||
import { FastifyInstance } from 'fastify';
|
import { FastifyInstance, FastifyRequest } from 'fastify';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { authenticate, authorizeProjectMember, authorizePlanner } from '../middleware/auth';
|
||||||
|
import { BlockService } from '../services/blockService';
|
||||||
|
|
||||||
|
const blockIdSchema = z.object({
|
||||||
|
blockId: z.string().uuid()
|
||||||
|
});
|
||||||
|
|
||||||
|
const blockCreateSchema = z.object({
|
||||||
|
name: z.string().min(1),
|
||||||
|
description: z.string().optional(),
|
||||||
|
elements: z.array(z.string().uuid())
|
||||||
|
});
|
||||||
|
|
||||||
|
const blockUpdateSchema = z.object({
|
||||||
|
name: z.string().min(1).optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
elements: z.array(z.string().uuid()).optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
const blockInsertSchema = z.object({
|
||||||
|
position_x: z.number(),
|
||||||
|
position_y: z.number(),
|
||||||
|
rotation: z.number().optional().default(0),
|
||||||
|
scale_x: z.number().optional().default(1),
|
||||||
|
scale_y: z.number().optional().default(1)
|
||||||
|
});
|
||||||
|
|
||||||
export default async function blocksRoutes(fastify: FastifyInstance) {
|
export default async function blocksRoutes(fastify: FastifyInstance) {
|
||||||
// Placeholder for blocks routes
|
// GET / - List block definitions for project
|
||||||
}
|
fastify.get('/', {
|
||||||
|
preHandler: [authenticate, authorizeProjectMember]
|
||||||
|
}, async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const projectId = request.params.projectId;
|
||||||
|
const blocks = await BlockService.listBlocks(projectId);
|
||||||
|
return blocks;
|
||||||
|
} catch (error) {
|
||||||
|
request.log.error(error);
|
||||||
|
reply.status(500).send({ error: 'Failed to list blocks' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST / - Create block definition from selected elements
|
||||||
|
fastify.post('/', {
|
||||||
|
preHandler: [authenticate, authorizePlanner]
|
||||||
|
}, async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const projectId = request.params.projectId;
|
||||||
|
const body = blockCreateSchema.parse(request.body);
|
||||||
|
const block = await BlockService.createBlock(projectId, body);
|
||||||
|
reply.status(201).send(block);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof z.ZodError) {
|
||||||
|
reply.status(400).send({ error: 'Validation error', details: error.errors });
|
||||||
|
} else {
|
||||||
|
request.log.error(error);
|
||||||
|
reply.status(500).send({ error: 'Failed to create block' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// PUT /:blockId - Update block definition
|
||||||
|
fastify.put('/:blockId', {
|
||||||
|
preHandler: [authenticate, authorizePlanner]
|
||||||
|
}, async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const { blockId } = blockIdSchema.parse(request.params);
|
||||||
|
const projectId = request.params.projectId;
|
||||||
|
const body = blockUpdateSchema.parse(request.body);
|
||||||
|
const block = await BlockService.updateBlock(projectId, blockId, body);
|
||||||
|
return block;
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof z.ZodError) {
|
||||||
|
reply.status(400).send({ error: 'Validation error', details: error.errors });
|
||||||
|
} else {
|
||||||
|
request.log.error(error);
|
||||||
|
reply.status(500).send({ error: 'Failed to update block' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// DELETE /:blockId - Delete block definition
|
||||||
|
fastify.delete('/:blockId', {
|
||||||
|
preHandler: [authenticate, authorizePlanner]
|
||||||
|
}, async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const { blockId } = blockIdSchema.parse(request.params);
|
||||||
|
const projectId = request.params.projectId;
|
||||||
|
await BlockService.deleteBlock(projectId, blockId);
|
||||||
|
reply.status(204).send();
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof z.ZodError) {
|
||||||
|
reply.status(400).send({ error: 'Validation error', details: error.errors });
|
||||||
|
} else {
|
||||||
|
request.log.error(error);
|
||||||
|
reply.status(500).send({ error: 'Failed to delete block' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST /:blockId/insert - Insert block instance with parameters
|
||||||
|
fastify.post('/:blockId/insert', {
|
||||||
|
preHandler: [authenticate, authorizePlanner]
|
||||||
|
}, async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const { blockId } = blockIdSchema.parse(request.params);
|
||||||
|
const projectId = request.params.projectId;
|
||||||
|
const body = blockInsertSchema.parse(request.body);
|
||||||
|
const instance = await BlockService.insertBlockInstance(projectId, blockId, body);
|
||||||
|
reply.status(201).send(instance);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof z.ZodError) {
|
||||||
|
reply.status(400).send({ error: 'Validation error', details: error.errors });
|
||||||
|
} else {
|
||||||
|
request.log.error(error);
|
||||||
|
reply.status(500).send({ error: 'Failed to insert block instance' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user