https://github.com/robertdp/purescript-apiary
For the creation of type-level specs that can be queried against automatically. For full-stack specs, see https://github.com/robertdp/purescript-apiary-server
https://github.com/robertdp/purescript-apiary
Last synced: about 1 year ago
JSON representation
For the creation of type-level specs that can be queried against automatically. For full-stack specs, see https://github.com/robertdp/purescript-apiary-server
- Host: GitHub
- URL: https://github.com/robertdp/purescript-apiary
- Owner: robertdp
- Created: 2019-10-29T05:14:41.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2022-12-10T07:09:09.000Z (over 3 years ago)
- Last Synced: 2025-06-07T06:34:24.913Z (about 1 year ago)
- Language: PureScript
- Homepage:
- Size: 153 KB
- Stars: 17
- Watchers: 1
- Forks: 2
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
_ _
/ \ _ __ (_) __ _ _ __ _ _ .' '. __
/ _ \ | '_ \| |/ _` | '__| | | | . . . (__\_
/ ___ \| |_) | | (_| | | | |_| | . . . -{{_(|8)
/_/ \_\ .__/|_|\__,_|_| \__, | ' . . ' ' . . ' (__/
|_| |___/
It's hard to be a busy little bee when working with unspec'ed APIs. This library is designed for the creation of type-level specs that can be queried against automatically!
### Example
```purescript
type User
= { id :: Int
, name :: String
, email :: String
}
type ListUsers
= GET "/users"
{ query ::
{ sortBy :: UserSort
, sortDir :: SortDir
}
, response ::
{ ok :: JSON (Array User)
}
}
type CreateNewUser
= POST "/users"
{ body :: JSON { name :: String, email :: String }
, response ::
{ ok :: JSON User
, badRequest :: JSON { errors :: Array { field :: String, message :: String } }
}
}
listUsers params =
Apiary.makeRequest (Route :: ListUsers) identity params none
createNewUser body =
Apiary.makeRequest (Route :: CreateNewUser) identity none body
```
This will give us inferred types equivalent to
```purescript
listUsers ::
{ sortBy :: Maybe UserSort, sortDir :: Maybe SortDir } ->
Aff (Either Apiary.Error (Variant ( ok :: Array User )))
createNewUser ::
{ name :: String, email :: String } ->
Aff
(Either Apiary.Error
(Variant
( ok :: User
, badRequest :: { errors :: Array { field :: String, message :: String } }
)
)
)
```
Here is an example with URL modification and JWT-based authorisation inspired by some production code:
```purescript
makeSecureRequest ::
forall m r route params body rep response.
MonadAff m =>
MonadAsk { baseUrl :: String, token :: String | r } m =>
Apiary.BuildRequest route params body rep =>
Apiary.DecodeResponse rep response =>
route ->
params ->
body ->
m (Either Apiary.Error response)
makeSecureRequest route params body = do
env <- ask
liftAff $ mkRequest (addBaseUrl env.baseUrl <<< addToken env.token)
where
mkRequest modify =
Apiary.makeRequest route modify params body
addToken token request@{ headers } =
request { headers = Object.insert "Authorization" ("Bearer " <> token) headers }
addBaseUrl baseUrl request@{ url: URL url } =
request { url = URL (baseUrl <> url) }
type AppM = ReaderT { baseUrl :: String, token :: String } Aff
listUsers ::
{ sortBy :: Maybe UserSort, sortDir :: Maybe SortDir } ->
AppM (Either Apiary.Error (Variant ( ok :: Array User )))
listUsers params =
makeSecureRequest (Route :: ListUsers) params unit
```