5.9 KiB
5.9 KiB
Handoff Report — Explorer 2 (Milestone 2: Backend & DB)
1. Observation
We observed the following definitions and implementations in the codebase:
-
Prisma Schema (
apps/backend/prisma/schema.prisma):Menumodel (lines 638-646):model Menu { id Int @id @default(autoincrement()) name String @unique // e.g., "header", "footer" payload Json? isActive Boolean @default(true) items MenuItem[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }MenuItemmodel (lines 648-658):model MenuItem { id Int @id @default(autoincrement()) menuId Int menu Menu @relation(fields: [menuId], references: [id], onDelete: Cascade) label String url String order Int @default(0) translations MenuItemTranslation[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }
-
Shared Types (
packages/types/index.ts):- Interfaces
MenuItemandMenu(lines 195-208):export interface MenuItem { id: number label: string url: string order: number translations?: any[] } export interface Menu { id: number name: string items: MenuItem[] payload?: any }
- Interfaces
-
Backend Routes (
apps/backend/src/routes/menus.ts):- Validation schema of
POST /body (lines 50-59):body: t.Object({ name: t.String(), items: t.Optional(t.Array(t.Object({ label: t.String(), url: t.String(), order: t.Number() }))) }) - Validation schema of
PUT /:namebody (lines 132-147):body: t.Object({ payload: t.Optional(t.Any()), isActive: t.Optional(t.Boolean()), items: t.Array(t.Object({ id: t.Optional(t.Number()), label: t.String(), url: t.String(), order: t.Number(), translations: t.Optional(t.Array(t.Object({ langCode: t.String(), label: t.String() }))) })) }) - Database operations mapping in
PUT /:name(lines 90-118):if (item.id && existingItemIds.includes(item.id)) { await tx.menuItem.update({ where: { id: item.id }, data: { label: item.label, url: item.url, order: item.order } }); // ... } else { await tx.menuItem.create({ data: { menuId: menu!.id, label: item.label, url: item.url, order: item.order, translations: item.translations?.length ? { ... } : undefined } }); }
- Validation schema of
-
MCP Tools (
apps/mcp-server/menu-tools.tsandapps/mcp-server/menu-toolkit.ts):validateMenuItemshelper (lines 158-184):if (item.order !== undefined && typeof item.order !== "number") { issues.push(`items[${index}].order must be a number when provided`); }upsert_menutool definition input schema (lines 34-74):items: { type: "array", description: "Array of menu items", items: { type: "object", properties: { id: { type: "number", description: "ID of existing item (optional)" }, label: { type: "string", description: "Label of the menu item" }, url: { type: "string", description: "URL of the menu item" }, order: { type: "number", description: "Order sequence" }, translations: { ... } }, required: ["label", "url", "order"] } }
2. Logic Chain
- Adding the new columns to Prisma schema (Observation 1) as optional fields (
rootImage String?,columnImage String?,hoverImage String?) ensures database schema compatibility. Runningprisma migrate devcompiles a safe SQL statement that populates defaultNULLvalues for existing rows, which avoids downtime or data loss. - Exposing the fields on the shared interfaces (
packages/types/index.ts, Observation 2) aligns the TypeScript contracts between package users. - In order to save these image fields, we must extend Elysia's schema validator body tags
t.Optional(t.Nullable(t.String()))(Observation 3) and map the properties directly to the Prisma create/update calls, otherwise Elysia will strip them and Prisma won't save them. - Finally, updating
validateMenuItems(Observation 4) and the JSON inputSchema ofupsert_menu(Observation 4) allows external agents/clients to supply the image variables when working via MCP server endpoints.
3. Caveats
- We assumed frontend (SPA/Website) changes are scheduled under Milestone 3 and thus out of scope for implementation/updates in this backend-only task, though we identified their locations (
apps/spa/src/store/menuStore.tsandapps/website/src/components/navigation/menuTypes.ts). - We did not apply database changes or make code modifications as we are under a read-only constraint.
4. Conclusion
We have mapped the precise locations, code structures, and type changes required to fully implement rootImage, columnImage, and hoverImage across the database, shared types, backend controllers, and MCP tool schemas.
Detailed changes are saved to /home/ti/git/homaroma/.agents/explorer_m2_2/analysis.md.
5. Verification Method
To verify the implementation once the implementer carries out the changes:
- Run the build/check scripts to ensure zero compilation or type errors:
npm run build - Test menu endpoint updates by sending a HTTP PUT to
/api/menus/headeror calling the MCP toolupsert_menuwith image URLs, then verify the response returns the fields and database contains the updated columns.