frontend elmélet

This commit is contained in:
magdo
2026-03-17 23:53:10 +01:00
parent 8da3a1eb32
commit 28bd7661f5
69 changed files with 1072 additions and 9534 deletions
+7 -1
View File
@@ -20,4 +20,10 @@
*/*/package-lock.json
*/*/yarn.lock
Thumbs.*
Thumbs.*
# tömörített fájlok
*.zip
*.tar.gz
*.rar
*.7z
@@ -1,418 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1772649160943" clover="3.2.0">
<project timestamp="1772649160943" name="All files">
<metrics statements="301" coveredstatements="1" conditionals="103" coveredconditionals="2" methods="83" coveredmethods="4" elements="487" coveredelements="7" complexity="0" loc="301" ncloc="301" packages="11" files="26" classes="26"/>
<package name="api.controllers">
<metrics statements="65" coveredstatements="0" conditionals="18" coveredconditionals="0" methods="9" coveredmethods="0"/>
<file name="AuthController.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\controllers\AuthController.js">
<metrics statements="26" coveredstatements="0" conditionals="10" coveredconditionals="0" methods="4" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="2" count="0" type="stmt"/>
<line num="10" count="0" type="stmt"/>
<line num="11" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
<line num="19" count="0" type="stmt"/>
<line num="20" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
<line num="23" count="0" type="stmt"/>
<line num="26" count="0" type="stmt"/>
<line num="32" count="0" type="stmt"/>
<line num="40" count="0" type="cond" truecount="0" falsecount="6"/>
<line num="45" count="0" type="stmt"/>
<line num="53" count="0" type="stmt"/>
<line num="54" count="0" type="stmt"/>
<line num="56" count="0" type="stmt"/>
<line num="57" count="0" type="stmt"/>
<line num="60" count="0" type="stmt"/>
<line num="66" count="0" type="stmt"/>
<line num="74" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="77" count="0" type="stmt"/>
<line num="85" count="0" type="stmt"/>
<line num="87" count="0" type="stmt"/>
<line num="94" count="0" type="stmt"/>
<line num="98" count="0" type="stmt"/>
<line num="103" count="0" type="stmt"/>
</file>
<file name="UserController.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\controllers\UserController.js">
<metrics statements="39" coveredstatements="0" conditionals="8" coveredconditionals="0" methods="5" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="2" count="0" type="stmt"/>
<line num="3" count="0" type="stmt"/>
<line num="4" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
<line num="13" count="0" type="stmt"/>
<line num="14" count="0" type="stmt"/>
<line num="15" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
<line num="24" count="0" type="stmt"/>
<line num="26" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="29" count="0" type="stmt"/>
<line num="34" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="35" count="0" type="stmt"/>
<line num="43" count="0" type="stmt"/>
<line num="44" count="0" type="stmt"/>
<line num="45" count="0" type="stmt"/>
<line num="47" count="0" type="stmt"/>
<line num="53" count="0" type="stmt"/>
<line num="61" count="0" type="stmt"/>
<line num="62" count="0" type="stmt"/>
<line num="63" count="0" type="stmt"/>
<line num="65" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="66" count="0" type="stmt"/>
<line num="69" count="0" type="stmt"/>
<line num="70" count="0" type="stmt"/>
<line num="72" count="0" type="stmt"/>
<line num="77" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="78" count="0" type="stmt"/>
<line num="86" count="0" type="stmt"/>
<line num="87" count="0" type="stmt"/>
<line num="88" count="0" type="stmt"/>
<line num="90" count="0" type="stmt"/>
<line num="91" count="0" type="stmt"/>
<line num="93" count="0" type="stmt"/>
<line num="98" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="99" count="0" type="stmt"/>
<line num="104" count="0" type="stmt"/>
</file>
</package>
<package name="api.middlewares">
<metrics statements="17" coveredstatements="0" conditionals="4" coveredconditionals="0" methods="4" coveredmethods="0"/>
<file name="authMiddleware.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\middlewares\authMiddleware.js">
<metrics statements="11" coveredstatements="0" conditionals="2" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="3" count="0" type="stmt"/>
<line num="14" count="0" type="stmt"/>
<line num="16" count="0" type="stmt"/>
<line num="18" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="19" count="0" type="stmt"/>
<line num="26" count="0" type="stmt"/>
<line num="29" count="0" type="stmt"/>
<line num="35" count="0" type="stmt"/>
<line num="37" count="0" type="stmt"/>
<line num="44" count="0" type="stmt"/>
</file>
<file name="corsMiddleware.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\middlewares\corsMiddleware.js">
<metrics statements="4" coveredstatements="0" conditionals="2" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="4" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="6" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
</file>
<file name="scopeMiddleware.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\middlewares\scopeMiddleware.js">
<metrics statements="2" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="6" count="0" type="stmt"/>
<line num="18" count="0" type="stmt"/>
</file>
</package>
<package name="api.routers">
<metrics statements="20" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="11" coveredmethods="0"/>
<file name="authRoutes.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\routers\authRoutes.js">
<metrics statements="9" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="5" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="10" count="0" type="stmt"/>
<line num="13" count="0" type="stmt"/>
<line num="20" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="33" count="0" type="stmt"/>
<line num="38" count="0" type="stmt"/>
<line num="40" count="0" type="stmt"/>
<line num="43" count="0" type="stmt"/>
</file>
<file name="userRoutes.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\api\routers\userRoutes.js">
<metrics statements="11" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="6" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="2" count="0" type="stmt"/>
<line num="11" count="0" type="stmt"/>
<line num="14" count="0" type="stmt"/>
<line num="20" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="33" count="0" type="stmt"/>
<line num="39" count="0" type="stmt"/>
<line num="44" count="0" type="stmt"/>
<line num="46" count="0" type="stmt"/>
<line num="49" count="0" type="stmt"/>
</file>
</package>
<package name="application.auth.commands">
<metrics statements="49" coveredstatements="0" conditionals="21" coveredconditionals="0" methods="7" coveredmethods="0"/>
<file name="LoginUserCommand.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\auth\commands\LoginUserCommand.js">
<metrics statements="3" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="8" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
</file>
<file name="LoginUserCommandHandler.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\auth\commands\LoginUserCommandHandler.js">
<metrics statements="17" coveredstatements="0" conditionals="8" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="2" count="0" type="stmt"/>
<line num="4" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
<line num="21" count="0" type="stmt"/>
<line num="24" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="25" count="0" type="stmt"/>
<line num="29" count="0" type="stmt"/>
<line num="33" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="34" count="0" type="stmt"/>
<line num="38" count="0" type="stmt"/>
<line num="40" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="41" count="0" type="stmt"/>
<line num="45" count="0" type="stmt"/>
<line num="51" count="0" type="stmt"/>
<line num="53" count="0" type="stmt"/>
<line num="60" count="0" type="stmt"/>
</file>
<file name="RegisterUserCommand.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\auth\commands\RegisterUserCommand.js">
<metrics statements="4" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="8" count="0" type="stmt"/>
<line num="9" count="0" type="stmt"/>
<line num="13" count="0" type="stmt"/>
</file>
<file name="RegisterUserCommandHandler.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\auth\commands\RegisterUserCommandHandler.js">
<metrics statements="25" coveredstatements="0" conditionals="13" coveredconditionals="0" methods="3" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="2" count="0" type="stmt"/>
<line num="4" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
<line num="13" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
<line num="25" count="0" type="cond" truecount="0" falsecount="5"/>
<line num="26" count="0" type="stmt"/>
<line num="29" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="30" count="0" type="stmt"/>
<line num="34" count="0" type="stmt"/>
<line num="35" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="36" count="0" type="stmt"/>
<line num="40" count="0" type="stmt"/>
<line num="44" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="45" count="0" type="stmt"/>
<line num="49" count="0" type="stmt"/>
<line num="52" count="0" type="stmt"/>
<line num="61" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="62" count="0" type="stmt"/>
<line num="63" count="0" type="stmt"/>
<line num="68" count="0" type="stmt"/>
<line num="74" count="0" type="stmt"/>
<line num="76" count="0" type="stmt"/>
<line num="83" count="0" type="stmt"/>
</file>
</package>
<package name="application.services">
<metrics statements="34" coveredstatements="1" conditionals="22" coveredconditionals="2" methods="14" coveredmethods="4"/>
<file name="Container.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\services\Container.js">
<metrics statements="1" coveredstatements="1" conditionals="2" coveredconditionals="2" methods="4" coveredmethods="4"/>
<line num="57" count="1" type="stmt"/>
</file>
<file name="EmailService.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\services\EmailService.js">
<metrics statements="4" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="20" count="0" type="stmt"/>
<line num="26" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="31" count="0" type="stmt"/>
</file>
<file name="JwtService.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\services\JwtService.js">
<metrics statements="29" coveredstatements="0" conditionals="20" coveredconditionals="0" methods="8" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="9" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="10" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="11" count="0" type="stmt"/>
<line num="20" count="0" type="stmt"/>
<line num="29" count="0" type="stmt"/>
<line num="30" count="0" type="stmt"/>
<line num="32" count="0" type="stmt"/>
<line num="42" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="43" count="0" type="stmt"/>
<line num="46" count="0" type="stmt"/>
<line num="48" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="49" count="0" type="stmt"/>
<line num="52" count="0" type="stmt"/>
<line num="61" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="62" count="0" type="stmt"/>
<line num="65" count="0" type="stmt"/>
<line num="73" count="0" type="stmt"/>
<line num="75" count="0" type="stmt"/>
<line num="91" count="0" type="stmt"/>
<line num="93" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="94" count="0" type="stmt"/>
<line num="95" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="96" count="0" type="stmt"/>
<line num="97" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="98" count="0" type="stmt"/>
<line num="102" count="0" type="stmt"/>
<line num="110" count="0" type="stmt"/>
<line num="114" count="0" type="stmt"/>
</file>
</package>
<package name="application.user.commands">
<metrics statements="11" coveredstatements="0" conditionals="2" coveredconditionals="0" methods="3" coveredmethods="0"/>
<file name="UpdateUserProfileCommand.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\commands\UpdateUserProfileCommand.js">
<metrics statements="3" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="8" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
</file>
<file name="UpdateUserProfileCommandHandler.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\commands\UpdateUserProfileCommandHandler.js">
<metrics statements="8" coveredstatements="0" conditionals="2" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="16" count="0" type="stmt"/>
<line num="18" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="19" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="28" count="0" type="stmt"/>
<line num="32" count="0" type="stmt"/>
</file>
</package>
<package name="application.user.queries">
<metrics statements="27" coveredstatements="0" conditionals="8" coveredconditionals="0" methods="10" coveredmethods="0"/>
<file name="GetAllUsersQuery.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\queries\GetAllUsersQuery.js">
<metrics statements="1" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="11" count="0" type="stmt"/>
</file>
<file name="GetAllUsersQueryHandler.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\queries\GetAllUsersQueryHandler.js">
<metrics statements="4" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="3" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="16" count="0" type="stmt"/>
<line num="21" count="0" type="stmt"/>
<line num="25" count="0" type="stmt"/>
</file>
<file name="GetMeQuery.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\queries\GetMeQuery.js">
<metrics statements="2" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="11" count="0" type="stmt"/>
</file>
<file name="GetMeQueryHandler.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\queries\GetMeQueryHandler.js">
<metrics statements="8" coveredstatements="0" conditionals="2" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="16" count="0" type="stmt"/>
<line num="18" count="0" type="stmt"/>
<line num="22" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="23" count="0" type="stmt"/>
<line num="26" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="31" count="0" type="stmt"/>
</file>
<file name="GetUserByIdQuery.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\queries\GetUserByIdQuery.js">
<metrics statements="2" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="11" count="0" type="stmt"/>
</file>
<file name="GetUserByIdQueryHandler.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\application\user\queries\GetUserByIdQueryHandler.js">
<metrics statements="10" coveredstatements="0" conditionals="6" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="16" count="0" type="stmt"/>
<line num="18" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="19" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
<line num="26" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="27" count="0" type="stmt"/>
<line num="30" count="0" type="stmt"/>
<line num="31" count="0" type="stmt"/>
<line num="35" count="0" type="stmt"/>
</file>
</package>
<package name="domain.irepositories">
<metrics statements="7" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="6" coveredmethods="0"/>
<file name="IUserRepository.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\domain\irepositories\IUserRepository.js">
<metrics statements="7" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="6" coveredmethods="0"/>
<line num="12" count="0" type="stmt"/>
<line num="21" count="0" type="stmt"/>
<line num="29" count="0" type="stmt"/>
<line num="38" count="0" type="stmt"/>
<line num="47" count="0" type="stmt"/>
<line num="56" count="0" type="stmt"/>
<line num="60" count="0" type="stmt"/>
</file>
</package>
<package name="domain.models">
<metrics statements="22" coveredstatements="0" conditionals="16" coveredconditionals="0" methods="5" coveredmethods="0"/>
<file name="User.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\domain\models\User.js">
<metrics statements="22" coveredstatements="0" conditionals="16" coveredconditionals="0" methods="5" coveredmethods="0"/>
<line num="7" count="0" type="stmt"/>
<line num="8" count="0" type="stmt"/>
<line num="9" count="0" type="stmt"/>
<line num="10" count="0" type="stmt"/>
<line num="11" count="0" type="stmt"/>
<line num="12" count="0" type="stmt"/>
<line num="21" count="0" type="stmt"/>
<line num="24" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="25" count="0" type="stmt"/>
<line num="28" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="29" count="0" type="stmt"/>
<line num="32" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="33" count="0" type="stmt"/>
<line num="36" count="0" type="stmt"/>
<line num="45" count="0" type="stmt"/>
<line num="46" count="0" type="stmt"/>
<line num="54" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="55" count="0" type="stmt"/>
<line num="57" count="0" type="stmt"/>
<line num="58" count="0" type="stmt"/>
<line num="66" count="0" type="stmt"/>
<line num="76" count="0" type="stmt"/>
</file>
</package>
<package name="infrastructure.db">
<metrics statements="25" coveredstatements="0" conditionals="8" coveredconditionals="0" methods="5" coveredmethods="0"/>
<file name="DatabaseConnection.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\infrastructure\db\DatabaseConnection.js">
<metrics statements="25" coveredstatements="0" conditionals="8" coveredconditionals="0" methods="5" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="9" count="0" type="stmt"/>
<line num="16" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="17" count="0" type="stmt"/>
<line num="18" count="0" type="stmt"/>
<line num="21" count="0" type="stmt"/>
<line num="22" count="0" type="stmt"/>
<line num="26" count="0" type="stmt"/>
<line num="27" count="0" type="stmt"/>
<line num="29" count="0" type="stmt"/>
<line num="30" count="0" type="stmt"/>
<line num="39" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="40" count="0" type="stmt"/>
<line num="42" count="0" type="stmt"/>
<line num="49" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="50" count="0" type="stmt"/>
<line num="51" count="0" type="stmt"/>
<line num="52" count="0" type="stmt"/>
<line num="61" count="0" type="stmt"/>
<line num="62" count="0" type="stmt"/>
<line num="63" count="0" type="stmt"/>
<line num="65" count="0" type="stmt"/>
<line num="66" count="0" type="stmt"/>
<line num="72" count="0" type="stmt"/>
<line num="74" count="0" type="stmt"/>
</file>
</package>
<package name="infrastructure.repositories">
<metrics statements="24" coveredstatements="0" conditionals="4" coveredconditionals="0" methods="9" coveredmethods="0"/>
<file name="UserRepository.js" path="D:\munka\Egyetem\25_26_II\GKNB_MSTM071\Backend\negyedik gyakorlat\src\infrastructure\repositories\UserRepository.js">
<metrics statements="24" coveredstatements="0" conditionals="4" coveredconditionals="0" methods="9" coveredmethods="0"/>
<line num="1" count="0" type="stmt"/>
<line num="2" count="0" type="stmt"/>
<line num="10" count="0" type="stmt"/>
<line num="11" count="0" type="stmt"/>
<line num="20" count="0" type="stmt"/>
<line num="24" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="25" count="0" type="stmt"/>
<line num="28" count="0" type="stmt"/>
<line num="37" count="0" type="stmt"/>
<line num="41" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="42" count="0" type="stmt"/>
<line num="45" count="0" type="stmt"/>
<line num="53" count="0" type="stmt"/>
<line num="57" count="0" type="stmt"/>
<line num="66" count="0" type="stmt"/>
<line num="74" count="0" type="stmt"/>
<line num="83" count="0" type="stmt"/>
<line num="93" count="0" type="stmt"/>
<line num="102" count="0" type="stmt"/>
<line num="103" count="0" type="stmt"/>
<line num="106" count="0" type="stmt"/>
<line num="108" count="0" type="stmt"/>
<line num="119" count="0" type="stmt"/>
<line num="130" count="0" type="stmt"/>
</file>
</package>
</project>
</coverage>
File diff suppressed because one or more lines are too long
@@ -1,394 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/controllers/AuthController.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/controllers</a> AuthController.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/26</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/10</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/26</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const RegisterUserCommand = <span class="cstat-no" title="statement not covered" >require('../../application/auth/commands/RegisterUserCommand');</span>
const LoginUserCommand = <span class="cstat-no" title="statement not covered" >require('../../application/auth/commands/LoginUserCommand');</span>
&nbsp;
/**
* Auth Controller
* Authentication endpoints using CQRS Commands with cookie-based JWT
*/
class AuthController {
<span class="fstat-no" title="function not covered" > co</span>nstructor(registerUserCommandHandler, loginUserCommandHandler, jwtService) {
<span class="cstat-no" title="statement not covered" > this.registerUserCommandHandler = registerUserCommandHandler;</span>
<span class="cstat-no" title="statement not covered" > this.loginUserCommandHandler = loginUserCommandHandler;</span>
<span class="cstat-no" title="statement not covered" > this.jwtService = jwtService;</span>
}
&nbsp;
/**
* POST /api/auth/register - User regisztráció
*/
<span class="fstat-no" title="function not covered" > as</span>ync register(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
const { name, email, password } = <span class="cstat-no" title="statement not covered" >req.body;</span>
&nbsp;
const command = <span class="cstat-no" title="statement not covered" >new RegisterUserCommand(name, email, password);</span>
const result = <span class="cstat-no" title="statement not covered" >await this.registerUserCommandHandler.handle(command);</span>
&nbsp;
// Set JWT token in httpOnly cookie
<span class="cstat-no" title="statement not covered" > res.cookie(</span>
this.jwtService.getCookieName(),
result.token,
this.jwtService.getCookieOptions()
);
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(201).json({</span>
message: 'User registered successfully',
data: {
user: result.user
}
});
} catch (error) {
// Validációs hibák -&gt; 400
const status = <span class="cstat-no" title="statement not covered" >error.message.includes('required') || </span>
error.message.includes('already exists') ||
error.message.includes('Invalid') ||
error.message.includes('must be') ? 400 : 500;
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(status).json({ error: error.message });</span>
}
}
&nbsp;
/**
* POST /api/auth/login - User bejelentkezés
*/
<span class="fstat-no" title="function not covered" > as</span>ync login(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
const { email, password } = <span class="cstat-no" title="statement not covered" >req.body;</span>
&nbsp;
const command = <span class="cstat-no" title="statement not covered" >new LoginUserCommand(email, password);</span>
const result = <span class="cstat-no" title="statement not covered" >await this.loginUserCommandHandler.handle(command);</span>
&nbsp;
// Set JWT token in httpOnly cookie
<span class="cstat-no" title="statement not covered" > res.cookie(</span>
this.jwtService.getCookieName(),
result.token,
this.jwtService.getCookieOptions()
);
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(200).json({</span>
message: 'Login successful',
data: {
user: result.user
}
});
} catch (error) {
// Validációs vagy auth hibák -&gt; 401
const status = <span class="cstat-no" title="statement not covered" >error.message.includes('Invalid') || </span>
error.message.includes('required') ? 401 : 500;
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(status).json({ error: error.message });</span>
}
}
&nbsp;
/**
* POST /api/auth/logout - User kijelentkezés
*/
<span class="fstat-no" title="function not covered" > as</span>ync logout(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
// Clear the auth cookie
<span class="cstat-no" title="statement not covered" > res.clearCookie(this.jwtService.getCookieName(), {</span>
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
path: '/'
});
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(200).json({</span>
message: 'Logout successful'
});
} catch (error) {
<span class="cstat-no" title="statement not covered" > res.status(500).json({ error: error.message });</span>
}
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = AuthController;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,397 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/controllers/UserController.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/controllers</a> UserController.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/39</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/39</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a>
<a name='L105'></a><a href='#L105'>105</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const GetMeQuery = <span class="cstat-no" title="statement not covered" >require('../../application/user/queries/GetMeQuery');</span>
const GetAllUsersQuery = <span class="cstat-no" title="statement not covered" >require('../../application/user/queries/GetAllUsersQuery');</span>
const GetUserByIdQuery = <span class="cstat-no" title="statement not covered" >require('../../application/user/queries/GetUserByIdQuery');</span>
const UpdateUserProfileCommand = <span class="cstat-no" title="statement not covered" >require('../../application/user/commands/UpdateUserProfileCommand');</span>
&nbsp;
/**
* User Controller
* User-related endpoints using CQRS pattern (protected by JWT)
*/
class UserController {
<span class="fstat-no" title="function not covered" > co</span>nstructor(getMeQueryHandler, getAllUsersQueryHandler, getUserByIdQueryHandler, updateUserProfileCommandHandler) {
<span class="cstat-no" title="statement not covered" > this.getMeQueryHandler = getMeQueryHandler;</span>
<span class="cstat-no" title="statement not covered" > this.getAllUsersQueryHandler = getAllUsersQueryHandler;</span>
<span class="cstat-no" title="statement not covered" > this.getUserByIdQueryHandler = getUserByIdQueryHandler;</span>
<span class="cstat-no" title="statement not covered" > this.updateUserProfileCommandHandler = updateUserProfileCommandHandler;</span>
}
&nbsp;
/**
* GET /api/users/me - Bejelentkezett user adatai (protected)
*/
<span class="fstat-no" title="function not covered" > as</span>ync getMe(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
// req.user-t az authMiddleware tölti ki a JWT-ből
const userId = <span class="cstat-no" title="statement not covered" >req.user.userId;</span>
&nbsp;
const query = <span class="cstat-no" title="statement not covered" >new GetMeQuery(userId);</span>
const user = <span class="cstat-no" title="statement not covered" >await this.getMeQueryHandler.handle(query);</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(200).json({</span>
message: 'User retrieved successfully',
data: user
});
} catch (error) {
const status = <span class="cstat-no" title="statement not covered" >error.message.includes('not found') ? 404 : 500;</span>
<span class="cstat-no" title="statement not covered" > res.status(status).json({ error: error.message });</span>
}
}
&nbsp;
/**
* GET /api/users - Összes user lekérése (protected)
*/
<span class="fstat-no" title="function not covered" > as</span>ync getAll(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
const query = <span class="cstat-no" title="statement not covered" >new GetAllUsersQuery();</span>
const users = <span class="cstat-no" title="statement not covered" >await this.getAllUsersQueryHandler.handle(query);</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(200).json({</span>
message: 'Users retrieved successfully',
data: users,
count: users.length
});
} catch (error) {
<span class="cstat-no" title="statement not covered" > res.status(500).json({ error: error.message });</span>
}
}
&nbsp;
/**
* GET /api/users/:id - User lekérése ID alapján (protected)
*/
<span class="fstat-no" title="function not covered" > as</span>ync getById(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
const { id } = <span class="cstat-no" title="statement not covered" >req.params;</span>
const userId = <span class="cstat-no" title="statement not covered" >parseInt(id);</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (isNaN(userId)) {</span>
<span class="cstat-no" title="statement not covered" > return res.status(400).json({ error: 'Invalid user ID' });</span>
}
&nbsp;
const query = <span class="cstat-no" title="statement not covered" >new GetUserByIdQuery(userId);</span>
const user = <span class="cstat-no" title="statement not covered" >await this.getUserByIdQueryHandler.handle(query);</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(200).json({</span>
message: 'User retrieved successfully',
data: user
});
} catch (error) {
const status = <span class="cstat-no" title="statement not covered" >error.message.includes('not found') ? 404 : 500;</span>
<span class="cstat-no" title="statement not covered" > res.status(status).json({ error: error.message });</span>
}
}
&nbsp;
/**
* PUT /api/users/me - User profil frissítése (protected)
*/
<span class="fstat-no" title="function not covered" > as</span>ync updateMe(req, res) {
<span class="cstat-no" title="statement not covered" > try {</span>
const userId = <span class="cstat-no" title="statement not covered" >req.user.userId;</span>
const { name } = <span class="cstat-no" title="statement not covered" >req.body;</span>
&nbsp;
const command = <span class="cstat-no" title="statement not covered" >new UpdateUserProfileCommand(userId, name);</span>
const user = <span class="cstat-no" title="statement not covered" >await this.updateUserProfileCommandHandler.handle(command);</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > res.status(200).json({</span>
message: 'Profile updated successfully',
data: user
});
} catch (error) {
const status = <span class="cstat-no" title="statement not covered" >error.message.includes('required') ? 400 : 500;</span>
<span class="cstat-no" title="statement not covered" > res.status(status).json({ error: error.message });</span>
}
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = UserController;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,131 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/controllers</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> api/controllers</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/65</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/18</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/9</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/65</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="AuthController.js"><a href="AuthController.js.html">AuthController.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="26" class="abs low">0/26</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="10" class="abs low">0/10</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="26" class="abs low">0/26</td>
</tr>
<tr>
<td class="file low" data-value="UserController.js"><a href="UserController.js.html">UserController.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="39" class="abs low">0/39</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="39" class="abs low">0/39</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,217 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/middlewares/authMiddleware.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/middlewares</a> authMiddleware.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/11</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/11</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const JwtService = <span class="cstat-no" title="statement not covered" >require('../../application/services/JwtService');</span>
&nbsp;
const jwtService = <span class="cstat-no" title="statement not covered" >new JwtService();</span>
&nbsp;
/**
* Authentication Middleware - JWT token ellenőrzés (Cookie-based)
*
* Ezt a middleware-t használd protected route-okon!
*
* Példa használat:
* router.get('/me', authMiddleware, userController.getMe);
*/
function <span class="fstat-no" title="function not covered" >authMiddleware(</span>req, res, next) {
<span class="cstat-no" title="statement not covered" > try {</span>
// 1. Token kinyerése cookieból
const token = <span class="cstat-no" title="statement not covered" >jwtService.extractTokenFromCookies(req.cookies);</span>
<span class="cstat-no" title="statement not covered" > if (!token) {</span>
<span class="cstat-no" title="statement not covered" > return res.status(401).json({ </span>
error: 'Authentication required',
message: 'No token provided in cookies'
});
}
&nbsp;
// 2. Token verifikálása
const decoded = <span class="cstat-no" title="statement not covered" >jwtService.verifyToken(token);</span>
&nbsp;
// 3. User adatok elhelyezése req.user-ben (controller-ek használhatják)
<span class="cstat-no" title="statement not covered" > req.user = {</span>
userId: decoded.userId,
email: decoded.email
};
&nbsp;
// 4. Folytatás
<span class="cstat-no" title="statement not covered" > next();</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > return res.status(401).json({ </span>
error: 'Authentication failed',
message: error.message
});
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = authMiddleware;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,151 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/middlewares/corsMiddleware.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/middlewares</a> corsMiddleware.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/4</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const cors = <span class="cstat-no" title="statement not covered" >require('cors');</span>
&nbsp;
// Engedélyezett origin-ek whitelist (környezeti változóból)
const allowedOrigins = <span class="cstat-no" title="statement not covered" >process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'];</span>
&nbsp;
const corsOptions = <span class="cstat-no" title="statement not covered" >{</span>
origin: <span class="fstat-no" title="function not covered" >fu</span>nction (origin, callback) {
// TODO 1: Ha nincs origin (pl. Postman, curl, backend-backend hívás), engedélyezd
// Tipp: if (!origin) return callback(null, true);
// TODO 2: Ha az origin benne van az allowedOrigins-ban, engedélyezd
// Tipp: if (allowedOrigins.includes(origin)) return callback(null, true);
// TODO 3: Egyébként tiltsd le CORS hibával
// Tipp: callback(new Error('Not allowed by CORS'));
},
credentials: true, // Cookie/Auth header engedélyezése
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization']
};
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = cors(corsOptions);</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,146 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/middlewares</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> api/middlewares</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/17</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/17</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="authMiddleware.js"><a href="authMiddleware.js.html">authMiddleware.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="11" class="abs low">0/11</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="11" class="abs low">0/11</td>
</tr>
<tr>
<td class="file low" data-value="corsMiddleware.js"><a href="corsMiddleware.js.html">corsMiddleware.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
</tr>
<tr>
<td class="file low" data-value="scopeMiddleware.js"><a href="scopeMiddleware.js.html">scopeMiddleware.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,139 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/middlewares/scopeMiddleware.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/middlewares</a> scopeMiddleware.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/2</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Request szintű DI scope létrehozása
* Middleware ami minden kéréshez új DI scope-ot készít
*/
function <span class="fstat-no" title="function not covered" >scopeMiddleware(</span>container) {
<span class="cstat-no" title="statement not covered" > return <span class="fstat-no" title="function not covered" >(r</span>eq, res, next) =&gt; {</span>
// TODO 1: Hozz létre request-specifikus scope-ot
// Tipp: const scope = container.createScope();
// TODO 2: Tárold el a scope-ot req.scope alatt
// Tipp: req.scope = scope;
// TODO 3: Hívd meg a next()-et
// Tipp: next();
};
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = scopeMiddleware;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,214 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/routers/authRoutes.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/routers</a> authRoutes.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/13</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/9</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const express = <span class="cstat-no" title="statement not covered" >require('express');</span>
&nbsp;
/**
* Auth Routes
* Public endpoints (nincs JWT védelem)
*
* @param {Container} container - DI Container
*/
function <span class="fstat-no" title="function not covered" >createAuthRoutes(</span>container) {
const router = <span class="cstat-no" title="statement not covered" >express.Router();</span>
&nbsp;
// AuthController lekérése a DI Container-ből
const authController = <span class="cstat-no" title="statement not covered" >container.resolve('AuthController');</span>
&nbsp;
/**
* POST /api/auth/register - User regisztráció
* Body: { name, email, password }
* Response: { user, token }
*/
<span class="cstat-no" title="statement not covered" > router.post('/register', <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >authController.register(req, res))</span>;</span>
&nbsp;
/**
* POST /api/auth/login - User bejelentkezés
* Body: { email, password }
* Response: { user, token }
*/
<span class="cstat-no" title="statement not covered" > router.post('/login', <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >authController.login(req, res))</span>;</span>
&nbsp;
/**
* POST /api/auth/logout - User kijelentkezés
* Clears the authentication cookie
*/
<span class="cstat-no" title="statement not covered" > router.post('/logout', <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >authController.logout(req, res))</span>;</span>
&nbsp;
/**
* OPTIONS /api/auth/* - CORS preflight
*/
<span class="cstat-no" title="statement not covered" > router.options('*', <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >res.sendStatus(204))</span>;</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > return router;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = createAuthRoutes;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,131 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/routers</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> api/routers</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/29</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/11</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/20</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="authRoutes.js"><a href="authRoutes.js.html">authRoutes.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="13" class="abs low">0/13</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="9" class="abs low">0/9</td>
</tr>
<tr>
<td class="file low" data-value="userRoutes.js"><a href="userRoutes.js.html">userRoutes.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="16" class="abs low">0/16</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="6" class="abs low">0/6</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="11" class="abs low">0/11</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,232 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for api/routers/userRoutes.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">api/routers</a> userRoutes.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/11</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const express = <span class="cstat-no" title="statement not covered" >require('express');</span>
const authMiddleware = <span class="cstat-no" title="statement not covered" >require('../middlewares/authMiddleware');</span>
&nbsp;
/**
* User Routes
* Protected endpoints (JWT authentication required)
*
* @param {Container} container - DI Container
*/
function <span class="fstat-no" title="function not covered" >createUserRoutes(</span>container) {
const router = <span class="cstat-no" title="statement not covered" >express.Router();</span>
&nbsp;
// UserController lekérése a DI Container-ből
const userController = <span class="cstat-no" title="statement not covered" >container.resolve('UserController');</span>
&nbsp;
/**
* GET /api/users/me - Bejelentkezett user adatai
* Headers: Authorization: Bearer &lt;token&gt;
*/
<span class="cstat-no" title="statement not covered" > router.get('/me', authMiddleware, <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >userController.getMe(req, res))</span>;</span>
&nbsp;
/**
* PUT /api/users/me - User profil frissítése
* Headers: Authorization: Bearer &lt;token&gt;
* Body: { name }
*/
<span class="cstat-no" title="statement not covered" > router.put('/me', authMiddleware, <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >userController.updateMe(req, res))</span>;</span>
&nbsp;
/**
* GET /api/users - Összes user lekérése (protected)
* Headers: Authorization: Bearer &lt;token&gt;
*/
<span class="cstat-no" title="statement not covered" > router.get('/', authMiddleware, <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >userController.getAll(req, res))</span>;</span>
&nbsp;
/**
* GET /api/users/:id - User lekérése ID alapján (protected)
* Headers: Authorization: Bearer &lt;token&gt;
*/
<span class="cstat-no" title="statement not covered" > router.get('/:id', authMiddleware, <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >userController.getById(req, res))</span>;</span>
&nbsp;
/**
* OPTIONS /api/users/* - CORS preflight
*/
<span class="cstat-no" title="statement not covered" > router.options('*', <span class="fstat-no" title="function not covered" >(r</span>eq, res) =&gt; <span class="cstat-no" title="statement not covered" >res.sendStatus(204))</span>;</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > return router;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = createUserRoutes;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,121 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/auth/commands/LoginUserCommand.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/auth/commands</a> LoginUserCommand.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/3</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Login User Command
* Command object for user login
*/
class LoginUserCommand {
<span class="fstat-no" title="function not covered" > co</span>nstructor(email, password) {
<span class="cstat-no" title="statement not covered" > this.email = email;</span>
<span class="cstat-no" title="statement not covered" > this.password = password;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = LoginUserCommand;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,265 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/auth/commands/LoginUserCommandHandler.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/auth/commands</a> LoginUserCommandHandler.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/17</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/17</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const bcrypt = <span class="cstat-no" title="statement not covered" >require('bcryptjs');</span>
const JwtService = <span class="cstat-no" title="statement not covered" >require('../../services/JwtService');</span>
&nbsp;
const jwtService = <span class="cstat-no" title="statement not covered" >new JwtService();</span>
&nbsp;
/**
* Login User Command Handler
* Handles user login authentication
*/
class LoginUserCommandHandler {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma) {
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
}
&nbsp;
/**
* Execute login command
* @param {LoginUserCommand} command
* @returns {Promise&lt;Object&gt;} { user, token }
*/
<span class="fstat-no" title="function not covered" > as</span>ync handle(command) {
const { email, password } = <span class="cstat-no" title="statement not covered" >command;</span>
&nbsp;
// Validáció
<span class="cstat-no" title="statement not covered" > if (!email || !password) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Email and password are required');</span>
}
&nbsp;
// User keresése email alapján
const user = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findUnique({</span>
where: { email }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!user) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Invalid email or password');</span>
}
&nbsp;
// Jelszó ellenőrzése
const isPasswordValid = <span class="cstat-no" title="statement not covered" >await bcrypt.compare(password, user.password);</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!isPasswordValid) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Invalid email or password');</span>
}
&nbsp;
// JWT token generálása
const token = <span class="cstat-no" title="statement not covered" >jwtService.generateToken({</span>
userId: user.id,
email: user.email
});
&nbsp;
// Jelszót ne adjuk vissza
const { password: _, ...userWithoutPassword } = <span class="cstat-no" title="statement not covered" >user;</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > return {</span>
user: userWithoutPassword,
token
};
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = LoginUserCommandHandler;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,124 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/auth/commands/RegisterUserCommand.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/auth/commands</a> RegisterUserCommand.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/4</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Register User Command
* Command object for user registration
*/
class RegisterUserCommand {
<span class="fstat-no" title="function not covered" > co</span>nstructor(name, email, password) {
<span class="cstat-no" title="statement not covered" > this.name = name;</span>
<span class="cstat-no" title="statement not covered" > this.email = email;</span>
<span class="cstat-no" title="statement not covered" > this.password = password;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = RegisterUserCommand;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,334 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/auth/commands/RegisterUserCommandHandler.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/auth/commands</a> RegisterUserCommandHandler.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/25</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/13</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/25</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const bcrypt = <span class="cstat-no" title="statement not covered" >require('bcryptjs');</span>
const JwtService = <span class="cstat-no" title="statement not covered" >require('../../services/JwtService');</span>
&nbsp;
const jwtService = <span class="cstat-no" title="statement not covered" >new JwtService();</span>
&nbsp;
/**
* Register User Command Handler
* Handles user registration business logic
*/
class RegisterUserCommandHandler {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma, emailService) {
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
<span class="cstat-no" title="statement not covered" > this.emailService = emailService;</span>
}
&nbsp;
/**
* Execute user registration command
* @param {RegisterUserCommand} command
* @returns {Promise&lt;Object&gt;} { user, token }
*/
<span class="fstat-no" title="function not covered" > as</span>ync handle(command) {
const { name, email, password } = <span class="cstat-no" title="statement not covered" >command;</span>
&nbsp;
// Validáció
<span class="cstat-no" title="statement not covered" > if (!name || !email || !password) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Name, email and password are required');</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > if (password.length &lt; 6) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Password must be at least 6 characters long');</span>
}
&nbsp;
// Email formátum ellenőrzés
const emailRegex = <span class="cstat-no" title="statement not covered" >/^[^\s@]+@[^\s@]+\.[^\s@]+$/;</span>
<span class="cstat-no" title="statement not covered" > if (!emailRegex.test(email)) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Invalid email format');</span>
}
&nbsp;
// Ellenőrizzük, hogy létezik-e már a user
const existingUser = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findUnique({</span>
where: { email }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > if (existingUser) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('User with this email already exists');</span>
}
&nbsp;
// Jelszó hashelése (bcrypt)
const hashedPassword = <span class="cstat-no" title="statement not covered" >await bcrypt.hash(password, 10);</span>
&nbsp;
// User létrehozása
const user = <span class="cstat-no" title="statement not covered" >await this.prisma.user.create({</span>
data: {
name,
email,
password: hashedPassword
}
});
&nbsp;
// Welcome email küldése (async, nem várunk rá)
<span class="cstat-no" title="statement not covered" > if (this.emailService) {</span>
<span class="cstat-no" title="statement not covered" > this.emailService.sendWelcomeEmail(email, name).catch(<span class="fstat-no" title="function not covered" >er</span>r =&gt; {</span>
<span class="cstat-no" title="statement not covered" > console.error('❌ Failed to send welcome email:', err.message);</span>
});
}
&nbsp;
// JWT token generálása
const token = <span class="cstat-no" title="statement not covered" >jwtService.generateToken({</span>
userId: user.id,
email: user.email
});
&nbsp;
// Jelszót ne adjuk vissza a response-ban
const { password: _, ...userWithoutPassword } = <span class="cstat-no" title="statement not covered" >user;</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > return {</span>
user: userWithoutPassword,
token
};
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = RegisterUserCommandHandler;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,161 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/auth/commands</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> application/auth/commands</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/49</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/21</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/7</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/49</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="LoginUserCommand.js"><a href="LoginUserCommand.js.html">LoginUserCommand.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
</tr>
<tr>
<td class="file low" data-value="LoginUserCommandHandler.js"><a href="LoginUserCommandHandler.js.html">LoginUserCommandHandler.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="17" class="abs low">0/17</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="17" class="abs low">0/17</td>
</tr>
<tr>
<td class="file low" data-value="RegisterUserCommand.js"><a href="RegisterUserCommand.js.html">RegisterUserCommand.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
</tr>
<tr>
<td class="file low" data-value="RegisterUserCommandHandler.js"><a href="RegisterUserCommandHandler.js.html">RegisterUserCommandHandler.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="13" class="abs low">0/13</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,256 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/services/Container.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">application/services</a> Container.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>4/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1/1</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line high'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Dependency Injection Container
* Supports singleton, transient, and scoped lifetimes
*/
class Container {
constructor() {
// TODO 1: Inicializáld a services Map-et (singleton instance-ok tárolása)
// TODO 2: Inicializáld a factories Map-et (factory függvények tárolása)
// TODO 3: Inicializáld a lifetimes Map-et (lifecycle típusok tárolása)
// Példa inicializálás:
// this.services = new Map();
// this.factories = new Map();
// this.lifetimes = new Map();
}
&nbsp;
register(name, factory, lifetime = 'singleton') {
// TODO 4: Tárold el a factory függvényt (this.factories.set(name, factory))
// TODO 5: Tárold el a lifetime típust (this.lifetimes.set(name, lifetime))
// TODO 6: Ha a lifetime === 'singleton', azonnal példányosítsd:
// - Hívd meg a factory-t: const instance = factory();
// - Tárold el: this.services.set(name, instance);
}
&nbsp;
resolve(name, scope = null) {
// TODO 7: Ha a service regisztrálva van mint 'scoped' ÉS van scope paraméter:
// - Ellenőrizd: if (scope &amp;&amp; scope.has(name)) return scope.get(name);
// - Ha nincs még a scope-ban, példányosítsd és tárold:
// const instance = this.factories.get(name)();
// scope.set(name, instance);
// return instance;
// TODO 8: Ha singleton, add vissza a services-ből:
// if (this.lifetimes.get(name) === 'singleton') {
// return this.services.get(name);
// }
// TODO 9: Ha transient, minden alkalommal hívj egy új factory-t:
// if (this.lifetimes.get(name) === 'transient') {
// return this.factories.get(name)();
// }
// TODO 10: Ha nem regisztrált a service, dobj hibát:
// throw new Error(`Service '${name}' is not registered`);
}
&nbsp;
createScope() {
// TODO 11: Hozz létre egy új Map-et az scoped instance-oknak
// TODO 12: Térj vissza egy objektummal ami tartalmaz egy resolve metódust:
// const scopeMap = new Map();
// return {
// resolve: (name) =&gt; this.resolve(name, scopeMap)
// };
}
}
&nbsp;
module.exports = Container;
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,178 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/services/EmailService.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">application/services</a> EmailService.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/4</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Email Service
* Nodemailer + Handlebars template based email sending
*
* TODO: Implement by students
*/
class EmailService {
<span class="fstat-no" title="function not covered" > co</span>nstructor() {
// TODO 1: Hozz létre Nodemailer transportot Ethereal tesztelő SMTP-vel
// this.transporter = nodemailer.createTransport({
// host: 'smtp.ethereal.email',
// port: 587,
// secure: false, // TLS
// auth: {
// user: process.env.ETHEREAL_USER || 'your-test-email@ethereal.email',
// pass: process.env.ETHEREAL_PASS || 'your-test-password'
// }
// });
<span class="cstat-no" title="statement not covered" > console.log('📧 EmailService initialized');</span>
}
&nbsp;
<span class="fstat-no" title="function not covered" > as</span>ync sendWelcomeEmail(userEmail, userName) {
// TODO 2-6: Implement email sending with Handlebars template
// For now, just log to console
<span class="cstat-no" title="statement not covered" > console.log(`📧 Would send welcome email to ${userEmail} (${userName})`);</span>
<span class="cstat-no" title="statement not covered" > return true;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = EmailService;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,427 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/services/JwtService.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">application/services</a> JwtService.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/29</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/20</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/29</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a>
<a name='L105'></a><a href='#L105'>105</a>
<a name='L106'></a><a href='#L106'>106</a>
<a name='L107'></a><a href='#L107'>107</a>
<a name='L108'></a><a href='#L108'>108</a>
<a name='L109'></a><a href='#L109'>109</a>
<a name='L110'></a><a href='#L110'>110</a>
<a name='L111'></a><a href='#L111'>111</a>
<a name='L112'></a><a href='#L112'>112</a>
<a name='L113'></a><a href='#L113'>113</a>
<a name='L114'></a><a href='#L114'>114</a>
<a name='L115'></a><a href='#L115'>115</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const jwt = <span class="cstat-no" title="statement not covered" >require('jsonwebtoken');</span>
&nbsp;
/**
* JWT Service
* Handles JWT token generation, verification, and cookie management
*/
class JwtService {
<span class="fstat-no" title="function not covered" > co</span>nstructor() {
<span class="cstat-no" title="statement not covered" > this.secret = process.env.JWT_SECRET || 'default-secret-change-me';</span>
<span class="cstat-no" title="statement not covered" > this.expiresIn = process.env.JWT_EXPIRES_IN || '1h';</span>
<span class="cstat-no" title="statement not covered" > this.cookieName = 'auth_token';</span>
}
&nbsp;
/**
* Generate JWT token
* @param {Object} payload - { userId, email }
* @returns {string} JWT token
*/
<span class="fstat-no" title="function not covered" > ge</span>nerateToken(payload) {
<span class="cstat-no" title="statement not covered" > return jwt.sign(payload, this.secret, { expiresIn: this.expiresIn });</span>
}
&nbsp;
/**
* Verify JWT token
* @param {string} token - JWT token
* @returns {Object} Decoded payload
*/
<span class="fstat-no" title="function not covered" > ve</span>rifyToken(token) {
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > return jwt.verify(token, this.secret);</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > throw new Error('Invalid or expired token');</span>
}
}
&nbsp;
/**
* Extract token from Authorization header (Bearer token)
* @param {string} authHeader - Authorization header value
* @returns {string|null} Token or null
*/
<span class="fstat-no" title="function not covered" > ex</span>tractTokenFromHeader(authHeader) {
<span class="cstat-no" title="statement not covered" > if (!authHeader) {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
}
&nbsp;
const parts = <span class="cstat-no" title="statement not covered" >authHeader.split(' ');</span>
<span class="cstat-no" title="statement not covered" > if (parts.length !== 2 || parts[0] !== 'Bearer') {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > return parts[1];</span>
}
&nbsp;
/**
* Extract token from cookies
* @param {Object} cookies - Request cookies object
* @returns {string|null} Token or null
*/
<span class="fstat-no" title="function not covered" > ex</span>tractTokenFromCookies(cookies) {
<span class="cstat-no" title="statement not covered" > if (!cookies || !cookies[this.cookieName]) {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > return cookies[this.cookieName];</span>
}
&nbsp;
/**
* Get cookie options for setting JWT cookie
* @returns {Object} Cookie options
*/
<span class="fstat-no" title="function not covered" > ge</span>tCookieOptions() {
const isProduction = <span class="cstat-no" title="statement not covered" >process.env.NODE_ENV === 'production';</span>
<span class="cstat-no" title="statement not covered" > return {</span>
httpOnly: true, // Prevents XSS attacks
secure: isProduction, // HTTPS only in production
sameSite: 'strict', // CSRF protection
maxAge: this._getMaxAge(),
path: '/'
};
}
&nbsp;
/**
* Get cookie max age in milliseconds
* @private
* @returns {number}
*/
<span class="fstat-no" title="function not covered" > _g</span>etMaxAge() {
// Parse JWT_EXPIRES_IN (e.g., "1h", "7d")
const expiresIn = <span class="cstat-no" title="statement not covered" >this.expiresIn;</span>
<span class="cstat-no" title="statement not covered" > if (expiresIn.endsWith('h')) {</span>
<span class="cstat-no" title="statement not covered" > return parseInt(expiresIn) * 60 * 60 * 1000;</span>
} else <span class="cstat-no" title="statement not covered" >if (expiresIn.endsWith('d')) {</span>
<span class="cstat-no" title="statement not covered" > return parseInt(expiresIn) * 24 * 60 * 60 * 1000;</span>
} else <span class="cstat-no" title="statement not covered" >if (expiresIn.endsWith('m')) {</span>
<span class="cstat-no" title="statement not covered" > return parseInt(expiresIn) * 60 * 1000;</span>
}
// Default: 1 hour
<span class="cstat-no" title="statement not covered" > return 60 * 60 * 1000;</span>
}
&nbsp;
/**
* Get cookie name
* @returns {string}
*/
<span class="fstat-no" title="function not covered" > ge</span>tCookieName() {
<span class="cstat-no" title="statement not covered" > return this.cookieName;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = JwtService;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,146 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/services</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> application/services</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">2.94% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1/34</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">9.09% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/22</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">28.57% </span>
<span class="quiet">Functions</span>
<span class='fraction'>4/14</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">2.94% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1/34</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file high" data-value="Container.js"><a href="Container.js.html">Container.js</a></td>
<td data-value="100" class="pic high">
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="1" class="abs high">1/1</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="2" class="abs high">2/2</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="4" class="abs high">4/4</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="1" class="abs high">1/1</td>
</tr>
<tr>
<td class="file low" data-value="EmailService.js"><a href="EmailService.js.html">EmailService.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
</tr>
<tr>
<td class="file low" data-value="JwtService.js"><a href="JwtService.js.html">JwtService.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="29" class="abs low">0/29</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="20" class="abs low">0/20</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="29" class="abs low">0/29</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,121 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/commands/UpdateUserProfileCommand.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/commands</a> UpdateUserProfileCommand.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/3</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Update User Profile Command
* Command object for updating user profile
*/
class UpdateUserProfileCommand {
<span class="fstat-no" title="function not covered" > co</span>nstructor(userId, name) {
<span class="cstat-no" title="statement not covered" > this.userId = userId;</span>
<span class="cstat-no" title="statement not covered" > this.name = name;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = UpdateUserProfileCommand;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,181 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/commands/UpdateUserProfileCommandHandler.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/commands</a> UpdateUserProfileCommandHandler.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/8</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Update User Profile Command Handler
* Handles user profile update logic
*/
class UpdateUserProfileCommandHandler {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma) {
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
}
&nbsp;
/**
* Execute update profile command
* @param {UpdateUserProfileCommand} command
* @returns {Promise&lt;Object&gt;} Updated user data
*/
<span class="fstat-no" title="function not covered" > as</span>ync handle(command) {
const { userId, name } = <span class="cstat-no" title="statement not covered" >command;</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!name) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Name is required');</span>
}
&nbsp;
const user = <span class="cstat-no" title="statement not covered" >await this.prisma.user.update({</span>
where: { id: userId },
data: { name }
});
&nbsp;
const { password, ...userWithoutPassword } = <span class="cstat-no" title="statement not covered" >user;</span>
<span class="cstat-no" title="statement not covered" > return userWithoutPassword;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = UpdateUserProfileCommandHandler;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,131 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/commands</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> application/user/commands</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/11</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/11</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="UpdateUserProfileCommand.js"><a href="UpdateUserProfileCommand.js.html">UpdateUserProfileCommand.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
</tr>
<tr>
<td class="file low" data-value="UpdateUserProfileCommandHandler.js"><a href="UpdateUserProfileCommandHandler.js.html">UpdateUserProfileCommandHandler.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,118 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries/GetAllUsersQuery.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/queries</a> GetAllUsersQuery.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/1</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Get All Users Query
* Query object for retrieving all users
*/
class GetAllUsersQuery {
<span class="fstat-no" title="function not covered" > co</span>nstructor() {
// No parameters needed for getting all users
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = GetAllUsersQuery;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,160 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries/GetAllUsersQueryHandler.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/queries</a> GetAllUsersQueryHandler.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/4</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Get All Users Query Handler
* Handles retrieval of all users
*/
class GetAllUsersQueryHandler {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma) {
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
}
&nbsp;
/**
* Execute get all users query
* @param {GetAllUsersQuery} query
* @returns {Promise&lt;Array&gt;} List of users without passwords
*/
<span class="fstat-no" title="function not covered" > as</span>ync handle(query) {
const users = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findMany({</span>
orderBy: { createdAt: 'desc' }
});
&nbsp;
// Remove passwords from all users
<span class="cstat-no" title="statement not covered" > return users.map(<span class="fstat-no" title="function not covered" >({</span> password, ...user }) =&gt; <span class="cstat-no" title="statement not covered" >user)</span>;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = GetAllUsersQueryHandler;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,118 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries/GetMeQuery.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/queries</a> GetMeQuery.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/2</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Get Me Query
* Query object for getting current authenticated user
*/
class GetMeQuery {
<span class="fstat-no" title="function not covered" > co</span>nstructor(userId) {
<span class="cstat-no" title="statement not covered" > this.userId = userId;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = GetMeQuery;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,178 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries/GetMeQueryHandler.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/queries</a> GetMeQueryHandler.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/8</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Get Me Query Handler
* Handles retrieval of current authenticated user
*/
class GetMeQueryHandler {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma) {
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
}
&nbsp;
/**
* Execute get me query
* @param {GetMeQuery} query
* @returns {Promise&lt;Object&gt;} User data without password
*/
<span class="fstat-no" title="function not covered" > as</span>ync handle(query) {
const { userId } = <span class="cstat-no" title="statement not covered" >query;</span>
&nbsp;
const user = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findUnique({</span>
where: { id: userId }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!user) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('User not found');</span>
}
&nbsp;
const { password, ...userWithoutPassword } = <span class="cstat-no" title="statement not covered" >user;</span>
<span class="cstat-no" title="statement not covered" > return userWithoutPassword;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = GetMeQueryHandler;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,118 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries/GetUserByIdQuery.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/queries</a> GetUserByIdQuery.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/2</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Get User By ID Query
* Query object for retrieving a user by ID
*/
class GetUserByIdQuery {
<span class="fstat-no" title="function not covered" > co</span>nstructor(userId) {
<span class="cstat-no" title="statement not covered" > this.userId = userId;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = GetUserByIdQuery;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,190 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries/GetUserByIdQueryHandler.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">application/user/queries</a> GetUserByIdQueryHandler.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/10</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/10</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Get User By ID Query Handler
* Handles retrieval of a specific user by ID
*/
class GetUserByIdQueryHandler {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma) {
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
}
&nbsp;
/**
* Execute get user by ID query
* @param {GetUserByIdQuery} query
* @returns {Promise&lt;Object&gt;} User data without password
*/
<span class="fstat-no" title="function not covered" > as</span>ync handle(query) {
const { userId } = <span class="cstat-no" title="statement not covered" >query;</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!userId || isNaN(userId)) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Valid user ID is required');</span>
}
&nbsp;
const user = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findUnique({</span>
where: { id: parseInt(userId) }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!user) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('User not found');</span>
}
&nbsp;
const { password, ...userWithoutPassword } = <span class="cstat-no" title="statement not covered" >user;</span>
<span class="cstat-no" title="statement not covered" > return userWithoutPassword;</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = GetUserByIdQueryHandler;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,191 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for application/user/queries</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> application/user/queries</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/28</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/10</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/27</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="GetAllUsersQuery.js"><a href="GetAllUsersQuery.js.html">GetAllUsersQuery.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
</tr>
<tr>
<td class="file low" data-value="GetAllUsersQueryHandler.js"><a href="GetAllUsersQueryHandler.js.html">GetAllUsersQueryHandler.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
</tr>
<tr>
<td class="file low" data-value="GetMeQuery.js"><a href="GetMeQuery.js.html">GetMeQuery.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
</tr>
<tr>
<td class="file low" data-value="GetMeQueryHandler.js"><a href="GetMeQueryHandler.js.html">GetMeQueryHandler.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
</tr>
<tr>
<td class="file low" data-value="GetUserByIdQuery.js"><a href="GetUserByIdQuery.js.html">GetUserByIdQuery.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
</tr>
<tr>
<td class="file low" data-value="GetUserByIdQueryHandler.js"><a href="GetUserByIdQueryHandler.js.html">GetUserByIdQueryHandler.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="10" class="abs low">0/10</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="6" class="abs low">0/6</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="10" class="abs low">0/10</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
@@ -1,224 +0,0 @@
body, html {
margin:0; padding: 0;
height: 100%;
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
font-size: 14px;
color:#333;
}
.small { font-size: 12px; }
*, *:after, *:before {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h1 { font-size: 20px; margin: 0;}
h2 { font-size: 14px; }
pre {
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
margin: 0;
padding: 0;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
a { color:#0074D9; text-decoration:none; }
a:hover { text-decoration:underline; }
.strong { font-weight: bold; }
.space-top1 { padding: 10px 0 0 0; }
.pad2y { padding: 20px 0; }
.pad1y { padding: 10px 0; }
.pad2x { padding: 0 20px; }
.pad2 { padding: 20px; }
.pad1 { padding: 10px; }
.space-left2 { padding-left:55px; }
.space-right2 { padding-right:20px; }
.center { text-align:center; }
.clearfix { display:block; }
.clearfix:after {
content:'';
display:block;
height:0;
clear:both;
visibility:hidden;
}
.fl { float: left; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
}
.quiet {
color: #7f7f7f;
color: rgba(0,0,0,0.5);
}
.quiet a { opacity: 0.7; }
.fraction {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 10px;
color: #555;
background: #E8E8E8;
padding: 4px 5px;
border-radius: 3px;
vertical-align: middle;
}
div.path a:link, div.path a:visited { color: #333; }
table.coverage {
border-collapse: collapse;
margin: 10px 0 0 0;
padding: 0;
}
table.coverage td {
margin: 0;
padding: 0;
vertical-align: top;
}
table.coverage td.line-count {
text-align: right;
padding: 0 5px 0 20px;
}
table.coverage td.line-coverage {
text-align: right;
padding-right: 10px;
min-width:20px;
}
table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 100%;
}
.missing-if-branch {
display: inline-block;
margin-right: 5px;
border-radius: 3px;
position: relative;
padding: 0 4px;
background: #333;
color: yellow;
}
.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.coverage-summary {
border-collapse: collapse;
width: 100%;
}
.coverage-summary tr { border-bottom: 1px solid #bbb; }
.keyline-all { border: 1px solid #ddd; }
.coverage-summary td, .coverage-summary th { padding: 10px; }
.coverage-summary tbody { border: 1px solid #bbb; }
.coverage-summary td { border-right: 1px solid #bbb; }
.coverage-summary td:last-child { border-right: none; }
.coverage-summary th {
text-align: left;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.file { border-right: none !important; }
.coverage-summary th.pct { }
.coverage-summary th.pic,
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs { text-align: right; }
.coverage-summary td.file { white-space: nowrap; }
.coverage-summary td.pic { min-width: 120px !important; }
.coverage-summary tfoot td { }
.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.status-line { height: 10px; }
/* yellow */
.cbranch-no { background: yellow !important; color: #111; }
/* dark red */
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
.low .chart { border:1px solid #C21F39 }
.highlighted,
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
background: #C21F39 !important;
}
/* medium red */
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
/* light red */
.low, .cline-no { background:#FCE1E5 }
/* light green */
.high, .cline-yes { background:rgb(230,245,208) }
/* medium green */
.cstat-yes { background:rgb(161,215,106) }
/* dark green */
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
.high .chart { border:1px solid rgb(77,146,33) }
/* dark yellow (gold) */
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
.medium .chart { border:1px solid #f9cd0b; }
/* light yellow */
.medium { background: #fff4c2; }
.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }
span.cline-neutral { background: #eaeaea; }
.coverage-summary td.empty {
opacity: .5;
padding-top: 4px;
padding-bottom: 4px;
line-height: 1;
color: #888;
}
.cover-fill, .cover-empty {
display:inline-block;
height: 12px;
}
.chart {
line-height: 0;
}
.cover-empty {
background: white;
}
.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -48px;
}
.footer, .push {
height: 48px;
}
@@ -1,87 +0,0 @@
/* eslint-disable */
var jumpToCode = (function init() {
// Classes of code we would like to highlight in the file view
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
// Elements to highlight in the file listing view
var fileListingElements = ['td.pct.low'];
// We don't want to select elements that are direct descendants of another match
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
// Selector that finds elements on the page to which we can jump
var selector =
fileListingElements.join(', ') +
', ' +
notSelector +
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
// The NodeList of matching elements
var missingCoverageElements = document.querySelectorAll(selector);
var currentIndex;
function toggleClass(index) {
missingCoverageElements
.item(currentIndex)
.classList.remove('highlighted');
missingCoverageElements.item(index).classList.add('highlighted');
}
function makeCurrent(index) {
toggleClass(index);
currentIndex = index;
missingCoverageElements.item(index).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}
function goToPrevious() {
var nextIndex = 0;
if (typeof currentIndex !== 'number' || currentIndex === 0) {
nextIndex = missingCoverageElements.length - 1;
} else if (missingCoverageElements.length > 1) {
nextIndex = currentIndex - 1;
}
makeCurrent(nextIndex);
}
function goToNext() {
var nextIndex = 0;
if (
typeof currentIndex === 'number' &&
currentIndex < missingCoverageElements.length - 1
) {
nextIndex = currentIndex + 1;
}
makeCurrent(nextIndex);
}
return function jump(event) {
if (
document.getElementById('fileSearch') === document.activeElement &&
document.activeElement != null
) {
// if we're currently focused on the search input, we don't want to navigate
return;
}
switch (event.which) {
case 78: // n
case 74: // j
goToNext();
break;
case 66: // b
case 75: // k
case 80: // p
goToPrevious();
break;
}
};
})();
window.addEventListener('keydown', jumpToCode);
@@ -1,265 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for domain/irepositories/IUserRepository.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">domain/irepositories</a> IUserRepository.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/7</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/7</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* User Repository Interface
* Defines contract for user data access
*/
class IUserRepository {
/**
* Find user by ID
* @param {number} id
* @returns {Promise&lt;User|null&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync findById(id) {
<span class="cstat-no" title="statement not covered" > throw new Error('Method findById() must be implemented');</span>
}
&nbsp;
/**
* Find user by email
* @param {string} email
* @returns {Promise&lt;User|null&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync findByEmail(email) {
<span class="cstat-no" title="statement not covered" > throw new Error('Method findByEmail() must be implemented');</span>
}
&nbsp;
/**
* Find all users
* @returns {Promise&lt;User[]&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync findAll() {
<span class="cstat-no" title="statement not covered" > throw new Error('Method findAll() must be implemented');</span>
}
&nbsp;
/**
* Create new user
* @param {User} user
* @returns {Promise&lt;User&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync create(user) {
<span class="cstat-no" title="statement not covered" > throw new Error('Method create() must be implemented');</span>
}
&nbsp;
/**
* Update existing user
* @param {User} user
* @returns {Promise&lt;User&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync update(user) {
<span class="cstat-no" title="statement not covered" > throw new Error('Method update() must be implemented');</span>
}
&nbsp;
/**
* Delete user by ID
* @param {number} id
* @returns {Promise&lt;boolean&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync delete(id) {
<span class="cstat-no" title="statement not covered" > throw new Error('Method delete() must be implemented');</span>
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = IUserRepository;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,116 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for domain/irepositories</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> domain/irepositories</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/7</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/7</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="IUserRepository.js"><a href="IUserRepository.js.html">IUserRepository.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="7" class="abs low">0/7</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="6" class="abs low">0/6</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="7" class="abs low">0/7</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,313 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for domain/models/User.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">domain/models</a> User.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/22</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/22</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* User Domain Model
* Pure domain entity with business logic validation
*/
class User {
<span class="fstat-no" title="function not covered" > co</span>nstructor(id, name, email, password, createdAt, updatedAt) {
<span class="cstat-no" title="statement not covered" > this.id = id;</span>
<span class="cstat-no" title="statement not covered" > this.name = name;</span>
<span class="cstat-no" title="statement not covered" > this.email = email;</span>
<span class="cstat-no" title="statement not covered" > this.password = password;</span>
<span class="cstat-no" title="statement not covered" > this.createdAt = createdAt;</span>
<span class="cstat-no" title="statement not covered" > this.updatedAt = updatedAt;</span>
}
&nbsp;
/**
* Factory method to create a new User
* @param {Object} data - { name, email, password }
* @returns {User}
*/
<span class="fstat-no" title="function not covered" > st</span>atic create(data) {
const { name, email, password } = <span class="cstat-no" title="statement not covered" >data;</span>
&nbsp;
// Validation
<span class="cstat-no" title="statement not covered" > if (!name || name.trim().length === 0) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('User name is required');</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!email || !User.isValidEmail(email)) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Valid email is required');</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!password || password.length &lt; 6) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Password must be at least 6 characters long');</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > return new User(null, name.trim(), email.toLowerCase(), password, new Date(), new Date());</span>
}
&nbsp;
/**
* Email validation
* @param {string} email
* @returns {boolean}
*/
<span class="fstat-no" title="function not covered" > st</span>atic isValidEmail(email) {
const emailRegex = <span class="cstat-no" title="statement not covered" >/^[^\s@]+@[^\s@]+\.[^\s@]+$/;</span>
<span class="cstat-no" title="statement not covered" > return emailRegex.test(email);</span>
}
&nbsp;
/**
* Update user name
* @param {string} newName
*/
<span class="fstat-no" title="function not covered" > up</span>dateName(newName) {
<span class="cstat-no" title="statement not covered" > if (!newName || newName.trim().length === 0) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('User name is required');</span>
}
<span class="cstat-no" title="statement not covered" > this.name = newName.trim();</span>
<span class="cstat-no" title="statement not covered" > this.updatedAt = new Date();</span>
}
&nbsp;
/**
* Get user without sensitive data
* @returns {Object}
*/
<span class="fstat-no" title="function not covered" > to</span>PublicJSON() {
<span class="cstat-no" title="statement not covered" > return {</span>
id: this.id,
name: this.name,
email: this.email,
createdAt: this.createdAt,
updatedAt: this.updatedAt
};
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = User;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,116 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for domain/models</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> domain/models</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/22</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/22</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="User.js"><a href="User.js.html">User.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="22" class="abs low">0/22</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="16" class="abs low">0/16</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="22" class="abs low">0/22</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 445 B

@@ -1,266 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for All files</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="prettify.css" />
<link rel="stylesheet" href="base.css" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>All files</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0.32% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1/312</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">1.94% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/103</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">4.81% </span>
<span class="quiet">Functions</span>
<span class='fraction'>4/83</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0.33% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1/301</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="api/controllers"><a href="api/controllers/index.html">api/controllers</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="65" class="abs low">0/65</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="18" class="abs low">0/18</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="9" class="abs low">0/9</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="65" class="abs low">0/65</td>
</tr>
<tr>
<td class="file low" data-value="api/middlewares"><a href="api/middlewares/index.html">api/middlewares</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="17" class="abs low">0/17</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="17" class="abs low">0/17</td>
</tr>
<tr>
<td class="file low" data-value="api/routers"><a href="api/routers/index.html">api/routers</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="29" class="abs low">0/29</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="11" class="abs low">0/11</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="20" class="abs low">0/20</td>
</tr>
<tr>
<td class="file low" data-value="application/auth/commands"><a href="application/auth/commands/index.html">application/auth/commands</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="49" class="abs low">0/49</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="21" class="abs low">0/21</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="7" class="abs low">0/7</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="49" class="abs low">0/49</td>
</tr>
<tr>
<td class="file low" data-value="application/services"><a href="application/services/index.html">application/services</a></td>
<td data-value="2.94" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 2%"></div><div class="cover-empty" style="width: 98%"></div></div>
</td>
<td data-value="2.94" class="pct low">2.94%</td>
<td data-value="34" class="abs low">1/34</td>
<td data-value="9.09" class="pct low">9.09%</td>
<td data-value="22" class="abs low">2/22</td>
<td data-value="28.57" class="pct low">28.57%</td>
<td data-value="14" class="abs low">4/14</td>
<td data-value="2.94" class="pct low">2.94%</td>
<td data-value="34" class="abs low">1/34</td>
</tr>
<tr>
<td class="file low" data-value="application/user/commands"><a href="application/user/commands/index.html">application/user/commands</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="11" class="abs low">0/11</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="3" class="abs low">0/3</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="11" class="abs low">0/11</td>
</tr>
<tr>
<td class="file low" data-value="application/user/queries"><a href="application/user/queries/index.html">application/user/queries</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="28" class="abs low">0/28</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="10" class="abs low">0/10</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="27" class="abs low">0/27</td>
</tr>
<tr>
<td class="file low" data-value="domain/irepositories"><a href="domain/irepositories/index.html">domain/irepositories</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="7" class="abs low">0/7</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="6" class="abs low">0/6</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="7" class="abs low">0/7</td>
</tr>
<tr>
<td class="file low" data-value="domain/models"><a href="domain/models/index.html">domain/models</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="22" class="abs low">0/22</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="16" class="abs low">0/16</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="22" class="abs low">0/22</td>
</tr>
<tr>
<td class="file low" data-value="infrastructure/db"><a href="infrastructure/db/index.html">infrastructure/db</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
</tr>
<tr>
<td class="file low" data-value="infrastructure/repositories"><a href="infrastructure/repositories/index.html">infrastructure/repositories</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="9" class="abs low">0/9</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="24" class="abs low">0/24</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
</html>
@@ -1,307 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for infrastructure/db/DatabaseConnection.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">infrastructure/db</a> DatabaseConnection.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/25</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/25</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const { PrismaClient } = <span class="cstat-no" title="statement not covered" >require('@prisma/client');</span>
&nbsp;
/**
* Database Connection Wrapper
* Manages Prisma Client lifecycle
*/
class DatabaseConnection {
<span class="fstat-no" title="function not covered" > co</span>nstructor() {
<span class="cstat-no" title="statement not covered" > this.prisma = null;</span>
}
&nbsp;
/**
* Initialize Prisma Client
*/
<span class="fstat-no" title="function not covered" > as</span>ync connect() {
<span class="cstat-no" title="statement not covered" > if (this.prisma) {</span>
<span class="cstat-no" title="statement not covered" > console.log('⚠️ Prisma Client already connected');</span>
<span class="cstat-no" title="statement not covered" > return;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > this.prisma = new PrismaClient({</span>
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
});
&nbsp;
<span class="cstat-no" title="statement not covered" > await this.prisma.$connect();</span>
<span class="cstat-no" title="statement not covered" > console.log('✅ Prisma connected to PostgreSQL');</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > console.error('❌ Failed to connect to database:', error);</span>
<span class="cstat-no" title="statement not covered" > throw error;</span>
}
}
&nbsp;
/**
* Get Prisma Client instance
* @returns {PrismaClient}
*/
<span class="fstat-no" title="function not covered" > ge</span>tClient() {
<span class="cstat-no" title="statement not covered" > if (!this.prisma) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error('Database not connected. Call connect() first.');</span>
}
<span class="cstat-no" title="statement not covered" > return this.prisma;</span>
}
&nbsp;
/**
* Close database connection
*/
<span class="fstat-no" title="function not covered" > as</span>ync disconnect() {
<span class="cstat-no" title="statement not covered" > if (this.prisma) {</span>
<span class="cstat-no" title="statement not covered" > await this.prisma.$disconnect();</span>
<span class="cstat-no" title="statement not covered" > console.log('🛑 Prisma disconnected');</span>
<span class="cstat-no" title="statement not covered" > this.prisma = null;</span>
}
}
&nbsp;
/**
* Health check
* @returns {Promise&lt;boolean&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync healthCheck() {
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > await this.prisma.$queryRaw`SELECT 1`;</span>
<span class="cstat-no" title="statement not covered" > return true;</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > console.error('❌ Database health check failed:', error);</span>
<span class="cstat-no" title="statement not covered" > return false;</span>
}
}
}
&nbsp;
// Singleton instance
const databaseConnection = <span class="cstat-no" title="statement not covered" >new DatabaseConnection();</span>
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = databaseConnection;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,116 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for infrastructure/db</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> infrastructure/db</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/25</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/25</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="DatabaseConnection.js"><a href="DatabaseConnection.js.html">DatabaseConnection.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="8" class="abs low">0/8</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,475 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for infrastructure/repositories/UserRepository.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> / <a href="index.html">infrastructure/repositories</a> UserRepository.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/25</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/9</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/24</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a>
<a name='L105'></a><a href='#L105'>105</a>
<a name='L106'></a><a href='#L106'>106</a>
<a name='L107'></a><a href='#L107'>107</a>
<a name='L108'></a><a href='#L108'>108</a>
<a name='L109'></a><a href='#L109'>109</a>
<a name='L110'></a><a href='#L110'>110</a>
<a name='L111'></a><a href='#L111'>111</a>
<a name='L112'></a><a href='#L112'>112</a>
<a name='L113'></a><a href='#L113'>113</a>
<a name='L114'></a><a href='#L114'>114</a>
<a name='L115'></a><a href='#L115'>115</a>
<a name='L116'></a><a href='#L116'>116</a>
<a name='L117'></a><a href='#L117'>117</a>
<a name='L118'></a><a href='#L118'>118</a>
<a name='L119'></a><a href='#L119'>119</a>
<a name='L120'></a><a href='#L120'>120</a>
<a name='L121'></a><a href='#L121'>121</a>
<a name='L122'></a><a href='#L122'>122</a>
<a name='L123'></a><a href='#L123'>123</a>
<a name='L124'></a><a href='#L124'>124</a>
<a name='L125'></a><a href='#L125'>125</a>
<a name='L126'></a><a href='#L126'>126</a>
<a name='L127'></a><a href='#L127'>127</a>
<a name='L128'></a><a href='#L128'>128</a>
<a name='L129'></a><a href='#L129'>129</a>
<a name='L130'></a><a href='#L130'>130</a>
<a name='L131'></a><a href='#L131'>131</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const IUserRepository = <span class="cstat-no" title="statement not covered" >require('../../domain/irepositories/IUserRepository');</span>
const User = <span class="cstat-no" title="statement not covered" >require('../../domain/models/User');</span>
&nbsp;
/**
* User Repository Implementation
* Prisma-based data access for User entity
*/
class UserRepository extends IUserRepository {
<span class="fstat-no" title="function not covered" > co</span>nstructor(prisma) {
<span class="cstat-no" title="statement not covered" > super();</span>
<span class="cstat-no" title="statement not covered" > this.prisma = prisma;</span>
}
&nbsp;
/**
* Find user by ID
* @param {number} id
* @returns {Promise&lt;User|null&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync findById(id) {
const userData = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findUnique({</span>
where: { id: parseInt(id) }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!userData) {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > return this._toDomain(userData);</span>
}
&nbsp;
/**
* Find user by email
* @param {string} email
* @returns {Promise&lt;User|null&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync findByEmail(email) {
const userData = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findUnique({</span>
where: { email: email.toLowerCase() }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!userData) {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > return this._toDomain(userData);</span>
}
&nbsp;
/**
* Find all users
* @returns {Promise&lt;User[]&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync findAll() {
const usersData = <span class="cstat-no" title="statement not covered" >await this.prisma.user.findMany({</span>
orderBy: { createdAt: 'desc' }
});
&nbsp;
<span class="cstat-no" title="statement not covered" > return usersData.map(<span class="fstat-no" title="function not covered" >us</span>erData =&gt; <span class="cstat-no" title="statement not covered" >this._toDomain(userData))</span>;</span>
}
&nbsp;
/**
* Create new user
* @param {User} user
* @returns {Promise&lt;User&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync create(user) {
const userData = <span class="cstat-no" title="statement not covered" >await this.prisma.user.create({</span>
data: {
name: user.name,
email: user.email,
password: user.password
}
});
&nbsp;
<span class="cstat-no" title="statement not covered" > return this._toDomain(userData);</span>
}
&nbsp;
/**
* Update existing user
* @param {User} user
* @returns {Promise&lt;User&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync update(user) {
const userData = <span class="cstat-no" title="statement not covered" >await this.prisma.user.update({</span>
where: { id: user.id },
data: {
name: user.name,
email: user.email,
password: user.password,
updatedAt: new Date()
}
});
&nbsp;
<span class="cstat-no" title="statement not covered" > return this._toDomain(userData);</span>
}
&nbsp;
/**
* Delete user by ID
* @param {number} id
* @returns {Promise&lt;boolean&gt;}
*/
<span class="fstat-no" title="function not covered" > as</span>ync delete(id) {
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > await this.prisma.user.delete({</span>
where: { id: parseInt(id) }
});
<span class="cstat-no" title="statement not covered" > return true;</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > return false;</span>
}
}
&nbsp;
/**
* Convert Prisma data to Domain model
* @private
* @param {Object} userData - Prisma user data
* @returns {User}
*/
<span class="fstat-no" title="function not covered" > _t</span>oDomain(userData) {
<span class="cstat-no" title="statement not covered" > return new User(</span>
userData.id,
userData.name,
userData.email,
userData.password,
userData.createdAt,
userData.updatedAt
);
}
}
&nbsp;
<span class="cstat-no" title="statement not covered" >module.exports = UserRepository;</span>
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1,116 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for infrastructure/repositories</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../index.html">All files</a> infrastructure/repositories</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/25</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/9</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/24</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="UserRepository.js"><a href="UserRepository.js.html">UserRepository.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="25" class="abs low">0/25</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="4" class="abs low">0/4</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="9" class="abs low">0/9</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="24" class="abs low">0/24</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-03-04T18:32:40.886Z
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../sorter.js"></script>
<script src="../../block-navigation.js"></script>
</body>
</html>
@@ -1 +0,0 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

@@ -1,210 +0,0 @@
/* eslint-disable */
var addSorting = (function() {
'use strict';
var cols,
currentSort = {
index: 0,
desc: false
};
// returns the summary table element
function getTable() {
return document.querySelector('.coverage-summary');
}
// returns the thead element of the summary table
function getTableHeader() {
return getTable().querySelector('thead tr');
}
// returns the tbody element of the summary table
function getTableBody() {
return getTable().querySelector('tbody');
}
// returns the th element for nth column
function getNthColumn(n) {
return getTableHeader().querySelectorAll('th')[n];
}
function onFilterInput() {
const searchValue = document.getElementById('fileSearch').value;
const rows = document.getElementsByTagName('tbody')[0].children;
// Try to create a RegExp from the searchValue. If it fails (invalid regex),
// it will be treated as a plain text search
let searchRegex;
try {
searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive
} catch (error) {
searchRegex = null;
}
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
let isMatch = false;
if (searchRegex) {
// If a valid regex was created, use it for matching
isMatch = searchRegex.test(row.textContent);
} else {
// Otherwise, fall back to the original plain text search
isMatch = row.textContent
.toLowerCase()
.includes(searchValue.toLowerCase());
}
row.style.display = isMatch ? '' : 'none';
}
}
// loads the search box
function addSearchBox() {
var template = document.getElementById('filterTemplate');
var templateClone = template.content.cloneNode(true);
templateClone.getElementById('fileSearch').oninput = onFilterInput;
template.parentElement.appendChild(templateClone);
}
// loads all columns
function loadColumns() {
var colNodes = getTableHeader().querySelectorAll('th'),
colNode,
cols = [],
col,
i;
for (i = 0; i < colNodes.length; i += 1) {
colNode = colNodes[i];
col = {
key: colNode.getAttribute('data-col'),
sortable: !colNode.getAttribute('data-nosort'),
type: colNode.getAttribute('data-type') || 'string'
};
cols.push(col);
if (col.sortable) {
col.defaultDescSort = col.type === 'number';
colNode.innerHTML =
colNode.innerHTML + '<span class="sorter"></span>';
}
}
return cols;
}
// attaches a data attribute to every tr element with an object
// of data values keyed by column name
function loadRowData(tableRow) {
var tableCols = tableRow.querySelectorAll('td'),
colNode,
col,
data = {},
i,
val;
for (i = 0; i < tableCols.length; i += 1) {
colNode = tableCols[i];
col = cols[i];
val = colNode.getAttribute('data-value');
if (col.type === 'number') {
val = Number(val);
}
data[col.key] = val;
}
return data;
}
// loads all row data
function loadData() {
var rows = getTableBody().querySelectorAll('tr'),
i;
for (i = 0; i < rows.length; i += 1) {
rows[i].data = loadRowData(rows[i]);
}
}
// sorts the table using the data for the ith column
function sortByIndex(index, desc) {
var key = cols[index].key,
sorter = function(a, b) {
a = a.data[key];
b = b.data[key];
return a < b ? -1 : a > b ? 1 : 0;
},
finalSorter = sorter,
tableBody = document.querySelector('.coverage-summary tbody'),
rowNodes = tableBody.querySelectorAll('tr'),
rows = [],
i;
if (desc) {
finalSorter = function(a, b) {
return -1 * sorter(a, b);
};
}
for (i = 0; i < rowNodes.length; i += 1) {
rows.push(rowNodes[i]);
tableBody.removeChild(rowNodes[i]);
}
rows.sort(finalSorter);
for (i = 0; i < rows.length; i += 1) {
tableBody.appendChild(rows[i]);
}
}
// removes sort indicators for current column being sorted
function removeSortIndicators() {
var col = getNthColumn(currentSort.index),
cls = col.className;
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
col.className = cls;
}
// adds sort indicators for current column being sorted
function addSortIndicators() {
getNthColumn(currentSort.index).className += currentSort.desc
? ' sorted-desc'
: ' sorted';
}
// adds event listeners for all sorter widgets
function enableUI() {
var i,
el,
ithSorter = function ithSorter(i) {
var col = cols[i];
return function() {
var desc = col.defaultDescSort;
if (currentSort.index === i) {
desc = !currentSort.desc;
}
sortByIndex(i, desc);
removeSortIndicators();
currentSort.index = i;
currentSort.desc = desc;
addSortIndicators();
};
};
for (i = 0; i < cols.length; i += 1) {
if (cols[i].sortable) {
// add the click event handler on the th so users
// dont have to click on those tiny arrows
el = getNthColumn(i).querySelector('.sorter').parentElement;
if (el.addEventListener) {
el.addEventListener('click', ithSorter(i));
} else {
el.attachEvent('onclick', ithSorter(i));
}
}
}
}
// adds sorting functionality to the UI
return function() {
if (!getTable()) {
return;
}
cols = loadColumns();
loadData();
addSearchBox();
addSortIndicators();
enableUI();
};
})();
window.addEventListener('load', addSorting);
@@ -1,804 +0,0 @@
TN:
SF:src\api\controllers\AuthController.js
FN:9,(anonymous_0)
FN:18,(anonymous_1)
FN:52,(anonymous_2)
FN:84,(anonymous_3)
FNF:4
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
DA:1,0
DA:2,0
DA:10,0
DA:11,0
DA:12,0
DA:19,0
DA:20,0
DA:22,0
DA:23,0
DA:26,0
DA:32,0
DA:40,0
DA:45,0
DA:53,0
DA:54,0
DA:56,0
DA:57,0
DA:60,0
DA:66,0
DA:74,0
DA:77,0
DA:85,0
DA:87,0
DA:94,0
DA:98,0
DA:103,0
LF:26
LH:0
BRDA:40,0,0,0
BRDA:40,0,1,0
BRDA:40,1,0,0
BRDA:40,1,1,0
BRDA:40,1,2,0
BRDA:40,1,3,0
BRDA:74,2,0,0
BRDA:74,2,1,0
BRDA:74,3,0,0
BRDA:74,3,1,0
BRF:10
BRH:0
end_of_record
TN:
SF:src\api\controllers\UserController.js
FN:11,(anonymous_0)
FN:21,(anonymous_1)
FN:42,(anonymous_2)
FN:60,(anonymous_3)
FN:85,(anonymous_4)
FNF:5
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
DA:1,0
DA:2,0
DA:3,0
DA:4,0
DA:12,0
DA:13,0
DA:14,0
DA:15,0
DA:22,0
DA:24,0
DA:26,0
DA:27,0
DA:29,0
DA:34,0
DA:35,0
DA:43,0
DA:44,0
DA:45,0
DA:47,0
DA:53,0
DA:61,0
DA:62,0
DA:63,0
DA:65,0
DA:66,0
DA:69,0
DA:70,0
DA:72,0
DA:77,0
DA:78,0
DA:86,0
DA:87,0
DA:88,0
DA:90,0
DA:91,0
DA:93,0
DA:98,0
DA:99,0
DA:104,0
LF:39
LH:0
BRDA:34,0,0,0
BRDA:34,0,1,0
BRDA:65,1,0,0
BRDA:65,1,1,0
BRDA:77,2,0,0
BRDA:77,2,1,0
BRDA:98,3,0,0
BRDA:98,3,1,0
BRF:8
BRH:0
end_of_record
TN:
SF:src\api\middlewares\authMiddleware.js
FN:13,authMiddleware
FNF:1
FNH:0
FNDA:0,authMiddleware
DA:1,0
DA:3,0
DA:14,0
DA:16,0
DA:18,0
DA:19,0
DA:26,0
DA:29,0
DA:35,0
DA:37,0
DA:44,0
LF:11
LH:0
BRDA:18,0,0,0
BRDA:18,0,1,0
BRF:2
BRH:0
end_of_record
TN:
SF:src\api\middlewares\corsMiddleware.js
FN:7,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:1,0
DA:4,0
DA:6,0
DA:22,0
LF:4
LH:0
BRDA:4,0,0,0
BRDA:4,0,1,0
BRF:2
BRH:0
end_of_record
TN:
SF:src\api\middlewares\scopeMiddleware.js
FN:5,scopeMiddleware
FN:6,(anonymous_1)
FNF:2
FNH:0
FNDA:0,scopeMiddleware
FNDA:0,(anonymous_1)
DA:6,0
DA:18,0
LF:2
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\api\routers\authRoutes.js
FN:9,createAuthRoutes
FN:20,(anonymous_1)
FN:27,(anonymous_2)
FN:33,(anonymous_3)
FN:38,(anonymous_4)
FNF:5
FNH:0
FNDA:0,createAuthRoutes
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
DA:1,0
DA:10,0
DA:13,0
DA:20,0
DA:27,0
DA:33,0
DA:38,0
DA:40,0
DA:43,0
LF:9
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\api\routers\userRoutes.js
FN:10,createUserRoutes
FN:20,(anonymous_1)
FN:27,(anonymous_2)
FN:33,(anonymous_3)
FN:39,(anonymous_4)
FN:44,(anonymous_5)
FNF:6
FNH:0
FNDA:0,createUserRoutes
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
DA:1,0
DA:2,0
DA:11,0
DA:14,0
DA:20,0
DA:27,0
DA:33,0
DA:39,0
DA:44,0
DA:46,0
DA:49,0
LF:11
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\auth\commands\LoginUserCommand.js
FN:6,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:7,0
DA:8,0
DA:12,0
LF:3
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\auth\commands\LoginUserCommandHandler.js
FN:11,(anonymous_0)
FN:20,(anonymous_1)
FNF:2
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
DA:1,0
DA:2,0
DA:4,0
DA:12,0
DA:21,0
DA:24,0
DA:25,0
DA:29,0
DA:33,0
DA:34,0
DA:38,0
DA:40,0
DA:41,0
DA:45,0
DA:51,0
DA:53,0
DA:60,0
LF:17
LH:0
BRDA:24,0,0,0
BRDA:24,0,1,0
BRDA:24,1,0,0
BRDA:24,1,1,0
BRDA:33,2,0,0
BRDA:33,2,1,0
BRDA:40,3,0,0
BRDA:40,3,1,0
BRF:8
BRH:0
end_of_record
TN:
SF:src\application\auth\commands\RegisterUserCommand.js
FN:6,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:7,0
DA:8,0
DA:9,0
DA:13,0
LF:4
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\auth\commands\RegisterUserCommandHandler.js
FN:11,(anonymous_0)
FN:21,(anonymous_1)
FN:62,(anonymous_2)
FNF:3
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
DA:1,0
DA:2,0
DA:4,0
DA:12,0
DA:13,0
DA:22,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
DA:34,0
DA:35,0
DA:36,0
DA:40,0
DA:44,0
DA:45,0
DA:49,0
DA:52,0
DA:61,0
DA:62,0
DA:63,0
DA:68,0
DA:74,0
DA:76,0
DA:83,0
LF:25
LH:0
BRDA:25,0,0,0
BRDA:25,0,1,0
BRDA:25,1,0,0
BRDA:25,1,1,0
BRDA:25,1,2,0
BRDA:29,2,0,0
BRDA:29,2,1,0
BRDA:35,3,0,0
BRDA:35,3,1,0
BRDA:44,4,0,0
BRDA:44,4,1,0
BRDA:61,5,0,0
BRDA:61,5,1,0
BRF:13
BRH:0
end_of_record
TN:
SF:src\application\services\Container.js
FN:6,(anonymous_0)
FN:17,(anonymous_1)
FN:25,(anonymous_2)
FN:47,(anonymous_3)
FNF:4
FNH:4
FNDA:22,(anonymous_0)
FNDA:22,(anonymous_1)
FNDA:19,(anonymous_2)
FNDA:9,(anonymous_3)
DA:57,1
LF:1
LH:1
BRDA:17,0,0,1
BRDA:25,1,0,17
BRF:2
BRH:2
end_of_record
TN:
SF:src\application\services\EmailService.js
FN:8,(anonymous_0)
FN:23,(anonymous_1)
FNF:2
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
DA:20,0
DA:26,0
DA:27,0
DA:31,0
LF:4
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\services\JwtService.js
FN:8,(anonymous_0)
FN:19,(anonymous_1)
FN:28,(anonymous_2)
FN:41,(anonymous_3)
FN:60,(anonymous_4)
FN:72,(anonymous_5)
FN:89,(anonymous_6)
FN:109,(anonymous_7)
FNF:8
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
FNDA:0,(anonymous_6)
FNDA:0,(anonymous_7)
DA:1,0
DA:9,0
DA:10,0
DA:11,0
DA:20,0
DA:29,0
DA:30,0
DA:32,0
DA:42,0
DA:43,0
DA:46,0
DA:48,0
DA:49,0
DA:52,0
DA:61,0
DA:62,0
DA:65,0
DA:73,0
DA:75,0
DA:91,0
DA:93,0
DA:94,0
DA:95,0
DA:96,0
DA:97,0
DA:98,0
DA:102,0
DA:110,0
DA:114,0
LF:29
LH:0
BRDA:9,0,0,0
BRDA:9,0,1,0
BRDA:10,1,0,0
BRDA:10,1,1,0
BRDA:42,2,0,0
BRDA:42,2,1,0
BRDA:48,3,0,0
BRDA:48,3,1,0
BRDA:48,4,0,0
BRDA:48,4,1,0
BRDA:61,5,0,0
BRDA:61,5,1,0
BRDA:61,6,0,0
BRDA:61,6,1,0
BRDA:93,7,0,0
BRDA:93,7,1,0
BRDA:95,8,0,0
BRDA:95,8,1,0
BRDA:97,9,0,0
BRDA:97,9,1,0
BRF:20
BRH:0
end_of_record
TN:
SF:src\application\user\commands\UpdateUserProfileCommand.js
FN:6,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:7,0
DA:8,0
DA:12,0
LF:3
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\user\commands\UpdateUserProfileCommandHandler.js
FN:6,(anonymous_0)
FN:15,(anonymous_1)
FNF:2
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
DA:7,0
DA:16,0
DA:18,0
DA:19,0
DA:22,0
DA:27,0
DA:28,0
DA:32,0
LF:8
LH:0
BRDA:18,0,0,0
BRDA:18,0,1,0
BRF:2
BRH:0
end_of_record
TN:
SF:src\application\user\queries\GetAllUsersQuery.js
FN:6,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:11,0
LF:1
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\user\queries\GetAllUsersQueryHandler.js
FN:6,(anonymous_0)
FN:15,(anonymous_1)
FN:21,(anonymous_2)
FNF:3
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
DA:7,0
DA:16,0
DA:21,0
DA:25,0
LF:4
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\user\queries\GetMeQuery.js
FN:6,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:7,0
DA:11,0
LF:2
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\user\queries\GetMeQueryHandler.js
FN:6,(anonymous_0)
FN:15,(anonymous_1)
FNF:2
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
DA:7,0
DA:16,0
DA:18,0
DA:22,0
DA:23,0
DA:26,0
DA:27,0
DA:31,0
LF:8
LH:0
BRDA:22,0,0,0
BRDA:22,0,1,0
BRF:2
BRH:0
end_of_record
TN:
SF:src\application\user\queries\GetUserByIdQuery.js
FN:6,(anonymous_0)
FNF:1
FNH:0
FNDA:0,(anonymous_0)
DA:7,0
DA:11,0
LF:2
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\application\user\queries\GetUserByIdQueryHandler.js
FN:6,(anonymous_0)
FN:15,(anonymous_1)
FNF:2
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
DA:7,0
DA:16,0
DA:18,0
DA:19,0
DA:22,0
DA:26,0
DA:27,0
DA:30,0
DA:31,0
DA:35,0
LF:10
LH:0
BRDA:18,0,0,0
BRDA:18,0,1,0
BRDA:18,1,0,0
BRDA:18,1,1,0
BRDA:26,2,0,0
BRDA:26,2,1,0
BRF:6
BRH:0
end_of_record
TN:
SF:src\domain\irepositories\IUserRepository.js
FN:11,(anonymous_0)
FN:20,(anonymous_1)
FN:28,(anonymous_2)
FN:37,(anonymous_3)
FN:46,(anonymous_4)
FN:55,(anonymous_5)
FNF:6
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
DA:12,0
DA:21,0
DA:29,0
DA:38,0
DA:47,0
DA:56,0
DA:60,0
LF:7
LH:0
BRF:0
BRH:0
end_of_record
TN:
SF:src\domain\models\User.js
FN:6,(anonymous_0)
FN:20,(anonymous_1)
FN:44,(anonymous_2)
FN:53,(anonymous_3)
FN:65,(anonymous_4)
FNF:5
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
DA:7,0
DA:8,0
DA:9,0
DA:10,0
DA:11,0
DA:12,0
DA:21,0
DA:24,0
DA:25,0
DA:28,0
DA:29,0
DA:32,0
DA:33,0
DA:36,0
DA:45,0
DA:46,0
DA:54,0
DA:55,0
DA:57,0
DA:58,0
DA:66,0
DA:76,0
LF:22
LH:0
BRDA:24,0,0,0
BRDA:24,0,1,0
BRDA:24,1,0,0
BRDA:24,1,1,0
BRDA:28,2,0,0
BRDA:28,2,1,0
BRDA:28,3,0,0
BRDA:28,3,1,0
BRDA:32,4,0,0
BRDA:32,4,1,0
BRDA:32,5,0,0
BRDA:32,5,1,0
BRDA:54,6,0,0
BRDA:54,6,1,0
BRDA:54,7,0,0
BRDA:54,7,1,0
BRF:16
BRH:0
end_of_record
TN:
SF:src\infrastructure\db\DatabaseConnection.js
FN:8,(anonymous_0)
FN:15,(anonymous_1)
FN:38,(anonymous_2)
FN:48,(anonymous_3)
FN:60,(anonymous_4)
FNF:5
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
DA:1,0
DA:9,0
DA:16,0
DA:17,0
DA:18,0
DA:21,0
DA:22,0
DA:26,0
DA:27,0
DA:29,0
DA:30,0
DA:39,0
DA:40,0
DA:42,0
DA:49,0
DA:50,0
DA:51,0
DA:52,0
DA:61,0
DA:62,0
DA:63,0
DA:65,0
DA:66,0
DA:72,0
DA:74,0
LF:25
LH:0
BRDA:16,0,0,0
BRDA:16,0,1,0
BRDA:23,1,0,0
BRDA:23,1,1,0
BRDA:39,2,0,0
BRDA:39,2,1,0
BRDA:49,3,0,0
BRDA:49,3,1,0
BRF:8
BRH:0
end_of_record
TN:
SF:src\infrastructure\repositories\UserRepository.js
FN:9,(anonymous_0)
FN:19,(anonymous_1)
FN:36,(anonymous_2)
FN:52,(anonymous_3)
FN:57,(anonymous_4)
FN:65,(anonymous_5)
FN:82,(anonymous_6)
FN:101,(anonymous_7)
FN:118,(anonymous_8)
FNF:9
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
FNDA:0,(anonymous_6)
FNDA:0,(anonymous_7)
FNDA:0,(anonymous_8)
DA:1,0
DA:2,0
DA:10,0
DA:11,0
DA:20,0
DA:24,0
DA:25,0
DA:28,0
DA:37,0
DA:41,0
DA:42,0
DA:45,0
DA:53,0
DA:57,0
DA:66,0
DA:74,0
DA:83,0
DA:93,0
DA:102,0
DA:103,0
DA:106,0
DA:108,0
DA:119,0
DA:130,0
LF:24
LH:0
BRDA:24,0,0,0
BRDA:24,0,1,0
BRDA:41,1,0,0
BRDA:41,1,1,0
BRF:4
BRH:0
end_of_record
Binary file not shown.
Binary file not shown.
+230
View File
@@ -0,0 +1,230 @@
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[magyar]{babel}
\usepackage{indentfirst}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{fancyvrb}
\usepackage{amssymb}
\usepackage{pifont}
\usepackage{newunicodechar}
% Unicode szimbólumok definiálása
\newcommand{\cmark}{\ding{51}} % ✓ check mark
\newcommand{\xmark}{\ding{55}} % ✗ ballot x
\newunicodechar{✓}{\cmark}
\newunicodechar{✗}{\xmark}
\newunicodechar{❌}{\textcolor{red}{\xmark}}
% Globális verbatim beállítás - tiny betűméret minden verbatim blokkhoz
\fvset{fontsize=\tiny}
\usepackage{listingsutf8}
\usepackage{textcomp}
\usepackage{eurosym}
\usepackage{mathtools}
\lstset{literate=
{á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1
{Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1
{à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1
{À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1
{ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1
{Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1
{â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1
{Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1
{œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1
{ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1
{€}{{\EUR}}1 {£}{{\pounds}}1 {ő}{{\H{o}}}1 {ű}{{\H{u}}}1
}
% Docker nyelvdefiníció
\lstdefinelanguage{Docker}{
keywords={FROM, RUN, CMD, LABEL, MAINTAINER, EXPOSE, ENV, ADD, COPY,
ENTRYPOINT, VOLUME, USER, WORKDIR, ARG, ONBUILD, STOPSIGNAL,
HEALTHCHECK, SHELL, AS},
keywordstyle=\color{blue}\bfseries,
identifierstyle=\color{black},
sensitive=false,
comment=[l]{\#},
commentstyle=\color{purple}\ttfamily,
stringstyle=\color{red}\ttfamily,
morestring=[b]',
morestring=[b]"
}
% JavaScript nyelvdefiníció
\lstdefinelanguage{JavaScript}{
keywords={typeof, new, true, false, catch, function, return, null, catch,
switch, var, const, let, if, in, while, do, else, case, break, async,
await, class, export, import, extends, super, this, throw, try, default},
keywordstyle=\color{blue}\bfseries,
ndkeywords={class, export, boolean, throw, implements, import, this},
ndkeywordstyle=\color{darkgray}\bfseries,
identifierstyle=\color{black},
sensitive=false,
comment=[l]{//},
morecomment=[s]{/*}{*/},
commentstyle=\color{purple}\ttfamily,
stringstyle=\color{red}\ttfamily,
morestring=[b]',
morestring=[b]"
}
% YAML nyelvdefiníció
\lstdefinelanguage{yaml}{
keywords={true,false,null,y,n},
keywordstyle=\color{darkgray}\bfseries,
sensitive=false,
comment=[l]{\#},
commentstyle=\color{purple}\ttfamily,
stringstyle=\color{red}\ttfamily,
morestring=[b]',
morestring=[b]",
basicstyle=\ttfamily\scriptsize,
breaklines=true,
columns=fullflexible,
keepspaces=true,
showstringspaces=false
}
\lstdefinestyle{HTML}{
language=HTML,
breaklines=true,
postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space},
stringstyle=\ttfamily,
inputencoding=utf8,
morekeywords={header, time, nav, main, article, section, aside, role,
footer, details, open, summary, srcdoc, list, datalist, placeholder,
pattern, required, min, max, step, enctype, formaction, formmethod,
formnovalidate, formtarget, output}
}
\lstdefinestyle{JavaScript}{
basicstyle=\ttfamily\scriptsize,
breaklines=true,
columns=fullflexible,
keepspaces=true,
showstringspaces=false,
literate={}
}
\lstdefinestyle{NodeJS}{
basicstyle=\ttfamily\scriptsize,
breaklines=true,
columns=fullflexible,
keepspaces=true,
showstringspaces=false,
literate={}
}
\lstdefinestyle{Express}{
basicstyle=\ttfamily\scriptsize,
breaklines=true,
columns=fullflexible,
keepspaces=true,
showstringspaces=false,
literate={}
}
\lstdefinestyle{Prisma}{
basicstyle=\ttfamily\scriptsize,
breaklines=true,
columns=fullflexible,
keepspaces=true,
showstringspaces=false,
literate={}
}
\usepackage{hyperref}
\usepackage{attachfile}
\usepackage{multirow}
% Navigációs pöttyök hozzáadása subsection nélküli fejezetekhez
\usepackage{remreset}
\makeatletter
\@removefromreset{subsection}{section}
\makeatother
\setcounter{subsection}{1}
%%%%%
\attachfilesetup{color={1.0 0.6 0.0},author={MD},description={Kattintson duplán a minta %
megtekintéséhez!},icon=Paperclip}
% Széchenyi Egyetem arculati színek
\definecolor{szenavy}{RGB}{44,62,80} % Sötét kék (fejléc)
\definecolor{szecyan}{RGB}{0,168,225} % Világos kék (kiemelés, logó)
\definecolor{szezold}{RGB}{139,195,74} % Élénk zöld (akcentus)
\definecolor{szeszurke}{RGB}{96,96,96} % Sötét szürke
% Kompatibilitás a régi parancsokkal
\definecolor{kiemelesszin}{RGB}{0,168,225} % Kék kiemelés (szecyan)
\definecolor{kiemelesszinZ}{RGB}{139,195,74} % Zöld kiemelés (szezold)
\definecolor{kiemelesszinN}{RGB}{44,62,80} % Navy kiemelés (szenavy)
\definecolor{hivatkozasszin}{RGB}{0,168,225} % Kék hivatkozás
\newcommand{\kiemel}[1]{{\color{kiemelesszin}#1}}
\newcommand{\kiemelZ}[1]{{\color{kiemelesszinZ}#1}}
\newcommand{\kiemelN}[1]{{\color{kiemelesszinN}#1}}
\newcommand{\hiv}[1]{{\color{hivatkozasszin}#1}}
\newcommand{\logoalul}{
\begin{picture}(0,0)
\put(120,-0){\hbox{\includegraphics[scale=.5]{../common/sze_logo.pdf}}}
\put(205,-6){\hbox{\includegraphics[scale=.4]{../common/it_logo.pdf}}}
\end{picture}
}
\frenchspacing
\usetheme[compress]{Berlin}
\useoutertheme[subsection=false]{miniframes}
\setbeamerfont{section in head/foot}{size=\tiny}
\setbeamerfont{subsection in head/foot}{size=\tiny}
% Adaptív, kattintható navigáció:
% sok section esetén az aktuális marad nagy és szöveges,
% a többi section lekicsinyített sorszámként jelenik meg.
\newcommand{\sectioncompactthreshold}{11}
\makeatletter
\providecommand{\totalsectionscount}{0}
\AtEndDocument{%
\immediate\write\@auxout{\string\gdef\string\totalsectionscount{\arabic{section}}}%
}
\makeatother
\setbeamertemplate{section in head/foot}{%
{\fontsize{6}{7}\selectfont\bfseries\insertsectionhead}%
}
\setbeamertemplate{section in head/foot shaded}{%
\ifnum\totalsectionscount>\sectioncompactthreshold
{\fontsize{4.5}{5.5}\selectfont\insertsectionheadnumber}%
\else
{\fontsize{5}{6}\selectfont\insertsectionhead}%
\fi
}
\setbeamertemplate{headline}
{
\leavevmode%
\hbox{%
\begin{beamercolorbox}[wd=\paperwidth,ht=2.5ex,dp=1.125ex]{section in head/foot}%
\insertsectionnavigationhorizontal{\paperwidth}{}{\hskip0pt plus1filll}
\end{beamercolorbox}%
}
\vskip0pt%
}
% Kisebb betűméret a slide-okhoz
\setbeamerfont{frametitle}{size=\normalsize}
\setbeamerfont{framesubtitle}{size=\small}
\setbeamerfont{block title}{size=\small}
\setbeamerfont{block body}{size=\footnotesize}
\setbeamerfont{itemize/enumerate body}{size=\footnotesize}
\setbeamerfont{itemize/enumerate subbody}{size=\scriptsize}
% Beamer színséma testreszabása Széchenyi arculathoz
\setbeamercolor{structure}{fg=szecyan}
\setbeamercolor{palette primary}{bg=szenavy,fg=white}
\setbeamercolor{palette secondary}{bg=szecyan,fg=white}
\setbeamercolor{palette tertiary}{bg=szezold,fg=white}
\setbeamercolor{palette quaternary}{bg=szeszurke,fg=white}
\setbeamercolor{titlelike}{parent=palette primary}
\setbeamercolor{frametitle}{bg=szenavy,fg=white}
\setbeamercolor{frametitle right}{bg=szenavy}
\setbeamercolor{block title}{bg=szecyan,fg=white}
\setbeamercolor{block body}{bg=szecyan!10,fg=black}
\setbeamercolor{block title alerted}{bg=szezold,fg=white}
\setbeamercolor{block body alerted}{bg=szezold!10,fg=black}
\setbeamercolor{item}{fg=szecyan}
\setbeamercolor{subitem}{fg=szezold}
\author{Magda Donát}
\institute{Széchenyi István Egyetem, Győr}
\date{\hiv{\href{https://git.mdnd-it.cc/Donat/GKNB_MSTM071}{https://git.mdnd-it.cc/Donat/GKNB_MSTM071}}\\ \today}
+37
View File
@@ -0,0 +1,37 @@
\section{Adatlekérés}
\begin{frame}{Hogyan kap adatot egy React alkalmazás?}
\begin{block}{Az alaphelyzet}
A React alkalmazás a böngészőben fut --- az adatok (felhasználók, termékek, stb.) általában egy \textbf{háttérszerveren} élnek. Az adatcserét HTTP kérésekkel végezzük: a frontend elküldi a kérést, a szerver JSON formátumban válaszol.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item A böngésző beépített \texttt{fetch} API-ját vagy az \textbf{Axios} könyvtárat használhatjuk.
\item Az adatlekérést általában egy \texttt{useEffect}-ben indítjuk el --- amikor a komponens megjelenik.
\end{itemize}
\end{frame}
\begin{frame}{Fetch vs.\ Axios}
\begin{itemize}
\item \textbf{Fetch:} beépített, nem kell telepíteni. Hátránya: a hibás HTTP kódokat (pl. 404) \emph{nem} dobja el automatikusan, JSON-t kézzel kell kezelni.
\item \textbf{Axios:} telepíthető könyvtár. Automatikusan kezeli a JSON-t, a HTTP hibákra kivételt dob, és \textbf{interceptorokkal} (pl. token hozzáadása minden kéréshez) könnyű kiegészíteni.
\item Nagyobb projekteknél az Axios általában kényelmesebb és biztonságosabb.
\end{itemize}
\end{frame}
\begin{frame}{Állapotok az adatlekérés során}
\begin{itemize}
\item \textbf{Betöltés (loading):} amíg a kérés folyamatban van, mutassunk spinner-t vagy skeleton-t --- ne maradjon üres az oldal.
\item \textbf{Siker:} megérkeztek az adatok, megjelenítjük.
\item \textbf{Hiba (error):} a hálózat megszakadt, a szerver hibát adott --- barátságos hibaüzenetet mutassunk, ne csak üres felületet.
\item \textbf{Üres állapot (empty):} a válasz sikeres, de nincs adat --- pl. "Nincsenek még termékek".
\end{itemize}
\end{frame}
\begin{frame}{Szerverállapot-kezelés: TanStack Query}
\begin{itemize}
\item Manuálisan kezelni a loading/error/data állapotokat minden komponensben ismétlődő és hibalehetőséges.
\item A \textbf{TanStack Query} (korábbi nevén React Query) ezt automatizálja: cache-eli az adatokat, háttérben frissíti, kezeli az újrapróbálkozást.
\item \textbf{Optimista frissítés:} azonnal frissítjük a UI-t a szerver válasza előtt --- ha a szerver hibát ad, visszaállítjuk. Így az alkalmazás gyorsabbnak tűnik.
\end{itemize}
\end{frame}
+38
View File
@@ -0,0 +1,38 @@
\section{Build \& Deploy}
\begin{frame}{Mi történik a build folyamatban?}
\begin{block}{Build = el'készítés az éles kiadásra}
Fejlesztés közben a kód sokszor nem optimális formában van --- sok fájl, olvasható változónevek, fejlesztői segédletek. A build folyamat ezeket átalakítja böngészőbarát, gyors formára.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item \textbf{Minifikálás:} felesleges szóközök, kommentek eltávolítása, változónevek rövidítése --- kisebb fájlméret.
\item \textbf{Tree-shaking:} a nem használt kód kiszűrése a végleges csomagból.
\item \textbf{Kódfelosztás:} az alkalmazás több kisebb fájlra bontva töltődik --- csak ami kell, töltődik le.
\end{itemize}
\end{frame}
\begin{frame}{Környezeti változók}
\begin{itemize}
\item Az alkalmazásnak fejlesztési és éles környezetben más beállításokra van szüksége (API URL, kulcsok stb.).
\item Ezeket \textbf{.env fájlokban} tároljuk --- a \texttt{.env.local} soha nem kerül Git-be (érzékeny adatok).
\item Vite-ban a \texttt{VITE\_} előtagú változók kerülnek a kliensoldali kódba --- a többi csak szerveroldalon érhető el.
\item \textbf{Figyelem:} titkos kulcsokat soha ne tegyük a kliensoldali kódba --- bárki láthatja!
\end{itemize}
\end{frame}
\begin{frame}{Deploy lehet'ségek}
\begin{itemize}
\item \textbf{Vercel, Netlify:} egy Git push-ra automatikusan deployol, ingyen elérhető próbaprojektekhez --- a legegyszerűbb indulás.
\item \textbf{GitHub Pages:} statikus oldalakhoz, nyílt forráskódú projektekhez kényelmes.
\item \textbf{Saját szerver / CDN:} Nginx-szel statikus fájlokat tálalunk; fontos az SPA fallback beállítása (minden URL-t az \texttt{index.html}-re irányítunk, a React Router veszi át).
\end{itemize}
\end{frame}
\begin{frame}{Biztonsági alapok}
\begin{itemize}
\item \textbf{XSS (Cross-Site Scripting) elleni védelem:} a React alapból escape-eli a JSX-ben megjelenített szövegeket --- a \texttt{dangerouslySetInnerHTML} viszont kikerüli ezt, csak tisztított adattal szabad használni.
\item \textbf{Auth token kezelés:} a JWT-t ne \texttt{localStorage}-ban tároljuk --- JavaScript elérheti. HTTP-only cookie biztonságosabb, mert JavaScriptből nem olvasható.
\item \textbf{Hibamonitorozás:} éles alkalmazásban szükséges eszköz (pl. Sentry), hogy a felhasználóknál fellépő hibákról értesüljünk.
\end{itemize}
\end{frame}
+53
View File
@@ -0,0 +1,53 @@
\section{Komponensek}
\begin{frame}{Mi az a komponens?}
\begin{block}{Analógia: LEGO kockák}
Képzeljük el, hogy a weboldalunk LEGO-ból épül. Minden egyes „kocka" egy önálló, újrafelhasználható egység --- ezt nevezzük \textbf{komponensnek}.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Egy komponens egy JavaScript \textbf{függvény}, amely JSX-et ad vissza --- leírja, mit jelenítsen meg.
\item A teljes oldal komponensek fájából áll: van egy gyökér (\texttt{App}), abból nőnek ki az alkomponensek.
\item Például: \texttt{<Header />}, \texttt{<ProductList />}, \texttt{<Footer />} --- mindegyik egy-egy felelősségi kör.
\end{itemize}
\end{frame}
\begin{frame}{Funkcionális és osztály alapú komponensek}
\begin{itemize}
\item \textbf{Funkcionális komponens (modern):} egyszerű JavaScript függvény, hookok segítségével kezeli az állapotot. Ez az ajánlott forma.
\item \textbf{Osztály alapú komponens (régebbi):} ES6 osztályból örököl, életciklus-metódusokat használ. Ma már nem szükséges új kódban alkalmazni.
\item A React csapat 2019 óta a funkcionális megközelítést javasolja --- rövidebb, könnyebben tesztelhető.
\end{itemize}
\end{frame}
\begin{frame}{Mi az a prop?}
\begin{block}{Analógia: paraméterek}
Ahogy egy függvénynek paramétereket adhatunk, a komponenseknek is adhatunk adatokat kívülről. Ezeket \textbf{props}-nak (properties --- tulajdonságok) hívjuk.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item A props \textbf{csak olvasható}: a komponens nem módosíthatja a kapott értéket.
\item Props segítségével ugyanaz a komponens különböző tartalommal jeleníthető meg --- ez teszi újrafelhasználhatóvá.
\item Szinte bármilyen érték átadható: szöveg, szám, tömb, függvény, sőt más komponens is.
\end{itemize}
\end{frame}
\begin{frame}{A \texttt{children} prop és a kompozíció}
\begin{itemize}
\item A \texttt{children} egy speciális prop: a komponens nyitó- és zárócímkéje \emph{közé} írt tartalmat jelenti.
\item Például egy \texttt{<Modal>} komponens bármilyen tartalmat fogadhat belülről --- nem kell előre tudni, mi lesz benne.
\item Ez a \textbf{kompozíció} alapelve: összetett UI-t kisebb, általános darabokból rakunk össze öröklés helyett.
\end{itemize}
\end{frame}
\begin{frame}{Kulcsok (\texttt{key}) listáknál}
\begin{block}{Miért kell a \texttt{key}?}
Ha React egy listát renderel, azonosítania kell, melyik elemet kell frissíteni, törölni vagy hozzáadni. A \texttt{key} prop ebben segít --- egyedi azonosítóként szolgál.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item A \texttt{key} értéke legyen \textbf{stabil és egyedi} --- tipikusan az adatbázisból érkező ID.
\item A tömb indexét csak akkor használjuk, ha a lista soha nem változik sorrendben.
\item Hiányzó vagy nem egyedi \texttt{key} esetén React figyelmeztetést dob, és hibás frissítések léphetnek fel.
\end{itemize}
\end{frame}
+133
View File
@@ -0,0 +1,133 @@
\section{Context}
\begin{frame}{A prop drilling probléma}
\begin{block}{Mi az a prop drilling?}
Ha egy adat a komponensfa tetején él, de csak mélyen lent lévő komponensnek kell, akkor az összes közbülső komponensen át kell „ütni" props-szal --- még akkor is, ha a köztes komponensek maguk nem használják. Ez nehézkessé és törékennyé teszi a kódot.
\end{block}
\vspace{0.5em}
A \textbf{Context API} ezt a problémát oldja meg: az adatot egy közös „kút"-ban tároljuk, amelyből bármely leszármazott komponens közvetlen props nélkül is ihat.
\end{frame}
\begin{frame}{Mire jó a Context API?}
\begin{itemize}
\item \textbf{Ritkán változó, globális adatok} átadásához ideális --- pl. téma (dark/light), aktív nyelv, bejelentkezett felhasználó adatai.
\item Két lépés: 1) \textbf{Provider} --- közzéteszi az értéket a fában; 2) \textbf{useContext} --- olvasásra foglalja le a komponensben.
\item Nem teljes értékű állapotkezelő: sűrűn változó adatokhoz ne használjuk, mert minden fogyasztó komponens újrarenderelődik.
\end{itemize}
\end{frame}
\begin{frame}{A Context és a Provider szerepe}
\begin{block}{Context}
A \texttt{createContext} egy konténer, amely az adatot tárolja. Maga nem csinál semmit --- csak definiálja, hogy melyik adat lesz megosztva.
\end{block}
\vspace{0.4em}
\begin{block}{Provider}
A \texttt{Provider} egy komponens, amely körülvesz más komponenseket, és az értéket \textbf{elérhetővé teszi} számukra. Minden komponens, amely a Provider-ben van, felhasználhatja az adatot.
\end{block}
\end{frame}
\begin{frame}[fragile]{Context és Provider --- alapvető kódpélda}
\begin{verbatim}
import { createContext, useContext } from "react";
// 1. Context létrehozása
const ThemeContext = createContext("light");
// 2. Provider komponens a legfelső szinten
function App() {
return (
<ThemeContext.Provider value="dark">
<Header />
<Content />
</ThemeContext.Provider>
);
}
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Context és Provider --- alapvető kódpélda folytatás}
\begin{verbatim}
// 3. Leszármazott komponensben: useContext
function Header() {
const theme = useContext(ThemeContext);
return <h1>Tema: {theme}</h1>;
}
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Állapottal rendelkező Context --- teljesebb példa}
\footnotesize\begin{verbatim}
// ThemeContext.js
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Felhasználás az alkalmazásban}
\begin{verbatim}
// App.js
import { ThemeProvider } from "./ThemeContext";
function App() {
return (
<ThemeProvider>
<Header />
<MainContent />
</ThemeProvider>
);
}
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Felhasználás az alkalmazásban folytatás}
\begin{verbatim}
// Header.js
function Header() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
Aktualis tema: {theme}
</button>
);
}
\end{verbatim}
\end{frame}
\begin{frame}{Hogyan működik a gyakorlatban?}
\begin{itemize}
\item \texttt{createContext()} a kontextus objektumot hozza létre.
\item A \texttt{Provider} értéket ad át a \texttt{value} prop-on.
\item Mélyen lent elhelyezkedő komponensek a \texttt{useContext()} hookkal használják az adatot.
\item Custom hook (pl. \texttt{useTheme()}) felhasználóbarátabb API-t nyújt.
\end{itemize}
\end{frame}
\begin{frame}{Jó gyakorlatok és gyakori hibák}
\begin{itemize}
\item \textbf{Custom hook:} szokjunk meg a saját hook megírásának (pl. \texttt{useTheme}), ez takarítja a kódot és segíti az újrafelhasználást.
\item \textbf{Túl nagy Context:} ha túl sok adat van egy Context-ben, minden frissítés újrarendereli az összes fogyasztót --- inkább bontsuk fel több kisebb Context-re.
\item \textbf{nem Context-ben való adat:} gyorsan változó, nagy mennyiségű adat (pl. valós idejű pozíciók) nem Context-ben való --- inkább store (Redux, Zustand) vagy külön state.
\item \textbf{Default érték:} adjunk adjunk értelmes \texttt{createContext()} paraméterét --- dev módban segít descobrire a hiányzó Providert.
\end{itemize}
\end{frame}
\begin{frame}{Context vs. más megoldások}
\begin{itemize}
\item \textbf{Props:} egyszerű, néhány szintű adatátadásra. Érthető, explicit.
\item \textbf{Context:} ritkán változó, globális adatok. Szétszórt komponensek között.
\item \textbf{State Manager (Redux/Zustand):} komplett üzleti logika, komplex frissítések, szinkronizálás.
\item \textbf{Szerverállapot (TanStack Query):} API-ból érkező adatok, cache, szinkronizálás.
\end{itemize}
\end{frame}
+43
View File
@@ -0,0 +1,43 @@
\section{Mellékhatások}
\begin{frame}{Mi az a mellékhatás (side effect)?}
\begin{block}{Definí­ció}
Mellékhatásnak nevezzük mindazt, ami a komponens \textbf{renderelésén kívül} történik: hálózati kérés, DOM-módosítás, timer beállítása, eseménykezelő regisztrálása.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item A renderelési fázisban ilyen műveletek nem végzhetők --- a React elvárja, hogy a renderelés \textbf{tiszta} (mellékhatásmentes) legyen.
\item A \texttt{useEffect} hook nyújtja a lehetőséget arra, hogy e műveleteket \emph{renderelés után} hajtsuk végreh.
\end{itemize}
\end{frame}
\begin{frame}{\texttt{useEffect} --- mikor és hányszor fut le?}
\begin{itemize}
\item \textbf{Függőségi történk:} minden egyes renderelés után lefut --- általában nem ezt akarjuk.
\item \textbf{Üres történk (\texttt{[]}):} csak az első megjelenítéskor fut le egyszer --- pl. induló adatlekéréshez.
\item \textbf{Értékekkel (\texttt{[id, szuro]}):} amikor a felsorolt értékek bármelyike megváltozik, újra lefut.
\end{itemize}
\vspace{0.4em}
A függőségi történk tehát azt szabályozza, \textbf{mikor} akarjuk az effektet ismét futtatni.
\end{frame}
\begin{frame}{Cleanup --- takarítás az effect után}
\begin{block}{Miért kell cleanup?}
Ha egy komponens eltűnik az oldalról (pl. navigáció közben), az esetlegesen elindított timerek, eseményfigyelők tovább futnak, memóriaszivárgást okozva. A cleanup függvény ezt akadályozza meg.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Az effect \textbf{visszaadhat egy cleanup függvényt}: ez fut le a komponens unmountjakor, illetve az effect következő lefutása előtt.
\item Tipikus eset: \texttt{clearInterval}, \texttt{removeEventListener}, API kérés megszakítása (\texttt{AbortController}).
\end{itemize}
\end{frame}
\begin{frame}{Leggyakoribb hibák \texttt{useEffect}-tel}
\begin{alertblock}{Figyelem}
\begin{itemize}
\item \textbf{Hiányzó dependency:} ha egy változót használunk de nem szerepel a tömbben, a hook régi értékkel dolgozhat --- ez nehezen felderíthető hiba.
\item \textbf{Végtelen ciklus:} ha az effect frissít egy állapotot, ami maga is dependency, kör forgás indul.
\item \textbf{Túl sok logika egy effectben:} egy effect egy felelősséget kezeljen; ha kettőt kezelne, bontsuk szét.
\end{itemize}
\end{alertblock}
\end{frame}
+38
View File
@@ -0,0 +1,38 @@
\section{Űrlapkezelés}
\begin{frame}{Kontrollált és nem kontrollált input}
\begin{block}{Kontrollált input}
Az input mező értékét a React állapot tárolja és vezérli. A \texttt{value} prop és az \texttt{onChange} esemény mindig szinkronban tartja a React állapotot és a mezőt --- bármikor pontosan tudjuk, mi van a mezőben.
\end{block}
\vspace{0.3em}
\begin{block}{Nem kontrollált input}
A DOM maga kezeli az értéket --- React csak beküldéskor kéri le (\texttt{useRef}-fel). Egyszerűbb felépítés, de valós idejű validáció nehezebb.
\end{block}
\end{frame}
\begin{frame}{Miért érdemes kontrollált inputot használni?}
\begin{itemize}
\item Mindig pontos képünk van az aktuális beviteli értékről --- nem kell a DOM-ból "kiolvasni".
\item \textbf{Valós idejű validáció:} hibát jelzünk gépelés közben, nem csak beküldéskor.
\item Feltételes engedélyezés/tiltás, formázás, karakterlimit könnyen kezelhető.
\item Hátránya: sok mezőnél sok state szükséges --- erre nyújtanak megoldást a könyvtárak.
\end{itemize}
\end{frame}
\begin{frame}{Validáció --- mit kell ellenőrizni?}
\begin{itemize}
\item \textbf{Kötelező mezők:} ne lehessen üres beküldés.
\item \textbf{Formátum:} email, telefonszám, irányítószám megfelelő-e?
\item \textbf{Üzleti szabályok:} min. 8 karakteres jelszó, egyező jelszavak, stb.
\item A hibákat erős vizuális visszajelzéssel kell jelezni --- a felhasználó ne találgasson, mi a baj.
\end{itemize}
\end{frame}
\begin{frame}{Miért használjunk könyvtárat?}
\begin{itemize}
\item Kézi megvalósításnál sok ismétl'd' kód keletkezik --- minden mez'höz saját state, validáció, hibaüzenet.
\item \textbf{React Hook Form:} minimális újrarenderelés, nagyon gyors, könnyen tanulható API --- a legtöbb esetben ez az ajánlott.
\item \textbf{Formik:} régebben nagyon népszerű, sok csapat már ismeri; kicsit több boilerplate.
\item \textbf{Zod / Yup:} séma alapú validáló könyvtárak --- a validációs logikát típusbiztos sémában írjuk le, React Hook Form-mal jól kombinálható.
\end{itemize}
\end{frame}
+55
View File
@@ -0,0 +1,55 @@
\section{Hookok}
\begin{frame}{Mi az a Hook?}
\begin{block}{Az alapgondolat}
A React 16.8 előtt az állapotkezelés és életciklus-logika csak osztály alapú komponensekben volt lehetséges. A hookok ezt hozták el \textbf{funkcionális komponensekbe} is --- így ma már egyszerűbb szintaxissal írhatunk komplex viselkedést.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item A hook neve mindig \texttt{use}-szal kezdődik (pl. \texttt{useState}, \texttt{useEffect}).
\item Beépített hookok lefedik a leggyakoribb igényeket: állapot, mellékhatás, kontextus, optimalizálás.
\item \textbf{Custom hook:} saját logikát csomagolhatunk újrafelhasználható hookba --- pl. \texttt{useWindowSize}, \texttt{useAuth}.
\end{itemize}
\end{frame}
\begin{frame}{\texttt{useState} --- az alapvető állapot hook}
\begin{block}{Mit csinál?}
Az \texttt{useState} lehetővé teszi, hogy egy komponens \textbf{emlékezzen} valamire a renderelések között --- pl. egy számláló értékére, egy modal nyitott/zárt állapotára.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Visszaad egy értéket és egy \textbf{szetter függvényt}: \texttt{const [ertek, setErtek] = useState(kezdoErtek)}.
\item Ha a szetter meghívódik, a React \textbf{újrarendereli} a komponenst az új értékkel.
\item A kezdeti érték csak az első renderelésnél számít --- utána React maga kezeli.
\end{itemize}
\end{frame}
\begin{frame}{\texttt{useReducer} --- összetettebb állapothoz}
\begin{itemize}
\item Ha az állapot több összefüggő értékből áll, vagy a frissítési logika bonyolult, \texttt{useReducer} jobb választás lehet.
\item Működése hasonló a Redux elvéhez: van egy \textbf{akció} (mi történt) és egy \textbf{reducer} függvény (hogyan változik az állapot).
\item A frissítési logika egy helyen, a reducerben él --- olvashatóbb, tesztelhető.
\end{itemize}
\end{frame}
\begin{frame}{\texttt{useRef} --- referencia DOM elemre vagy értékre}
\begin{itemize}
\item Az \texttt{useRef} olyan értéket tárol, amely \textbf{nem vált ki újrarenderelést} megváltozásakor.
\item Leggyakoribb használat: közvetlen DOM-elem elérése --- pl. input fókuszálása, video lejátszás indítása.
\item Hasznos timer ID-k és előző értékek tárolására is: bármire, amit renderelések között „el akarunk menteni" anélkül, hogy az oldal frissüljön.
\end{itemize}
\end{frame}
\begin{frame}{Hook szabályok --- miért fontosak?}
\begin{alertblock}{Alapszabályok}
\begin{enumerate}
\item Hookot csak \textbf{komponens vagy custom hook legfelső szintjén} hívjunk.
\item Ne ciklusban, feltételben vagy beágyazott függvényen belül hívjuk.
\end{enumerate}
\end{alertblock}
\vspace{0.5em}
\begin{itemize}
\item \textbf{Miért?} A React a hookok \emph{hívási sorrendje} alapján párosítja az állapotokat a komponenshez. Ha a sorrend változik (pl. feltétel miatt kimarad egy hook), React összetéveszti, melyik állapot melyikhez tartozik.
\item Az ESLint \texttt{eslint-plugin-react-hooks} csomag automatikusan ellenőrzi ezeket.
\end{itemize}
\end{frame}
@@ -0,0 +1,37 @@
\section{Könyvtárak}
\begin{frame}{UI komponens könyvtárak}
\begin{block}{Mire valók?}
Kész, előre megírt és stílusozott UI komponensek gyűjteményei --- gombok, táblázatok, modalok, értesítések stb. Nem kell nulláról megírni a vizuális elemeket.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item \textbf{MUI (Material UI):} Google Material Design stílus, nagyon széleskörű komponenskészlet.
\item \textbf{Headless UI, Radix UI:} csak a viselkedési logikát adják, a megjelenést teljes egészében mi írjuk --- maximális szabadság, Tailwind-del kombinálható.
\item \textbf{shadcn/ui:} Radix + Tailwind alapú, másolható komponensek --- egyre népszerűbb.
\end{itemize}
\end{frame}
\begin{frame}{Állapot és adatkezelés ökoszisztéma}
\begin{itemize}
\item \textbf{Redux Toolkit:} a Redux modern, kevésbé terjengős változata. Komplex állapotlogikához és nagy csapatoknak ideális.
\item \textbf{Zustand:} egyszerű, minimális API-jú globális store. Kis és közepes projekteknél kiváló alternatíva.
\item \textbf{Jotai:} atomi állapotkezelés --- az állapot apró, egymásra épülő atomokból áll. Fine-grained reaktivitáshoz jó.
\item \textbf{TanStack Query:} szerverállapot kezelésére specializált --- cache, háttérfrissítés, újrapróbálkozás.
\item \textbf{Zod:} típusbiztos adatvalidáció sémákkal --- API válaszok, form adatok ellenőrzéséhez.
\end{itemize}
\end{frame}
\begin{frame}{Összefoglalás --- a React ökoszisztéma}
\begin{itemize}
\item \textbf{Alap:} komponensek, props, state, hookok, JSX.
\item \textbf{Interakció:} eseménykezelés, űrlapok, navigáció.
\item \textbf{Adatok:} useEffect, Axios / TanStack Query, Context.
\item \textbf{Minőség:} TypeScript, tesztelés, teljesítmény.
\item \textbf{Kiadás:} build, deploy, biztonság, monitorozás.
\end{itemize}
\vspace{0.5em}
\begin{alertblock}{Tanács kezdőknek}
Ne akarjuk egyszerre megtanulni az összes eszközt. Kezdjük az alapokkal (komponens, state, effect), és szükség szerint bővítsük a tudást.
\end{alertblock}
\end{frame}
+36
View File
@@ -0,0 +1,36 @@
\section{Teljesítmény}
\begin{frame}{Mi az az újrarenderelés?}
\begin{block}{Az alapjelenség}
Amikor egy komponens állapota vagy props-a megváltozik, a React \textbf{újrarendereli} azt a komponenst --- és alapértelmezetten az összes gyermekét is. Ez legtöbbször tökéletesen gyors. Nagy és mély fáknál azonban szükségtelen újrarenderelések lassíthatnak.
\end{block}
\vspace{0.5em}
Fontos szabály: \textbf{mérjünk, aztán optimalizáljunk!} Ne alkalmazzunk előre memoizációt ott, ahol valójában nincs probléma.
\end{frame}
\begin{frame}{React DevTools Profiler}
\begin{itemize}
\item A React DevTools böngésző-bővítmény beépített \textbf{Profiler} lapján látjuk, hogy melyik komponens hányszor és mennyi ideig rendereledett.
\item Felvesszük egy interakció közben a renderelési folyamatot, majd azonosítjuk a lassú vagy felesleges részeket.
\item Csak azután nyúljunk optimalizáláshoz, ha a profiler valódi problémát mutat.
\end{itemize}
\end{frame}
\begin{frame}{Memoizáció --- mit és mikor?}
\begin{itemize}
\item \textbf{React.memo:} ha egy komponens props-ai nem változnak, ne renderelje újra. Érdemes drága megjelenítésű, sokszor hívott komponenseken alkalmazni.
\item \textbf{useMemo:} ha egy számítás nagyon drága (pl. óriási lista szűrése), cache-eljük az eredményt --- csak akkor számítsuk újra, ha a bemenetek megváltoztak.
\item \textbf{useCallback:} ha egy függvényt props-ként adunk át, és fontos, hogy a referenciája stabil maradjon (pl. React.memo-val védett gyermeknek).
\end{itemize}
\end{frame}
\begin{frame}{Kódfelosztás és lusta betöltés}
\begin{block}{A probléma}
Nagy alkalmazásoknál a teljes JavaScript csomag egyszerre töltődik be --- ez lassítja az első megjelenést.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item \textbf{React.lazy + Suspense:} az egyes oldalakat/modulokat csak akkor töltjük be, amikor a felhasználó ténylegesen odanavigál.
\item \textbf{Lista virtualizáció} (pl. \texttt{react-window}): ha több ezer listaelemet kell megjeleníteni, csak a látható elemeket rendereljük --- a többi DOM-ban sem szerepel.
\end{itemize}
\end{frame}
+80
View File
@@ -0,0 +1,80 @@
\section{React alapok}
\begin{frame}{Mi a React?}
\begin{block}{Rövid definíció}
A React egy nyílt forráskódú JavaScript \textbf{könyvtár}, amelyet a Meta (Facebook) fejlesztett ki.
Fő célja: webalkalmazások felhasználói felületének (UI) hatékony és karbantartható megírása.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Nem egy teljes keretrendszer --- csak a megjelenítési réteggel foglalkozik.
\item Kiegészítő könyvtárakkal (routing, adatkezelés) teljes alkalmazás is építhető.
\item 2013 óta aktívan fejlesztik; ma az egyik legelterjedtebb frontend technológia.
\end{itemize}
\end{frame}
\begin{frame}{Deklaratív vs.\ imperatív szemlélet}
\begin{columns}
\column{0.48\textwidth}
\textbf{Régi, imperatív szemlélet}\\
\textit{„Keresd meg a gombot, módosítsd a szövegét, frissítsd a listát\ldots"}\\
\vspace{0.5em}
$\Rightarrow$ Megadjuk, \emph{hogyan} csinálja a böngésző lépésről lépésre.
\column{0.48\textwidth}
\textbf{React: deklaratív szemlélet}\\
\textit{„Ha a kosár üres, ezt jelenítsd meg; ha van termék, amazt."}\\
\vspace{0.5em}
$\Rightarrow$ Megadjuk, \emph{mit} akarunk látni --- a React intézi a DOM-frissítést.
\end{columns}
\end{frame}
\begin{frame}{Mi az a virtuális DOM?}
\begin{block}{DOM = Document Object Model}
A böngésző az oldalt egy faszerkezetben (DOM) tárolja. Sok elem esetén a közvetlen DOM-módosítás lassú lehet.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item A React egy \textbf{virtuális DOM}-ot tart fenn a memóriában --- ez egy gyors, könnyű másolata a valódi DOM-nak.
\item Állapotváltozáskor összehasonlítja az új és a régi virtuális DOM-ot (\emph{diffing}).
\item Csak a ténylegesen megváltozott részeket frissíti a böngészőben --- ezért gyors és hatékony.
\end{itemize}
\end{frame}
\begin{frame}{Miért érdemes React-et tanulni?}
\begin{itemize}
\item \textbf{Újrafelhasználhatóság:} egyszer megírt komponens bárhová beilleszthető.
\item \textbf{Nagy közösség:} rengeteg oktatóanyag, könyvtár és álláshirdetés.
\item \textbf{Skálázhatóság:} kis projekttől nagy vállalati alkalmazásig alkalmazható.
\item \textbf{Átváltható tudás:} React Native-szal mobilalkalmazás is írható ugyanezzel a szemlélettel.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Projektindítás Vite-tal}
\begin{block}{Miért Vite?}
A Vite egy modern build eszköz: gyorsan indítja el a fejlesztői szervert, és azonnal tükrözi a módosításokat a böngészőben. Ezt hívják HMR-nek (Hot Module Replacement --- „élő újratöltés").
\end{block}
\begin{verbatim}
npm create vite@latest sajat-app -- --template react
cd sajat-app
npm install
npm run dev
\end{verbatim}
\begin{itemize}
\item Az \texttt{npm run dev} elindítja a fejlesztői szervert (alapból \texttt{localhost:5173}).
\item \texttt{npm run build} paranccsal production-kész, tömörített kódot kapunk.
\end{itemize}
\end{frame}
\begin{frame}{JSX --- HTML és JavaScript egyben}
\begin{block}{Mi az a JSX?}
A JSX (JavaScript XML) egy szintaktikai kiterjesztés: HTML-szerű kódot írhatunk JavaScript-ben.
A böngésző közvetlenül nem érti --- a build eszköz fordítja sima JavaScript-té.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item JavaScript kifejezéseket \texttt{\{\}} zárójelbe írjuk: változó, függvényhívás, feltétel.
\item Minden JSX elemnek pontosan egy gyökéreleme lehet (vagy \texttt{<>\ldots</>} fragment).
\item A \texttt{class} HTML attribútum neve JSX-ben \texttt{className} --- a \texttt{class} JS-ben foglalt szó.
\end{itemize}
\end{frame}
Binary file not shown.
+31
View File
@@ -0,0 +1,31 @@
\documentclass[usenames,dvipsnames,aspectratio=169,compress]{beamer}
\usepackage{../common/webfejl}
\title[Webtechnológia és webalkalmazás-fejlesztés - Frontend (React)]{Webtechnológia és webalkalmazás-fejlesztés - Frontend (React)}
\subtitle{Frontend fejlesztés React könyvtárral}
\begin{document}
\begin{frame}[plain]
\titlepage
\logoalul
\end{frame}
\input{react.tex}
\input{components.tex}
\input{hooks.tex}
\input{state.tex}
\input{forms.tex}
\input{effects.tex}
\input{routing.tex}
\input{context.tex}
\input{tailwind.tex}
\input{axios.tex}
\input{performance.tex}
\input{testing.tex}
\input{typescript_nextjs.tex}
\input{build_deploy.tex}
\input{other_relevant_libraries.tex}
\end{document}
+98
View File
@@ -0,0 +1,98 @@
\section{Navigáció}
\begin{frame}{Mit jelent a kliensoldali navigáció?}
\begin{block}{Hagyományos vs.\ SPA navigáció}
Hagyományos weboldalon minden oldalváltáskor a böngésző \textbf{új HTTP kérést} küld, és teljesen újratölti az oldalt.
SPA (Single Page Application) esetén az oldal egyszer töltődik be, a navigáció pedig JavaScript-tel történik,
ezért gyorsabb és folyamatosabb élményt ad.
\end{block}
\vspace{0.5em}
A React Router a legelterjedtebb könyvtár erre a feladatra React alkalmazásokban.
\end{frame}
\begin{frame}{React Router --- hogyan működik?}
\begin{itemize}
\item A \texttt{BrowserRouter} figyeli a böngésző URL-jét.
\item A \texttt{Routes} és \texttt{Route} elemek URL mintákhoz komponenseket rendelnek.
\item A \texttt{Link} URL-t vált teljes oldalfrissítés nélkül.
\item A React újrarendereli a megfelelő oldalkomponenst az aktuális útvonal alapján.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{React Router példa kód 1/2}
\begin{verbatim}
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Fooldal</Link>
<Link to="/termekek">Termekek</Link>
</nav>
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{React Router példa kód 2/2}
\begin{verbatim}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/termekek" element={<Products />} />
<Route path="/termekek/:id" element={<ProductDetails />} />
</Routes>
</BrowserRouter>
);
}
\end{verbatim}
\end{frame}
\begin{frame}{Dinamikus útvonalak (React Router)}
\begin{itemize}
\item Paraméteres route példa: \texttt{/termekek/:id}
\item Ha az URL \texttt{/termekek/42}, akkor a \texttt{useParams()} eredménye: \texttt{\{ id: "42" \}}
\item Tipikusan ilyen paraméterrel kérünk le részletes adatot API-ból.
\end{itemize}
\end{frame}
\begin{frame}{Mappa routing (file-system routing) --- mi ez?}
\begin{block}{Alapelv}
Mappaalapú routingnál az útvonalakat nem külön \texttt{Routes} konfigurációban írjuk,
hanem a mappastruktúra \textbf{automatikusan} meghatározza őket.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Ez főleg Next.js-ben elterjedt (App Router).
\item Az \texttt{app/} mappában minden \texttt{page.tsx} egy útvonalat jelent.
\item Dinamikus route mappanévben: \texttt{[id]}.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Mappa routing példa (Next.js App Router)}
\begin{verbatim}
app/
page.tsx -> /
kapcsolat/
page.tsx -> /kapcsolat
termekek/
page.tsx -> /termekek
[id]/
page.tsx -> /termekek/:id
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Dinamikus mappa route komponens példa}
\begin{verbatim}
// app/termekek/[id]/page.tsx
export default function ProductPage({ params }) {
return <h2>Termek azonosito: {params.id}</h2>;
}
\end{verbatim}
\end{frame}
\begin{frame}{React Router vs. mappa routing}
\begin{itemize}
\item \textbf{React Router:} explicit útvonal definíció a kódban (rugalmas, kontrollált).
\item \textbf{Mappa routing:} mappaszerkezetből automatikus route (gyors indulás, kevesebb konfiguráció).
\item Kezdőknek mindkettőt érdemes ismerni: React Router SPA-hoz, mappa routing Next.js projektekhez.
\end{itemize}
\end{frame}
+50
View File
@@ -0,0 +1,50 @@
\section{Állapotkezelés}
\begin{frame}{Mi az állapot (state)?}
\begin{block}{Analógia: a komponens "emlékezete"}
Az állapot az, amit a komponens \textbf{megjegyez} renderelések között. Gondoljunk rá úgy, mint egy cetlire, amire a komponens feljegyzi az aktuális értékeit --- hány termék van a kosárban, be van-e jelentkezve a felhasználó, milyen szöveg van az input mezőben.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Az állapot megváltozásakor a React \textbf{automatikusan újrarendereli} az érintett komponenst.
\item Az állapot a komponensen \emph{belül} él --- más komponens nem látja közvetlenül.
\end{itemize}
\end{frame}
\begin{frame}{Állapot típusok a gyakorlatban}
\begin{itemize}
\item \textbf{Lokális UI állapot:} csak egy komponenst érint --- pl. le van-e hajtva egy dropdown, aktív-e egy fül.
\item \textbf{Megosztott állapot:} több komponens is olvas vagy ír belőle --- pl. a bejelentkezett felhasználó neve.
\item \textbf{Szerverállapot:} API-ból érkező, kiszolgálón élő adat, amelyet le kell kérni és szinkronban kell tartani.
\item \textbf{URL állapot:} az aktuális útvonal, query paraméterek --- természetesen megosztható és könyvjelzőzhető.
\end{itemize}
\end{frame}
\begin{frame}{Egyirányú adatfolyam}
\begin{block}{Mi ez pontosan?}
Reactben az adatok mindig \textbf{szülőtől gyermek felé} áramlanak (props-on keresztül). A gyermek \emph{nem módosíthatja} a szülő állapotát közvetlenül --- csak egy callback függvényen (eseménykezelőn) keresztül jelezhet vissza.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Ezért kiszámítható: mindig tudjuk, honnan ered egy érték.
\item Hibakeresés könnyebb --- az adatfolyamot felfelé haladva követhetjük.
\end{itemize}
\end{frame}
\begin{frame}{State emelés (Lifting State Up)}
\begin{itemize}
\item Ha két testvérkomponensnek ugyanazt az adatot kell látnia, az állapotot a legközelebbi közös ősbe \textbf{emeljük fel}.
\item Az ős kezeli az állapotot, és props-on keresztül osztja szét a gyermekek között.
\item \textbf{Példa:} egy szűrő mező és egy lista --- mindkettőnek ugyanaz a szűrési feltétel kell, ezért azt a szülőben tároljuk.
\end{itemize}
\end{frame}
\begin{frame}{Mikor kell külső állapotkezelő?}
\begin{itemize}
\item Ha az állapot emelése sok szinten keresztül megy, és a köztes komponensek csak "átpasszolják" --- ezt hívjuk \textbf{prop drilling}-nek.
\item Ha az állapot nagyon sok helyen kell, és bonyolult szinkronizálás szükséges.
\item Külső megoldások: \textbf{Redux Toolkit} (nagy, komplex alkalmazásokhoz), \textbf{Zustand} (könnyű, egyszerű API), \textbf{Jotai} (atomi, finomhangolt).
\item Legtöbb esetben a beépített eszközök (useState + Context) elegendők --- ne bonyolítsuk túl.
\end{itemize}
\end{frame}
+38
View File
@@ -0,0 +1,38 @@
\section{Stílusozás}
\begin{frame}{A CSS megközelítések áttekintése}
\begin{itemize}
\item \textbf{Globális CSS:} hagyományos, minden komponens látja --- névütközések kockázatával.
\item \textbf{CSS Modules:} minden komponensnek saját, automatikusan lokalizált CSS osztályai vannak --- nincs névütközés.
\item \textbf{CSS-in-JS} (pl. styled-components, Emotion): közvetlenül JavaScript-ben írunk stílusokat, dinamikus értékek könnyen használhatók.
\item \textbf{Utility-first} (Tailwind CSS): előre definiált kis osztályokat kombinálunk --- nincs saját CSS fájl.
\end{itemize}
\end{frame}
\begin{frame}{Mi az a Tailwind CSS?}
\begin{block}{Az alapötlet}
A Tailwind CSS nem komponenseket, hanem apró, egy-egy CSS tulajdonságot képviselő \textbf{utility osztályokat} ad. Ezeket közvetlenül a JSX-be írjuk --- pl. \texttt{flex}, \texttt{pt-4}, \texttt{text-gray-700}.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item Előny: nem kell kitalálni osztályneveket, nincsenek névütközések, konzisztens design tokenek.
\item Hátrány: a JSX-ben hosszú osztálylisták keletkezhetnek --- komponens-szintű absztrakciókkal kezelhető.
\end{itemize}
\end{frame}
\begin{frame}{Design rendszer gondolkodás}
\begin{itemize}
\item Jól felépített alkalmazásban definiálunk \textbf{UI primitíveket}: \texttt{Button}, \texttt{Input}, \texttt{Card}, \texttt{Badge} stb.
\item Ezek belül rejtenek el minden stílust --- a felhasználójuk csak a variánst adja meg (pl. \texttt{variant="primary"}).
\item \textbf{Egységes spacing, színek, tipográfia:} ezeket design tokenek (Tailwind config vagy CSS változók) rögzítik, nem ismétlünk hardcoded értékeket.
\end{itemize}
\end{frame}
\begin{frame}{Hozzáférhetőség (accessibility)}
\begin{itemize}
\item \textbf{Kontraszt:} a szöveg és háttér közötti kontraszt arány elégítse ki a WCAG irányelveket.
\item \textbf{Fókuszállapot:} billentyűzettel is navigálható legyen az oldal --- a fókuszjelzőt ne távolítsuk el.
\item \textbf{Szemantikus HTML:} helyes heading hierarchia, gomb valóban \texttt{<button>}, ne \texttt{<div onClick>}.
\item \textbf{ARIA attribútumok:} ahol a HTML szemantika nem elég (pl. egyedi komponensek).
\end{itemize}
\end{frame}
+33
View File
@@ -0,0 +1,33 @@
\section{Tesztelés}
\begin{frame}{Miért teszteljünk?}
\begin{block}{Az alapmotiváció}
A tesztek nem csak hibákat fednek fel --- \textbf{dokumentálják a szándékolt viselkedést} és biztosítékot adnak arra, hogy jövőbeli módosítások nem törnek el meglévő funkciókat. Refaktorálás és csapatmunka esetén különösen értékes.
\end{block}
\end{frame}
\begin{frame}{Tesztelési szintek}
\begin{itemize}
\item \textbf{Unit teszt:} egyetlen függvény, hook vagy logikai egység viselkedését ellenőrzi, függetlenül a többitől. Gyors, izolált.
\item \textbf{Integrációs teszt:} több komponens vagy réteg együttműködését vizsgálja --- pl. egy form elküldésének teljes folyamata, beleértve az állapotkezelést.
\item \textbf{E2E teszt} (End-to-End): egy valódi böngészőben szimulál felhasználói lépéseket --- pl. Playwright-tal. Lassabb, de a legvalóságosabb visszajelzést adja.
\end{itemize}
\end{frame}
\begin{frame}{Ajánlott eszközök}
\begin{itemize}
\item \textbf{Vitest:} modern, Vite-alapú tesztfuttató --- gyors, könnyen konfigurálható, ES module-barát.
\item \textbf{Jest:} régebben az iparági standard, nagyon elterjedt, rengeteg dokumentáció.
\item \textbf{React Testing Library:} komponenseket \emph{felhasználói szemszögből} tesztel --- nem implementációs részleteket, hanem azt, amit a felhasználó lát és tehet.
\item \textbf{Mock Service Worker (MSW):} API válaszokat szimulál hálózati szinten --- nem kell valódi szerver a tesztekhez.
\end{itemize}
\end{frame}
\begin{frame}{Mit érdemes tesztelni?}
\begin{itemize}
\item \textbf{Kritikus folyamatok:} regisztráció, bejelentkezés, fizetés, jogosultság-ellenőrzés.
\item \textbf{Hibaállapotok:} mi történik, ha a hálózat megszakad, a szerver hibát ad, az input érvénytelen?
\item \textbf{Szélsőértékek (edge case):} üres lista, nagyon hosszú szöveg, speciális karakterek.
\item \textbf{Hozzáférhetőség:} a kritikus UI elemek megfelelő ARIA szerepkörrel és felirattal rendelkeznek-e?
\end{itemize}
\end{frame}
@@ -0,0 +1,35 @@
\section{TypeScript / Next.js}
\begin{frame}{Mi az a TypeScript?}
\begin{block}{JavaScript + típusok}
A TypeScript a JavaScript egy \textbf{típusos kibővítése}: szintaktikailag ugyanolyan, de lehetővé teszi, hogy megmondjuk, egy változó szám-e, szöveg-e, vagy éppen egy konkrét adatstruktúra. A böngésző ezután sem érti --- fordításkor sima JavaScript-té alakul.
\end{block}
\end{frame}
\begin{frame}{Miért TypeScript Reacthez?}
\begin{itemize}
\item \textbf{Korai hibajelzés:} a szerkesztő azonnal jelzi, ha rossz típusú props-ot adunk át egy komponensnek --- nem kell a böngészőben futtatni.
\item \textbf{Öndokumentáló kód:} a props típusai rögtön megmondják, mit vár a komponens --- nincs szükség külön kommentre.
\item \textbf{Karbantarthatóság:} refaktoráláskor a fordító jelzi, hol kell módosítani --- nagyobb változtatások biztonságosabbak.
\item Kis projekten is megéri a tanulási görbéje, mert a hosszabb távú haszon jelentős.
\end{itemize}
\end{frame}
\begin{frame}{Mi az a Next.js?}
\begin{block}{React + szerver}
A Next.js egy teljes React keretrendszer: beépített routing, szerveroldali renderelés (SSR), statikus oldalak generálása (SSG), képoptimalizálás, és más funkciók --- mindez konfiguráció nélkül.
\end{block}
\vspace{0.5em}
\begin{itemize}
\item \textbf{SSR (Server-Side Rendering):} a szerver minden kérésnél rendereli az oldalt --- friss adatok, jó SEO.
\item \textbf{SSG (Static Site Generation):} build-időben generál HTML-t --- villámgyors, CDN-ről tálalható.
\end{itemize}
\end{frame}
\begin{frame}{Mikor melyiket válasszuk?}
\begin{itemize}
\item \textbf{Vite + React (SPA):} admin felületek, dashboardok, belső eszközök --- ahol a SEO nem kritikus, a bejelentkezés után töltődik be a tartalom.
\item \textbf{Next.js:} publikus weboldalak, e-commerce, blog, dokumentáció --- ahol a keres'optimalizálás és a gyors els' betöltés fontos.
\item \textbf{Mindkét esetben ajánlott:} TypeScript, lint, automatikus tesztek, CI/CD csővezeték.
\end{itemize}
\end{frame}