{"id":24903077,"url":"https://github.com/codewithashim/easy-express-server-cli","last_synced_at":"2025-10-16T14:30:56.523Z","repository":{"id":246324199,"uuid":"820733996","full_name":"codewithashim/Easy-Express-Server-CLI","owner":"codewithashim","description":"`easy-express` is a CLI tool to automate the setup of a common Express.js backend. This tool helps you quickly scaffold a backend setup without rewriting the setup each time.","archived":false,"fork":false,"pushed_at":"2024-09-18T06:10:56.000Z","size":7710,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"production","last_synced_at":"2024-09-19T07:37:08.978Z","etag":null,"topics":["aws","codewithashim","common-server","docker","expressjs","modules","mongodb","nodejs","npm-package","packe","s3","server","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/easy-express-cwa","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codewithashim.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":"2024-06-27T04:39:00.000Z","updated_at":"2024-09-18T06:10:59.000Z","dependencies_parsed_at":"2024-06-27T06:50:03.708Z","dependency_job_id":"0fd4cdde-c8c2-417e-9253-5391480d5c07","html_url":"https://github.com/codewithashim/Easy-Express-Server-CLI","commit_stats":null,"previous_names":["codewithashim/cwa-backend-setup","codewithashim/easy-express-server-cli"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codewithashim%2FEasy-Express-Server-CLI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codewithashim%2FEasy-Express-Server-CLI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codewithashim%2FEasy-Express-Server-CLI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codewithashim%2FEasy-Express-Server-CLI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codewithashim","download_url":"https://codeload.github.com/codewithashim/Easy-Express-Server-CLI/tar.gz/refs/heads/production","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236726467,"owners_count":19194916,"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":["aws","codewithashim","common-server","docker","expressjs","modules","mongodb","nodejs","npm-package","packe","s3","server","typescript"],"created_at":"2025-02-01T22:18:53.132Z","updated_at":"2025-10-16T14:30:52.865Z","avatar_url":"https://github.com/codewithashim.png","language":"TypeScript","readme":"# Easy Express CWA 🚀\n\n`easy-express` is a CLI tool to automate the setup of a common Express.js backend. This tool helps you quickly scaffold a backend setup without rewriting the setup each time.\n\n## Features ✨\n\n- **Predefined Backend Setup**: Copies a predefined backend setup to your current working directory.\n- **Common Configurations**: Includes configurations such as `.env.example`, `.eslintignore`, `.eslintrc`, `.gitignore`, `.prettierrc`, `docker-compose.yml`, `Dockerfile`, `package.json`, and `tsconfig.json`.\n- **Prebuilt Functionalities**:\n  * 🔐 Authentication and authorization\n  * 🔑 JWT handling\n  * 🔗 Login with Google Auth\n  * 📜 Logger setup\n  * 🐳 Docker configuration\n  * 🚀 Redis integration\n  * 📂 File upload middleware (Cloudinary, AWS S3)\n  * 📘 Swagger for API documentation\n  * 🍪 Cookies handling\n  * 🔒 Security features\n  * 🛠️ Many more features upcoming\n\n## Installation 🛠\n\n```sh\nnpm install -g easy-express-cwa\nmkdir server\n```\n\n```sh\ncd server\n```\n\n```sh\nnpx easy-express-cwa\n```\n\nConfigure your environment variables:\n\nCopy the `.env.example` file to `.env` and update the values as needed:\n\n```sh\nNODE_ENV=development\nPORT=8000\nDB_URL=mongodb://localhost:27017/yourdb\nENCRYPTION_METHOD=AES-256-CBC\nENCRYPTION_KEY=DR8j97BtgHVBiEKAjqRlfn6VSLTJTIpwsgNo0vTWKvA=\nBCRYPT_SALT_ROUNDS=14\n\nDOMAIN=yourdomain.com\n\nAPP_ID=your-app-id\nAPP_CERTIFICATE=your-app-certificate\n\nJWT_SECRET=GiCj9Qrmy4vYeDbBjrVCszy0xlN5PGZQQ77iLExHVuI=\nJWT_REFRESH_SECRET=jiS8zP3qHU2fgKblrhqVKhFEYYqpwsrh/6Z/Ak0ZhL8=\nJWT_EXPIRATION_TIME=3d\nJWT_REFRESH_EXPIRATION_TIME=3d\n\nCLOUDINARY_CLOUD_NAME=\"\"\nCLOUDINARY_API_KEY=\"\"\nCLOUDINARY_API_SECRET=\"\"\n\nREDIS_PASSWORD=your-redis-password\nREDIS_HOST=your-redis-host\nREDIS_PORT=your-redis-port\n\nGOOGLE_CLIENT_ID=your-google-client-id\nGOOGLE_CLIENT_SECRET=your-google-client-secret\nGOOGLE_CALLBACK_URL=your-google-callback-url\nGOOGLE_REDIRECT_URL=your-google-redirect-url\nGOOGLE_APP_USER=your-google-app-user\nGOOGLE_APP_PASSWORD=your-google-app-password\n\n```\n\n# Folder Structure 📂\n\nHere's the folder structure generated by `easy-express`:\n\n```\n└── 📁 server\n    └── 🚫 .dockerignore\n    └── 🛠️ .env\n    └── 🛠️ .env.example\n    └── 🐳 Dockerfile\n    └── 📜 README.md\n    └── 🐳 docker-compose.yml\n    └── 📦 package.json\n    └── 📁 src\n        └── 📁 app\n            └── 📁 middlewares\n                └── 🔒 auth.ts\n                └── 📁 cloudinary\n                    └── ☁️ cloudinary.ts\n                └── ⚠️ globalErrorHandler.ts\n                └── 🛠️ handleZodError.ts\n                └── 📁 multer\n                    └── 📤 multer.ts\n                └── 📁 redis\n                    └── 🛠️ redis.ts\n                └── ✅ validateRequest.ts\n            └── 📁 modules\n                └── 📁 auth\n                    └── 👤 auth.controller.ts\n                    └── 🚦 auth.route.ts\n                    └── 🛠️ auth.service.ts\n                └── 📁 example\n                    └── 📄 example.controller.ts\n                    └── 📄 example.interface.ts\n                    └── 🗃️ example.model.ts\n                    └── 🚦 example.route.ts\n                    └── 🛠️ example.service.ts\n                    └── ✅ example.validation.ts\n                └── 📁 googleOAuth\n                    └── 🌐 googleOAuth.controller.ts\n                    └── 🚦 googleOAuth.route.ts\n                    └── 🛠️ googleOAuth.service.ts\n                └── 📁 user\n                    └── 👤 user.controller.ts\n                    └── 🗃️ user.interface.ts\n                    └── 🗃️ user.model.ts\n                    └── 🚦 user.route.ts\n                    └── 🛠️ user.service.ts\n                    └── ✅ user.validation.ts\n            └── 📁 routes\n                └── 🚦 index.ts\n        └── 🛠️ app.ts\n        └── 📁 config\n            └── ⚙️ index.ts\n            └── 🛂 passport.ts\n        └── 📁 constants\n            └── 💬 message.ts\n            └── 🔢 pagination.ts\n            └── ⏳ redisCacheExpireDate.ts\n            └── 🔑 redisKeys.ts\n        └── 📁 enums\n            └── 📄 common.ts\n            └── 📄 user.ts\n        └── 📁 errors\n            └── 🛠️ ApiError.ts\n            └── ❌ handleCastError.ts\n            └── 🛠️ handleValidationError.ts\n            └── 🛠️ handleZodError.ts\n        └── 📁 helpers\n            └── 🛡️ jwtHelper.ts\n            └── 🛠️ paginationHelper.ts\n        └── 📁 interfaces\n            └── 📄 common.ts\n            └── 📄 error.ts\n            └── 📄 index.d.ts\n            └── 📄 pagination.ts\n        └── 🛠️ server.ts\n        └── 📁 shared\n            └── 🛠️ catchAsync.ts\n            └── 📋 logger.ts\n            └── 🛠️ pick.ts\n            └── ✉️ sendResponse.ts\n        └── 📁 utils\n            └── 📧 mail.util.ts\n            └── 🔑 oAuth.ts\n    └── ⚙️ tsconfig.json\n    └── 📦 yarn.lock\n\n```\n\n### API Documentation\n\nAccess the Swagger API documentation at `http://localhost:3000/api-docs`.\n\n## Contributing 🤝\n\nContributions are welcome! Please open an issue or submit a pull request for any improvements.\n\n## License 📄\n\nThis project is licensed under the MIT License.\n\n## Contact 📬\n\nFor any inquiries or feedback, please reach out at [codewithashim@gmail.com]().\n\n# **Example**\n\nTo add the example code snippets for the `example` entity CRUD operations in your `README.md` file, you can follow this structure:\n\n1. **Overview of the Example Module**\n2. **Interface**\n3. **Model**\n4. **Controller**\n5. **Service**\n6. **Route**\n7. **Validation**\n\nHere’s how you can add them to your `README.md`:\n\n# Example Module\n\nThis module provides CRUD operations for the `example` entity. Below are the code snippets for the controller, interface, model, route, service, and validation.\n\n## Interface\n\n```typescript\nimport { Model } from \"mongoose\";\n\nexport type IExample = {\n  title: string;\n  description: string;\n  createdAt?: Date;\n  updatedAt?: Date;\n}\n\nexport type ExampleModel =Model\u003cIExample, Record\u003cstring, unknown\u003e\u003e;\n\n```\n\n## Model\n\n```typescript\nimport { Schema, model } from \"mongoose\";\nimport { IExample, ExampleModel } from \"./example.interface\";\n\nconst ExampleSchema = new Schema\u003cIExample\u003e(\n  {\n    name: {\n      type: String,\n      required: true,\n    },\n    description: {\n      type: String,\n      required: true,\n    },\n  },\n  {\n    timestamps: true,\n    toJSON: {\n      virtuals: true,\n    },\n  }\n);\n\nexport const Example = model\u003cIExample, ExampleModel\u003e(\"Example\", ExampleSchema);\n\n```\n\n## Controller\n\n```typescript\nimport { Request, Response } from \"express\";\nimport httpStatus from \"http-status\";\nimport catchAsync from \"../../../shared/catchAsync\";\nimport sendResponse from \"../../../shared/sendResponse\";\nimport { IExample } from \"./example.interface\";\nimport { ExampleService } from \"./example.service\";\nimport { responseMessage } from \"../../../constants/message\";\n\nconst getAllExamples = catchAsync(async (req: Request, res: Response) =\u003e {\n  const result = await ExampleService.getAllExamples();\n  \n  sendResponse\u003cIExample[]\u003e(res, {\n    statusCode: httpStatus.OK,\n    success: true,\n    message: responseMessage.GET_ALL_EXAMPLES_MESSAGE,\n    data: result,\n  });\n});\n\nconst getExampleById = catchAsync(async (req: Request, res: Response) =\u003e {\n  const result = await ExampleService.getExampleById(req.params.id);\n\n  sendResponse\u003cIExample\u003e(res, {\n    statusCode: httpStatus.OK,\n    success: true,\n    message: responseMessage.GET_EXAMPLE_BY_ID_MESSAGE,\n    data: result,\n  });\n});\n\nconst updateExample = catchAsync(async (req: Request, res: Response) =\u003e {\n  const id = req.params.id;\n  const updatedData = req.body;\n\n  const result = await ExampleService.updateExample(id, updatedData);\n\n  sendResponse\u003cIExample\u003e(res, {\n    statusCode: httpStatus.OK,\n    success: true,\n    message: responseMessage.UPDATE_EXAMPLE_MESSAGE,\n    data: result,\n  });\n});\n\nconst deleteExample = catchAsync(async (req: Request, res: Response) =\u003e {\n  const { id } = req.params;\n  const result = await ExampleService.deleteExample(id);\n  sendResponse\u003cIExample\u003e(res, {\n    statusCode: httpStatus.OK,\n    success: true,\n    message: responseMessage.DELETE_EXAMPLE_MESSAGE,\n    data: result,\n  });\n});\n\nexport const ExampleController = {\n  getAllExamples,\n  getExampleById,\n  updateExample,\n  deleteExample,\n};\n```\n\n## Service\n\n```typescript\nimport ApiError from \"../../../errors/ApiError\";\nimport { Example } from \"./example.model\";\nimport { IExample } from \"./example.interface\";\nimport httpStatus from \"http-status\";\nimport { responseMessage } from \"../../../constants/message\";\n\nconst getAllExamples = async (): Promise\u003cArray\u003cIExample\u003e\u003e =\u003e {\n  try {\n    const examples = await Example.find();\n    return examples;\n  } catch (error) {\n    throw new ApiError(\n      httpStatus.INTERNAL_SERVER_ERROR,\n      `${responseMessage.FAILED_MESSAGE} get all examples`\n    );\n  }\n};\n\nconst getExampleById = async (id: string): Promise\u003cIExample | null\u003e =\u003e {\n  try {\n    const example = await Example.findById(id);\n    if (!example) {\n      throw new ApiError(\n        httpStatus.NOT_FOUND,\n        `Example ${responseMessage.NOT_FOUND_MESSAGE}`\n      );\n    }\n    return example;\n  } catch (error) {\n    throw new ApiError(\n      httpStatus.INTERNAL_SERVER_ERROR,\n      `${responseMessage.FAILED_MESSAGE} get example by ID`\n    );\n  }\n};\n\nconst updateExample = async (\n  id: string,\n  payload: Partial\u003cIExample\u003e\n): Promise\u003cIExample | null\u003e =\u003e {\n  try {\n    const isExist = await Example.findOne({ _id: id });\n    if (!isExist) {\n      throw new ApiError(\n        httpStatus.NOT_FOUND,\n        `Example ${responseMessage.NOT_FOUND_MESSAGE}`\n      );\n    }\n\n    const updateExampleData = payload;\n\n    const result = await Example.findOneAndUpdate({ _id: id }, updateExampleData, {\n      new: true,\n    });\n    return result;\n  } catch (error) {\n    throw new ApiError(\n      httpStatus.INTERNAL_SERVER_ERROR,\n      `${responseMessage.FAILED_MESSAGE} update example`\n    );\n  }\n};\n\nconst deleteExample = async (id: string): Promise\u003cIExample | null\u003e =\u003e {\n  try {\n    const example = await Example.findByIdAndDelete(id);\n    if (!example) {\n      throw new ApiError(\n        httpStatus.NOT_FOUND,\n        `Example ${responseMessage.NOT_FOUND_MESSAGE}`\n      );\n    }\n    return example;\n  } catch (error) {\n    throw new ApiError(\n      httpStatus.INTERNAL_SERVER_ERROR,\n      `${responseMessage.FAILED_MESSAGE} delete example`\n    );\n  }\n};\n\nexport const ExampleService = {\n  getAllExamples,\n  getExampleById,\n  updateExample,\n  deleteExample,\n};\n\n```\n\n## Route\n\n```typescript\nimport express from \"express\";\nimport validateRequest from \"../../middlewares/validateRequest\";\nimport { ExampleController } from \"./example.controller\";\nimport { createExampleValidator } from \"./example.validation\";\nconst router = express.Router();\n\nrouter.get(\"/\", ExampleController.getAllExamples);\nrouter.get(\"/:id\", ExampleController.getExampleById);\nrouter.patch(\n  \"/:id\",\n  validateRequest(createExampleValidator.updateExampleZodSchema),\n  ExampleController.updateExample\n);\nrouter.delete(\"/:id\", ExampleController.deleteExample);\n\nexport const ExampleRoutes = router\n```\n\n## Validation\n\n```typescript\nimport { z } from \"zod\";\n\nconst createExampleZodSchema = z.object({\n  body: z.object({\n    name: z.string({\n      required_error: \"Name is required\",\n    }),\n    description: z.string({\n      required_error: \"Description is required\",\n    }),\n  }),\n});\n\nconst updateExampleZodSchema = z.object({\n  body: z.object({\n    name: z.string().optional(),\n    description: z.string().optional(),\n  }),\n});\n\nexport const createExampleValidator = {\n  createExampleZodSchema,\n  updateExampleZodSchema,\n};\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodewithashim%2Feasy-express-server-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodewithashim%2Feasy-express-server-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodewithashim%2Feasy-express-server-cli/lists"}