import { Router } from "express"; import { ok } from "../../lib/api-response.js"; import { getSingleParam } from "../../lib/http.js"; import { requireTableAccess } from "../../middleware/permission.js"; import { validateBody } from "../../middleware/validate.js"; import { createAuditEvent } from "../audit/audit.service.js"; import { addColumn, dropColumn, ensureSchemaMutationsEnabled, updateColumn } from "./schema.service.js"; import { createColumnSchema, updateColumnSchema } from "./schema.schemas.js"; export const schemaRouter = Router({ mergeParams: true }); schemaRouter.post("/", requireTableAccess("schema_change"), validateBody(createColumnSchema), async (req, res, next) => { try { const tableName = getSingleParam(req.params.table); await ensureSchemaMutationsEnabled(); await addColumn(tableName, req.body); await createAuditEvent({ actorUserId: req.user?.id ?? null, action: "schema.column.create", resourceType: "table", resourceName: tableName, payloadAfter: req.body, ip: req.ip, userAgent: req.headers["user-agent"] ?? null, status: "success" }); res.status(201).json(ok({ created: true })); } catch (error) { next(error); } }); schemaRouter.put( "/:column", requireTableAccess("schema_change"), validateBody(updateColumnSchema), async (req, res, next) => { try { const tableName = getSingleParam(req.params.table); const columnName = getSingleParam(req.params.column); await ensureSchemaMutationsEnabled(); await updateColumn(tableName, columnName, req.body); await createAuditEvent({ actorUserId: req.user?.id ?? null, action: "schema.column.update", resourceType: "table", resourceName: `${tableName}.${columnName}`, payloadAfter: req.body, ip: req.ip, userAgent: req.headers["user-agent"] ?? null, status: "success" }); res.json(ok({ updated: true })); } catch (error) { next(error); } } ); schemaRouter.delete("/:column", requireTableAccess("schema_change"), async (req, res, next) => { try { const tableName = getSingleParam(req.params.table); const columnName = getSingleParam(req.params.column); await ensureSchemaMutationsEnabled(); await dropColumn(tableName, columnName); await createAuditEvent({ actorUserId: req.user?.id ?? null, action: "schema.column.delete", resourceType: "table", resourceName: `${tableName}.${columnName}`, ip: req.ip, userAgent: req.headers["user-agent"] ?? null, status: "success" }); res.json(ok({ deleted: true })); } catch (error) { next(error); } });