Spinjitzu API
Svět Ninjago má neobyčejně bohatou historii a lore, avšak dosud chyběl jakýkoli strukturovaný způsob, jak v těchto datech vyhledávat. Spinjitzu API je veřejné REST API, které tuto mezeru zaplňuje. Poskytuje strukturovaná data o postavách, sériích, elementech, zbraních, lokacích a říších s podporou filtrování, stránkováním a interaktivní dokumentace OpenAPI. K projektu jsem přistupoval jako k plnohodnotné veřejné službě: navrhl jsem jednotnou strukturu odpovědí (response envelopes), důslednou validaci, rate limiting, zabezpečení pomocí JWT, testování, kontejnerizaci v Dockeru a serverless nasazení.
- NestJS
- TypeScript
- PostgreSQL
- Neon
- Drizzle ORM
- Passport
- Zod
- class-validator
- Jest
- Docker
- Swagger / OpenAPI
Náhled projektu
Kontext
Sérii Ninjago sleduji už řadu let. Když jsem pro jeden ze svých nápadů hledal veřejné API s daty o postavách, sériích nebo elementech, zjistil jsem, že neexistuje nic použitelného – tak jsem se rozhodl ho vybudovat sám. I když je téma ryze neformální, technické zpracování muselo splňovat standardy reálného produkčního projektu: od jasně definovaných kontraktů a bezpečnostních bariér přes rate limiting až po kompletní dokumentaci a robustní nasazení.
Technický přístup
- Modulární struktura organizovaná podle funkcí (feature-first) s průchodem Controller → Service → Drizzle → PostgreSQL. Vzor Repository jsem se rozhodl vynechat, dokud pro něj nevznikne reálné opodstatnění.
- Neon serverless Postgres s využitím HTTP ovladače, který byl zvolen pro optimální kompatibilitu a výkon v bezserverovém (serverless) prostředí Vercelu.
- Centralizované sjednocení struktury odpovědí pomocí globálního interceptoru a filtru výjimek (exception filter) zajišťující, že každý endpoint vrací identický formát pro úspěšné i chybové stavy.
- Vlastní složené dekorátory (např. @AdminWrite()), které u zápisových endpointů elegantně sdružují ověření JWT tokenu, kontrolu rolí, přísnější rate limiting pro zápis a pravidla pro produkční deaktivaci či skrytí.
Výzvy
- Správný návrh a modelování vazeb typu many-to-many mezi postavami, elementy, zbraněmi a sériemi. Data musela zůstat historicky přesná, přestože se v průběhu času mění majitelé zbraní, jejich schopnosti či jednotlivé éry příběhu.
- Hledání příčiny konfliktu mezi verzováním API v NestJS a globálním prefixem, který znefunkčnil neverzovaný kořenový endpoint. Problém jsem vyřešil konfigurací směrování jako VERSION_NEUTRAL.
- Zajištění spolehlivého načítání statických souborů pro Swagger UI v serverless prostředí na platformě Vercel, čehož jsem docílil servírováním CSS a JS souborů z veřejné CDN sítě namísto spoléhání se na dynamické cesty v lokálním balíčku.
- Rozhodnutí, které funkce je v produkci nutné zcela deaktivovat a které stačí pouze skrýt. Administrační trasy a přihlašování jsou v produkčním režimu nekompromisně blokovány vlastním autorizačním strážcem (DisabledInProductionGuard) a nezmizely tak pouze z OpenAPI dokumentace.
Co jsem se naučil
- Osobní vztah k tématu byl skvělým motorem pro dokončení projektu. Publikace ve formě veřejně přístupného API však i tak vyžadovala stejně precizní architektonická rozhodnutí jako při návrhu komerčních B2B služeb.
- Vedení podrobného architektonického deníku a záznamu rozhodnutí (decision log v souboru AGENTS.md) již od počáteční fáze mi pomohlo jasně definovat technologické kompromisy a udržet konzistentní směr napříč celým vývojem.
- Bezserverové (serverless) nasazení odhalí skryté předpoklady frameworku týkající se servírování statických souborů a práce s vnitřní pamětí, které se při běhu na klasickém, nepřetržitě běžícím serveru vůbec neprojeví.
- Doporučení z automatizovaných bezpečnostních auditů je vždy nutné posuzovat v širším kontextu. Zatímco některé nálezy (např. ošetření souběhu u unikátních databázových omezení) byly klíčové, jiné (jako zákaz divokých karet u CORS) nedávaly u veřejného, převážně čtecího API žádný smysl.
- Zavedení osobních přístupových tokenů (Personal Access Tokens) sdílejících hlavičku Authorization s JWT je naplánováno do verze v2. Implementace složité hybridní autentizace před dokončením stabilního čtecího rozhraní by byla předčasným rozhodnutím.
Hlavní funkce
- Kompletní CRUD operace pro 6 relačně propojených entit se složitými vazbami typu many-to-many (postavy ↔ elementy, zbraně, série)
- Autentizace pomocí JWT s ochranou přístupu na základě uživatelských rolí (role-based guards). Administrační zápisy jsou v produkčním prostředí striktně zablokovány přímo v autorizační vrstvě, nikoli pouze skryty v dokumentaci
- Víceúrovňový rate limiting (např. 200 požadavků pro čtení, 20 pro zápis, 5 pro autentizaci za minutu) s možností specifického přepsání (throttler overrides) u jednotlivých tras
- Jednotný formát úspěšných odpovědí se strukturou {data, meta} a konzistentní chybové obálky (error envelopes) napříč všemi endpointy
- Verzování API pomocí URI, což umožňuje bezproblémový souběh verzí v1 a v2 bez rizika narušení funkčnosti u stávajících uživatelů
- Jednotkové testy s mockováním databázové vrstvy Drizzle pokrývající aplikační logiku a autentizaci. Interaktivní dokumentace OpenAPI na adrese /docs
Další projekt
Minimal E-Shop
Full-stack e-commerce demo se Spring Bootem, platbami přes Stripe a dockerizovaným backendem.