git.iko.soy/rowtype-yoga/purescript-yoga-http-api
on feat/custom-type-errors help sign in
feat: Add respondStatus for numeric status codes

Add respondStatus and respondStatusWith functions that accept numeric status codes using visible type application: respondStatus @200 { message: "success" } respondStatusWith @201 { "Location": "/users/123" } user This provides an alternative to the label-based respond functions: respond @"ok" ... respondWith @"created" ... Both styles are supported. The numeric version uses StatusCodeToLabel class to map status codes (200, 404, etc.) to their label names ("ok", "notFound", etc.) at the type level.

commita1f9ddf6299ce2dd4260456760e7625fc428352b authorMark <mark.eibes@gmail.com> dateFri 6 Feb 2026, 22:34 (8 months ago) parent3c2045c
2 files changed+71
src/Yoga/HTTP/API/Route/Response.purs+34 src/Yoga/HTTP/API/Route/StatusCode.purs+37
src/Yoga/HTTP/API/Route/Response.purs+34
@@ -6,6 +6,8 @@ module Yoga.HTTP.API.Route.Response
66 , respond
77 , respondWith
88 , respondNoHeaders
9+ , respondStatus
10+ , respondStatusWith
911 , respondNoBody
1012 , respondNothing
1113 , respondNoContent
@@ -22,6 +24,7 @@ import Prim.RowList as RL
2224import Prim.TypeError (class Fail, Text, Above)
2325import Type.Proxy (Proxy(..))
2426import Unsafe.Coerce (unsafeCoerce)
27+import Yoga.HTTP.API.Route.StatusCode (class StatusCodeToLabel)
2528
2629--------------------------------------------------------------------------------
2730-- Response Data Type
@@ -157,6 +160,37 @@ respondNoHeaders
157160respondNoHeaders body =
158161 Variant.inj (Proxy :: Proxy label) (Response { headers: {}, body })
159162
163+-- | Construct a variant response using numeric status code
164+-- |
165+-- | Example:
166+-- | respondStatus @200 user
167+-- | respondStatus @404 { error: "Not found" }
168+respondStatus
169+ :: forall @code label body r1 r2
170+ . StatusCodeToLabel code label
171+ => IsSymbol label
172+ => Cons label (Response () body) r1 r2
173+ => body
174+ -> Variant r2
175+respondStatus body =
176+ Variant.inj (Proxy :: Proxy label) (Response { headers: {}, body })
177+
178+-- | Construct a variant response with headers using numeric status code
179+-- |
180+-- | Example:
181+-- | respondStatusWith @201 { "Location": "/users/123" } user
182+respondStatusWith
183+ :: forall @code label headers body r1 r2
184+ . StatusCodeToLabel code label
185+ => IsSymbol label
186+ => Cons label (Response headers body) r1 r2
187+ => Record headers
188+ -> body
189+ -> Variant r2
190+respondStatusWith headers body =
191+ Variant.inj (Proxy :: Proxy label) (Response { headers, body })
192+
193+
160194-- | Construct a variant response with headers but no body
161195-- |
162196-- | Example:
src/Yoga/HTTP/API/Route/StatusCode.purs+37
@@ -5,6 +5,7 @@ module Yoga.HTTP.API.Route.StatusCode
55 , statusCodeFor
66 , statusCodeToString
77 , StatusCode(..)
8+ , class StatusCodeToLabel
89 ) where
910
1011import Prelude
@@ -264,3 +265,39 @@ instance StatusCodeMapImpl (Proxy sym) => StatusCodeMap sym where
264265-- | Convert StatusCode to String for OpenAPI generation
265266statusCodeToString :: StatusCode -> String
266267statusCodeToString (StatusCode n) = show n
268+
269+--------------------------------------------------------------------------------
270+-- Status Code to Label Mapping
271+--------------------------------------------------------------------------------
272+
273+-- | Map numeric status codes to their label names
274+class StatusCodeToLabel (code :: Int) (label :: Symbol) | code -> label
275+
276+-- 2xx Success
277+instance StatusCodeToLabel 200 "ok"
278+instance StatusCodeToLabel 201 "created"
279+instance StatusCodeToLabel 202 "accepted"
280+instance StatusCodeToLabel 204 "noContent"
281+
282+-- 3xx Redirection
283+instance StatusCodeToLabel 301 "movedPermanently"
284+instance StatusCodeToLabel 302 "found"
285+instance StatusCodeToLabel 303 "seeOther"
286+instance StatusCodeToLabel 304 "notModified"
287+instance StatusCodeToLabel 307 "temporaryRedirect"
288+instance StatusCodeToLabel 308 "permanentRedirect"
289+
290+-- 4xx Client Errors
291+instance StatusCodeToLabel 400 "badRequest"
292+instance StatusCodeToLabel 401 "unauthorized"
293+instance StatusCodeToLabel 403 "forbidden"
294+instance StatusCodeToLabel 404 "notFound"
295+instance StatusCodeToLabel 409 "conflict"
296+instance StatusCodeToLabel 422 "unprocessableEntity"
297+instance StatusCodeToLabel 429 "tooManyRequests"
298+
299+-- 5xx Server Errors
300+instance StatusCodeToLabel 500 "internalServerError"
301+instance StatusCodeToLabel 502 "badGateway"
302+instance StatusCodeToLabel 503 "serviceUnavailable"
303+