diff --git a/packages/runtime/src/dispatcher-plugin.routes.test.ts b/packages/runtime/src/dispatcher-plugin.routes.test.ts index 594531d10..14635abb9 100644 --- a/packages/runtime/src/dispatcher-plugin.routes.test.ts +++ b/packages/runtime/src/dispatcher-plugin.routes.test.ts @@ -73,6 +73,22 @@ describe('createDispatcherPlugin — HTTP route registration', () => { expect(routes).toContain('GET /api/v1/ready'); }); + // Regression: PATCH /packages/:id (edit a package's manifest — name / + // description / version) had a handlePackages() branch all along but NO + // server.patch() registration, so it 405'd over HTTP and the Studio "edit + // package" form silently failed. Same class of bug as /ready above. The + // sibling /:id/enable|disable PATCH routes were mounted; the bare /:id was not. + it('mounts PATCH /packages/:id so the edit-manifest form reaches dispatch()', async () => { + const { server, routes } = makeFakeServer(); + const plugin = createDispatcherPlugin({ prefix: '/api/v1', securityHeaders: false }); + await plugin.start?.(makeCtx(server)); + + expect(routes).toContain('PATCH /api/v1/packages/:id'); + // Sanity: the sibling routes that WERE always mounted. + expect(routes).toContain('PATCH /api/v1/packages/:id/enable'); + expect(routes).toContain('POST /api/v1/packages'); + }); + it('also mounts a known existing route (sanity that start() ran)', async () => { const { server, routes } = makeFakeServer(); const plugin = createDispatcherPlugin({ prefix: '/api/v1', securityHeaders: false }); diff --git a/packages/runtime/src/dispatcher-plugin.ts b/packages/runtime/src/dispatcher-plugin.ts index 64bfcffed..7d8c2b765 100644 --- a/packages/runtime/src/dispatcher-plugin.ts +++ b/packages/runtime/src/dispatcher-plugin.ts @@ -721,6 +721,20 @@ export function createDispatcherPlugin(config: DispatcherPluginConfig = {}): Plu } }); + // Edit a package's manifest (name / description / version). The + // handler for this has existed in handlePackages all along, but the + // route was never registered, so PATCH /packages/:id 405'd and the + // Studio "edit package" form silently failed. `/:id` is a single + // segment, so this does not shadow the `/:id/enable|disable` routes. + server.patch(`${prefix}/packages/:id`, async (req: any, res: any) => { + try { + const result = await dispatcher.handlePackages(`/${req.params.id}`, 'PATCH', req.body, req.query, { request: req }); + sendResult(result, res); + } catch (err: any) { + errorResponse(err, res); + } + }); + server.patch(`${prefix}/packages/:id/enable`, async (req: any, res: any) => { try { const result = await dispatcher.handlePackages(`/${req.params.id}/enable`, 'PATCH', {}, {}, { request: req });