{"id":48820450,"url":"https://github.com/timothyrushing/nestjs-tweets-microservice","last_synced_at":"2026-04-14T14:33:52.592Z","repository":{"id":312645057,"uuid":"1048172102","full_name":"timothyrushing/nestjs-tweets-microservice","owner":"timothyrushing","description":"NestJS based microservice for tweeting system, users, auth and tweets","archived":false,"fork":false,"pushed_at":"2025-09-01T03:37:25.000Z","size":326,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-01T06:29:22.520Z","etag":null,"topics":["authentication","nestjs","nodejs","tweets","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/timothyrushing.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-01T03:36:20.000Z","updated_at":"2025-09-01T03:38:29.000Z","dependencies_parsed_at":"2025-09-01T06:29:25.485Z","dependency_job_id":"c35571cf-6f54-4298-afdf-85aec6dd72eb","html_url":"https://github.com/timothyrushing/nestjs-tweets-microservice","commit_stats":null,"previous_names":["timothyrushing/nestjs-tweets-microservice"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/timothyrushing/nestjs-tweets-microservice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timothyrushing%2Fnestjs-tweets-microservice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timothyrushing%2Fnestjs-tweets-microservice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timothyrushing%2Fnestjs-tweets-microservice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timothyrushing%2Fnestjs-tweets-microservice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timothyrushing","download_url":"https://codeload.github.com/timothyrushing/nestjs-tweets-microservice/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timothyrushing%2Fnestjs-tweets-microservice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31801459,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T11:13:53.975Z","status":"ssl_error","status_checked_at":"2026-04-14T11:13:53.299Z","response_time":153,"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":["authentication","nestjs","nodejs","tweets","typescript"],"created_at":"2026-04-14T14:33:48.434Z","updated_at":"2026-04-14T14:33:52.575Z","avatar_url":"https://github.com/timothyrushing.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simple tweet backend system\n\n## Description\n\nA simple tweet backend system written in Typescript + nestjs.\nIncludes user and tweet management.\nThe system is designed as a microservice with a distributed database.\n\n### Architecture Overview\n1. API Gateway (api-gateway):\n    * Handles all incoming HTTP requests\n    * Responsible for JWT authentication and initial RBAC checks\n    * Routes requests to the appropriate microservice\n    * Exposes the RESTful API\n    \n2. Auth Service (auth-service):\n    * Manages user credentials data (hashed password, user role)\n    * Handles password hashing, jwt token signing and validation\n    * Has its own database\n\n3. User Service (users-service):\n    * Manages user data (creation, retrieval, update, deletion)\n    * Handles user information, the main primary key for user credentials, and tweets\n    * Has its own database\n\n4. Tweets Service (tweets-service):\n    * Manages tweet data (creation, retrieval, update, deletion)\n    * Performs ownership checks for tweet modifications\n    * Has its own database\n\nCommunication: The API Gateway will communicate with the Auth, User and Tweet services using TCP (NestJS's default microservice transport, easy for local dev).\n\n## Installation\n\n1. copy the `/.env.sample` as `/.env`\n2. update the `/.env`\n3. run the `start.sh` script\n4. (Optional) run `npm run cli create:admin -- -u ${username} -p ${strongPassword}` to create first admin user\n5. have fun\n\n## Test\n\n```bash\n# unit tests\n$ npm run test\n\n# e2e tests (not ready)\n$ npm run test:e2e\n\n# test coverage\n$ npm run test:cov\n```\n\n## Api endpoints\n\n**User Object Structure (shared):**\n\n| Field       | Type   | Description                                                     |\n|-------------|--------|-----------------------------------------------------------------|\n| id          | string | Unique identifier for the user (derived from `idHash`).         |\n| username    | string | The user's username.                                            |\n| firstName   | string | The user's first name.                                          |\n| lastName    | string | The user's last name.                                           |\n| dateOfBirth | Date   | The user's date of birth (ISO 8601 format, e.g., \"YYYY-MM-DD\"). |\n| role        | string | The user's role (e.g., \"USER\", \"ADMIN\").                        |\n| createdAt   | Date   | Timestamp indicating when the user account was created.         |\n| updatedAt   | Date   | Timestamp indicating when the user account was last updated.    |\n\n### root\n\n1. **POST /register**\n    * Registers a new user\n\n    Request:\n    \n    | Field       | Type   | Description                                                                             | \n    |-------------|--------|-----------------------------------------------------------------------------------------| \n    | username    | string | User's desired username. Must start with a letter and contain only letters and numbers. | \n    | password    | string | User's password. Must meet strong password requirements.                                | \n    | firstName   | string | User's first name.                                                                      | \n    | lastName    | string | User's last name.                                                                       | \n    | dateOfBirth | Date   | User's date of birth. Must be between 14 and 70 years old.                              |\n    \n    Response:\n    \n    | Field       | Type   | Description                                                  | \n    |-------------|--------|--------------------------------------------------------------| \n    | id          | string | Unique identifier for the registered user.                   | \n    | username    | string | The registered user's username.                              | \n    | firstName   | string | The registered user's first name.                            | \n    | lastName    | string | The registered user's last name.                             | \n    | dateOfBirth | Date   | The registered user's date of birth.                         | \n    | role        | string | The registered user's role (e.g., \"USER\", \"ADMIN\").          | \n    | createdAt   | Date   | Timestamp indicating when the user account was created.      | \n    | updatedAt   | Date   | Timestamp indicating when the user account was last updated. | \n\n2. **POST /login**\n    * Authenticates an existing user \n\n    Request:\n    \n    | Field    | Type   | Description                                                                     | \n    |----------|--------|---------------------------------------------------------------------------------| \n    | username | string | User's username. Must start with a letter and contain only letters and numbers. | \n    | password | string | User's password.                                                                |\n    \n    Response:\n    \n    | Field | Type   | Description                         | \n    |-------|--------|-------------------------------------| \n    | user  | User   | Object containing user information. | \n    | token | string | JWT token for authentication.       |\n    \n\n### users\n\n1. **GET /users**\n    * Retrieves paginated list of users \n    * Requires authentication (valid JWT)\n    * Requires **ADMIN** role.\n\n    Query Parameters:\n\n    | Field | Type   | Optional | Default | Min | Max | Description                                       |\n    |-------|--------|----------|---------|-----|-----|---------------------------------------------------|\n    | page  | number | Yes      | 1       | 1   | -   | The page number to retrieve.                      |\n    | limit | number | Yes      | 10      | 1   | 100 | The number of users to retrieve per page.         |\n\n    Response: \n\n    | Field        | Type       | Description                                                               |\n    |--------------|------------|---------------------------------------------------------------------------|\n    | data         | User Array | An array of user objects for the current page.                            |\n    | totalItems   | number     | Total number of users available across all pages.                         |\n    | itemCount    | number     | Number of users in the `data` array for the current page.                 |\n    | itemsPerPage | number     | The number of items requested per page (matches the `limit` query param). |\n    | totalPages   | number     | Total number of pages available.                                          |\n    | currentPage  | number     | The current page number (matches the `page` query param).                 |\n\n2. **POST /users**\n    * Creates a new user. This endpoint can be used by an administrator to create users with either 'USER' or 'ADMIN' roles.\n    * Requires authentication (valid JWT)\n    * Requires **ADMIN** role.\n\n    Request:\n\n    | Field       | Type                       | Optional | Description                                                                                                                                                                                                         |\n    |-------------|----------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n    | username    | string                     | No       | User's desired username. Must start with a letter and can only contain letters and numbers. (e.g., \"newuser123\")                                                                                                    |\n    | password    | string                     | No       | User's password. Must be a strong password (typically requires a mix of uppercase, lowercase, numbers, and special characters, with a minimum length - specific rules depend on `@IsStrongPassword` configuration). |\n    | firstName   | string                     | No       | User's first name. Cannot be blank.                                                                                                                                                                                 |\n    | lastName    | string                     | No       | User's last name. Cannot be blank.                                                                                                                                                                                  |\n    | role        | string (Enum: `EUserRole`) | No       | The role to assign to the new user. Must be a valid role from `EUserRole` (e.g., \"USER\", \"ADMIN\").                                                                                                                  |\n    | dateOfBirth | string (ISO Date)          | No       | User's date of birth in `YYYY-MM-DD` format. The user must be between 14 and 70 years old.                                                                                                                          |\n\n    Response:\n\n    ref to User Object\n3. **GET /users/:id**\n    * Retrieves the profile information for a specific user by their unique hashed ID\n    * Requires authentication (valid JWT)\n    * Requires **ADMIN** / **USER** role.\n\n    Path Parameters:\n\n    | Parameter | Type   | Required | Description                                          |\n    |-----------|--------|----------|------------------------------------------------------|\n    | id        | string | Yes      | The unique hashed identifier (`idHash`) of the user. |\n\n    Response:\n\n    ref to User Object\n4. **PUT /users/:id**\n    * Updates the profile information for a specific user by their unique hashed ID\n    * Requires authentication (valid JWT).\n    * At least one field (`firstName`, `lastName`, or `dateOfBirth`) must be provided in the request body.\n    * Requires **ADMIN** / **USER** role.\n        * **ADMINS:** Can update any user.\n        * **USERS (Tweet Owners):** Can only update their own user.\n    \n    Path Parameters:\n\n    | Parameter | Type   | Required | Description                                                    |\n    |-----------|--------|----------|----------------------------------------------------------------|\n    | id        | string | Yes      | The unique hashed identifier (`idHash`) of the user to update. |\n\n    Request: \n\n    | Field       | Type              | Optional | Description                                                                                              |\n    |-------------|-------------------|----------|----------------------------------------------------------------------------------------------------------|\n    | firstName   | string / null     | Yes      | User's updated first name. Can be set to `null` to clear it (if allowed by the backend logic).           |\n    | lastName    | string            | Yes      | User's updated last name.                                                                                |\n    | dateOfBirth | string (ISO Date) | Yes      | User's updated date of birth in `YYYY-MM-DD` format. Must adhere to age constraints (14-70 years old).   |\n\n    Response:\n\n    ref to User Object\n5. **DELETE /users/:id**\n    * Soft deletes a user by their unique hashed ID. This typically means the user is marked as inactive or deleted in the database but not permanently removed\n    * Also emit event to soft all the related **tweet** by the user\n    * Requires **ADMIN** role\n\n    Path Parameters:\n\n    | Parameter | Type   | Required | Description                                                    |\n    |-----------|--------|----------|----------------------------------------------------------------|\n    | id        | string | Yes      | The unique hashed identifier (`idHash`) of the user to delete. |\n\n### Tweet\n**Tweet Object Structure (shared):**\n\n| Field     | Type             | Description                                             |\n|-----------|------------------|---------------------------------------------------------|\n| id        | string           | Unique identifier for the tweet.                        |\n| title     | string           | The title of the tweet.                                 |\n| content   | string           | The main content of the tweet.                          |\n| updatedAt | Date             | Timestamp indicating when the tweet was last updated.   |\n| createdAt | Date             | Timestamp indicating when the tweet was created.        |\n| own       | TweetOwnerObject | Object containing information about the tweet's author. |\n\n**Own Object Structure (shared):**\n\n| Field    | Type   | Description                                            |\n|----------|--------|--------------------------------------------------------|\n| userId   | string | The unique user hashed identifier of the tweet author. |\n| username | string | The username of the tweet author.                      |\n\n1. **GET /tweets**\n    * Retrieves a paginated list of all tweets\n    * Requires authentication (any logged-in user can access this).\n\n    Query Parameters:\n\n    | Field | Type   | Optional | Default | Min | Max | Description                                       |\n    |-------|--------|----------|---------|-----|-----|---------------------------------------------------|\n    | page  | number | Yes      | 1       | 1   | -   | The page number to retrieve.                      |\n    | limit | number | Yes      | 10      | 1   | 100 | The number of users to retrieve per page.         |\n\n    Response:\n\n    | Field        | Type        | Description                                                               |\n    |--------------|-------------|---------------------------------------------------------------------------|\n    | data         | Tweet Array | An array of tweet objects for the current page.                           |\n    | totalItems   | number      | Total number of tweets available across all pages.                        |\n    | itemCount    | number      | Number of tweets in the `data` array for the current page.                |\n    | itemsPerPage | number      | The number of items requested per page (matches the `limit` query param). |\n    | totalPages   | number      | Total number of pages available.                                          |\n    | currentPage  | number      | The current page number (matches the `page` query param).                 |\n2. **GET /tweets/:id**\n    * Retrieves a specific tweet by its unique ID\n    * Requires authentication (any logged-in user can access this).\n\n   Path Parameters:\n\n   | Parameter | Type            | Required | Description                             |\n   |-----------|-----------------|----------|-----------------------------------------|\n   | id        | string / number | Yes      | The unique identifier of the tweet.     |\n\n    Response:\n    ref to Tweet object\n3. **POST /tweets**\n    * Creates a new tweet for the authenticated user.\n    * Requires authentication (any logged-in user can create a tweet).\n\n    Request:\n\n    | Field   | Type   | Required | Max Length | Description                    |\n    |---------|--------|----------|------------|--------------------------------|\n    | title   | string | Yes      | 100        | The title of the tweet.        |\n    | content | string | Yes      | 800        | The main content of the tweet. |\n\n    Response:\n    ref to Tweet object\n4. **PUT /tweets/:id**\n    * Updates an existing tweet\n    * Requires authentication\n    * At least one field (`title` or `content`) must be provided in the request body\n    * Requires **ADMIN** / **USER** role.\n        * **ADMINS:** Can update any tweet.\n        * **USERS (Tweet Owners):** Can only update their own tweet.\n\n    Path Parameters:\n\n    | Parameter | Type            | Required | Description                                   |\n    |-----------|-----------------|----------|-----------------------------------------------|\n    | id        | string / number | Yes      | The unique identifier of the tweet to update. |\n\n    Request:\n\n    | Field   | Type   | Optional | Max Length | Description                       |\n    |---------|--------|----------|------------|-----------------------------------|\n    | title   | string | Yes      | 100        | The updated title of the tweet.   |\n    | content | string | Yes      | 800        | The updated content of the tweet. |\n\n    Response:\n    ref to Tweet object\n5. **DELETE /tweets/:id**\n    * Soft deletes a specific tweet by its unique ID. This typically marks the tweet as inactive or deleted but does not permanently remove it from the database\n    * Requires authentication\n    * Requires **ADMIN** / **USER** role\n      * **ADMINS:** Can soft delete any tweet.\n      * **USERS (Tweet Owners):** Can only soft delete their own tweets.\n\n    Path Parameters:**\n\n    | Parameter | Type            | Required | Description                                   |\n    |-----------|-----------------|----------|-----------------------------------------------|\n    | id        | string / number | Yes      | The unique identifier of the tweet to delete. |\n\n\n## Improvement\n\n1. setup migration stage instead of docker start sql\n2. setup mq \n3. setup microservice dockerfile for deployment\n4. complete e2e test\n ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimothyrushing%2Fnestjs-tweets-microservice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimothyrushing%2Fnestjs-tweets-microservice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimothyrushing%2Fnestjs-tweets-microservice/lists"}