{"id":19044802,"url":"https://github.com/salvillalon45/exercisetracker-freecodecamp","last_synced_at":"2026-04-08T16:01:10.160Z","repository":{"id":217910619,"uuid":"744660560","full_name":"salvillalon45/exerciseTracker-freeCodeCamp","owner":"salvillalon45","description":"An Exercise Tracker REST API","archived":false,"fork":false,"pushed_at":"2024-02-01T19:35:53.000Z","size":6544,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-04T04:54:41.346Z","etag":null,"topics":["expressjs","javascript","mongodb","nodejs","prisma","render","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/salvillalon45.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":"2024-01-17T18:51:01.000Z","updated_at":"2024-02-01T19:34:43.000Z","dependencies_parsed_at":"2024-01-22T20:56:03.620Z","dependency_job_id":"600910a4-ac5c-4623-a3d8-3b2f748c5e99","html_url":"https://github.com/salvillalon45/exerciseTracker-freeCodeCamp","commit_stats":null,"previous_names":["salvillalon45/exercisetracker-freecodecamp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/salvillalon45/exerciseTracker-freeCodeCamp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salvillalon45%2FexerciseTracker-freeCodeCamp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salvillalon45%2FexerciseTracker-freeCodeCamp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salvillalon45%2FexerciseTracker-freeCodeCamp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salvillalon45%2FexerciseTracker-freeCodeCamp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salvillalon45","download_url":"https://codeload.github.com/salvillalon45/exerciseTracker-freeCodeCamp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salvillalon45%2FexerciseTracker-freeCodeCamp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31562696,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"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":["expressjs","javascript","mongodb","nodejs","prisma","render","rest-api","typescript"],"created_at":"2024-11-08T22:47:30.699Z","updated_at":"2026-04-08T16:01:10.145Z","avatar_url":"https://github.com/salvillalon45.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exercise Tracker\n\nfreeCodeCamp - Back End Development and APIs | Project: Exercise Tracker\n\n# Summary\n\nCreate a Exercise Tracker REST API that does the follwing:\n\n-   Create new users\n-   Create new exercise for users\n-   Creates a log of the exercises a user has done\n\nIt has the following routes:\n\n-   **/api/users**\n    -   **GET**: Get a list of users\n    -   **POST**: Pass in a `username` in the form data to create a new user. The response from this request will be an object withe `username` and `_id` properties\n    -   Response Example\n    ```\n    {\n        username: \"fcc_test\",\n        _id: \"5fb5853f734231456ccb3b05\"\n    }\n    ```\n-   **/api/users/:\\_id/exercises**\n    -   **POST**: With form data `description`, `duration`, and optionally `date`. If no `date` is supplied, the current `date` will be used. It will create a new exercise for the user. The response from this request will be a `user` object with the `exercise fields` added.\n    -   Response Example\n    ```\n    {\n        username: \"fcc_test\",\n        description: \"test\",\n        duration: 60,\n        date: \"Mon Jan 01 1990\",\n        _id: \"5fb5853f734231456ccb3b05\"\n    }\n    ```\n-   **/api/users/:\\_id/logs**\n    -   **GET**: To retrieve a full exercise log of any user. The response object from this request will contain\n        -   `count`: total exercises in the log\n        -   `log`: array of all exercises added\n        -   `username` and `id`\n        -   Example of Response\n        ```\n        {\n            username: \"fcc_test\",\n            count: 1,\n            _id: \"5fb5853f734231456ccb3b05\",\n            log: [{\n                description: \"test\",\n                duration: 60,\n                date: \"Mon Jan 01 1990\",\n            }]\n        }\n        ```\n\n**[Learn more about the Project Task.](https://www.freecodecamp.org/learn/back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker)**\n\n### Implementation\n\n-   Created a TypeScript + Express API\n-   Created the `routes/api.ts` to organize the routes that the api will use\n-   Created the `controllers/userController.ts`. It contains all the api handlers that the routes will use to do the logic on each api call\n-   Trying for the first time Prisma as an ORM. Connected Prisma with MongoDB\n-   Created three prisma schemas: `Log`, `User`, and `Exercise`. Where `Log` has a relation to `User`.\n-   Created the `apiUtils.ts` to contain five functions that connect to the `MongoDB` using the Prisma client.\n-   Created `utils/index.ts` that has two functions to organize and validate dates\n-   Created four routes along with their api handlers:\n    -   `router.post('/users', createNewUser);`\n    -   `router.get('/users', getUsers);`\n    -   `router.post('/users/:_id/exercises', createExercise);`\n    -   `router.get('/users/:_id/logs', getUserExerciseLog);`\n\n### Lessons Learned\n\n-   This was my first time using Prisma and it very easy to use. I noticed that when I created a new `Log` entity. It was automatically inserted into the `User` `log` field. I still need to investiage why that happend. Is it due to the `relation` that the `User` and `Log` schemas have with each other?\n-   Object-Relational Mapping (ORM): It is a programming technique that allows developers to interact with a relational database using an object-oriented programming language. Here we use Prisma to bridge the gap between `MongoDB` and `TypeScript`. With Prisma I could use `TypeScript` code to make queries! This is different from just doing straight SQL queries in the code.\n-   Object-Document Mapping (ODM): A concept similar to ORM, but ODM is for `NoSQL` databases. I will use `Mongoose` in my projects a lot. Using `Mongoose` with `MongoDB` is a better developer experience since `Mongoose` is intended for `MongoDB`! While Prisma supports mainly relational dbs.\n-   MongoDB stores their `id` field with an underscore like so `_id`. Prisma keeps their `id` with no underscore. For the tests to pass I had to switch each `id` to `_id`.\n    -   Example\n    ```\n    const users = usersDB.map(({ username, id }) =\u003e {\n    \treturn {\n    \t\tusername,\n    \t\t_id: id\n    \t};\n    })\n    ```\n\n### Resources\n\n-   Use the [Prisma Quickstart guide](https://www.prisma.io/docs/getting-started/quickstart)!\n-   Needed to learn how to distinguish between Prisma and Mongoose. Use this [documenation](https://www.prisma.io/docs/orm/more/comparisons/prisma-and-mongoose) to learn from!\n-   `Date.parse()`: This parses the string representation of a date and returns the date timestamp in a number! This is great when trying to compare two dates! This was done in the `getUserExerciseLog` api handler where I was comparing the `to` and `from` query params to filter out the dates\n-   `Number.isInteger()`: Did not use it in the code, but this determines whether the input is an integer or not!\n-   Use [this repo](https://replit.com/@juanrozo89/exercise-tracker#index.js) for guidance on the to, from, and limit query. Thank you @juanrozo89!\n\n### Demo\nhttps://github.com/salvillalon45/exerciseTracker-freeCodeCamp/assets/18276475/01ade50a-9c5b-4869-a4fe-9c7b599a30be\n\n\n\n# Technologies:\n\n-   JavaScript\n-   TypeScript\n-   Render\n-   MongoDB\n-   Prisma\n-   NodeJS\n-   ExpressJS\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalvillalon45%2Fexercisetracker-freecodecamp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalvillalon45%2Fexercisetracker-freecodecamp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalvillalon45%2Fexercisetracker-freecodecamp/lists"}