Boilerplate for NodeJS Express Projects written in Typescript
The purpose of this template repository is to fast track APIs development and reach to production ASAP.
At most places except TSOA, there is very less use of external dependency injection or similar libraries to demonstrate how same thing can be achieved in vanilla code. The advantage of this is more control on behavior of dependency injection.
It is designed keeping SOLID Principles and Loose Coupling in mind. It demonstrates use of Singleton (like db, auth etc), Factory(cache), Strategy(injecting dependency based on .env like DB_TYPE) design patterns at multiple places.
- Controllers written using TSOA library
- Controllers, Services, Middlewares, Entities, Error handlers all are pre-configured with standard best practices and follows SOLID Principles, loose coupled Architecture
- Mongo Database with extensible database interface for other Databases implementation
- Redis Persistent Queue with extensible interface for other Queues implementation
- NodeCache and RedisCache support with extensible interface for other Cache implementation
- Rust Web assembly boilerplate for compute intensive tasks
- Worker pool for running compute intensive tasks in worker threads
- Standard utilities for validation, email sender are available
- Automatic Swagger generation - combined swagger is generated from swagger docs and tsoa generated swagger specs
- Eslint and Prettier configured for Code quality checks
- Husky configured to run pre commit git hooks to run code quality checks
src/index.tsThis is entry point of project when we donpm start.src/controllersThis serves as entrypoint of different APIssrc/authThis contains extensible Auth interface and JWT Auth Implementation for that interfacesrc/middlewaresThis contains middlewares that are executed before reaching code flow to controllerssrc/errorsCustom error typessrc/dbThis contains extensible Database interface and MongoDB implementationsrc/modelsThis contains model validation using mongoose schema. Mostlytsoais capable of doing basic validation based on type but sometimes we need some conditional validation logic and we need custom validators.src/configsThis contains configuration filessrc/entitiesThis contains entity cum repository classes. Repository methods are implemented in Entities itself as static methodssrc/servicesThis is executed from controllers and contains main business logic for each APIsrc/typesThis contains types of different objects used across applicationsrc/typingsThis extends express namespace for custom properties in request/responsesrc/utilsThis contains common utilitiessrc/workersThis implements workerpool and worker tasks to execute in worker threadssrc/p_queueThis contains extensible Persistent Queue interface and Redis Pub/Sub implementationsrc/cacheThis contains extensible application cache and Implementation of Node Cache and Redis Cache demonstrating factory patternsrc/__tests__This contains unit and integration test casesrust-wasm-libsThis contains web assembly code for simple factorial examplekeysThis contains blankprivateKey.pemandpublicKey.pemused by JWT auth implementation. One needs to put actual RSA keys in those files before running the application or test cases.DockerfileTo dockerize the applicationDockerfile.rust-wasmTo dockerize the application with Rust and other dependencies if rust web assembly is usedswagger.jsonGenerated fromtsoaand Swagger comments in the code.envThis contains environment variables referred in the codetsoa.jsonConfiguration file fortsoatsconfig.jsonConfiguration file for typescriptjest.config.tsConfiguration file forJest Test Runner
- NodeJs >= v22.12.0
Install npm modules:
npm installRust web assembly code is written in rust-wasm-libs directory. To compile wasm package Run:
npm run build-rust-wasmIf not using rust web assembly, remove rust-wasm-libs from package.json and run npm install again.
Start application:
npm startTo Run with different env file (e.g. .env.local):
ENV_FILE=.env.local npm startTo run test cases:
ENV_FILE=.env.test npm run testOnly NodeJS without rust wasm:
docker build . -t <image-repo>/<image-tag> --platform linux/amd64With rust wasm:
docker build . -f Dockerfile.rust-wasm -t <image-repo>/<image-tag> --platform linux/amd64To use src/workers/factorial.ts (rust wasm) - use following snippet into src/routes/app.ts
// Imports
import { createOrGetPool } from "../workers/workerPool.js";
import { Promise as WorkerPromise } from "workerpool";
// Wasm Route
app.get("/wasm/:n", async (req: Request, res: Response) => {
try {
const factorial = await createOrGetPool({
workerFileName: "factorial"
})
.exec("factorial", [req.params.n])
.timeout(10000);
return res.OK(factorial.toString());
} catch (err) {
logger.error(`Error occurred in ${req.path}: %o`, err);
if (err instanceof WorkerPromise.TimeoutError) {
return res.BAD_REQUEST("Operation timeout because of large input. Try smaller input");
}
return res.INTERNAL_SERVER_ERROR((err as Error).message);
}
});rm -rf rust-wasm-libs src/workers/factorial.ts Dockerfile.rust-wasmDelete "rust-wasm-libs": "file:rust-wasm-libs/pkg" dependency and build-rust-wasm task from package.json file.