{"id":27498313,"url":"https://github.com/pulgamecanica/matcha","last_synced_at":"2025-04-17T08:31:35.495Z","repository":{"id":286663021,"uuid":"961946424","full_name":"pulgamecanica/matcha","owner":"pulgamecanica","description":"Matcha - 42","archived":false,"fork":false,"pushed_at":"2025-04-15T08:14:58.000Z","size":226,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T08:34:49.654Z","etag":null,"topics":["api","ruby","sinatra","sinatra-applications"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/pulgamecanica.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-04-07T12:18:02.000Z","updated_at":"2025-04-15T08:15:02.000Z","dependencies_parsed_at":"2025-04-07T18:55:01.295Z","dependency_job_id":null,"html_url":"https://github.com/pulgamecanica/matcha","commit_stats":null,"previous_names":["pulgamecanica/matcha"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulgamecanica%2Fmatcha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulgamecanica%2Fmatcha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulgamecanica%2Fmatcha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulgamecanica%2Fmatcha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pulgamecanica","download_url":"https://codeload.github.com/pulgamecanica/matcha/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249326181,"owners_count":21251735,"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":["api","ruby","sinatra","sinatra-applications"],"created_at":"2025-04-17T08:31:35.051Z","updated_at":"2025-04-17T08:31:35.479Z","avatar_url":"https://github.com/pulgamecanica.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🧪 Matcha API — Love \u0026 Ruby 💘\n\n[![Sinatra](https://img.shields.io/badge/Made%20with-Sinatra-ff69b4?logo=sinatra)](http://sinatrarb.com/)\n[![PostgreSQL](https://img.shields.io/badge/Database-PostgreSQL-336791?logo=postgresql)](https://www.postgresql.org/)\n[![Dockerized](https://img.shields.io/badge/Dockerized-Yes-blue?logo=docker)](https://www.docker.com/)\n[![Tested with RSpec](https://img.shields.io/badge/Tested%20with-RSpec-ff4155?logo=ruby)](https://rspec.info/)\n[![TDD](https://img.shields.io/badge/TDD-Driven-%23cc0066?logo=testing-library)]()\n[![Custom DSL](https://img.shields.io/badge/DSL-api_doc-%23bada55)]()\n\n\u003e The only thing better than a Matcha latte is a **match made in Ruby**.  \n\u003e This is a fully-documented, TDD-driven Sinatra API for the Matcha dating platform. It’s modular, dockerized, and optimized for love at first request 💘\n\n---\n\n## 📦 Tech Stack\n\n| Layer         | Tech                    |\n|---------------|-------------------------|\n| Framework     | Sinatra (modular style) |\n| Language      | Ruby 3.2                |\n| Database      | PostgreSQL 14           |\n| Persistence   | Raw SQL + SQLHelper     |\n| Auth          | JWT (handrolled)        |\n| Container     | Docker + Compose        |\n| Testing       | RSpec + Rack::Test      |\n| Docs          | `api_doc` DSL (custom)  |\n| Console       | IRB via bin/console     |\n| Tasks         | Rake + Makefile         |\n\n---\n\n## ⚙️ Features\n\n- 🔐 **Authentication**: Email/password \u0026 social (Google, Facebook, Snapchat)\n- 🧪 **TDD-first** with RSpec specs for everything\n- 🧼 **Clean architecture**: Helpers, controllers, and models separated\n- 🔒 **JWT-based sessions** (no gem dependencies)\n- 🧠 **Robust validation** with reusable DSL-based `Validator`\n- 🌍 **RESTful routes**: `/auth`, `/me`, `/users/:username`, etc.\n- 🚫 **Ban \u0026 Confirm logic**: No banned or unconfirmed user can access the API\n- 💾 **Smart SQL helper**: `SQLHelper.create`, `update`, `find_by`, etc.\n- 🧾 **API docs**: Exportable via `make docs`\n- 🐳 **Fully dockerized**\n- 💬 Friendly, readable logs\n\n---\n\n## 🗂️ Project Structure\n\n```\n.\n├── app/\n│   ├── controllers/     # Modular Sinatra apps (AuthController, UsersController)\n│   ├── helpers/         # Validators, SQLHelper, Request parsing, Auth, Database\n│   ├── models/          # Models (User, ...)\n│   ├── lib/             # Shared error classes, doc\n├── config/\n│   └── database.yml     # Database settings\n│   └── environment.rb   # Loads everything\n├── db/\n│   ├── migrate/         # DB migrations\n│   └── seeds.rb         # (optional)\n├── spec/                # RSpec suite\n├── docker/              # Dockerfile\n├── docker-compose.yml\n├── Rakefile\n├── Makefile\n├── .env\n├── config.ru\n└── README.md\n```\n\n---\n\n## 🚀 Getting Started\n\n---\n\n### 📘 Postman Collection\n\n\u003e Visit the [Postman Colleciton](https://pulgamecanica.postman.co/workspace/pulgamecanica~fddcef76-1724-4c9d-8f90-c24cfe79c2b9/collection/13231501-422c8247-c0ee-4bec-834b-ede0215c4e05?action=share\u0026creator=13231501) to run all the API endpoints.\n\n---\n\n### 🔧 Local Dev (Dockerized)\n\n```bash\ngit clone https://github.com/pulgamecanica/matcha\ncd matcha\n\n# Build containers\ndocker compose build\n\n# Start the app\ndocker compose up\n\n# Open dev console\nmake console\n\n# Run the test suite\nmake test\n```\n\n---\n\n## 🧪 Testing\n\nRSpec tests live in `spec/`, with:\n- Integration tests for endpoints\n- Unit tests for helpers\n- Full TDD on auth, validation, sessions, and core models\n\n```bash\nmake test\n```\n\n---\n\n## 🛠️ Developer Shortcuts (Makefile)\n\n```bash\nmake create   # db:create\nmake migrate  # db:migrate\nmake test     # run all specs\nmake console  # open IRB console\nmake docs     # export route documentation\n```\n\n---\n\n## 🔐 Authentication\n\nStateless JWT (no libraries!) via `SessionToken`.\n\n```rb\nSessionToken.generate(user_id)  # =\u003e \"encoded.jwt.token\"\nSessionToken.decode(token)      # =\u003e { \"user_id\" =\u003e 42, ... }\n```\n\n---\n\n## 📘 API Documentation\n\nEach route is documented inline with the `api_doc` DSL.  \nTo export to markdown:\n\n```bash\nmake docs\n```\n\n➡ Output: `docs/exported.md`\n\nExample:\n\n```ruby\napi_doc \"/auth/register\", method: :post do\n  description \"Register a new user\"\n  param :email, String, required: true\n  param :username, String, required: true\n  param :password, String, required: true\n  response 201, \"User created\"\nend\n```\n\n---\n\n## 🚀 Endpoints (Implemented)\n\n- `POST /auth/register`\n- `POST /auth/login`\n- `POST /auth/social`\n- `GET  /me`\n- `PATCH /me`\n- `DELETE /me`\n- `GET  /users/:username`\n\n(⚠️ All protected endpoints require JWT via `Authorization: Bearer \u003ctoken\u003e`)\n\n---\n\n## 🎯 Roadmap\n\n- [x] JWT session system\n- [x] Login, Register, Social Auth\n- [x] Patch \u0026 Delete `/me`\n- [x] Ban, confirm \u0026 protect endpoints\n- [x] Public profiles `/users/:username`\n- [x] API Docs via DSL\n- [x] Validation system\n- [x] SQLHelper abstraction\n- [x] Tag system\n- [x] Connections, Likes\n- [X] Notifications\n- [ ] Commonly used English words should not be accepted as passwords.\n- [ ] Real-time messaging (WebSocket or polling)\n- [ ] Full CI/CD pipeline\n\n---\n\n## 💡 Philosophy\n\n\u003e 📜 Everything documented  \n\u003e 🧪 Everything tested  \n\u003e 🚫 No unhandled JSON  \n\u003e 💥 No silent failures  \n\u003e 💎 Code should read like Ruby poetry  \n\n---","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpulgamecanica%2Fmatcha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpulgamecanica%2Fmatcha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpulgamecanica%2Fmatcha/lists"}