Clean install
This page provides a Step by step
guide to creating a clean Enso project.
You can also use the quickstart to achieve the same goal.
- Install packages
- Setup TypeScript
- Prepare the directory structure
- Setup a HTTP server
- Setup your environment
- Setup a container
- Utilse debugging
Step by step
Install packages
Create a new directory and initialise the project. Then install the following package dependencies.
# init new project
yarn init
# add deps
yarn add @ensojs/framework typescript ts-node tslint-config-standard dotenv-safe @types/node
Setup TypeScript
Configure the typescript compiler
In the project root vi tsconfig.json
.
{
"compilerOptions": {
"module": "commonjs",
"alwaysStrict": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "es6",
"lib": [
"es6",
"es7"
]
},
"exclude": [
"node_modules"
]
}
Configure the linter
In the project root vi tslint.json
. Enso adopts the Standard JS style.
{
"extends": [
"tslint-config-standard"
]
}
Prepare the directory structure
mkdir -p src/config
Setup a HTTP server
Note
A
HTTPServer
is a thin abstraction around the excellentkoa
library
src/App.ts
// src/App.ts
import { HTTPServer } from '@ensojs/framework'
export class App extends HTTPServer {
applyMiddleware (): void {}
}
src/server.ts
This manages an instance of your App.
// src/server.ts
import 'reflect-metadata'
import { App } from './App'
import { env } from './config/env'
import { container } from './config/container'
const debug = require('debug')('server')
const server = async () => {
try {
debug('============================================')
debug('> Starting server...')
debug('============================================')
const app = new App(env)
await app.build(container)
await app.start()
debug('')
debug('✔ [nodejs] %s', process.version)
debug('')
debug(
'✔ API server listening on port %d in [%s] mode',
env.PORT,
env.ENVIRONMENT
)
} catch (e) {
debug(e)
process.exit(1)
}
}
// start
server()
If at this point we attempt to start the server, we will see some errors given we are yet to define an environment
and a container
.
# Attempt to start server
ts-node src/server.ts
Setup your environment
Enso uses dotenv-safe. Your must have an ENVIRONMENT
and PORT
defined.
src/.env.example
# file: src/.env.example
#=========================================
# Settings
#=========================================
ENVIRONMENT="development"
PORT=5000
Then copy the settings locally and fill in the relevant values.
cp src/.env.example src/.env
Important
Remember to not commit your “.env” to your repository and add it to your “.gitignore” file
src/config/env.ts
Let’s explicitly bind our environment to an interface.
import dotenv from 'dotenv-safe'
import { IEnvironmentConfig } from '@ensojs/framework'
dotenv.config({
allowEmptyValues: false
})
export const env: IEnvironmentConfig = {
ENVIRONMENT: process.env.ENVIRONMENT!,
PORT: parseInt(process.env.PORT!)
}
Setup a container
Eventually our controllers and other services will be registered here.
src/config/container.ts
import { Container } from 'inversify'
export const container = new Container()
Utilse debugging
The debug package heavily used within the NodeJS ecosystem. Take some time to learn it.
# Attempt to start server again...
ts-node src/server.ts
There are now no error messages, however there are still some issues that need to be fixed.
Append the DEBUG=*
flag when starting the server to investigate further.
# Start the server with debug
DEBUG=* ts-node src/server.ts
From the messages we can see that we are missing a controller which brings us to the next step.
Info
Currently the inversify bridge Enso depends on requires a controller to be setup inversify-koa. We aim to resolve this in the future.
So for now…
Continue setup with an IndexController
Our controller will respond with its package name and version number.
src/IndexController.ts
// file: src/IndexController.ts
import { injectable } from 'inversify'
import { interfaces, controller, httpGet } from 'inversify-koa'
import Router from 'koa-router'
import pkg from '../package.json'
@injectable()
@controller('/')
export class IndexController implements interfaces.Controller {
/**
* GET /
*/
@httpGet('')
async getIndex (ctx: Router.IRouterContext) {
ctx.status = 200
ctx.body = {
name: pkg.name,
version: pkg.version,
env: process.env.NODE_ENV,
up: process.uptime(),
message: 'ok'
}
}
}
Edit the container file and register our IndexController
.
// file: src/config/container.ts
import { Container } from 'inversify'
import { interfaces } from 'inversify-koa'import { TYPE } from '@ensojs/framework'import { IndexController } from '../IndexController'
export const container = new Container()
// controllerscontainer.bind<interfaces.Controller>(TYPE.Controller).to(IndexController).whenTargetNamed('IndexController')
Now our server should be up and running.
# start the server
DEBUG=* ts-node src/server.ts
# server ============================================ +0ms
# server > Starting server... +1ms
# server ============================================ +0ms
# enso:HTTPServer listRegisteredControllers() +0ms
# enso:HTTPServer => IndexController +2ms
# ...
# server ✔ [nodejs] v10.15.3 +0ms
# server ✔ API server listening on port 5000 in [development] mode +0ms
A simple requests to curl localhost:5000
should display
{
"name":"@enso/standalone",
"version":"1.0.0",
"up":5.031,
"message":"ok"
}
Congratulations, you now have a skeleton HTTP server that:
- works with
TypeScript
- configured with
koa
- supports dependency injection with
inversify
- can be introspected with
debug