This is a monorepo template built using TurboRepo. Under the hood we have Fastify Service which is running with a Postgres instance.
The monorepo works on K8s for local development and also is deployable on K8s and is fully cloudnative follow the guides below for quick and easy setup.
No code is a bad code. The code you start with is always good code because you and your team (even if you're the only team 🙃) agreed upon it. What we have in this repository is also good code. Well not exactly good, but in our opinion good code.
Good code because it follows what we wanted it to follow. Then what is bad code? No code repository becomes bad code repository in a day or two. It becomes bad/unmaintainable/unscalable/sluggish with time. Call it whatever you want bad code is easily recognizable. And it falls down to you to fix and then maintain it.
There are several things in this repository that help catch what a human eye might miss. Linters, Type Checkers, Editor configurations, pre-commit hooks, and much more. But they can be avoided because they are bypassable. And that is exactly what makes the good code bad.
So rules to live by:
- Linter is your friend NOT your enemy; don't bypass it (feel free to change the initial rules)
- Follow the code style that you decide upon (establish it with your team)
- Use comments to let the other devs know what the code does
- Don't bypass the pre-commit hooks, it starts as "just this one time" and becomes a "let's do it who cares"
- Write tests that actually test the logic that you're trying to implement, make sure to write tests first and then write logic accordingly
The following are the technology that this template utilizes.
The template is a monorepo where the main applications are in the /apps
directory.
Aside that we also have several packages
that we store in the packages
directory that provided shared config and code.
We use dotenv-cli
to pass the environment
files based on what NODE_ENV
we wanna use. The monorepo utilizes K8s for development too, please refer the developer's guide to know more.
We use Jest
test-runner for testing out the application.
The alpha
application has both Unit tests
and Integration tests
done. We'd suggest you to have a look at how they are implemented and feel free to augment them to your liking.
For running unit tests across all your applications the following need to be done. Do note Turbo and Jest are already hooked up for Unit and Integration testing across all the application(s) present in the apps
directory.
However the TurboRepo pipeline specified in turbo.json
requires you to have same names across the applications only then your application would be included in the pipeline.
You can create Jest patterns by specifying a jest.config.js
file in your application and change your config as you wish. However for testing create an npm script with the name test:unit
and this will automatically hook it in your TurboRepo pipeline. And then just run pnpm run test:unit
from the root directory. That will automatically run all the unit tests across each of your applications.
Steps for reference
- Create a
jest.config.js
file at the base directory of your application. - Extend the common
jest.config.js
by importing it injest.config.js
by doingrequire('../../jest.config.js')
- Define your unit test patterns and write a bunch of unit tests.
- Create an npm script with the following name
test:unit
and it should execute unit testing. - Do
pnpm run test:unit
at your root directory and watch your unit tests run!
We also support Integration tests. To be honest Integration testing simply means that you just normally run your application in a test environment. The test runner provides you with features to handle opening and closing your application. For testing the backend we run our integration tests against a real database and a redis instance both of which will be running inside their own docker containers.
The process of creating integration tests is quite similar to how we created Unit tests above. However there is a subtle catch. For testing be it Unit or Integration testing we generally create setup file(s) that help us do stuff after, before, or in between with any logic we want. Maybe you wanna create your database instance before you even start testing! In such a case prefer using Jest CLI flags to pass the setupFilesAfterEnv
with the file path you wanna initialize.
This has been done in the alpha
service which shows a good example of how to use different support files based upon if we're running unit tests or integration tests.
We have a bash script and a docker-compose
that will automatically spin up a postgres and a redis instance (you require docker
and docker-compose
). The postgres and the redis instance also define their required envs in docker-compose.yml
itself.
You can start the postgres and redis instance on docker using:
pnpm start:svc
For teardown you can use:
pnpm stop:svc
IMPORTANT - Don't forget to close your connection to your database in your setup file in the afterAll
block or this will leave it hanging and jest will report for open handles.
- Create your
setup-jest
file depending upon if you're using TypeScript or JavaScript
- Setup
beforeAll
andafterAll
logic in this file - Its a good idea to connect to your
db
here and close connection to it in theafterAll
block - You can also clear your database in the
beforeEach
block which will run before each and every test
- Create integration tests directory and write integration tests
- Create an npm script with the following name
test:integration
and it should execute integration tests.
- PS: You can use
testPathPattern
CLI flag to specify in which directory your integration tests reside in
- Do
pnpm run test:integration
at your root directory and watch your integration tests run!
Development scripts are there to you help you out with a bunch of stuff. Few are listed below!
Purpose | Script |
---|---|
Install dependencies | pnpm i |
Start development server | pnpm start:dev |
Create and run qa build | pnpm start:qa |
Create and run prod build | pnpm start:prod |