Fix ignore route slug collision ([packageId] → [id]) — Next.js runtime 500s (ISS-047 part B)
CI / build + unit + e2e (pull_request) Successful in 8m21s
CI / build + unit + e2e (pull_request) Successful in 8m21s
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
## v0.29.0 — 2026-09-20 14:27
|
||||
- **Ignore a job (ISS-047, part B).** A player can now dismiss an open job so it leaves the market permanently; new random jobs spawn in its place via the existing top-up logic (`spawnOpenPackages` counts 'open', so the market refills to 10 on the next tick). New terminal package status `'ignored'` added to the status union/enum in `lib/db/schema.ts`, `lib/game/state.ts`, `lib/openapi.ts` (PackageState.status) and the e2e-local interface copy in `e2e/right-pane.spec.ts`. No DB migration — the column is plain TEXT with no CHECK constraint. New action `ignorePackage` (`lib/game/actions.ts`) next to abandon: 404 unknown id, 409 unless open ("only open packages can be ignored"), otherwise flips status to 'ignored' — no body, no penalty, nothing else changes
|
||||
- **New route.** `POST /api/packages/{packageId}/ignore` (`app/api/packages/[packageId]/ignore/route.ts`) — no body, mirrors the abandon route exactly (same performAction wrapper, full state snapshot on success). The 13th public endpoint: OpenAPI spec gains the path + 'ignored' in PackageState.status; `lib/openapi.test.ts` and `e2e/api.spec.ts` path lists updated twelve → thirteen
|
||||
- **New route.** `POST /api/packages/{id}/ignore` (`app/api/packages/[id]/ignore/route.ts`) — no body, mirrors the abandon route exactly (same performAction wrapper, full state snapshot on success). The 13th public endpoint: OpenAPI spec gains the path + 'ignored' in PackageState.status; `lib/openapi.test.ts` and `e2e/api.spec.ts` path lists updated twelve → thirteen
|
||||
- **UI.** Each open-package row in the Jobs tab gains a small "Ignore" button beside the Load controls (`components/RightPane.tsx`, testid `ignore-{pkg.id}`, disabled while the pane action is busy, calls runAction with no body). Ignored rows vanish from the list automatically — the section filters status==='open'; no toast (deriveEvents untouched)
|
||||
- Verified-safe consumers unchanged: expirePackages selects only open|loaded ('ignored' never expires), deliverPackages handles loaded/expired, RightPane filters 'open'
|
||||
- Tests: unit — new `ignorePackage` block in `lib/game/actions.test.ts` (open → ignored with cash/planeId untouched; 409 for each of loaded/delivered/expired/abandoned/already-ignored; 404 unknown id), `lib/sim/engine.test.ts` terminal-statuses test gains an 'ignored' row, `lib/openapi.test.ts` status enum list gains 'ignored'. E2E — new "Ignore removes an open job from the list permanently" test in `e2e/right-pane.spec.ts`: hook-created package renders with an enabled Ignore button, UI click → /api/state shows 'ignored', row gone from `[data-testid="open-packages"]`, second API ignore 409s
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import { ignorePackage, performAction } from '@/lib/game/actions';
|
||||
// leaves the market permanently; the top-up logic spawns a replacement on the next tick. No penalty,
|
||||
// nothing else changes. 404 unknown id; 409 unless open. On success returns the full state snapshot.
|
||||
|
||||
export async function POST(_req: Request, ctx: { params: Promise<{ packageId: string }> }) {
|
||||
const { packageId } = await ctx.params;
|
||||
return performAction((inst) => ignorePackage(inst, packageId));
|
||||
export async function POST(_req: Request, ctx: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await ctx.params;
|
||||
return performAction((inst) => ignorePackage(inst, id));
|
||||
}
|
||||
+1
-1
@@ -26,8 +26,8 @@ test('GET /api/openapi serves the spec with all thirteen endpoints and the packa
|
||||
'/api/market/buy-plane',
|
||||
'/api/market/sell-plane',
|
||||
'/api/packages/{id}/abandon',
|
||||
'/api/packages/{id}/ignore', // v0.29.0 (ISS-047 part B)
|
||||
'/api/packages/{id}/load',
|
||||
'/api/packages/{packageId}/ignore', // v0.29.0 (ISS-047 part B)
|
||||
'/api/planes/{planeId}/fly',
|
||||
'/api/planes/{planeId}/queue',
|
||||
'/api/planes/{planeId}/queue/cancel',
|
||||
|
||||
+1
-1
@@ -9,8 +9,8 @@ describe('OpenAPI spec', () => {
|
||||
'/api/market/buy-plane',
|
||||
'/api/market/sell-plane',
|
||||
'/api/packages/{id}/abandon',
|
||||
'/api/packages/{id}/ignore', // v0.29.0 (ISS-047 part B)
|
||||
'/api/packages/{id}/load',
|
||||
'/api/packages/{packageId}/ignore', // v0.29.0 (ISS-047 part B)
|
||||
'/api/planes/{planeId}/fly',
|
||||
'/api/planes/{planeId}/queue', // v0.25.0 (ISS-043)
|
||||
'/api/planes/{planeId}/queue/cancel', // v0.25.0 (ISS-043)
|
||||
|
||||
+2
-2
@@ -165,14 +165,14 @@ export const openApiSpec = {
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/packages/{packageId}/ignore': {
|
||||
'/api/packages/{id}/ignore': {
|
||||
post: {
|
||||
summary: 'Ignore an open job',
|
||||
description:
|
||||
'Dismiss an OPEN job so it leaves the market permanently (v0.29.0, ISS-047 part B). No penalty and nothing else changes — the top-up logic spawns a replacement on the next tick. No body.',
|
||||
operationId: 'ignorePackage',
|
||||
parameters: [
|
||||
{ name: 'packageId', in: 'path', required: true, schema: { type: 'string' } },
|
||||
{ name: 'id', in: 'path', required: true, schema: { type: 'string' } },
|
||||
],
|
||||
responses: {
|
||||
200: {
|
||||
|
||||
Reference in New Issue
Block a user