{"id":20581232,"url":"https://github.com/jonathas/todo-service","last_synced_at":"2026-04-17T08:04:51.214Z","repository":{"id":200678626,"uuid":"705317310","full_name":"jonathas/todo-service","owner":"jonathas","description":"A GraphQL API for managing To Dos and synchronizing them with the Microsoft To Do API","archived":false,"fork":false,"pushed_at":"2023-10-17T10:09:29.000Z","size":1204,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-03-06T12:16:19.251Z","etag":null,"topics":["graphql","microsoft-todo","nestjs","todo","todo-list","todo-list-app","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonathas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-10-15T17:20:10.000Z","updated_at":"2024-08-25T16:45:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"b6ebc1a4-f351-4fb0-896c-3acb2c33945b","html_url":"https://github.com/jonathas/todo-service","commit_stats":null,"previous_names":["jonathas/todo-service"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jonathas/todo-service","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathas%2Ftodo-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathas%2Ftodo-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathas%2Ftodo-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathas%2Ftodo-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonathas","download_url":"https://codeload.github.com/jonathas/todo-service/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathas%2Ftodo-service/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31920520,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"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":["graphql","microsoft-todo","nestjs","todo","todo-list","todo-list-app","typescript"],"created_at":"2024-11-16T06:27:32.485Z","updated_at":"2026-04-17T08:04:51.197Z","avatar_url":"https://github.com/jonathas.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# To Do management service\n\nA GraphQL API for managing To Dos and synchronizing them with Microsoft To Do API\n\n![Microsoft To Do](/docs/images/microsoft-todo.png)\n\n## Table of Contents\n\n- [Features](#features)\n- [Tech](#tech)\n- [Installation](#installation)\n- [Running the project](#running-the-project)\n- [Configuring the integration with the Microsoft To Do API](#configuring-the-integration-with-the-microsoft-to-do-api)\n- [Way of working](#way-of-working)\n- [Integration tests](#integration-tests)\n- [Database](#database)\n- [Synchronization](#synchronization)\n  - [Webhook](#webhook)\n  - [GraphQL Subscription](#graphql-subscription)\n  - [Manual synchronization](#manual-synchronization)\n  - [Cron job](#cron-job)\n- [More documentation](#more-documentation)\n  - [Compodoc](#compodoc)\n  - [Postman collection](#postman-collection)\n  - [GraphQL Playground](#graphql-playground)\n- [Known limitations](#known-limitations)\n\n## Features\n\n- Possibility to query tasks\n  - Query tasks that are not done\n  - Tasks can be grouped in lists\n- Possibility to add a task\n- Possibility to update tasks\n  - Possibility to mark tasks as done\n- Integration with Microsoft To Do. Tasks are kept in sync between our service and the third-party integration\n  - Tasks created in the third-party integration are always created in our service\n  - The status of tasks is always in sync between our service and the integration\n\n## Tech\n\n- PostgreSQL\n- Redis\n- Docker\n- TypeScript\n- NestJS\n- Express\n- GraphQL\n\n## Installation\n\n```bash\n$ npm install\n```\n\n## Running the project\n\n1) Copy the .sample.env file to .env and fill in the Microsoft To Do API integration values.\n\n2) Add to MICROSOFT_GRAPH_WEBHOOK_URL the address where the Microsoft To Do API will be able to find the webhook it will need to call to deliver the updates. In my case I have a free domain on [ngrok](https://ngrok.com/), so after starting the API I run the following to make it available:\n\n```bash\n$ ngrok http --domain=close-wrongly-jaybird.ngrok-free.app 3000\n```\n\nPs: Webhook is only one of the ways that our project synchronizes with the Microsoft To Do API. The API should also work without it.\n\n3) Run the containers for the DB and Redis (used for our GraphQL subscription)\n\n```bash\n$ docker compose -f ./resources/docker-compose.yml up\n```\n\nThis command will automatically create the DB and required tables.\n\n4) Run the API with one of the following commands (debug preferred)\n\n```bash\n# development\n$ npm start\n\n# watch mode\n$ npm run start:dev\n\n# debug mode\n$ npm run start:debug\n\n# production mode\n$ npm run start:prod\n```\n\n## Configuring the integration with the Microsoft To Do API\n\nSince there's no client-side part connecting to our API yet, the OAuth flow has been simplified without any page interaction.\n\nAfter running the API successfully with the correct .env values:\n\n1) Open [http://localhost:3000/microsoft/auth/signin](http://localhost:3000/microsoft/auth/signin) on your browser. This will redirect you to the authorization page from Microsoft after signing in.\n\n![Permissions](/docs/images/permissions.png)\n\n2) The redirect url is configured to [http://localhost:3000/microsoft/auth/redirect](http://localhost:3000/microsoft/auth/redirect) in Azure (app config), so after you accept the permission, you'll be redirected to the redirect endpoint. The MSIdentity controller will then use the code it received, request tokens and save them to the microsoft_integrations table.\n\n3) That's it! After the previous step, our API is able to sync with the Microsoft To Do API.\n\n## Integration tests\n\nFirst the Docker containers need to be running and then you can run the integration tests like so:\n\n```bash\n$ npm run test:integration\n```\n\n## Way of working\n\nThe [husky](https://www.npmjs.com/package/husky) lib is used for enforcing some rules for local development using Git hooks.\n\n- On every commit:\n  - The commit message is validated against [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)\n  - The staged files are linted with several [eslint](https://www.npmjs.com/package/eslint) rules\n- Before every push to the repository, the integration tests will run and should pass for the push to proceed.\n\nMore about way of working and release management can be found on [this post I wrote a while ago](https://jonathas.com/efficient-software-release-management-with-automated-changelog-generation/).\n\n## Database\n\nThe diagram below is parsed via [mermaid](https://mermaid.js.org/syntax/entityRelationshipDiagram.html).\n\n- The \"ext\" prefix in some of the fields refers to values that come from the Microsoft To Do API.\n- A basic users table was created in order to keep track of the tokens, but no user authentication or handling is done at the moment.\n- The subscriptions table was created so that when a list is created, a subscription for that list is created in the Microsoft To Do API. We need to create a subscription in order to be able to receive requests to our webhook which are related to tasks in a list. We keep track of it so that when a list is deleted, its related subscription is also deleted from the Microsoft To Do API.\n\n```mermaid\nerDiagram\n    lists ||--|{ tasks : contains\n    users ||--|| microsoft_integrations : has\n    tasks ||--|| subscriptions : has\n\n    tasks {\n        id int\n        name varchar(255)\n        description varchar(255)\n        is_done boolean\n        ext_id varchar(255)\n        list_id int\n        last_synched_at timestamp\n        created_at timestamp\n        updated_at timestamp\n    }\n    lists {\n      id int\n      name varchar(255)\n      description varchar(255)\n      ext_id varchar(255)\n      ext_subscription_id varchar(255)\n      last_synched_at timestamp\n      created_at timestamp\n      updated_at timestamp\n    }\n    users {\n      id int\n      email varchar(255)\n      password varchar(255)\n      created_at timestamp\n      updated_at timestamp\n    }\n    microsoft_integrations {\n      id int\n      user_id int\n      access_token text\n      id_token text\n      refresh_token text\n      expires_on timestamp\n      created_at timestamp\n      updated_at timestamp      \n    }\n    subscriptions {\n      id int\n      subscription_id varchar(255)\n      resource varchar(255)\n      ext_list_id varchar(255)\n      expiration_date_time timestamp\n      created_at timestamp\n      updated_at timestamp\n    }\n```\n\n## Synchronization\n\nOur API synchronizes with the Microsoft To Do API in 3 ways: Webhook, manually and via a cron job\n\n### Webhook\n\nThe Microsoft Graph API allows subscribing to task changes inside of lists, so whenever a list is created in our API, a subscription is created in the Microsoft Graph API to track changes to it.\nIn order for the webhook sync to work, a publicly accessible url for our API needs to be configured on .env and the integration set to true\n\n```bash\nMICROSOFT_GRAPH_USE_WEBHOOK=true\nMICROSOFT_GRAPH_WEBHOOK_URL=https://close-wrongly-jaybird.ngrok-free.app/webhook\n```\n\n### GraphQL subscription\n\nThere's a ```notifications``` subscription available, which can be useful for client-side apps to know when some event happens. Every time a webhook request changes something in our DB, this change is pushed to the subscription\n\n![GraphQL Subscription](/docs/images/subscription.png)\n\n### Manual synchronization\n\nIt might happen that you created a task in the Microsoft To Do app but our API wasn't running at the time, or perhaps when you started the API you already had tasks in the app, so the manual synchronization allows for these changes to be synchronized to the DB.\n\nYou can run it by calling the ```startManualSync``` mutation.\n\n### Cron job\n\nA cron job can also be enabled in .env\n\n```bash\nUSE_CRON=true\n```\n\nIf enabled, it should run every minute and call the same method as the manual synchronization\n\n## More documentation\n\n## Compodoc\n\nYou can have a good overview about the project by running Compodoc:\n\n```bash\n$ npm run compodoc\n```\n\nThis will generate a directory called \"documentation\" with several files, so you can open the index.html file on your browser.\n\n## Postman collection\n\nA [Postman](https://www.postman.com/downloads/) collection can be found inside of the docs directory. You can just import it to Postman and start using it to interact with the API.\n\n## GraphQL Playground\n\nAnother way of interacting with the API is with GraphQL Playground. You can access it by opening [http://localhost:3000/graphql](http://localhost:3000/graphql) on your browser.\n\n## Known limitations\n\n- There's no user management yet\n- There's no user authentication yet\n- Microsoft Graph API subscriptions are currently set to their [maximum length of subscription](https://learn.microsoft.com/en-us/graph/api/resources/subscription?view=graph-rest-1.0#maximum-length-of-subscription-per-resource-type) (4230 minutes) and there's no renewal mechanism.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathas%2Ftodo-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonathas%2Ftodo-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathas%2Ftodo-service/lists"}