{"id":27462193,"url":"https://github.com/namtndev/be_deploy_learning","last_synced_at":"2025-04-15T21:59:46.541Z","repository":{"id":279934000,"uuid":"940477942","full_name":"NamTNDEV/be_deploy_learning","owner":"NamTNDEV","description":null,"archived":false,"fork":false,"pushed_at":"2025-02-28T10:48:47.000Z","size":67,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T21:59:41.385Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/NamTNDEV.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":"2025-02-28T08:46:57.000Z","updated_at":"2025-02-28T10:48:50.000Z","dependencies_parsed_at":"2025-02-28T16:11:35.788Z","dependency_job_id":"9f40333e-1f2a-4608-9c5c-40c46b8540ae","html_url":"https://github.com/NamTNDEV/be_deploy_learning","commit_stats":null,"previous_names":["namtndev/be_deploy_learning"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NamTNDEV%2Fbe_deploy_learning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NamTNDEV%2Fbe_deploy_learning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NamTNDEV%2Fbe_deploy_learning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NamTNDEV%2Fbe_deploy_learning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NamTNDEV","download_url":"https://codeload.github.com/NamTNDEV/be_deploy_learning/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249161118,"owners_count":21222470,"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":[],"created_at":"2025-04-15T21:59:46.051Z","updated_at":"2025-04-15T21:59:46.534Z","avatar_url":"https://github.com/NamTNDEV.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Giới thiệu về API\n\nĐây là backend API cho dự án Next.js Free. Chủ đề là một Shop bán hàng đơn giản với với các chức năng cơ bản:\n\n- Authentication: Login, Register, Logout\n- Account: Get thông tin cá nhân, Cập nhật thông tin cá nhân\n- Product: Thêm, Sửa, Xóa sản phẩm, Lấy danh sách sản phẩm\n- Media: Upload hình ảnh\n- Test API\n\n\u003e Lưu ý quan trọng: thỉnh thoảng nên pull code mới từ github repo của mình về, vì đôi khi mình có cập nhật logic API trong quá trình mình quay video\n\n\u003e Trong file `server/.env` có thuộc tính `COOKIE_MODE`, hãy set `true` nếu bạn muốn dùng cookie cho việc authentication ở server\n\n## Công nghệ sử dụng\n\nNode.js + Fastify + Sqlite\n\n## Cài đặt\n\nChỉ cần clone repository này về máy, cd vào thư mục, cài đặt các packages và chạy lệnh `npm run dev` là được\n\n```bash\ncd server\nnpm i\nnpm run dev\n```\n\nTrong trường hợp muốn chạy production, chạy lệnh\n\n```bash\nnpm run build\nnpm run start\n```\n\nMuốn xem thông tin database, chỉ cần mở Prisma Studio lên bằng câu lệnh\n\n```bash\nnpx prisma studio\n```\n\nNó sẽ chạy ở url [http://localhost:5555](http://localhost:5555)\n\nTrong source code có chứa file `.env` để config, trong file này bạn có thể đổi port cho API backend, mặc định là port `4000`\n\nKhi upload thì hình ảnh sẽ được đi vào thư mục `/uploads` trong folder `server`\n\n## Format response trả về\n\nĐịnh dạng trả về là JSON, và luôn có trường `message`, ngoài ra có thể sẽ có trường `data` hoặc `errors`\n\nĐây là ví dụ về response trả về khi thành công\n\n```json\n{\n  \"data\": {\n    \"id\": 2,\n    \"name\": \"Iphone 11\",\n    \"price\": 20000000,\n    \"description\": \"Mô tả cho iphone 11\",\n    \"image\": \"http://localhost:4000/static/bec024f9ea534b7fbf078cb5462b30aa.jpg\",\n    \"createdAt\": \"2024-03-11T03:51:14.028Z\",\n    \"updatedAt\": \"2024-03-11T03:51:14.028Z\"\n  },\n  \"message\": \"Tạo sản phẩm thành công!\"\n}\n```\n\nTrong trường hợp lỗi thì nếu lỗi liên quan đến việc body gửi lên không đúng định dạng thì server sẽ trả về lỗi `422` và thông tin lỗi như sau\n\nVí dụ dưới đây body thiếu trường `price`\n\n```json\n{\n  \"message\": \"A validation error occurred when validating the body...\",\n  \"errors\": [\n    {\n      \"code\": \"invalid_type\",\n      \"expected\": \"number\",\n      \"received\": \"undefined\",\n      \"path\": [\"price\"],\n      \"message\": \"Required\",\n      \"field\": \"price\"\n    }\n  ],\n  \"code\": \"FST_ERR_VALIDATION\",\n  \"statusCode\": 422\n}\n```\n\nTrong trường hợp lỗi khác, server sẽ trả về lỗi trong trường `message`, ví dụ\n\n```json\n{\n  \"message\": \"Không tìm thấy dữ liệu!\",\n  \"statusCode\": 404\n}\n```\n\n## Chi tiết các API\n\nMặc định API sẽ chạy ở địa chỉ [http://localhost:4000](http://localhost:4000), các bạn nào muốn đổi port thì vào file `.env` để thay đổi port\n\nVới các API POST, PUT thông thường thì body gửi lên phải là JSON, và phải có header `Content-Type: application/json`.\n\nĐặc biệt API upload hình ảnh thì phải gửi dưới dạng `form-data`\n\nAPI xác thực người dùng thông qua session token, session token này là một JWT, secret key JWT này sẽ được lưu trong file `.env` và được sử dụng để tạo và verify token\n\nĐối với các API cần xác thực người dùng như bên cụm API về `Account` thì bạn có 2 cách để server biết bạn là ai:\n\n1. Gửi session token thông qua header `sessionToken`\n2. Để cookie tự gửi lên (vì khi gọi api login hay register thì server sẽ set cookie cho bạn)\n\n### Test API: muốn biết api có hoạt động không\n\n- `GET /test`: Trả về message nghĩa là API hoạt động\n\n### Authentication\n\n- `POST /auth/register`: Đăng ký tài khoản\n\n```json\n{\n  \"name\": \"Dư Thanh Được\",\n  \"email\": \"user@gmail.com\",\n  \"password\": \"123123\",\n  \"confirmPassword\": \"123123\"\n}\n```\n\nKhi register, login thành công thì server sẽ tự động set cookie cho domain là `localhost` với tên là `sessionToken`\n\n- `POST /auth/login`: Đăng nhập\n\n```json\n{\n  \"email\": \"user@gmail.com\",\n  \"password\": \"123123\"\n}\n```\n\n- `POST /auth/slide-session`: Tăng thời gian hết hạn của session token. Body là `{}`\n\nYêu cầu cần phải gửi lên `sessionToken` (qua cookie hay Authorization header là tùy mode của bạn)\n\n- `POST /auth/logout`: Đăng xuất với body là `{}`, yêu cầu xác thực\n\nKhi logout thì server của mình sẽ tự động remove cookie `sessionToken` đi\n\n### Account: Cần xác thực\n\n- `GET /account/me`: Lấy thông tin cá nhân\n- `PUT /account/me`: Cập nhật thông tin cá nhân\n\n```json\n{\n  \"name\": \"Dư Thanh Được\"\n}\n```\n\n### Media: Cần xác thực\n\n- `POST /media/upload`: Upload hình ảnh\n\nBody gửi dưới dạng `form-data`, key là `file`, value là file hình ảnh.\n\nAPI này mình cũng làm nhanh nên backend không có validate ảnh có đúng định dạng gì không, nên các bạn upload cho đúng hình ảnh là được.\n\nGiới hạn file upload là 10MB\n\n### Products\n\n- `GET /products`: Lấy danh sách sản phẩm\n- `POST /products`: Thêm sản phẩm (Cần xác thực)\n  Body định dạng sau\n\n  ```json\n  {\n    \"name\": \"Iphone 11\",\n    \"price\": 20000000,\n    \"description\": \"Mô tả cho iphone 11\",\n    \"image\": \"http://localhost:4000/static/bec024f9ea534b7fbf078cb5462b30aa.jpg\"\n  }\n  ```\n\n- `PUT /products/:id`: Sửa sản phẩm, body tương tự như thêm sản phẩm (Cần xác thực)\n- `DELETE /products/:id`: Xóa sản phẩm (Cần xác thực)\n- `GET /products/:id`: Lấy chi tiết sản phẩm\n\n## Setup nhanh postman\n\nMình có lưu 1 file là `NextJs Free API.postman_collection.json` trong thư mục `server`, các bạn chỉ cần import file này vào Postman là có ngay collection của mình. Tiếp theo các bạn tạo 1 environment mới, và set biến `host` là `http://localhost:4000`, và chọn environment này khi gọi API là xong.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnamtndev%2Fbe_deploy_learning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnamtndev%2Fbe_deploy_learning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnamtndev%2Fbe_deploy_learning/lists"}