{"id":20113757,"url":"https://github.com/zrwusa/bunny-rest","last_synced_at":"2025-09-21T01:32:33.002Z","repository":{"id":181373278,"uuid":"441692306","full_name":"zrwusa/bunny-rest","owner":"zrwusa","description":"Typescript + Express + Docker + GraphQL  + PostgreSQL + MongoDB + Redis + Nginx + Swagger + Pino + Prom-client + Prometheus Boilerplate","archived":false,"fork":false,"pushed_at":"2023-08-03T01:21:20.000Z","size":1748,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-03T18:21:41.446Z","etag":null,"topics":["boilerplate","docker","express","graphql","mongodb","nginx","pino","postgresql","prometheus","redis","swagger","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/zrwusa.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2021-12-25T14:10:06.000Z","updated_at":"2024-07-20T02:48:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"f873ddc7-23e5-4bed-aae7-02fb1ed82be2","html_url":"https://github.com/zrwusa/bunny-rest","commit_stats":null,"previous_names":["zrwusa/bunny-rest"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zrwusa/bunny-rest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrwusa%2Fbunny-rest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrwusa%2Fbunny-rest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrwusa%2Fbunny-rest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrwusa%2Fbunny-rest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zrwusa","download_url":"https://codeload.github.com/zrwusa/bunny-rest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrwusa%2Fbunny-rest/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276183680,"owners_count":25599223,"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","status":"online","status_checked_at":"2025-09-20T02:00:10.207Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","docker","express","graphql","mongodb","nginx","pino","postgresql","prometheus","redis","swagger","typescript"],"created_at":"2024-11-13T18:25:45.436Z","updated_at":"2025-09-21T01:32:32.591Z","avatar_url":"https://github.com/zrwusa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Architecture\n\n\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\u003cth\u003eFeature\u003c/th\u003e\u003cth\u003eDesc\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003eDevelopment, test, production environment\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eRESTFul \u0026 API protocol\u003c/td\u003e\u003ctd\u003eStandard RESTFul API with a protocol structured encapsulated response\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eGraphQL\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eDocker\u003c/td\u003e\u003ctd\u003eContainers manager\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ePostgres\u003c/td\u003e\u003ctd\u003eRDB\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eMongoDB\u003c/td\u003e\u003ctd\u003eNoSQL\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eRedis\u003c/td\u003e\u003ctd\u003eMemory cache \u0026 session storage\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eNginx\u003c/td\u003e\u003ctd\u003eLoad Balancing\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eI18n\u003c/td\u003e\u003ctd\u003eSupports translation\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eSwagger\u003c/td\u003e\u003ctd\u003eAPI docs\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ePino\u003c/td\u003e\u003ctd\u003eLogger\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ePrometheus,Prom-client\u003c/td\u003e\u003ctd\u003eAPI performance monitoring with Prometheus\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eMailer\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n## Standard RESTFul API with a protocol structured encapsulated response\n\n```\n{\n    \"http\": {\n        \"code\": 200,\n        \"message\": \"OK\",\n        \"description\": \"indicates that the request has succeeded.\"\n    },\n    \"bizLogic\": {\n        \"code\": \"APP_ORDER_0060\",\n        \"message\": \"Associate order with products success\"\n    },\n    \"resData\": {\n        \"id\": \"95da24dd-9200-4e87-90b4-bff84e52011f\",\n        \"create_at\": \"2023-07-19T16:27:29.429Z\",\n        \"update_at\": \"2023-07-19T16:27:29.429Z\",\n        \"price\": \"56936.52\",\n        \"address\": \"test address\",\n        \"amount\": 1,\n        \"products\": [\n            {\n                \"id\": \"7f4b18ad-1621-45f3-a572-9826a9071f9a\",\n                \"create_at\": \"2023-07-19T16:26:55.667Z\",\n                \"update_at\": \"2023-07-19T16:27:14.618Z\",\n                \"title\": \"Canon EOS 1500D DSLR Camera with 18-55mm Lens\",\n                \"description\": \"Designed for first-time DSLR owners who want impressive results straight out of the box, capture those magic moments no matter your level with the EOS 1500D. With easy to use automatic shooting modes, large 24.1 MP sensor, Canon Camera Connect app integration and built-in feature guide, EOS 1500D is always ready to go.\",\n                \"price\": \"1699.99\",\n                \"image\": \"https://i.imgur.com/QlRphfQ.jpg\"\n            }\n        ]\n    }\n}\n```\n\n## Standard validation response \n\n```\n{\n    \"http\": {\n        \"code\": 400,\n        \"message\": \"Bad Request\",\n        \"description\": \"indicates that the server cannot or will not process the request because the received syntax is invalid, nonsensical, or exceeds some limitation on what the server is willing to process.\"\n    },\n    \"bizLogic\": {\n        \"code\": \"AUTH_0049\",\n        \"message\": \"Request validated failed\",\n        \"payload\": [\n            {\n                \"code\": \"invalid_type\",\n                \"expected\": \"string\",\n                \"received\": \"undefined\",\n                \"path\": [\n                    \"body\",\n                    \"password\"\n                ],\n                \"message\": \"Password is required\"\n            }\n        ]\n    },\n    \"resData\": null\n}\n```\n\nModular Architecture: Divide the entire system into multiple modules or services, with each module responsible for specific functionalities. This modular design improves the maintainability and scalability of the system. The frontend and backend can be developed and deployed as separate modules.\n\nMicroservices Architecture: Further divide the system into independent microservices. Each microservice can be deployed, scaled, and maintained independently, providing specific business functionalities. Docker containerization can simplify the deployment and management of microservices.\n\nLoad Balancing: Use load balancing to distribute traffic and requests, ensuring the system can handle a high volume of concurrent requests. Nginx can serve as a reverse proxy server for load balancing, distributing requests to multiple backend service instances.\n\nCaching: Utilize caching to enhance system performance and response time. Redis can be used as a caching server to store frequently accessed data and alleviate the load on the database.\n\nDatabase Selection: Choose the appropriate database based on your business requirements. PostgreSQL and MongoDB are suitable for structured and document-oriented data storage, respectively. You can select which database(s) to use or employ a combination based on your specific needs.\n\nAsynchronous Task Processing: Employ message queues or task queues to handle asynchronous tasks such as sending emails, processing background tasks, etc. RabbitMQ or Kafka can serve as message queues, helping decouple system components.\n\nSecurity: Ensure the system's security by implementing mechanisms such as authentication, authorization, and data encryption. Use JWT (JSON Web Token) or other authentication mechanisms to verify user identities, and employ HTTPS for data encryption during transmission.\n\nMonitoring and Logging: Utilize monitoring tools (e.g., Prometheus) and logging libraries (e.g., Pino) to track system performance, errors, and log information. These tools assist in quickly diagnosing and resolving issues.\n\nHigh Availability and Fault Tolerance: Improve system availability by designing redundant and backup architectures. Container orchestration tools like Kubernetes can aid in managing and automating container deployment and scaling.\n\nAutomated Deployment and Continuous Integration/Continuous Delivery (CI/CD): Employ tools like Jenkins, GitLab CI/CD, or Travis CI to automate deployment and establish a CI/CD pipeline, streamlining development, testing, and deployment processes.\n\n# Dependencies \n\n\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\u003cth\u003eApplication\u003c/th\u003e\u003cth\u003eVersion\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003eDocker\u003c/td\u003e\u003ctd\u003eEngine: 24.0.2\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eNode.js\u003c/td\u003e\u003ctd\u003ev19.9.0\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n# Development\n\n## develop\n\n### prepare, create .env.development file, then config it\n\n```dotenv \n      - NODE_ENV=development\n      - PORT=8080\n      - MONGO_DB_URI=mongodb://root_dev:root_dev_password@mongo-dev:27017/bunny_rest_dev?authSource=admin\n      - SALT_WORK_FACTOR=10\n      - ACCESS_TOKEN_TTL=0.1m\n      - REFRESH_TOKEN_TTL=60m\n      - METRICS_PORT=9090\n      - REDIS_URI=redis://@redis-dev:6379\n      - POSTGRES_URI=postgresql://postgres:root_dev_password@postgres-dev:5432/bunny_rest_dev\n      - APOLLO_PORT=7070\n      - CORS_ORIGINS=http://localhost:3000,http://localhost:3001\n      - OPEN_API_URL=http://example.com\n```\n\n### start\n\n```shell script\nyarn install\nyarn dev:prepare\nyarn dev\n```\n\n### stop\n\n```shell script\nyarn dev:unprepare\n```\n\n\n## Docker development\n\n### start(all services including Bunny-rest, Swagger, prom-client, Nginx, Postgres, MongoDB, Redis)\n\nAfterward, you can write code locally and have the changes automatically synced to the Docker containers. This approach is designed specifically for debugging issues that cannot be replicated in the local environment, for example, when the testing environment has complete test data and you need to debug in that environment. However, for regular local development, it is still recommended to use the first approach where Docker is used solely as containers for the dependent services while the local environment serves as the development environment.\n\n```shell script\nyarn dev:all-in-docker\n```\n\n### start(not including Nginx as loading balance, neither bunny-rest)\n\n```shell script\nyarn dev:prepare\nyarn dev\n```\n\n# Architecture principles\n\nUnderstand the optimization process, but don't optimize prematurely\n\n## Separation of Concern\n\n## Feature Encapsulation\n\nThis means that we group the files related to a single feature together. This has helped me to reuse my codebase across\nprojects. Let's face it we do not write everything again and again but rather copy-paste the code once perfected to all\nthe required places. If all the things are clubbed together then it's super easy to achieve this safely. This also helps\nin building a logical structure in mind to find a particular file while writing code that needs it as a dependency.\n\n## Better Error Handling\n\nThis is very important for the application to be consistent with errors and the corresponding API responses. So,\nadopting the separation of concern principle and also the uniformity in the API responses.\n\n## Better Response Handling\n\nThe same reason as provided in the above error handling example is also valid for the response handling.\n\n## Better Promise Management\n\nThe callback is replaced by Promises and now the Promise chain is replaced by the async/await. This greatly enhances the\ncoding experience. One problem with this implementation is to write the ugly try/catch block.\n\u003c!--## Robust Unit Tests\nThe primary purpose of Unit-test is not to detect incorrect grammar but to validate behaviors of logics.--\u003e\n\n## Avoiding side effects, always keep functional purity\n\n\u003c!--## Simple Deployability\nDockerfile and docker-compose.yml to simplify the deployment of the application. It is also possible to manually deploy the application.--\u003e\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzrwusa%2Fbunny-rest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzrwusa%2Fbunny-rest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzrwusa%2Fbunny-rest/lists"}