Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/haskell-to-elm/servant-to-elm-example
Full-stack web app, built in a typesafe functional way, where servant-to-elm generates types, decoders/encoders, and fetching functions from Haskell types and Servant endpoint definition to Elm.🤘🏻
https://github.com/haskell-to-elm/servant-to-elm-example
codegen codegeneration elm-lang elm-language functional-programming generic-types haskell haskell-application http-client http-server servant typesafe
Last synced: 25 days ago
JSON representation
Full-stack web app, built in a typesafe functional way, where servant-to-elm generates types, decoders/encoders, and fetching functions from Haskell types and Servant endpoint definition to Elm.🤘🏻
- Host: GitHub
- URL: https://github.com/haskell-to-elm/servant-to-elm-example
- Owner: haskell-to-elm
- Created: 2021-01-06T02:12:47.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-05-22T01:59:23.000Z (6 months ago)
- Last Synced: 2024-05-23T01:27:43.888Z (6 months ago)
- Topics: codegen, codegeneration, elm-lang, elm-language, functional-programming, generic-types, haskell, haskell-application, http-client, http-server, servant, typesafe
- Language: Elm
- Homepage:
- Size: 776 KB
- Stars: 12
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# servant-to-elm-example
![build status](https://github.com/haskell-to-elm/servant-to-elm-example/actions/workflows/build.yml/badge.svg)
This example is a full-stack web application, built in a typesafe functional way.
What's cool here is that [servant-to-elm] does the job of generating types and decoders/encoders from Haskell types and [Servant] definition to Elm, which not only catches regressions in the compile-time but also provides ready (and highly configurable) Elm functions to fetch necessary data from the server.
## Prepare
- Install [Stack] and [Elm]
- Run code generation
```sh
cd backend && stack run codegen
```
- Install frontend dependencies
```sh
cd frontend && npm i
```### Set up editor (optional)
- If you are using VSCode and you want to open both frontend and backend as a single workspace, use `File > Open Workspace` and choose `servant-to-elm-example.code-workspace`. In this scenario, VSCode will work correctly with both languages simultaneously. Also, the editor may recommend extensions, and installing them is a wise choice.
## Run
- Start the server on port 8000:
```sh
cd backend && stack run server
```
- Run frontend in dev mode
```sh
cd frontend && npm start
```
- Open http://localhost:8080## Domain model: Library
- A book can have exactly 1 author
- An author can have zero to many books
- Book title must be unique per author
- The author's name must be unique## This example does demonstrate:
- [x] How to fetch data and handle errors and "loading" state
- [x] How to post a new entity related to another, either new or existing one (submit a book with a new or existing author)## This example does not demonstrate:
- User input ~~validation~~ parsing best practices
- Client-side routing best practices
- Debouncing user input
- Client-side validation before submitting a form
- Subscriptions via WebSockets (which could be implemented, but they are related more to Servant or Elm, rather than to code-generation)### Other choices
- New entries that are in relation are submitted together and inserted transactionally.
- Search is case-insensitive## Technical notes
- This app was not tested on Windows systems yet. While is not a showcase of cross-platform compatibility, you can still open an issue or PR if something does not work as expected.
### Adding new types
- in `backend/src/DomainModel.hs`:
- Define the type
- Derive necessary instances, also specify Elm module name and Elm type (it's better to keep type name the same, but it's convenient to use one module for several coupled types - see `Book`, `NewBook`, and `NewBookAuthor` types and corresponding generated Elm module)
- Add the type to `typeDefinitions` list - `jsonDefinitions @YourNewType`
- Use your type in `backend/src/Server.hs` or wherever it's intended to
- Run code-generation again### Design choices and alternatives
- An obsolete generated Elm code can be removed before writing the new ones. Subdirectories that must be deleted are listed in `backend/src/Codegen.hs`. In this example, only the `frontend/src/Api` directory is removed before writing new files.
- One of the alternatives to this approach is GraphQL, and there is a [Haskell/Elm full-stack GraphQL example app](https://github.com/higherkindness/mu-graphql-example-elm). This example app was shamelessly inspired by that example.[stack]: https://docs.haskellstack.org/en/stable/README/#how-to-install
[elm]: https://guide.elm-lang.org/install/elm.html
[servant]: https://www.servant.dev/
[servant-to-elm]: https://github.com/haskell-to-elm/servant-to-elm