{"id":15321800,"url":"https://github.com/eldimious/nodejs-api-showcase","last_synced_at":"2025-04-09T19:20:36.656Z","repository":{"id":42202973,"uuid":"105887424","full_name":"eldimious/nodejs-api-showcase","owner":"eldimious","description":"A Node.js App Architecture showcase  heavily influenced by the Clean Architecture and Hexagonal Architecture, using MongoDB.","archived":false,"fork":false,"pushed_at":"2023-02-11T23:05:38.000Z","size":2145,"stargazers_count":253,"open_issues_count":10,"forks_count":40,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T12:40:30.651Z","etag":null,"topics":["architecture-showcase","boilerplate","clean-architecture","clustering","continuous-integration","dependency-injection","docker","docker-compose","express","express-boilerplate","hexagonal-architecture","javascript","layered-architecture","mongodb","node-js","nodejs","nodejs-boilerplate","swagger","travis-ci","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eldimious.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-05T12:30:45.000Z","updated_at":"2025-03-16T12:20:14.000Z","dependencies_parsed_at":"2023-02-18T13:46:37.033Z","dependency_job_id":null,"html_url":"https://github.com/eldimious/nodejs-api-showcase","commit_stats":{"total_commits":225,"total_committers":2,"mean_commits":112.5,"dds":0.008888888888888835,"last_synced_commit":"6a35edb0b0a14cf3e951ff87c110b89022102d8a"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldimious%2Fnodejs-api-showcase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldimious%2Fnodejs-api-showcase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldimious%2Fnodejs-api-showcase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldimious%2Fnodejs-api-showcase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eldimious","download_url":"https://codeload.github.com/eldimious/nodejs-api-showcase/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094991,"owners_count":21046770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["architecture-showcase","boilerplate","clean-architecture","clustering","continuous-integration","dependency-injection","docker","docker-compose","express","express-boilerplate","hexagonal-architecture","javascript","layered-architecture","mongodb","node-js","nodejs","nodejs-boilerplate","swagger","travis-ci","typescript"],"created_at":"2024-10-01T09:13:09.655Z","updated_at":"2025-04-09T19:20:36.611Z","avatar_url":"https://github.com/eldimious.png","language":"JavaScript","readme":"[![Build Status](https://api.travis-ci.org/eldimious/nodejs-api-showcase.svg?branch=master)](https://api.travis-ci.org/eldimious/nodejs-api-showcase)\n\n# Typescript #\nYou can take a look at Typescript source code at the branch [typescript](https://github.com/eldimious/nodejs-api-showcase/tree/typescript)\n\n# What is this repository for? #\nNode.js app architecture showcase using [Express](https://www.npmjs.com/package/express), [MongoDB](https://www.mongodb.com/) and [Mongoose](http://mongoosejs.com/) as ORM. The project has an  implementation of an authentication system that uses JSON Web Token to manage users' login data in Node.js web server. You can start your Node.js projects building on this boilerplate.\n\n# Architecture Overview #\nThe app is designed to use a layered architecture. The architecture is heavily influenced by the Clean Architecture.[Clean Architecture](https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html) is an architecture where:\n\n  1. **does not depend on the existence of some framework, database, external agency.**\n  2. **does not depend on UI**\n  3. **the business rules can be tested without the UI, database, web server, or any external element.** \n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/719/1*ZNT5apOxDzGrTKUJQAIcvg.png\" width=\"350\"/\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/900/0*R7uuhFwZbhcqZSvn\" width=\"350\" /\u003e \n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/1200/0*rFs1UtU4sRns5vCJ.png\" width=\"350\" /\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/1200/0*C-snK7L4sMn7b6CW.png\" width=\"350\" /\u003e \n\u003c/p\u003e\n\nAlso, in entry point(server.js), I use Dependency Injection(DI). There are many reasons using Dependency Injection as:\n1. Decoupling\n2. Easier unit testing\n3. Faster development\n4. Dependency injection is really helpful when it comes to testing. You can easily mock your modules' dependencies using this pattern.\n\nYou can take a look at this tutorial: `https://blog.risingstack.com/dependency-injection-in-node-js/`.\nAccording to DI:\n  A. High-level modules should not depend on low-level modules. Both should depend on abstractions.\n  B. Abstractions should not depend on details.\n\nThe code style being used is based on the airbnb js style guide.\n\n\n## Data Layer ##\n\nThe data layer is implemented using repositories, that hide the underlying data sources (database, network, cache, etc), and provides an abstraction over them so other parts of the application that make use of the repositories, don't care about the origin of the data and are decoupled from the specific implementations used, like the Mongoose ORM that is used by this app. Furthermore, the repositories are responsible to map the entities they fetch from the data sources to the models used in the applications. This is important to enable the decoupling.\n\n## Domain Layer ##\n\nThe domain layer is implemented using services. They depend on the repositories to get the app models and apply the business rules on them. They are not coupled to a specific database implementation and can be reused if we add more data sources to the app or even if we change the database for example from MongoDB to Couchbase Server.\n\n## Routes/Controller Layer ##\n\nThis layer is being used in the express app and depends on the domain layer (services). Here we define the routes that can be called from outside. The services are always used as the last middleware on the routes and we must not rely on res.locals from express to get data from previous middlewares. That means that the middlewares registered before should not alter data being passed to the domain layer. They are only allowed to act upon the data without modification, like for example validating the data and skipping calling next().\n\n## Entry point ##\n\nThe entry point for the applications is the server.js file. It does not depend on express.js or other node.js frameworks. It is responsible for instantiating the application layers, connecting to the db and  mounting the http server to the specified port.\n\n# Quick start #\n\n### Prerequisites ###\n\nCreate an .env file in project root to register the following required environment variables:\n  - `DATABASE_URL` - MongoDB connection URL\n  - `HTTP_PORT` - port of server\n  - `JWT_SECRET` - we will use secret to generate our JSON web tokens\n  - `REDIS_URL` - redis client\n\n### Use Docker: ###\n\nYou can use Docker to start the app locally. The Dockerfile and the docker-compose.yml are already provided for you. You have to run the following command:\n\n```shell\ndocker-compose up\n```\n\n### Use the npm scripts: ###\n\n```shell\nnpm run test\n```\nfor running tests.\n\n\n# Endpoints #\n\nYou can take a look at API's endpoints navigated to http://localhost:5555/docs/\n\n## Auth Routes ##\n  \n### Register ###\n\n```shell\nPOST /auth/register\n```\n\nBody Params:\n```shell\n{ \n  name,\n  surname,\n  username,\n  email,\n  password\n}\n```\n\nDescription: creates a new user. Password is stored in bcrypt format.\n\n\n### Login ###\n\n```shell\nPOST /auth/login\n```\n\nBody Params:\n```shell\n{ \n  email,\n  password\n}\n```\n\n**Description**: logs in to the server. Server will return a JWT token and user's info as:\n\n```js\n{\n    \"status\": \"success\",\n    \"data\": {\n        \"token\": {\n          id: \"eyJhbGciOiJIUzxxxxxxx.eyJlbWFpbCI6ImRpbW9zdGhlbxxxxxxxxxxxxx.axxxxxxxxxx\",\n          expiresIn: 86400,\n        },\n        \"user\": {\n            \"id\": \"mongoID\",\n            \"fullName\": \"clark kent\",\n            \"username\": \"superman\",\n            \"email\": \"clarkkent@test.com\",\n            \"created\": \"2018-01-08T14:43:32.480Z\"\n        }\n    }\n}\n```\n\n## User Routes ##\n\nIn order to be able to retrieve posts list, user should send a Bearer token using Authorization header, otherwise server will answer with 401.\n\n### Get specific user ###\n\n```shell\nGET /users/:userId\n```\n\n**Description**: Gets specific user.\n\n## Posts Routes ##\n\nIn order to be able to retrieve posts list, user should send a Bearer token using Authorization header, otherwise server will answer with 401.\n\n### Posts List ###\n\n```shell\nGET /users/:userId/posts\n```\n\nQuery Params:\n```shell\n{ \n  publisher, {String} (optional)\n}\n```\n**Description**: retrieves user's posts docs, based on his token and his id.\n\n\n```shell\nPOST /users/:userId/posts\n```\n\nBody Params:\n```shell\n{ \n  imageUrl, {String}\n  publisher, {String}\n  description, {String} (optional)\n}\n```\n**Description**: creates a new post doc in DB for user.\n\n```shell\nGET /users/:userId/posts/:postId\n```\n\n**Description**: Gets specific user's post.\n\n# Packages and Tools #\n\n  - [Node.js](https://nodejs.org/en/)\n  - [Express](https://www.npmjs.com/package/express)\n  - [Mongoose](http://mongoosejs.com/)\n  - [Mongoose-Pagination](https://github.com/edwardhotchkiss/mongoose-paginate)\n  - [Express-jsend](https://www.npmjs.com/package/express-jsend)\n  - [Express-validator](https://github.com/ctavan/express-validator)\n  - [Bcrypt](https://github.com/dcodeIO/bcrypt.js)\n  - [Jsonwebtoken](https://github.com/auth0/node-jsonwebtoken)\n  - [Redis](https://github.com/luin/ioredis)\n  - [Express-winston](https://github.com/bithavoc/express-winston)\n  - [Winston](https://github.com/winstonjs/winston)\n  - [Mocha](https://www.npmjs.com/package/mocha)\n  - [Chai](https://www.npmjs.com/package/chai)\n  - [Sinon](https://www.npmjs.com/package/sinon)\n  - [Supertest](https://github.com/visionmedia/supertest)\n  - [Eslint](https://www.npmjs.com/package/eslint)\n\n\n## Support Me\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y797KCA)\n\n## Show your support\n\nGive a ⭐️ if this project helped you!\n","funding_links":["https://ko-fi.com/Y8Y797KCA"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feldimious%2Fnodejs-api-showcase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feldimious%2Fnodejs-api-showcase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feldimious%2Fnodejs-api-showcase/lists"}