git.iko.soy/rowtype-yoga/purescript-yoga-http-api
on feat/custom-type-errors help sign in
feat: Add custom type error for invalid response record structure

Add a helpful compile-time error message when users provide response records with invalid fields (e.g., including 'status' or 'statusCode' fields). The error message clearly explains: - Valid response record structure (body required, headers optional) - Examples of correct usage - Common mistakes to avoid This improves developer experience by catching structural errors at compile time with actionable feedback instead of generic type mismatch errors.

commit5dab98820b265e2c6bcc54eae3ff2d836e0f8865 authorMark <mark.eibes@gmail.com> dateFri 6 Feb 2026, 21:53 (8 months ago) parentcb61c73
3 files changed+41−1
src/Yoga/HTTP/API/Path.purs+1−1 src/Yoga/HTTP/API/Route/Response.purs+38 src/Yoga/HTTP/API/Route/StatusCode.purs+2
src/Yoga/HTTP/API/Path.purs+1−1
@@ -34,7 +34,6 @@ import Prim.Row as Row
3434import Record as Record
3535import Type.Proxy (Proxy(..))
3636import Unsafe.Coerce (unsafeCoerce)
37−
3837--------------------------------------------------------------------------------
3938-- Type-Level Path DSL
4039--------------------------------------------------------------------------------
@@ -242,6 +241,7 @@ instance parseParamNumber :: ParseParam Number where
242241 Nothing -> Left $ "Expected a number but got: " <> s
243242 Just n -> Right (Int.toNumber n) -- Simple version, doesn't handle floats
244243
244+
245245-- | Parse a URL string into a record of typed path parameters
246246-- |
247247-- | Examples:
src/Yoga/HTTP/API/Route/Response.purs+38
@@ -19,6 +19,7 @@ import Data.Variant (Variant)
1919import Data.Variant as Variant
2020import Prim.Row (class Cons)
2121import Prim.RowList as RL
22+import Prim.TypeError (class Fail, Text, Above)
2223import Type.Proxy (Proxy(..))
2324import Unsafe.Coerce (unsafeCoerce)
2425
@@ -70,6 +71,43 @@ instance toResponseRLBodyHeaders ::
7071else instance toResponseRLBodyOnly ::
7172 ToResponseRL (RL.Cons "body" body RL.Nil) () body
7273
74+-- Invalid record structure: has fields other than "body" and "headers"
75+else instance toResponseRLInvalid ::
76+ ( Fail
77+ ( Above
78+ (Text "Invalid response record structure.")
79+ ( Above
80+ (Text "")
81+ ( Above
82+ (Text "Response records must contain ONLY:")
83+ ( Above
84+ (Text " • body :: YourBodyType (required)")
85+ ( Above
86+ (Text " • headers :: Record (...) (optional)")
87+ ( Above
88+ (Text "")
89+ ( Above
90+ (Text "Valid examples:")
91+ ( Above
92+ (Text " { body: user }")
93+ ( Above
94+ (Text " { body: user, headers: { \"Location\": \"/users/123\" } }")
95+ ( Above
96+ (Text "")
97+ (Text "Do not include 'status', 'statusCode', or other fields.")
98+ )
99+ )
100+ )
101+ )
102+ )
103+ )
104+ )
105+ )
106+ )
107+ )
108+ ) =>
109+ ToResponseRL rl headers body
110+
73111--------------------------------------------------------------------------------
74112-- Response Construction Helpers
75113--------------------------------------------------------------------------------
src/Yoga/HTTP/API/Route/StatusCode.purs+2
@@ -9,6 +9,7 @@ import Prelude
99
1010import Type.Proxy (Proxy(..))
1111import Data.Newtype (class Newtype)
12+import Prim.TypeError (class Fail, Text, Beside, Above, Quote)
1213
1314newtype StatusCode = StatusCode Int
1415
@@ -225,6 +226,7 @@ instance StatusCodeMap "notExtended" where
225226instance StatusCodeMap "networkAuthenticationRequired" where
226227 statusCodeFor _ = StatusCode 511
227228
229+
228230--------------------------------------------------------------------------------
229231-- Helper Functions
230232--------------------------------------------------------------------------------