{"id":31479364,"url":"https://github.com/ujjwalprajapati16/elib-api","last_synced_at":"2026-04-28T12:06:30.349Z","repository":{"id":315100102,"uuid":"1056632045","full_name":"Ujjwalprajapati16/elib-api","owner":"Ujjwalprajapati16","description":"elib-apis is a lightweight REST API built with Node.js, Express, and TypeScript. It supports user authentication (JWT), book CRUD, and file/image uploads via Cloudinary, backed by MongoDB.","archived":false,"fork":false,"pushed_at":"2025-12-02T10:20:56.000Z","size":124,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-05T05:42:04.885Z","etag":null,"topics":["cloudinary","express","jwt","mongodb","nodejs","rest-api","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/Ujjwalprajapati16.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-14T13:52:31.000Z","updated_at":"2025-12-02T10:20:59.000Z","dependencies_parsed_at":"2025-09-16T19:18:32.131Z","dependency_job_id":"24409803-2bda-4eab-ab3a-193509784850","html_url":"https://github.com/Ujjwalprajapati16/elib-api","commit_stats":null,"previous_names":["ujjwalprajapati16/elib-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Ujjwalprajapati16/elib-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ujjwalprajapati16%2Felib-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ujjwalprajapati16%2Felib-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ujjwalprajapati16%2Felib-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ujjwalprajapati16%2Felib-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ujjwalprajapati16","download_url":"https://codeload.github.com/Ujjwalprajapati16/elib-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ujjwalprajapati16%2Felib-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32379679,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T11:25:28.583Z","status":"ssl_error","status_checked_at":"2026-04-28T11:25:05.435Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cloudinary","express","jwt","mongodb","nodejs","rest-api","typescript"],"created_at":"2025-10-02T04:23:29.750Z","updated_at":"2026-04-28T12:06:30.343Z","avatar_url":"https://github.com/Ujjwalprajapati16.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# elib-apis\n\nA modern, lightweight REST API backend for elib — a simple ebook library. It provides user authentication, book management with uploads, user ratings, insights/analytics, likes, and pagination.\n\n- Runtime: Node.js (ESM), TypeScript\n- Framework: Express\n- Database: MongoDB (Mongoose)\n- Uploads: Cloudinary (cover images and files)\n- Auth: JWT (Bearer tokens)\n\n\n## Features\n- User registration and login with hashed passwords (bcrypt)\n- JWT-based authentication middleware\n- CRUD operations for books\n- File uploads (cover image required; ebook file optional) via Multer + Cloudinary\n- Book likes (toggle like/unlike)\n- User ratings with comments\n- Insights for authors (average rating, highest avg rated book, most recent rating)\n- Pagination for listing books\n- Centralized error handling\n- CORS configured for a single frontend origin\n\n## Database Schema\n\n```mermaid\nerDiagram\n    USER {\n        ObjectId _id PK\n        string name\n        string email\n        string password \"hashed\"\n        string role \"user | author\"\n        Date createdAt\n        Date updatedAt\n    }\n\n    BOOK {\n        ObjectId _id PK\n        string title\n        ObjectId authorFK \"Ref: User\"\n        string description\n        string genre\n        string coverImage \"URL\"\n        string file \"URL\"\n        number views\n        ObjectId[] likes \"Array of User IDs\"\n        DateWK createdAt\n        Date updatedAt\n    }\n\n    RATING {\n        ObjectId _id PK\n        ObjectId bookFK \"Ref: Book\"\n        ObjectId userFK \"Ref: User\"\n        number rating \"1-5\"\n        string comment\n        Date createdAt\n        Date updatedAt\n    }\n\n    %% Relationships\n    USER ||--o{ BOOK : \"authors (1:N)\"\n    USER ||--o{ RATING : \"writes (1:N)\"\n    BOOK ||--o{ RATING : \"has (1:N)\"\n    \n    %% Many-to-Many relationship handled via array of IDs in Book model\n    BOOK }|..|{ USER : \"liked by (M:N)\"\n```\n\n## Data Flow Diagram (DFD)\n\n```mermaid\ngraph TD\n    %% External Entities\n    Client[Client / User]\n    Cloudinary[Cloudinary Service]\n    MongoDB[(MongoDB Database)]\n\n    %% System Boundaries\n    subgraph \"elib-api Application\"\n        direction TB\n        \n        %% Routers\n        UserRouter[User Router]\n        BookRouter[Book Router]\n        RateRouter[Rating Router]\n        InsightRouter[Insight Router]\n        \n        %% Middleware\n        AuthMD[Auth Middleware]\n        UploadMD[Multer Upload]\n\n        %% Controllers\n        UserCtrl[User Controller]\n        BookCtrl[Book Controller]\n        RateCtrl[Rating Controller]\n        InsightCtrl[Insight Controller]\n    end\n\n    %% Data Flows\n    \n    %% Auth Flow\n    Client -- \"1. Register / Login\" --\u003e UserRouter\n    UserRouter --\u003e UserCtrl\n    UserCtrl -- \"Create/Find User\" --\u003e MongoDB\n    MongoDB -- \"User Data\" --\u003e UserCtrl\n    UserCtrl -- \"JWT Token\" --\u003e Client\n\n    %% Book Management Flow\n    Client -- \"2. Upload Book (Multipart)\" --\u003e AuthMD\n    AuthMD -- \"Validated User\" --\u003e UploadMD\n    UploadMD -- \"File Stream\" --\u003e BookRouter\n    BookRouter --\u003e BookCtrl\n    \n    BookCtrl -- \"Upload Cover/PDF\" --\u003e Cloudinary\n    Cloudinary -- \"File URLs\" --\u003e BookCtrl\n    \n    BookCtrl -- \"Save Book Meta + URLs\" --\u003e MongoDB\n    MongoDB -- \"Book Doc\" --\u003e BookCtrl\n    BookCtrl -- \"Response\" --\u003e Client\n\n    %% Rating Flow\n    Client -- \"3. Rate Book\" --\u003e AuthMD\n    AuthMD --\u003e RateRouter\n    RateRouter --\u003e RateCtrl\n    RateCtrl -- \"Create Rating\" --\u003e MongoDB\n\n    %% Insight/Analytics Flow\n    Client -- \"4. Request Analytics\" --\u003e InsightRouter\n    InsightRouter --\u003e InsightCtrl\n    InsightCtrl -- \"Aggregate Query\" --\u003e MongoDB\n    MongoDB -- \"Aggregated Stats\" --\u003e InsightCtrl\n    InsightCtrl -- \"JSON Report\" --\u003e Client\n```\n\n## Quick start\n\n```bash\n# 1) Install dependencies\nnpm install\n\n# 2) Configure environment (see .env example below)\n#    Create a .env file in the project root\n\n# 3) Start in dev (nodemon + ts-node)\nnpm run dev\n\n# Server will run at http://localhost:3000 by default\n```\n\n\n## Environment variables\nCreate a .env in the project root with the following keys:\n\n```bash\nPORT=3000\nNODE_ENV=development\nMONGO_URI=mongodb://localhost:27017/elib\nJWT_SECRET=replace-with-strong-secret\nFRONTEND_URL=http://localhost:3001\n\n# Cloudinary\nCLOUDINARY_CLOUD_NAME=your_cloud_name\nCLOUDINARY_API_KEY=your_api_key\nCLOUDINARY_API_SECRET=your_api_secret\n```\n\nGenerate a strong JWT secret (PowerShell, no output to console):\n\n```powershell\n$bytes = New-Object byte[] 64; [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes); $env:JWT_SECRET = [Convert]::ToBase64String($bytes); Add-Content -Path .env -Value \"JWT_SECRET=$env:JWT_SECRET\"\n```\n\n\n## Project structure (key files)\n- src/app.ts — Express app, routes, and middleware\n- src/config/config.ts — environment configuration\n- src/config/db.ts — Mongo connection helper\n- src/middlewares/authenticate.ts — JWT auth middleware\n- src/middlewares/globalErrorHandler.ts — error shape and handling\n- src/controllers/*, src/models/*, src/routes/* — feature modules\n- server.ts — app bootstrap\n\n\n## API Reference\nBase URL: http://localhost:3000\n\nError responses follow this shape:\n```json\n{\n  \"status\": \"error\",\n  \"statusCode\": 400,\n  \"message\": \"Human readable error message\"\n}\n```\n\nAuth\n- Authentication: Bearer \u003cJWT\u003e\n- Header: Authorization: Bearer \u003ctoken\u003e\n\n\nHealth/Welcome\n- GET /\n  - 200 OK\n  - Response:\n  ```json\n  { \"message\": \"Welcome to the elib APIs\" }\n  ```\n\n\nUsers\n\n1) Register\n- Method: POST\n- Path: /api/users/register\n- Body (JSON):\n  ```json\n  {\n    \"name\": \"Alice\",\n    \"email\": \"alice@example.com\",\n    \"password\": \"password123\",\n    \"role\": \"author\"    // or \"reader\"\n  }\n  ```\n- 201 Created\n- Response:\n  ```json\n  {\n    \"accessToken\": \"\u003cjwt\u003e\",\n    \"user\": { \"name\": \"Alice\", \"email\": \"alice@example.com\", \"role\": \"author\" }\n  }\n  ```\n\n2) Login\n- Method: POST\n- Path: /api/users/login\n- Body (JSON):\n  ```json\n  {\n    \"email\": \"alice@example.com\",\n    \"password\": \"password123\"\n  }\n  ```\n- 200 OK\n- Response:\n  ```json\n  {\n    \"accessToken\": \"\u003cjwt\u003e\",\n    \"user\": { \"name\": \"Alice\", \"email\": \"alice@example.com\", \"role\": \"author\" }\n  }\n  ```\n\n\nBooks\nAll endpoints under /api/books. Some actions require Authorization header.\n\nFields:\n- title: string (required on create)\n- genre: string (required on create)\n- description: string (required on create)\n- coverImage: file (required on create; form key: coverImage)\n- file: file (optional; form key: file)\n\n1) Create book\n- Method: POST\n- Path: /api/books/add\n- Auth: Required (Bearer token)\n- Content-Type: multipart/form-data\n- Form fields:\n  - title: string\n  - genre: string\n  - description: string\n  - coverImage: file (required)\n  - file: file (optional)\n- 201 Created\n- Response:\n  ```json\n  {\n    \"message\": \"Book created successfully\",\n    \"book\": {\n      \"_id\": \"...\",\n      \"title\": \"...\",\n      \"genre\": \"...\",\n      \"description\": \"...\",\n      \"coverImage\": \"https://...\",\n      \"file\": \"https://...\" | null,\n      \"author\": { \"_id\": \"...\", \"name\": \"...\" },\n      \"createdAt\": \"...\",\n      \"updatedAt\": \"...\"\n    }\n  }\n  ```\n\n2) Update book\n- Method: PATCH\n- Path: /api/books/update/:Bookid\n- Auth: Required\n- Content-Type: multipart/form-data\n- Any of the following fields can be sent:\n  - title, genre, description, coverImage (file), file (file)\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Book updated successfully\",\n    \"book\": { /* updated book */ }\n  }\n  ```\n\n3) List books with pagination\n- Method: GET\n- Path: /api/books/\n- Query params:\n  - page: number (default 1)\n  - limit: number (default 10)\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Books listed successfully\",\n    \"books\": [ /* books */ ],\n    \"pagination\": {\n      \"totalBooks\": 42,\n      \"currentPage\": 1,\n      \"totalPages\": 5,\n      \"pageSize\": 10\n    }\n  }\n  ```\n\n4) Book details (increments view count, returns ratings and average)\n- Method: GET\n- Path: /api/books/:Bookid\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Book details fetched successfully\",\n    \"book\": { /* book incl. updated views */ },\n    \"ratings\": [\n      { \"_id\": \"...\", \"rating\": 5, \"comment\": \"...\", \"user\": { \"name\": \"...\" } }\n    ],\n    \"averageRating\": \"4.50\",\n    \"totalRatings\": 12\n  }\n  ```\n\n5) Delete book (also deletes associated ratings)\n- Method: DELETE\n- Path: /api/books/:Bookid\n- Auth: Required (must be author)\n- 200 OK\n- Response:\n  ```json\n  { \"message\": \"Book and related ratings deleted successfully\" }\n  ```\n\n6) Toggle like/unlike a book\n- Method: PATCH\n- Path: /api/books/:Bookid/like\n- Auth: Required\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Book liked successfully\",\n    \"likesCount\": 3,\n    \"book\": { /* book */ }\n  }\n  ```\n  or\n  ```json\n  {\n    \"message\": \"Book unliked successfully\",\n    \"likesCount\": 2,\n    \"book\": { /* book */ }\n  }\n  ```\n\n\nRatings\nBase: /api/rate\n\n1) Add rating to a book\n- Method: POST\n- Path: /api/rate/:BookId\n- Auth: Required\n- Body (JSON):\n  ```json\n  { \"rating\": 5, \"comment\": \"Excellent read\" }\n  ```\n- 200 OK\n- Response:\n  ```json\n  { \"message\": \"Rating added successfully\" }\n  ```\n\n2) Delete a rating\n- Method: DELETE\n- Path: /api/rate/:BookId/:ratingId\n- Auth: Required\n- 200 OK\n- Response:\n  ```json\n  { \"message\": \"Rating deleted successfully\" }\n  ```\n\n3) Get ratings for a book\n- Method: GET\n- Path: /api/rate/book/:BookId\n- Auth: Required\n- 200 OK\n- Response:\n  ```json\n  [ { \"_id\": \"...\", \"rating\": 5, \"comment\": \"...\", \"book\": \"...\", \"user\": \"...\" } ]\n  ```\n\n4) Get ratings for all books by an author\n- Method: GET\n- Path: /api/rate/author/:AuthorId\n- Auth: Required\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"All ratings for author's books fetched successfully\",\n    \"totalRatings\": 10,\n    \"ratings\": [\n      {\n        \"_id\": \"...\",\n        \"rating\": 4,\n        \"comment\": \"...\",\n        \"createdAt\": \"...\",\n        \"book\": { \"_id\": \"...\", \"title\": \"...\" },\n        \"reviewer\": { \"_id\": \"...\", \"name\": \"...\", \"email\": \"...\" }\n      }\n    ]\n  }\n  ```\n\n\nInsights (author analytics)\nBase: /api/insight\n\n1) Average rating for an author's books\n- Method: GET\n- Path: /api/insight/averageRating/:authorId\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Average rating fetched successfully\",\n    \"averageRating\": 4.2,\n    \"totalRatings\": 57\n  }\n  ```\n\n2) Highest average rated book for an author\n- Method: GET\n- Path: /api/insight/heighestRatedBook/:authorId\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Highest average rated book fetched successfully\",\n    \"highestAvgRatedBook\": \"\u003cbookId\u003e\",\n    \"averageRating\": 4.8\n  }\n  ```\n\n3) Most recent rating for an author's books\n- Method: GET\n- Path: /api/insight/recentRating/:authorId\n- 200 OK\n- Response:\n  ```json\n  {\n    \"message\": \"Most recent rating fetched successfully\",\n    \"recentRating\": {\n      \"bookTitle\": \"...\",\n      \"rating\": 5,\n      \"comment\": \"...\",\n      \"createdAt\": \"...\",\n      \"reviewerName\": \"...\",\n      \"reviewerEmail\": \"...\"\n    }\n  }\n  ```\n\n\n## Development notes\n- ESM + TypeScript are configured with NodeNext in tsconfig.json and \"type\": \"module\" in package.json.\n- JWT tokens include sub, email, and role, and expire in 7 days by default.\n- Error handler returns a consistent JSON shape and includes stack traces only in development.\n- CORS is restricted to FRONTEND_URL.\n\n\n## Scripts\n```json\n{\n  \"dev\": \"nodemon server.ts\"\n}\n```\n\n\n## License\nISC © Ujjwal Prajapati\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fujjwalprajapati16%2Felib-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fujjwalprajapati16%2Felib-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fujjwalprajapati16%2Felib-api/lists"}