✨ A boilerplate for writing beautiful async-await
-based Koa API's using babel
for Node v8.0 and above!. 🚀
Clone this repo and adjust details in package.json
. Remove the .git
directory and git init
to start fresh.
Read on to learn how to actually start being productive.
- 🏃♀️
npm run
scripts, see next section for details. - 🛣
awilix-koa
for declarative routing. - 🗣
babel
withenv
presets,transform-runtime
+transform-object-rest-spread
plugins and sourcemaps. - 🃏
jest
for testing with some API testing helpers. - 💪
koa-bodyparser
for parsing request bodies. - ✅
eslint
with standard, works with ES7 thanks tobabel-eslint
. - 👀
prettier
code formatting, configured to work witheslint
out of the box. - 🐶
husky
+lint-staged
to lint and format files when committing. - ❌
@koa/cors
CORS middleware for cross-domain requests. - 🕵️♀️
nodemon
for development to auto-restart when your files change. - 🛠
koa-respond
for helper functions on the context. - 📄
yenv
+keyblade
for environment variable management. - 💉
awilix
for dependency injection / IoC. ⚠️ fejl
for assertions and errors.
There are a few defined run scripts, here's a list of them with a description of what they do. To run them, simply execute npm run <script name>
- e.g. npm run dev
start
: Used by the production environment to start the app. This will run a compiled version, so you need to executebuild
first.build
: Runs thebabel
CLI to compile the app. Files are emitted todist/
.dev
: Runs the app in development mode - usesbabel-node
to compile on-the-fly. Also usesnodemon
to automatically restart when stuff changes.test
: Runs tests.cover
: Runs tests and collects coverage.lint
: Lints + formats the code.
Tip: to pass additional arguments to the actual CLI's being called, do it like in this example:
For npm:
# Note the `--` before the actual arguments.
npm run test -- --debug
For yarn:
# Yarn does not need the `--` before the actual arguments.
yarn test --debug
The repository root contains auxiliary files like package.json
, .gitignore
, etc.
src
: the actual source for the app goes here. Duh.__tests__
: In the source root folder, contains integration tests.routes
: API endpoints go here, and are automatically loaded at startup. Please see the section about API endpoints for details.bin
: files that are usually executed bynpm run
scripts, e.g. starting the server.lib
: stuff that helps the app start up, e.g. environment, logger, the container configuration, etc.middleware
: custom app middleware.services
: application services, this is just to illustrate the dynamic discovery of stuff as described in the Dependency injection section.__tests__
: Unit tests for files in theservices
directory.
[your directory]
: you can plop anything else here, too.__tests__
: Unit tests for files in your directory.
To recap the previous section, src/__tests__
are for integration tests, and any __tests__
folder under src/<folder>
are unit tests.
Test files must end with .test.js
.
There is a src/__tests__/api-helper.js
that makes writing integration tests way easier. Simply replace the example functions with ones matching your own API. The created server instance is closed whenever all tests are done as to not leak resources. This is why it's important to close network connections in the close
event!
The environment variables can be reached by importing lib/env
.
import { env } from '../lib/env'
Additionally, all environment variables you'd usually find on process.env
will be available on this object.
When attempting to access a key (env.PORT
for example), if the key does not exist an error is thrown and the process terminated. See keyblade for more info.
In the repository root, you will find a env.yaml
, which is where you can set up environment variables so you won't have to do it from your shell. This also makes it more platform-agnostic.
The top-level nodes in the YAML-file contain a set of environment variables.
yenv
will load the set that matches whatever NODE_ENV
says.
I've set it up so anything in tests
will override anything in development
when running tests.
Actual environment variables will take precedence over the env.yaml
file!
See the yenv
docs for more info.
Each file in /routes
exports a default function that takes the router as the first parameter. That function registers API endpoints.
This boilerplate uses the Awilix
container for managing dependencies - please check out the Awilix documentation
for details. The container is configured in lib/container.js
.
Middleware is located in the middleware
folder and is not automatically loaded - they should be installed in lib/server
.
- Jeff Hansen - @Jeffijoe
MIT.