Skip to content

Commit 0302e29

Browse files
add an affjax POST recipe (#259)
* add an affjax POST recipe * Clean up some links and minor typos Co-authored-by: JordanMartinez <[email protected]>
1 parent ac573b7 commit 0302e29

File tree

7 files changed

+106
-1
lines changed

7 files changed

+106
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Running a web-compatible recipe:
8888
| | :heavy_check_mark: ([try](https://try.ps.ai/?github=JordanMartinez/purescript-cookbook/master/recipes/AceEditorHalogenHooks/src/Main.purs) - [fixme](recipes/AceEditorHalogenHooks/tryFixMe.md)) | [AceEditorHalogenHooks](recipes/AceEditorHalogenHooks) | A Halogen Hooks port of the ["Ace Editor" Halogen Example](https://github.com/purescript-halogen/purescript-halogen/tree/master/examples/ace). |
8989
| | :heavy_check_mark: ([try](https://try.ps.ai/?github=JordanMartinez/purescript-cookbook/master/recipes/AddRemoveEventListenerJs/src/Main.purs) - [fixme](recipes/AddRemoveEventListenerJs/tryFixMe.md)) | [AddRemoveEventListenerJs](recipes/AddRemoveEventListenerJs) | This recipe shows how to add and remove an event listener to an HTML element. |
9090
| | :heavy_check_mark: ([try](https://try.ps.ai/?github=JordanMartinez/purescript-cookbook/master/recipes/AffGameSnakeJs/src/Main.purs) - [fixme](recipes/AffGameSnakeJs/tryFixMe.md)) | [AffGameSnakeJs](recipes/AffGameSnakeJs) | A snake game built using [AffGame](https://pursuit.purescript.org/packages/purescript-game/2.0.0). |
91+
| :heavy_check_mark: | | [AffjaxPostNode](recipes/AffjaxPostNode) | Performs a simple HTTP Post request using the [Affjax](https://pursuit.purescript.org/packages/purescript-affjax/) library. |
9192
| | :heavy_check_mark: ([try](https://try.ps.ai/?github=JordanMartinez/purescript-cookbook/master/recipes/BasicHalogenHooks/src/Main.purs)) | [BasicHalogenHooks](recipes/BasicHalogenHooks) | Displays a button that toggles the label to "On" and "Off". |
9293
| | :heavy_check_mark: ([try](https://try.ps.ai/?github=JordanMartinez/purescript-cookbook/master/recipes/BehaviorSuperCircleJs/src/Main.purs)) | [BehaviorSuperCircleJs](recipes/BehaviorSuperCircleJs) | A simplified Super Hexagon clone written with [behaviors](https://pursuit.purescript.org/packages/purescript-behaviors). |
9394
| :heavy_check_mark: | :heavy_check_mark: ([try](https://try.ps.ai/?github=JordanMartinez/purescript-cookbook/master/recipes/BigIntJs/src/Main.purs)) | [BigIntJs](recipes/BigIntJs) | This recipe shows how to print, create, and use values of the `BigIntJs` type in either the node.js or web browser console. |

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"ace-builds": "^1.4.11",
1010
"big-integer": "^1.6.48",
1111
"react": "^16.13.1",
12-
"react-dom": "^16.13.1"
12+
"react-dom": "^16.13.1",
13+
"xhr2": "^0.2.0"
1314
}
1415
}

recipes/AffjaxPostNode/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/bower_components/
2+
/node_modules/
3+
/.pulp-cache/
4+
/output/
5+
/generated-docs/
6+
/.psc-package/
7+
/.psc*
8+
/.purs*
9+
/.psa*
10+
/.spago
11+
/web-dist/
12+
/prod-dist/
13+
/prod/

recipes/AffjaxPostNode/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# AffjaxPostNode
2+
3+
Performs a simple HTTP Post request using the [Affjax](https://pursuit.purescript.org/packages/purescript-affjax/) library.
4+
5+
The Post data that is sent with the request makes use of the PureScript
6+
[Argonaut](https://github.com/purescript-contrib/purescript-argonaut) library
7+
to reduce the boilerplate needed to serialize and de-serialize the JSON.
8+
9+
See [Thoughts on Typeclass Codecs (blog post)](https://code.slipthrough.net/2018/03/13/thoughts-on-typeclass-codecs/) for pros
10+
and cons of this approach to encodings.
11+
12+
NB: this recipe depends upon the continuing availability of the dummy JSON provider "http://jsonplaceholder.typicode.com/posts"
13+
14+
## Expected Behavior:
15+
16+
Prints to the console:
17+
18+
```
19+
POST http://jsonplaceholder.typicode.com/posts response: {"userId":22,"title":"title","id":101,"body":"body"}
20+
>>> (Right { body: "body", id: (Just 101), title: "title", userId: 22 })
21+
```
22+
23+
## Dependencies used
24+
25+
When used in Node.js this code depends up on [xhr2](https://www.npmjs.com/package/xhr2)
26+
27+
This recipe is only implemented for Node.js as of this initial commit but it can be made run in the browser instead and no `xhr2` dependency would apply in that case.
28+
29+
### Node.js
30+
31+
Prints the contents of this repo's LICENSE file. Note that this recipe is run from the repo's root directory.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This file just indicates that the node backend is supported.
2+
It is used for CI and autogeneration purposes.

recipes/AffjaxPostNode/spago.dhall

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{ name = "AffjaxPostNode"
2+
, dependencies =
3+
[ "affjax", "argonaut", "console", "effect", "node-fs-aff", "psci-support" ]
4+
, packages = ../../packages.dhall
5+
, sources = [ "recipes/AffjaxPostNode/src/**/*.purs" ]
6+
}

recipes/AffjaxPostNode/src/Main.purs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
module AffjaxPostNode.Main where
2+
3+
import Data.Argonaut
4+
5+
import Affjax as AX
6+
import Affjax.RequestBody (json)
7+
import Affjax.ResponseFormat as ResponseFormat
8+
import Data.Argonaut as J
9+
import Data.Either (Either(..))
10+
import Data.Maybe (Maybe(..))
11+
import Effect (Effect)
12+
import Effect.Aff (launchAff_)
13+
import Effect.Class.Console (log)
14+
import Prelude (Unit, bind, show, ($), (<>))
15+
16+
-- expected response: (at least if `http://jsonplaceholder.typicode.com/posts` is available to you)
17+
-- POST http://jsonplaceholder.typicode.com/posts response: (Right { body: "body", id: (Just 101), title: "title", userId: 22 })
18+
19+
type Post = { id :: Maybe Int
20+
, title :: String
21+
, body :: String
22+
, userId :: Int
23+
}
24+
25+
postToJson :: Post -> Json
26+
postToJson = encodeJson
27+
28+
jsonToPost :: Json -> Either JsonDecodeError Post
29+
jsonToPost = decodeJson
30+
31+
main :: Effect Unit
32+
main = launchAff_ $ do
33+
let
34+
postdata :: Post
35+
postdata = { id : Nothing -- note how this returns filled-in if service works
36+
, title : "title"
37+
, body : "body"
38+
, userId: 22 }
39+
40+
endpoint :: String
41+
endpoint = "http://jsonplaceholder.typicode.com/posts"
42+
43+
result <- AX.post ResponseFormat.json endpoint (Just $ json $ postToJson postdata)
44+
case result of
45+
46+
Left err ->
47+
log $ "POST " <> endpoint <> " response failed to decode: " <> AX.printError err
48+
49+
Right response -> do
50+
log $ "POST " <> endpoint <> " response: " <> J.stringify response.body
51+
<> "\n>>> " <> show (jsonToPost response.body)

0 commit comments

Comments
 (0)