feat(FN-1492): fix workspace file operation route collision

- Fix Express route ordering where wildcard POST /files/{*filepath} was capturing operation routes
- Move operation routes (delete, copy, move, rename) before the generic write route to ensure proper matching
- Add missing ProjectEngine methods (getHeartbeatTriggerScheduler) for dashboard compatibility
- Add 189 regression tests verifying operation routes work correctly with nested paths
- Document Express wildcard route ordering pitfall in memory
This commit is contained in:
gsxdsm
2026-04-12 23:58:49 -07:00
parent 372337c608
commit 522a2d52b0
4 changed files with 248 additions and 49 deletions

View File

@@ -207,6 +207,7 @@ Dashboard SSE (`/api/events`) streams plugin lifecycle events as normalized `plu
## Pitfalls
- When adding props to a React component interface that were previously declared but not destructured in the function body, remember to add them to the destructuring list too. TypeScript won't warn about unused interface fields, so `onOpenScripts` in `MobileNavBarProps` compiled fine but caused `ReferenceError: onOpenScripts is not defined` at runtime.
- **Express wildcard route ordering (FN-1492)**: When defining Express routes with wildcard patterns like `{*filepath}`, ALWAYS define more specific routes BEFORE the generic wildcard route. Express matches routes in order, so `POST /files/{*filepath}` would shadow `POST /files/{*filepath}/delete` if defined first. The fix is to define operation routes (`/copy`, `/move`, `/delete`, `/rename`, `/download`, etc.) BEFORE the generic write route. See `packages/dashboard/src/routes.ts` for the correct ordering pattern.
- **Webhook HMAC testing**: The `REQUEST` test utility in `test-request.ts` doesn't handle stream-based middleware like `express.raw()` well. For webhook routes requiring HMAC verification (e.g., GitHub webhooks, routine webhooks), test the `verifyWebhookSignature` function directly using `await import()` rather than trying to set up raw body middleware through Express. See the routine webhook tests in `routes.test.ts` for the pattern.
- `vi.fn<Parameters<SomeType>, ReturnType<SomeType>>()` works in Vitest runtime but causes TypeScript build errors (`TS2558: Expected 0-1 type arguments, but got 2`). Always use the cast pattern instead.