Node API template, written in Typescript, with dependency injection
_Available on _GitHub
├── .circleci/config.yml # Circle CI Config
├── src/ # All application source
├──── app/
├────── api/ # Root of route definition
├────── expressMiddleware.ts # Connect express middleware and controllers to routes and express app
├────── socketMiddleware.ts # Connect socket middleware and controllers to socket.io
├────── index.ts # Export major app components
├────── serviceManager.ts # COMPOSITION ROOT: https://blog.ploeh.dk/2011/07/28/CompositionRoot
| Create and connect all clients, services, middleware and controllers
├──── lib/
├────── express/ # Define all express controllers and middleware
├────── models/ # Define all models (objects that get saved to the db or used internally)
├────── requests/ # Define all requests (objects coming into the API from outside)
├────── services/ # Define all DI classes for business logic and DB CRUD
├────── socket/ # Define all socket controllers and middleware
|
├──── config.ts # Define the app configuration model with validation
├──── configLoader.ts # Read configuration from env vars into configuration model
├──── logger.ts # Global singleton for logging to console
├──── server.ts # Create express app, connect to http server and serviceManager instance
├──── start.ts # ENTRYPOINT - Create serviceManager, use it to create and start server
|
└── Lots of random build-related files
For those of you that have not heard the term before, dependency injection (or inversion of control), is a pattern wherein an object or function is passed it’s dependencies by the caller instead of requesting them directly. This improves modularity, reuse, and makes testing much easier.
Without dependency injection, any class you create would directly require it’s dependencies. This tightly binds one class to another, and means that when you are writing tests you either have to spin up the entire dependency tree and deal with all that complexity, or you have to intercept the require call.
Intercepting require calls is possible and commonly done, but not without caveats and side effects.
In my opinion, using dependency injection is just simpler for both implementation and testing.
#typescript #testing #nodejs #api