If you are a Wasp user and not a contributor (yet :)), you might want to look into following resources instead ([**Project page**](https://wasp-lang.dev), [**Docs**](https://wasp-lang.dev/docs)).
If you would like to make your first contribution, here is a handy checklist we made for you:
- [ ] Read [Quick overview](#quick-overview).
- [ ] Compile the project successfully and get todoApp example running (follow [Basics](#basics)).
- [ ] Join [Discord](https://discord.gg/rzdnErX) and say hi :)!
- [ ] Pick an issue [labeled with "good first issue"](https://github.com/wasp-lang/wasp/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) and let us know you would like to work on it - ideally immediatelly propose a plan of action and ask questions.
If you can't find a suitable issue for you, reach out to us on Discord and we can try to find smth for you together.
- [ ] Make a PR and have it accepted! Check [Typical workflow](#typical-development-workflow) for guidance, and consult [Codebase overview](#codebase-overview) for more details on how Wasp compiler works internally.
## Quick overview
Wasp compiler is implemented in Haskell, but you will also see a lot of Javascript and other web technologies because Wasp compiler transpiles Wasp code into them.
You don't have to be expert in Haskell to contribute or understand the code, since we don't use complicated Haskell features much -> most of the code is relatively simple and straight-forward, and we are happy to help with the part that is not.
Main result of building the project is `wasp` executable (also reffered to as CLI), which is both Wasp compiler, CLI and Wasp project runner in one - one tool for everything Wasp-related.
`wasp` executable takes `.wasp` files and `ext/` dir as input and generates a web app from them.
![Wasp compilation](images/wasp-diagram.png)
It can then also run that web app for you, deploy it (not yet but that is coming), and manage it in other ways.
## Basics
### Setup
We use [Stack](https://docs.haskellstack.org/en/stable/README/) for building the project, so you will need to install `stack` on your machine.
### Repo
Fork this repo and clone the fork to your machine (or clone this repo directly if you don't plan to contribute but just want to try it out).
Position yourself in this directory (`waspc/`) and make sure that you are on the `master` branch.
`NOTE:` For macOS Big Sur users there is a bug in older GHC versions (<= 8.10.3) causing system frameworks to load improperly and will fail when building the project. This can be fixed with the following steps:
<details>
<summary>Show details</summary>
1. Clean up stack cache which could have been carried over from previous OS versions using below command.
```
rm -Rf ~/.stack/setup-exe-cache/x86_64-osx
```
2. Run `stack build` until it fails with error `can't load framework: Cocoa (not found)`.
3. Checkout and build this [workaround](https://github.com/yairchu/macos11-haskell-workaround).
4. Re-run stack build with workaround using below command and it should build without errors.
5. If needed, confirm that `examples/todoApp/` is working correctly by running `stack build` first, to build the wasp executable, and then by running that executable with `stack exec wasp start` from the `examples/todoApp/` dir -> this will run the web app in development mode with the current version of your Wasp code.
Manually inspect that app behaves ok: In the future we will add automatic integration tests, but for now testing is manual.
7. If your PR changes how users(Waspers) use Wasp, make sure to also create a PR that will update the documentation, which is in a [separate repo](https://wasp-lang.dev/docs/tutorials/getting-started).
Generated web app consists of client, server and database.
Client is written with React and react-query.
Server is written in NodeJS and uses ExpressJs.
Database is abstracted via Prisma.
We can run Wasp project with `wasp start`.
This will first compile the app, generate JS code in the `.wasp/out/` dir, and then run `npm start` for the client, `npm start` for the server, and also run the database.
On any changes you do to the source code of Wasp, Wasp project gets recompiled, and then changes in the generated code are picked up by the `npm start` of the client/server, therefore updating the web app.
## Important directories (in waspc/)
- src/ -> main source code, library
- cli/ -> rest of the source code, cli, uses library
- test/ -> tests
- data/Generator/templates/ -> mustache templates for the generated client/server.
- examples/ -> example apps
## Building / development (detailed)
Some useful stack commands:
-`stack build` to build the project, including `wasp` binary which is both CLI and compiler in one.
-`stack exec wasp <arguments>` to run the `wasp` binary that you have built.
-`stack test` to build the whole project + tests and then also run tests.
-`stack build --file-watch` -> live watch, reruns every time a file changes. But we prefer using `ghcid`, it is faster.
You can install it globally with `stack install ghcid` and then just type `ghcid --command=stack ghci` when in the project -> it will watch for any file changes and report errors.
For tests we are using [**Tasty**](https://documentup.com/feuerbach/tasty) testing framework. Tasty let's us combine different types of tests into a single test suite.
In Tasty, there is a main test file that is run when test suite is run. In that file we need to manually compose test tree out of tests that we wrote. We organize tests in test groups, which are then recursively grouped resulting in a test tree.
Tests are normally split in files of course, so we need to import those all the way up to the main test file, however we organize our test groups/trees.
In order to avoid need for manual organization and importing of test files described above, we are using [tasty-discover](https://hackage.haskell.org/package/tasty-discover) which does this for us.
It automatically detects files containing tests and organizes them for us into a test tree (and also takes care of importing).
This means we only need to create a file, write tests in it and that is it.
Test functions however do need to be prefixed with special prefix to indicate which type of test are they: spec_ for Hspec, prop_ for QuickCheck and similar.
We can however still organize tests manually if we want in Tasty test trees, and then we just prefix them with test_ and tasty-discover will pick them up from there.
This is convention for Haskell, opposite to mixing them with source code as in Javascript for example.
Not only that, but Haskell build tools don't have a good support for mixing them with source files, so even if we wanted to do that it is just not worth the hassle.
If using Hlint as a linter, be aware that Hlint doesn't know which default extensions are we using via Stack/cabal, so it might be missing some extension and therefore report false errors.
Hlint already adds a lot of extensions on its own so this is not a very often problem, but if that happens, add default extensions to .hlint.yaml so that Hlint knows to use them.