{"id":13622779,"url":"https://github.com/anandundavia/express-api-structure","last_synced_at":"2025-04-15T09:33:56.531Z","repository":{"id":68737088,"uuid":"157969283","full_name":"anandundavia/express-api-structure","owner":"anandundavia","description":"Structure for Express based API server","archived":false,"fork":false,"pushed_at":"2020-10-21T23:39:38.000Z","size":34,"stargazers_count":114,"open_issues_count":2,"forks_count":27,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-01T21:55:07.124Z","etag":null,"topics":["boilerplate","convention","expressjs","nodejs"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anandundavia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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":"2018-11-17T09:22:14.000Z","updated_at":"2024-07-10T01:58:54.000Z","dependencies_parsed_at":"2023-03-14T21:45:21.723Z","dependency_job_id":null,"html_url":"https://github.com/anandundavia/express-api-structure","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anandundavia%2Fexpress-api-structure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anandundavia%2Fexpress-api-structure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anandundavia%2Fexpress-api-structure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anandundavia%2Fexpress-api-structure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anandundavia","download_url":"https://codeload.github.com/anandundavia/express-api-structure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223668413,"owners_count":17182926,"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":["boilerplate","convention","expressjs","nodejs"],"created_at":"2024-08-01T21:01:23.938Z","updated_at":"2024-11-08T10:31:03.835Z","avatar_url":"https://github.com/anandundavia.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"## Structure\n\n`src` contains the whole source code of the api.\nInside `src`, there are three directories: `api`, `config`, `constants` and one `index.js` file which will be the entry point to the application\n\n### `constants` directory\n\n`index.js` will export all the constants required in the api.\n\n-   constants which are common across environments like dev and prod should be defined in `constants.common.js`\n\n-   constants which are specific for environments should be defined in `constants.dev.js` or `constants.dev.js`. Make sure to have the same shape of constants in all the `constants.[env].js` files\n\n*   \u003e DO NOT include sensitive information like credentials of database in the constants, they should be defined in the .env file which is explained\n\n### `config` directory\n\nThis directory will have self-contained config files for different modules in your api.\nIn the boilerplate, `express.js` and `session.js` are included which configures the appropriate modules.\n\nWhile creating new config files, in the mind that self-contained config files will help in scaling the application as well as make it more maintainable,\nFor example, If in future you want to shift to sails from express, all you need to do is create one `sails.js` file, require it in the `src/index.js` and done!\n\nYou can even take this to one level further by doing `express.dev.js` and `express.prod.js` and require appropriate file in `src/index.js` based on the env. For the most applications however, that part will be taken care by constants. But if needed, above can be done as well\n\n### `api` directory\n\nThis directory will be the one you will be working with most of the time\nThis directory contains more directories:\n\n-   `controllers`\n-   `middlewares`\n-   `repository`\n-   `routes`\n-   `services`\n-   `utils`\n-   `validations`\n\n#### controllers\n\nA controller will have all the business logic related to one object or one api path ( `/v1/product` )\n\nNaming convention: If your api is `/v1/product` then name your controller as `product.controller.js`\n`product.controller.js` will have all the business logic that will be performed at `/v1/product/...` endpoints.\nAPI and controller function mapping:\n\n```\nAPI                         | controller function\n                            |\nGET: /v1/product/all        | `exports.getAllProducts`\nGET: /v1/product/:productID | `exports.getSingleProduct`\nPOST: /v1/product           | `exports.createProduct`\nPUT: /v1/product/productID  | `exports.updateProduct`\n```\n\nA `product.controller.js` file should ideally use `product.service.js` and `response.service.js` files located in `api/services` directory\n\n#### middlewares\n\nAny common functions that are needed across routes should be inside this directory.\nMiddlewares with functionalities of error handling and authentication are the most common across routes and thus are included in this boilerplate\n\nConvention: In case of express, all the middlewares should be a function which takes either (req, res, next) or (error, req, res, next) as argument\n\n#### repository\n\nAll the queries to database should reside here. In this boilerplate, `mongo` directory is included as example. Which will have all the queries to the mongo database.\n\nConvention:\n\n-   A separate directory for each repository/database used. For example if you use `redis` and\n    `mysql`, you will have two directories inside `repository`\n-   Each database specific directory should have `[name-of-db].repository.js` file (`mongo.repository.js` is included in the example). This file should have logic to open and close the connection to\n    the database. This files also multiplexes the queries fired on that database.\n    You might want to have one more directory named `collection` or `table` inside each database specific directory. If you have two collection/table named `product` and `user` in your database, then `collection` directory should have `product.collection.js` and `user.collection.js` ( or `table` directory should have `product.table.js` and `user.table.js` ).\n-   Each `[entity].collection.js` or `[entity].table.js` should at least export two members. A function named `setDatabase` and An object named `queries` containing all the query functions. Explore the boilerplate example for more information\n-   All the queries should be exported in such a manner that a controller or a service using that query should not know on which database it is being fired. For example a controller should import a query like: `import { findUser, setSession } = require('../repository');` Chances are, `findUser` is exported by `mongo` and `setSession` is exported by `redis`. Use object destructuring at appropriate places to achieve the same\n\n#### routes\n\nAll the API routes.\n\nConvention:\n\n-   Create version wise directories ( `v1`, `v2` )\n-   Each version directory should have `index.js`.\n-   If there are apis of `user` and `product`, the `v1` directory should have `user.route.js` and `product.route.js`\n\nLook at the example given in the boilerplate and read the comments to get the better idea\n\n#### services\n\nA service should be created:\n\n1. To increase code reuse ( `response.service.js` )\n2. To encapsulate complex business logic which is outside of the scope of a controller\n3. If you need to manage some sort of state in the API ( when was the last time some cron job ran )\n\n\u003e If a service maintains some state, it must be a singleton\n\n#### utils\n\nUtility classes and functions that are used frequently in the API ( which can not be inside middlewares or can not be a service on their own )\n\n#### validations\n\nValidations for each api.\n\nConvention:\n\n-   All the validations of `/v1/product/...` route should be inside `product.validation.js`\n    Have a look at the `user.validation.js` included in the boilerplate example.\n\n---\n\n## Some Details combining everything together\n\nTo create a /v1/product/... API routes:\n\n1. Create `product.controller.js` in `controllers`\n2. Create `product.route.js` in `routes`\n3. Create `product.validation.js` in `validations`\n4. Create `product.collection.js` in `repository/mongo`\n5. You might want to create `product.service.js` inside `services`\n\nInside the `routes/v1/index.js` file, the routes should be mounted like\n\n```\nconst productRoutes = require('./product.route');\n...\nrouter.use('/product', productRoutes);\n```\n\n\u003cbr\u003e\n`product.route.js` should look like:\n\n```\nconst validate = require('express-validation');\n\nconst controller = require('../../controllers/product.controller');\nconst validation = require('../../validations/product.validation');\n\n\n...\nrouter.route('/')\n    .get(validate(validation.getProduct), controller.getProduct)\n    .post(validate(validation.createProduct), controller.createProduct)\n```\n\n\u003cbr\u003e\n`product.controller.js` should make use of functions exported by `product.collection.js`\n\n## Sensitive information and .env files\n\nSensitive information like database credentials and keys to sign cookies should not be included in\nconstants file. They should be in `.env` file\n\n\u003e `.env` must never be committed to version control. `.env.example` file should be committed to let other developers know what env variables should be defined\n\nCheckout `.env.example` and `.env` to get the better idea\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanandundavia%2Fexpress-api-structure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanandundavia%2Fexpress-api-structure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanandundavia%2Fexpress-api-structure/lists"}