x
This commit is contained in:
1 parent
3965f4f4da
commit
70877882b0
82 files changed
+4353
-186
No files matched your search
@@ -0,0 +1,150 @@
|
||||
# Handoff Report — Explorer 2 (Milestone 2: Backend & DB)
|
||||
|
||||
## 1. Observation
|
||||
We observed the following definitions and implementations in the codebase:
|
||||
|
||||
1. **Prisma Schema (`apps/backend/prisma/schema.prisma`)**:
|
||||
- `Menu` model (lines 638-646):
|
||||
```prisma
|
||||
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
|
||||
}
|
||||
```
|
||||
- `MenuItem` model (lines 648-658):
|
||||
```prisma
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
2. **Shared Types (`packages/types/index.ts`)**:
|
||||
- Interfaces `MenuItem` and `Menu` (lines 195-208):
|
||||
```typescript
|
||||
export interface MenuItem {
|
||||
id: number
|
||||
label: string
|
||||
url: string
|
||||
order: number
|
||||
translations?: any[]
|
||||
}
|
||||
|
||||
export interface Menu {
|
||||
id: number
|
||||
name: string
|
||||
items: MenuItem[]
|
||||
payload?: any
|
||||
}
|
||||
```
|
||||
|
||||
3. **Backend Routes (`apps/backend/src/routes/menus.ts`)**:
|
||||
- Validation schema of `POST /` body (lines 50-59):
|
||||
```typescript
|
||||
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 /:name` body (lines 132-147):
|
||||
```typescript
|
||||
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):
|
||||
```typescript
|
||||
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
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
4. **MCP Tools (`apps/mcp-server/menu-tools.ts` and `apps/mcp-server/menu-toolkit.ts`)**:
|
||||
- `validateMenuItems` helper (lines 158-184):
|
||||
```typescript
|
||||
if (item.order !== undefined && typeof item.order !== "number") {
|
||||
issues.push(`items[${index}].order must be a number when provided`);
|
||||
}
|
||||
```
|
||||
- `upsert_menu` tool definition input schema (lines 34-74):
|
||||
```json
|
||||
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. Running `prisma migrate dev` compiles a safe SQL statement that populates default `NULL` values 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 of `upsert_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.ts` and `apps/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:
|
||||
1. Run the build/check scripts to ensure zero compilation or type errors:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
2. Test menu endpoint updates by sending a HTTP PUT to `/api/menus/header` or calling the MCP tool `upsert_menu` with image URLs, then verify the response returns the fields and database contains the updated columns.
|
||||
Reference in new issue
Block a user