ReviewOS

also looking at this

stacks/pet-store

umbrella: pet-store storefront fixes (rolling)

#3
Merged glennmichael123 wants to merge umbrella/pet-store into main
586 files +38082 -7487

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

storage/framework/core/router/src/middleware.tsmodified+31-0
Changes to storage/framework/core/router/src/middleware.ts
@@ -45,4 +45,35 @@ export class Middleware {
4545 this.priority = config.priority ?? 10
4646 this.handle = config.handle
4747 }
48
49 /**
50 * Adapt this Middleware to the bun-router (req, next) → Response shape.
51 *
52 * The Middleware class contract is "return void to continue, throw a
53 * Response/HttpError to short-circuit". Bun-router's middleware contract
54 * is "call next() and return its Response". Pushing `handle.bind(this)`
55 * straight onto `globalMiddleware` drops the second contract on the
56 * floor — `handle` ignores `next` and returns `undefined`, which
57 * `buildMiddlewareChain` interprets as a final response, so it falls
58 * back to `new Response(null, { status: 200 })` and the actual route
59 * handler downstream never runs. Visible symptom: every route returns
60 * `200 OK` with `Content-Length: 0`.
61 *
62 * Use this adapter whenever attaching a `Middleware` instance via
63 * `route.use(...)` or `route.middleware(...)` so the void/throw contract
64 * is honoured.
65 */
66 toRouterHandler(): (req: EnhancedRequest, next: () => Promise<Response>) => Promise<Response> {
67 const handle = this.handle.bind(this)
68 return async (req, next) => {
69 try {
70 await handle(req)
71 }
72 catch (thrown) {
73 if (thrown instanceof Response) return thrown
74 throw thrown
75 }
76 return next()
77 }
78 }
4879}
storage/framework/defaults/bootstrap.tsmodified+7-1
Changes to storage/framework/defaults/bootstrap.ts
@@ -37,7 +37,13 @@ import MaintenanceMiddleware from './app/Middleware/Maintenance'
3737// itself reads `activeSiteModePayload()` so it covers both maintenance
3838// and coming-soon modes (plus `APP_MAINTENANCE` / `APP_COMING_SOON`
3939// env overrides) without the bootstrap needing to know the details.
40route.use(MaintenanceMiddleware.handle.bind(MaintenanceMiddleware) as any)
40//
41// `toRouterHandler()` adapts the Middleware contract (return void to
42// continue, throw a Response to short-circuit) to bun-router's
43// `(req, next) => Response` shape. Without the adapter, `handle` would
44// return `undefined`, bun-router's chain treats that as a short-circuit
45// to an empty 200, and every route returns `200 OK Content-Length: 0`.
46route.use(MaintenanceMiddleware.toRouterHandler() as any)
4147
4248// Feature-gated route registration. The dashboard.ts file currently bundles
4349// ~687 lines covering auth, password reset, email subscribe, storefront