IMLaoJI / realworld-scotty-hs

An implementation of the RealWorld API spec w/ Haskell + Scotty

Home Page:https://realworld.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RealWorld Example App

Haskell codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.

This codebase was created to demonstrate a fully fledged fullstack application built with Haskell/Scotty including CRUD operations, authentication, routing, pagination, and more.

We've gone to great lengths to adhere to the Haskell/Scotty community styleguides & best practices.

For more information on how to this works with other frontends/backends, head over to the RealWorld repo.

How it works

Basic architectural overview

Since this is small application (only ~2k actual LOC), I've opted for a very vertical-slice-esque architecture, with each endpoint getting its own file, and with common logic simply going in its own files. Controllers, services, and data access are of course still decoupled through MTL style classes (inspired by three-layer-cake), making testing extremely simple. I believe the general architecture should be quite self explanitory and easy to refactor as the app scales. I will admit it is slightly influenced by Haskell's dissallowance of circular imports, esp. as I didn't want to deal with hs-boot files.

Feel free to let me know your thoughts, or open an issue!

View more fine-grained documentation here.

File-structure overview

app/                      # The entrypoint into the application.
  Main.hs                 # Very thin, just deals with configuration.

sqlbits/                  # Some sql files w/ triggers/functions
                          # which are embedded directly within
                          # the haskell files via TemplateHaskell.

src/                      # The actual source code for Conduit.

  Conduit/App/            # This folder deals with the App Monad,
                          # which holds the server's global state.

  Conduit/DB/             # Holds some DB-related utilities and
                          # code for decoupling/abstraction purposes.
                          # Also holds some DB initializtion code.

  Conduit/Features/       # Contains the bulk of the Conduit logic,
                          # including the API endpoints/services/DB
                          # access logic.
                          # Also holds feature-related DB/error logic.

  Conduit/Identity/       # Holds the code for the JWT-based auth.
                          # uses argon2 for pw hashing.

  Validation.hs           # Some utilities for basic validation
                          # of incoming data.

static/                   # Holds the static files where the avatar
                          # images reside. The images are actually just
                          # blank files for now but it's fiiine.

test/                     # Contains the unit tests made w/ hspec,
                          # currently only have tests for auth and
                          # slug-building since cypress covers the rest.

package.yaml              # Describes the project and its dependencies.
realworld-hs.cabal        # hpack generates the .cabal file from the
                          # package.yaml which, IMO, is much nicer
                          # to work with.

conduit-schema.json       # The configuration files for conduit itself. 
conduit.json              # The schema file for your convenience.

Noteworthy dependencies

(Not including common dependencies such as mtl and aeson)

Getting started

This project requires Cabal & a running Postgres instance. Here're a couple links of that may help you out:

To begin, of course, clone the repo and cd into it:

git clone https://github.com/toptobes/realworld-scotty-hs.git && cd realworld-scotty-hs
# or
gh repo clone toptobes/realworld-scotty-hs && cd realworld-scotty-hs

From there, update the appropriate configs in conduit.json

  • It's already set with sensible defaults; be sure to double-check the postgres connection string
  • there is a conduit-schema.json for your convenience as well that provides extra info
  • If necessary, you can set the CONDUIT_CONFIG env var to to some custom config path

Then, you can start the app via cabal run app, or run the unit tests w/ cabal run spec.

It may take a while the first time while it obtains/builds the relevant dependencies.

If you plan to make any modifications involving creating new files or adding new dependencies, you may need hpack.

  • You could update the realworld-hs.cabal file manually if you really wanted or needed to though
  • Otherwise, just run the hpack command whenever you modify package.yaml

Further documentation

You can create the documentation site for this project using cabal haddock, and then access it w/ npx serve or whatever else you fancy. Nearly everything except for the features are decently documented, and I'll work on adding more soon.

Or just read through the code manually if you prefer, whatever you want lol.

About

An implementation of the RealWorld API spec w/ Haskell + Scotty

https://realworld.io

License:MIT License


Languages

Language:Haskell 98.3%Language:PLpgSQL 1.7%