Full Code of rolling-scopes/rsschool-app for AI

master a3363fecfac5 cached
1783 files
5.0 MB
1.4M tokens
4373 symbols
1 requests
Download .txt
Showing preview only (5,605K chars total). Download the full file or copy to clipboard to get everything.
Repository: rolling-scopes/rsschool-app
Branch: master
Commit: a3363fecfac5
Files: 1783
Total size: 5.0 MB

Directory structure:
gitextract_5q18uku4/

├── .agents/
│   └── skills/
│       ├── nestjs-best-practices/
│       │   ├── .github/
│       │   │   └── workflows/
│       │   │       ├── branch-protection.yml
│       │   │       └── deploy.yml
│       │   ├── .gitignore
│       │   ├── AGENTS.md
│       │   ├── README.md
│       │   ├── SKILL.md
│       │   ├── rules/
│       │   │   ├── api-use-dto-serialization.md
│       │   │   ├── api-use-interceptors.md
│       │   │   ├── api-use-pipes.md
│       │   │   ├── api-versioning.md
│       │   │   ├── arch-avoid-circular-deps.md
│       │   │   ├── arch-feature-modules.md
│       │   │   ├── arch-module-sharing.md
│       │   │   ├── arch-single-responsibility.md
│       │   │   ├── arch-use-events.md
│       │   │   ├── arch-use-repository-pattern.md
│       │   │   ├── db-avoid-n-plus-one.md
│       │   │   ├── db-use-migrations.md
│       │   │   ├── db-use-transactions.md
│       │   │   ├── devops-graceful-shutdown.md
│       │   │   ├── devops-use-config-module.md
│       │   │   ├── devops-use-logging.md
│       │   │   ├── di-avoid-service-locator.md
│       │   │   ├── di-interface-segregation.md
│       │   │   ├── di-liskov-substitution.md
│       │   │   ├── di-prefer-constructor-injection.md
│       │   │   ├── di-scope-awareness.md
│       │   │   ├── di-use-interfaces-tokens.md
│       │   │   ├── error-handle-async-errors.md
│       │   │   ├── error-throw-http-exceptions.md
│       │   │   ├── error-use-exception-filters.md
│       │   │   ├── micro-use-health-checks.md
│       │   │   ├── micro-use-patterns.md
│       │   │   ├── micro-use-queues.md
│       │   │   ├── perf-async-hooks.md
│       │   │   ├── perf-lazy-loading.md
│       │   │   ├── perf-optimize-database.md
│       │   │   ├── perf-use-caching.md
│       │   │   ├── security-auth-jwt.md
│       │   │   ├── security-rate-limiting.md
│       │   │   ├── security-sanitize-output.md
│       │   │   ├── security-use-guards.md
│       │   │   ├── security-validate-all-input.md
│       │   │   ├── test-e2e-supertest.md
│       │   │   ├── test-mock-external-services.md
│       │   │   └── test-use-testing-module.md
│       │   └── scripts/
│       │       ├── build-agents.ts
│       │       ├── build.sh
│       │       └── package.json
│       ├── typeorm/
│       │   └── SKILL.md
│       └── typescript-advanced-types/
│           └── SKILL.md
├── .dockerignore
├── .editorconfig
├── .eslintignore
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── data-issue-report.md
│   │   └── feature-request.md
│   ├── auto-label.json
│   ├── copilot-instructions.md
│   ├── pull_request_template.md
│   └── workflows/
│       ├── deploy-sloths.yaml
│       ├── deploy.yaml
│       ├── pull_request.yml
│       ├── pull_request_close.yml
│       └── renovate.yml
├── .gitignore
├── .oxfmtrc.json
├── AGENTS.md
├── CONTRIBUTING.md
├── DOMAIN.md
├── GUIDELINES.md
├── LICENSE
├── README.md
├── VITEST.md
├── client/
│   ├── .dockerignore
│   ├── Dockerfile
│   ├── Dockerfile.lambda
│   ├── README.md
│   ├── eslint.config.mjs
│   ├── next-env.d.ts
│   ├── next.config.mjs
│   ├── next.config.prod.mjs
│   ├── package.json
│   ├── playwright.config.ts
│   ├── public/
│   │   └── static/
│   │       └── empty.txt
│   ├── specs/
│   │   └── smoke.spec.ts
│   ├── src/
│   │   ├── __mocks__/
│   │   │   ├── axios.js
│   │   │   ├── hooks/
│   │   │   │   ├── index.ts
│   │   │   │   ├── useMessage.tsx
│   │   │   │   └── useTheme.tsx
│   │   │   └── next/
│   │   │       └── config.ts
│   │   ├── __tests__/
│   │   │   ├── ProfilePage.test.tsx
│   │   │   └── __snapshots__/
│   │   │       └── ProfilePage.test.tsx.snap
│   │   ├── api/
│   │   │   ├── .gitignore
│   │   │   ├── .npmignore
│   │   │   ├── .openapi-generator/
│   │   │   │   ├── FILES
│   │   │   │   └── VERSION
│   │   │   ├── .openapi-generator-ignore
│   │   │   ├── api.ts
│   │   │   ├── base.ts
│   │   │   ├── common.ts
│   │   │   ├── configuration.ts
│   │   │   ├── git_push.sh
│   │   │   └── index.ts
│   │   ├── components/
│   │   │   ├── Analytics.tsx
│   │   │   ├── Comment.tsx
│   │   │   ├── CountBadge/
│   │   │   │   ├── CountBadge.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── CoursePageLayout.tsx
│   │   │   ├── DevTools/
│   │   │   │   ├── DevToolsContainer.tsx
│   │   │   │   ├── DevToolsCurrentUser.tsx
│   │   │   │   ├── DevToolsUsers.tsx
│   │   │   │   └── index.ts
│   │   │   ├── Footer/
│   │   │   │   ├── Donation.tsx
│   │   │   │   ├── Feedback.tsx
│   │   │   │   ├── FooterLayout.tsx
│   │   │   │   ├── Help.tsx
│   │   │   │   ├── Menu.tsx
│   │   │   │   ├── SocialNetworks.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── HeaderMiniBannerCarousel.module.css
│   │   │   ├── HeaderMiniBannerCarousel.test.tsx
│   │   │   ├── HeaderMiniBannerCarousel.tsx
│   │   │   ├── Heroes/
│   │   │   │   ├── HeroesCountBadge.tsx
│   │   │   │   ├── HeroesRadarTab.tsx
│   │   │   │   └── HeroesRadarTable.tsx
│   │   │   ├── LoadingScreen.module.css
│   │   │   ├── MentorOptions.tsx
│   │   │   ├── Profile/
│   │   │   │   ├── AboutCard.tsx
│   │   │   │   ├── CommonCard.tsx
│   │   │   │   ├── CommonCardWithSettingsModal.tsx
│   │   │   │   ├── ContactsCard.tsx
│   │   │   │   ├── ContactsCardForm.tsx
│   │   │   │   ├── DiscordCard.tsx
│   │   │   │   ├── EducationCard.tsx
│   │   │   │   ├── EmailConfirmation.tsx
│   │   │   │   ├── InterviewCard.tsx
│   │   │   │   ├── InterviewModal.tsx
│   │   │   │   ├── LanguagesCard.tsx
│   │   │   │   ├── MainCard.tsx
│   │   │   │   ├── MentorStatsCard.tsx
│   │   │   │   ├── MentorStatsModal.tsx
│   │   │   │   ├── ObfuscateConfirmationModal.tsx
│   │   │   │   ├── ProfileSettingsModal.module.css
│   │   │   │   ├── ProfileSettingsModal.tsx
│   │   │   │   ├── PublicFeedbackCard.tsx
│   │   │   │   ├── PublicFeedbackModal.tsx
│   │   │   │   ├── StudentLeaveCourse.tsx
│   │   │   │   ├── StudentStatsCard.tsx
│   │   │   │   ├── StudentStatsModal.tsx
│   │   │   │   ├── __test__/
│   │   │   │   │   ├── AboutCard.test.tsx
│   │   │   │   │   ├── CommonCard.test.tsx
│   │   │   │   │   ├── CommonCardWithSettingsModal.test.tsx
│   │   │   │   │   ├── ContactsCard.test.tsx
│   │   │   │   │   ├── ContactsCardForm.test.tsx
│   │   │   │   │   ├── EducationCard.test.tsx
│   │   │   │   │   ├── InterviewCard.test.tsx
│   │   │   │   │   ├── InterviewModal.test.tsx
│   │   │   │   │   ├── MainCard.test.tsx
│   │   │   │   │   ├── MentorStatsCard.test.tsx
│   │   │   │   │   ├── MentorStatsModal.test.tsx
│   │   │   │   │   ├── ProfileSettingsModal.test.tsx
│   │   │   │   │   ├── PublicFeedbackCard.test.tsx
│   │   │   │   │   ├── PublicFeedbackModal.test.tsx
│   │   │   │   │   ├── StudentStatsCard.test.tsx
│   │   │   │   │   ├── StudentStatsModal.test.tsx
│   │   │   │   │   └── __snapshots__/
│   │   │   │   │       ├── AboutCard.test.tsx.snap
│   │   │   │   │       ├── CommonCard.test.tsx.snap
│   │   │   │   │       ├── CommonCardWithSettingsModal.test.tsx.snap
│   │   │   │   │       ├── ContactsCard.test.tsx.snap
│   │   │   │   │       ├── ContactsCardForm.test.tsx.snap
│   │   │   │   │       ├── EducationCard.test.tsx.snap
│   │   │   │   │       ├── MainCard.test.tsx.snap
│   │   │   │   │       ├── ProfileSettingsModal.test.tsx.snap
│   │   │   │   │       ├── PublicFeedbackCard.test.tsx.snap
│   │   │   │   │       ├── PublicFeedbackModal.test.tsx.snap
│   │   │   │   │       ├── StudentStatsCard.test.tsx.snap
│   │   │   │   │       └── StudentStatsModal.test.tsx.snap
│   │   │   │   └── ui/
│   │   │   │       ├── DateWidget.tsx
│   │   │   │       ├── ExpandButtonWidget.tsx
│   │   │   │       ├── InterviewerWidget.tsx
│   │   │   │       ├── IsGoodCandidateWidget.tsx
│   │   │   │       ├── LegacyScreeningFeedback.tsx
│   │   │   │       ├── PrescreeningFeedback.tsx
│   │   │   │       ├── ScoreWidget.tsx
│   │   │   │       ├── __tests__/
│   │   │   │       │   ├── DateWidget.test.tsx
│   │   │   │       │   ├── ExpandButtonWidget.test.tsx
│   │   │   │       │   ├── InterviewerWidget.test.tsx
│   │   │   │       │   ├── IsGoodCandidateWidget.test.tsx
│   │   │   │       │   └── ScoreWidget.test.tsx
│   │   │   │       └── index.ts
│   │   │   ├── RegistrationPageLayout.tsx
│   │   │   ├── SelectLanguages.tsx
│   │   │   ├── SettingsItem.tsx
│   │   │   ├── SlothImage.tsx
│   │   │   ├── Student/
│   │   │   │   ├── AssignStudentModal.tsx
│   │   │   │   ├── DashboardDetails.module.css
│   │   │   │   ├── DashboardDetails.tsx
│   │   │   │   └── index.ts
│   │   │   ├── StudentDiscord.tsx
│   │   │   ├── TabsWithCounter/
│   │   │   │   └── renderers.tsx
│   │   │   ├── Warning/
│   │   │   │   └── index.tsx
│   │   │   ├── WelcomeCard.tsx
│   │   │   ├── __tests__/
│   │   │   │   ├── CopyToClipboardButton.test.tsx
│   │   │   │   ├── GithubUserLink.test.tsx
│   │   │   │   ├── Rating.test.tsx
│   │   │   │   └── StudenDiscrod.test.tsx
│   │   │   ├── common/
│   │   │   │   └── CustomPopconfirm.tsx
│   │   │   ├── useLoading.tsx
│   │   │   ├── withGoogleMaps.tsx
│   │   │   └── withSession.tsx
│   │   ├── configs/
│   │   │   ├── cdn.ts
│   │   │   ├── course-icons.ts
│   │   │   ├── discord-integration.ts
│   │   │   ├── gcp.ts
│   │   │   ├── heroes-badges.ts
│   │   │   ├── registry.ts
│   │   │   └── timezones.ts
│   │   ├── data/
│   │   │   ├── course-leave-reasons.ts
│   │   │   ├── english.ts
│   │   │   ├── eventTypes.ts
│   │   │   ├── index.ts
│   │   │   ├── interviews/
│   │   │   │   ├── __tests__/
│   │   │   │   │   └── templateValidator.test.ts
│   │   │   │   ├── angular.ts
│   │   │   │   ├── corejs1.ts
│   │   │   │   ├── corejs2.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── react.ts
│   │   │   │   ├── shortTrackJavaScript.ts
│   │   │   │   ├── shortTrackPerformance.ts
│   │   │   │   ├── shortTrackScreening.ts
│   │   │   │   ├── shortTrackTypeScript.ts
│   │   │   │   ├── technical-screening.tsx
│   │   │   │   ├── templateValidator.ts
│   │   │   │   └── types.ts
│   │   │   ├── skills.ts
│   │   │   ├── taskTypes.ts
│   │   │   └── tshirts.ts
│   │   ├── domain/
│   │   │   ├── course.test.ts
│   │   │   ├── course.ts
│   │   │   ├── interview.test.ts
│   │   │   ├── interview.tsx
│   │   │   ├── user.test.tsx
│   │   │   └── user.ts
│   │   ├── hooks/
│   │   │   └── index.ts
│   │   ├── index.d.ts
│   │   ├── modules/
│   │   │   ├── AutoTest/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AttemptsAnswers/
│   │   │   │   │   │   └── AttemptsAnswers.tsx
│   │   │   │   │   ├── AutoTestTaskCard/
│   │   │   │   │   │   └── AutoTestTaskCard.tsx
│   │   │   │   │   ├── Coding/
│   │   │   │   │   │   ├── Coding.test.tsx
│   │   │   │   │   │   └── Coding.tsx
│   │   │   │   │   ├── Exercise/
│   │   │   │   │   │   └── Exercise.tsx
│   │   │   │   │   ├── JupyterNotebook/
│   │   │   │   │   │   └── JupyterNotebook.tsx
│   │   │   │   │   ├── Question/
│   │   │   │   │   │   ├── Question.module.css
│   │   │   │   │   │   └── Question.tsx
│   │   │   │   │   ├── SelfEducation/
│   │   │   │   │   │   ├── SelfEducation.module.css
│   │   │   │   │   │   ├── SelfEducation.test.tsx
│   │   │   │   │   │   └── SelfEducation.tsx
│   │   │   │   │   ├── StatusTabs/
│   │   │   │   │   │   ├── StatusTabs.test.tsx
│   │   │   │   │   │   ├── StatusTabs.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── TaskCard/
│   │   │   │   │   │   ├── TaskCard.test.tsx
│   │   │   │   │   │   └── TaskCard.tsx
│   │   │   │   │   ├── TaskCardColumn/
│   │   │   │   │   │   └── TaskCardColumn.tsx
│   │   │   │   │   ├── TaskDeadlineDate/
│   │   │   │   │   │   ├── TaskDeadlineDate.test.tsx
│   │   │   │   │   │   └── TaskDeadlineDate.tsx
│   │   │   │   │   ├── TaskDescription/
│   │   │   │   │   │   └── TaskDescription.tsx
│   │   │   │   │   ├── VerificationInformation/
│   │   │   │   │   │   ├── VerificationInformation.test.tsx
│   │   │   │   │   │   └── VerificationInformation.tsx
│   │   │   │   │   ├── VerificationsTable/
│   │   │   │   │   │   ├── VerificationsTable.test.tsx
│   │   │   │   │   │   ├── VerificationsTable.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useAttemptsMessage/
│   │   │   │   │   │   ├── useAttemptsMessage.test.ts
│   │   │   │   │   │   └── useAttemptsMessage.ts
│   │   │   │   │   ├── useCourseTaskSubmit/
│   │   │   │   │   │   ├── useCourseTaskSubmit.test.ts
│   │   │   │   │   │   └── useCourseTaskSubmit.ts
│   │   │   │   │   ├── useCourseTaskVerifications/
│   │   │   │   │   │   └── useCourseTaskVerifications.ts
│   │   │   │   │   └── useVerificationsAnswers/
│   │   │   │   │       └── useVerificationsAnswers.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── AutoTests/
│   │   │   │   │   │   └── AutoTests.tsx
│   │   │   │   │   ├── Task/
│   │   │   │   │   │   └── Task.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       └── map.ts
│   │   │   ├── Contributor/
│   │   │   │   ├── components/
│   │   │   │   │   ├── ContributorModal.tsx
│   │   │   │   │   └── ContributorsTable.tsx
│   │   │   │   └── pages/
│   │   │   │       └── ContributorPage.tsx
│   │   │   ├── Course/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CourseNoAccess.tsx
│   │   │   │   │   └── NoSubmissionAvailable/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── contexts/
│   │   │   │   │   ├── ActiveCourseContext.tsx
│   │   │   │   │   ├── SessionContext.test.tsx
│   │   │   │   │   ├── SessionContext.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   └── pages/
│   │   │   │       ├── CouseNoAccess/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── Student/
│   │   │   │           └── CrossCheckSubmit/
│   │   │   │               └── index.tsx
│   │   │   ├── CourseManagement/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CertificateCriteriaModal/
│   │   │   │   │   │   ├── CertificateCriteriaModal.test.tsx
│   │   │   │   │   │   └── CertificateCriteriaModal.tsx
│   │   │   │   │   ├── CourseEventModal/
│   │   │   │   │   │   ├── formState.ts
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CourseModal/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CourseTaskModal/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CoursesListModal/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ExpelCriteriaModal/
│   │   │   │   │   │   ├── ExpelCriteriaModal.test.tsx
│   │   │   │   │   │   └── ExpelCriteriaModal.tsx
│   │   │   │   │   ├── ExpelledStudentsStats.tsx
│   │   │   │   │   ├── SelectCourseTasks/
│   │   │   │   │   │   ├── SelectCourseTasks.test.tsx
│   │   │   │   │   │   └── SelectCourseTasks.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   └── hooks/
│   │   │   │       └── useExpelledStats.ts
│   │   │   ├── CourseStatistics/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CountriesChart/
│   │   │   │   │   │   └── CountriesChart.tsx
│   │   │   │   │   ├── DonutChart/
│   │   │   │   │   │   └── DonutChart.tsx
│   │   │   │   │   ├── EpamMentorsStatsCard/
│   │   │   │   │   │   ├── EpamMentorsStatsCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── LiquidChart/
│   │   │   │   │   │   └── LiquidChart.tsx
│   │   │   │   │   ├── MentorsCountriesCard/
│   │   │   │   │   │   ├── MentorsCountriesCard.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StatCards/
│   │   │   │   │   │   ├── StatCards.module.css
│   │   │   │   │   │   ├── StatCards.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StatScopeSelector/
│   │   │   │   │   │   ├── StatScopeSelector.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StudentsCertificatesCountriesCard/
│   │   │   │   │   │   ├── StudentsCertificatesCountriesCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsCountriesCard/
│   │   │   │   │   │   ├── StudentsCountriesCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsEligibleForCertificationCard/
│   │   │   │   │   │   ├── StudentsEligibleForCertificationCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsStatsCard/
│   │   │   │   │   │   ├── StudentsStatsCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsWithCertificateCard/
│   │   │   │   │   │   ├── StudentsWithCertificateCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsWithMentorsCard/
│   │   │   │   │   │   ├── StudentsWithMentorsCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── TaskPerformanceCard/
│   │   │   │   │       ├── TaskPerformanceCard.tsx
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── data.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useCourseStats.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── pages/
│   │   │   │       └── CourseStatistics.tsx
│   │   │   ├── CrossCheck/
│   │   │   │   ├── AddCriteriaForCrossCheck.tsx
│   │   │   │   ├── CriteriaActions.tsx
│   │   │   │   ├── CriteriaTypeSelect.tsx
│   │   │   │   ├── DeleteAllCrossCheckCriteriaButton.tsx
│   │   │   │   ├── EditableCellForCrossCheck.tsx
│   │   │   │   ├── EditableCriteriaInput.tsx
│   │   │   │   ├── EditableTableForCrossCheck.tsx
│   │   │   │   ├── ExportJSONButton.tsx
│   │   │   │   ├── UploadCriteriaJSON.tsx
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── AddCriteriaForCrossCheck.test.tsx
│   │   │   │   │   ├── ExportJSONButton.test.tsx
│   │   │   │   │   ├── UploadCriteriaJSON.test.tsx
│   │   │   │   │   └── __snapshots__/
│   │   │   │   │       └── AddCriteriaForCrossCheck.test.tsx.snap
│   │   │   │   ├── components/
│   │   │   │   │   ├── CriteriaForm.tsx
│   │   │   │   │   ├── CrossCheckAssignmentLink.tsx
│   │   │   │   │   ├── CrossCheckCriteriaForm.module.css
│   │   │   │   │   ├── CrossCheckCriteriaForm.tsx
│   │   │   │   │   ├── CrossCheckHistory.tsx
│   │   │   │   │   ├── DragHandle.module.css
│   │   │   │   │   ├── DragHandle.tsx
│   │   │   │   │   ├── DragSortTable.tsx
│   │   │   │   │   ├── SolutionReview/
│   │   │   │   │   │   ├── Message/
│   │   │   │   │   │   │   ├── Message.test.tsx
│   │   │   │   │   │   │   ├── Message.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── MessageSendingPanel/
│   │   │   │   │   │   │   ├── MessageSendingPanel.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── SolutionReview.module.css
│   │   │   │   │   │   ├── SolutionReview.tsx
│   │   │   │   │   │   ├── UserAvatar/
│   │   │   │   │   │   │   ├── UserAvatar.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── Username/
│   │   │   │   │   │   │   ├── Username.test.tsx
│   │   │   │   │   │   │   ├── Username.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── helpers.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── SolutionReviewSettingsPanel/
│   │   │   │   │   │   ├── SolutionReviewSettingsPanel.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── SubmittedStatus.tsx
│   │   │   │   │   └── criteria/
│   │   │   │   │       ├── CrossCheckCriteria.tsx
│   │   │   │   │       ├── CrossCheckCriteriaModal.tsx
│   │   │   │   │       ├── PenaltyCriteria.tsx
│   │   │   │   │       ├── SubtaskCriteria.tsx
│   │   │   │   │       └── TitleCriteria.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useSolutionReviewSettings.ts
│   │   │   │   ├── index.tsx
│   │   │   │   └── utils/
│   │   │   │       ├── addKeyAndIndex.tsx
│   │   │   │       ├── arrayMoveImmutable.tsx
│   │   │   │       └── getCriteriaStatusColor.ts
│   │   │   ├── CrossCheckPairs/
│   │   │   │   ├── components/
│   │   │   │   │   ├── BadReview/
│   │   │   │   │   │   ├── BadReviewControllers.tsx
│   │   │   │   │   │   └── BadReviewTable.tsx
│   │   │   │   │   └── CrossCheckPairsTable/
│   │   │   │   │       ├── CrossCheckPairsTable.module.css
│   │   │   │   │       └── CrossCheckPairsTable.tsx
│   │   │   │   ├── data/
│   │   │   │   │   └── getCrossCheckPairsColumns.tsx
│   │   │   │   └── pages/
│   │   │   │       └── CrossCheckPairs/
│   │   │   │           ├── CrossCheckPairs.tsx
│   │   │   │           └── index.ts
│   │   │   ├── Discipline/
│   │   │   │   ├── components/
│   │   │   │   │   ├── DisciplineModal.tsx
│   │   │   │   │   └── DisciplineTable.tsx
│   │   │   │   └── pages/
│   │   │   │       └── DisciplinePage.tsx
│   │   │   ├── DiscordAdmin/
│   │   │   │   ├── components/
│   │   │   │   │   ├── DiscordServersModal.tsx
│   │   │   │   │   └── DiscordServersTable.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useDiscordServers.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── pages/
│   │   │   │       └── DiscordAdminPage/
│   │   │   │           ├── DiscordAdminPage.tsx
│   │   │   │           └── index.ts
│   │   │   ├── EventsAdmin/
│   │   │   │   ├── components/
│   │   │   │   │   ├── EventsModal.tsx
│   │   │   │   │   └── EventsTable.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useEvents.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── pages/
│   │   │   │       └── EventsAdminPage/
│   │   │   │           ├── EventsAdminPage.tsx
│   │   │   │           └── index.ts
│   │   │   ├── Feedback/
│   │   │   │   ├── components/
│   │   │   │   │   └── FeedbackForm.tsx
│   │   │   │   └── data/
│   │   │   │       └── softSkills.ts
│   │   │   ├── Home/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CourseLinks/
│   │   │   │   │   │   ├── CourseLinks.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CourseSelector/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── HomeSummary/
│   │   │   │   │   │   ├── HomeSummary.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── NoCourse/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── RegistryBanner/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── SystemAlerts/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── data/
│   │   │   │   │   ├── links.tsx
│   │   │   │   │   └── loadHomeData.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useActiveCourse.test.tsx
│   │   │   │   │   ├── useActiveCourse.tsx
│   │   │   │   │   └── useStudentSummary.tsx
│   │   │   │   └── pages/
│   │   │   │       └── HomePage/
│   │   │   │           └── index.tsx
│   │   │   ├── Interview/
│   │   │   │   └── Student/
│   │   │   │       ├── components/
│   │   │   │       │   ├── AlertDescription.module.css
│   │   │   │       │   ├── AlertDescription.tsx
│   │   │   │       │   ├── ExtraInfo.tsx
│   │   │   │       │   ├── InterviewCard.tsx
│   │   │   │       │   ├── InterviewDescription.tsx
│   │   │   │       │   ├── NoInterviewsAlert.tsx
│   │   │   │       │   └── StatusLabel.tsx
│   │   │   │       ├── data/
│   │   │   │       │   └── getInterviewCardDetails.tsx
│   │   │   │       └── index.ts
│   │   │   ├── Interviews/
│   │   │   │   ├── data/
│   │   │   │   │   ├── getInterviewData.ts
│   │   │   │   │   ├── getStageInterviewData.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── pages/
│   │   │   │       ├── InterviewFeedback/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── StageInterviewFeedback/
│   │   │   │           ├── CustomQuestion.tsx
│   │   │   │           ├── FormItem.tsx
│   │   │   │           ├── NestedRadio.tsx
│   │   │   │           ├── QuestionCard.tsx
│   │   │   │           ├── QuestionList.tsx
│   │   │   │           ├── QuestionsPicker.tsx
│   │   │   │           ├── StageInterviewFeedback.tsx
│   │   │   │           ├── StepContext.tsx
│   │   │   │           ├── StepForm.tsx
│   │   │   │           ├── Steps.tsx
│   │   │   │           ├── StepsContent.tsx
│   │   │   │           ├── StudentInfo.tsx
│   │   │   │           ├── SubHeader.module.css
│   │   │   │           ├── SubHeader.tsx
│   │   │   │           ├── feedbackTemplateHandler.test.ts
│   │   │   │           ├── feedbackTemplateHandler.ts
│   │   │   │           └── index.ts
│   │   │   ├── Mentor/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Instructions/
│   │   │   │   │   │   ├── Instructions.tsx
│   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── MentorDashboard/
│   │   │   │   │   │   ├── MentorDashboard.test.tsx
│   │   │   │   │   │   ├── MentorDashboard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Notification/
│   │   │   │   │   │   ├── Notification.test.tsx
│   │   │   │   │   │   ├── Notification.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ReviewRandomTask/
│   │   │   │   │   │   ├── ReviewRandomTask.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── SubmitReviewModal/
│   │   │   │   │   │   ├── SubmitReviewModal.test.tsx
│   │   │   │   │   │   ├── SubmitReviewModal.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── TaskSolutionsTable/
│   │   │   │   │   │   ├── TaskSolutionsTable.test.tsx
│   │   │   │   │   │   ├── TaskSolutionsTable.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── TaskStatusTabs/
│   │   │   │   │   │   ├── TaskStatusTabs.test.tsx
│   │   │   │   │   │   ├── TaskStatusTabs.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── data/
│   │   │   │   │   └── softSkills.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useMentorDashboard.tsx
│   │   │   │   │   └── useMentorStudents.tsx
│   │   │   │   └── pages/
│   │   │   │       ├── InterviewWaitingList/
│   │   │   │       │   └── index.tsx
│   │   │   │       ├── Interviews/
│   │   │   │       │   ├── components/
│   │   │   │       │   │   ├── InterviewCard.module.css
│   │   │   │       │   │   ├── InterviewCard.tsx
│   │   │   │       │   │   ├── InterviewDetails.tsx
│   │   │   │       │   │   ├── InterviewsList.module.css
│   │   │   │       │   │   ├── InterviewsList.tsx
│   │   │   │       │   │   ├── InterviewsSummary.tsx
│   │   │   │       │   │   ├── MentorPreferencesModal.tsx
│   │   │   │       │   │   ├── RegistrationNotice.test.tsx
│   │   │   │       │   │   ├── RegistrationNoticeAlert.module.css
│   │   │   │       │   │   ├── RegistrationNoticeAlert.tsx
│   │   │   │       │   │   ├── SelectMentorModal.tsx
│   │   │   │       │   │   ├── StudentInterview.module.css
│   │   │   │       │   │   ├── StudentInterview.tsx
│   │   │   │       │   │   ├── WaitListAlert.module.css
│   │   │   │       │   │   └── WaitListAlert.tsx
│   │   │   │       │   ├── hooks/
│   │   │   │       │   │   └── useAlert.ts
│   │   │   │       │   ├── index.module.css
│   │   │   │       │   └── index.tsx
│   │   │   │       ├── StudentFeedback/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── Students/
│   │   │   │           └── index.tsx
│   │   │   ├── MentorRegistry/
│   │   │   │   ├── components/
│   │   │   │   │   ├── InviteMentorsModal.tsx
│   │   │   │   │   ├── MentorRegistryDeleteModal.tsx
│   │   │   │   │   ├── MentorRegistryResendModal.tsx
│   │   │   │   │   ├── MentorRegistryTable.tsx
│   │   │   │   │   ├── MentorRegistryTableContainer.module.css
│   │   │   │   │   └── MentorRegistryTableContainer.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   └── index.ts
│   │   │   ├── MentorTasksReview/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AssignReviewerModal/
│   │   │   │   │   │   ├── AssignReviewerModal.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── ReviewsTable/
│   │   │   │   │       ├── index.tsx
│   │   │   │   │       └── renderers.tsx
│   │   │   │   └── pages/
│   │   │   │       ├── MentorTasksReview.constants.ts
│   │   │   │       └── MentorTasksReview.tsx
│   │   │   ├── MentorsHallOfFame/
│   │   │   │   ├── components/
│   │   │   │   │   └── MentorCard/
│   │   │   │   │       ├── MentorCard.module.css
│   │   │   │   │       ├── MentorCard.test.tsx
│   │   │   │   │       └── MentorCard.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── MentorsHallOfFamePage.test.tsx
│   │   │   │   │   └── MentorsHallOfFamePage.tsx
│   │   │   │   ├── services/
│   │   │   │   │   ├── mentors-hall-of-fame.service.test.ts
│   │   │   │   │   └── mentors-hall-of-fame.service.ts
│   │   │   │   └── types.ts
│   │   │   ├── NotAccess/
│   │   │   │   ├── NotAccess.tsx
│   │   │   │   └── index.ts
│   │   │   ├── Notifications/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Consents.tsx
│   │   │   │   │   ├── NotificationSettingsModal.module.css
│   │   │   │   │   ├── NotificationSettingsModal.tsx
│   │   │   │   │   ├── NotificationSettingsTable.tsx
│   │   │   │   │   ├── NotificationsUserSettingsTable.module.css
│   │   │   │   │   └── NotificationsUserSettingsTable.tsx
│   │   │   │   ├── pages/
│   │   │   │   │   ├── AdminNotificationsPage/
│   │   │   │   │   │   ├── AdminNotificationsSettingsPage.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ConnectionConfirmedPage.tsx
│   │   │   │   │   └── UserNotificationsSettingsPage.tsx
│   │   │   │   └── services/
│   │   │   │       └── notifications.ts
│   │   │   ├── Opportunities/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AvatarCv/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── EditCv/
│   │   │   │   │   │   ├── ContactsForm/
│   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── GeneralInfoForm/
│   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── VisibleCoursesForm/
│   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── form-validation.ts
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── EditViewCv/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ExpirationTooltip/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Link/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── NameTitle/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── NoConsentView/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── PublicLink/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentStatus/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── ViewCv/
│   │   │   │   │       ├── AboutSection/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── ActionButtons/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── BaseSection/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── ContactsSection/
│   │   │   │   │       │   ├── ContactsList/
│   │   │   │   │       │   │   ├── index.module.css
│   │   │   │   │       │   │   ├── index.test.tsx
│   │   │   │   │       │   │   └── index.tsx
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── CoursesSection/
│   │   │   │   │       │   ├── CoursesSection.module.css
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── DataTextValue/
│   │   │   │   │       │   ├── DataTextValue.module.css
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── FeedbackSection/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── GratitudeSection/
│   │   │   │   │       │   ├── GratitudeList/
│   │   │   │   │       │   │   ├── index.test.tsx
│   │   │   │   │       │   │   └── index.tsx
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── PersonalSection/
│   │   │   │   │       │   ├── PersonalSection.module.css
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── index.test.tsx
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── data/
│   │   │   │   │   ├── __snapshots__/
│   │   │   │   │   │   └── getPersonalToRender.test.tsx.snap
│   │   │   │   │   ├── getContactsToRender.test.tsx
│   │   │   │   │   ├── getContactsToRender.ts
│   │   │   │   │   ├── getPersonalToRender.test.tsx
│   │   │   │   │   └── getPersonalToRender.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useExpiration.test.tsx
│   │   │   │   │   ├── useExpiration.ts
│   │   │   │   │   ├── useResumeData.test.tsx
│   │   │   │   │   ├── useResumeData.tsx
│   │   │   │   │   ├── useViewData.test.tsx
│   │   │   │   │   └── useViewData.tsx
│   │   │   │   ├── models.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── EditPage/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── PublicPage/
│   │   │   │   │       ├── getServerSideProps.ts
│   │   │   │   │       └── index.tsx
│   │   │   │   └── transformers/
│   │   │   │       ├── index.ts
│   │   │   │       ├── splitDataForForms.test.ts
│   │   │   │       ├── splitDataForForms.ts
│   │   │   │       ├── transformFieldsData.test.ts
│   │   │   │       ├── transformFieldsData.ts
│   │   │   │       ├── transformInitialCvData.test.ts
│   │   │   │       └── transformInitialCvData.ts
│   │   │   ├── Profile/
│   │   │   │   └── components/
│   │   │   │       └── MentorEndorsement/
│   │   │   │           ├── MentorEndorsement.tsx
│   │   │   │           └── index.tsx
│   │   │   ├── Prompts/
│   │   │   │   ├── components/
│   │   │   │   │   ├── PromptModal.tsx
│   │   │   │   │   └── PromptTable.tsx
│   │   │   │   └── pages/
│   │   │   │       └── PromptPage.tsx
│   │   │   ├── Registry/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Cards/
│   │   │   │   │   │   ├── AdditionalInfo/
│   │   │   │   │   │   │   ├── AdditionalInfo.test.tsx
│   │   │   │   │   │   │   └── AdditionalInfo.tsx
│   │   │   │   │   │   ├── ContactInfo/
│   │   │   │   │   │   │   ├── ContactInfo.test.tsx
│   │   │   │   │   │   │   └── ContactInfo.tsx
│   │   │   │   │   │   ├── CourseDetails/
│   │   │   │   │   │   │   ├── CourseDetails.test.tsx
│   │   │   │   │   │   │   └── CourseDetails.tsx
│   │   │   │   │   │   ├── Disciplines/
│   │   │   │   │   │   │   ├── Disciplines.test.tsx
│   │   │   │   │   │   │   └── Disciplines.tsx
│   │   │   │   │   │   ├── PersonalInfo/
│   │   │   │   │   │   │   ├── PersonalInfo.test.tsx
│   │   │   │   │   │   │   └── PersonalInfo.tsx
│   │   │   │   │   │   └── Preferences/
│   │   │   │   │   │       ├── Preferences.test.tsx
│   │   │   │   │   │       └── Preferences.tsx
│   │   │   │   │   ├── CourseCertificateAlert/
│   │   │   │   │   │   └── CourseCertificateAlert.tsx
│   │   │   │   │   ├── CourseLabel/
│   │   │   │   │   │   └── CourseLabel.tsx
│   │   │   │   │   ├── DataProcessingCheckbox/
│   │   │   │   │   │   ├── DataProcessingCheckbox.test.tsx
│   │   │   │   │   │   └── DataProcessingCheckbox.tsx
│   │   │   │   │   ├── Footer/
│   │   │   │   │   │   └── Footer.tsx
│   │   │   │   │   ├── FormButtons/
│   │   │   │   │   │   ├── FormButtons.test.tsx
│   │   │   │   │   │   └── FormButtons.tsx
│   │   │   │   │   ├── FormCard/
│   │   │   │   │   │   └── FormCard.tsx
│   │   │   │   │   ├── FormSections/
│   │   │   │   │   │   ├── DoneSection/
│   │   │   │   │   │   │   ├── DoneSection.test.tsx
│   │   │   │   │   │   │   └── DoneSection.tsx
│   │   │   │   │   │   ├── GeneralSection/
│   │   │   │   │   │   │   ├── GeneralSection.test.tsx
│   │   │   │   │   │   │   └── GeneralSection.tsx
│   │   │   │   │   │   └── MentorshipSection/
│   │   │   │   │   │       ├── MentorshipSection.test.tsx
│   │   │   │   │   │       └── MentorshipSection.tsx
│   │   │   │   │   ├── Header/
│   │   │   │   │   │   └── Header.tsx
│   │   │   │   │   ├── LanguagesMentoring/
│   │   │   │   │   │   ├── LanguagesMentoring.test.tsx
│   │   │   │   │   │   └── LanguagesMentoring.tsx
│   │   │   │   │   ├── NoCourses/
│   │   │   │   │   │   └── NoCourses.tsx
│   │   │   │   │   ├── RegistrationForm/
│   │   │   │   │   │   ├── RegistrationForm.test.tsx
│   │   │   │   │   │   └── RegistrationForm.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── constants/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useFormLayout/
│   │   │   │   │   │   └── useFormLayout.ts
│   │   │   │   │   ├── useMentorData/
│   │   │   │   │   │   └── useMentorData.tsx
│   │   │   │   │   └── useStudentData/
│   │   │   │   │       └── useStudentData.tsx
│   │   │   │   └── pages/
│   │   │   │       ├── Mentor/
│   │   │   │       │   └── Mentor.tsx
│   │   │   │       ├── Student/
│   │   │   │       │   └── Student.tsx
│   │   │   │       └── index.ts
│   │   │   ├── Schedule/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AdditionalActions/
│   │   │   │   │   │   ├── AdditionalActions.test.tsx
│   │   │   │   │   │   ├── AdditionalActions.tsx
│   │   │   │   │   │   ├── helpers.ts
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── EventDetails/
│   │   │   │   │   │   ├── EventDetails.module.css
│   │   │   │   │   │   ├── EventDetails.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── FilteredTags/
│   │   │   │   │   │   ├── FilteredTags.test.tsx
│   │   │   │   │   │   ├── FilteredTags.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── MobileItemCard/
│   │   │   │   │   │   ├── MobileItemCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── SettingsDrawer/
│   │   │   │   │   │   ├── ChangeTagColors.tsx
│   │   │   │   │   │   ├── SettingsDrawer.tsx
│   │   │   │   │   │   ├── ShowTableColumns.tsx
│   │   │   │   │   │   ├── TimeZone.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── SettingsPanel/
│   │   │   │   │   │   ├── SettingsPanel.test.tsx
│   │   │   │   │   │   ├── SettingsPanel.tsx
│   │   │   │   │   │   ├── helpers.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StatusTabs/
│   │   │   │   │   │   ├── StatusTabs.test.tsx
│   │   │   │   │   │   ├── StatusTabs.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── TableView/
│   │   │   │   │       ├── TableView.test.tsx
│   │   │   │   │       ├── TableView.tsx
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── renderers.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   └── useScheduleSettings.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── pages/
│   │   │   │   │   └── SchedulePage/
│   │   │   │   │       └── index.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── Score/
│   │   │   │   ├── components/
│   │   │   │   │   ├── ExportCsvButton/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ScoreTable/
│   │   │   │   │   │   ├── ScoreTableTabs.tsx
│   │   │   │   │   │   ├── Summary.tsx
│   │   │   │   │   │   ├── index.module.css
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── SettingsDrawer/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── data/
│   │   │   │   │   ├── getColumns.tsx
│   │   │   │   │   ├── getExportCsvUrl.ts
│   │   │   │   │   ├── getTaskColumns.tsx
│   │   │   │   │   └── isExportEnabled.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── useScorePaging.tsx
│   │   │   │   └── pages/
│   │   │   │       └── ScorePage/
│   │   │   │           ├── UpdateAlert.module.css
│   │   │   │           ├── UpdateAlert.tsx
│   │   │   │           └── index.tsx
│   │   │   ├── StudentDashboard/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AvailableReviewCard/
│   │   │   │   │   │   ├── AvailableReviewCard.test.tsx
│   │   │   │   │   │   ├── AvailableReviewCard.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── CommonDashboardCard.tsx
│   │   │   │   │   ├── MainStatsCard.tsx
│   │   │   │   │   ├── MentorCard/
│   │   │   │   │   │   ├── MentorCard.test.tsx
│   │   │   │   │   │   ├── MentorCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── MentorInfo/
│   │   │   │   │   │   ├── MentorInfo.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── NextEventCard/
│   │   │   │   │   │   ├── NextEventCard.module.css
│   │   │   │   │   │   ├── NextEventCard.test.tsx
│   │   │   │   │   │   ├── NextEventCard.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── RepositoryCard.tsx
│   │   │   │   │   ├── SubmitTaskSolution/
│   │   │   │   │   │   ├── SubmitTaskSolution.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── TasksChart.tsx
│   │   │   │   │   ├── TasksStatsCard.tsx
│   │   │   │   │   ├── TasksStatsModal.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useDashboardData.ts
│   │   │   │   │   ├── useSubmitTaskSolution.test.ts
│   │   │   │   │   └── useSubmitTaskSolution.ts
│   │   │   │   └── index.ts
│   │   │   ├── Students/
│   │   │   │   ├── Pages/
│   │   │   │   │   └── Students.tsx
│   │   │   │   └── components/
│   │   │   │       ├── CourseItem/
│   │   │   │       │   └── index.tsx
│   │   │   │       ├── StudentInfo/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── StudentsTable/
│   │   │   │           ├── index.tsx
│   │   │   │           └── renderers.tsx
│   │   │   ├── Tasks/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CrossCheckTaskCriteriaPanel/
│   │   │   │   │   │   ├── CrossCheckTaskCriteriaPanel.test.tsx
│   │   │   │   │   │   └── CrossCheckTaskCriteriaPanel.tsx
│   │   │   │   │   ├── GitHubPanel/
│   │   │   │   │   │   ├── GitHubPanel.test.tsx
│   │   │   │   │   │   └── GitHubPanel.tsx
│   │   │   │   │   ├── JsonAttributesPanel/
│   │   │   │   │   │   ├── JsonAttributesPanel.test.tsx
│   │   │   │   │   │   └── JsonAttributesPanel.tsx
│   │   │   │   │   ├── TaskModal/
│   │   │   │   │   │   ├── TaskModal.test.tsx
│   │   │   │   │   │   └── TaskModal.tsx
│   │   │   │   │   ├── TaskSettings/
│   │   │   │   │   │   ├── TaskSettings.test.tsx
│   │   │   │   │   │   └── TaskSettings.tsx
│   │   │   │   │   ├── TasksTable/
│   │   │   │   │   │   ├── TasksTable.test.tsx
│   │   │   │   │   │   └── TasksTable.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── TasksPage/
│   │   │   │   │   │   └── TasksPage.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       └── test-utils.ts
│   │   │   ├── TeamDistribution/
│   │   │   │   ├── components/
│   │   │   │   │   ├── SubmitScoreModal/
│   │   │   │   │   │   ├── SubmitScoreModal.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── TeamDistributionCard/
│   │   │   │   │   │   ├── Actions.test.tsx
│   │   │   │   │   │   ├── Actions.tsx
│   │   │   │   │   │   ├── CardTitle.test.tsx
│   │   │   │   │   │   ├── CardTitle.tsx
│   │   │   │   │   │   ├── DistributionPeriod.tsx
│   │   │   │   │   │   ├── TeamDistributionCard.test.tsx
│   │   │   │   │   │   ├── TeamDistributionCard.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── TeamDistributionModal/
│   │   │   │   │   │   ├── TeamDistributionModal.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── WelcomeCard/
│   │   │   │   │       ├── WelcomeCard.test.tsx
│   │   │   │   │       ├── WelcomeCard.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useSubmitTeamScore.test.tsx
│   │   │   │   │   └── useSubmitTeamScore.tsx
│   │   │   │   └── pages/
│   │   │   │       └── TeamDistributions/
│   │   │   │           ├── TeamDistributions.tsx
│   │   │   │           └── index.tsx
│   │   │   ├── Teams/
│   │   │   │   ├── Pages/
│   │   │   │   │   └── Teams.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── JoinTeamModal/
│   │   │   │   │   │   └── JoinTeamModal.tsx
│   │   │   │   │   ├── MyTeamSection/
│   │   │   │   │   │   └── MyTeamSection.tsx
│   │   │   │   │   ├── StudentsTable/
│   │   │   │   │   │   ├── StudentsTable.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── StudentsWithoutTeamSection/
│   │   │   │   │   │   └── StudentsWithoutTeamSection.tsx
│   │   │   │   │   ├── TeamModal/
│   │   │   │   │   │   ├── TeamModal.test.tsx
│   │   │   │   │   │   └── TeamModal.tsx
│   │   │   │   │   ├── TeamsHeader/
│   │   │   │   │   │   ├── ActionCard.tsx
│   │   │   │   │   │   └── TeamsHeader.tsx
│   │   │   │   │   ├── TeamsSection/
│   │   │   │   │   │   ├── TeamsSection.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useDistribution/
│   │   │   │   │       ├── useDistribution.test.ts
│   │   │   │   │       └── useDistribution.ts
│   │   │   │   └── index.tsx
│   │   │   ├── UserGroupsAdmin/
│   │   │   │   ├── components/
│   │   │   │   │   ├── UserGroupsModal.tsx
│   │   │   │   │   └── UserGroupsTable.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useUserGroups.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── pages/
│   │   │   │       └── UserGroupsAdminPage/
│   │   │   │           ├── UserGroupsAdminPage.tsx
│   │   │   │           └── index.ts
│   │   │   └── UsersAdmin/
│   │   │       ├── hooks/
│   │   │       │   ├── index.ts
│   │   │       │   └── useUsersSearch.ts
│   │   │       ├── index.ts
│   │   │       └── pages/
│   │   │           └── UsersAdminPage/
│   │   │               ├── UsersAdminPage.tsx
│   │   │               └── index.ts
│   │   ├── pages/
│   │   │   ├── 404.tsx
│   │   │   ├── _app.tsx
│   │   │   ├── _document.tsx
│   │   │   ├── admin/
│   │   │   │   ├── auto-test-task/
│   │   │   │   │   └── [taskId].tsx
│   │   │   │   ├── auto-test.tsx
│   │   │   │   ├── contributors.tsx
│   │   │   │   ├── courses.tsx
│   │   │   │   ├── disciplines.tsx
│   │   │   │   ├── discord-telegram.tsx
│   │   │   │   ├── events.tsx
│   │   │   │   ├── mentor-registry.module.css
│   │   │   │   ├── mentor-registry.tsx
│   │   │   │   ├── notifications.tsx
│   │   │   │   ├── prompts.tsx
│   │   │   │   ├── registrations.tsx
│   │   │   │   ├── students.tsx
│   │   │   │   ├── tasks.tsx
│   │   │   │   ├── user-group.tsx
│   │   │   │   └── users.tsx
│   │   │   ├── applicants/
│   │   │   │   └── index.tsx
│   │   │   ├── course/
│   │   │   │   ├── 403.tsx
│   │   │   │   ├── admin/
│   │   │   │   │   ├── certified-students.tsx
│   │   │   │   │   ├── cross-check-table.tsx
│   │   │   │   │   ├── events.tsx
│   │   │   │   │   ├── interviews.tsx
│   │   │   │   │   ├── mentor-tasks-review.tsx
│   │   │   │   │   ├── mentors.tsx
│   │   │   │   │   ├── reports.tsx
│   │   │   │   │   ├── stage-interviews.tsx
│   │   │   │   │   ├── students.tsx
│   │   │   │   │   ├── tasks.tsx
│   │   │   │   │   └── users.tsx
│   │   │   │   ├── interview/
│   │   │   │   │   └── [type]/
│   │   │   │   │       └── feedback.tsx
│   │   │   │   ├── mentor/
│   │   │   │   │   ├── confirm.tsx
│   │   │   │   │   ├── dashboard.tsx
│   │   │   │   │   ├── expel-student.tsx
│   │   │   │   │   ├── feedback/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── interview-technical-screening.tsx
│   │   │   │   │   ├── interview-wait-list.tsx
│   │   │   │   │   ├── interviews.tsx
│   │   │   │   │   └── students.tsx
│   │   │   │   ├── schedule.tsx
│   │   │   │   ├── score.tsx
│   │   │   │   ├── stats.tsx
│   │   │   │   ├── student/
│   │   │   │   │   ├── auto-test/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── task.tsx
│   │   │   │   │   ├── cross-check-review.tsx
│   │   │   │   │   ├── cross-check-submit.tsx
│   │   │   │   │   ├── dashboard.module.css
│   │   │   │   │   ├── dashboard.tsx
│   │   │   │   │   └── interviews.tsx
│   │   │   │   ├── submit-scores.tsx
│   │   │   │   ├── team-distributions.tsx
│   │   │   │   └── teams.tsx
│   │   │   ├── cv/
│   │   │   │   ├── [uuid].tsx
│   │   │   │   └── edit.tsx
│   │   │   ├── gratitude.tsx
│   │   │   ├── heroes.tsx
│   │   │   ├── index.tsx
│   │   │   ├── login/
│   │   │   │   ├── index.module.css
│   │   │   │   └── index.tsx
│   │   │   ├── mentors-hall-of-fame.tsx
│   │   │   ├── profile/
│   │   │   │   ├── connection-confirmed.tsx
│   │   │   │   ├── index.module.css
│   │   │   │   ├── index.tsx
│   │   │   │   └── notifications.tsx
│   │   │   └── registry/
│   │   │       ├── epamlearningjs.tsx
│   │   │       ├── mentor.tsx
│   │   │       └── student.tsx
│   │   ├── providers/
│   │   │   ├── DevToolsProvider.tsx
│   │   │   ├── MessageProvider.tsx
│   │   │   ├── ThemeProvider.tsx
│   │   │   └── index.ts
│   │   ├── reset.d.ts
│   │   ├── services/
│   │   │   ├── cdn.ts
│   │   │   ├── check.ts
│   │   │   ├── course.ts
│   │   │   ├── courses.ts
│   │   │   ├── features.tsx
│   │   │   ├── files.ts
│   │   │   ├── formatter.ts
│   │   │   ├── gratitude.ts
│   │   │   ├── mentorRegistry.ts
│   │   │   ├── models.ts
│   │   │   ├── reference-data/
│   │   │   │   └── stageInterview.ts
│   │   │   ├── routes.ts
│   │   │   ├── user.ts
│   │   │   ├── validators.test.ts
│   │   │   └── validators.ts
│   │   ├── setupTests.ts
│   │   ├── shared/
│   │   │   ├── components/
│   │   │   │   ├── CommentModal.tsx
│   │   │   │   ├── CopyToClipboardButton.tsx
│   │   │   │   ├── FilteredTags.tsx
│   │   │   │   ├── Forms/
│   │   │   │   │   ├── CommentInput.tsx
│   │   │   │   │   ├── CourseTaskSelect.tsx
│   │   │   │   │   ├── GdprCheckbox.tsx
│   │   │   │   │   ├── Heroes/
│   │   │   │   │   │   ├── index.module.css
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── LocationSelect.tsx
│   │   │   │   │   ├── MarkdownInput.tsx
│   │   │   │   │   ├── ModalForm.tsx
│   │   │   │   │   ├── ModalSubmitForm.test.tsx
│   │   │   │   │   ├── ModalSubmitForm.tsx
│   │   │   │   │   ├── PreparedComment.tsx
│   │   │   │   │   ├── ScoreInput.tsx
│   │   │   │   │   ├── __tests__/
│   │   │   │   │   │   ├── CourseTaskSelect.test.tsx
│   │   │   │   │   │   └── __snapshots__/
│   │   │   │   │   │       └── CourseTaskSelect.test.tsx.snap
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useGoogleMapsPlaces.test.ts
│   │   │   │   │   └── useGoogleMapsPlaces.ts
│   │   │   │   ├── GithubAvatar.tsx
│   │   │   │   ├── GithubUserLink.module.css
│   │   │   │   ├── GithubUserLink.tsx
│   │   │   │   ├── Header.module.css
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── Icons/
│   │   │   │   │   ├── CourseIcon.tsx
│   │   │   │   │   ├── DeadlineIcon.tsx
│   │   │   │   │   ├── DiscordFilled.tsx
│   │   │   │   │   ├── DiscordOutlined.tsx
│   │   │   │   │   ├── GitHubLogoIcon.tsx
│   │   │   │   │   ├── HealthMask.tsx
│   │   │   │   │   ├── LinkedInIcon.tsx
│   │   │   │   │   ├── PublicSvgIcon.tsx
│   │   │   │   │   ├── RSLogoIcon.tsx
│   │   │   │   │   ├── ScoreIcon.tsx
│   │   │   │   │   ├── TelegramIcon.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── LoadingScreen.module.css
│   │   │   │   ├── LoadingScreen.tsx
│   │   │   │   ├── MentorSearch.tsx
│   │   │   │   ├── NonTouchTooltip.tsx
│   │   │   │   ├── PageLayout.tsx
│   │   │   │   ├── PersonSelect.tsx
│   │   │   │   ├── Rating.tsx
│   │   │   │   ├── ScoreCard.module.css
│   │   │   │   ├── ScoreCard.tsx
│   │   │   │   ├── ScoreSelector.module.css
│   │   │   │   ├── ScoreSelector.tsx
│   │   │   │   ├── Sider/
│   │   │   │   │   ├── AdminSider.test.tsx
│   │   │   │   │   ├── AdminSider.tsx
│   │   │   │   │   └── data/
│   │   │   │   │       └── menuItems.tsx
│   │   │   │   ├── SolidarityUkraine.tsx
│   │   │   │   ├── StudentMentorModal.tsx
│   │   │   │   ├── StudentSearch.tsx
│   │   │   │   ├── Table/
│   │   │   │   │   ├── PersonCell.tsx
│   │   │   │   │   ├── columns.tsx
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── renderers.tsx
│   │   │   │   │   └── sorters.ts
│   │   │   │   ├── ThemeSwitch.tsx
│   │   │   │   ├── Timer.tsx
│   │   │   │   ├── TooltipedButton.tsx
│   │   │   │   └── UserSearch.tsx
│   │   │   ├── hooks/
│   │   │   │   ├── useMessage.tsx
│   │   │   │   ├── useModal/
│   │   │   │   │   ├── useModalForm.test.tsx
│   │   │   │   │   └── useModalForm.tsx
│   │   │   │   ├── useTheme.tsx
│   │   │   │   └── useWindowDimensions.ts
│   │   │   └── utils/
│   │   │       ├── onlyDefined.ts
│   │   │       ├── pagination.ts
│   │   │       ├── queryParams-utils.test.ts
│   │   │       ├── queryParams-utils.ts
│   │   │       ├── text-utils.test.ts
│   │   │       └── text-utils.ts
│   │   ├── styles/
│   │   │   └── main.css
│   │   └── utils/
│   │       ├── dynamicWithSkeleton.tsx
│   │       ├── optionalQueryString.ts
│   │       └── profilePageUtils.ts
│   ├── tsconfig.json
│   └── vitest.config.mts
├── common/
│   ├── README.md
│   └── models/
│       ├── index.ts
│       ├── interview.ts
│       ├── profile.ts
│       ├── stage-interview-feedback.ts
│       └── user.ts
├── docker-compose.yml
├── docs/
│   ├── .nojekyll
│   ├── CNAME
│   ├── README.md
│   ├── _sidebar.md
│   ├── code-of-conduct.md
│   ├── index.html
│   └── platform/
│       ├── about.md
│       ├── adding-tests.md
│       ├── choose-kata-languages.md
│       ├── cross-check-flow.md
│       ├── cross-check-scheduling.md
│       ├── cv.md
│       ├── notifications.md
│       ├── pull-request-review-process.md
│       ├── shedule.md
│       ├── tasks.md
│       └── typical-problems.md
├── eslint.config.mjs
├── nestjs/
│   ├── .dockerignore
│   ├── .swcrc
│   ├── Dockerfile
│   ├── Dockerfile.lambda
│   ├── README.md
│   ├── eslint.config.mjs
│   ├── nest-cli.json
│   ├── openapitools.json
│   ├── package.json
│   ├── src/
│   │   ├── activity/
│   │   │   ├── activity.controller.ts
│   │   │   ├── activity.module.ts
│   │   │   └── dto/
│   │   │       ├── activity.dto.ts
│   │   │       ├── create-activity-webhook.dto.ts
│   │   │       └── create-activity.dto.ts
│   │   ├── alerts/
│   │   │   ├── alerts.controller.ts
│   │   │   ├── alerts.module.ts
│   │   │   ├── alerts.service.ts
│   │   │   └── dto/
│   │   │       ├── alert.dto.ts
│   │   │       ├── create-alert.dto.ts
│   │   │       ├── index.ts
│   │   │       └── update-alert.dto.ts
│   │   ├── app.module.ts
│   │   ├── auth/
│   │   │   ├── auth-user.model.spec.ts
│   │   │   ├── auth-user.model.ts
│   │   │   ├── auth.controller.spec.ts
│   │   │   ├── auth.controller.ts
│   │   │   ├── auth.module.ts
│   │   │   ├── auth.service.spec.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── constants.ts
│   │   │   ├── course.guard.ts
│   │   │   ├── default.guard.ts
│   │   │   ├── dto/
│   │   │   │   └── auth-connection.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── role.decorator.ts
│   │   │   ├── role.guard.ts
│   │   │   └── strategies/
│   │   │       ├── basic.strategy.ts
│   │   │       ├── dev.strategy.ts
│   │   │       ├── github.strategy.ts
│   │   │       └── jwt.strategy.ts
│   │   ├── auto-test/
│   │   │   ├── auto-test.controller.ts
│   │   │   ├── auto-test.module.ts
│   │   │   ├── auto-test.service.ts
│   │   │   └── dto/
│   │   │       ├── auto-test-task.dto.ts
│   │   │       ├── basic-auto-test-task.dto.ts
│   │   │       └── task-solution.dto.ts
│   │   ├── certificates/
│   │   │   ├── certificates.controller.ts
│   │   │   ├── certificates.module.ts
│   │   │   ├── certificates.service.ts
│   │   │   └── dto/
│   │   │       ├── certificate-metadata.dto.ts
│   │   │       └── save-certificate-dto.ts
│   │   ├── cloud-api/
│   │   │   ├── cloud-api.module.ts
│   │   │   └── cloud-api.service.ts
│   │   ├── config/
│   │   │   ├── config.module.ts
│   │   │   ├── config.service.ts
│   │   │   └── index.ts
│   │   ├── constants.ts
│   │   ├── contributors/
│   │   │   ├── contributors.controller.ts
│   │   │   ├── contributors.module.ts
│   │   │   ├── contributors.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── contributor.dto.ts
│   │   │   │   ├── create-contributor.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── update-contributor.dto.ts
│   │   │   └── index.ts
│   │   ├── core/
│   │   │   ├── core.module.ts
│   │   │   ├── decorators/
│   │   │   │   ├── index.ts
│   │   │   │   └── student-id.decorator.ts
│   │   │   ├── dto/
│   │   │   │   ├── id-name.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── pagination.dto.ts
│   │   │   │   └── person.dto.ts
│   │   │   ├── filters/
│   │   │   │   ├── entity-not-found.filter.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── sentry.filter.ts
│   │   │   ├── jwt/
│   │   │   │   └── jwt.service.ts
│   │   │   ├── middlewares/
│   │   │   │   ├── index.ts
│   │   │   │   ├── logger.middleware.ts
│   │   │   │   └── no-cache.middleware.ts
│   │   │   ├── paginate/
│   │   │   │   ├── dto/
│   │   │   │   │   └── Paginate.dto.ts
│   │   │   │   ├── index.test.ts
│   │   │   │   └── index.ts
│   │   │   ├── pino.ts
│   │   │   ├── subscribers/
│   │   │   │   ├── base-subscriber.ts
│   │   │   │   ├── course-event.subscriber.ts
│   │   │   │   └── course-task.subscriber.ts
│   │   │   ├── templates/
│   │   │   │   └── index.ts
│   │   │   └── validation/
│   │   │       ├── index.ts
│   │   │       ├── validation.exception.ts
│   │   │       └── validation.filter.ts
│   │   ├── courses/
│   │   │   ├── course-access.service.ts
│   │   │   ├── course-events/
│   │   │   │   ├── course-events.controller.ts
│   │   │   │   ├── course-events.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-event.dto.ts
│   │   │   │   │   ├── create-course-event.dto.ts
│   │   │   │   │   └── update-course-event.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-mentors/
│   │   │   │   ├── course-mentors.controller.ts
│   │   │   │   ├── course-mentors.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── mentor-details.dto.ts
│   │   │   │   │   └── search-mentor.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-schedule/
│   │   │   │   ├── course-icalendar.controller.ts
│   │   │   │   ├── course-icalendar.service.ts
│   │   │   │   ├── course-schedule.controller.ts
│   │   │   │   ├── course-schedule.service.spec.ts
│   │   │   │   ├── course-schedule.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-copy-from.dto.ts
│   │   │   │   │   ├── course-schedule-hash.dto.ts
│   │   │   │   │   ├── course-schedule-item.dto.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-students/
│   │   │   │   ├── course-students.controller.ts
│   │   │   │   ├── course-students.service.ts
│   │   │   │   └── dto/
│   │   │   │       ├── mentor-student-summary.dto.ts
│   │   │   │       ├── result.dto.ts
│   │   │   │       ├── student-status.dto.ts
│   │   │   │       └── student-summary.dto.ts
│   │   │   ├── course-tasks/
│   │   │   │   ├── course-tasks.controller.ts
│   │   │   │   ├── course-tasks.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-task-detailed.dto.ts
│   │   │   │   │   ├── course-task.dto.ts
│   │   │   │   │   ├── create-course-task.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── update-course-task.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-users/
│   │   │   │   ├── course-users.controller.spec.ts
│   │   │   │   ├── course-users.controller.ts
│   │   │   │   ├── course-users.service.spec.ts
│   │   │   │   ├── course-users.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-roles.dto.ts
│   │   │   │   │   ├── course-user.dto.ts
│   │   │   │   │   └── update-user.dto.ts
│   │   │   │   └── types.ts
│   │   │   ├── courses.controller.ts
│   │   │   ├── courses.module.ts
│   │   │   ├── courses.service.ts
│   │   │   ├── cross-checks/
│   │   │   │   ├── course-cross-checks.controller.ts
│   │   │   │   ├── course-cross-checks.service.spec.ts
│   │   │   │   ├── course-cross-checks.service.ts
│   │   │   │   ├── cross-check-feedback.guard.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── available-review-stats.dto.ts
│   │   │   │   │   ├── check-tasks-pairs.dto.ts
│   │   │   │   │   ├── cross-check-criteria-data.dto.ts
│   │   │   │   │   ├── cross-check-feedback.dto.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   ├── dto/
│   │   │   │   ├── course.dto.ts
│   │   │   │   ├── create-course.dto.ts
│   │   │   │   ├── export-course.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── leave-course.dto.ts
│   │   │   │   ├── update-course.dto.ts
│   │   │   │   └── used-course.dto.ts
│   │   │   ├── expelled-stats.service.test.ts
│   │   │   ├── expelled-stats.service.ts
│   │   │   ├── index.ts
│   │   │   ├── interviews/
│   │   │   │   ├── cross-mentor-distribution.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── available-student.dto.ts
│   │   │   │   │   ├── get-interview-feedback.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── interview-comment.dto.ts
│   │   │   │   │   ├── interview-distribute.dto.ts
│   │   │   │   │   ├── interview-pair.dto.ts
│   │   │   │   │   ├── interview.dto.ts
│   │   │   │   │   ├── put-interview-feedback.dto.ts
│   │   │   │   │   └── registration-interview.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── interviewFeedback.service.ts
│   │   │   │   ├── interviews.controller.ts
│   │   │   │   └── interviews.service.ts
│   │   │   ├── mentor-reviews/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── mentor-review-assign.dto.ts
│   │   │   │   │   ├── mentor-reviews-query.dto.ts
│   │   │   │   │   └── mentor-reviews.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── mentor-reviews.controller.ts
│   │   │   │   └── mentor-reviews.service.ts
│   │   │   ├── mentors/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── mentor-dashboard.dto.ts
│   │   │   │   │   ├── mentor-options.dto.ts
│   │   │   │   │   └── mentor-student.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── mentors.controller.ts
│   │   │   │   └── mentors.service.ts
│   │   │   ├── score/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── score-query.dto.ts
│   │   │   │   │   └── score.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── score.controller.ts
│   │   │   │   ├── score.service.ts
│   │   │   │   └── write-score.service.ts
│   │   │   ├── stats/
│   │   │   │   ├── course-stats.controller.ts
│   │   │   │   ├── course-stats.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── countries-stats.dto.ts
│   │   │   │   │   ├── course-mentors-stats.dto.ts
│   │   │   │   │   ├── course-stats.dto.ts
│   │   │   │   │   ├── expelled-stats.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── task-performance-stats.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── students/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── student.dto.ts
│   │   │   │   │   ├── user-students-query.dto.ts
│   │   │   │   │   └── user-students.dto.ts
│   │   │   │   ├── feedbacks/
│   │   │   │   │   ├── dto/
│   │   │   │   │   │   ├── create-student-feedback.dto.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── student-feedback.dto.ts
│   │   │   │   │   │   └── update-student-feedback.dto.ts
│   │   │   │   │   ├── feedbacks.controller.ts
│   │   │   │   │   ├── feedbacks.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── students.controller.ts
│   │   │   │   └── students.service.ts
│   │   │   ├── task-solutions/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── create-task-solution.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── task-solution.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── task-solutions.controller.ts
│   │   │   │   └── task-solutions.service.ts
│   │   │   ├── task-verifications/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── create-task-verification.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── self-education.dto.ts
│   │   │   │   │   └── task-verifications-attempts.dto.ts
│   │   │   │   ├── self-education.service.test.ts
│   │   │   │   ├── self-education.service.ts
│   │   │   │   ├── task-verifications.controller.ts
│   │   │   │   ├── task-verifications.service.test.ts
│   │   │   │   └── task-verifications.service.ts
│   │   │   ├── tasks/
│   │   │   │   ├── dto/
│   │   │   │   │   └── check-tasks-deadline.ts
│   │   │   │   ├── tasks.controller.ts
│   │   │   │   └── tasks.service.ts
│   │   │   └── team-distribution/
│   │   │       ├── distribute-students.service.ts
│   │   │       ├── dto/
│   │   │       │   ├── create-team-distribution.dto.ts
│   │   │       │   ├── create-team.dto.ts
│   │   │       │   ├── index.ts
│   │   │       │   ├── join-team.dto.ts
│   │   │       │   ├── team-distribution-student.dto.ts
│   │   │       │   ├── team-distribution.dto.ts
│   │   │       │   ├── team.dto.ts
│   │   │       │   ├── update-team-distribution.dto.ts
│   │   │       │   └── update-team-dto.ts
│   │   │       ├── registered-student-guard.ts
│   │   │       ├── team-distribution-student.service.test.ts
│   │   │       ├── team-distribution-student.service.ts
│   │   │       ├── team-distribution.controller.ts
│   │   │       ├── team-distribution.service.test.ts
│   │   │       ├── team-distribution.service.ts
│   │   │       ├── team-lead-or-manager.guard.ts
│   │   │       ├── team.controller.ts
│   │   │       └── team.service.ts
│   │   ├── cross-check/
│   │   │   ├── cross-check.module.ts
│   │   │   ├── cross-check.service.spec.ts
│   │   │   ├── cross-check.service.ts
│   │   │   └── tasks-filtering.ts
│   │   ├── devtools/
│   │   │   ├── devtools.controller.ts
│   │   │   ├── devtools.module.ts
│   │   │   ├── devtools.service.ts
│   │   │   └── dto/
│   │   │       └── devtools.users-dto.ts
│   │   ├── disciplines/
│   │   │   ├── disciplines.controller.test.ts
│   │   │   ├── disciplines.controller.ts
│   │   │   ├── disciplines.module.ts
│   │   │   ├── disciplines.service.test.ts
│   │   │   ├── disciplines.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── create-discipline.dto.ts
│   │   │   │   ├── discipline-ids.dto.ts
│   │   │   │   ├── discipline.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── update-discipline.dto.ts
│   │   │   └── index.ts
│   │   ├── discord-servers/
│   │   │   ├── discord-servers.controller.ts
│   │   │   ├── discord-servers.module.ts
│   │   │   ├── discord-servers.service.ts
│   │   │   └── dto/
│   │   │       ├── create-discord-server.dto.ts
│   │   │       ├── discord-server.dto.ts
│   │   │       ├── index.ts
│   │   │       └── update-discord-server.dto.ts
│   │   ├── events/
│   │   │   ├── dto/
│   │   │   │   ├── create-event.dto.ts
│   │   │   │   ├── event.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── update-event.dto.ts
│   │   │   ├── events.controller.ts
│   │   │   ├── events.module.ts
│   │   │   └── events.service.ts
│   │   ├── gratitudes/
│   │   │   ├── discord.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── badge.dto.ts
│   │   │   │   ├── country.dto.ts
│   │   │   │   ├── create-gratitude.dto.ts
│   │   │   │   ├── gratitude.dto.ts
│   │   │   │   ├── hero-radar.dto.ts
│   │   │   │   ├── heroes-radar-badge.dto.ts
│   │   │   │   ├── heroes-radar-query.dto.ts
│   │   │   │   ├── heroes-radar.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── gratitudes.controller.ts
│   │   │   ├── gratitudes.module.ts
│   │   │   ├── gratitudes.service.ts
│   │   │   └── index.ts
│   │   ├── listeners/
│   │   │   ├── course.listener.ts
│   │   │   ├── index.ts
│   │   │   └── listeners.module.ts
│   │   ├── main.ts
│   │   ├── mentors-hall-of-fame/
│   │   │   ├── dto/
│   │   │   │   ├── course-stats.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── top-mentor.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── mentors-hall-of-fame.controller.test.ts
│   │   │   ├── mentors-hall-of-fame.controller.ts
│   │   │   ├── mentors-hall-of-fame.module.ts
│   │   │   ├── mentors-hall-of-fame.service.test.ts
│   │   │   └── mentors-hall-of-fame.service.ts
│   │   ├── migrations.ts
│   │   ├── notifications/
│   │   │   ├── dto/
│   │   │   │   ├── notification.dto.ts
│   │   │   │   └── update-notification.dto.ts
│   │   │   ├── email-template.ts
│   │   │   ├── notifications.controller.ts
│   │   │   ├── notifications.module.ts
│   │   │   └── notifications.service.ts
│   │   ├── openapi-spec.ts
│   │   ├── opportunities/
│   │   │   ├── dto/
│   │   │   │   ├── applicant-resume.dto.ts
│   │   │   │   ├── consent.dto.ts
│   │   │   │   ├── form-data.dto.ts
│   │   │   │   ├── give-consent-dto.ts
│   │   │   │   ├── resume.dto.ts
│   │   │   │   ├── status.dto.ts
│   │   │   │   └── visibility.dto.ts
│   │   │   ├── opportunities.controller.ts
│   │   │   ├── opportunities.module.ts
│   │   │   ├── opportunities.service.test.ts
│   │   │   └── opportunities.service.ts
│   │   ├── ormconfig.ts
│   │   ├── profile/
│   │   │   ├── dto/
│   │   │   │   ├── endorsement.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── personal-profile.dto.ts
│   │   │   │   ├── profile-course.dto.ts
│   │   │   │   ├── profile.dto.ts
│   │   │   │   ├── update-profile.dto.ts
│   │   │   │   └── update-user.dto.ts
│   │   │   ├── endorsement.service.ts
│   │   │   ├── index.ts
│   │   │   ├── profile.controller.ts
│   │   │   ├── profile.module.ts
│   │   │   └── profile.service.ts
│   │   ├── prompts/
│   │   │   ├── dto/
│   │   │   │   ├── create-prompt.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── prompt.dto.ts
│   │   │   │   └── update-prompt.dto.ts
│   │   │   ├── prompts.controller.ts
│   │   │   ├── prompts.module.ts
│   │   │   └── prompts.service.ts
│   │   ├── registry/
│   │   │   ├── constants.ts
│   │   │   ├── dto/
│   │   │   │   ├── approve-mentor.dto.ts
│   │   │   │   ├── comment-mentor-registry.dto.ts
│   │   │   │   ├── invite-mentors.dto.ts
│   │   │   │   └── mentor-registry.dto.ts
│   │   │   ├── registry.controller.ts
│   │   │   ├── registry.module.ts
│   │   │   └── registry.service.ts
│   │   ├── repositories/
│   │   │   ├── dto/
│   │   │   │   ├── create-repository-event.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── index.ts
│   │   │   ├── repositories.controller.ts
│   │   │   ├── repositories.module.ts
│   │   │   └── repositories.service.ts
│   │   ├── reset.d.ts
│   │   ├── schedule/
│   │   │   ├── dto/
│   │   │   │   └── check-schedule-changes.ts
│   │   │   ├── schedule.controller.ts
│   │   │   ├── schedule.module.ts
│   │   │   └── schedule.service.ts
│   │   ├── session/
│   │   │   ├── dto/
│   │   │   │   └── auth-user.dto.ts
│   │   │   ├── session.controller.ts
│   │   │   └── session.module.ts
│   │   ├── setup.ts
│   │   ├── spec.json
│   │   ├── tasks/
│   │   │   ├── dto/
│   │   │   │   ├── create-task.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── task.dto.ts
│   │   │   │   └── update-task.dto.ts
│   │   │   ├── tasks-criteria/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── criteria.dto.ts
│   │   │   │   │   └── task-criteria.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── tasks-criteria.controller.ts
│   │   │   │   └── tasks-criteria.service.ts
│   │   │   ├── tasks.controller.ts
│   │   │   ├── tasks.module.ts
│   │   │   └── tasks.service.ts
│   │   ├── user-groups/
│   │   │   ├── dto/
│   │   │   │   ├── create-user-group.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── update-user-group.dto.ts
│   │   │   │   └── user-group.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── user-groups.controller.ts
│   │   │   ├── user-groups.module.ts
│   │   │   └── user-groups.service.ts
│   │   ├── users/
│   │   │   ├── dto/
│   │   │   │   ├── index.ts
│   │   │   │   ├── user-search.dto.ts
│   │   │   │   └── user.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── users.controller.ts
│   │   │   ├── users.module.ts
│   │   │   └── users.service.ts
│   │   ├── users-notifications/
│   │   │   ├── dto/
│   │   │   │   ├── notification-connection-exists.dto.ts
│   │   │   │   ├── notification-connection.dto.ts
│   │   │   │   ├── notification-user-connections.dto.ts
│   │   │   │   ├── notification-user-settings.dto.ts
│   │   │   │   ├── send-user-notification.dto.ts
│   │   │   │   ├── update-notification-user-settings.dto.ts
│   │   │   │   └── upsert-notification-connection.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── users-notifications.module.ts
│   │   │   ├── users.notifications.controller.ts
│   │   │   └── users.notifications.service.ts
│   │   └── utils/
│   │       ├── index.ts
│   │       ├── shuffle.test.ts
│   │       └── shuffle.ts
│   ├── test/
│   │   └── app.e2e-spec.ts
│   ├── tsconfig.build.json
│   ├── tsconfig.json
│   └── vitest.config.mts
├── package.json
├── renovate.json
├── server/
│   ├── .dockerignore
│   ├── .swcrc
│   ├── Dockerfile
│   ├── Dockerfile.lambda
│   ├── README.md
│   ├── eslint.config.mjs
│   ├── package.json
│   ├── public/
│   │   └── swagger.yml
│   ├── src/
│   │   ├── app.ts
│   │   ├── config.ts
│   │   ├── dataSource.ts
│   │   ├── dataSourceOptions.ts
│   │   ├── index.ts
│   │   ├── logger.ts
│   │   ├── migrations/
│   │   │   ├── 1630340371992-UserMigration.ts
│   │   │   ├── 1630341383942-TaskResult.ts
│   │   │   ├── 1630342025950-StudentMigration.ts
│   │   │   ├── 1630342266002-UserMigration.ts
│   │   │   ├── 1630347897950-StudentMigration.ts
│   │   │   ├── 1632333725126-ResumeMigration.ts
│   │   │   ├── 1635365797478-User.ts
│   │   │   ├── 1637591194886-StageInterview.ts
│   │   │   ├── 1638302439645-CourseMigration.ts
│   │   │   ├── 1639418471577-Indicies.ts
│   │   │   ├── 1639427578702-Update.ts
│   │   │   ├── 1639502600339-Student.ts
│   │   │   ├── 1642884123347-ResumeSelectCourses.ts
│   │   │   ├── 1643481312933-Task.ts
│   │   │   ├── 1643550350939-LoginState.ts
│   │   │   ├── 1643926895264-Notifications.ts
│   │   │   ├── 1644695410918-NotificationConnection.ts
│   │   │   ├── 1645364514538-RepositoryEvent.ts
│   │   │   ├── 1645654601903-Opportunitites.ts
│   │   │   ├── 1647103154082-CrossCheckScheduling.ts
│   │   │   ├── 1647175301446-TaskSolutionConstraint.ts
│   │   │   ├── 1647550751147-NotificationType.ts
│   │   │   ├── 1647885219936-LoginStateUserId.ts
│   │   │   ├── 1649505252996-CourseLogo.ts
│   │   │   ├── 1649868994688-CourseLogo.ts
│   │   │   ├── 1650652882300-DiscordChannel.ts
│   │   │   ├── 1652870756742-Resume.ts
│   │   │   ├── 1656326258991-History.ts
│   │   │   ├── 1661034658479-Feedback.ts
│   │   │   ├── 1661087975938-Discipline.ts
│   │   │   ├── 1661106736439-Disciplines.ts
│   │   │   ├── 1661107174477-Disciplines.ts
│   │   │   ├── 1661616212488-NotificationCategory.ts
│   │   │   ├── 1662275601017-CourseTask.ts
│   │   │   ├── 1664183799115-CourseEvent.ts
│   │   │   ├── 1666348642811-TaskCriteria.ts
│   │   │   ├── 1666621080327-TaskSolutionResult.ts
│   │   │   ├── 1671475396333-Tasks.ts
│   │   │   ├── 1672142743107-TeamDistribution.ts
│   │   │   ├── 1672386450861-TeamDistribution.ts
│   │   │   ├── 1673090827105-TaskVerification.ts
│   │   │   ├── 1673692838338-User.ts
│   │   │   ├── 1674128274839-Team.ts
│   │   │   ├── 1674377676805-TeamDistributionStudent.ts
│   │   │   ├── 1674755854609-Resume.ts
│   │   │   ├── 1675245424426-UserGroup.ts
│   │   │   ├── 1675345245770-Course.ts
│   │   │   ├── 1676139987317-User.ts
│   │   │   ├── 1685197747051-MentorRegistry.ts
│   │   │   ├── 1686657350908-InterviewScore.ts
│   │   │   ├── 1687009744110-Prompt.ts
│   │   │   ├── 1691520611773-Temperature.ts
│   │   │   ├── 1691524327332-Temperature.ts
│   │   │   ├── 1693930286280-CourseUsersActivist.ts
│   │   │   ├── 1699808604000-AddMinStudentPerMentorColumnToCourse.ts
│   │   │   ├── 1700391857109-Obfuscation.ts
│   │   │   ├── 1712137476312-Course.ts
│   │   │   ├── 1730926720293-CourseTask.ts
│   │   │   ├── 1734874453585-Contributor.ts
│   │   │   ├── 1736458672717-Course.ts
│   │   │   ├── 1738250779923-CoursePersonalMentoringDates.ts
│   │   │   ├── 1746467689328-Course.ts
│   │   │   ├── 1747380525126-CourseTaskInterviewCreatingPairs.ts
│   │   │   ├── 1760699701354-AddCourseLeaveSurveyResponse.ts
│   │   │   └── index.ts
│   │   ├── models/
│   │   │   ├── alert.ts
│   │   │   ├── certificate.ts
│   │   │   ├── contributor.ts
│   │   │   ├── course-leave-survey-response.entity.ts
│   │   │   ├── course.ts
│   │   │   ├── courseEvent.ts
│   │   │   ├── courseManager.ts
│   │   │   ├── courseTask.ts
│   │   │   ├── courseUser.ts
│   │   │   ├── data/
│   │   │   │   ├── available-languages.data.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── language-levels.data.ts
│   │   │   ├── discipline.ts
│   │   │   ├── discordServer.ts
│   │   │   ├── event.ts
│   │   │   ├── feedback.ts
│   │   │   ├── history.ts
│   │   │   ├── index.ts
│   │   │   ├── loginState.ts
│   │   │   ├── mentor.ts
│   │   │   ├── mentorRegistry.ts
│   │   │   ├── notification.ts
│   │   │   ├── notificationChannel.ts
│   │   │   ├── notificationChannelSettings.ts
│   │   │   ├── notificationUserConnection.ts
│   │   │   ├── notificationUserSettings.ts
│   │   │   ├── privateFeedback.ts
│   │   │   ├── profilePermissions.ts
│   │   │   ├── prompt.ts
│   │   │   ├── registry.ts
│   │   │   ├── repositoryEvent.ts
│   │   │   ├── resume.ts
│   │   │   ├── session.ts
│   │   │   ├── stageInterview.ts
│   │   │   ├── stageInterviewFeedback.ts
│   │   │   ├── stageInterviewStudent.ts
│   │   │   ├── student-feedback.ts
│   │   │   ├── student.ts
│   │   │   ├── task.ts
│   │   │   ├── taskArtefact.ts
│   │   │   ├── taskChecker.ts
│   │   │   ├── taskCriteria.ts
│   │   │   ├── taskInterviewResult.ts
│   │   │   ├── taskInterviewStudent.ts
│   │   │   ├── taskResult.ts
│   │   │   ├── taskSolution.ts
│   │   │   ├── taskSolutionChecker.ts
│   │   │   ├── taskSolutionResult.ts
│   │   │   ├── taskVerification.ts
│   │   │   ├── team.ts
│   │   │   ├── teamDistribution.ts
│   │   │   ├── teamDistributionStudent.ts
│   │   │   ├── user.ts
│   │   │   └── userGroup.ts
│   │   ├── repositories/
│   │   │   ├── courseTask.repository.ts
│   │   │   ├── crossCheck.repository.ts
│   │   │   ├── feedback.repository.ts
│   │   │   ├── interview.repository.ts
│   │   │   ├── mentor.repository.ts
│   │   │   ├── mentorRegistry.repository.ts
│   │   │   ├── repositoryEvent.repository.ts
│   │   │   ├── stageInterview.repository.ts
│   │   │   ├── stageInterviewFeedback.repository.ts
│   │   │   ├── student.repository.ts
│   │   │   └── user.repository.ts
│   │   ├── reset.d.ts
│   │   ├── routes/
│   │   │   ├── checks/
│   │   │   │   ├── getBadComment.ts
│   │   │   │   ├── getMaxScoreCheckers.ts
│   │   │   │   └── index.ts
│   │   │   ├── common.ts
│   │   │   ├── course/
│   │   │   │   ├── certificates.ts
│   │   │   │   ├── crossCheck/
│   │   │   │   │   ├── createCompletion.ts
│   │   │   │   │   ├── createDistribution.ts
│   │   │   │   │   ├── createMessage.ts
│   │   │   │   │   ├── createResult.ts
│   │   │   │   │   ├── createSolution.ts
│   │   │   │   │   ├── deleteSolution.ts
│   │   │   │   │   ├── getAssignments.ts
│   │   │   │   │   ├── getResult.ts
│   │   │   │   │   ├── getSolution.ts
│   │   │   │   │   ├── getTaskDetails.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── updateMessage.ts
│   │   │   │   ├── events.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── interviews.ts
│   │   │   │   ├── mentor.ts
│   │   │   │   ├── repository.ts
│   │   │   │   ├── schedule.ts
│   │   │   │   ├── score/
│   │   │   │   │   ├── createMultipleScores.ts
│   │   │   │   │   ├── createSingleScore.ts
│   │   │   │   │   ├── getScoreByStudent.ts
│   │   │   │   │   ├── getScoreCsv.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── recalculateScore.ts
│   │   │   │   ├── stageInterview/
│   │   │   │   │   ├── cancelInterview.ts
│   │   │   │   │   ├── createFeedback.ts
│   │   │   │   │   ├── createInterview.ts
│   │   │   │   │   ├── createInterviews.ts
│   │   │   │   │   ├── getFeedback.ts
│   │   │   │   │   ├── getInterviewStudent.ts
│   │   │   │   │   ├── getInterviewerStudents.ts
│   │   │   │   │   ├── getInterviews.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── updateInterview.ts
│   │   │   │   ├── student.ts
│   │   │   │   ├── students.ts
│   │   │   │   ├── taskArtefact.ts
│   │   │   │   ├── taskVerifications.ts
│   │   │   │   └── tasks/
│   │   │   │       ├── createCourseTaskDistribution.ts
│   │   │   │       ├── getCourseTasksDetails.ts
│   │   │   │       └── index.ts
│   │   │   ├── feedback.ts
│   │   │   ├── file/
│   │   │   │   ├── index.ts
│   │   │   │   └── upload.ts
│   │   │   ├── guards.ts
│   │   │   ├── index.ts
│   │   │   ├── logging.ts
│   │   │   ├── me.ts
│   │   │   ├── middlewares.ts
│   │   │   ├── profile/
│   │   │   │   ├── __test__/
│   │   │   │   │   └── permissions.test.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── info.ts
│   │   │   │   ├── me.ts
│   │   │   │   ├── mentor-stats.ts
│   │   │   │   ├── permissions.ts
│   │   │   │   ├── public-feedback.ts
│   │   │   │   ├── stage-interview-feedback.ts
│   │   │   │   ├── student-stats.ts
│   │   │   │   └── user-info.ts
│   │   │   ├── registry/
│   │   │   │   └── index.ts
│   │   │   ├── repository/
│   │   │   │   ├── events.ts
│   │   │   │   └── index.ts
│   │   │   ├── task/
│   │   │   │   └── index.ts
│   │   │   ├── taskVerification/
│   │   │   │   └── index.ts
│   │   │   ├── tasks/
│   │   │   │   └── index.ts
│   │   │   ├── users/
│   │   │   │   └── index.ts
│   │   │   ├── utils.ts
│   │   │   └── validators.ts
│   │   ├── rules/
│   │   │   ├── __tests__/
│   │   │   │   └── mentors.test.ts
│   │   │   ├── index.ts
│   │   │   ├── interviews.ts
│   │   │   ├── mentors.ts
│   │   │   ├── name.ts
│   │   │   └── types.ts
│   │   ├── schedule.ts
│   │   └── services/
│   │       ├── aws.service.ts
│   │       ├── check.service.ts
│   │       ├── course.service.ts
│   │       ├── crossCheck.service.ts
│   │       ├── distribution/
│   │       │   ├── __tests__/
│   │       │   │   ├── crossCheck.test.ts
│   │       │   │   ├── crossMentor.test.ts
│   │       │   │   └── shuffle.test.ts
│   │       │   ├── crossCheckDistribution.service.ts
│   │       │   ├── crossMentorDistribution.service.ts
│   │       │   ├── index.ts
│   │       │   └── shuffle.ts
│   │       ├── github.service.ts
│   │       ├── index.ts
│   │       ├── interview.service.ts
│   │       ├── notification.service.ts
│   │       ├── operationResult.ts
│   │       ├── repository.service.ts
│   │       ├── score/
│   │       │   ├── index.ts
│   │       │   └── score.service.ts
│   │       ├── stageInterview.service.ts
│   │       ├── student.service.ts
│   │       ├── taskResults.service.ts
│   │       ├── taskVerification.service.ts
│   │       ├── tasks.service.ts
│   │       └── user.service.ts
│   ├── swaggerDef.js
│   ├── tsconfig.json
│   └── vitest.config.mts
├── setup/
│   ├── backup-local.sql
│   ├── cdk/
│   │   ├── App.ts
│   │   ├── DockerFunctionConstruct.ts
│   │   ├── Stack.ts
│   │   ├── cdk.json
│   │   └── package.json
│   ├── docker-compose.yml
│   ├── dump-local.sh
│   ├── dump.sh
│   ├── nginx/
│   │   └── nginx.conf
│   ├── restore-local.sh
│   └── restore.sh
├── skills-lock.json
├── tools/
│   └── sloths/
│       ├── .eslintrc.cjs
│       ├── .gitignore
│       ├── .oxfmtrc.json
│       ├── README.md
│       ├── env.d.ts
│       ├── index.html
│       ├── package.json
│       ├── public/
│       │   └── cdn/
│       │       ├── cleaned/
│       │       │   └── filelist.json
│       │       └── stickers/
│       │           ├── activist/
│       │           │   └── metadata.json
│       │           ├── codewars/
│       │           │   └── metadata.json
│       │           ├── congrats/
│       │           │   └── metadata.json
│       │           └── metadata.json
│       ├── src/
│       │   ├── App.vue
│       │   ├── assets/
│       │   │   ├── locales/
│       │   │   │   └── en.json
│       │   │   └── styles/
│       │   │       ├── base.css
│       │   │       ├── fonts.css
│       │   │       ├── main.css
│       │   │       └── variables.css
│       │   ├── common/
│       │   │   ├── const.ts
│       │   │   └── types.ts
│       │   ├── components/
│       │   │   ├── about/
│       │   │   │   ├── AboutSection.vue
│       │   │   │   └── AboutTeammate.vue
│       │   │   ├── background/
│       │   │   │   └── BackgroundView.vue
│       │   │   ├── buttons/
│       │   │   │   ├── CustomBtn.vue
│       │   │   │   ├── IconBtn.vue
│       │   │   │   └── ImageBtn.vue
│       │   │   ├── catalog/
│       │   │   │   ├── SlothCard.vue
│       │   │   │   └── SlothInfo.vue
│       │   │   ├── controls-list/
│       │   │   │   ├── ControlsList.vue
│       │   │   │   ├── PaginationList.vue
│       │   │   │   ├── SearchText.vue
│       │   │   │   ├── SortingList.vue
│       │   │   │   └── TagCloud.vue
│       │   │   ├── footer/
│       │   │   │   └── FooterView.vue
│       │   │   ├── guess/
│       │   │   │   └── GuessInfo.vue
│       │   │   ├── header/
│       │   │   │   └── HeaderView.vue
│       │   │   ├── home/
│       │   │   │   ├── HomeAbout.vue
│       │   │   │   ├── HomeCatalog.vue
│       │   │   │   └── HomeCategory.vue
│       │   │   ├── loader/
│       │   │   │   └── LoaderView.vue
│       │   │   ├── memory/
│       │   │   │   ├── GameField.vue
│       │   │   │   └── MemoryInfo.vue
│       │   │   ├── mixins/
│       │   │   │   └── sort-mixin.ts
│       │   │   ├── modal/
│       │   │   │   ├── AlertModal.vue
│       │   │   │   └── ModalWindow.vue
│       │   │   └── switchers/
│       │   │       ├── SoundSwitcher.vue
│       │   │       └── ThemeSwitcher.vue
│       │   ├── i18n.ts
│       │   ├── main.ts
│       │   ├── router/
│       │   │   └── index.ts
│       │   ├── services/
│       │   │   ├── error-handler.ts
│       │   │   └── sloths-service.ts
│       │   ├── shims-vue.d.ts
│       │   ├── stores/
│       │   │   ├── alert-modal.ts
│       │   │   ├── audio-on.ts
│       │   │   ├── cleaned.ts
│       │   │   ├── counter.ts
│       │   │   ├── loader.ts
│       │   │   ├── pages-store.ts
│       │   │   ├── pagination.ts
│       │   │   ├── search-text.ts
│       │   │   ├── sloth-info.ts
│       │   │   ├── sloths.ts
│       │   │   ├── sorting-list.ts
│       │   │   ├── tag-cloud.ts
│       │   │   └── theme.ts
│       │   ├── utils/
│       │   │   ├── audio.ts
│       │   │   ├── canvas-utils.ts
│       │   │   ├── game-utils.ts
│       │   │   └── userTheme.ts
│       │   └── views/
│       │       ├── 404.vue
│       │       ├── About.vue
│       │       ├── Catalog.vue
│       │       ├── Create.vue
│       │       ├── Guess.vue
│       │       ├── Home.vue
│       │       ├── Memory.vue
│       │       └── Merch.vue
│       ├── tsconfig.config.json
│       ├── tsconfig.json
│       └── vite.config.ts
├── turbo.json
└── vitest.shared.mts

================================================
FILE CONTENTS
================================================

================================================
FILE: .agents/skills/nestjs-best-practices/.github/workflows/branch-protection.yml
================================================
name: Branch Protection

on:
  pull_request:
    branches: [main]

jobs:
  check-branch:
    runs-on: ubuntu-latest
    steps:
      - name: Block docs branch merge to main
        if: github.head_ref == 'docs'
        run: |
          echo "::error::Merging 'docs' branch into 'main' is not allowed."
          echo ""
          echo "The 'docs' branch contains the documentation website which should"
          echo "remain separate from the main skill files to keep installations lightweight."
          echo ""
          echo "If you need to sync changes, cherry-pick specific commits instead."
          exit 1

      - name: Branch check passed
        if: github.head_ref != 'docs'
        run: echo "Branch check passed - not merging from docs branch"


================================================
FILE: .agents/skills/nestjs-best-practices/.github/workflows/deploy.yml
================================================
name: Deploy to GitHub Pages

on:
  push:
    branches: [docs]
    paths:
      - 'website/**'
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
          cache-dependency-path: website/package-lock.json

      - name: Setup Pages
        uses: actions/configure-pages@v4

      - name: Install dependencies
        run: npm ci
        working-directory: website

      - name: Build
        run: npm run build
        working-directory: website

      - name: Copy index.html to 404.html for SPA routing
        run: cp website/dist/index.html website/dist/404.html

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: website/dist

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4


================================================
FILE: .agents/skills/nestjs-best-practices/.gitignore
================================================
# Dependencies
node_modules/

# Website (lives on docs branch)
website/

# Build outputs
dist/
*.js
*.d.ts
*.js.map

# IDE
.idea/
.vscode/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*

# Environment
.env
.env.local


================================================
FILE: .agents/skills/nestjs-best-practices/AGENTS.md
================================================
# NestJS Best Practices

**Version 1.1.0**
NestJS Best Practices
January 2026

> **Note:**
> This document is mainly for agents and LLMs to follow when maintaining,
> generating, or refactoring NestJS codebases. Humans may also find it
> useful, but guidance here is optimized for automation and consistency
> by AI-assisted workflows.

---

## Abstract

Comprehensive best practices and architecture guide for NestJS applications, designed for AI agents and LLMs. Contains 40 rules across 10 categories, prioritized by impact from critical (architecture, dependency injection) to incremental (DevOps patterns). Each rule includes detailed explanations, real-world examples comparing incorrect vs. correct implementations, and specific impact metrics to guide automated refactoring and code generation.

---

## Table of Contents

1. [Architecture](#1-architecture) — **CRITICAL**
   - 1.1 [Avoid Circular Dependencies](#11-avoid-circular-dependencies)
   - 1.2 [Organize by Feature Modules](#12-organize-by-feature-modules)
   - 1.3 [Use Proper Module Sharing Patterns](#13-use-proper-module-sharing-patterns)
   - 1.4 [Single Responsibility for Services](#14-single-responsibility-for-services)
   - 1.5 [Use Event-Driven Architecture for Decoupling](#15-use-event-driven-architecture-for-decoupling)
   - 1.6 [Use Repository Pattern for Data Access](#16-use-repository-pattern-for-data-access)
2. [Dependency Injection](#2-dependency-injection) — **CRITICAL**
   - 2.1 [Avoid Service Locator Anti-Pattern](#21-avoid-service-locator-anti-pattern)
   - 2.2 [Apply Interface Segregation Principle](#22-apply-interface-segregation-principle)
   - 2.3 [Honor Liskov Substitution Principle](#23-honor-liskov-substitution-principle)
   - 2.4 [Prefer Constructor Injection](#24-prefer-constructor-injection)
   - 2.5 [Understand Provider Scopes](#25-understand-provider-scopes)
   - 2.6 [Use Injection Tokens for Interfaces](#26-use-injection-tokens-for-interfaces)
3. [Error Handling](#3-error-handling) — **HIGH**
   - 3.1 [Handle Async Errors Properly](#31-handle-async-errors-properly)
   - 3.2 [Throw HTTP Exceptions from Services](#32-throw-http-exceptions-from-services)
   - 3.3 [Use Exception Filters for Error Handling](#33-use-exception-filters-for-error-handling)
4. [Security](#4-security) — **HIGH**
   - 4.1 [Implement Secure JWT Authentication](#41-implement-secure-jwt-authentication)
   - 4.2 [Implement Rate Limiting](#42-implement-rate-limiting)
   - 4.3 [Sanitize Output to Prevent XSS](#43-sanitize-output-to-prevent-xss)
   - 4.4 [Use Guards for Authentication and Authorization](#44-use-guards-for-authentication-and-authorization)
   - 4.5 [Validate All Input with DTOs and Pipes](#45-validate-all-input-with-dtos-and-pipes)
5. [Performance](#5-performance) — **HIGH**
   - 5.1 [Use Async Lifecycle Hooks Correctly](#51-use-async-lifecycle-hooks-correctly)
   - 5.2 [Use Lazy Loading for Large Modules](#52-use-lazy-loading-for-large-modules)
   - 5.3 [Optimize Database Queries](#53-optimize-database-queries)
   - 5.4 [Use Caching Strategically](#54-use-caching-strategically)
6. [Testing](#6-testing) — **MEDIUM-HIGH**
   - 6.1 [Use Supertest for E2E Testing](#61-use-supertest-for-e2e-testing)
   - 6.2 [Mock External Services in Tests](#62-mock-external-services-in-tests)
   - 6.3 [Use Testing Module for Unit Tests](#63-use-testing-module-for-unit-tests)
7. [Database & ORM](#7-database-orm) — **MEDIUM-HIGH**
   - 7.1 [Avoid N+1 Query Problems](#71-avoid-n-1-query-problems)
   - 7.2 [Use Database Migrations](#72-use-database-migrations)
   - 7.3 [Use Transactions for Multi-Step Operations](#73-use-transactions-for-multi-step-operations)
8. [API Design](#8-api-design) — **MEDIUM**
   - 8.1 [Use DTOs and Serialization for API Responses](#81-use-dtos-and-serialization-for-api-responses)
   - 8.2 [Use Interceptors for Cross-Cutting Concerns](#82-use-interceptors-for-cross-cutting-concerns)
   - 8.3 [Use Pipes for Input Transformation](#83-use-pipes-for-input-transformation)
   - 8.4 [Use API Versioning for Breaking Changes](#84-use-api-versioning-for-breaking-changes)
9. [Microservices](#9-microservices) — **MEDIUM**
   - 9.1 [Implement Health Checks for Microservices](#91-implement-health-checks-for-microservices)
   - 9.2 [Use Message and Event Patterns Correctly](#92-use-message-and-event-patterns-correctly)
   - 9.3 [Use Message Queues for Background Jobs](#93-use-message-queues-for-background-jobs)
10. [DevOps & Deployment](#10-devops-deployment) — **LOW-MEDIUM**

- 10.1 [Implement Graceful Shutdown](#101-implement-graceful-shutdown)
- 10.2 [Use ConfigModule for Environment Configuration](#102-use-configmodule-for-environment-configuration)
- 10.3 [Use Structured Logging](#103-use-structured-logging)

---

## 1. Architecture

**Section Impact: CRITICAL**

### 1.1 Avoid Circular Dependencies

**Impact: CRITICAL** — "#1 cause of runtime crashes"

Circular dependencies occur when Module A imports Module B, and Module B imports Module A (directly or transitively). NestJS can sometimes resolve these through forward references, but they indicate architectural problems and should be avoided. This is the #1 cause of runtime crashes in NestJS applications.

**Incorrect (circular module imports):**

```typescript
// users.module.ts
@Module({
  imports: [OrdersModule], // Orders needs Users, Users needs Orders = circular
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

// orders.module.ts
@Module({
  imports: [UsersModule], // Circular dependency!
  providers: [OrdersService],
  exports: [OrdersService],
})
export class OrdersModule {}
```

**Correct (extract shared logic or use events):**

```typescript
// Option 1: Extract shared logic to a third module
// shared.module.ts
@Module({
  providers: [SharedService],
  exports: [SharedService],
})
export class SharedModule {}

// users.module.ts
@Module({
  imports: [SharedModule],
  providers: [UsersService],
})
export class UsersModule {}

// orders.module.ts
@Module({
  imports: [SharedModule],
  providers: [OrdersService],
})
export class OrdersModule {}

// Option 2: Use events for decoupled communication
// users.service.ts
@Injectable()
export class UsersService {
  constructor(private eventEmitter: EventEmitter2) {}

  async createUser(data: CreateUserDto) {
    const user = await this.userRepo.save(data);
    this.eventEmitter.emit('user.created', user);
    return user;
  }
}

// orders.service.ts
@Injectable()
export class OrdersService {
  @OnEvent('user.created')
  handleUserCreated(user: User) {
    // React to user creation without direct dependency
  }
}
```

Reference: [NestJS Circular Dependency](https://docs.nestjs.com/fundamentals/circular-dependency)

---

### 1.2 Organize by Feature Modules

**Impact: CRITICAL** — "3-5x faster onboarding and development"

Organize your application into feature modules that encapsulate related functionality. Each feature module should be self-contained with its own controllers, services, entities, and DTOs. Avoid organizing by technical layer (all controllers together, all services together). This enables 3-5x faster onboarding and feature development.

**Incorrect (technical layer organization):**

```typescript
// Technical layer organization (anti-pattern)
src/
├── controllers/
│   ├── users.controller.ts
│   ├── orders.controller.ts
│   └── products.controller.ts
├── services/
│   ├── users.service.ts
│   ├── orders.service.ts
│   └── products.service.ts
├── entities/
│   ├── user.entity.ts
│   ├── order.entity.ts
│   └── product.entity.ts
└── app.module.ts  // Imports everything directly
```

**Correct (feature module organization):**

```typescript
// Feature module organization
src/
├── users/
│   ├── dto/
│   │   ├── create-user.dto.ts
│   │   └── update-user.dto.ts
│   ├── entities/
│   │   └── user.entity.ts
│   ├── users.controller.ts
│   ├── users.service.ts
│   ├── users.repository.ts
│   └── users.module.ts
├── orders/
│   ├── dto/
│   ├── entities/
│   ├── orders.controller.ts
│   ├── orders.service.ts
│   └── orders.module.ts
├── shared/
│   ├── guards/
│   ├── interceptors/
│   ├── filters/
│   └── shared.module.ts
└── app.module.ts

// users.module.ts
@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService, UsersRepository],
  exports: [UsersService], // Only export what others need
})
export class UsersModule {}

// app.module.ts
@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRoot(),
    UsersModule,
    OrdersModule,
    SharedModule,
  ],
})
export class AppModule {}
```

Reference: [NestJS Modules](https://docs.nestjs.com/modules)

---

### 1.3 Use Proper Module Sharing Patterns

**Impact: CRITICAL** — Prevents duplicate instances, memory leaks, and state inconsistency

NestJS modules are singletons by default. When a service is properly exported from a module and that module is imported elsewhere, the same instance is shared. However, providing a service in multiple modules creates separate instances, leading to memory waste, state inconsistency, and confusing behavior. Always encapsulate services in dedicated modules, export them explicitly, and import the module where needed.

**Incorrect (service provided in multiple modules):**

```typescript
// StorageService provided directly in multiple modules - WRONG
// storage.service.ts
@Injectable()
export class StorageService {
  private cache = new Map(); // Each instance has separate state!

  store(key: string, value: any) {
    this.cache.set(key, value);
  }
}

// app.module.ts
@Module({
  providers: [StorageService], // Instance #1
  controllers: [AppController],
})
export class AppModule {}

// videos.module.ts
@Module({
  providers: [StorageService], // Instance #2 - different from AppModule!
  controllers: [VideosController],
})
export class VideosModule {}

// Problems:
// 1. Two separate StorageService instances exist
// 2. cache.set() in VideosModule doesn't affect AppModule's cache
// 3. Memory wasted on duplicate instances
// 4. Debugging nightmares when state doesn't sync
```

**Correct (dedicated module with exports):**

```typescript
// storage/storage.module.ts
@Module({
  providers: [StorageService],
  exports: [StorageService], // Make available to importers
})
export class StorageModule {}

// videos/videos.module.ts
@Module({
  imports: [StorageModule], // Import the module, not the service
  controllers: [VideosController],
  providers: [VideosService],
})
export class VideosModule {}

// channels/channels.module.ts
@Module({
  imports: [StorageModule], // Same instance shared
  controllers: [ChannelsController],
  providers: [ChannelsService],
})
export class ChannelsModule {}

// app.module.ts
@Module({
  imports: [
    StorageModule, // Only if AppModule itself needs StorageService
    VideosModule,
    ChannelsModule,
  ],
})
export class AppModule {}

// Now all modules share the SAME StorageService instance
```

**When to use @Global() (sparingly):**

```typescript
// ONLY for truly cross-cutting concerns
@Global()
@Module({
  providers: [ConfigService, LoggerService],
  exports: [ConfigService, LoggerService],
})
export class CoreModule {}

// Import once in AppModule
@Module({
  imports: [CoreModule], // Registered globally, available everywhere
})
export class AppModule {}

// Other modules don't need to import CoreModule
@Module({
  controllers: [UsersController],
  providers: [UsersService], // Can inject ConfigService without importing
})
export class UsersModule {}

// WARNING: Don't make everything global!
// - Hides dependencies (can't see what a module needs from imports)
// - Makes testing harder
// - Reserve for: config, logging, database connections
```

**Module re-exporting pattern:**

```typescript
// common.module.ts - shared utilities
@Module({
  providers: [DateService, ValidationService],
  exports: [DateService, ValidationService],
})
export class CommonModule {}

// core.module.ts - re-exports common for convenience
@Module({
  imports: [CommonModule, DatabaseModule],
  exports: [CommonModule, DatabaseModule], // Re-export for consumers
})
export class CoreModule {}

// feature.module.ts - imports CoreModule, gets both
@Module({
  imports: [CoreModule], // Gets CommonModule + DatabaseModule
  controllers: [FeatureController],
})
export class FeatureModule {}
```

Reference: [NestJS Modules](https://docs.nestjs.com/modules#shared-modules)

---

### 1.4 Single Responsibility for Services

**Impact: CRITICAL** — "40%+ improvement in testability"

Each service should have a single, well-defined responsibility. Avoid "god services" that handle multiple unrelated concerns. If a service name includes "And" or handles more than one domain concept, it likely violates single responsibility. This reduces complexity and improves testability by 40%+.

**Incorrect (god service anti-pattern):**

```typescript
// God service anti-pattern
@Injectable()
export class UserAndOrderService {
  constructor(
    private userRepo: UserRepository,
    private orderRepo: OrderRepository,
    private mailer: MailService,
    private payment: PaymentService,
  ) {}

  async createUser(dto: CreateUserDto) {
    const user = await this.userRepo.save(dto);
    await this.mailer.sendWelcome(user);
    return user;
  }

  async createOrder(userId: string, dto: CreateOrderDto) {
    const order = await this.orderRepo.save({ userId, ...dto });
    await this.payment.charge(order);
    await this.mailer.sendOrderConfirmation(order);
    return order;
  }

  async calculateOrderStats(userId: string) {
    // Stats logic mixed in
  }

  async validatePayment(orderId: string) {
    // Payment logic mixed in
  }
}
```

**Correct (focused services with single responsibility):**

```typescript
// Focused services with single responsibility
@Injectable()
export class UsersService {
  constructor(private userRepo: UserRepository) {}

  async create(dto: CreateUserDto): Promise<User> {
    return this.userRepo.save(dto);
  }

  async findById(id: string): Promise<User> {
    return this.userRepo.findOneOrFail({ where: { id } });
  }
}

@Injectable()
export class OrdersService {
  constructor(private orderRepo: OrderRepository) {}

  async create(userId: string, dto: CreateOrderDto): Promise<Order> {
    return this.orderRepo.save({ userId, ...dto });
  }

  async findByUser(userId: string): Promise<Order[]> {
    return this.orderRepo.find({ where: { userId } });
  }
}

@Injectable()
export class OrderStatsService {
  constructor(private orderRepo: OrderRepository) {}

  async calculateForUser(userId: string): Promise<OrderStats> {
    // Focused stats calculation
  }
}

// Orchestration in controller or dedicated orchestrator
@Controller('orders')
export class OrdersController {
  constructor(
    private orders: OrdersService,
    private payment: PaymentService,
    private notifications: NotificationService,
  ) {}

  @Post()
  async create(@CurrentUser() user: User, @Body() dto: CreateOrderDto) {
    const order = await this.orders.create(user.id, dto);
    await this.payment.charge(order);
    await this.notifications.sendOrderConfirmation(order);
    return order;
  }
}
```

Reference: [NestJS Providers](https://docs.nestjs.com/providers)

---

### 1.5 Use Event-Driven Architecture for Decoupling

**Impact: MEDIUM-HIGH** — Enables async processing and modularity

Use `@nestjs/event-emitter` for intra-service events and message brokers for inter-service communication. Events allow modules to react to changes without direct dependencies, improving modularity and enabling async processing.

**Incorrect (direct service coupling):**

```typescript
// Direct service coupling
@Injectable()
export class OrdersService {
  constructor(
    private inventoryService: InventoryService,
    private emailService: EmailService,
    private analyticsService: AnalyticsService,
    private notificationService: NotificationService,
    private loyaltyService: LoyaltyService,
  ) {}

  async createOrder(dto: CreateOrderDto): Promise<Order> {
    const order = await this.repo.save(dto);

    // Tight coupling - OrdersService knows about all consumers
    await this.inventoryService.reserve(order.items);
    await this.emailService.sendConfirmation(order);
    await this.analyticsService.track('order_created', order);
    await this.notificationService.push(order.userId, 'Order placed');
    await this.loyaltyService.addPoints(order.userId, order.total);

    // Adding new behavior requires modifying this service
    return order;
  }
}
```

**Correct (event-driven decoupling):**

```typescript
// Use EventEmitter for decoupling
import { EventEmitter2 } from '@nestjs/event-emitter';

// Define event
export class OrderCreatedEvent {
  constructor(
    public readonly orderId: string,
    public readonly userId: string,
    public readonly items: OrderItem[],
    public readonly total: number,
  ) {}
}

// Service emits events
@Injectable()
export class OrdersService {
  constructor(
    private eventEmitter: EventEmitter2,
    private repo: Repository<Order>,
  ) {}

  async createOrder(dto: CreateOrderDto): Promise<Order> {
    const order = await this.repo.save(dto);

    // Emit event - no knowledge of consumers
    this.eventEmitter.emit('order.created', new OrderCreatedEvent(order.id, order.userId, order.items, order.total));

    return order;
  }
}

// Listeners in separate modules
@Injectable()
export class InventoryListener {
  @OnEvent('order.created')
  async handleOrderCreated(event: OrderCreatedEvent): Promise<void> {
    await this.inventoryService.reserve(event.items);
  }
}

@Injectable()
export class EmailListener {
  @OnEvent('order.created')
  async handleOrderCreated(event: OrderCreatedEvent): Promise<void> {
    await this.emailService.sendConfirmation(event.orderId);
  }
}

@Injectable()
export class AnalyticsListener {
  @OnEvent('order.created')
  async handleOrderCreated(event: OrderCreatedEvent): Promise<void> {
    await this.analyticsService.track('order_created', {
      orderId: event.orderId,
      total: event.total,
    });
  }
}
```

Reference: [NestJS Events](https://docs.nestjs.com/techniques/events)

---

### 1.6 Use Repository Pattern for Data Access

**Impact: HIGH** — Decouples business logic from database

Create custom repositories to encapsulate complex queries and database logic. This keeps services focused on business logic, makes testing easier with mock repositories, and allows changing database implementations without affecting business code.

**Incorrect (complex queries in services):**

```typescript
// Complex queries in services
@Injectable()
export class UsersService {
  constructor(@InjectRepository(User) private repo: Repository<User>) {}

  async findActiveWithOrders(minOrders: number): Promise<User[]> {
    // Complex query logic mixed with business logic
    return this.repo
      .createQueryBuilder('user')
      .leftJoinAndSelect('user.orders', 'order')
      .where('user.isActive = :active', { active: true })
      .andWhere('user.deletedAt IS NULL')
      .groupBy('user.id')
      .having('COUNT(order.id) >= :min', { min: minOrders })
      .orderBy('user.createdAt', 'DESC')
      .getMany();
  }

  // Service becomes bloated with query logic
}
```

**Correct (custom repository with encapsulated queries):**

```typescript
// Custom repository with encapsulated queries
@Injectable()
export class UsersRepository {
  constructor(@InjectRepository(User) private repo: Repository<User>) {}

  async findById(id: string): Promise<User | null> {
    return this.repo.findOne({ where: { id } });
  }

  async findByEmail(email: string): Promise<User | null> {
    return this.repo.findOne({ where: { email } });
  }

  async findActiveWithMinOrders(minOrders: number): Promise<User[]> {
    return this.repo
      .createQueryBuilder('user')
      .leftJoinAndSelect('user.orders', 'order')
      .where('user.isActive = :active', { active: true })
      .andWhere('user.deletedAt IS NULL')
      .groupBy('user.id')
      .having('COUNT(order.id) >= :min', { min: minOrders })
      .orderBy('user.createdAt', 'DESC')
      .getMany();
  }

  async save(user: User): Promise<User> {
    return this.repo.save(user);
  }
}

// Clean service with business logic only
@Injectable()
export class UsersService {
  constructor(private usersRepo: UsersRepository) {}

  async getActiveUsersWithOrders(): Promise<User[]> {
    return this.usersRepo.findActiveWithMinOrders(1);
  }

  async create(dto: CreateUserDto): Promise<User> {
    const existing = await this.usersRepo.findByEmail(dto.email);
    if (existing) {
      throw new ConflictException('Email already registered');
    }

    const user = new User();
    user.email = dto.email;
    user.name = dto.name;
    return this.usersRepo.save(user);
  }
}
```

Reference: [Repository Pattern](https://martinfowler.com/eaaCatalog/repository.html)

---

## 2. Dependency Injection

**Section Impact: CRITICAL**

### 2.1 Avoid Service Locator Anti-Pattern

**Impact: HIGH** — Hides dependencies and breaks testability

Avoid using `ModuleRef.get()` or global containers to resolve dependencies at runtime. This hides dependencies, makes code harder to test, and breaks the benefits of dependency injection. Use constructor injection instead.

**Incorrect (service locator anti-pattern):**

```typescript
// Use ModuleRef to get dependencies dynamically
@Injectable()
export class OrdersService {
  constructor(private moduleRef: ModuleRef) {}

  async createOrder(dto: CreateOrderDto): Promise<Order> {
    // Dependencies are hidden - not visible in constructor
    const usersService = this.moduleRef.get(UsersService);
    const inventoryService = this.moduleRef.get(InventoryService);
    const paymentService = this.moduleRef.get(PaymentService);

    const user = await usersService.findOne(dto.userId);
    // ... rest of logic
  }
}

// Global singleton container
class ServiceContainer {
  private static instance: ServiceContainer;
  private services = new Map<string, any>();

  static getInstance(): ServiceContainer {
    if (!this.instance) {
      this.instance = new ServiceContainer();
    }
    return this.instance;
  }

  get<T>(key: string): T {
    return this.services.get(key);
  }
}
```

**Correct (constructor injection with explicit dependencies):**

```typescript
// Use constructor injection - dependencies are explicit
@Injectable()
export class OrdersService {
  constructor(
    private usersService: UsersService,
    private inventoryService: InventoryService,
    private paymentService: PaymentService,
  ) {}

  async createOrder(dto: CreateOrderDto): Promise<Order> {
    const user = await this.usersService.findOne(dto.userId);
    const inventory = await this.inventoryService.check(dto.items);
    // Dependencies are clear and testable
  }
}

// Easy to test with mocks
describe('OrdersService', () => {
  let service: OrdersService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        OrdersService,
        { provide: UsersService, useValue: mockUsersService },
        { provide: InventoryService, useValue: mockInventoryService },
        { provide: PaymentService, useValue: mockPaymentService },
      ],
    }).compile();

    service = module.get(OrdersService);
  });
});

// VALID: Factory pattern for dynamic instantiation
@Injectable()
export class HandlerFactory {
  constructor(private moduleRef: ModuleRef) {}

  getHandler(type: string): Handler {
    switch (type) {
      case 'email':
        return this.moduleRef.get(EmailHandler);
      case 'sms':
        return this.moduleRef.get(SmsHandler);
      default:
        return this.moduleRef.get(DefaultHandler);
    }
  }
}
```

Reference: [NestJS Module Reference](https://docs.nestjs.com/fundamentals/module-ref)

---

### 2.2 Apply Interface Segregation Principle

**Impact: HIGH** — Reduces coupling and improves testability by 30-50%

Clients should not be forced to depend on interfaces they don't use. In NestJS, this means keeping interfaces small and focused on specific capabilities rather than creating "fat" interfaces that bundle unrelated methods. When a service only needs to send emails, it shouldn't depend on an interface that also includes SMS, push notifications, and logging. Split large interfaces into role-based ones.

**Incorrect (fat interface forcing unused dependencies):**

```typescript
// Fat interface - forces all consumers to depend on everything
interface NotificationService {
  sendEmail(to: string, subject: string, body: string): Promise<void>;
  sendSms(phone: string, message: string): Promise<void>;
  sendPush(userId: string, notification: PushPayload): Promise<void>;
  sendSlack(channel: string, message: string): Promise<void>;
  logNotification(type: string, payload: any): Promise<void>;
  getDeliveryStatus(id: string): Promise<DeliveryStatus>;
  retryFailed(id: string): Promise<void>;
  scheduleNotification(dto: ScheduleDto): Promise<string>;
}

// Consumer only needs email, but must mock everything for tests
@Injectable()
export class OrdersService {
  constructor(
    private notifications: NotificationService, // Depends on 8 methods, uses 1
  ) {}

  async confirmOrder(order: Order): Promise<void> {
    await this.notifications.sendEmail(
      order.customer.email,
      'Order Confirmed',
      `Your order ${order.id} has been confirmed.`,
    );
  }
}

// Testing is painful - must mock unused methods
const mockNotificationService = {
  sendEmail: jest.fn(),
  sendSms: jest.fn(), // Never used, but required
  sendPush: jest.fn(), // Never used, but required
  sendSlack: jest.fn(), // Never used, but required
  logNotification: jest.fn(), // Never used, but required
  getDeliveryStatus: jest.fn(), // Never used, but required
  retryFailed: jest.fn(), // Never used, but required
  scheduleNotification: jest.fn(), // Never used, but required
};
```

**Correct (segregated interfaces by capability):**

```typescript
// Segregated interfaces - each focused on one capability
interface EmailSender {
  sendEmail(to: string, subject: string, body: string): Promise<void>;
}

interface SmsSender {
  sendSms(phone: string, message: string): Promise<void>;
}

interface PushSender {
  sendPush(userId: string, notification: PushPayload): Promise<void>;
}

interface NotificationLogger {
  logNotification(type: string, payload: any): Promise<void>;
}

interface NotificationScheduler {
  scheduleNotification(dto: ScheduleDto): Promise<string>;
}

// Implementation can implement multiple interfaces
@Injectable()
export class NotificationService implements EmailSender, SmsSender, PushSender {
  async sendEmail(to: string, subject: string, body: string): Promise<void> {
    // Email implementation
  }

  async sendSms(phone: string, message: string): Promise<void> {
    // SMS implementation
  }

  async sendPush(userId: string, notification: PushPayload): Promise<void> {
    // Push implementation
  }
}

// Or separate implementations
@Injectable()
export class SendGridEmailService implements EmailSender {
  async sendEmail(to: string, subject: string, body: string): Promise<void> {
    // SendGrid-specific implementation
  }
}

// Consumer depends only on what it needs
@Injectable()
export class OrdersService {
  constructor(
    @Inject(EMAIL_SENDER) private emailSender: EmailSender, // Minimal dependency
  ) {}

  async confirmOrder(order: Order): Promise<void> {
    await this.emailSender.sendEmail(
      order.customer.email,
      'Order Confirmed',
      `Your order ${order.id} has been confirmed.`,
    );
  }
}

// Testing is simple - only mock what's used
const mockEmailSender: EmailSender = {
  sendEmail: jest.fn(),
};

// Module registration with tokens
export const EMAIL_SENDER = Symbol('EMAIL_SENDER');
export const SMS_SENDER = Symbol('SMS_SENDER');

@Module({
  providers: [
    { provide: EMAIL_SENDER, useClass: SendGridEmailService },
    { provide: SMS_SENDER, useClass: TwilioSmsService },
  ],
  exports: [EMAIL_SENDER, SMS_SENDER],
})
export class NotificationModule {}
```

**Combining interfaces when needed:**

```typescript
// Sometimes a consumer legitimately needs multiple capabilities
interface EmailAndSmsSender extends EmailSender, SmsSender {}

// Or use intersection types
type MultiChannelSender = EmailSender & SmsSender & PushSender;

// Consumer that genuinely needs multiple channels
@Injectable()
export class AlertService {
  constructor(
    @Inject(MULTI_CHANNEL_SENDER)
    private sender: EmailSender & SmsSender,
  ) {}

  async sendCriticalAlert(user: User, message: string): Promise<void> {
    await Promise.all([
      this.sender.sendEmail(user.email, 'Critical Alert', message),
      this.sender.sendSms(user.phone, message),
    ]);
  }
}
```

Reference: [Interface Segregation Principle](https://en.wikipedia.org/wiki/Interface_segregation_principle)

---

### 2.3 Honor Liskov Substitution Principle

**Impact: HIGH** — Ensures implementations are truly interchangeable without breaking callers

Subtypes must be substitutable for their base types without altering program correctness. In NestJS with dependency injection, this means any implementation of an interface or abstract class must honor the contract completely. A mock payment service used in tests must behave like a real payment service (return similar shapes, handle errors the same way). Violating LSP causes subtle bugs when swapping implementations.

**Incorrect (implementation violates the contract):**

```typescript
// Base interface with clear contract
interface PaymentGateway {
  /**
   * Charges the specified amount.
   * @returns PaymentResult on success
   * @throws PaymentFailedException on payment failure
   */
  charge(amount: number, currency: string): Promise<PaymentResult>;
}

// Production implementation - follows the contract
@Injectable()
export class StripeService implements PaymentGateway {
  async charge(amount: number, currency: string): Promise<PaymentResult> {
    const response = await this.stripe.charges.create({ amount, currency });
    return { success: true, transactionId: response.id, amount };
  }
}

// Mock that violates LSP - different behavior!
@Injectable()
export class MockPaymentService implements PaymentGateway {
  async charge(amount: number, currency: string): Promise<PaymentResult> {
    // VIOLATION 1: Throws for valid input (contract says return PaymentResult)
    if (amount > 1000) {
      throw new Error('Mock does not support large amounts');
    }

    // VIOLATION 2: Returns null instead of PaymentResult
    if (currency !== 'USD') {
      return null as any; // Real service would convert or reject properly
    }

    // VIOLATION 3: Missing required field
    return { success: true } as PaymentResult; // Missing transactionId!
  }
}

// Consumer trusts the contract
@Injectable()
export class OrdersService {
  constructor(@Inject(PAYMENT_GATEWAY) private payment: PaymentGateway) {}

  async checkout(order: Order): Promise<void> {
    const result = await this.payment.charge(order.total, order.currency);
    // These fail with MockPaymentService:
    await this.saveTransaction(result.transactionId); // undefined!
    await this.sendReceipt(result); // might be null!
  }
}
```

**Correct (implementations honor the contract):**

```typescript
// Well-defined interface with documented behavior
interface PaymentGateway {
  /**
   * Charges the specified amount.
   * @param amount - Amount in smallest currency unit (cents)
   * @param currency - ISO 4217 currency code
   * @returns PaymentResult with transactionId, success status, and amount
   * @throws PaymentFailedException if charge is declined
   * @throws InvalidCurrencyException if currency is not supported
   */
  charge(amount: number, currency: string): Promise<PaymentResult>;

  /**
   * Refunds a previous charge.
   * @throws TransactionNotFoundException if transactionId is invalid
   */
  refund(transactionId: string, amount?: number): Promise<RefundResult>;
}

// Production implementation
@Injectable()
export class StripeService implements PaymentGateway {
  async charge(amount: number, currency: string): Promise<PaymentResult> {
    try {
      const response = await this.stripe.charges.create({ amount, currency });
      return {
        success: true,
        transactionId: response.id,
        amount: response.amount,
      };
    } catch (error) {
      if (error.type === 'card_error') {
        throw new PaymentFailedException(error.message);
      }
      throw error;
    }
  }

  async refund(transactionId: string, amount?: number): Promise<RefundResult> {
    // Implementation...
  }
}

// Mock that honors LSP - same contract, same behavior shape
@Injectable()
export class MockPaymentService implements PaymentGateway {
  private transactions = new Map<string, PaymentResult>();

  async charge(amount: number, currency: string): Promise<PaymentResult> {
    // Honor the contract: validate currency like real service would
    if (!['USD', 'EUR', 'GBP'].includes(currency)) {
      throw new InvalidCurrencyException(`Unsupported currency: ${currency}`);
    }

    // Simulate decline for specific test scenarios
    if (amount === 99999) {
      throw new PaymentFailedException('Card declined (test scenario)');
    }

    // Return same shape as production
    const result: PaymentResult = {
      success: true,
      transactionId: `mock_${Date.now()}_${Math.random().toString(36)}`,
      amount,
    };

    this.transactions.set(result.transactionId, result);
    return result;
  }

  async refund(transactionId: string, amount?: number): Promise<RefundResult> {
    // Honor the contract: throw if transaction not found
    if (!this.transactions.has(transactionId)) {
      throw new TransactionNotFoundException(transactionId);
    }

    return {
      success: true,
      refundId: `refund_${transactionId}`,
      amount: amount ?? this.transactions.get(transactionId)!.amount,
    };
  }
}

// Consumer can swap implementations safely
@Injectable()
export class OrdersService {
  constructor(@Inject(PAYMENT_GATEWAY) private payment: PaymentGateway) {}

  async checkout(order: Order): Promise<Order> {
    try {
      const result = await this.payment.charge(order.total, order.currency);
      // Works with both StripeService and MockPaymentService
      order.transactionId = result.transactionId;
      order.status = 'paid';
      return order;
    } catch (error) {
      if (error instanceof PaymentFailedException) {
        order.status = 'payment_failed';
        return order;
      }
      throw error;
    }
  }
}
```

**Testing LSP compliance:**

```typescript
// Shared test suite that any implementation must pass
function testPaymentGatewayContract(createGateway: () => PaymentGateway) {
  describe('PaymentGateway contract', () => {
    let gateway: PaymentGateway;

    beforeEach(() => {
      gateway = createGateway();
    });

    it('returns PaymentResult with all required fields', async () => {
      const result = await gateway.charge(1000, 'USD');
      expect(result).toHaveProperty('success');
      expect(result).toHaveProperty('transactionId');
      expect(result).toHaveProperty('amount');
      expect(typeof result.transactionId).toBe('string');
    });

    it('throws InvalidCurrencyException for unsupported currency', async () => {
      await expect(gateway.charge(1000, 'INVALID')).rejects.toThrow(InvalidCurrencyException);
    });

    it('throws TransactionNotFoundException for invalid refund', async () => {
      await expect(gateway.refund('nonexistent')).rejects.toThrow(TransactionNotFoundException);
    });
  });
}

// Run against all implementations
describe('StripeService', () => {
  testPaymentGatewayContract(() => new StripeService(mockStripeClient));
});

describe('MockPaymentService', () => {
  testPaymentGatewayContract(() => new MockPaymentService());
});
```

Reference: [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle)

---

### 2.4 Prefer Constructor Injection

**Impact: CRITICAL** — Required for proper DI and testing

Always use constructor injection over property injection. Constructor injection makes dependencies explicit, enables TypeScript type checking, ensures dependencies are available when the class is instantiated, and improves testability. This is required for proper DI, testing, and TypeScript support.

**Incorrect (property injection with hidden dependencies):**

```typescript
// Property injection - avoid unless necessary
@Injectable()
export class UsersService {
  @Inject()
  private userRepo: UserRepository; // Hidden dependency

  @Inject('CONFIG')
  private config: ConfigType; // Also hidden

  async findAll() {
    return this.userRepo.find();
  }
}

// Problems:
// 1. Dependencies not visible in constructor
// 2. Service can be instantiated without dependencies in tests
// 3. TypeScript can't enforce dependency types at instantiation
```

**Correct (constructor injection with explicit dependencies):**

```typescript
// Constructor injection - explicit and testable
@Injectable()
export class UsersService {
  constructor(
    private readonly userRepo: UserRepository,
    @Inject('CONFIG') private readonly config: ConfigType,
  ) {}

  async findAll(): Promise<User[]> {
    return this.userRepo.find();
  }
}

// Testing is straightforward
describe('UsersService', () => {
  let service: UsersService;
  let mockRepo: jest.Mocked<UserRepository>;

  beforeEach(() => {
    mockRepo = {
      find: jest.fn(),
      save: jest.fn(),
    } as any;

    service = new UsersService(mockRepo, { dbUrl: 'test' });
  });

  it('should find all users', async () => {
    mockRepo.find.mockResolvedValue([{ id: '1', name: 'Test' }]);
    const result = await service.findAll();
    expect(result).toHaveLength(1);
  });
});

// Only use property injection for optional dependencies
@Injectable()
export class LoggingService {
  @Optional()
  @Inject('ANALYTICS')
  private analytics?: AnalyticsService;

  log(message: string) {
    console.log(message);
    this.analytics?.track('log', message); // Optional enhancement
  }
}
```

Reference: [NestJS Providers](https://docs.nestjs.com/providers)

---

### 2.5 Understand Provider Scopes

**Impact: CRITICAL** — Prevents data leaks and performance issues

NestJS has three provider scopes: DEFAULT (singleton), REQUEST (per-request instance), and TRANSIENT (new instance for each injection). Most providers should be singletons. Request-scoped providers have performance implications as they bubble up through the dependency tree. Understanding scopes prevents memory leaks and incorrect data sharing.

**Incorrect (wrong scope usage):**

```typescript
// Request-scoped when not needed (performance hit)
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
  // This creates a new instance for EVERY request
  // All dependencies also become request-scoped
  async findAll() {
    return this.userRepo.find();
  }
}

// Singleton with mutable request state
@Injectable() // Default: singleton
export class RequestContextService {
  private userId: string; // DANGER: Shared across all requests!

  setUser(userId: string) {
    this.userId = userId; // Overwrites for all concurrent requests
  }

  getUser() {
    return this.userId; // Returns wrong user!
  }
}
```

**Correct (appropriate scope for each use case):**

```typescript
// Singleton for stateless services (default, most common)
@Injectable()
export class UsersService {
  constructor(private readonly userRepo: UserRepository) {}

  async findById(id: string): Promise<User> {
    return this.userRepo.findOne({ where: { id } });
  }
}

// Request-scoped ONLY when you need request context
@Injectable({ scope: Scope.REQUEST })
export class RequestContextService {
  private userId: string;

  setUser(userId: string) {
    this.userId = userId;
  }

  getUser(): string {
    return this.userId;
  }
}

// Better: Use NestJS built-in request context
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable({ scope: Scope.REQUEST })
export class AuditService {
  constructor(@Inject(REQUEST) private request: Request) {}

  log(action: string) {
    console.log(`User ${this.request.user?.id} performed ${action}`);
  }
}

// Best: Use ClsModule for async context (no scope bubble-up)
import { ClsService } from 'nestjs-cls';

@Injectable() // Stays singleton!
export class AuditService {
  constructor(private cls: ClsService) {}

  log(action: string) {
    const userId = this.cls.get('userId');
    console.log(`User ${userId} performed ${action}`);
  }
}
```

Reference: [NestJS Injection Scopes](https://docs.nestjs.com/fundamentals/injection-scopes)

---

### 2.6 Use Injection Tokens for Interfaces

**Impact: HIGH** — Enables interface-based DI at runtime

TypeScript interfaces are erased at compile time and can't be used as injection tokens. Use string tokens, symbols, or abstract classes when you want to inject implementations of interfaces. This enables swapping implementations for testing or different environments.

**Incorrect (interface can't be used as token):**

```typescript
// Interface can't be used as injection token
interface PaymentGateway {
  charge(amount: number): Promise<PaymentResult>;
}

@Injectable()
export class StripeService implements PaymentGateway {
  charge(amount: number) {
    /* ... */
  }
}

@Injectable()
export class OrdersService {
  // This WON'T work - PaymentGateway doesn't exist at runtime
  constructor(private payment: PaymentGateway) {}
}
```

**Correct (symbol tokens or abstract classes):**

```typescript
// Option 1: String/Symbol tokens (most flexible)
export const PAYMENT_GATEWAY = Symbol('PAYMENT_GATEWAY');

export interface PaymentGateway {
  charge(amount: number): Promise<PaymentResult>;
}

@Injectable()
export class StripeService implements PaymentGateway {
  async charge(amount: number): Promise<PaymentResult> {
    // Stripe implementation
  }
}

@Injectable()
export class MockPaymentService implements PaymentGateway {
  async charge(amount: number): Promise<PaymentResult> {
    return { success: true, id: 'mock-id' };
  }
}

// Module registration
@Module({
  providers: [
    {
      provide: PAYMENT_GATEWAY,
      useClass: process.env.NODE_ENV === 'test' ? MockPaymentService : StripeService,
    },
  ],
  exports: [PAYMENT_GATEWAY],
})
export class PaymentModule {}

// Injection
@Injectable()
export class OrdersService {
  constructor(@Inject(PAYMENT_GATEWAY) private payment: PaymentGateway) {}

  async createOrder(dto: CreateOrderDto) {
    await this.payment.charge(dto.amount);
  }
}

// Option 2: Abstract class (carries runtime type info)
export abstract class PaymentGateway {
  abstract charge(amount: number): Promise<PaymentResult>;
}

@Injectable()
export class StripeService extends PaymentGateway {
  async charge(amount: number): Promise<PaymentResult> {
    // Implementation
  }
}

// No @Inject needed with abstract class
@Injectable()
export class OrdersService {
  constructor(private payment: PaymentGateway) {}
}
```

Reference: [NestJS Custom Providers](https://docs.nestjs.com/fundamentals/custom-providers)

---

## 3. Error Handling

**Section Impact: HIGH**

### 3.1 Handle Async Errors Properly

**Impact: HIGH** — Prevents process crashes from unhandled rejections

NestJS automatically catches errors from async route handlers, but errors from background tasks, event handlers, and manually created promises can crash your application. Always handle async errors explicitly and use global handlers as a safety net.

**Incorrect (fire-and-forget without error handling):**

```typescript
// Fire-and-forget without error handling
@Injectable()
export class UsersService {
  async createUser(dto: CreateUserDto): Promise<User> {
    const user = await this.repo.save(dto);

    // Fire and forget - if this fails, error is unhandled!
    this.emailService.sendWelcome(user.email);

    return user;
  }
}

// Unhandled promise in event handler
@Injectable()
export class OrdersService {
  @OnEvent('order.created')
  handleOrderCreated(event: OrderCreatedEvent) {
    // This returns a promise but it's not awaited!
    this.processOrder(event);
    // Errors will crash the process
  }

  private async processOrder(event: OrderCreatedEvent): Promise<void> {
    await this.inventoryService.reserve(event.items);
    await this.notificationService.send(event.userId);
  }
}

// Missing try-catch in scheduled tasks
@Cron('0 0 * * *')
async dailyCleanup(): Promise<void> {
  await this.cleanupService.run();
  // If this throws, no error handling
}
```

**Correct (explicit async error handling):**

```typescript
// Handle fire-and-forget with explicit catch
@Injectable()
export class UsersService {
  private readonly logger = new Logger(UsersService.name);

  async createUser(dto: CreateUserDto): Promise<User> {
    const user = await this.repo.save(dto);

    // Explicitly catch and log errors
    this.emailService.sendWelcome(user.email).catch(error => {
      this.logger.error('Failed to send welcome email', error.stack);
      // Optionally queue for retry
    });

    return user;
  }
}

// Properly handle async event handlers
@Injectable()
export class OrdersService {
  private readonly logger = new Logger(OrdersService.name);

  @OnEvent('order.created')
  async handleOrderCreated(event: OrderCreatedEvent): Promise<void> {
    try {
      await this.processOrder(event);
    } catch (error) {
      this.logger.error('Failed to process order', { event, error });
      // Don't rethrow - would crash the process
      await this.deadLetterQueue.add('order.created', event);
    }
  }
}

// Safe scheduled tasks
@Injectable()
export class CleanupService {
  private readonly logger = new Logger(CleanupService.name);

  @Cron('0 0 * * *')
  async dailyCleanup(): Promise<void> {
    try {
      await this.cleanupService.run();
      this.logger.log('Daily cleanup completed');
    } catch (error) {
      this.logger.error('Daily cleanup failed', error.stack);
      // Alert or retry logic
    }
  }
}

// Global unhandled rejection handler in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const logger = new Logger('Bootstrap');

  process.on('unhandledRejection', (reason, promise) => {
    logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
  });

  process.on('uncaughtException', error => {
    logger.error('Uncaught Exception:', error);
    process.exit(1);
  });

  await app.listen(3000);
}
```

Reference: [Node.js Unhandled Rejections](https://nodejs.org/api/process.html#event-unhandledrejection)

---

### 3.2 Throw HTTP Exceptions from Services

**Impact: HIGH** — Keeps controllers thin and simplifies error handling

It's acceptable (and often preferable) to throw `HttpException` subclasses from services in HTTP applications. This keeps controllers thin and allows services to communicate appropriate error states. For truly layer-agnostic services, use domain exceptions that map to HTTP status codes.

**Incorrect (return error objects instead of throwing):**

```typescript
// Return error objects instead of throwing
@Injectable()
export class UsersService {
  async findById(id: string): Promise<{ user?: User; error?: string }> {
    const user = await this.repo.findOne({ where: { id } });
    if (!user) {
      return { error: 'User not found' }; // Controller must check this
    }
    return { user };
  }
}

@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string) {
    const result = await this.usersService.findById(id);
    if (result.error) {
      throw new NotFoundException(result.error);
    }
    return result.user;
  }
}
```

**Correct (throw exceptions directly from service):**

```typescript
// Throw exceptions directly from service
@Injectable()
export class UsersService {
  constructor(private readonly repo: UserRepository) {}

  async findById(id: string): Promise<User> {
    const user = await this.repo.findOne({ where: { id } });
    if (!user) {
      throw new NotFoundException(`User #${id} not found`);
    }
    return user;
  }

  async create(dto: CreateUserDto): Promise<User> {
    const existing = await this.repo.findOne({
      where: { email: dto.email },
    });
    if (existing) {
      throw new ConflictException('Email already registered');
    }
    return this.repo.save(dto);
  }

  async update(id: string, dto: UpdateUserDto): Promise<User> {
    const user = await this.findById(id); // Throws if not found
    Object.assign(user, dto);
    return this.repo.save(user);
  }
}

// Controller stays thin
@Controller('users')
export class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findById(id);
  }

  @Post()
  create(@Body() dto: CreateUserDto): Promise<User> {
    return this.usersService.create(dto);
  }
}

// For layer-agnostic services, use domain exceptions
export class EntityNotFoundException extends Error {
  constructor(
    public readonly entity: string,
    public readonly id: string,
  ) {
    super(`${entity} with ID "${id}" not found`);
  }
}

// Map to HTTP in exception filter
@Catch(EntityNotFoundException)
export class EntityNotFoundFilter implements ExceptionFilter {
  catch(exception: EntityNotFoundException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    response.status(404).json({
      statusCode: 404,
      message: exception.message,
      entity: exception.entity,
      id: exception.id,
    });
  }
}
```

Reference: [NestJS Exception Filters](https://docs.nestjs.com/exception-filters)

---

### 3.3 Use Exception Filters for Error Handling

**Impact: HIGH** — Consistent, centralized error handling

Never catch exceptions and manually format error responses in controllers. Use NestJS exception filters to handle errors consistently across your application. Create custom exception filters for specific error types and a global filter for unhandled exceptions.

**Incorrect (manual error handling in controllers):**

```typescript
// Manual error handling in controllers
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string, @Res() res: Response) {
    try {
      const user = await this.usersService.findById(id);
      if (!user) {
        return res.status(404).json({
          statusCode: 404,
          message: 'User not found',
        });
      }
      return res.json(user);
    } catch (error) {
      console.error(error);
      return res.status(500).json({
        statusCode: 500,
        message: 'Internal server error',
      });
    }
  }
}
```

**Correct (exception filters with consistent handling):**

```typescript
// Use built-in and custom exceptions
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    const user = await this.usersService.findById(id);
    if (!user) {
      throw new NotFoundException(`User #${id} not found`);
    }
    return user;
  }
}

// Custom domain exception
export class UserNotFoundException extends NotFoundException {
  constructor(userId: string) {
    super({
      statusCode: 404,
      error: 'Not Found',
      message: `User with ID "${userId}" not found`,
      code: 'USER_NOT_FOUND',
    });
  }
}

// Custom exception filter for domain errors
@Catch(DomainException)
export class DomainExceptionFilter implements ExceptionFilter {
  catch(exception: DomainException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const status = exception.getStatus?.() || 400;

    response.status(status).json({
      statusCode: status,
      code: exception.code,
      message: exception.message,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

// Global exception filter for unhandled errors
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  constructor(private readonly logger: Logger) {}

  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;

    const message = exception instanceof HttpException ? exception.message : 'Internal server error';

    this.logger.error(`${request.method} ${request.url}`, exception instanceof Error ? exception.stack : exception);

    response.status(status).json({
      statusCode: status,
      message,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

// Register globally in main.ts
app.useGlobalFilters(new AllExceptionsFilter(app.get(Logger)), new DomainExceptionFilter());

// Or via module
@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: AllExceptionsFilter,
    },
  ],
})
export class AppModule {}
```

Reference: [NestJS Exception Filters](https://docs.nestjs.com/exception-filters)

---

## 4. Security

**Section Impact: HIGH**

### 4.1 Implement Secure JWT Authentication

**Impact: CRITICAL** — Essential for secure APIs

Use `@nestjs/jwt` with `@nestjs/passport` for authentication. Store secrets securely, use appropriate token lifetimes, implement refresh tokens, and validate tokens properly. Never expose sensitive data in JWT payloads.

**Incorrect (insecure JWT implementation):**

```typescript
// Hardcode secrets
@Module({
  imports: [
    JwtModule.register({
      secret: 'my-secret-key', // Exposed in code
      signOptions: { expiresIn: '7d' }, // Too long
    }),
  ],
})
export class AuthModule {}

// Store sensitive data in JWT
async login(user: User): Promise<{ accessToken: string }> {
  const payload = {
    sub: user.id,
    email: user.email,
    password: user.password, // NEVER include password!
    ssn: user.ssn, // NEVER include sensitive data!
    isAdmin: user.isAdmin, // Can be tampered if not verified
  };
  return { accessToken: this.jwtService.sign(payload) };
}

// Skip token validation
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'my-secret',
    });
  }

  async validate(payload: any): Promise<any> {
    return payload; // No validation of user existence
  }
}
```

**Correct (secure JWT with refresh tokens):**

```typescript
// Secure JWT configuration
@Module({
  imports: [
    JwtModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        secret: config.get<string>('JWT_SECRET'),
        signOptions: {
          expiresIn: '15m', // Short-lived access tokens
          issuer: config.get<string>('JWT_ISSUER'),
          audience: config.get<string>('JWT_AUDIENCE'),
        },
      }),
    }),
    PassportModule.register({ defaultStrategy: 'jwt' }),
  ],
})
export class AuthModule {}

// Minimal JWT payload
@Injectable()
export class AuthService {
  async login(user: User): Promise<TokenResponse> {
    // Only include necessary, non-sensitive data
    const payload: JwtPayload = {
      sub: user.id,
      email: user.email,
      roles: user.roles,
      iat: Math.floor(Date.now() / 1000),
    };

    const accessToken = this.jwtService.sign(payload);
    const refreshToken = await this.createRefreshToken(user.id);

    return { accessToken, refreshToken, expiresIn: 900 };
  }

  private async createRefreshToken(userId: string): Promise<string> {
    const token = randomBytes(32).toString('hex');
    const hashedToken = await bcrypt.hash(token, 10);

    await this.refreshTokenRepo.save({
      userId,
      token: hashedToken,
      expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
    });

    return token;
  }
}

// Proper JWT strategy with validation
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private config: ConfigService,
    private usersService: UsersService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: config.get<string>('JWT_SECRET'),
      ignoreExpiration: false,
      issuer: config.get<string>('JWT_ISSUER'),
      audience: config.get<string>('JWT_AUDIENCE'),
    });
  }

  async validate(payload: JwtPayload): Promise<User> {
    // Verify user still exists and is active
    const user = await this.usersService.findById(payload.sub);

    if (!user || !user.isActive) {
      throw new UnauthorizedException('User not found or inactive');
    }

    // Verify token wasn't issued before password change
    if (user.passwordChangedAt) {
      const tokenIssuedAt = new Date(payload.iat * 1000);
      if (tokenIssuedAt < user.passwordChangedAt) {
        throw new UnauthorizedException('Token invalidated by password change');
      }
    }

    return user;
  }
}
```

Reference: [NestJS Authentication](https://docs.nestjs.com/security/authentication)

---

### 4.2 Implement Rate Limiting

**Impact: HIGH** — Protects against abuse and ensures fair resource usage

Use `@nestjs/throttler` to limit request rates per client. Apply different limits for different endpoints - stricter for auth endpoints, more relaxed for read operations. Consider using Redis for distributed rate limiting in clustered deployments.

**Incorrect (no rate limiting on sensitive endpoints):**

```typescript
// No rate limiting on sensitive endpoints
@Controller('auth')
export class AuthController {
  @Post('login')
  async login(@Body() dto: LoginDto): Promise<TokenResponse> {
    // Attackers can brute-force credentials
    return this.authService.login(dto);
  }

  @Post('forgot-password')
  async forgotPassword(@Body() dto: ForgotPasswordDto): Promise<void> {
    // Can be abused to spam users with emails
    return this.authService.sendResetEmail(dto.email);
  }
}

// Same limits for all endpoints
@UseGuards(ThrottlerGuard)
@Controller('api')
export class ApiController {
  @Get('public-data')
  async getPublic() {} // Should allow more requests

  @Post('process-payment')
  async payment() {} // Should be more restrictive
}
```

**Correct (configured throttler with endpoint-specific limits):**

```typescript
// Configure throttler globally with multiple limits
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';

@Module({
  imports: [
    ThrottlerModule.forRoot([
      {
        name: 'short',
        ttl: 1000, // 1 second
        limit: 3, // 3 requests per second
      },
      {
        name: 'medium',
        ttl: 10000, // 10 seconds
        limit: 20, // 20 requests per 10 seconds
      },
      {
        name: 'long',
        ttl: 60000, // 1 minute
        limit: 100, // 100 requests per minute
      },
    ]),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class AppModule {}

// Override limits per endpoint
@Controller('auth')
export class AuthController {
  @Post('login')
  @Throttle({ short: { limit: 5, ttl: 60000 } }) // 5 attempts per minute
  async login(@Body() dto: LoginDto): Promise<TokenResponse> {
    return this.authService.login(dto);
  }

  @Post('forgot-password')
  @Throttle({ short: { limit: 3, ttl: 3600000 } }) // 3 per hour
  async forgotPassword(@Body() dto: ForgotPasswordDto): Promise<void> {
    return this.authService.sendResetEmail(dto.email);
  }
}

// Skip throttling for certain routes
@Controller('health')
export class HealthController {
  @Get()
  @SkipThrottle()
  check(): string {
    return 'OK';
  }
}

// Custom throttle per user type
@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
  protected async getTracker(req: Request): Promise<string> {
    // Use user ID if authenticated, IP otherwise
    return req.user?.id || req.ip;
  }

  protected async getLimit(context: ExecutionContext): Promise<number> {
    const request = context.switchToHttp().getRequest();

    // Higher limits for authenticated users
    if (request.user) {
      return request.user.isPremium ? 1000 : 200;
    }

    return 50; // Anonymous users
  }
}
```

Reference: [NestJS Throttler](https://docs.nestjs.com/security/rate-limiting)

---

### 4.3 Sanitize Output to Prevent XSS

**Impact: HIGH** — XSS vulnerabilities can compromise user sessions and data

While NestJS APIs typically return JSON (which browsers don't execute), XSS risks exist when rendering HTML, storing user content, or when frontend frameworks improperly handle API responses. Sanitize user-generated content before storage and use proper Content-Type headers.

**Incorrect (storing raw HTML without sanitization):**

```typescript
// Store raw HTML from users
@Injectable()
export class CommentsService {
  async create(dto: CreateCommentDto): Promise<Comment> {
    // User can inject: <script>steal(document.cookie)</script>
    return this.repo.save({
      content: dto.content, // Raw, unsanitized
      authorId: dto.authorId,
    });
  }
}

// Return HTML without sanitization
@Controller('pages')
export class PagesController {
  @Get(':slug')
  @Header('Content-Type', 'text/html')
  async getPage(@Param('slug') slug: string): Promise<string> {
    const page = await this.pagesService.findBySlug(slug);
    // If page.content contains user input, XSS is possible
    return `<html><body>${page.content}</body></html>`;
  }
}

// Reflect user input in errors
@Get(':id')
async findOne(@Param('id') id: string): Promise<User> {
  const user = await this.repo.findOne({ where: { id } });
  if (!user) {
    // XSS if id contains malicious content and error is rendered
    throw new NotFoundException(`User ${id} not found`);
  }
  return user;
}
```

**Correct (sanitize content and use proper headers):**

```typescript
// Sanitize HTML content before storage
import * as sanitizeHtml from 'sanitize-html';

@Injectable()
export class CommentsService {
  private readonly sanitizeOptions: sanitizeHtml.IOptions = {
    allowedTags: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
    allowedAttributes: {
      a: ['href', 'title'],
    },
    allowedSchemes: ['http', 'https', 'mailto'],
  };

  async create(dto: CreateCommentDto): Promise<Comment> {
    return this.repo.save({
      content: sanitizeHtml(dto.content, this.sanitizeOptions),
      authorId: dto.authorId,
    });
  }
}

// Use validation pipe to strip HTML
import { Transform } from 'class-transformer';

export class CreatePostDto {
  @IsString()
  @MaxLength(1000)
  @Transform(({ value }) => sanitizeHtml(value, { allowedTags: [] }))
  title: string;

  @IsString()
  @Transform(({ value }) =>
    sanitizeHtml(value, {
      allowedTags: ['p', 'br', 'b', 'i', 'a'],
      allowedAttributes: { a: ['href'] },
    }),
  )
  content: string;
}

// Set proper Content-Type headers
@Controller('api')
export class ApiController {
  @Get('data')
  @Header('Content-Type', 'application/json')
  async getData(): Promise<DataResponse> {
    // JSON response - browser won't execute scripts
    return this.service.getData();
  }
}

// Sanitize error messages
@Get(':id')
async findOne(@Param('id', ParseUUIDPipe) id: string): Promise<User> {
  const user = await this.repo.findOne({ where: { id } });
  if (!user) {
    // UUID validation ensures safe format
    throw new NotFoundException('User not found');
  }
  return user;
}

// Use Helmet for CSP headers
import helmet from 'helmet';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.use(
    helmet({
      contentSecurityPolicy: {
        directives: {
          defaultSrc: ["'self'"],
          scriptSrc: ["'self'"],
          styleSrc: ["'self'", "'unsafe-inline'"],
          imgSrc: ["'self'", 'data:', 'https:'],
        },
      },
    }),
  );

  await app.listen(3000);
}
```

Reference: [OWASP XSS Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)

---

### 4.4 Use Guards for Authentication and Authorization

**Impact: HIGH** — Enforces access control before handlers execute

Guards determine whether a request should be handled based on authentication state, roles, permissions, or other conditions. They run after middleware but before pipes and interceptors, making them ideal for access control. Use guards instead of manual checks in controllers.

**Incorrect (manual auth checks in every handler):**

```typescript
// Manual auth checks in every handler
@Controller('admin')
export class AdminController {
  @Get('users')
  async getUsers(@Request() req) {
    if (!req.user) {
      throw new UnauthorizedException();
    }
    if (!req.user.roles.includes('admin')) {
      throw new ForbiddenException();
    }
    return this.adminService.getUsers();
  }

  @Delete('users/:id')
  async deleteUser(@Request() req, @Param('id') id: string) {
    if (!req.user) {
      throw new UnauthorizedException();
    }
    if (!req.user.roles.includes('admin')) {
      throw new ForbiddenException();
    }
    return this.adminService.deleteUser(id);
  }
}
```

**Correct (guards with declarative decorators):**

```typescript
// JWT Auth Guard
@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(
    private jwtService: JwtService,
    private reflector: Reflector,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    // Check for @Public() decorator
    const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [context.getHandler(), context.getClass()]);
    if (isPublic) return true;

    const request = context.switchToHttp().getRequest();
    const token = this.extractToken(request);

    if (!token) {
      throw new UnauthorizedException('No token provided');
    }

    try {
      request.user = await this.jwtService.verifyAsync(token);
      return true;
    } catch {
      throw new UnauthorizedException('Invalid token');
    }
  }

  private extractToken(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }
}

// Roles Guard
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>('roles', [context.getHandler(), context.getClass()]);

    if (!requiredRoles) return true;

    const { user } = context.switchToHttp().getRequest();
    return requiredRoles.some(role => user.roles?.includes(role));
  }
}

// Decorators
export const Public = () => SetMetadata('isPublic', true);
export const Roles = (...roles: Role[]) => SetMetadata('roles', roles);

// Register guards globally
@Module({
  providers: [
    { provide: APP_GUARD, useClass: JwtAuthGuard },
    { provide: APP_GUARD, useClass: RolesGuard },
  ],
})
export class AppModule {}

// Clean controller
@Controller('admin')
@Roles(Role.Admin) // Applied to all routes
export class AdminController {
  @Get('users')
  getUsers(): Promise<User[]> {
    return this.adminService.getUsers();
  }

  @Delete('users/:id')
  deleteUser(@Param('id') id: string): Promise<void> {
    return this.adminService.deleteUser(id);
  }

  @Public() // Override: no auth required
  @Get('health')
  health() {
    return { status: 'ok' };
  }
}
```

Reference: [NestJS Guards](https://docs.nestjs.com/guards)

---

### 4.5 Validate All Input with DTOs and Pipes

**Impact: HIGH** — First line of defense against attacks

Always validate incoming data using class-validator decorators on DTOs and the global ValidationPipe. Never trust user input. Validate all request bodies, query parameters, and route parameters before processing.

**Incorrect (trust raw input without validation):**

```typescript
// Trust raw input without validation
@Controller('users')
export class UsersController {
  @Post()
  create(@Body() body: any) {
    // body could contain anything - SQL injection, XSS, etc.
    return this.usersService.create(body);
  }

  @Get()
  findAll(@Query() query: any) {
    // query.limit could be "'; DROP TABLE users; --"
    return this.usersService.findAll(query.limit);
  }
}

// DTOs without validation decorators
export class CreateUserDto {
  name: string; // No validation
  email: string; // Could be "not-an-email"
  age: number; // Could be "abc" or -999
}
```

**Correct (validated DTOs with global ValidationPipe):**

```typescript
// Enable ValidationPipe globally in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true, // Strip unknown properties
      forbidNonWhitelisted: true, // Throw on unknown properties
      transform: true, // Auto-transform to DTO types
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
  );

  await app.listen(3000);
}

// Create well-validated DTOs
import {
  IsString,
  IsEmail,
  IsInt,
  Min,
  Max,
  IsOptional,
  MinLength,
  MaxLength,
  Matches,
  IsNotEmpty,
} from 'class-validator';
import { Transform, Type } from 'class-transformer';

export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  @MinLength(2)
  @MaxLength(100)
  @Transform(({ value }) => value?.trim())
  name: string;

  @IsEmail()
  @Transform(({ value }) => value?.toLowerCase().trim())
  email: string;

  @IsInt()
  @Min(0)
  @Max(150)
  age: number;

  @IsString()
  @MinLength(8)
  @MaxLength(100)
  @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, {
    message: 'Password must contain uppercase, lowercase, and number',
  })
  password: string;
}

// Query DTO with defaults and transformation
export class FindUsersQueryDto {
  @IsOptional()
  @IsString()
  @MaxLength(100)
  search?: string;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(100)
  limit: number = 20;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(0)
  offset: number = 0;
}

// Param validation
export class UserIdParamDto {
  @IsUUID('4')
  id: string;
}

@Controller('users')
export class UsersController {
  @Post()
  create(@Body() dto: CreateUserDto): Promise<User> {
    // dto is guaranteed to be valid
    return this.usersService.create(dto);
  }

  @Get()
  findAll(@Query() query: FindUsersQueryDto): Promise<User[]> {
    // query.limit is a number, query.search is sanitized
    return this.usersService.findAll(query);
  }

  @Get(':id')
  findOne(@Param() params: UserIdParamDto): Promise<User> {
    // params.id is a valid UUID
    return this.usersService.findById(params.id);
  }
}
```

Reference: [NestJS Validation](https://docs.nestjs.com/techniques/validation)

---

## 5. Performance

**Section Impact: HIGH**

### 5.1 Use Async Lifecycle Hooks Correctly

**Impact: HIGH** — Improper async handling blocks application startup

NestJS lifecycle hooks (`onModuleInit`, `onApplicationBootstrap`, etc.) support async operations. However, misusing them can block application startup or cause race conditions. Understand the lifecycle order and use hooks appropriately.

**Incorrect (fire-and-forget async without await):**

```typescript
// Fire-and-forget async without await
@Injectable()
export class DatabaseService implements OnModuleInit {
  onModuleInit() {
    // This runs but doesn't block - app starts before DB is ready!
    this.connect();
  }

  private async connect() {
    await this.pool.connect();
    console.log('Database connected');
  }
}

// Heavy blocking operations in constructor
@Injectable()
export class ConfigService {
  private config: Config;

  constructor() {
    // BLOCKS entire module instantiation synchronously
    this.config = fs.readFileSync('config.json');
  }
}
```

**Correct (return promises from async hooks):**

```typescript
// Return promise from async hooks
@Injectable()
export class DatabaseService implements OnModuleInit {
  private pool: Pool;

  async onModuleInit(): Promise<void> {
    // NestJS waits for this to complete before continuing
    await this.pool.connect();
    console.log('Database connected');
  }

  async onModuleDestroy(): Promise<void> {
    // Clean up resources on shutdown
    await this.pool.end();
    console.log('Database disconnected');
  }
}

// Use onApplicationBootstrap for cross-module dependencies
@Injectable()
export class CacheWarmerService implements OnApplicationBootstrap {
  constructor(
    private cache: CacheService,
    private products: ProductsService,
  ) {}

  async onApplicationBootstrap(): Promise<void> {
    // All modules are initialized, safe to warm cache
    const products = await this.products.findPopular();
    await this.cache.warmup(products);
  }
}

// Heavy init in async hooks, not constructor
@Injectable()
export class ConfigService implements OnModuleInit {
  private config: Config;

  constructor() {
    // Keep constructor synchronous and fast
  }

  async onModuleInit(): Promise<void> {
    // Async loading in lifecycle hook
    this.config = await this.loadConfig();
  }

  private async loadConfig(): Promise<Config> {
    const file = await fs.promises.readFile('config.json');
    return JSON.parse(file.toString());
  }

  get<T>(key: string): T {
    return this.config[key];
  }
}

// Enable shutdown hooks in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableShutdownHooks(); // Enable SIGTERM/SIGINT handling
  await app.listen(3000);
}
```

Reference: [NestJS Lifecycle Events](https://docs.nestjs.com/fundamentals/lifecycle-events)

---

### 5.2 Use Lazy Loading for Large Modules

**Impact: MEDIUM** — Improves startup time for large applications

NestJS supports lazy-loading modules, which defers initialization until first use. This is valuable for large applications where some features are rarely used, serverless deployments where cold start time matters, or when certain modules have heavy initialization costs.

**Incorrect (loading everything eagerly):**

```typescript
// Load everything eagerly in a large app
@Module({
  imports: [
    UsersModule,
    OrdersModule,
    PaymentsModule,
    ReportsModule, // Heavy, rarely used
    AnalyticsModule, // Heavy, rarely used
    AdminModule, // Only admins use this
    LegacyModule, // Migration module, rarely used
    BulkImportModule, // Used once a month
  ],
})
export class AppModule {}

// All modules initialize at startup, even if never used
// Slow cold starts in serverless
// Memory wasted on unused modules
```

**Correct (lazy load rarely-used modules):**

```typescript
// Use LazyModuleLoader for optional modules
import { LazyModuleLoader } from '@nestjs/core';

@Injectable()
export class ReportsService {
  constructor(private lazyModuleLoader: LazyModuleLoader) {}

  async generateReport(type: string): Promise<Report> {
    // Load module only when needed
    const { ReportsModule } = await import('./reports/reports.module');
    const moduleRef = await this.lazyModuleLoader.load(() => ReportsModule);

    const reportsService = moduleRef.get(ReportsGeneratorService);
    return reportsService.generate(type);
  }
}

// Lazy load admin features with caching
@Injectable()
export class AdminService {
  private adminModule: ModuleRef | null = null;

  constructor(private lazyModuleLoader: LazyModuleLoader) {}

  private async getAdminModule(): Promise<ModuleRef> {
    if (!this.adminModule) {
      const { AdminModule } = await import('./admin/admin.module');
      this.adminModule = await this.lazyModuleLoader.load(() => AdminModule);
    }
    return this.adminModule;
  }

  async runAdminTask(task: string): Promise<void> {
    const moduleRef = await this.getAdminModule();
    const taskRunner = moduleRef.get(AdminTaskRunner);
    await taskRunner.run(task);
  }
}

// Reusable lazy loader service
@Injectable()
export class ModuleLoaderService {
  private loadedModules = new Map<string, ModuleRef>();

  constructor(private lazyModuleLoader: LazyModuleLoader) {}

  async load<T>(key: string, importFn: () => Promise<{ default: Type<T> } | Type<T>>): Promise<ModuleRef> {
    if (!this.loadedModules.has(key)) {
      const module = await importFn();
      const moduleType = 'default' in module ? module.default : module;
      const moduleRef = await this.lazyModuleLoader.load(() => moduleType);
      this.loadedModules.set(key, moduleRef);
    }
    return this.loadedModules.get(key)!;
  }
}

// Preload modules in background after startup
@Injectable()
export class ModulePreloader implements OnApplicationBootstrap {
  constructor(private lazyModuleLoader: LazyModuleLoader) {}

  async onApplicationBootstrap(): Promise<void> {
    setTimeout(async () => {
      await this.preloadModule(() => import('./reports/reports.module'));
    }, 5000); // 5 seconds after startup
  }

  private async preloadModule(importFn: () => Promise<any>): Promise<void> {
    try {
      const module = await importFn();
      const moduleType = module.default || Object.values(module)[0];
      await this.lazyModuleLoader.load(() => moduleType);
    } catch (error) {
      console.warn('Failed to preload module', error);
    }
  }
}
```

Reference: [NestJS Lazy Loading Modules](https://docs.nestjs.com/fundamentals/lazy-loading-modules)

---

### 5.3 Optimize Database Queries

**Impact: HIGH** — Database queries are typically the largest source of latency

Select only needed columns, use proper indexes, avoid over-fetching relations, and consider query performance when designing your data access. Most API slowness traces back to inefficient database queries.

**Incorrect (over-fetching data and missing indexes):**

```typescript
// Select everything when you need few fields
@Injectable()
export class UsersService {
  async findAllEmails(): Promise<string[]> {
    const users = await this.repo.find();
    // Fetches ALL columns for ALL users
    return users.map(u => u.email);
  }

  async getUserSummary(id: string): Promise<UserSummary> {
    const user = await this.repo.findOne({
      where: { id },
      relations: ['posts', 'posts.comments', 'posts.comments.author', 'followers'],
    });
    // Over-fetches massive relation tree
    return { name: user.name, postCount: user.posts.length };
  }
}

// No indexes on frequently queried columns
@Entity()
export class Order {
  @Column()
  userId: string; // No index - full table scan on every lookup

  @Column()
  status: string; // No index - slow status filtering
}
```

**Correct (select only needed data with proper indexes):**

```typescript
// Select only needed columns
@Injectable()
export class UsersService {
  async findAllEmails(): Promise<string[]> {
    const users = await this.repo.find({
      select: ['email'], // Only fetch email column
    });
    return users.map(u => u.email);
  }

  // Use QueryBuilder for complex selections
  async getUserSummary(id: string): Promise<UserSummary> {
    return this.repo
      .createQueryBuilder('user')
      .select('user.name', 'name')
      .addSelect('COUNT(post.id)', 'postCount')
      .leftJoin('user.posts', 'post')
      .where('user.id = :id', { id })
      .groupBy('user.id')
      .getRawOne();
  }

  // Fetch relations only when needed
  async getFullProfile(id: string): Promise<User> {
    return this.repo.findOne({
      where: { id },
      relations: ['posts'], // Only immediate relation
      select: {
        id: true,
        name: true,
        email: true,
        posts: {
          id: true,
          title: true,
        },
      },
    });
  }
}

// Add indexes on frequently queried columns
@Entity()
@Index(['userId'])
@Index(['status'])
@Index(['createdAt'])
@Index(['userId', 'status']) // Composite index for common query pattern
export class Order {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  userId: string;

  @Column()
  status: string;

  @CreateDateColumn()
  createdAt: Date;
}

// Always paginate large datasets
@Injectable()
export class OrdersService {
  async findAll(page = 1, limit = 20): Promise<PaginatedResult<Order>> {
    const [items, total] = await this.repo.findAndCount({
      skip: (page - 1) * limit,
      take: limit,
      order: { createdAt: 'DESC' },
    });

    return {
      items,
      meta: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit),
      },
    };
  }
}
```

Reference: [TypeORM Query Builder](https://typeorm.io/select-query-builder)

---

### 5.4 Use Caching Strategically

**Impact: HIGH** — Dramatically reduces database load and response times

Implement caching for expensive operations, frequently accessed data, and external API calls. Use NestJS CacheModule with appropriate TTLs and cache invalidation strategies. Don't cache everything - focus on high-impact areas.

**Incorrect (no caching or caching everything):**

```typescript
// No caching for expensive, repeated queries
@Injectable()
export class ProductsService {
  async getPopular(): Promise<Product[]> {
    // Runs complex aggregation query EVERY request
    return this.productsRepo
      .createQueryBuilder('p')
      .leftJoin('p.orders', 'o')
      .select('p.*, COUNT(o.id) as orderCount')
      .groupBy('p.id')
      .orderBy('orderCount', 'DESC')
      .limit(20)
      .getMany();
  }
}

// Cache everything without thought
@Injectable()
export class UsersService {
  @CacheKey('users')
  @CacheTTL(3600)
  @UseInterceptors(CacheInterceptor)
  async findAll(): Promise<User[]> {
    // Caching user list for 1 hour is wrong if data changes frequently
    return this.usersRepo.find();
  }
}
```

**Correct (strategic caching with proper invalidation):**

```typescript
// Setup caching module
@Module({
  imports: [
    CacheModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        stores: [new KeyvRedis(config.get('REDIS_URL'))],
        ttl: 60 * 1000, // Default 60s
      }),
    }),
  ],
})
export class AppModule {}

// Manual caching for granular control
@Injectable()
export class ProductsService {
  constructor(
    @Inject(CACHE_MANAGER) private cache: Cache,
    private productsRepo: ProductRepository,
  ) {}

  async getPopular(): Promise<Product[]> {
    const cacheKey = 'products:popular';

    // Try cache first
    const cached = await this.cache.get<Product[]>(cacheKey);
    if (cached) return cached;

    // Cache miss - fetch and cache
    const products = await this.fetchPopularProducts();
    await this.cache.set(cacheKey, products, 5 * 60 * 1000); // 5 min TTL
    return products;
  }

  // Invalidate cache on changes
  async updateProduct(id: string, dto: UpdateProductDto): Promise<Product> {
    const product = await this.productsRepo.save({ id, ...dto });
    await this.cache.del('products:popular'); // Invalidate
    return product;
  }
}

// Decorator-based caching with auto-interceptor
@Controller('categories')
@UseInterceptors(CacheInterceptor)
export class CategoriesController {
  @Get()
  @CacheTTL(30 * 60 * 1000) // 30 minutes - categories rarely change
  findAll(): Promise<Category[]> {
    return this.categoriesService.findAll();
  }

  @Get(':id')
  @CacheTTL(60 * 1000) // 1 minute
  @CacheKey('category')
  findOne(@Param('id') id: string): Promise<Category> {
    return this.categoriesService.findOne(id);
  }
}

// Event-based cache invalidation
@Injectable()
export class CacheInvalidationService {
  constructor(@Inject(CACHE_MANAGER) private cache: Cache) {}

  @OnEvent('product.created')
  @OnEvent('product.updated')
  @OnEvent('product.deleted')
  async invalidateProductCaches(event: ProductEvent) {
    await Promise.all([this.cache.del('products:popular'), this.cache.del(`product:${event.productId}`)]);
  }
}
```

Reference: [NestJS Caching](https://docs.nestjs.com/techniques/caching)

---

## 6. Testing

**Section Impact: MEDIUM-HIGH**

### 6.1 Use Supertest for E2E Testing

**Impact: HIGH** — Validates the full request/response cycle

End-to-end tests use Supertest to make real HTTP requests against your NestJS application. They test the full stack including middleware, guards, pipes, and interceptors. E2E tests catch integration issues that unit tests miss.

**Incorrect (no proper E2E setup or teardown):**

```typescript
// Only unit test controllers
describe('UsersController', () => {
  it('should return users', async () => {
    const service = { findAll: jest.fn().mockResolvedValue([]) };
    const controller = new UsersController(service as any);

    const result = await controller.findAll();

    expect(result).toEqual([]);
    // Doesn't test: routes, guards, pipes, serialization
  });
});

// E2E tests without proper setup/teardown
describe('Users API', () => {
  it('should create user', async () => {
    const app = await NestFactory.create(AppModule);
    // No proper initialization
    // No cleanup after test
    // Hits real database
  });
});
```

**Correct (proper E2E setup with Supertest):**

```typescript
// Proper E2E test setup
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';

describe('UsersController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();

    // Apply same config as production
    app.useGlobalPipes(
      new ValidationPipe({
        whitelist: true,
        transform: true,
        forbidNonWhitelisted: true,
      }),
    );

    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  describe('/users (POST)', () => {
    it('should create a user', () => {
      return request(app.getHttpServer())
        .post('/users')
        .send({ name: 'John', email: 'john@test.com' })
        .expect(201)
        .expect(res => {
          expect(res.body).toHaveProperty('id');
          expect(res.body.name).toBe('John');
          expect(res.body.email).toBe('john@test.com');
        });
    });

    it('should return 400 for invalid email', () => {
      return request(app.getHttpServer())
        .post('/users')
        .send({ name: 'John', email: 'invalid-email' })
        .expect(400)
        .expect(res => {
          expect(res.body.message).toContain('email');
        });
    });
  });

  describe('/users/:id (GET)', () => {
    it('should return 404 for non-existent user', () => {
      return request(app.getHttpServer()).get('/users/non-existent-id').expect(404);
    });
  });
});

// Testing with authentication
describe('Protected Routes (e2e)', () => {
  let app: INestApplication;
  let authToken: string;

  beforeAll(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
    await app.init();

    // Get auth token
    const loginResponse = await request(app.getHttpServer())
      .post('/auth/login')
      .send({ email: 'test@test.com', password: 'password' });

    authToken = loginResponse.body.accessToken;
  });

  it('should return 401 without token', () => {
    return request(app.getHttpServer()).get('/users/me').expect(401);
  });

  it('should return user profile with valid token', () => {
    return request(app.getHttpServer())
      .get('/users/me')
      .set('Authorization', `Bearer ${authToken}`)
      .expect(200)
      .expect(res => {
        expect(res.body.email).toBe('test@test.com');
      });
  });
});

// Database isolation for E2E tests
describe('Orders API (e2e)', () => {
  let app: INestApplication;
  let dataSource: DataSource;

  beforeAll(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          envFilePath: '.env.test', // Test database config
        }),
        AppModule,
      ],
    }).compile();

    app = moduleFixture.createNestApplication();
    dataSource = moduleFixture.get(DataSource);
    await app.init();
  });

  beforeEach(async () => {
    // Clean database between tests
    await dataSource.synchronize(true);
  });

  afterAll(async () => {
    await dataSource.destroy();
    await app.close();
  });
});
```

Reference: [NestJS E2E Testing](https://docs.nestjs.com/fundamentals/testing#end-to-end-testing)

---

### 6.2 Mock External Services in Tests

**Impact: HIGH** — Ensures fast, reliable, deterministic tests

Never call real external services (APIs, databases, message queues) in unit tests. Mock them to ensure tests are fast, deterministic, and don't incur costs. Use realistic mock data and test edge cases like timeouts and errors.

**Incorrect (calling real APIs and databases):**

```typescript
// Call real APIs in tests
describe('PaymentService', () => {
  it('should process payment', async () => {
    const service = new PaymentService(new StripeClient(realApiKey));
    // Hits real Stripe API!
    const result = await service.charge('tok_visa', 1000);
    // Slow, costs money, flaky
  });
});

// Use real database
describe('UsersService', () => {
  beforeEach(async () => {
    await connection.query('DELETE FROM users'); // Modifies real DB
  });

  it('should create user', async () => {
    const user = await service.create({ email: 'test@test.com' });
    // Side effects on shared database
  });
});

// Incomplete mocks
const mockHttpService = {
  get: jest.fn().mockResolvedValue({ data: {} }),
  // Missing error scenarios, missing other methods
};
```

**Correct (mock all external dependencies):**

```typescript
// Mock HTTP service properly
describe('WeatherService', () => {
  let service: WeatherService;
  let httpService: jest.Mocked<HttpService>;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        WeatherService,
        {
          provide: HttpService,
          useValue: {
            get: jest.fn(),
            post: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get(WeatherService);
    httpService = module.get(HttpService);
  });

  it('should return weather data', async () => {
    const mockResponse = {
      data: { temperature: 72, humidity: 45 },
      status: 200,
      statusText: 'OK',
      headers: {},
      config: {},
    };

    httpService.get.mockReturnValue(of(mockResponse));

    const result = await service.getWeather('NYC');

    expect(result).toEqual({ temperature: 72, humidity: 45 });
  });

  it('should handle API timeout', async () => {
    httpService.get.mockReturnValue(throwError(() => new Error('ETIMEDOUT')));

    await expect(service.getWeather('NYC')).rejects.toThrow('Weather service unavailable');
  });

  it('should handle rate limiting', async () => {
    httpService.get.mockReturnValue(
      throwError(() => ({
        response: { status: 429, data: { message: 'Rate limited' } },
      })),
    );

    await expect(service.getWeather('NYC')).rejects.toThrow(TooManyRequestsException);
  });
});

// Mock repository instead of database
describe('UsersService', () => {
  let service: UsersService;
  let repo: jest.Mocked<Repository<User>>;

  beforeEach(async () => {
    const mockRepo = {
      find: jest.fn(),
      findOne: jest.fn(),
      save: jest.fn(),
      delete: jest.fn(),
      createQueryBuilder: jest.fn(),
    };

    const module = await Test.createTestingModule({
      providers: [UsersService, { provide: getRepositoryToken(User), useValue: mockRepo }],
    }).compile();

    service = module.get(UsersService);
    repo = module.get(getRepositoryToken(User));
  });

  it('should find user by id', async () => {
    const mockUser = { id: '1', name: 'John', email: 'john@test.com' };
    repo.findOne.mockResolvedValue(mockUser);

    const result = await service.findById('1');

    expect(result).toEqual(mockUser);
    expect(repo.findOne).toHaveBeenCalledWith({ where: { id: '1' } });
  });
});

// Create mock factory for complex SDKs
function createMockStripe(): jest.Mocked<Stripe> {
  return {
    paymentIntents: {
      create: jest.fn(),
      retrieve: jest.fn(),
      confirm: jest.fn(),
      cancel: jest.fn(),
    },
    customers: {
      create: jest.fn(),
      retrieve: jest.fn(),
    },
  } as any;
}

// Mock time for time-dependent tests
describe('TokenService', () => {
  beforeEach(() => {
    jest.useFakeTimers();
    jest.setSystemTime(new Date('2024-01-15'));
  });

  afterEach(() => {
    jest.useRealTimers();
  });

  it('should expire token after 1 hour', async () => {
    const token = await service.createToken();

    // Fast-forward time
    jest.advanceTimersByTime(61 * 60 * 1000);

    expect(await service.isValid(token)).toBe(false);
  });
});
```

Reference: [Jest Mocking](https://jestjs.io/docs/mock-functions)

---

### 6.3 Use Testing Module for Unit Tests

**Impact: HIGH** — Enables proper isolated testing with mocked dependencies

Use `@nestjs/testing` module to create isolated test environments with mocked dependencies. This ensures your tests run fast, don't depend on external services, and properly test your business logic in isolation.

**Incorrect (manual instantiation bypassing DI):**

```typescript
// Instantiate services manually without DI
describe('UsersService', () => {
  it('should create user', async () => {
    // Manual instantiation bypasses DI
    const repo = new UserRepository(); // Real repo!
    const service = new UsersService(repo);

    const user = await service.create({ name: 'Test' });
    // This hits the real database!
  });
});

// Test implementation details
describe('UsersController', () => {
  it('should call service', async () => {
    const service = { create: jest.fn() };
    const controller = new UsersController(service as any);

    await controller.create({ name: 'Test' });

    expect(service.create).toHaveBeenCalled(); // Tests implementation, not behavior
  });
});
```

**Correct (use Test.createTestingModule with mocked dependencies):**

```typescript
// Use Test.createTestingModule for proper DI
import { Test, TestingModule } from '@nestjs/testing';

describe('UsersService', () => {
  let service: UsersService;
  let repo: jest.Mocked<UserRepository>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UsersService,
        {
          provide: UserRepository,
          useValue: {
            save: jest.fn(),
            findOne: jest.fn(),
            find: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get<UsersService>(UsersService);
    repo = module.get(UserRepository);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('create', () => {
    it('should save and return user', async () => {
      const dto = { name: 'John', email: 'john@test.com' };
      const expectedUser = { id: '1', ...dto };

      repo.save.mockResolvedValue(expectedUser);

      const result = await service.create(dto);

      expect(result).toEqual(expectedUser);
      expect(repo.save).toHaveBeenCalledWith(dto);
    });

    it('should throw on duplicate email', async () => {
      repo.findOne.mockResolvedValue({ id: '1', email: 'test@test.com' });

      await expect(service.create({ name: 'Test', email: 'test@test.com' })).rejects.toThrow(ConflictException);
    });
  });

  describe('findById', () => {
    it('should return user when found', async () => {
      const user = { id: '1', name: 'John' };
      repo.findOne.mockResolvedValue(user);

      const result = await service.findById('1');

      expect(result).toEqual(user);
    });

    it('should throw NotFoundException when not found', async () => {
      repo.findOne.mockResolvedValue(null);

      await expect(service.findById('999')).rejects.toThrow(NotFoundException);
    });
  });
});

// Testing guards and interceptors
describe('RolesGuard', () => {
  let guard: RolesGuard;
  let reflector: Reflector;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [RolesGuard, Reflector],
    }).compile();

    guard = module.get<RolesGuard>(RolesGuard);
    reflector = module.get<Reflector>(Reflector);
  });

  it('should allow when no roles required', () => {
    const context = createMockExecutionContext({ user: { roles: [] } });
    jest.spyOn(reflector, 'getAllAndOverride').mockReturnValue(undefined);

    expect(guard.canActivate(context)).toBe(true);
  });

  it('should allow admin for admin-only route', () => {
    const context = createMockExecutionContext({ user: { roles: ['admin'] } });
    jest.spyOn(reflector, 'getAllAndOverride').mockReturnValue(['admin']);

    expect(guard.canActivate(context)).toBe(true);
  });
});

function createMockExecutionContext(request: Partial<Request>): ExecutionContext {
  return {
    switchToHttp: () => ({
      getRequest: () => request,
    }),
    getHandler: () => jest.fn(),
    getClass: () => jest.fn(),
  } as ExecutionContext;
}
```

Reference: [NestJS Testing](https://docs.nestjs.com/fundamentals/testing)

---

## 7. Database & ORM

**Section Impact: MEDIUM-HIGH**

### 7.1 Avoid N+1 Query Problems

**Impact: HIGH** — N+1 queries are one of the most common performance killers

N+1 queries occur when you fetch a list of entities, then make an additional query for each entity to load related data. Use eager loading with `relations`, query builder joins, or DataLoader to batch queries efficiently.

**Incorrect (lazy loading in loops causes N+1):**

```typescript
// Lazy loading in loops causes N+1
@Injectable()
export class OrdersService {
  async getOrdersWithItems(userId: string): Promise<Order[]> {
    const orders = await this.orderRepo.find({ where: { userId } });
    // 1 query for orders

    for (const order of orders) {
      // N additional queries - one per order!
      order.items = await this.itemRepo.find({ where: { orderId: order.id } });
    }

    return orders;
  }
}

// Accessing lazy relations without loading
@Controller('users')
export class UsersController {
  @Get()
  async findAll(): Promise<User[]> {
    const users = await this.userRepo.find();
    // If User.posts is lazy-loaded, serializing triggers N queries
    return users; // Each user.posts access = 1 query
  }
}
```

**Correct (use relations for eager loading):**

```typescript
// Use relations option for eager loading
@Injectable()
export class OrdersService {
  async getOrdersWithItems(userId: string): Promise<Order[]> {
    // Single query with JOIN
    return this.orderRepo.find({
      where: { userId },
      relations: ['items', 'items.product'],
    });
  }
}

// Use QueryBuilder for complex joins
@Injectable()
export class UsersService {
  async getUsersWithPostCounts(): Promise<UserWithPostCount[]> {
    return this.userRepo
      .createQueryBuilder('user')
      .leftJoin('user.posts', 'post')
      .select('user.id', 'id')
      .addSelect('user.name', 'name')
      .addSelect('COUNT(post.id)', 'postCount')
      .groupBy('user.id')
      .getRawMany();
  }

  async getActiveUsersWithPosts(): Promise<User[]> {
    return this.userRepo
      .createQueryBuilder('user')
      .leftJoinAndSelect('user.posts', 'post')
      .leftJoinAndSelect('post.comments', 'comment')
      .where('user.isActive = :active', { active: true })
      .andWhere('post.status = :status', { status: 'published' })
      .getMany();
  }
}

// Use find options for specific fields
async getOrderSummaries(userId: string): Promise<OrderSummary[]> {
  return this.orderRepo.find({
    where: { userId },
    relations: ['items'],
    select: {
      id: true,
      total: true,
      status: true,
      items: {
        id: true,
        quantity: true,
        price: true,
      },
    },
  });
}

// Use DataLoader for GraphQL to batch and cache queries
import DataLoader from 'dataloader';

@Injectable({ scope: Scope.REQUEST })
export class PostsLoader {
  constructor(private postsService: PostsService) {}

  readonly batchPosts = new DataLoader<string, Post[]>(async (userIds) => {
    // Single query for all users' posts
    const posts = await this.postsService.findByUserIds([...userIds]);

    // Group by userId
    const postsMap = new Map<string, Post[]>();
    for (const post of posts) {
      const userPosts = postsMap.get(post.userId) || [];
      userPosts.push(post);
      postsMap.set(post.userId, userPosts);
    }

    // Return in same order as input
    return userIds.map((id) => postsMap.get(id) || []);
  });
}

// In resolver
@ResolveField()
async posts(@Parent() user: User): Promise<Post[]> {
  // DataLoader batches multiple calls into single query
  return this.postsLoader.batchPosts.load(user.id);
}

// Enable query logging in development to detect N+1
TypeOrmModule.forRoot({
  logging: ['query', 'error'],
  logger: 'advanced-console',
});
```

Reference: [TypeORM Relations](https://typeorm.io/relations)

---

### 7.2 Use Database Migrations

**Impact: HIGH** — Enables safe, repeatable database schema changes

Never use `synchronize: true` in production. Use migrations for all schema changes. Migrations provide version control for your database, enable safe rollbacks, and ensure consistency across all environments.

**Incorrect (using synchronize or manual SQL):**

```typescript
// Use synchronize in production
TypeOrmModule.forRoot({
  type: 'postgres',
  synchronize: true, // DANGEROUS in production!
  // Can drop columns, tables, or data
});

// Manual SQL in production
@Injectable()
export class DatabaseService {
  async addColumn(): Promise<void> {
    await this.dataSource.query('ALTER TABLE users ADD COLUMN age INT');
    // No version control, no rollback, inconsistent across envs
  }
}

// Modify entities without migration
@Entity()
export class User {
  @Column()
  email: string;

  @Column() // Added without migration
  newField: string; // Will crash in production if synchronize is false
}
```

**Correct (use migrations for all schema changes):**

```typescript
// Configure TypeORM for migrations
// data-source.ts
export const dataSource = new DataSource({
  type: 'postgres',
  host: process.env.DB_HOST,
  port: parseInt(process.env.DB_PORT),
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  entities: ['dist/**/*.entity.js'],
  migrations: ['dist/migrations/*.js'],
  synchronize: false, // Always false in production
  migrationsRun: true, // Run migrations on startup
});

// app.module.ts
TypeOrmModule.forRootAsync({
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    type: 'postgres',
    host: config.get('DB_HOST'),
    synchronize: config.get('NODE_ENV') === 'development', // Only in dev
    migrations: ['dist/migrations/*.js'],
    migrationsRun: true,
  }),
});

// migrations/1705312800000-AddUserAge.ts
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddUserAge1705312800000 implements MigrationInterface {
  name = 'AddUserAge1705312800000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    // Add column with default to handle existing rows
    await queryRunner.query(`
      ALTER TABLE "users" ADD "age" integer DEFAULT 0
    `);

    // Add index for frequently queried columns
    await queryRunner.query(`
      CREATE INDEX "IDX_users_age" ON "users" ("age")
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    // Always implement down for rollback
    await queryRunner.query(`DROP INDEX "IDX_users_age"`);
    await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "age"`);
  }
}

// Safe column rename (two-step)
export class RenameNameToFullName1705312900000 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    // Step 1: Add new column
    await queryRunner.query(`
      ALTER TABLE "users" ADD "full_name" varchar(255)
    `);

    // Step 2: Copy data
    await queryRunner.query(`
      UPDATE "users" SET "full_name" = "name"
    `);

    // Step 3: Add NOT NULL constraint
    await queryRunner.query(`
      ALTER TABLE "users" ALTER COLUMN "full_name" SET NOT NULL
    `);

    // Step 4: Drop old column (after verifying app works)
    await queryRunner.query(`
      ALTER TABLE "users" DROP COLUMN "name"
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`ALTER TABLE "users" ADD "name" varchar(255)`);
    await queryRunner.query(`UPDATE "users" SET "name" = "full_name"`);
    await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "full_name"`);
  }
}
```

Reference: [TypeORM Migrations](https://typeorm.io/migrations)

---

### 7.3 Use Transactions for Multi-Step Operations

**Impact: HIGH** — Ensures data consistency in multi-step operations

When multiple database operations must succeed or fail together, wrap them in a transaction. This prevents partial updates that leave your data in an inconsistent state. Use TypeORM's transaction APIs or the DataSource query runner for complex scenarios.

**Incorrect (multiple saves without transaction):**

```typescript
// Multiple saves without transaction
@Injectable()
export class OrdersService {
  async createOrder(userId: string, items: OrderItem[]): Promise<Order> {
    // If any step fails, data is inconsistent
    const order = await this.orderRepo.save({ userId, status: 'pending' });

    for (const item of items) {
      await this.orderItemRepo.save({ orderId: order.id, ...item });
      await this.inventoryRepo.decrement({ productId: item.productId }, 'stock', item.quantity);
    }

    await this.paymentService.charge(order.id);
    // If payment fails, order and inventory are already modified!

    return order;
  }
}
```

**Correct (use DataSource.transaction for automatic rollback):**

```typescript
// Use DataSource.transaction() for automatic rollback
@Injectable()
export class OrdersService {
  constructor(private dataSource: DataSource) {}

  async createOrder(userId: string, items: OrderItem[]): Promise<Order> {
    return this.dataSource.transaction(async manager => {
      // All operations use the same transactional manager
      const order = await manager.save(Order, { userId, status: 'pending' });

      for (const item of items) {
        await manager.save(OrderItem, { orderId: order.id, ...item });
        await manager.decrement(Inventory, { productId: item.productId }, 'stock', item.quantity);
      }

      // If this throws, everything rolls back
      await this.paymentService.chargeWithManager(manager, order.id);

      return order;
    });
  }
}

// QueryRunner for manual transaction control
@Injectable()
export class TransferService {
  constructor(private dataSource: DataSource) {}

  async transfer(fromId: string, toId: string, amount: number): Promise<void> {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      // Debit source account
      await queryRunner.manager.decrement(Account, { id: fromId }, 'balance', amount);

      // Verify sufficient funds
      const source = await queryRunner.manager.findOne(Account, {
        where: { id: fromId },
      });
      if (source.balance < 0) {
        throw new BadRequestException('Insufficient funds');
      }

      // Credit destination account
      await queryRunner.manager.increment(Account, { id: toId }, 'balance', amount);

      // Log the transaction
      await queryRunner.manager.save(TransactionLog, {
        fromId,
        toId,
        amount,
        timestamp: new Date(),
      });

      await queryRunner.commitTransaction();
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }
}

// Repository method with transaction support
@Injectable()
export class UsersRepository {
  constructor(
    @InjectRepository(User) private repo: Repository<User>,
    private dataSource: DataSource,
  ) {}

  async createWithProfile(userData: CreateUserDto, profileData: CreateProfileDto): Promise<User> {
    return this.dataSource.transaction(async manager => {
      const user = await manager.save(User, userData);
      await manager.save(Profile, { ...profileData, userId: user.id });
      return user;
    });
  }
}
```

Reference: [TypeORM Transactions](https://typeorm.io/transactions)

---

## 8. API Design

**Section Impact: MEDIUM**

### 8.1 Use DTOs and Serialization for API Responses

**Impact: MEDIUM** — Response DTOs prevent accidental data exposure and ensure consistency

Never return entity objects directly from controllers. Use response DTOs with class-transformer's `@Exclude()` and `@Expose()` decorators to control exactly what data is sent to clients. This prevents accidental exposure of sensitive fields and provides a stable API contract.

**Incorrect (returning entities directly or manual spreading):**

```typescript
// Return entities directly
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findById(id);
    // Returns: { id, email, passwordHash, ssn, internalNotes, ... }
    // Exposes sensitive data!
  }
}

// Manual object spreading (error-prone)
@Get(':id')
async findOne(@Param('id') id: string) {
  const user = await this.usersService.findById(id);
  return {
    id: user.id,
    email: user.email,
    name: user.name,
    // Easy to forget to exclude sensitive fields
    // Hard to maintain across endpoints
  };
}
```

**Correct (use class-transformer with @Exclude and response DTOs):**

```typescript
// Enable class-transformer globally
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
  await app.listen(3000);
}

// Entity with serialization control
@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  email: string;

  @Column()
  name: string;

  @Column()
  @Exclude() // Never include in responses
  passwordHash: string;

  @Column({ nullable: true })
  @Exclude()
  ssn: string;

  @Column({ default: false })
  @Exclude({ toPlainOnly: true }) // Exclude from response, allow in requests
  isAdmin: boolean;

  @CreateDateColumn()
  createdAt: Date;

  @Column()
  @Exclude()
  internalNotes: string;
}

// Now returning entity is safe
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findById(id);
    // Returns: { id, email, name, createdAt }
    // Sensitive fields excluded automatically
  }
}

// For different response shapes, use explicit DTOs
export class UserResponseDto {
  @Expose()
  id: string;

  @Expose()
  email: string;

  @Expose()
  name: string;

  @Expose()
  @Transform(({ obj }) => obj.posts?.length || 0)
  postCount: number;

  constructor(partial: Partial<User>) {
    Object.assign(this, partial);
  }
}

export class UserDetailResponseDto extends UserResponseDto {
  @Expose()
  createdAt: Date;

  @Expose()
  @Type(() => PostResponseDto)
  posts: PostResponseDto[];
}

// Controller with explicit DTOs
@Controller('users')
export class UsersController {
  @Get()
  @SerializeOptions({ type: UserResponseDto })
  async findAll(): Promise<UserResponseDto[]> {
    const users = await this.usersService.findAll();
    return users.map(u => plainToInstance(UserResponseDto, u));
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<UserDetailResponseDto> {
    const user = await this.usersService.findByIdWithPosts(id);
    return plainToInstance(UserDetailResponseDto, user, {
      excludeExtraneousValues: true,
    });
  }
}

// Groups for conditional serialization
export class UserDto {
  @Expose()
  id: string;

  @Expose()
  name: string;

  @Expose({ groups: ['admin'] })
  email: string;

  @Expose({ groups: ['admin'] })
  createdAt: Date;

  @Expose({ groups: ['admin', 'owner'] })
  settings: UserSettings;
}

@Controller('users')
export class UsersController {
  @Get()
  @SerializeOptions({ groups: ['public'] })
  async findAllPublic(): Promise<UserDto[]> {
    // Returns: { id, name }
  }

  @Get('admin')
  @UseGuards(AdminGuard)
  @SerializeOptions({ groups: ['admin'] })
  async findAllAdmin(): Promise<UserDto[]> {
    // Returns: { id, name, email, createdAt }
  }

  @Get('me')
  @SerializeOptions({ groups: ['owner'] })
  async getProfile(@CurrentUser() user: User): Promise<UserDto> {
    // Returns: { id, name, settings }
  }
}
```

Reference: [NestJS Serialization](https://docs.nestjs.com/techniques/serialization)

---

### 8.2 Use Interceptors for Cross-Cutting Concerns

**Impact: MEDIUM-HIGH** — Interceptors provide clean separation for cross-cutting logic

Interceptors can transform responses, add logging, handle caching, and measure performance without polluting your business logic. They wrap the route handler execution, giving you access to both the request and response streams.

**Incorrect (logging and transformation in every method):**

```typescript
// Logging in every controller method
@Controller('users')
export class UsersController {
  @Get()
  async findAll(): Promise<User[]> {
    const start = Date.now();
    this.logger.log('findAll called');

    const users = await this.usersService.findAll();

    this.logger.log(`findAll completed in ${Date.now() - start}ms`);
    return users;
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    const start = Date.now();
    this.logger.log(`findOne called with id: ${id}`);

    const user = await this.usersService.findOne(id);

    this.logger.log(`findOne completed in ${Date.now() - start}ms`);
    return user;
  }
  // Repeated in every method!
}

// Manual response wrapping
@Get()
async findAll(): Promise<{ data: User[]; meta: Meta }> {
  const users = await this.usersService.findAll();
  return {
    data: users,
    meta: { timestamp: new Date(), count: users.length },
  };
}
```

**Correct (use interceptors for cross-cutting concerns):**

```typescript
// Logging interceptor
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  private readonly logger = new Logger('HTTP');

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const { method, url, body } = request;
    const now = Date.now();

    return next.handle().pipe(
      tap({
        next: (data) => {
          const response = context.switchToHttp().getResponse();
          this.logger.log(
            `${method} ${url} ${response.statusCode} - ${Date.now() - now}ms`,
          );
        },
        error: (error) => {
          this.logger.error(
            `${method} ${url} ${error.status || 500} - ${Date.now() - now}ms`,
            error.stack,
          );
        },
      }),
    );
  }
}

// Response transformation interceptor
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
  intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
    return next.handle().pipe(
      map((data) => ({
        data,
        meta: {
          timestamp: new Date().toISOString(),
          path: context.switchToHttp().getRequest().url,
        },
      })),
    );
  }
}

// Timeout interceptor
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(5000),
      catchError((err) => {
        if (err instanceof TimeoutError) {
          throw new RequestTimeoutException('Request timed out');
        }
        throw err;
      }),
    );
  }
}

// Apply globally or per-controller
@Module({
  providers: [
    { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
    { provide: APP_INTERCEPTOR, useClass: TransformInterceptor },
  ],
})
export class AppModule {}

// Or per-controller
@Controller('users')
@UseInterceptors(LoggingInterceptor)
export class UsersController {
  @Get()
  async findAll(): Promise<User[]> {
    // Clean business logic only
    return this.usersService.findAll();
  }
}

// Custom cache interceptor with TTL
@Injectable()
export class HttpCacheInterceptor implements NestInterceptor {
  constructor(
    private cacheManager: Cache,
    private reflector: Reflector,
  ) {}

  async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
    const request = context.switchToHttp().getRequest();

    // Only cache GET requests
    if (request.method !== 'GET') {
      return next.handle();
    }

    const cacheKey = this.generateKey(request);
    const ttl = this.reflector.get<number>('cacheTTL', context.getHandler()) || 300;

    const cached = await this.cacheManager.get(cacheKey);
    if (cached) {
      return of(cached);
    }

    return next.handle().pipe(
      tap((response) => {
        this.cacheManager.set(cacheKey, response, ttl);
      }),
    );
  }

  private generateKey(request: Request): string {
    return `cache:${request.url}:${JSON.stringify(request.query)}`;
  }
}

// Usage with custom TTL
@Get()
@SetMetadata('cacheTTL', 600)
@UseInterceptors(HttpCacheInterceptor)
async findAll(): Promise<User[]> {
  return this.usersService.findAll();
}

// Error mapping interceptor
@Injectable()
export class ErrorMappingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      catchError((error) => {
        if (error instanceof EntityNotFoundError) {
          throw new NotFoundException(error.message);
        }
        if (error instanceof QueryFailedError) {
          if (error.message.includes('duplicate')) {
            throw new ConflictException('Resource already exists');
          }
        }
        throw error;
      }),
    );
  }
}
```

Reference: [NestJS Interceptors](https://docs.nestjs.com/interceptors)

---

### 8.3 Use Pipes for Input Transformation

**Impact: MEDIUM** — Pipes ensure clean, validated data reaches your handlers

Use built-in pipes like `ParseIntPipe`, `ParseUUIDPipe`, and `DefaultValuePipe` for common transformations. Create custom pipes for business-specific transformations. Pipes separate validation/transformation logic from controllers.

**Incorrect (manual type parsing in handlers):**

```typescript
// Manual type parsing in handlers
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    // Manual validation in every handler
    const uuid = id.trim();
    if (!isUUID(uuid)) {
      throw new BadRequestException('Invalid UUID');
    }
    return this.usersService.findOne(uuid);
  }

  @Get()
  async findAll(
    @Query('page') page: string,
    @Query('limit') limit: string,
  ): Promise<User[]> {
    // Manual parsing and defaults
    const pageNum = parseInt(page) || 1;
    const limitNum = parseInt(limit) || 10;
    return this.usersService.findAll(pageNum, limitNum);
  }
}

// Type coercion without validation
@Get()
async search(@Query('price') price: string): Promise<Product[]> {
  const priceNum = +price; // NaN if invalid, no error
  return this.productsService.findByPrice(priceNum);
}
```

**Correct (use built-in and custom pipes):**

```typescript
// Use built-in pipes for common transformations
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id', ParseUUIDPipe) id: string): Promise<User> {
    // id is guaranteed to be a valid UUID
    return this.usersService.findOne(id);
  }

  @Get()
  async findAll(
    @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
    @Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
  ): Promise<User[]> {
    // Automatic defaults and type conversion
    return this.usersService.findAll(page, limit);
  }

  @Get('by-status/:status')
  async findByStatus(
    @Param('status', new ParseEnumPipe(UserStatus)) status: UserStatus,
  ): Promise<User[]> {
    return this.usersService.findByStatus(status);
  }
}

// Custom pipe for business logic
@Injectable()
export class ParseDatePipe implements PipeTransform<string, Date> {
  transform(value: string): Date {
    const date = new Date(value);
    if (isNaN(date.getTime())) {
      throw new BadRequestException('Invalid date format');
    }
    return date;
  }
}

@Get('reports')
async getReports(
  @Query('from', ParseDatePipe) from: Date,
  @Query('to', ParseDatePipe) to: Date,
): Promise<Report[]> {
  return this.reportsService.findBetween(from, to);
}

// Custom transformation pipes
@Injectable()
export class NormalizeEmailPipe implements PipeTransform<string, string> {
  transform(value: string): string {
    if (!value) return value;
    return value.trim().toLowerCase();
  }
}

// Parse comma-separated values
@Injectable()
export class ParseArrayPipe implements PipeTransform<string, string[]> {
  transform(value: string): string[] {
    if (!value) return [];
    return value.split(',').map((v) => v.trim()).filter(Boolean);
  }
}

@Get('products')
async findProducts(
  @Query('ids', ParseArrayPipe) ids: string[],
  @Query('email', NormalizeEmailPipe) email: string,
): Promise<Product[]> {
  // ids is already an array, email is normalized
  return this.productsService.findByIds(ids);
}

// Sanitize HTML input
@Injectable()
export class SanitizeHtmlPipe implements PipeTransform<string, string> {
  transform(value: string): string {
    if (!value) return value;
    return sanitizeHtml(value, { allowedTags: [] });
  }
}

// Global validation pipe with transformation
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true, // Strip non-DTO properties
    transform: true, // Auto-transform to DTO types
    transformOptions: {
      enableImplicitConversion: true, // Convert query strings to numbers
    },
    forbidNonWhitelisted: true, // Throw on extra properties
  }),
);

// DTO with transformation decorators
export class FindProductsDto {
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  page?: number = 1;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(100)
  limit?: number = 10;

  @IsOptional()
  @Transform(({ value }) => value?.toLowerCase())
  @IsString()
  search?: string;

  @IsOptional()
  @Transform(({ value }) => value?.split(','))
  @IsArray()
  @IsString({ each: true })
  categories?: string[];
}

@Get()
async findAll(@Query() dto: FindProductsDto): Promise<Product[]> {
  // dto is already transformed and validated
  return this.productsService.findAll(dto);
}

// Pipe error customization
@Injectable()
export class CustomParseIntPipe extends ParseIntPipe {
  constructor() {
    super({
      exceptionFactory: (error) =>
        new BadRequestException(`${error} must be a valid integer`),
    });
  }
}

// Or use options on built-in pipes
@Get(':id')
async findOne(
  @Param(
    'id',
    new ParseIntPipe({
      errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE,
      exceptionFactory: () => new NotAcceptableException('ID must be numeric'),
    }),
  )
  id: number,
): Promise<Item> {
  return this.itemsService.findOne(id);
}
```

Reference: [NestJS Pipes](https://docs.nestjs.com/pipes)

---

### 8.4 Use API Versioning for Breaking Changes

**Impact: MEDIUM** — Versioning allows you to evolve APIs without breaking existing clients

Use NestJS built-in versioning when making breaking changes to your API. Choose a versioning strategy (URI, header, or media type) and apply it consistently. This allows old clients to continue working while new clients use updated endpoints.

**Incorrect (breaking changes without versioning):**

```typescript
// Breaking changes without versioning
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    // Original response: { id, name, email }
    // Later changed to: { id, firstName, lastName, emailAddress }
    // Old clients break!
    return this.usersService.findOne(id);
  }
}

// Manual versioning in routes
@Controller('v1/users')
export class UsersV1Controller {}

@Controller('v2/users')
export class UsersV2Controller {}
// Inconsistent, error-prone, hard to maintain
```

**Correct (use NestJS built-in versioning):**

```typescript
// Enable versioning in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // URI versioning: /v1/users, /v2/users
  app.enableVersioning({
    type: VersioningType.URI,
    defaultVersion: '1',
  });

  // Or header versioning: X-API-Version: 1
  app.enableVersioning({
    type: VersioningType.HEADER,
    header: 'X-API-Version',
    defaultVersion: '1',
  });

  // Or media type: Accept: application/json;v=1
  app.enableVersioning({
    type: VersioningType.MEDIA_TYPE,
    key: 'v=',
    defaultVersion: '1',
  });

  await app.listen(3000);
}

// Version-specific controllers
@Controller('users')
@Version('1')
export class UsersV1Controller {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<UserV1Response> {
    const user = await this.usersService.findOne(id);
    // V1 response format
    return {
      id: user.id,
      name: user.name,
      email: user.email,
    };
  }
}

@Controller('users')
@Version('2')
export class UsersV2Controller {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<UserV2Response> {
    const user = await this.usersService.findOne(id);
    // V2 response format with breaking changes
    return {
      id: user.id,
      firstName: user.firstName,
      lastName: user.lastName,
      emailAddress: user.email,
      createdAt: user.createdAt,
    };
  }
}

// Per-route versioning - different versions for different routes
@Controller('users')
export class UsersController {
  @Get()
  @Version('1')
  findAllV1(): Promise<UserV1Response[]> {
    return this.usersService.findAllV1();
  }

  @Get()
  @Version('2')
  findAllV2(): Promise<UserV2Response[]> {
    return this.usersService.findAllV2();
  }

  @Get(':id')
  @Version(['1', '2']) // Same handler for multiple versions
  findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findOne(id);
  }

  @Post()
  @Version(VERSION_NEUTRAL) // Available in all versions
  create(@Body() dto: CreateUserDto): Promise<User> {
    return this.usersService.create(dto);
  }
}

// Shared service with version-specific logic
@Injectable()
export class UsersService {
  async findOne(id: string, version: string): Promise<any> {
    const user = await this.repo.findOne({ where: { id } });

    if (version === '1') {
      return this.toV1Response(user);
    }
    return this.toV2Response(user);
  }

  private toV1Response(user: User): UserV1Response {
    return {
      id: user.id,
      name: `${user.firstName} ${user.lastName}`,
      email: user.email,
    };
  }

  private toV2Response(user: User): UserV2Response {
    return {
      id: user.id,
      firstName: user.firstName,
      lastName: user.lastName,
      emailAddress: user.email,
      createdAt: user.createdAt,
    };
  }
}

// Controller extracts version
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string, @Headers('X-API-Version') version: string = '1'): Promise<any> {
    return this.usersService.findOne(id, version);
  }
}

// Deprecation strategy - mark old versions as deprecated
@Controller('users')
@Version('1')
@UseInterceptors(DeprecationInterceptor)
export class UsersV1Controller {
  // All V1 routes will include deprecation warning
}

@Injectable()
export class DeprecationInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const response = context.switchToHttp().getResponse();
    response.setHeader('Deprecation', 'true');
    response.setHeader('Sunset', 'Sat, 1 Jan 2025 00:00:00 GMT');
    response.setHeader('Link', '</v2/users>; rel="successor-version"');

    return next.handle();
  }
}
```

Reference: [NestJS Versioning](https://docs.nestjs.com/techniques/versioning)

---

## 9. Microservices

**Section Impact: MEDIUM**

### 9.1 Implement Health Checks for Microservices

**Impact: MEDIUM-HIGH** — Health checks enable orchestrators to manage service lifecycle

Implement liveness and readiness probes using `@nestjs/terminus`. Liveness checks determine if the service should be restarted. Readiness checks determine if the service can accept traffic. Proper health checks enable Kubernetes and load balancers to route traffic correctly.

**Incorrect (simple ping that doesn't check dependencies):**

```typescript
// Simple ping that doesn't check dependencies
@Controller('health')
export class HealthController {
  @Get()
  check(): string {
    return 'OK'; // Service might be unhealthy but returns OK
  }
}

// Health check that blocks on slow dependencies
@Controller('health')
export class HealthController {
  @Get()
  async check(): Promise<string> {
    // If database is slow, health check times out
    await this.userRepo.findOne({ where: { id: '1' } });
    await this.redis.ping();
    await this.externalApi.healthCheck();
    return 'OK';
  }
}
```

**Correct (use @nestjs/terminus for comprehensive health checks):**

```typescript
// Use @nestjs/terminus for comprehensive health checks
import {
  HealthCheckService,
  HttpHealthIndicator,
  TypeOrmHealthIndicator,
  HealthCheck,
  DiskHealthIndicator,
  MemoryHealthIndicator,
} from '@nestjs/terminus';

@Controller('health')
export class HealthController {
  constructor(
    private health: HealthCheckService,
    private http: HttpHealthIndicator,
    private db: TypeOrmHealthIndicator,
    private disk: DiskHealthIndicator,
    private memory: MemoryHealthIndicator,
  ) {}

  // Liveness probe - is the service alive?
  @Get('live')
  @HealthCheck()
  liveness() {
    return this.health.check([
      // Basic checks only
      () => this.memory.checkHeap('memory_heap', 200 * 1024 * 1024), // 200MB
    ]);
  }

  // Readiness probe - can the service handle traffic?
  @Get('ready')
  @HealthCheck()
  readiness() {
    return this.health.check([
      () => this.db.pingCheck('database'),
      () =>
        this.http.pingCheck('redis', 'http://redis:6379', { timeout: 1000 }),
      () =>
        this.disk.checkStorage('disk', { path: '/', thresholdPercent: 0.9 }),
    ]);
  }

  // Deep health check for debugging
  @Get('deep')
  @HealthCheck()
  deepCheck() {
    return this.health.check([
      () => this.db.pingCheck('database'),
      () => this.memory.checkHeap('memory_heap', 200 * 1024 * 1024),
      () => this.memory.checkRSS('memory_rss', 300 * 1024 * 1024),
      () =>
        this.disk.checkStorage('disk', { path: '/', thresholdPercent: 0.9 }),
      () =>
        this.http.pingCheck('external-api', 'https://api.example.com/health'),
    ]);
  }
}

// Custom indicator for business-specific health
@Injectable()
export class QueueHealthIndicator extends HealthIndicator {
  constructor(private queueService: QueueService) {
    super();
  }

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    const queueStats = await this.queueService.getStats();

    const isHealthy = queueStats.failedCount < 100;
    const result = this.getStatus(key, isHealthy, {
      waiting: queueStats.waitingCount,
      active: queueStats.activeCount,
      failed: queueStats.failedCount,
    });

    if (!isHealthy) {
      throw new HealthCheckError('Queue unhealthy', result);
    }

    return result;
  }
}

// Redis health indicator
@Injectable()
export class RedisHealthIndicator extends HealthIndicator {
  constructor(@InjectRedis() private redis: Redis) {
    super();
  }

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    try {
      const pong = await this.redis.ping();
      return this.getStatus(key, pong === 'PONG');
    } catch (error) {
      throw new HealthCheckError('Redis check failed', this.getStatus(key, false));
    }
  }
}

// Use custom indicators
@Get('ready')
@HealthCheck()
readiness() {
  return this.health.check([
    () => this.db.pingCheck('database'),
    () => this.redis.isHealthy('redis'),
    () => this.queue.isHealthy('job-queue'),
  ]);
}

// Graceful shutdown handling
@Injectable()
export class GracefulShutdownService implements OnApplicationShutdown {
  private isShuttingDown = false;

  isShutdown(): boolean {
    return this.isShuttingDown;
  }

  async onApplicationShutdown(signal: string): Promise<void> {
    this.isShuttingDown = true;
    console.log(`Shutting down on ${signal}`);

    // Wait for in-flight requests
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
}

// Health check respects shutdown state
@Get('ready')
@HealthCheck()
readiness() {
  if (this.shutdownService.isShutdown()) {
    throw new ServiceUnavailableException('Shutting down');
  }

  return this.health.check([
    () => this.db.pingCheck('database'),
  ]);
}
```

### Kubernetes Configuration

```yaml
# Kubernetes deployment with probes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-service
spec:
  template:
    spec:
      containers:
        - name: api
          image: api-service:latest
          ports:
            - containerPort: 3000
          livenessProbe:
            httpGet:
              path: /health/live
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health/live
              port: 3000
            initialDelaySeconds: 0
            periodSeconds: 5
            failureThreshold: 30
```

Reference: [NestJS Terminus](https://docs.nestjs.com/recipes/terminus)

---

### 9.2 Use Message and Event Patterns Correctly

**Impact: MEDIUM** — Proper patterns ensure reliable microservice communication

NestJS microservices support two communication patterns: request-response (MessagePattern) and event-based (EventPattern). Use MessagePattern when you need a response, and EventPattern for fire-and-forget notifications. Understanding the difference prevents communication bugs.

**Incorrect (using wrong pattern for use case):**

```typescript
// Use @MessagePattern for fire-and-forget
@Controller()
export class NotificationsController {
  @MessagePattern('user.created')
  async handleUserCreated(data: UserCreatedEvent) {
    // This WAITS for response, blocking the sender
    await this.emailService.sendWelcome(data.email);
    // If email fails, sender gets an error (coupling!)
  }
}

// Use @EventPattern expecting a response
@Controller()
export class OrdersController {
  @EventPattern('inventory.check')
  async checkInventory(data: CheckInventoryDto) {
    const available = await this.inventory.check(data);
    return available; // This return value is IGNORED with @EventPattern!
  }
}

// Tight coupling in client
@Injectable()
export class UsersService {
  async createUser(dto: CreateUserDto): Promise<User> {
    const user = await this.repo.save(dto);

    // Blocks until notification service responds
    await this.client.send('user.created', user).toPromise();
    // If notification service is down, user creation fails!

    return user;
  }
}
```

**Correct (use MessagePattern for request-response, EventPattern for fire-and-forget):**

```typescript
// MessagePattern: Request-Response (when you NEED a response)
@Controller()
export class InventoryController {
  @MessagePattern({ cmd: 'check_inventory' })
  async checkInventory(data: CheckInventoryDto): Promise<InventoryResult> {
    const result = await this.inventoryService.check(data.productId, data.quantity);
    return result; // Response sent back to caller
  }
}

// Client expects response
@Injectable()
export class OrdersService {
  async createOrder(dto: CreateOrderDto): Promise<Order> {
    // Check inventory - we NEED this response to proceed
    const inventory = await firstValueFrom(
      this.inventoryClient.send<InventoryResult>(
        { cmd: 'check_inventory' },
        { productId: dto.productId, quantity: dto.quantity },
      ),
    );

    if (!inventory.available) {
      throw new BadRequestException('Insufficient inventory');
    }

    return this.repo.save(dto);
  }
}

// EventPattern: Fire-and-Forget (for notifications, side effects)
@Controller()
export class NotificationsController {
  @EventPattern('user.created')
  async handleUserCreated(data: UserCreatedEvent): Promise<void> {
    // No return value needed - just process the event
    await this.emailService.sendWelcome(data.email);
    await this.analyticsService.track('user_signup', data);
    // If this fails, it doesn't affect the sender
  }
}

// Client emits event without waiting
@Injectable()
export class UsersService {
  async createUser(dto: CreateUserDto): Promise<User> {
    const user = await this.repo.save(dto);

    // Fire and forget - doesn't block, doesn't wait
    this.eventClient.emit('user.created', {
      userId: user.id,
      email: user.email,
      timestamp: new Date(),
    });

    return user; // User creation succeeds regardless of event handling
  }
}

// Hybrid pattern for critical events
@Injectable()
export class OrdersService {
  async createOrder(dto: CreateOrderDto): Promise<Order> {
    const order = await this.repo.save(dto);

    // Critical: inventory reservation (use MessagePattern)
    const reserved = await firstValueFrom(
      this.inventoryClient.send({ cmd: 'reserve_inventory' }, {
        orderId: order.id,
        items: dto.items,
      }),
    );

    if (!reserved.success) {
      await this.repo.delete(order.id);
      throw new BadRequestException('Could not reserve inventory');
    }

    // Non-critical: notifications (use EventPattern)
    this.eventClient.emit('order.created', {
      orderId: order.id,
      userId: dto.userId,
      total: dto.total,
    });

    return order;
  }
}

// Error handling patterns
// MessagePattern errors propagate to caller
@MessagePattern({ cmd: 'get_user' })
async getUser(userId: string): Promise<User> {
  const user = await this.repo.findOne({ where: { id: userId } });
  if (!user) {
    throw new RpcException('User not found'); // Received by caller
  }
  return user;
}

// EventPattern errors should be handled locally
@EventPattern('order.created')
async handleOrderCreated(data: OrderCreatedEvent): Promise<void> {
  try {
    await this.processOrder(data);
  } catch (error) {
    // Log and potentially retry - don't throw
    this.logger.error('Failed to process order event', error);
    await this.deadLetterQueue.add(data);
  }
}
```

Reference: [NestJS Microservices](https://docs.nestjs.com/microservices/basics)

---

### 9.3 Use Message Queues for Background Jobs

**Impact: MEDIUM-HIGH** — Queues enable reliable background processing

Use `@nestjs/bullmq` for background job processing. Queues decouple long-running tasks from HTTP requests, enable retry logic, and distribute workload across workers. Use them for emails, file processing, notifications, and any task that shouldn't block user requests.

**Incorrect (long-running tasks in HTTP handlers):**

```typescript
// Long-running tasks in HTTP handlers
@Controller('reports')
export class ReportsController {
  @Post()
  async generate(@Body() dto: GenerateReportDto): Promise<Report> {
    // This blocks the request for potentially minutes
    const data = await this.fetchLargeDataset(dto);
    const report = await this.processData(data); // Slow!
    await this.sendEmail(dto.email, report); // Can fail!
    return report; // Client times out
  }
}

// Fire-and-forget without retry
@Injectable()
export class EmailService {
  async sendWelcome(email: string): Promise<void> {
    // If this fails, email is never sent
    await this.mailer.send({ to: email, template: 'welcome' });
    // No retry, no tracking, no visibility
  }
}

// Use setInterval for scheduled tasks
setInterval(async () => {
  await cleanupOldRecords();
}, 60000); // No error handling, memory leaks
```

**Correct (use BullMQ for background processing):**

```typescript
// Configure BullMQ
import { BullModule } from '@nestjs/bullmq';

@Module({
  imports: [
    BullModule.forRoot({
      connection: {
        host: 'localhost',
        port: 6379,
      },
      defaultJobOptions: {
        removeOnComplete: 1000,
        removeOnFail: 5000,
        attempts: 3,
        backoff: {
          type: 'exponential',
          delay: 1000,
        },
      },
    }),
    BullModule.registerQueue({ name: 'email' }, { name: 'reports' }, { name: 'notifications' }),
  ],
})
export class QueueModule {}

// Producer: Add jobs to queue
@Injectable()
export class ReportsService {
  constructor(@InjectQueue('reports') private reportsQueue: Queue) {}

  async requestReport(dto: GenerateReportDto): Promise<{ jobId: string }> {
    // Return immediately, process in background
    const job = await this.reportsQueue.add('generate', dto, {
      priority: dto.urgent ? 1 : 10,
      delay: dto.scheduledFor ? Date.parse(dto.scheduledFor) - Date.now() : 0,
    });

    return { jobId: job.id };
  }

  async getJobStatus(jobId: string): Promise<JobStatus> {
    const job = await this.reportsQueue.getJob(jobId);
    return {
      status: await job.getState(),
      progress: job.progress,
      result: job.returnvalue,
    };
  }
}

// Consumer: Process jobs
@Processor('reports')
export class ReportsProcessor {
  private readonly logger = new Logger(ReportsProcessor.name);

  @Process('generate')
  async generateReport(job: Job<GenerateReportDto>): Promise<Report> {
    this.logger.log(`Processing report job ${job.id}`);

    // Update progress
    await job.updateProgress(10);

    const data = await this.fetchData(job.data);
    await job.updateProgress(50);

    const report = await this.processData(data);
    await job.updateProgress(90);

    await this.saveReport(report);
    await job.updateProgress(100);

    return report;
  }

  @OnQueueActive()
  onActive(job: Job) {
    this.logger.log(`Processing job ${job.id}`);
  }

  @OnQueueCompleted()
  onCompleted(job: Job, result: any) {
    this.logger.log(`Job ${job.id} completed`);
  }

  @OnQueueFailed()
  onFailed(job: Job, error: Error) {
    this.logger.error(`Job ${job.id} failed: ${error.message}`);
  }
}

// Email queue with retry
@Processor('email')
export class EmailProcessor {
  @Process('send')
  async sendEmail(job: Job<SendEmailDto>): Promise<void> {
    const { to, template, data } = job.data;

    try {
      await this.mailer.send({
        to,
        template,
        context: data,
      });
    } catch (error) {
      // BullMQ will retry based on job options
      throw error;
    }
  }
}

// Usage
@Injectable()
export class NotificationService {
  constructor(@InjectQueue('email') private emailQueue: Queue) {}

  async sendWelcome(user: User): Promise<void> {
    await this.emailQueue.add(
      'send',
      {
        to: user.email,
        template: 'welcome',
        data: { name: user.name },
      },
      {
        attempts: 5,
        backoff: { type: 'exponential', delay: 5000 },
      },
    );
  }
}

// Scheduled jobs
@Injectable()
export class ScheduledJobsService implements OnModuleInit {
  constructor(@InjectQueue('maintenance') private queue: Queue) {}

  async onModuleInit(): Promise<void> {
    // Clean up old reports daily at midnight
    await this.queue.add(
      'cleanup',
      {},
      {
        repeat: { cron: '0 0 * * *' },
        jobId: 'daily-cleanup', // Prevent duplicates
      },
    );

    // Send digest every hour
    await this.queue.add(
      'digest',
      {},
      {
        repeat: { every: 60 * 60 * 1000 },
        jobId: 'hourly-digest',
      },
    );
  }
}

@Processor('maintenance')
export class MaintenanceProcessor {
  @Process('cleanup')
  async cleanup(): Promise<void> {
    await this.cleanupOldReports();
    await this.cleanupExpiredSessions();
  }

  @Process('digest')
  async sendDigest(): Promise<void> {
    const users = await this.getUsersForDigest();
    for (const user of users) {
      await this.emailQueue.add('send', { to: user.email, template: 'digest' });
    }
  }
}

// Queue monitoring with Bull Board
import { BullBoardModule } from '@bull-board/nestjs';
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';

@Module({
  imports: [
    BullBoardModule.forRoot({
      route: '/admin/queues',
      adapter: ExpressAdapter,
    }),
    BullBoardModule.forFeature({
      name: 'email',
      adapter: BullMQAdapter,
    }),
    BullBoardModule.forFeature({
      name: 'reports',
      adapter: BullMQAdapter,
    }),
  ],
})
export class AdminModule {}
```

Reference: [NestJS Queues](https://docs.nestjs.com/techniques/queues)

---

## 10. DevOps & Deployment

**Section Impact: LOW-MEDIUM**

### 10.1 Implement Graceful Shutdown

**Impact: MEDIUM-HIGH** — Proper shutdown handling ensures zero-downtime deployments

Handle SIGTERM and SIGINT signals to gracefully shutdown your NestJS application. Stop accepting new requests, wait for in-flight requests to complete, close database connections, and clean up resources. This prevents data loss and connection errors during deployments.

**Incorrect (ignoring shutdown signals):**

```typescript
// Ignore shutdown signals
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
  // App crashes immediately on SIGTERM
  // In-flight requests fail
  // Database connections are abruptly closed
}

// Long-running tasks without cancellation
@Injectable()
export class ProcessingService {
  async processLargeFile(file: File): Promise<void> {
    // No way to interrupt this during shutdown
    for (let i = 0; i < file.chunks.length; i++) {
      await this.processChunk(file.chunks[i]);
      // May run for minutes, blocking shutdown
    }
  }
}
```

**Correct (enable shutdown hooks and handle cleanup):**

```typescript
// Enable shutdown hooks in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Enable shutdown hooks
  app.enableShutdownHooks();

  // Optional: Add timeout for forced shutdown
  const server = await app.listen(3000);
  server.setTimeout(30000); // 30 second timeout

  // Handle graceful shutdown
  const signals = ['SIGTERM', 'SIGINT'];
  signals.forEach(signal => {
    process.on(signal, async () => {
      console.log(`Received ${signal}, starting graceful shutdown...`);

      // Stop accepting new connections
      server.close(async () => {
        console.log('HTTP server closed');
        await app.close();
        process.exit(0);
      });

      // Force exit after timeout
      setTimeout(() => {
        console.error('Forced shutdown after timeout');
        process.exit(1);
      }, 30000);
    });
  });
}

// Lifecycle hooks for cleanup
@Injectable()
export class DatabaseService implements OnApplicationShutdown {
  private readonly connections: Connection[] = [];

  async onApplicationShutdown(signal?: string): Promise<void> {
    console.log(`Database service shutting down on ${signal}`);

    // Close all connections gracefully
    await Promise.all(this.connections.map(conn => conn.close()));

    console.log('All database connections closed');
  }
}

// Queue processor with graceful shutdown
@Injectable()
export class QueueService implements OnApplicationShutdown, OnModuleDestroy {
  private isShuttingDown = false;

  onModuleDestroy(): void {
    this.isShuttingDown = true;
  }

  async onApplicationShutdown(): Promise<void> {
    // Wait for current jobs to complete
    await this.queue.close();
  }

  async processJob(job: Job): Promise<void> {
    if (this.isShuttingDown) {
      throw new Error('Service is shutting down');
    }
    await this.doWork(job);
  }
}

// WebSocket gateway cleanup
@WebSocketGateway()
export class EventsGateway implements OnApplicationShutdown {
  @WebSocketServer()
  server: Server;

  async onApplicationShutdown(): Promise<void> {
    // Notify all connected clients
    this.server.emit('shutdown', { message: 'Server is shutting down' });

    // Close all connections
    this.server.disconnectSockets();
  }
}

// Health check integration
@Injectable()
export class ShutdownService {
  private isShuttingDown = false;

  startShutdown(): void {
    this.isShuttingDown = true;
  }

  isShutdown(): boolean {
    return this.isShuttingDown;
  }
}

@Controller('health')
export class HealthController {
  constructor(private shutdownService: ShutdownService) {}

  @Get('ready')
  @HealthCheck()
  readiness(): Promise<HealthCheckResult> {
    // Return 503 during shutdown - k8s stops sending traffic
    if (this.shutdownService.isShutdown()) {
      throw new ServiceUnavailableException('Shutting down');
    }

    return this.health.check([() => this.db.pingCheck('database')]);
  }
}

// Integrate with shutdown
@Injectable()
export class AppShutdownService implements OnApplicationShutdown {
  constructor(private shutdownService: ShutdownService) {}

  async onApplicationShutdown(): Promise<void> {
    // Mark as unhealthy first
    this.shutdownService.startShutdown();

    // Wait for k8s to update endpoints
    await this.sleep(5000);

    // Then proceed with cleanup
  }
}

// Request tracking for in-flight requests
@Injectable()
export class RequestTracker implements NestMiddleware, OnApplicationShutdown {
  private activeRequests = 0;
  private isShuttingDown = false;
  private shutdownPromise: Promise<void> | null = null;
  private resolveShutdown: (() => void) | null = null;

  use(req: Request, res: Response, next: NextFunction): void {
    if (this.isShuttingDown) {
      res.status(503).send('Service Unavailable');
      return;
    }

    this.activeRequests++;

    res.on('finish', () => {
      this.activeRequests--;
      if (this.isShuttingDown && this.activeRequests === 0 && this.resolveShutdown) {
        this.resolveShutdown();
      }
    });

    next();
  }

  async onApplicationShutdown(): Promise<void> {
    this.isShuttingDown = true;

    if (this.activeRequests > 0) {
      console.log(`Waiting for ${this.activeRequests} requests to complete`);
      this.shutdownPromise = new Promise(resolve => {
        this.resolveShutdown = resolve;
      });

      // Wait with timeout
      await Promise.race([this.shutdownPromise, new Promise(resolve => setTimeout(resolve, 30000))]);
    }

    console.log('All requests completed');
  }
}
```

Reference: [NestJS Lifecycle Events](https://docs.nestjs.com/fundamentals/lifecycle-events)

---

### 10.2 Use ConfigModule for Environment Configuration

**Impact: LOW-MEDIUM** — Proper configuration prevents deployment failures

Use `@nestjs/config` for environment-based configuration. Validate configuration at startup to fail fast on misconfigurations. Use namespaced configuration for organization and type safety.

**Incorrect (accessing process.env directly):**

```typescript
// Access process.env directly
@Injectable()
export class DatabaseService {
  constructor() {
    // No validation, can fail at runtime
    this.connection = new Pool({
      host: process.env.DB_HOST,
      port: parseInt(process.env.DB_PORT), // NaN if missing
      password: process.env.DB_PASSWORD, // undefined if missing
    });
  }
}

// Scattered env access
@Injectable()
export class EmailService {
  sendEmail() {
    // Different services access env differently
    const apiKey = process.env.SENDGRID_API_KEY || 'default';
    // Typos go unnoticed: process.env.SENDGRID_API_KY
  }
}
```

**Correct (use @nestjs/config with validation):**

```typescript
// Setup validated configuration
import { ConfigModule, ConfigService, registerAs } from '@nestjs/config';
import * as Joi from 'joi';

// config/database.config.ts
export const databaseConfig = registerAs('database', () => ({
  host: process.env.DB_HOST,
  port: parseInt(process.env.DB_PORT, 10),
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
}));

// config/app.config.ts
export const appConfig = registerAs('app', () => ({
  port: parseInt(process.env.PORT, 10) || 3000,
  environment: process.env.NODE_ENV || 'development',
  apiPrefix: process.env.API_PREFIX || 'api',
}));

// config/validation.schema.ts
export const validationSchema = Joi.object({
  NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
  PORT: Joi.number().default(3000),
  DB_HOST: Joi.string().required(),
  DB_PORT: Joi.number().default(5432),
  DB_USERNAME: Joi.string().required(),
  DB_PASSWORD: Joi.string().required(),
  DB_NAME: Joi.string().required(),
  JWT_SECRET: Joi.string().min(32).required(),
  REDIS_URL: Joi.string().uri().required(),
});

// app.module.ts
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true, // Available everywhere without importing
      load: [databaseConfig, appConfig],
      validationSchema,
      validationOptions: {
        abortEarly: true, // Stop on first error
        allowUnknown: true, // Allow other env vars
      },
    }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        type: 'postgres',
        host: config.get('database.host'),
        port: config.get('database.port'),
        username: config.get('database.username'),
        password: config.get('database.password'),
        database: config.get('database.database'),
        autoLoadEntities: true,
      }),
    }),
  ],
})
export class AppModule {}

// Type-safe configuration access
export interface AppConfig {
  port: number;
  environment: 'development' | 'production' | 'test';
  apiPrefix: string;
}

export interface DatabaseConfig {
  host: string;
  port: number;
  username: string;
  password: string;
  database: string;
}

// Type-safe access
@Injectable()
export class AppService {
  constructor(private config: ConfigService) {}

  getPort(): number {
    // Type-safe with generic
    return this.config.get<number>('app.port');
  }

  getDatabaseConfig(): DatabaseConfig {
    return this.config.get<DatabaseConfig>('database');
  }
}

// Inject namespaced config directly
@Injectable()
export class DatabaseService {
  constructor(
    @Inject(databaseConfig.KEY)
    private dbConfig: ConfigType<typeof databaseConfig>,
  ) {
    // Full type inference!
    const host = this.dbConfig.host; // string
    const port = this.dbConfig.port; // number
  }
}

// Environment files support
ConfigModule.forRoot({
  envFilePath: [`.env.${process.env.NODE_ENV}.local`, `.env.${process.env.NODE_ENV}`, '.env.local', '.env'],
});

// .env.development
// DB_HOST=localhost
// DB_PORT=5432

// .env.production
// DB_HOST=prod-db.example.com
// DB_PORT=5432
```

Reference: [NestJS Configuration](https://docs.nestjs.com/techniques/configuration)

---

### 10.3 Use Structured Logging

**Impact: MEDIUM-HIGH** — Structured logging enables effective debugging and monitoring

Use NestJS Logger with structured JSON output in production. Include contextual information (request ID, user ID, operation) to trace requests across services. Avoid console.log and implement proper log levels.

**Incorrect (using console.log in production):**

```typescript
// Use console.log in production
@Injectable()
export class UsersService {
  async createUser(dto: CreateUserDto): Promise<User> {
    console.log('Creating user:', dto);
    // Not structured, no levels, lost in production logs

    try {
      const user = await this.repo.save(dto);
      console.log('User created:', user.id);
      return user;
    } catch (error) {
      console.log('Error:', error); // Using log for errors
      throw error;
    }
  }
}

// Log sensitive data
console.log('Login attempt:', { email, password }); // SECURITY RISK!

// Inconsistent log format
logger.log('User ' + userId + ' created at ' + new Date());
// Hard to parse, no structure
```

**Correct (use structured logging with context):**

```typescript
// Configure logger in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger:
      process.env.NODE_ENV === 'production' ? ['error', 'warn', 'log'] : ['error', 'warn', 'log', 'debug', 'verbose'],
  });
}

// Use NestJS Logger with context
@Injectable()
export class UsersService {
  private readonly logger = new Logger(UsersService.name);

  async createUser(dto: CreateUserDto): Promise<User> {
    this.logger.log('Creating user', { email: dto.email });

    try {
      const user = await this.repo.save(dto);
      this.logger.log('User created', { userId: user.id });
      return user;
    } catch (error) {
      this.logger.error('Failed to create user', error.stack, {
        email: dto.email,
      });
      throw error;
    }
  }
}

// Custom logger for JSON output
@Injectable()
export class JsonLogger implements LoggerService {
  log(message: string, context?: object): void {
    console.log(
      JSON.stringify({
        level: 'info',
        timestamp: new Date().toISOString(),
        message,
        ...context,
      }),
    );
  }

  error(message: string, trace?: string, context?: object): void {
    console.error(
      JSON.stringify({
        level: 'error',
        timestamp: new Date().toISOString(),
        message,
        trace,
        ...context,
      }),
    );
  }

  warn(message: string, context?: object): void {
    console.warn(
      JSON.stringify({
        level: 'warn',
        timestamp: new Date().toISOString(),
        message,
        ...context,
      }),
    );
  }

  debug(message: string, context?: object): void {
    console.debug(
      JSON.stringify({
        level: 'debug',
        timestamp: new Date().toISOString(),
        message,
        ...context,
      }),
    );
  }
}

// Request context logging with ClsModule
import { ClsModule, ClsService } from 'nestjs-cls';

@Module({
  imports: [
    ClsModule.forRoot({
      global: true,
      middleware: {
        mount: true,
        generateId: true,
      },
    }),
  ],
})
export class AppModule {}

// Middleware to set request context
@Injectable()
export class RequestContextMiddleware implements NestMiddleware {
  constructor(private cls: ClsService) {}

  use(req: Request, res: Response, next: NextFunction): void {
    const requestId = req.headers['x-request-id'] || randomUUID();
    this.cls.set('requestId', requestId);
    this.cls.set('userId', req.user?.id);

    res.setHeader('x-request-id', requestId);
    next();
  }
}

// Logger that includes request context
@Injectable()
export class ContextLogger {
  constructor(private cls: ClsService) {}

  log(message: string, data?: object): void {
    console.log(
      JSON.stringify({
        level: 'info',
        timestamp: new Date().toISOString(),
        requestId: this.cls.get('requestId'),
        userId: this.cls.get('userId'),
        message,
        ...data,
      }),
    );
  }

  error(message: string, error: Error, data?: object): void {
    console.error(
      JSON.stringify({
        level: 'error',
        timestamp: new Date().toISOString(),
        requestId: this.cls.get('requestId'),
        userId: this.cls.get('userId'),
        message,
        error: error.message,
        stack: error.stack,
        ...data,
      }),
    );
  }
}

// Pino integration for high-performance logging
import { LoggerModule } from 'nestjs-pino';

@Module({
  imports: [
    LoggerModule.forRoot({
      pinoHttp: {
        level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
        transport: process.env.NODE_ENV !== 'production' ? { target: 'pino-pretty' } : undefined,
        redact: ['req.headers.authorization', 'req.body.password'],
        serializers: {
          req: req => ({
            method: req.method,
            url: req.url,
            query: req.query,
          }),
          res: res => ({
            statusCode: res.statusCode,
          }),
        },
      },
    }),
  ],
})
export class AppModule {}

// Usage with Pino
@Injectable()
export class UsersService {
  constructor(private logger: PinoLogger) {
    this.logger.setContext(UsersService.name);
  }

  async findOne(id: string): Promise<User> {
    this.logger.info({ userId: id }, 'Finding user');
    // Pino uses first arg for data, second for message
  }
}
```

Reference: [NestJS Logger](https://docs.nestjs.com/techniques/logger)

---

## References

- https://docs.nestjs.com
- https://github.com/nestjs/nest
- https://typeorm.io
- https://github.com/typestack/class-validator
- https://github.com/goldbergyoni/nodebestpractices

---

_Generated by build-agents.ts on 2026-01-16_

================================================
FILE: .agents/skills/nestjs-best-practices/README.md
================================================
# NestJS Best Practices

📖 [For Humans <3](https://kadajett.github.io/agent-nestjs-skills/)

A structured repository for creating and maintaining NestJS Best Practices optimized for agents and LLMs.

## Installation

Install this skill using [skills](https://github.com/vercel-labs/skills):

```bash
# GitHub shorthand
npx skills add Kadajett/agent-nestjs-skills

# Install globally (available across all projects)
npx skills add Kadajett/agent-nestjs-skills --global

# Install for specific agents
npx skills add Kadajett/agent-nestjs-skills -a claude-code -a cursor
```

### Supported Agents

- Claude Code
- OpenCode
- Codex
- Cursor
- Antigravity
- Roo Code

## Structure

- `rules/` - Individual rule files (one per rule)
  - `_sections.md` - Section metadata (titles, impacts, descriptions)
  - `_template.md` - Template for creating new rules
  - `area-description.md` - Individual rule files
- `scripts/` - Build scripts and utilities
- `metadata.json` - Document metadata (version, organization, abstract)
- **`AGENTS.md`** - Compiled output (generated)

## Getting Started

1. Install dependencies:

   ```bash
   cd scripts && npm install
   ```

2. Build AGENTS.md from rules:
   ```bash
   npm run build
   # or
   ./scripts/build.sh
   ```

## Creating a New Rule

1. Copy `rules/_template.md` to `rules/area-description.md`
2. Choose the appropriate area prefix:
   - `arch-` for Architecture (Section 1)
   - `di-` for Dependency Injection (Section 2)
   - `error-` for Error Handling (Section 3)
   - `security-` for Security (Section 4)
   - `perf-` for Performance (Section 5)
   - `test-` for Testing (Section 6)
   - `db-` for Database & ORM (Section 7)
   - `api-` for API Design (Section 8)
   - `micro-` for Microservices (Section 9)
   - `devops-` for DevOps & Deployment (Section 10)
3. Fill in the frontmatter and content
4. Ensure you have clear examples with explanations
5. Run the build script to regenerate AGENTS.md

## Rule File Structure

Each rule file should follow this structure:

````markdown
---
title: Rule Title Here
impact: MEDIUM
impactDescription: Optional description
tags: tag1, tag2, tag3
---

## Rule Title Here

Brief explanation of the rule and why it matters.

**Incorrect (description of what's wrong):**

```typescript
// Bad code example
```
````

**Correct (description of what's right):**

```typescript
// Good code example
```

Optional explanatory text after examples.

Reference: [NestJS Documentation](https://docs.nestjs.com)

## File Naming Convention

- Files starting with `_` are special (excluded from build)
- Rule files: `area-description.md` (e.g., `arch-avoid-circular-deps.md`)
- Section is automatically inferred from filename prefix
- Rules are sorted alphabetically by title within each section
- IDs (e.g., 1.1, 1.2) are auto-generated during build

## Impact Levels

| Level       | Description                                                                           |
| ----------- | ------------------------------------------------------------------------------------- |
| CRITICAL    | Violations cause runtime errors, security vulnerabilities, or architectural breakdown |
| HIGH        | Significant impact on reliability, security, or maintainability                       |
| MEDIUM-HIGH | Notable impact on quality and developer experience                                    |
| MEDIUM      | Moderate impact on code quality and best practices                                    |
| LOW-MEDIUM  | Minor improvements for consistency and maintainability                                |

## Scripts

- `npm run build` (in scripts/) - Compile rules into AGENTS.md

## Contributing

When adding or modifying rules:

1. Use the correct filename prefix for your section
2. Follow the `_template.md` structure
3. Include clear bad/good examples with explanations
4. Add appropriate tags
5. Run the build script to regenerate AGENTS.md
6. Rules are automatically sorted by title - no need to manage numbers!

## Documentation Website

The documentation website source code lives on the [`docs` branch](https://github.com/Kadajett/agent-nestjs-skills/tree/docs/website). This separation keeps the skill installation lightweight while maintaining the full documentation site.

To contribute to the website:

```bash
git checkout docs
cd website
npm install
npm run dev
```

## Acknowledgments

- Inspired by the [Vercel React Best Practices](https://github.com/vercel-labs/agent-skills) skill structure
- Compatible with [skills](https://github.com/vercel-labs/skills) for easy installation across coding agents

## Compatible Agents

These NestJS skills work with:

- [Claude Code](https://claude.ai/code) - Anthropic's official CLI
- [AdaL](https://sylph.ai/adal) - Self-evolving AI coding agent with MCP support

================================================
FILE: .agents/skills/nestjs-best-practices/SKILL.md
================================================
---
name: nestjs-best-practices
description: NestJS best practices and architecture patterns for building production-ready applications. This skill should be used when writing, reviewing, or refactoring NestJS code to ensure proper patterns for modules, dependency injection, security, and performance.
license: MIT
metadata:
  author: Kadajett
  version: '1.1.0'
---

# NestJS Best Practices

Comprehensive best practices guide for NestJS applications. Contains 40 rules across 10 categories, prioritized by impact to guide automated refactoring and code generation.

## When to Apply

Reference these guidelines when:

- Writing new NestJS modules, controllers, or services
- Implementing authentication and authorization
- Reviewing code for architecture and security issues
- Refactoring existing NestJS codebases
- Optimizing performance or database queries
- Building microservices architectures

## Rule Categories by Priority

| Priority | Category             | Impact      | Prefix      |
| -------- | -------------------- | ----------- | ----------- |
| 1        | Architecture         | CRITICAL    | `arch-`     |
| 2        | Dependency Injection | CRITICAL    | `di-`       |
| 3        | Error Handling       | HIGH        | `error-`    |
| 4        | Security             | HIGH        | `security-` |
| 5        | Performance          | HIGH        | `perf-`     |
| 6        | Testing              | MEDIUM-HIGH | `test-`     |
| 7        | Database & ORM       | MEDIUM-HIGH | `db-`       |
| 8        | API Design           | MEDIUM      | `api-`      |
| 9        | Microservices        | MEDIUM      | `micro-`    |
| 10       | DevOps & Deployment  | LOW-MEDIUM  | `devops-`   |

## Quick Reference

### 1. Architecture (CRITICAL)

- `arch-avoid-circular-deps` - Avoid circular module dependencies
- `arch-feature-modules` - Organize by feature, not technical layer
- `arch-module-sharing` - Proper module exports/imports, avoid duplicate providers
- `arch-single-responsibility` - Focused services over "god services"
- `arch-use-repository-pattern` - Abstract database logic for testability
- `arch-use-events` - Event-driven architecture for decoupling

### 2. Dependency Injection (CRITICAL)

- `di-avoid-service-locator` - Avoid service locator anti-pattern
- `di-interface-segregation` - Interface Segregation Principle (ISP)
- `di-liskov-substitution` - Liskov Substitution Principle (LSP)
- `di-prefer-constructor-injection` - Constructor over property injection
- `di-scope-awareness` - Understand singleton/request/transient scopes
- `di-use-interfaces-tokens` - Use injection tokens for interfaces

### 3. Error Handling (HIGH)

- `error-use-exception-filters` - Centralized exception handling
- `error-throw-http-exceptions` - Use NestJS HTTP exceptions
- `error-handle-async-errors` - Handle async errors properly

### 4. Security (HIGH)

- `security-auth-jwt` - Secure JWT authentication
- `security-validate-all-input` - Validate with class-validator
- `security-use-guards` - Authentication and authorization guards
- `security-sanitize-output` - Prevent XSS attacks
- `security-rate-limiting` - Implement rate limiting

### 5. Performance (HIGH)

- `perf-async-hooks` - Proper async lifecycle hooks
- `perf-use-caching` - Implement caching strategies
- `perf-optimize-database` - Optimize database queries
- `perf-lazy-loading` - Lazy load modules for faster startup

### 6. Testing (MEDIUM-HIGH)

- `test-use-testing-module` - Use NestJS testing utilities
- `test-e2e-supertest` - E2E testing with Supertest
- `test-mock-external-services` - Mock external dependencies

### 7. Database & ORM (MEDIUM-HIGH)

- `db-use-transactions` - Transaction management
- `db-avoid-n-plus-one` - Avoid N+1 query problems
- `db-use-migrations` - Use migrations for schema changes

### 8. API Design (MEDIUM)

- `api-use-dto-serialization` - DTO and response serialization
- `api-use-interceptors` - Cross-cutting concerns
- `api-versioning` - API versioning strategies
- `api-use-pipes` - Input transformation with pipes

### 9. Microservices (MEDIUM)

- `micro-use-patterns` - Message and event patterns
- `micro-use-health-checks` - Health checks for orchestration
- `micro-use-queues` - Background job processing

### 10. DevOps & Deployment (LOW-MEDIUM)

- `devops-use-config-module` - Environment configuration
- `devops-use-logging` - Structured logging
- `devops-graceful-shutdown` - Zero-downtime deployments

## How to Use

Read individual rule files for detailed explanations and code examples:

```
rules/arch-avoid-circular-deps.md
rules/security-validate-all-input.md
rules/_sections.md
```

Each rule file contains:

- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Additional context and references

## Full Compiled Document

For the complete guide with all rules expanded: `AGENTS.md`

================================================
FILE: .agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md
================================================
---
title: Use DTOs and Serialization for API Responses
impact: MEDIUM
impactDescription: Response DTOs prevent accidental data exposure and ensure consistency
tags: api, dto, serialization, class-transformer
---

## Use DTOs and Serialization for API Responses

Never return entity objects directly from controllers. Use response DTOs with class-transformer's `@Exclude()` and `@Expose()` decorators to control exactly what data is sent to clients. This prevents accidental exposure of sensitive fields and provides a stable API contract.

**Incorrect (returning entities directly or manual spreading):**

```typescript
// Return entities directly
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findById(id);
    // Returns: { id, email, passwordHash, ssn, internalNotes, ... }
    // Exposes sensitive data!
  }
}

// Manual object spreading (error-prone)
@Get(':id')
async findOne(@Param('id') id: string) {
  const user = await this.usersService.findById(id);
  return {
    id: user.id,
    email: user.email,
    name: user.name,
    // Easy to forget to exclude sensitive fields
    // Hard to maintain across endpoints
  };
}
```

**Correct (use class-transformer with @Exclude and response DTOs):**

```typescript
// Enable class-transformer globally
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
  await app.listen(3000);
}

// Entity with serialization control
@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  email: string;

  @Column()
  name: string;

  @Column()
  @Exclude() // Never include in responses
  passwordHash: string;

  @Column({ nullable: true })
  @Exclude()
  ssn: string;

  @Column({ default: false })
  @Exclude({ toPlainOnly: true }) // Exclude from response, allow in requests
  isAdmin: boolean;

  @CreateDateColumn()
  createdAt: Date;

  @Column()
  @Exclude()
  internalNotes: string;
}

// Now returning entity is safe
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findById(id);
    // Returns: { id, email, name, createdAt }
    // Sensitive fields excluded automatically
  }
}

// For different response shapes, use explicit DTOs
export class UserResponseDto {
  @Expose()
  id: string;

  @Expose()
  email: string;

  @Expose()
  name: string;

  @Expose()
  @Transform(({ obj }) => obj.posts?.length || 0)
  postCount: number;

  constructor(partial: Partial<User>) {
    Object.assign(this, partial);
  }
}

export class UserDetailResponseDto extends UserResponseDto {
  @Expose()
  createdAt: Date;

  @Expose()
  @Type(() => PostResponseDto)
  posts: PostResponseDto[];
}

// Controller with explicit DTOs
@Controller('users')
export class UsersController {
  @Get()
  @SerializeOptions({ type: UserResponseDto })
  async findAll(): Promise<UserResponseDto[]> {
    const users = await this.usersService.findAll();
    return users.map(u => plainToInstance(UserResponseDto, u));
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<UserDetailResponseDto> {
    const user = await this.usersService.findByIdWithPosts(id);
    return plainToInstance(UserDetailResponseDto, user, {
      excludeExtraneousValues: true,
    });
  }
}

// Groups for conditional serialization
export class UserDto {
  @Expose()
  id: string;

  @Expose()
  name: string;

  @Expose({ groups: ['admin'] })
  email: string;

  @Expose({ groups: ['admin'] })
  createdAt: Date;

  @Expose({ groups: ['admin', 'owner'] })
  settings: UserSettings;
}

@Controller('users')
export class UsersController {
  @Get()
  @SerializeOptions({ groups: ['public'] })
  async findAllPublic(): Promise<UserDto[]> {
    // Returns: { id, name }
  }

  @Get('admin')
  @UseGuards(AdminGuard)
  @SerializeOptions({ groups: ['admin'] })
  async findAllAdmin(): Promise<UserDto[]> {
    // Returns: { id, name, email, createdAt }
  }

  @Get('me')
  @SerializeOptions({ groups: ['owner'] })
  async getProfile(@CurrentUser() user: User): Promise<UserDto> {
    // Returns: { id, name, settings }
  }
}
```

Reference: [NestJS Serialization](https://docs.nestjs.com/techniques/serialization)

================================================
FILE: .agents/skills/nestjs-best-practices/rules/api-use-interceptors.md
================================================
---
title: Use Interceptors for Cross-Cutting Concerns
impact: MEDIUM-HIGH
impactDescription: Interceptors provide clean separation for cross-cutting logic
tags: api, interceptors, logging, caching
---

## Use Interceptors for Cross-Cutting Concerns

Interceptors can transform responses, add logging, handle caching, and measure performance without polluting your business logic. They wrap the route handler execution, giving you access to both the request and response streams.

**Incorrect (logging and transformation in every method):**

```typescript
// Logging in every controller method
@Controller('users')
export class UsersController {
  @Get()
  async findAll(): Promise<User[]> {
    const start = Date.now();
    this.logger.log('findAll called');

    const users = await this.usersService.findAll();

    this.logger.log(`findAll completed in ${Date.now() - start}ms`);
    return users;
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    const start = Date.now();
    this.logger.log(`findOne called with id: ${id}`);

    const user = await this.usersService.findOne(id);

    this.logger.log(`findOne completed in ${Date.now() - start}ms`);
    return user;
  }
  // Repeated in every method!
}

// Manual response wrapping
@Get()
async findAll(): Promise<{ data: User[]; meta: Meta }> {
  const users = await this.usersService.findAll();
  return {
    data: users,
    meta: { timestamp: new Date(), count: users.length },
  };
}
```

**Correct (use interceptors for cross-cutting concerns):**

```typescript
// Logging interceptor
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  private readonly logger = new Logger('HTTP');

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const { method, url, body } = request;
    const now = Date.now();

    return next.handle().pipe(
      tap({
        next: (data) => {
          const response = context.switchToHttp().getResponse();
          this.logger.log(
            `${method} ${url} ${response.statusCode} - ${Date.now() - now}ms`,
          );
        },
        error: (error) => {
          this.logger.error(
            `${method} ${url} ${error.status || 500} - ${Date.now() - now}ms`,
            error.stack,
          );
        },
      }),
    );
  }
}

// Response transformation interceptor
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
  intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
    return next.handle().pipe(
      map((data) => ({
        data,
        meta: {
          timestamp: new Date().toISOString(),
          path: context.switchToHttp().getRequest().url,
        },
      })),
    );
  }
}

// Timeout interceptor
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(5000),
      catchError((err) => {
        if (err instanceof TimeoutError) {
          throw new RequestTimeoutException('Request timed out');
        }
        throw err;
      }),
    );
  }
}

// Apply globally or per-controller
@Module({
  providers: [
    { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
    { provide: APP_INTERCEPTOR, useClass: TransformInterceptor },
  ],
})
export class AppModule {}

// Or per-controller
@Controller('users')
@UseInterceptors(LoggingInterceptor)
export class UsersController {
  @Get()
  async findAll(): Promise<User[]> {
    // Clean business logic only
    return this.usersService.findAll();
  }
}

// Custom cache interceptor with TTL
@Injectable()
export class HttpCacheInterceptor implements NestInterceptor {
  constructor(
    private cacheManager: Cache,
    private reflector: Reflector,
  ) {}

  async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
    const request = context.switchToHttp().getRequest();

    // Only cache GET requests
    if (request.method !== 'GET') {
      return next.handle();
    }

    const cacheKey = this.generateKey(request);
    const ttl = this.reflector.get<number>('cacheTTL', context.getHandler()) || 300;

    const cached = await this.cacheManager.get(cacheKey);
    if (cached) {
      return of(cached);
    }

    return next.handle().pipe(
      tap((response) => {
        this.cacheManager.set(cacheKey, response, ttl);
      }),
    );
  }

  private generateKey(request: Request): string {
    return `cache:${request.url}:${JSON.stringify(request.query)}`;
  }
}

// Usage with custom TTL
@Get()
@SetMetadata('cacheTTL', 600)
@UseInterceptors(HttpCacheInterceptor)
async findAll(): Promise<User[]> {
  return this.usersService.findAll();
}

// Error mapping interceptor
@Injectable()
export class ErrorMappingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      catchError((error) => {
        if (error instanceof EntityNotFoundError) {
          throw new NotFoundException(error.message);
        }
        if (error instanceof QueryFailedError) {
          if (error.message.includes('duplicate')) {
            throw new ConflictException('Resource already exists');
          }
        }
        throw error;
      }),
    );
  }
}
```

Reference: [NestJS Interceptors](https://docs.nestjs.com/interceptors)

================================================
FILE: .agents/skills/nestjs-best-practices/rules/api-use-pipes.md
================================================
---
title: Use Pipes for Input Transformation
impact: MEDIUM
impactDescription: Pipes ensure clean, validated data reaches your handlers
tags: api, pipes, validation, transformation
---

## Use Pipes for Input Transformation

Use built-in pipes like `ParseIntPipe`, `ParseUUIDPipe`, and `DefaultValuePipe` for common transformations. Create custom pipes for business-specific transformations. Pipes separate validation/transformation logic from controllers.

**Incorrect (manual type parsing in handlers):**

```typescript
// Manual type parsing in handlers
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    // Manual validation in every handler
    const uuid = id.trim();
    if (!isUUID(uuid)) {
      throw new BadRequestException('Invalid UUID');
    }
    return this.usersService.findOne(uuid);
  }

  @Get()
  async findAll(
    @Query('page') page: string,
    @Query('limit') limit: string,
  ): Promise<User[]> {
    // Manual parsing and defaults
    const pageNum = parseInt(page) || 1;
    const limitNum = parseInt(limit) || 10;
    return this.usersService.findAll(pageNum, limitNum);
  }
}

// Type coercion without validation
@Get()
async search(@Query('price') price: string): Promise<Product[]> {
  const priceNum = +price; // NaN if invalid, no error
  return this.productsService.findByPrice(priceNum);
}
```

**Correct (use built-in and custom pipes):**

```typescript
// Use built-in pipes for common transformations
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id', ParseUUIDPipe) id: string): Promise<User> {
    // id is guaranteed to be a valid UUID
    return this.usersService.findOne(id);
  }

  @Get()
  async findAll(
    @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
    @Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
  ): Promise<User[]> {
    // Automatic defaults and type conversion
    return this.usersService.findAll(page, limit);
  }

  @Get('by-status/:status')
  async findByStatus(
    @Param('status', new ParseEnumPipe(UserStatus)) status: UserStatus,
  ): Promise<User[]> {
    return this.usersService.findByStatus(status);
  }
}

// Custom pipe for business logic
@Injectable()
export class ParseDatePipe implements PipeTransform<string, Date> {
  transform(value: string): Date {
    const date = new Date(value);
    if (isNaN(date.getTime())) {
      throw new BadRequestException('Invalid date format');
    }
    return date;
  }
}

@Get('reports')
async getReports(
  @Query('from', ParseDatePipe) from: Date,
  @Query('to', ParseDatePipe) to: Date,
): Promise<Report[]> {
  return this.reportsService.findBetween(from, to);
}

// Custom transformation pipes
@Injectable()
export class NormalizeEmailPipe implements PipeTransform<string, string> {
  transform(value: string): string {
    if (!value) return value;
    return value.trim().toLowerCase();
  }
}

// Parse comma-separated values
@Injectable()
export class ParseArrayPipe implements PipeTransform<string, string[]> {
  transform(value: string): string[] {
    if (!value) return [];
    return value.split(',').map((v) => v.trim()).filter(Boolean);
  }
}

@Get('products')
async findProducts(
  @Query('ids', ParseArrayPipe) ids: string[],
  @Query('email', NormalizeEmailPipe) email: string,
): Promise<Product[]> {
  // ids is already an array, email is normalized
  return this.productsService.findByIds(ids);
}

// Sanitize HTML input
@Injectable()
export class SanitizeHtmlPipe implements PipeTransform<string, string> {
  transform(value: string): string {
    if (!value) return value;
    return sanitizeHtml(value, { allowedTags: [] });
  }
}

// Global validation pipe with transformation
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true, // Strip non-DTO properties
    transform: true, // Auto-transform to DTO types
    transformOptions: {
      enableImplicitConversion: true, // Convert query strings to numbers
    },
    forbidNonWhitelisted: true, // Throw on extra properties
  }),
);

// DTO with transformation decorators
export class FindProductsDto {
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  page?: number = 1;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(100)
  limit?: number = 10;

  @IsOptional()
  @Transform(({ value }) => value?.toLowerCase())
  @IsString()
  search?: string;

  @IsOptional()
  @Transform(({ value }) => value?.split(','))
  @IsArray()
  @IsString({ each: true })
  categories?: string[];
}

@Get()
async findAll(@Query() dto: FindProductsDto): Promise<Product[]> {
  // dto is already transformed and validated
  return this.productsService.findAll(dto);
}

// Pipe error customization
@Injectable()
export class CustomParseIntPipe extends ParseIntPipe {
  constructor() {
    super({
      exceptionFactory: (error) =>
        new BadRequestException(`${error} must be a valid integer`),
    });
  }
}

// Or use options on built-in pipes
@Get(':id')
async findOne(
  @Param(
    'id',
    new ParseIntPipe({
      errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE,
      exceptionFactory: () => new NotAcceptableException('ID must be numeric'),
    }),
  )
  id: number,
): Promise<Item> {
  return this.itemsService.findOne(id);
}
```

Reference: [NestJS Pipes](https://docs.nestjs.com/pipes)

================================================
FILE: .agents/skills/nestjs-best-practices/rules/api-versioning.md
================================================
---
title: Use API Versioning for Breaking Changes
impact: MEDIUM
impactDescription: Versioning allows you to evolve APIs without breaking existing clients
tags: api, versioning, breaking-changes, compatibility
---

## Use API Versioning for Breaking Changes

Use NestJS built-in versioning when making breaking changes to your API. Choose a versioning strategy (URI, header, or media type) and apply it consistently. This allows old clients to continue working while new clients use updated endpoints.

**Incorrect (breaking changes without versioning):**

```typescript
// Breaking changes without versioning
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<User> {
    // Original response: { id, name, email }
    // Later changed to: { id, firstName, lastName, emailAddress }
    // Old clients break!
    return this.usersService.findOne(id);
  }
}

// Manual versioning in routes
@Controller('v1/users')
export class UsersV1Controller {}

@Controller('v2/users')
export class UsersV2Controller {}
// Inconsistent, error-prone, hard to maintain
```

**Correct (use NestJS built-in versioning):**

```typescript
// Enable versioning in main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // URI versioning: /v1/users, /v2/users
  app.enableVersioning({
    type: VersioningType.URI,
    defaultVersion: '1',
  });

  // Or header versioning: X-API-Version: 1
  app.enableVersioning({
    type: VersioningType.HEADER,
    header: 'X-API-Version',
    defaultVersion: '1',
  });

  // Or media type: Accept: application/json;v=1
  app.enableVersioning({
    type: VersioningType.MEDIA_TYPE,
    key: 'v=',
    defaultVersion: '1',
  });

  await app.listen(3000);
}

// Version-specific controllers
@Controller('users')
@Version('1')
export class UsersV1Controller {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<UserV1Response> {
    const user = await this.usersService.findOne(id);
    // V1 response format
    return {
      id: user.id,
      name: user.name,
      email: user.email,
    };
  }
}

@Controller('users')
@Version('2')
export class UsersV2Controller {
  @Get(':id')
  async findOne(@Param('id') id: string): Promise<UserV2Response> {
    const user = await this.usersService.findOne(id);
    // V2 response format with breaking changes
    return {
      id: user.id,
      firstName: user.firstName,
      lastName: user.lastName,
      emailAddress: user.email,
      createdAt: user.createdAt,
    };
  }
}

// Per-route versioning - different versions for different routes
@Controller('users')
export class UsersController {
  @Get()
  @Version('1')
  findAllV1(): Promise<UserV1Response[]> {
    return this.usersService.findAllV1();
  }

  @Get()
  @Version('2')
  findAllV2(): Promise<UserV2Response[]> {
    return this.usersService.findAllV2();
  }

  @Get(':id')
  @Version(['1', '2']) // Same handler for multiple versions
  findOne(@Param('id') id: string): Promise<User> {
    return this.usersService.findOne(id);
  }

  @Post()
  @Version(VERSION_NEUTRAL) // Available in all versions
  create(@Body() dto: CreateUserDto): Promise<User> {
    return this.usersService.create(dto);
  }
}

// Shared service with version-specific logic
@Injectable()
export class UsersService {
  async findOne(id: string, version: string): Promise<any> {
    const user = await this.repo.findOne({ where: { id } });

    if (version === '1') {
      return this.toV1Response(user);
    }
    return this.toV2Response(user);
  }

  private toV1Response(user: User): UserV1Response {
    return {
      id: user.id,
      name: `${user.firstName} ${user.lastName}`,
      email: user.email,
    };
  }

  private toV2Response(user: User): UserV2Response {
    return {
      id: user.id,
      firstName: user.firstName,
      lastName: user.lastName,
      emailAddress: user.email,
      createdAt: user.createdAt,
    };
  }
}

// Controller extracts version
@Controller('users')
export class UsersController {
  @Get(':id')
  async findOne(@Param('id') id: string, @Headers('X-API-Version') version: string = '1'): Promise<any> {
    return this.usersService.findOne(id, version);
  }
}

// Deprecation strategy - mark old versions as deprecated
@Controller('users')
@Version('1')
@UseInterceptors(DeprecationInterceptor)
export class UsersV1Controller {
  // All V1 routes will include deprecation warning
}

@Injectable()
export class DeprecationInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const response = context.switchToHttp().getResponse();
    response.setHeader('Deprecation', 'true');
    response.setHeader('Sunset', 'Sat, 1 Jan 2025 00:00:00 GMT');
    response.setHeader('Link', '</v2/users>; rel="successor-version"');

    return next.handle();
  }
}
```

Reference: [NestJS Versioning](https://docs.nestjs.com/techniques/versioning)

================================================
FILE: .agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md
================================================
---
title: Avoid Circular Dependencies
impact: CRITICAL
impactDescription: '#1 cause of runtime crashes'
tags: architecture, modules, dependencies
---

## Avoid Circular Dependencies

Circular dependencies occur when Module A imports Module B, and Module B imports Module A (directly or transitively). NestJS can sometimes resolve these through forward references, but they indicate architectural problems and should be avoided. This is the #1 cause of runtime crashes in NestJS applications.

**Incorrect (circular module imports):**

```typescript
// users.module.ts
@Module({
  imports: [OrdersModule], // Orders needs Users, Users needs Orders = circular
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

// orders.module.ts
@Module({
  imports: [UsersModule], // Circular dependency!
  providers: [OrdersService],
  exports: [OrdersService],
})
export class OrdersModule {}
```

**Correct (extract shared logic or use events):**

```typescript
// Option 1: Extract shared logic to a third module
// shared.module.ts
@Module({
  providers: [SharedService],
  exports: [SharedService],
})
export class SharedModule {}

// users.module.ts
@Module({
  imports: [SharedModule],
  providers: [UsersService],
})
export class UsersModule {}

// orders.module.ts
@Module({
  imports: [SharedModule],
  providers: [OrdersService],
})
export class OrdersModule {}

// Option 2: Use events for decoupled communication
// users.service.ts
@Injectable()
export class UsersService {
  constructor(private eventEmitter: EventEmitter2) {}

  async createUser(data: CreateUserDto) {
    const user = await this.userRepo.save(data);
    this.eventEmitter.emit('user.created', user);
    return user;
  }
}

// orders.service.ts
@Injectable()
export class OrdersService {
  @OnEvent('user.created')
  handleUserCreated(user: User) {
    // React to user creation without direct dependency
  }
}
```

Reference: [NestJS Circular Dependency](https://docs.nestjs.com/fundamentals/circular-dependency)

================================================
FILE: .agents/skills/nestjs-best-practices/rules/arch-feature-modules.md
================================================
---
title: Organize by Feature Modules
impact: CRITICAL
impactDescription: '3-5x faster onboarding and development'
tags: architecture, modules, organization
---

## Organize by Feature Modules

Organize your application into feature modules that encapsulate related functionality. Each feature module should be self-contained with its own controllers, services, entities, and DTOs. Avoid organizing by technical layer (all controllers together, all services together). This enables 3-5x faster onboarding and feature development.

**Incorrect (technical layer organization):**

```typescript
// Technical layer organization (anti-pattern)
src/
├── controllers/
│   ├── users.controller.ts
│   ├── orders.controller.ts
│   └── products.controller.ts
├── services/
│   ├── users.service.ts
│   ├── orders.service.ts
│   └── products.service.ts
├── entities/
│   ├── user.entity.ts
│   ├── order.entity.ts
│   └── product.entity.ts
└── app.module.ts  // Imports everything directly
```

**Correct (feature module organization):**

```typescript
// Feature module organization
src/
├── users/
│   ├── dto/
│   │   ├── create-user.dto.ts
│   │   └── update-user.dto.ts
│   ├── entities/
│   │   └── user.entity.ts
│   ├── users.controller.ts
│   ├── users.service.ts
│   ├── users.repository.ts
│   └── users.module.ts
├── orders/
│   ├── dto/
│   ├── entities/
│   ├── orders.controller.ts
│   ├── orders.service.ts
│   └── orders.module.ts
├── shared/
│   ├── guards/
│   ├── interceptors/
│   ├── filters/
│   └── shared.module.ts
└── app.module.ts

// users.module.ts
@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService, UsersRepository],
  exports: [UsersService], // Only export what others need
})
export class UsersModule {}

// app.module.ts
@Module({
  imports: [
Download .txt
gitextract_5q18uku4/

├── .agents/
│   └── skills/
│       ├── nestjs-best-practices/
│       │   ├── .github/
│       │   │   └── workflows/
│       │   │       ├── branch-protection.yml
│       │   │       └── deploy.yml
│       │   ├── .gitignore
│       │   ├── AGENTS.md
│       │   ├── README.md
│       │   ├── SKILL.md
│       │   ├── rules/
│       │   │   ├── api-use-dto-serialization.md
│       │   │   ├── api-use-interceptors.md
│       │   │   ├── api-use-pipes.md
│       │   │   ├── api-versioning.md
│       │   │   ├── arch-avoid-circular-deps.md
│       │   │   ├── arch-feature-modules.md
│       │   │   ├── arch-module-sharing.md
│       │   │   ├── arch-single-responsibility.md
│       │   │   ├── arch-use-events.md
│       │   │   ├── arch-use-repository-pattern.md
│       │   │   ├── db-avoid-n-plus-one.md
│       │   │   ├── db-use-migrations.md
│       │   │   ├── db-use-transactions.md
│       │   │   ├── devops-graceful-shutdown.md
│       │   │   ├── devops-use-config-module.md
│       │   │   ├── devops-use-logging.md
│       │   │   ├── di-avoid-service-locator.md
│       │   │   ├── di-interface-segregation.md
│       │   │   ├── di-liskov-substitution.md
│       │   │   ├── di-prefer-constructor-injection.md
│       │   │   ├── di-scope-awareness.md
│       │   │   ├── di-use-interfaces-tokens.md
│       │   │   ├── error-handle-async-errors.md
│       │   │   ├── error-throw-http-exceptions.md
│       │   │   ├── error-use-exception-filters.md
│       │   │   ├── micro-use-health-checks.md
│       │   │   ├── micro-use-patterns.md
│       │   │   ├── micro-use-queues.md
│       │   │   ├── perf-async-hooks.md
│       │   │   ├── perf-lazy-loading.md
│       │   │   ├── perf-optimize-database.md
│       │   │   ├── perf-use-caching.md
│       │   │   ├── security-auth-jwt.md
│       │   │   ├── security-rate-limiting.md
│       │   │   ├── security-sanitize-output.md
│       │   │   ├── security-use-guards.md
│       │   │   ├── security-validate-all-input.md
│       │   │   ├── test-e2e-supertest.md
│       │   │   ├── test-mock-external-services.md
│       │   │   └── test-use-testing-module.md
│       │   └── scripts/
│       │       ├── build-agents.ts
│       │       ├── build.sh
│       │       └── package.json
│       ├── typeorm/
│       │   └── SKILL.md
│       └── typescript-advanced-types/
│           └── SKILL.md
├── .dockerignore
├── .editorconfig
├── .eslintignore
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── data-issue-report.md
│   │   └── feature-request.md
│   ├── auto-label.json
│   ├── copilot-instructions.md
│   ├── pull_request_template.md
│   └── workflows/
│       ├── deploy-sloths.yaml
│       ├── deploy.yaml
│       ├── pull_request.yml
│       ├── pull_request_close.yml
│       └── renovate.yml
├── .gitignore
├── .oxfmtrc.json
├── AGENTS.md
├── CONTRIBUTING.md
├── DOMAIN.md
├── GUIDELINES.md
├── LICENSE
├── README.md
├── VITEST.md
├── client/
│   ├── .dockerignore
│   ├── Dockerfile
│   ├── Dockerfile.lambda
│   ├── README.md
│   ├── eslint.config.mjs
│   ├── next-env.d.ts
│   ├── next.config.mjs
│   ├── next.config.prod.mjs
│   ├── package.json
│   ├── playwright.config.ts
│   ├── public/
│   │   └── static/
│   │       └── empty.txt
│   ├── specs/
│   │   └── smoke.spec.ts
│   ├── src/
│   │   ├── __mocks__/
│   │   │   ├── axios.js
│   │   │   ├── hooks/
│   │   │   │   ├── index.ts
│   │   │   │   ├── useMessage.tsx
│   │   │   │   └── useTheme.tsx
│   │   │   └── next/
│   │   │       └── config.ts
│   │   ├── __tests__/
│   │   │   ├── ProfilePage.test.tsx
│   │   │   └── __snapshots__/
│   │   │       └── ProfilePage.test.tsx.snap
│   │   ├── api/
│   │   │   ├── .gitignore
│   │   │   ├── .npmignore
│   │   │   ├── .openapi-generator/
│   │   │   │   ├── FILES
│   │   │   │   └── VERSION
│   │   │   ├── .openapi-generator-ignore
│   │   │   ├── api.ts
│   │   │   ├── base.ts
│   │   │   ├── common.ts
│   │   │   ├── configuration.ts
│   │   │   ├── git_push.sh
│   │   │   └── index.ts
│   │   ├── components/
│   │   │   ├── Analytics.tsx
│   │   │   ├── Comment.tsx
│   │   │   ├── CountBadge/
│   │   │   │   ├── CountBadge.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── CoursePageLayout.tsx
│   │   │   ├── DevTools/
│   │   │   │   ├── DevToolsContainer.tsx
│   │   │   │   ├── DevToolsCurrentUser.tsx
│   │   │   │   ├── DevToolsUsers.tsx
│   │   │   │   └── index.ts
│   │   │   ├── Footer/
│   │   │   │   ├── Donation.tsx
│   │   │   │   ├── Feedback.tsx
│   │   │   │   ├── FooterLayout.tsx
│   │   │   │   ├── Help.tsx
│   │   │   │   ├── Menu.tsx
│   │   │   │   ├── SocialNetworks.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── HeaderMiniBannerCarousel.module.css
│   │   │   ├── HeaderMiniBannerCarousel.test.tsx
│   │   │   ├── HeaderMiniBannerCarousel.tsx
│   │   │   ├── Heroes/
│   │   │   │   ├── HeroesCountBadge.tsx
│   │   │   │   ├── HeroesRadarTab.tsx
│   │   │   │   └── HeroesRadarTable.tsx
│   │   │   ├── LoadingScreen.module.css
│   │   │   ├── MentorOptions.tsx
│   │   │   ├── Profile/
│   │   │   │   ├── AboutCard.tsx
│   │   │   │   ├── CommonCard.tsx
│   │   │   │   ├── CommonCardWithSettingsModal.tsx
│   │   │   │   ├── ContactsCard.tsx
│   │   │   │   ├── ContactsCardForm.tsx
│   │   │   │   ├── DiscordCard.tsx
│   │   │   │   ├── EducationCard.tsx
│   │   │   │   ├── EmailConfirmation.tsx
│   │   │   │   ├── InterviewCard.tsx
│   │   │   │   ├── InterviewModal.tsx
│   │   │   │   ├── LanguagesCard.tsx
│   │   │   │   ├── MainCard.tsx
│   │   │   │   ├── MentorStatsCard.tsx
│   │   │   │   ├── MentorStatsModal.tsx
│   │   │   │   ├── ObfuscateConfirmationModal.tsx
│   │   │   │   ├── ProfileSettingsModal.module.css
│   │   │   │   ├── ProfileSettingsModal.tsx
│   │   │   │   ├── PublicFeedbackCard.tsx
│   │   │   │   ├── PublicFeedbackModal.tsx
│   │   │   │   ├── StudentLeaveCourse.tsx
│   │   │   │   ├── StudentStatsCard.tsx
│   │   │   │   ├── StudentStatsModal.tsx
│   │   │   │   ├── __test__/
│   │   │   │   │   ├── AboutCard.test.tsx
│   │   │   │   │   ├── CommonCard.test.tsx
│   │   │   │   │   ├── CommonCardWithSettingsModal.test.tsx
│   │   │   │   │   ├── ContactsCard.test.tsx
│   │   │   │   │   ├── ContactsCardForm.test.tsx
│   │   │   │   │   ├── EducationCard.test.tsx
│   │   │   │   │   ├── InterviewCard.test.tsx
│   │   │   │   │   ├── InterviewModal.test.tsx
│   │   │   │   │   ├── MainCard.test.tsx
│   │   │   │   │   ├── MentorStatsCard.test.tsx
│   │   │   │   │   ├── MentorStatsModal.test.tsx
│   │   │   │   │   ├── ProfileSettingsModal.test.tsx
│   │   │   │   │   ├── PublicFeedbackCard.test.tsx
│   │   │   │   │   ├── PublicFeedbackModal.test.tsx
│   │   │   │   │   ├── StudentStatsCard.test.tsx
│   │   │   │   │   ├── StudentStatsModal.test.tsx
│   │   │   │   │   └── __snapshots__/
│   │   │   │   │       ├── AboutCard.test.tsx.snap
│   │   │   │   │       ├── CommonCard.test.tsx.snap
│   │   │   │   │       ├── CommonCardWithSettingsModal.test.tsx.snap
│   │   │   │   │       ├── ContactsCard.test.tsx.snap
│   │   │   │   │       ├── ContactsCardForm.test.tsx.snap
│   │   │   │   │       ├── EducationCard.test.tsx.snap
│   │   │   │   │       ├── MainCard.test.tsx.snap
│   │   │   │   │       ├── ProfileSettingsModal.test.tsx.snap
│   │   │   │   │       ├── PublicFeedbackCard.test.tsx.snap
│   │   │   │   │       ├── PublicFeedbackModal.test.tsx.snap
│   │   │   │   │       ├── StudentStatsCard.test.tsx.snap
│   │   │   │   │       └── StudentStatsModal.test.tsx.snap
│   │   │   │   └── ui/
│   │   │   │       ├── DateWidget.tsx
│   │   │   │       ├── ExpandButtonWidget.tsx
│   │   │   │       ├── InterviewerWidget.tsx
│   │   │   │       ├── IsGoodCandidateWidget.tsx
│   │   │   │       ├── LegacyScreeningFeedback.tsx
│   │   │   │       ├── PrescreeningFeedback.tsx
│   │   │   │       ├── ScoreWidget.tsx
│   │   │   │       ├── __tests__/
│   │   │   │       │   ├── DateWidget.test.tsx
│   │   │   │       │   ├── ExpandButtonWidget.test.tsx
│   │   │   │       │   ├── InterviewerWidget.test.tsx
│   │   │   │       │   ├── IsGoodCandidateWidget.test.tsx
│   │   │   │       │   └── ScoreWidget.test.tsx
│   │   │   │       └── index.ts
│   │   │   ├── RegistrationPageLayout.tsx
│   │   │   ├── SelectLanguages.tsx
│   │   │   ├── SettingsItem.tsx
│   │   │   ├── SlothImage.tsx
│   │   │   ├── Student/
│   │   │   │   ├── AssignStudentModal.tsx
│   │   │   │   ├── DashboardDetails.module.css
│   │   │   │   ├── DashboardDetails.tsx
│   │   │   │   └── index.ts
│   │   │   ├── StudentDiscord.tsx
│   │   │   ├── TabsWithCounter/
│   │   │   │   └── renderers.tsx
│   │   │   ├── Warning/
│   │   │   │   └── index.tsx
│   │   │   ├── WelcomeCard.tsx
│   │   │   ├── __tests__/
│   │   │   │   ├── CopyToClipboardButton.test.tsx
│   │   │   │   ├── GithubUserLink.test.tsx
│   │   │   │   ├── Rating.test.tsx
│   │   │   │   └── StudenDiscrod.test.tsx
│   │   │   ├── common/
│   │   │   │   └── CustomPopconfirm.tsx
│   │   │   ├── useLoading.tsx
│   │   │   ├── withGoogleMaps.tsx
│   │   │   └── withSession.tsx
│   │   ├── configs/
│   │   │   ├── cdn.ts
│   │   │   ├── course-icons.ts
│   │   │   ├── discord-integration.ts
│   │   │   ├── gcp.ts
│   │   │   ├── heroes-badges.ts
│   │   │   ├── registry.ts
│   │   │   └── timezones.ts
│   │   ├── data/
│   │   │   ├── course-leave-reasons.ts
│   │   │   ├── english.ts
│   │   │   ├── eventTypes.ts
│   │   │   ├── index.ts
│   │   │   ├── interviews/
│   │   │   │   ├── __tests__/
│   │   │   │   │   └── templateValidator.test.ts
│   │   │   │   ├── angular.ts
│   │   │   │   ├── corejs1.ts
│   │   │   │   ├── corejs2.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── react.ts
│   │   │   │   ├── shortTrackJavaScript.ts
│   │   │   │   ├── shortTrackPerformance.ts
│   │   │   │   ├── shortTrackScreening.ts
│   │   │   │   ├── shortTrackTypeScript.ts
│   │   │   │   ├── technical-screening.tsx
│   │   │   │   ├── templateValidator.ts
│   │   │   │   └── types.ts
│   │   │   ├── skills.ts
│   │   │   ├── taskTypes.ts
│   │   │   └── tshirts.ts
│   │   ├── domain/
│   │   │   ├── course.test.ts
│   │   │   ├── course.ts
│   │   │   ├── interview.test.ts
│   │   │   ├── interview.tsx
│   │   │   ├── user.test.tsx
│   │   │   └── user.ts
│   │   ├── hooks/
│   │   │   └── index.ts
│   │   ├── index.d.ts
│   │   ├── modules/
│   │   │   ├── AutoTest/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AttemptsAnswers/
│   │   │   │   │   │   └── AttemptsAnswers.tsx
│   │   │   │   │   ├── AutoTestTaskCard/
│   │   │   │   │   │   └── AutoTestTaskCard.tsx
│   │   │   │   │   ├── Coding/
│   │   │   │   │   │   ├── Coding.test.tsx
│   │   │   │   │   │   └── Coding.tsx
│   │   │   │   │   ├── Exercise/
│   │   │   │   │   │   └── Exercise.tsx
│   │   │   │   │   ├── JupyterNotebook/
│   │   │   │   │   │   └── JupyterNotebook.tsx
│   │   │   │   │   ├── Question/
│   │   │   │   │   │   ├── Question.module.css
│   │   │   │   │   │   └── Question.tsx
│   │   │   │   │   ├── SelfEducation/
│   │   │   │   │   │   ├── SelfEducation.module.css
│   │   │   │   │   │   ├── SelfEducation.test.tsx
│   │   │   │   │   │   └── SelfEducation.tsx
│   │   │   │   │   ├── StatusTabs/
│   │   │   │   │   │   ├── StatusTabs.test.tsx
│   │   │   │   │   │   ├── StatusTabs.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── TaskCard/
│   │   │   │   │   │   ├── TaskCard.test.tsx
│   │   │   │   │   │   └── TaskCard.tsx
│   │   │   │   │   ├── TaskCardColumn/
│   │   │   │   │   │   └── TaskCardColumn.tsx
│   │   │   │   │   ├── TaskDeadlineDate/
│   │   │   │   │   │   ├── TaskDeadlineDate.test.tsx
│   │   │   │   │   │   └── TaskDeadlineDate.tsx
│   │   │   │   │   ├── TaskDescription/
│   │   │   │   │   │   └── TaskDescription.tsx
│   │   │   │   │   ├── VerificationInformation/
│   │   │   │   │   │   ├── VerificationInformation.test.tsx
│   │   │   │   │   │   └── VerificationInformation.tsx
│   │   │   │   │   ├── VerificationsTable/
│   │   │   │   │   │   ├── VerificationsTable.test.tsx
│   │   │   │   │   │   ├── VerificationsTable.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useAttemptsMessage/
│   │   │   │   │   │   ├── useAttemptsMessage.test.ts
│   │   │   │   │   │   └── useAttemptsMessage.ts
│   │   │   │   │   ├── useCourseTaskSubmit/
│   │   │   │   │   │   ├── useCourseTaskSubmit.test.ts
│   │   │   │   │   │   └── useCourseTaskSubmit.ts
│   │   │   │   │   ├── useCourseTaskVerifications/
│   │   │   │   │   │   └── useCourseTaskVerifications.ts
│   │   │   │   │   └── useVerificationsAnswers/
│   │   │   │   │       └── useVerificationsAnswers.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── AutoTests/
│   │   │   │   │   │   └── AutoTests.tsx
│   │   │   │   │   ├── Task/
│   │   │   │   │   │   └── Task.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       └── map.ts
│   │   │   ├── Contributor/
│   │   │   │   ├── components/
│   │   │   │   │   ├── ContributorModal.tsx
│   │   │   │   │   └── ContributorsTable.tsx
│   │   │   │   └── pages/
│   │   │   │       └── ContributorPage.tsx
│   │   │   ├── Course/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CourseNoAccess.tsx
│   │   │   │   │   └── NoSubmissionAvailable/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── contexts/
│   │   │   │   │   ├── ActiveCourseContext.tsx
│   │   │   │   │   ├── SessionContext.test.tsx
│   │   │   │   │   ├── SessionContext.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   └── pages/
│   │   │   │       ├── CouseNoAccess/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── Student/
│   │   │   │           └── CrossCheckSubmit/
│   │   │   │               └── index.tsx
│   │   │   ├── CourseManagement/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CertificateCriteriaModal/
│   │   │   │   │   │   ├── CertificateCriteriaModal.test.tsx
│   │   │   │   │   │   └── CertificateCriteriaModal.tsx
│   │   │   │   │   ├── CourseEventModal/
│   │   │   │   │   │   ├── formState.ts
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CourseModal/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CourseTaskModal/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CoursesListModal/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ExpelCriteriaModal/
│   │   │   │   │   │   ├── ExpelCriteriaModal.test.tsx
│   │   │   │   │   │   └── ExpelCriteriaModal.tsx
│   │   │   │   │   ├── ExpelledStudentsStats.tsx
│   │   │   │   │   ├── SelectCourseTasks/
│   │   │   │   │   │   ├── SelectCourseTasks.test.tsx
│   │   │   │   │   │   └── SelectCourseTasks.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   └── hooks/
│   │   │   │       └── useExpelledStats.ts
│   │   │   ├── CourseStatistics/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CountriesChart/
│   │   │   │   │   │   └── CountriesChart.tsx
│   │   │   │   │   ├── DonutChart/
│   │   │   │   │   │   └── DonutChart.tsx
│   │   │   │   │   ├── EpamMentorsStatsCard/
│   │   │   │   │   │   ├── EpamMentorsStatsCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── LiquidChart/
│   │   │   │   │   │   └── LiquidChart.tsx
│   │   │   │   │   ├── MentorsCountriesCard/
│   │   │   │   │   │   ├── MentorsCountriesCard.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StatCards/
│   │   │   │   │   │   ├── StatCards.module.css
│   │   │   │   │   │   ├── StatCards.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StatScopeSelector/
│   │   │   │   │   │   ├── StatScopeSelector.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StudentsCertificatesCountriesCard/
│   │   │   │   │   │   ├── StudentsCertificatesCountriesCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsCountriesCard/
│   │   │   │   │   │   ├── StudentsCountriesCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsEligibleForCertificationCard/
│   │   │   │   │   │   ├── StudentsEligibleForCertificationCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsStatsCard/
│   │   │   │   │   │   ├── StudentsStatsCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsWithCertificateCard/
│   │   │   │   │   │   ├── StudentsWithCertificateCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentsWithMentorsCard/
│   │   │   │   │   │   ├── StudentsWithMentorsCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── TaskPerformanceCard/
│   │   │   │   │       ├── TaskPerformanceCard.tsx
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── data.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useCourseStats.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── pages/
│   │   │   │       └── CourseStatistics.tsx
│   │   │   ├── CrossCheck/
│   │   │   │   ├── AddCriteriaForCrossCheck.tsx
│   │   │   │   ├── CriteriaActions.tsx
│   │   │   │   ├── CriteriaTypeSelect.tsx
│   │   │   │   ├── DeleteAllCrossCheckCriteriaButton.tsx
│   │   │   │   ├── EditableCellForCrossCheck.tsx
│   │   │   │   ├── EditableCriteriaInput.tsx
│   │   │   │   ├── EditableTableForCrossCheck.tsx
│   │   │   │   ├── ExportJSONButton.tsx
│   │   │   │   ├── UploadCriteriaJSON.tsx
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── AddCriteriaForCrossCheck.test.tsx
│   │   │   │   │   ├── ExportJSONButton.test.tsx
│   │   │   │   │   ├── UploadCriteriaJSON.test.tsx
│   │   │   │   │   └── __snapshots__/
│   │   │   │   │       └── AddCriteriaForCrossCheck.test.tsx.snap
│   │   │   │   ├── components/
│   │   │   │   │   ├── CriteriaForm.tsx
│   │   │   │   │   ├── CrossCheckAssignmentLink.tsx
│   │   │   │   │   ├── CrossCheckCriteriaForm.module.css
│   │   │   │   │   ├── CrossCheckCriteriaForm.tsx
│   │   │   │   │   ├── CrossCheckHistory.tsx
│   │   │   │   │   ├── DragHandle.module.css
│   │   │   │   │   ├── DragHandle.tsx
│   │   │   │   │   ├── DragSortTable.tsx
│   │   │   │   │   ├── SolutionReview/
│   │   │   │   │   │   ├── Message/
│   │   │   │   │   │   │   ├── Message.test.tsx
│   │   │   │   │   │   │   ├── Message.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── MessageSendingPanel/
│   │   │   │   │   │   │   ├── MessageSendingPanel.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── SolutionReview.module.css
│   │   │   │   │   │   ├── SolutionReview.tsx
│   │   │   │   │   │   ├── UserAvatar/
│   │   │   │   │   │   │   ├── UserAvatar.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── Username/
│   │   │   │   │   │   │   ├── Username.test.tsx
│   │   │   │   │   │   │   ├── Username.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── helpers.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── SolutionReviewSettingsPanel/
│   │   │   │   │   │   ├── SolutionReviewSettingsPanel.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── SubmittedStatus.tsx
│   │   │   │   │   └── criteria/
│   │   │   │   │       ├── CrossCheckCriteria.tsx
│   │   │   │   │       ├── CrossCheckCriteriaModal.tsx
│   │   │   │   │       ├── PenaltyCriteria.tsx
│   │   │   │   │       ├── SubtaskCriteria.tsx
│   │   │   │   │       └── TitleCriteria.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useSolutionReviewSettings.ts
│   │   │   │   ├── index.tsx
│   │   │   │   └── utils/
│   │   │   │       ├── addKeyAndIndex.tsx
│   │   │   │       ├── arrayMoveImmutable.tsx
│   │   │   │       └── getCriteriaStatusColor.ts
│   │   │   ├── CrossCheckPairs/
│   │   │   │   ├── components/
│   │   │   │   │   ├── BadReview/
│   │   │   │   │   │   ├── BadReviewControllers.tsx
│   │   │   │   │   │   └── BadReviewTable.tsx
│   │   │   │   │   └── CrossCheckPairsTable/
│   │   │   │   │       ├── CrossCheckPairsTable.module.css
│   │   │   │   │       └── CrossCheckPairsTable.tsx
│   │   │   │   ├── data/
│   │   │   │   │   └── getCrossCheckPairsColumns.tsx
│   │   │   │   └── pages/
│   │   │   │       └── CrossCheckPairs/
│   │   │   │           ├── CrossCheckPairs.tsx
│   │   │   │           └── index.ts
│   │   │   ├── Discipline/
│   │   │   │   ├── components/
│   │   │   │   │   ├── DisciplineModal.tsx
│   │   │   │   │   └── DisciplineTable.tsx
│   │   │   │   └── pages/
│   │   │   │       └── DisciplinePage.tsx
│   │   │   ├── DiscordAdmin/
│   │   │   │   ├── components/
│   │   │   │   │   ├── DiscordServersModal.tsx
│   │   │   │   │   └── DiscordServersTable.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useDiscordServers.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── pages/
│   │   │   │       └── DiscordAdminPage/
│   │   │   │           ├── DiscordAdminPage.tsx
│   │   │   │           └── index.ts
│   │   │   ├── EventsAdmin/
│   │   │   │   ├── components/
│   │   │   │   │   ├── EventsModal.tsx
│   │   │   │   │   └── EventsTable.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useEvents.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── pages/
│   │   │   │       └── EventsAdminPage/
│   │   │   │           ├── EventsAdminPage.tsx
│   │   │   │           └── index.ts
│   │   │   ├── Feedback/
│   │   │   │   ├── components/
│   │   │   │   │   └── FeedbackForm.tsx
│   │   │   │   └── data/
│   │   │   │       └── softSkills.ts
│   │   │   ├── Home/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CourseLinks/
│   │   │   │   │   │   ├── CourseLinks.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── CourseSelector/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── HomeSummary/
│   │   │   │   │   │   ├── HomeSummary.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── NoCourse/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── RegistryBanner/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── SystemAlerts/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── data/
│   │   │   │   │   ├── links.tsx
│   │   │   │   │   └── loadHomeData.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useActiveCourse.test.tsx
│   │   │   │   │   ├── useActiveCourse.tsx
│   │   │   │   │   └── useStudentSummary.tsx
│   │   │   │   └── pages/
│   │   │   │       └── HomePage/
│   │   │   │           └── index.tsx
│   │   │   ├── Interview/
│   │   │   │   └── Student/
│   │   │   │       ├── components/
│   │   │   │       │   ├── AlertDescription.module.css
│   │   │   │       │   ├── AlertDescription.tsx
│   │   │   │       │   ├── ExtraInfo.tsx
│   │   │   │       │   ├── InterviewCard.tsx
│   │   │   │       │   ├── InterviewDescription.tsx
│   │   │   │       │   ├── NoInterviewsAlert.tsx
│   │   │   │       │   └── StatusLabel.tsx
│   │   │   │       ├── data/
│   │   │   │       │   └── getInterviewCardDetails.tsx
│   │   │   │       └── index.ts
│   │   │   ├── Interviews/
│   │   │   │   ├── data/
│   │   │   │   │   ├── getInterviewData.ts
│   │   │   │   │   ├── getStageInterviewData.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── pages/
│   │   │   │       ├── InterviewFeedback/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── StageInterviewFeedback/
│   │   │   │           ├── CustomQuestion.tsx
│   │   │   │           ├── FormItem.tsx
│   │   │   │           ├── NestedRadio.tsx
│   │   │   │           ├── QuestionCard.tsx
│   │   │   │           ├── QuestionList.tsx
│   │   │   │           ├── QuestionsPicker.tsx
│   │   │   │           ├── StageInterviewFeedback.tsx
│   │   │   │           ├── StepContext.tsx
│   │   │   │           ├── StepForm.tsx
│   │   │   │           ├── Steps.tsx
│   │   │   │           ├── StepsContent.tsx
│   │   │   │           ├── StudentInfo.tsx
│   │   │   │           ├── SubHeader.module.css
│   │   │   │           ├── SubHeader.tsx
│   │   │   │           ├── feedbackTemplateHandler.test.ts
│   │   │   │           ├── feedbackTemplateHandler.ts
│   │   │   │           └── index.ts
│   │   │   ├── Mentor/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Instructions/
│   │   │   │   │   │   ├── Instructions.tsx
│   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── MentorDashboard/
│   │   │   │   │   │   ├── MentorDashboard.test.tsx
│   │   │   │   │   │   ├── MentorDashboard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Notification/
│   │   │   │   │   │   ├── Notification.test.tsx
│   │   │   │   │   │   ├── Notification.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ReviewRandomTask/
│   │   │   │   │   │   ├── ReviewRandomTask.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── SubmitReviewModal/
│   │   │   │   │   │   ├── SubmitReviewModal.test.tsx
│   │   │   │   │   │   ├── SubmitReviewModal.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── TaskSolutionsTable/
│   │   │   │   │   │   ├── TaskSolutionsTable.test.tsx
│   │   │   │   │   │   ├── TaskSolutionsTable.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── TaskStatusTabs/
│   │   │   │   │   │   ├── TaskStatusTabs.test.tsx
│   │   │   │   │   │   ├── TaskStatusTabs.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── data/
│   │   │   │   │   └── softSkills.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useMentorDashboard.tsx
│   │   │   │   │   └── useMentorStudents.tsx
│   │   │   │   └── pages/
│   │   │   │       ├── InterviewWaitingList/
│   │   │   │       │   └── index.tsx
│   │   │   │       ├── Interviews/
│   │   │   │       │   ├── components/
│   │   │   │       │   │   ├── InterviewCard.module.css
│   │   │   │       │   │   ├── InterviewCard.tsx
│   │   │   │       │   │   ├── InterviewDetails.tsx
│   │   │   │       │   │   ├── InterviewsList.module.css
│   │   │   │       │   │   ├── InterviewsList.tsx
│   │   │   │       │   │   ├── InterviewsSummary.tsx
│   │   │   │       │   │   ├── MentorPreferencesModal.tsx
│   │   │   │       │   │   ├── RegistrationNotice.test.tsx
│   │   │   │       │   │   ├── RegistrationNoticeAlert.module.css
│   │   │   │       │   │   ├── RegistrationNoticeAlert.tsx
│   │   │   │       │   │   ├── SelectMentorModal.tsx
│   │   │   │       │   │   ├── StudentInterview.module.css
│   │   │   │       │   │   ├── StudentInterview.tsx
│   │   │   │       │   │   ├── WaitListAlert.module.css
│   │   │   │       │   │   └── WaitListAlert.tsx
│   │   │   │       │   ├── hooks/
│   │   │   │       │   │   └── useAlert.ts
│   │   │   │       │   ├── index.module.css
│   │   │   │       │   └── index.tsx
│   │   │   │       ├── StudentFeedback/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── Students/
│   │   │   │           └── index.tsx
│   │   │   ├── MentorRegistry/
│   │   │   │   ├── components/
│   │   │   │   │   ├── InviteMentorsModal.tsx
│   │   │   │   │   ├── MentorRegistryDeleteModal.tsx
│   │   │   │   │   ├── MentorRegistryResendModal.tsx
│   │   │   │   │   ├── MentorRegistryTable.tsx
│   │   │   │   │   ├── MentorRegistryTableContainer.module.css
│   │   │   │   │   └── MentorRegistryTableContainer.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   └── index.ts
│   │   │   ├── MentorTasksReview/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AssignReviewerModal/
│   │   │   │   │   │   ├── AssignReviewerModal.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── ReviewsTable/
│   │   │   │   │       ├── index.tsx
│   │   │   │   │       └── renderers.tsx
│   │   │   │   └── pages/
│   │   │   │       ├── MentorTasksReview.constants.ts
│   │   │   │       └── MentorTasksReview.tsx
│   │   │   ├── MentorsHallOfFame/
│   │   │   │   ├── components/
│   │   │   │   │   └── MentorCard/
│   │   │   │   │       ├── MentorCard.module.css
│   │   │   │   │       ├── MentorCard.test.tsx
│   │   │   │   │       └── MentorCard.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── MentorsHallOfFamePage.test.tsx
│   │   │   │   │   └── MentorsHallOfFamePage.tsx
│   │   │   │   ├── services/
│   │   │   │   │   ├── mentors-hall-of-fame.service.test.ts
│   │   │   │   │   └── mentors-hall-of-fame.service.ts
│   │   │   │   └── types.ts
│   │   │   ├── NotAccess/
│   │   │   │   ├── NotAccess.tsx
│   │   │   │   └── index.ts
│   │   │   ├── Notifications/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Consents.tsx
│   │   │   │   │   ├── NotificationSettingsModal.module.css
│   │   │   │   │   ├── NotificationSettingsModal.tsx
│   │   │   │   │   ├── NotificationSettingsTable.tsx
│   │   │   │   │   ├── NotificationsUserSettingsTable.module.css
│   │   │   │   │   └── NotificationsUserSettingsTable.tsx
│   │   │   │   ├── pages/
│   │   │   │   │   ├── AdminNotificationsPage/
│   │   │   │   │   │   ├── AdminNotificationsSettingsPage.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ConnectionConfirmedPage.tsx
│   │   │   │   │   └── UserNotificationsSettingsPage.tsx
│   │   │   │   └── services/
│   │   │   │       └── notifications.ts
│   │   │   ├── Opportunities/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AvatarCv/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── EditCv/
│   │   │   │   │   │   ├── ContactsForm/
│   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── GeneralInfoForm/
│   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── VisibleCoursesForm/
│   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── form-validation.ts
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── EditViewCv/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ExpirationTooltip/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Link/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── NameTitle/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── NoConsentView/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── PublicLink/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── StudentStatus/
│   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── ViewCv/
│   │   │   │   │       ├── AboutSection/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── ActionButtons/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── BaseSection/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── ContactsSection/
│   │   │   │   │       │   ├── ContactsList/
│   │   │   │   │       │   │   ├── index.module.css
│   │   │   │   │       │   │   ├── index.test.tsx
│   │   │   │   │       │   │   └── index.tsx
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── CoursesSection/
│   │   │   │   │       │   ├── CoursesSection.module.css
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── DataTextValue/
│   │   │   │   │       │   ├── DataTextValue.module.css
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── FeedbackSection/
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── GratitudeSection/
│   │   │   │   │       │   ├── GratitudeList/
│   │   │   │   │       │   │   ├── index.test.tsx
│   │   │   │   │       │   │   └── index.tsx
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── PersonalSection/
│   │   │   │   │       │   ├── PersonalSection.module.css
│   │   │   │   │       │   ├── index.test.tsx
│   │   │   │   │       │   └── index.tsx
│   │   │   │   │       ├── index.test.tsx
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── data/
│   │   │   │   │   ├── __snapshots__/
│   │   │   │   │   │   └── getPersonalToRender.test.tsx.snap
│   │   │   │   │   ├── getContactsToRender.test.tsx
│   │   │   │   │   ├── getContactsToRender.ts
│   │   │   │   │   ├── getPersonalToRender.test.tsx
│   │   │   │   │   └── getPersonalToRender.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useExpiration.test.tsx
│   │   │   │   │   ├── useExpiration.ts
│   │   │   │   │   ├── useResumeData.test.tsx
│   │   │   │   │   ├── useResumeData.tsx
│   │   │   │   │   ├── useViewData.test.tsx
│   │   │   │   │   └── useViewData.tsx
│   │   │   │   ├── models.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── EditPage/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── PublicPage/
│   │   │   │   │       ├── getServerSideProps.ts
│   │   │   │   │       └── index.tsx
│   │   │   │   └── transformers/
│   │   │   │       ├── index.ts
│   │   │   │       ├── splitDataForForms.test.ts
│   │   │   │       ├── splitDataForForms.ts
│   │   │   │       ├── transformFieldsData.test.ts
│   │   │   │       ├── transformFieldsData.ts
│   │   │   │       ├── transformInitialCvData.test.ts
│   │   │   │       └── transformInitialCvData.ts
│   │   │   ├── Profile/
│   │   │   │   └── components/
│   │   │   │       └── MentorEndorsement/
│   │   │   │           ├── MentorEndorsement.tsx
│   │   │   │           └── index.tsx
│   │   │   ├── Prompts/
│   │   │   │   ├── components/
│   │   │   │   │   ├── PromptModal.tsx
│   │   │   │   │   └── PromptTable.tsx
│   │   │   │   └── pages/
│   │   │   │       └── PromptPage.tsx
│   │   │   ├── Registry/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Cards/
│   │   │   │   │   │   ├── AdditionalInfo/
│   │   │   │   │   │   │   ├── AdditionalInfo.test.tsx
│   │   │   │   │   │   │   └── AdditionalInfo.tsx
│   │   │   │   │   │   ├── ContactInfo/
│   │   │   │   │   │   │   ├── ContactInfo.test.tsx
│   │   │   │   │   │   │   └── ContactInfo.tsx
│   │   │   │   │   │   ├── CourseDetails/
│   │   │   │   │   │   │   ├── CourseDetails.test.tsx
│   │   │   │   │   │   │   └── CourseDetails.tsx
│   │   │   │   │   │   ├── Disciplines/
│   │   │   │   │   │   │   ├── Disciplines.test.tsx
│   │   │   │   │   │   │   └── Disciplines.tsx
│   │   │   │   │   │   ├── PersonalInfo/
│   │   │   │   │   │   │   ├── PersonalInfo.test.tsx
│   │   │   │   │   │   │   └── PersonalInfo.tsx
│   │   │   │   │   │   └── Preferences/
│   │   │   │   │   │       ├── Preferences.test.tsx
│   │   │   │   │   │       └── Preferences.tsx
│   │   │   │   │   ├── CourseCertificateAlert/
│   │   │   │   │   │   └── CourseCertificateAlert.tsx
│   │   │   │   │   ├── CourseLabel/
│   │   │   │   │   │   └── CourseLabel.tsx
│   │   │   │   │   ├── DataProcessingCheckbox/
│   │   │   │   │   │   ├── DataProcessingCheckbox.test.tsx
│   │   │   │   │   │   └── DataProcessingCheckbox.tsx
│   │   │   │   │   ├── Footer/
│   │   │   │   │   │   └── Footer.tsx
│   │   │   │   │   ├── FormButtons/
│   │   │   │   │   │   ├── FormButtons.test.tsx
│   │   │   │   │   │   └── FormButtons.tsx
│   │   │   │   │   ├── FormCard/
│   │   │   │   │   │   └── FormCard.tsx
│   │   │   │   │   ├── FormSections/
│   │   │   │   │   │   ├── DoneSection/
│   │   │   │   │   │   │   ├── DoneSection.test.tsx
│   │   │   │   │   │   │   └── DoneSection.tsx
│   │   │   │   │   │   ├── GeneralSection/
│   │   │   │   │   │   │   ├── GeneralSection.test.tsx
│   │   │   │   │   │   │   └── GeneralSection.tsx
│   │   │   │   │   │   └── MentorshipSection/
│   │   │   │   │   │       ├── MentorshipSection.test.tsx
│   │   │   │   │   │       └── MentorshipSection.tsx
│   │   │   │   │   ├── Header/
│   │   │   │   │   │   └── Header.tsx
│   │   │   │   │   ├── LanguagesMentoring/
│   │   │   │   │   │   ├── LanguagesMentoring.test.tsx
│   │   │   │   │   │   └── LanguagesMentoring.tsx
│   │   │   │   │   ├── NoCourses/
│   │   │   │   │   │   └── NoCourses.tsx
│   │   │   │   │   ├── RegistrationForm/
│   │   │   │   │   │   ├── RegistrationForm.test.tsx
│   │   │   │   │   │   └── RegistrationForm.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── constants/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useFormLayout/
│   │   │   │   │   │   └── useFormLayout.ts
│   │   │   │   │   ├── useMentorData/
│   │   │   │   │   │   └── useMentorData.tsx
│   │   │   │   │   └── useStudentData/
│   │   │   │   │       └── useStudentData.tsx
│   │   │   │   └── pages/
│   │   │   │       ├── Mentor/
│   │   │   │       │   └── Mentor.tsx
│   │   │   │       ├── Student/
│   │   │   │       │   └── Student.tsx
│   │   │   │       └── index.ts
│   │   │   ├── Schedule/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AdditionalActions/
│   │   │   │   │   │   ├── AdditionalActions.test.tsx
│   │   │   │   │   │   ├── AdditionalActions.tsx
│   │   │   │   │   │   ├── helpers.ts
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── EventDetails/
│   │   │   │   │   │   ├── EventDetails.module.css
│   │   │   │   │   │   ├── EventDetails.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── FilteredTags/
│   │   │   │   │   │   ├── FilteredTags.test.tsx
│   │   │   │   │   │   ├── FilteredTags.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── MobileItemCard/
│   │   │   │   │   │   ├── MobileItemCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── SettingsDrawer/
│   │   │   │   │   │   ├── ChangeTagColors.tsx
│   │   │   │   │   │   ├── SettingsDrawer.tsx
│   │   │   │   │   │   ├── ShowTableColumns.tsx
│   │   │   │   │   │   ├── TimeZone.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── SettingsPanel/
│   │   │   │   │   │   ├── SettingsPanel.test.tsx
│   │   │   │   │   │   ├── SettingsPanel.tsx
│   │   │   │   │   │   ├── helpers.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── StatusTabs/
│   │   │   │   │   │   ├── StatusTabs.test.tsx
│   │   │   │   │   │   ├── StatusTabs.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── TableView/
│   │   │   │   │       ├── TableView.test.tsx
│   │   │   │   │       ├── TableView.tsx
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── renderers.tsx
│   │   │   │   ├── constants.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   └── useScheduleSettings.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── pages/
│   │   │   │   │   └── SchedulePage/
│   │   │   │   │       └── index.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── Score/
│   │   │   │   ├── components/
│   │   │   │   │   ├── ExportCsvButton/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ScoreTable/
│   │   │   │   │   │   ├── ScoreTableTabs.tsx
│   │   │   │   │   │   ├── Summary.tsx
│   │   │   │   │   │   ├── index.module.css
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── SettingsDrawer/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── data/
│   │   │   │   │   ├── getColumns.tsx
│   │   │   │   │   ├── getExportCsvUrl.ts
│   │   │   │   │   ├── getTaskColumns.tsx
│   │   │   │   │   └── isExportEnabled.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── useScorePaging.tsx
│   │   │   │   └── pages/
│   │   │   │       └── ScorePage/
│   │   │   │           ├── UpdateAlert.module.css
│   │   │   │           ├── UpdateAlert.tsx
│   │   │   │           └── index.tsx
│   │   │   ├── StudentDashboard/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AvailableReviewCard/
│   │   │   │   │   │   ├── AvailableReviewCard.test.tsx
│   │   │   │   │   │   ├── AvailableReviewCard.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── CommonDashboardCard.tsx
│   │   │   │   │   ├── MainStatsCard.tsx
│   │   │   │   │   ├── MentorCard/
│   │   │   │   │   │   ├── MentorCard.test.tsx
│   │   │   │   │   │   ├── MentorCard.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── MentorInfo/
│   │   │   │   │   │   ├── MentorInfo.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── NextEventCard/
│   │   │   │   │   │   ├── NextEventCard.module.css
│   │   │   │   │   │   ├── NextEventCard.test.tsx
│   │   │   │   │   │   ├── NextEventCard.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── RepositoryCard.tsx
│   │   │   │   │   ├── SubmitTaskSolution/
│   │   │   │   │   │   ├── SubmitTaskSolution.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── TasksChart.tsx
│   │   │   │   │   ├── TasksStatsCard.tsx
│   │   │   │   │   ├── TasksStatsModal.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useDashboardData.ts
│   │   │   │   │   ├── useSubmitTaskSolution.test.ts
│   │   │   │   │   └── useSubmitTaskSolution.ts
│   │   │   │   └── index.ts
│   │   │   ├── Students/
│   │   │   │   ├── Pages/
│   │   │   │   │   └── Students.tsx
│   │   │   │   └── components/
│   │   │   │       ├── CourseItem/
│   │   │   │       │   └── index.tsx
│   │   │   │       ├── StudentInfo/
│   │   │   │       │   └── index.tsx
│   │   │   │       └── StudentsTable/
│   │   │   │           ├── index.tsx
│   │   │   │           └── renderers.tsx
│   │   │   ├── Tasks/
│   │   │   │   ├── components/
│   │   │   │   │   ├── CrossCheckTaskCriteriaPanel/
│   │   │   │   │   │   ├── CrossCheckTaskCriteriaPanel.test.tsx
│   │   │   │   │   │   └── CrossCheckTaskCriteriaPanel.tsx
│   │   │   │   │   ├── GitHubPanel/
│   │   │   │   │   │   ├── GitHubPanel.test.tsx
│   │   │   │   │   │   └── GitHubPanel.tsx
│   │   │   │   │   ├── JsonAttributesPanel/
│   │   │   │   │   │   ├── JsonAttributesPanel.test.tsx
│   │   │   │   │   │   └── JsonAttributesPanel.tsx
│   │   │   │   │   ├── TaskModal/
│   │   │   │   │   │   ├── TaskModal.test.tsx
│   │   │   │   │   │   └── TaskModal.tsx
│   │   │   │   │   ├── TaskSettings/
│   │   │   │   │   │   ├── TaskSettings.test.tsx
│   │   │   │   │   │   └── TaskSettings.tsx
│   │   │   │   │   ├── TasksTable/
│   │   │   │   │   │   ├── TasksTable.test.tsx
│   │   │   │   │   │   └── TasksTable.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── pages/
│   │   │   │   │   ├── TasksPage/
│   │   │   │   │   │   └── TasksPage.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       └── test-utils.ts
│   │   │   ├── TeamDistribution/
│   │   │   │   ├── components/
│   │   │   │   │   ├── SubmitScoreModal/
│   │   │   │   │   │   ├── SubmitScoreModal.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── TeamDistributionCard/
│   │   │   │   │   │   ├── Actions.test.tsx
│   │   │   │   │   │   ├── Actions.tsx
│   │   │   │   │   │   ├── CardTitle.test.tsx
│   │   │   │   │   │   ├── CardTitle.tsx
│   │   │   │   │   │   ├── DistributionPeriod.tsx
│   │   │   │   │   │   ├── TeamDistributionCard.test.tsx
│   │   │   │   │   │   ├── TeamDistributionCard.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── TeamDistributionModal/
│   │   │   │   │   │   ├── TeamDistributionModal.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── WelcomeCard/
│   │   │   │   │       ├── WelcomeCard.test.tsx
│   │   │   │   │       ├── WelcomeCard.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── useSubmitTeamScore.test.tsx
│   │   │   │   │   └── useSubmitTeamScore.tsx
│   │   │   │   └── pages/
│   │   │   │       └── TeamDistributions/
│   │   │   │           ├── TeamDistributions.tsx
│   │   │   │           └── index.tsx
│   │   │   ├── Teams/
│   │   │   │   ├── Pages/
│   │   │   │   │   └── Teams.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── JoinTeamModal/
│   │   │   │   │   │   └── JoinTeamModal.tsx
│   │   │   │   │   ├── MyTeamSection/
│   │   │   │   │   │   └── MyTeamSection.tsx
│   │   │   │   │   ├── StudentsTable/
│   │   │   │   │   │   ├── StudentsTable.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   ├── StudentsWithoutTeamSection/
│   │   │   │   │   │   └── StudentsWithoutTeamSection.tsx
│   │   │   │   │   ├── TeamModal/
│   │   │   │   │   │   ├── TeamModal.test.tsx
│   │   │   │   │   │   └── TeamModal.tsx
│   │   │   │   │   ├── TeamsHeader/
│   │   │   │   │   │   ├── ActionCard.tsx
│   │   │   │   │   │   └── TeamsHeader.tsx
│   │   │   │   │   ├── TeamsSection/
│   │   │   │   │   │   ├── TeamsSection.tsx
│   │   │   │   │   │   └── renderers.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useDistribution/
│   │   │   │   │       ├── useDistribution.test.ts
│   │   │   │   │       └── useDistribution.ts
│   │   │   │   └── index.tsx
│   │   │   ├── UserGroupsAdmin/
│   │   │   │   ├── components/
│   │   │   │   │   ├── UserGroupsModal.tsx
│   │   │   │   │   └── UserGroupsTable.tsx
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── useUserGroups.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── pages/
│   │   │   │       └── UserGroupsAdminPage/
│   │   │   │           ├── UserGroupsAdminPage.tsx
│   │   │   │           └── index.ts
│   │   │   └── UsersAdmin/
│   │   │       ├── hooks/
│   │   │       │   ├── index.ts
│   │   │       │   └── useUsersSearch.ts
│   │   │       ├── index.ts
│   │   │       └── pages/
│   │   │           └── UsersAdminPage/
│   │   │               ├── UsersAdminPage.tsx
│   │   │               └── index.ts
│   │   ├── pages/
│   │   │   ├── 404.tsx
│   │   │   ├── _app.tsx
│   │   │   ├── _document.tsx
│   │   │   ├── admin/
│   │   │   │   ├── auto-test-task/
│   │   │   │   │   └── [taskId].tsx
│   │   │   │   ├── auto-test.tsx
│   │   │   │   ├── contributors.tsx
│   │   │   │   ├── courses.tsx
│   │   │   │   ├── disciplines.tsx
│   │   │   │   ├── discord-telegram.tsx
│   │   │   │   ├── events.tsx
│   │   │   │   ├── mentor-registry.module.css
│   │   │   │   ├── mentor-registry.tsx
│   │   │   │   ├── notifications.tsx
│   │   │   │   ├── prompts.tsx
│   │   │   │   ├── registrations.tsx
│   │   │   │   ├── students.tsx
│   │   │   │   ├── tasks.tsx
│   │   │   │   ├── user-group.tsx
│   │   │   │   └── users.tsx
│   │   │   ├── applicants/
│   │   │   │   └── index.tsx
│   │   │   ├── course/
│   │   │   │   ├── 403.tsx
│   │   │   │   ├── admin/
│   │   │   │   │   ├── certified-students.tsx
│   │   │   │   │   ├── cross-check-table.tsx
│   │   │   │   │   ├── events.tsx
│   │   │   │   │   ├── interviews.tsx
│   │   │   │   │   ├── mentor-tasks-review.tsx
│   │   │   │   │   ├── mentors.tsx
│   │   │   │   │   ├── reports.tsx
│   │   │   │   │   ├── stage-interviews.tsx
│   │   │   │   │   ├── students.tsx
│   │   │   │   │   ├── tasks.tsx
│   │   │   │   │   └── users.tsx
│   │   │   │   ├── interview/
│   │   │   │   │   └── [type]/
│   │   │   │   │       └── feedback.tsx
│   │   │   │   ├── mentor/
│   │   │   │   │   ├── confirm.tsx
│   │   │   │   │   ├── dashboard.tsx
│   │   │   │   │   ├── expel-student.tsx
│   │   │   │   │   ├── feedback/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── interview-technical-screening.tsx
│   │   │   │   │   ├── interview-wait-list.tsx
│   │   │   │   │   ├── interviews.tsx
│   │   │   │   │   └── students.tsx
│   │   │   │   ├── schedule.tsx
│   │   │   │   ├── score.tsx
│   │   │   │   ├── stats.tsx
│   │   │   │   ├── student/
│   │   │   │   │   ├── auto-test/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── task.tsx
│   │   │   │   │   ├── cross-check-review.tsx
│   │   │   │   │   ├── cross-check-submit.tsx
│   │   │   │   │   ├── dashboard.module.css
│   │   │   │   │   ├── dashboard.tsx
│   │   │   │   │   └── interviews.tsx
│   │   │   │   ├── submit-scores.tsx
│   │   │   │   ├── team-distributions.tsx
│   │   │   │   └── teams.tsx
│   │   │   ├── cv/
│   │   │   │   ├── [uuid].tsx
│   │   │   │   └── edit.tsx
│   │   │   ├── gratitude.tsx
│   │   │   ├── heroes.tsx
│   │   │   ├── index.tsx
│   │   │   ├── login/
│   │   │   │   ├── index.module.css
│   │   │   │   └── index.tsx
│   │   │   ├── mentors-hall-of-fame.tsx
│   │   │   ├── profile/
│   │   │   │   ├── connection-confirmed.tsx
│   │   │   │   ├── index.module.css
│   │   │   │   ├── index.tsx
│   │   │   │   └── notifications.tsx
│   │   │   └── registry/
│   │   │       ├── epamlearningjs.tsx
│   │   │       ├── mentor.tsx
│   │   │       └── student.tsx
│   │   ├── providers/
│   │   │   ├── DevToolsProvider.tsx
│   │   │   ├── MessageProvider.tsx
│   │   │   ├── ThemeProvider.tsx
│   │   │   └── index.ts
│   │   ├── reset.d.ts
│   │   ├── services/
│   │   │   ├── cdn.ts
│   │   │   ├── check.ts
│   │   │   ├── course.ts
│   │   │   ├── courses.ts
│   │   │   ├── features.tsx
│   │   │   ├── files.ts
│   │   │   ├── formatter.ts
│   │   │   ├── gratitude.ts
│   │   │   ├── mentorRegistry.ts
│   │   │   ├── models.ts
│   │   │   ├── reference-data/
│   │   │   │   └── stageInterview.ts
│   │   │   ├── routes.ts
│   │   │   ├── user.ts
│   │   │   ├── validators.test.ts
│   │   │   └── validators.ts
│   │   ├── setupTests.ts
│   │   ├── shared/
│   │   │   ├── components/
│   │   │   │   ├── CommentModal.tsx
│   │   │   │   ├── CopyToClipboardButton.tsx
│   │   │   │   ├── FilteredTags.tsx
│   │   │   │   ├── Forms/
│   │   │   │   │   ├── CommentInput.tsx
│   │   │   │   │   ├── CourseTaskSelect.tsx
│   │   │   │   │   ├── GdprCheckbox.tsx
│   │   │   │   │   ├── Heroes/
│   │   │   │   │   │   ├── index.module.css
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── LocationSelect.tsx
│   │   │   │   │   ├── MarkdownInput.tsx
│   │   │   │   │   ├── ModalForm.tsx
│   │   │   │   │   ├── ModalSubmitForm.test.tsx
│   │   │   │   │   ├── ModalSubmitForm.tsx
│   │   │   │   │   ├── PreparedComment.tsx
│   │   │   │   │   ├── ScoreInput.tsx
│   │   │   │   │   ├── __tests__/
│   │   │   │   │   │   ├── CourseTaskSelect.test.tsx
│   │   │   │   │   │   └── __snapshots__/
│   │   │   │   │   │       └── CourseTaskSelect.test.tsx.snap
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useGoogleMapsPlaces.test.ts
│   │   │   │   │   └── useGoogleMapsPlaces.ts
│   │   │   │   ├── GithubAvatar.tsx
│   │   │   │   ├── GithubUserLink.module.css
│   │   │   │   ├── GithubUserLink.tsx
│   │   │   │   ├── Header.module.css
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── Icons/
│   │   │   │   │   ├── CourseIcon.tsx
│   │   │   │   │   ├── DeadlineIcon.tsx
│   │   │   │   │   ├── DiscordFilled.tsx
│   │   │   │   │   ├── DiscordOutlined.tsx
│   │   │   │   │   ├── GitHubLogoIcon.tsx
│   │   │   │   │   ├── HealthMask.tsx
│   │   │   │   │   ├── LinkedInIcon.tsx
│   │   │   │   │   ├── PublicSvgIcon.tsx
│   │   │   │   │   ├── RSLogoIcon.tsx
│   │   │   │   │   ├── ScoreIcon.tsx
│   │   │   │   │   ├── TelegramIcon.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── LoadingScreen.module.css
│   │   │   │   ├── LoadingScreen.tsx
│   │   │   │   ├── MentorSearch.tsx
│   │   │   │   ├── NonTouchTooltip.tsx
│   │   │   │   ├── PageLayout.tsx
│   │   │   │   ├── PersonSelect.tsx
│   │   │   │   ├── Rating.tsx
│   │   │   │   ├── ScoreCard.module.css
│   │   │   │   ├── ScoreCard.tsx
│   │   │   │   ├── ScoreSelector.module.css
│   │   │   │   ├── ScoreSelector.tsx
│   │   │   │   ├── Sider/
│   │   │   │   │   ├── AdminSider.test.tsx
│   │   │   │   │   ├── AdminSider.tsx
│   │   │   │   │   └── data/
│   │   │   │   │       └── menuItems.tsx
│   │   │   │   ├── SolidarityUkraine.tsx
│   │   │   │   ├── StudentMentorModal.tsx
│   │   │   │   ├── StudentSearch.tsx
│   │   │   │   ├── Table/
│   │   │   │   │   ├── PersonCell.tsx
│   │   │   │   │   ├── columns.tsx
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── renderers.tsx
│   │   │   │   │   └── sorters.ts
│   │   │   │   ├── ThemeSwitch.tsx
│   │   │   │   ├── Timer.tsx
│   │   │   │   ├── TooltipedButton.tsx
│   │   │   │   └── UserSearch.tsx
│   │   │   ├── hooks/
│   │   │   │   ├── useMessage.tsx
│   │   │   │   ├── useModal/
│   │   │   │   │   ├── useModalForm.test.tsx
│   │   │   │   │   └── useModalForm.tsx
│   │   │   │   ├── useTheme.tsx
│   │   │   │   └── useWindowDimensions.ts
│   │   │   └── utils/
│   │   │       ├── onlyDefined.ts
│   │   │       ├── pagination.ts
│   │   │       ├── queryParams-utils.test.ts
│   │   │       ├── queryParams-utils.ts
│   │   │       ├── text-utils.test.ts
│   │   │       └── text-utils.ts
│   │   ├── styles/
│   │   │   └── main.css
│   │   └── utils/
│   │       ├── dynamicWithSkeleton.tsx
│   │       ├── optionalQueryString.ts
│   │       └── profilePageUtils.ts
│   ├── tsconfig.json
│   └── vitest.config.mts
├── common/
│   ├── README.md
│   └── models/
│       ├── index.ts
│       ├── interview.ts
│       ├── profile.ts
│       ├── stage-interview-feedback.ts
│       └── user.ts
├── docker-compose.yml
├── docs/
│   ├── .nojekyll
│   ├── CNAME
│   ├── README.md
│   ├── _sidebar.md
│   ├── code-of-conduct.md
│   ├── index.html
│   └── platform/
│       ├── about.md
│       ├── adding-tests.md
│       ├── choose-kata-languages.md
│       ├── cross-check-flow.md
│       ├── cross-check-scheduling.md
│       ├── cv.md
│       ├── notifications.md
│       ├── pull-request-review-process.md
│       ├── shedule.md
│       ├── tasks.md
│       └── typical-problems.md
├── eslint.config.mjs
├── nestjs/
│   ├── .dockerignore
│   ├── .swcrc
│   ├── Dockerfile
│   ├── Dockerfile.lambda
│   ├── README.md
│   ├── eslint.config.mjs
│   ├── nest-cli.json
│   ├── openapitools.json
│   ├── package.json
│   ├── src/
│   │   ├── activity/
│   │   │   ├── activity.controller.ts
│   │   │   ├── activity.module.ts
│   │   │   └── dto/
│   │   │       ├── activity.dto.ts
│   │   │       ├── create-activity-webhook.dto.ts
│   │   │       └── create-activity.dto.ts
│   │   ├── alerts/
│   │   │   ├── alerts.controller.ts
│   │   │   ├── alerts.module.ts
│   │   │   ├── alerts.service.ts
│   │   │   └── dto/
│   │   │       ├── alert.dto.ts
│   │   │       ├── create-alert.dto.ts
│   │   │       ├── index.ts
│   │   │       └── update-alert.dto.ts
│   │   ├── app.module.ts
│   │   ├── auth/
│   │   │   ├── auth-user.model.spec.ts
│   │   │   ├── auth-user.model.ts
│   │   │   ├── auth.controller.spec.ts
│   │   │   ├── auth.controller.ts
│   │   │   ├── auth.module.ts
│   │   │   ├── auth.service.spec.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── constants.ts
│   │   │   ├── course.guard.ts
│   │   │   ├── default.guard.ts
│   │   │   ├── dto/
│   │   │   │   └── auth-connection.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── role.decorator.ts
│   │   │   ├── role.guard.ts
│   │   │   └── strategies/
│   │   │       ├── basic.strategy.ts
│   │   │       ├── dev.strategy.ts
│   │   │       ├── github.strategy.ts
│   │   │       └── jwt.strategy.ts
│   │   ├── auto-test/
│   │   │   ├── auto-test.controller.ts
│   │   │   ├── auto-test.module.ts
│   │   │   ├── auto-test.service.ts
│   │   │   └── dto/
│   │   │       ├── auto-test-task.dto.ts
│   │   │       ├── basic-auto-test-task.dto.ts
│   │   │       └── task-solution.dto.ts
│   │   ├── certificates/
│   │   │   ├── certificates.controller.ts
│   │   │   ├── certificates.module.ts
│   │   │   ├── certificates.service.ts
│   │   │   └── dto/
│   │   │       ├── certificate-metadata.dto.ts
│   │   │       └── save-certificate-dto.ts
│   │   ├── cloud-api/
│   │   │   ├── cloud-api.module.ts
│   │   │   └── cloud-api.service.ts
│   │   ├── config/
│   │   │   ├── config.module.ts
│   │   │   ├── config.service.ts
│   │   │   └── index.ts
│   │   ├── constants.ts
│   │   ├── contributors/
│   │   │   ├── contributors.controller.ts
│   │   │   ├── contributors.module.ts
│   │   │   ├── contributors.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── contributor.dto.ts
│   │   │   │   ├── create-contributor.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── update-contributor.dto.ts
│   │   │   └── index.ts
│   │   ├── core/
│   │   │   ├── core.module.ts
│   │   │   ├── decorators/
│   │   │   │   ├── index.ts
│   │   │   │   └── student-id.decorator.ts
│   │   │   ├── dto/
│   │   │   │   ├── id-name.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── pagination.dto.ts
│   │   │   │   └── person.dto.ts
│   │   │   ├── filters/
│   │   │   │   ├── entity-not-found.filter.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── sentry.filter.ts
│   │   │   ├── jwt/
│   │   │   │   └── jwt.service.ts
│   │   │   ├── middlewares/
│   │   │   │   ├── index.ts
│   │   │   │   ├── logger.middleware.ts
│   │   │   │   └── no-cache.middleware.ts
│   │   │   ├── paginate/
│   │   │   │   ├── dto/
│   │   │   │   │   └── Paginate.dto.ts
│   │   │   │   ├── index.test.ts
│   │   │   │   └── index.ts
│   │   │   ├── pino.ts
│   │   │   ├── subscribers/
│   │   │   │   ├── base-subscriber.ts
│   │   │   │   ├── course-event.subscriber.ts
│   │   │   │   └── course-task.subscriber.ts
│   │   │   ├── templates/
│   │   │   │   └── index.ts
│   │   │   └── validation/
│   │   │       ├── index.ts
│   │   │       ├── validation.exception.ts
│   │   │       └── validation.filter.ts
│   │   ├── courses/
│   │   │   ├── course-access.service.ts
│   │   │   ├── course-events/
│   │   │   │   ├── course-events.controller.ts
│   │   │   │   ├── course-events.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-event.dto.ts
│   │   │   │   │   ├── create-course-event.dto.ts
│   │   │   │   │   └── update-course-event.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-mentors/
│   │   │   │   ├── course-mentors.controller.ts
│   │   │   │   ├── course-mentors.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── mentor-details.dto.ts
│   │   │   │   │   └── search-mentor.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-schedule/
│   │   │   │   ├── course-icalendar.controller.ts
│   │   │   │   ├── course-icalendar.service.ts
│   │   │   │   ├── course-schedule.controller.ts
│   │   │   │   ├── course-schedule.service.spec.ts
│   │   │   │   ├── course-schedule.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-copy-from.dto.ts
│   │   │   │   │   ├── course-schedule-hash.dto.ts
│   │   │   │   │   ├── course-schedule-item.dto.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-students/
│   │   │   │   ├── course-students.controller.ts
│   │   │   │   ├── course-students.service.ts
│   │   │   │   └── dto/
│   │   │   │       ├── mentor-student-summary.dto.ts
│   │   │   │       ├── result.dto.ts
│   │   │   │       ├── student-status.dto.ts
│   │   │   │       └── student-summary.dto.ts
│   │   │   ├── course-tasks/
│   │   │   │   ├── course-tasks.controller.ts
│   │   │   │   ├── course-tasks.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-task-detailed.dto.ts
│   │   │   │   │   ├── course-task.dto.ts
│   │   │   │   │   ├── create-course-task.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── update-course-task.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── course-users/
│   │   │   │   ├── course-users.controller.spec.ts
│   │   │   │   ├── course-users.controller.ts
│   │   │   │   ├── course-users.service.spec.ts
│   │   │   │   ├── course-users.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── course-roles.dto.ts
│   │   │   │   │   ├── course-user.dto.ts
│   │   │   │   │   └── update-user.dto.ts
│   │   │   │   └── types.ts
│   │   │   ├── courses.controller.ts
│   │   │   ├── courses.module.ts
│   │   │   ├── courses.service.ts
│   │   │   ├── cross-checks/
│   │   │   │   ├── course-cross-checks.controller.ts
│   │   │   │   ├── course-cross-checks.service.spec.ts
│   │   │   │   ├── course-cross-checks.service.ts
│   │   │   │   ├── cross-check-feedback.guard.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── available-review-stats.dto.ts
│   │   │   │   │   ├── check-tasks-pairs.dto.ts
│   │   │   │   │   ├── cross-check-criteria-data.dto.ts
│   │   │   │   │   ├── cross-check-feedback.dto.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   ├── dto/
│   │   │   │   ├── course.dto.ts
│   │   │   │   ├── create-course.dto.ts
│   │   │   │   ├── export-course.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── leave-course.dto.ts
│   │   │   │   ├── update-course.dto.ts
│   │   │   │   └── used-course.dto.ts
│   │   │   ├── expelled-stats.service.test.ts
│   │   │   ├── expelled-stats.service.ts
│   │   │   ├── index.ts
│   │   │   ├── interviews/
│   │   │   │   ├── cross-mentor-distribution.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── available-student.dto.ts
│   │   │   │   │   ├── get-interview-feedback.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── interview-comment.dto.ts
│   │   │   │   │   ├── interview-distribute.dto.ts
│   │   │   │   │   ├── interview-pair.dto.ts
│   │   │   │   │   ├── interview.dto.ts
│   │   │   │   │   ├── put-interview-feedback.dto.ts
│   │   │   │   │   └── registration-interview.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── interviewFeedback.service.ts
│   │   │   │   ├── interviews.controller.ts
│   │   │   │   └── interviews.service.ts
│   │   │   ├── mentor-reviews/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── mentor-review-assign.dto.ts
│   │   │   │   │   ├── mentor-reviews-query.dto.ts
│   │   │   │   │   └── mentor-reviews.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── mentor-reviews.controller.ts
│   │   │   │   └── mentor-reviews.service.ts
│   │   │   ├── mentors/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── mentor-dashboard.dto.ts
│   │   │   │   │   ├── mentor-options.dto.ts
│   │   │   │   │   └── mentor-student.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── mentors.controller.ts
│   │   │   │   └── mentors.service.ts
│   │   │   ├── score/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── score-query.dto.ts
│   │   │   │   │   └── score.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── score.controller.ts
│   │   │   │   ├── score.service.ts
│   │   │   │   └── write-score.service.ts
│   │   │   ├── stats/
│   │   │   │   ├── course-stats.controller.ts
│   │   │   │   ├── course-stats.service.ts
│   │   │   │   ├── dto/
│   │   │   │   │   ├── countries-stats.dto.ts
│   │   │   │   │   ├── course-mentors-stats.dto.ts
│   │   │   │   │   ├── course-stats.dto.ts
│   │   │   │   │   ├── expelled-stats.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── task-performance-stats.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── students/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── student.dto.ts
│   │   │   │   │   ├── user-students-query.dto.ts
│   │   │   │   │   └── user-students.dto.ts
│   │   │   │   ├── feedbacks/
│   │   │   │   │   ├── dto/
│   │   │   │   │   │   ├── create-student-feedback.dto.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── student-feedback.dto.ts
│   │   │   │   │   │   └── update-student-feedback.dto.ts
│   │   │   │   │   ├── feedbacks.controller.ts
│   │   │   │   │   ├── feedbacks.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── students.controller.ts
│   │   │   │   └── students.service.ts
│   │   │   ├── task-solutions/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── create-task-solution.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── task-solution.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── task-solutions.controller.ts
│   │   │   │   └── task-solutions.service.ts
│   │   │   ├── task-verifications/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── create-task-verification.dto.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── self-education.dto.ts
│   │   │   │   │   └── task-verifications-attempts.dto.ts
│   │   │   │   ├── self-education.service.test.ts
│   │   │   │   ├── self-education.service.ts
│   │   │   │   ├── task-verifications.controller.ts
│   │   │   │   ├── task-verifications.service.test.ts
│   │   │   │   └── task-verifications.service.ts
│   │   │   ├── tasks/
│   │   │   │   ├── dto/
│   │   │   │   │   └── check-tasks-deadline.ts
│   │   │   │   ├── tasks.controller.ts
│   │   │   │   └── tasks.service.ts
│   │   │   └── team-distribution/
│   │   │       ├── distribute-students.service.ts
│   │   │       ├── dto/
│   │   │       │   ├── create-team-distribution.dto.ts
│   │   │       │   ├── create-team.dto.ts
│   │   │       │   ├── index.ts
│   │   │       │   ├── join-team.dto.ts
│   │   │       │   ├── team-distribution-student.dto.ts
│   │   │       │   ├── team-distribution.dto.ts
│   │   │       │   ├── team.dto.ts
│   │   │       │   ├── update-team-distribution.dto.ts
│   │   │       │   └── update-team-dto.ts
│   │   │       ├── registered-student-guard.ts
│   │   │       ├── team-distribution-student.service.test.ts
│   │   │       ├── team-distribution-student.service.ts
│   │   │       ├── team-distribution.controller.ts
│   │   │       ├── team-distribution.service.test.ts
│   │   │       ├── team-distribution.service.ts
│   │   │       ├── team-lead-or-manager.guard.ts
│   │   │       ├── team.controller.ts
│   │   │       └── team.service.ts
│   │   ├── cross-check/
│   │   │   ├── cross-check.module.ts
│   │   │   ├── cross-check.service.spec.ts
│   │   │   ├── cross-check.service.ts
│   │   │   └── tasks-filtering.ts
│   │   ├── devtools/
│   │   │   ├── devtools.controller.ts
│   │   │   ├── devtools.module.ts
│   │   │   ├── devtools.service.ts
│   │   │   └── dto/
│   │   │       └── devtools.users-dto.ts
│   │   ├── disciplines/
│   │   │   ├── disciplines.controller.test.ts
│   │   │   ├── disciplines.controller.ts
│   │   │   ├── disciplines.module.ts
│   │   │   ├── disciplines.service.test.ts
│   │   │   ├── disciplines.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── create-discipline.dto.ts
│   │   │   │   ├── discipline-ids.dto.ts
│   │   │   │   ├── discipline.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── update-discipline.dto.ts
│   │   │   └── index.ts
│   │   ├── discord-servers/
│   │   │   ├── discord-servers.controller.ts
│   │   │   ├── discord-servers.module.ts
│   │   │   ├── discord-servers.service.ts
│   │   │   └── dto/
│   │   │       ├── create-discord-server.dto.ts
│   │   │       ├── discord-server.dto.ts
│   │   │       ├── index.ts
│   │   │       └── update-discord-server.dto.ts
│   │   ├── events/
│   │   │   ├── dto/
│   │   │   │   ├── create-event.dto.ts
│   │   │   │   ├── event.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── update-event.dto.ts
│   │   │   ├── events.controller.ts
│   │   │   ├── events.module.ts
│   │   │   └── events.service.ts
│   │   ├── gratitudes/
│   │   │   ├── discord.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── badge.dto.ts
│   │   │   │   ├── country.dto.ts
│   │   │   │   ├── create-gratitude.dto.ts
│   │   │   │   ├── gratitude.dto.ts
│   │   │   │   ├── hero-radar.dto.ts
│   │   │   │   ├── heroes-radar-badge.dto.ts
│   │   │   │   ├── heroes-radar-query.dto.ts
│   │   │   │   ├── heroes-radar.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── gratitudes.controller.ts
│   │   │   ├── gratitudes.module.ts
│   │   │   ├── gratitudes.service.ts
│   │   │   └── index.ts
│   │   ├── listeners/
│   │   │   ├── course.listener.ts
│   │   │   ├── index.ts
│   │   │   └── listeners.module.ts
│   │   ├── main.ts
│   │   ├── mentors-hall-of-fame/
│   │   │   ├── dto/
│   │   │   │   ├── course-stats.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── top-mentor.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── mentors-hall-of-fame.controller.test.ts
│   │   │   ├── mentors-hall-of-fame.controller.ts
│   │   │   ├── mentors-hall-of-fame.module.ts
│   │   │   ├── mentors-hall-of-fame.service.test.ts
│   │   │   └── mentors-hall-of-fame.service.ts
│   │   ├── migrations.ts
│   │   ├── notifications/
│   │   │   ├── dto/
│   │   │   │   ├── notification.dto.ts
│   │   │   │   └── update-notification.dto.ts
│   │   │   ├── email-template.ts
│   │   │   ├── notifications.controller.ts
│   │   │   ├── notifications.module.ts
│   │   │   └── notifications.service.ts
│   │   ├── openapi-spec.ts
│   │   ├── opportunities/
│   │   │   ├── dto/
│   │   │   │   ├── applicant-resume.dto.ts
│   │   │   │   ├── consent.dto.ts
│   │   │   │   ├── form-data.dto.ts
│   │   │   │   ├── give-consent-dto.ts
│   │   │   │   ├── resume.dto.ts
│   │   │   │   ├── status.dto.ts
│   │   │   │   └── visibility.dto.ts
│   │   │   ├── opportunities.controller.ts
│   │   │   ├── opportunities.module.ts
│   │   │   ├── opportunities.service.test.ts
│   │   │   └── opportunities.service.ts
│   │   ├── ormconfig.ts
│   │   ├── profile/
│   │   │   ├── dto/
│   │   │   │   ├── endorsement.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── personal-profile.dto.ts
│   │   │   │   ├── profile-course.dto.ts
│   │   │   │   ├── profile.dto.ts
│   │   │   │   ├── update-profile.dto.ts
│   │   │   │   └── update-user.dto.ts
│   │   │   ├── endorsement.service.ts
│   │   │   ├── index.ts
│   │   │   ├── profile.controller.ts
│   │   │   ├── profile.module.ts
│   │   │   └── profile.service.ts
│   │   ├── prompts/
│   │   │   ├── dto/
│   │   │   │   ├── create-prompt.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── prompt.dto.ts
│   │   │   │   └── update-prompt.dto.ts
│   │   │   ├── prompts.controller.ts
│   │   │   ├── prompts.module.ts
│   │   │   └── prompts.service.ts
│   │   ├── registry/
│   │   │   ├── constants.ts
│   │   │   ├── dto/
│   │   │   │   ├── approve-mentor.dto.ts
│   │   │   │   ├── comment-mentor-registry.dto.ts
│   │   │   │   ├── invite-mentors.dto.ts
│   │   │   │   └── mentor-registry.dto.ts
│   │   │   ├── registry.controller.ts
│   │   │   ├── registry.module.ts
│   │   │   └── registry.service.ts
│   │   ├── repositories/
│   │   │   ├── dto/
│   │   │   │   ├── create-repository-event.dto.ts
│   │   │   │   └── index.ts
│   │   │   ├── index.ts
│   │   │   ├── repositories.controller.ts
│   │   │   ├── repositories.module.ts
│   │   │   └── repositories.service.ts
│   │   ├── reset.d.ts
│   │   ├── schedule/
│   │   │   ├── dto/
│   │   │   │   └── check-schedule-changes.ts
│   │   │   ├── schedule.controller.ts
│   │   │   ├── schedule.module.ts
│   │   │   └── schedule.service.ts
│   │   ├── session/
│   │   │   ├── dto/
│   │   │   │   └── auth-user.dto.ts
│   │   │   ├── session.controller.ts
│   │   │   └── session.module.ts
│   │   ├── setup.ts
│   │   ├── spec.json
│   │   ├── tasks/
│   │   │   ├── dto/
│   │   │   │   ├── create-task.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── task.dto.ts
│   │   │   │   └── update-task.dto.ts
│   │   │   ├── tasks-criteria/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── criteria.dto.ts
│   │   │   │   │   └── task-criteria.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── tasks-criteria.controller.ts
│   │   │   │   └── tasks-criteria.service.ts
│   │   │   ├── tasks.controller.ts
│   │   │   ├── tasks.module.ts
│   │   │   └── tasks.service.ts
│   │   ├── user-groups/
│   │   │   ├── dto/
│   │   │   │   ├── create-user-group.dto.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── update-user-group.dto.ts
│   │   │   │   └── user-group.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── user-groups.controller.ts
│   │   │   ├── user-groups.module.ts
│   │   │   └── user-groups.service.ts
│   │   ├── users/
│   │   │   ├── dto/
│   │   │   │   ├── index.ts
│   │   │   │   ├── user-search.dto.ts
│   │   │   │   └── user.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── users.controller.ts
│   │   │   ├── users.module.ts
│   │   │   └── users.service.ts
│   │   ├── users-notifications/
│   │   │   ├── dto/
│   │   │   │   ├── notification-connection-exists.dto.ts
│   │   │   │   ├── notification-connection.dto.ts
│   │   │   │   ├── notification-user-connections.dto.ts
│   │   │   │   ├── notification-user-settings.dto.ts
│   │   │   │   ├── send-user-notification.dto.ts
│   │   │   │   ├── update-notification-user-settings.dto.ts
│   │   │   │   └── upsert-notification-connection.dto.ts
│   │   │   ├── index.ts
│   │   │   ├── users-notifications.module.ts
│   │   │   ├── users.notifications.controller.ts
│   │   │   └── users.notifications.service.ts
│   │   └── utils/
│   │       ├── index.ts
│   │       ├── shuffle.test.ts
│   │       └── shuffle.ts
│   ├── test/
│   │   └── app.e2e-spec.ts
│   ├── tsconfig.build.json
│   ├── tsconfig.json
│   └── vitest.config.mts
├── package.json
├── renovate.json
├── server/
│   ├── .dockerignore
│   ├── .swcrc
│   ├── Dockerfile
│   ├── Dockerfile.lambda
│   ├── README.md
│   ├── eslint.config.mjs
│   ├── package.json
│   ├── public/
│   │   └── swagger.yml
│   ├── src/
│   │   ├── app.ts
│   │   ├── config.ts
│   │   ├── dataSource.ts
│   │   ├── dataSourceOptions.ts
│   │   ├── index.ts
│   │   ├── logger.ts
│   │   ├── migrations/
│   │   │   ├── 1630340371992-UserMigration.ts
│   │   │   ├── 1630341383942-TaskResult.ts
│   │   │   ├── 1630342025950-StudentMigration.ts
│   │   │   ├── 1630342266002-UserMigration.ts
│   │   │   ├── 1630347897950-StudentMigration.ts
│   │   │   ├── 1632333725126-ResumeMigration.ts
│   │   │   ├── 1635365797478-User.ts
│   │   │   ├── 1637591194886-StageInterview.ts
│   │   │   ├── 1638302439645-CourseMigration.ts
│   │   │   ├── 1639418471577-Indicies.ts
│   │   │   ├── 1639427578702-Update.ts
│   │   │   ├── 1639502600339-Student.ts
│   │   │   ├── 1642884123347-ResumeSelectCourses.ts
│   │   │   ├── 1643481312933-Task.ts
│   │   │   ├── 1643550350939-LoginState.ts
│   │   │   ├── 1643926895264-Notifications.ts
│   │   │   ├── 1644695410918-NotificationConnection.ts
│   │   │   ├── 1645364514538-RepositoryEvent.ts
│   │   │   ├── 1645654601903-Opportunitites.ts
│   │   │   ├── 1647103154082-CrossCheckScheduling.ts
│   │   │   ├── 1647175301446-TaskSolutionConstraint.ts
│   │   │   ├── 1647550751147-NotificationType.ts
│   │   │   ├── 1647885219936-LoginStateUserId.ts
│   │   │   ├── 1649505252996-CourseLogo.ts
│   │   │   ├── 1649868994688-CourseLogo.ts
│   │   │   ├── 1650652882300-DiscordChannel.ts
│   │   │   ├── 1652870756742-Resume.ts
│   │   │   ├── 1656326258991-History.ts
│   │   │   ├── 1661034658479-Feedback.ts
│   │   │   ├── 1661087975938-Discipline.ts
│   │   │   ├── 1661106736439-Disciplines.ts
│   │   │   ├── 1661107174477-Disciplines.ts
│   │   │   ├── 1661616212488-NotificationCategory.ts
│   │   │   ├── 1662275601017-CourseTask.ts
│   │   │   ├── 1664183799115-CourseEvent.ts
│   │   │   ├── 1666348642811-TaskCriteria.ts
│   │   │   ├── 1666621080327-TaskSolutionResult.ts
│   │   │   ├── 1671475396333-Tasks.ts
│   │   │   ├── 1672142743107-TeamDistribution.ts
│   │   │   ├── 1672386450861-TeamDistribution.ts
│   │   │   ├── 1673090827105-TaskVerification.ts
│   │   │   ├── 1673692838338-User.ts
│   │   │   ├── 1674128274839-Team.ts
│   │   │   ├── 1674377676805-TeamDistributionStudent.ts
│   │   │   ├── 1674755854609-Resume.ts
│   │   │   ├── 1675245424426-UserGroup.ts
│   │   │   ├── 1675345245770-Course.ts
│   │   │   ├── 1676139987317-User.ts
│   │   │   ├── 1685197747051-MentorRegistry.ts
│   │   │   ├── 1686657350908-InterviewScore.ts
│   │   │   ├── 1687009744110-Prompt.ts
│   │   │   ├── 1691520611773-Temperature.ts
│   │   │   ├── 1691524327332-Temperature.ts
│   │   │   ├── 1693930286280-CourseUsersActivist.ts
│   │   │   ├── 1699808604000-AddMinStudentPerMentorColumnToCourse.ts
│   │   │   ├── 1700391857109-Obfuscation.ts
│   │   │   ├── 1712137476312-Course.ts
│   │   │   ├── 1730926720293-CourseTask.ts
│   │   │   ├── 1734874453585-Contributor.ts
│   │   │   ├── 1736458672717-Course.ts
│   │   │   ├── 1738250779923-CoursePersonalMentoringDates.ts
│   │   │   ├── 1746467689328-Course.ts
│   │   │   ├── 1747380525126-CourseTaskInterviewCreatingPairs.ts
│   │   │   ├── 1760699701354-AddCourseLeaveSurveyResponse.ts
│   │   │   └── index.ts
│   │   ├── models/
│   │   │   ├── alert.ts
│   │   │   ├── certificate.ts
│   │   │   ├── contributor.ts
│   │   │   ├── course-leave-survey-response.entity.ts
│   │   │   ├── course.ts
│   │   │   ├── courseEvent.ts
│   │   │   ├── courseManager.ts
│   │   │   ├── courseTask.ts
│   │   │   ├── courseUser.ts
│   │   │   ├── data/
│   │   │   │   ├── available-languages.data.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── language-levels.data.ts
│   │   │   ├── discipline.ts
│   │   │   ├── discordServer.ts
│   │   │   ├── event.ts
│   │   │   ├── feedback.ts
│   │   │   ├── history.ts
│   │   │   ├── index.ts
│   │   │   ├── loginState.ts
│   │   │   ├── mentor.ts
│   │   │   ├── mentorRegistry.ts
│   │   │   ├── notification.ts
│   │   │   ├── notificationChannel.ts
│   │   │   ├── notificationChannelSettings.ts
│   │   │   ├── notificationUserConnection.ts
│   │   │   ├── notificationUserSettings.ts
│   │   │   ├── privateFeedback.ts
│   │   │   ├── profilePermissions.ts
│   │   │   ├── prompt.ts
│   │   │   ├── registry.ts
│   │   │   ├── repositoryEvent.ts
│   │   │   ├── resume.ts
│   │   │   ├── session.ts
│   │   │   ├── stageInterview.ts
│   │   │   ├── stageInterviewFeedback.ts
│   │   │   ├── stageInterviewStudent.ts
│   │   │   ├── student-feedback.ts
│   │   │   ├── student.ts
│   │   │   ├── task.ts
│   │   │   ├── taskArtefact.ts
│   │   │   ├── taskChecker.ts
│   │   │   ├── taskCriteria.ts
│   │   │   ├── taskInterviewResult.ts
│   │   │   ├── taskInterviewStudent.ts
│   │   │   ├── taskResult.ts
│   │   │   ├── taskSolution.ts
│   │   │   ├── taskSolutionChecker.ts
│   │   │   ├── taskSolutionResult.ts
│   │   │   ├── taskVerification.ts
│   │   │   ├── team.ts
│   │   │   ├── teamDistribution.ts
│   │   │   ├── teamDistributionStudent.ts
│   │   │   ├── user.ts
│   │   │   └── userGroup.ts
│   │   ├── repositories/
│   │   │   ├── courseTask.repository.ts
│   │   │   ├── crossCheck.repository.ts
│   │   │   ├── feedback.repository.ts
│   │   │   ├── interview.repository.ts
│   │   │   ├── mentor.repository.ts
│   │   │   ├── mentorRegistry.repository.ts
│   │   │   ├── repositoryEvent.repository.ts
│   │   │   ├── stageInterview.repository.ts
│   │   │   ├── stageInterviewFeedback.repository.ts
│   │   │   ├── student.repository.ts
│   │   │   └── user.repository.ts
│   │   ├── reset.d.ts
│   │   ├── routes/
│   │   │   ├── checks/
│   │   │   │   ├── getBadComment.ts
│   │   │   │   ├── getMaxScoreCheckers.ts
│   │   │   │   └── index.ts
│   │   │   ├── common.ts
│   │   │   ├── course/
│   │   │   │   ├── certificates.ts
│   │   │   │   ├── crossCheck/
│   │   │   │   │   ├── createCompletion.ts
│   │   │   │   │   ├── createDistribution.ts
│   │   │   │   │   ├── createMessage.ts
│   │   │   │   │   ├── createResult.ts
│   │   │   │   │   ├── createSolution.ts
│   │   │   │   │   ├── deleteSolution.ts
│   │   │   │   │   ├── getAssignments.ts
│   │   │   │   │   ├── getResult.ts
│   │   │   │   │   ├── getSolution.ts
│   │   │   │   │   ├── getTaskDetails.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── updateMessage.ts
│   │   │   │   ├── events.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── interviews.ts
│   │   │   │   ├── mentor.ts
│   │   │   │   ├── repository.ts
│   │   │   │   ├── schedule.ts
│   │   │   │   ├── score/
│   │   │   │   │   ├── createMultipleScores.ts
│   │   │   │   │   ├── createSingleScore.ts
│   │   │   │   │   ├── getScoreByStudent.ts
│   │   │   │   │   ├── getScoreCsv.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── recalculateScore.ts
│   │   │   │   ├── stageInterview/
│   │   │   │   │   ├── cancelInterview.ts
│   │   │   │   │   ├── createFeedback.ts
│   │   │   │   │   ├── createInterview.ts
│   │   │   │   │   ├── createInterviews.ts
│   │   │   │   │   ├── getFeedback.ts
│   │   │   │   │   ├── getInterviewStudent.ts
│   │   │   │   │   ├── getInterviewerStudents.ts
│   │   │   │   │   ├── getInterviews.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── updateInterview.ts
│   │   │   │   ├── student.ts
│   │   │   │   ├── students.ts
│   │   │   │   ├── taskArtefact.ts
│   │   │   │   ├── taskVerifications.ts
│   │   │   │   └── tasks/
│   │   │   │       ├── createCourseTaskDistribution.ts
│   │   │   │       ├── getCourseTasksDetails.ts
│   │   │   │       └── index.ts
│   │   │   ├── feedback.ts
│   │   │   ├── file/
│   │   │   │   ├── index.ts
│   │   │   │   └── upload.ts
│   │   │   ├── guards.ts
│   │   │   ├── index.ts
│   │   │   ├── logging.ts
│   │   │   ├── me.ts
│   │   │   ├── middlewares.ts
│   │   │   ├── profile/
│   │   │   │   ├── __test__/
│   │   │   │   │   └── permissions.test.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── info.ts
│   │   │   │   ├── me.ts
│   │   │   │   ├── mentor-stats.ts
│   │   │   │   ├── permissions.ts
│   │   │   │   ├── public-feedback.ts
│   │   │   │   ├── stage-interview-feedback.ts
│   │   │   │   ├── student-stats.ts
│   │   │   │   └── user-info.ts
│   │   │   ├── registry/
│   │   │   │   └── index.ts
│   │   │   ├── repository/
│   │   │   │   ├── events.ts
│   │   │   │   └── index.ts
│   │   │   ├── task/
│   │   │   │   └── index.ts
│   │   │   ├── taskVerification/
│   │   │   │   └── index.ts
│   │   │   ├── tasks/
│   │   │   │   └── index.ts
│   │   │   ├── users/
│   │   │   │   └── index.ts
│   │   │   ├── utils.ts
│   │   │   └── validators.ts
│   │   ├── rules/
│   │   │   ├── __tests__/
│   │   │   │   └── mentors.test.ts
│   │   │   ├── index.ts
│   │   │   ├── interviews.ts
│   │   │   ├── mentors.ts
│   │   │   ├── name.ts
│   │   │   └── types.ts
│   │   ├── schedule.ts
│   │   └── services/
│   │       ├── aws.service.ts
│   │       ├── check.service.ts
│   │       ├── course.service.ts
│   │       ├── crossCheck.service.ts
│   │       ├── distribution/
│   │       │   ├── __tests__/
│   │       │   │   ├── crossCheck.test.ts
│   │       │   │   ├── crossMentor.test.ts
│   │       │   │   └── shuffle.test.ts
│   │       │   ├── crossCheckDistribution.service.ts
│   │       │   ├── crossMentorDistribution.service.ts
│   │       │   ├── index.ts
│   │       │   └── shuffle.ts
│   │       ├── github.service.ts
│   │       ├── index.ts
│   │       ├── interview.service.ts
│   │       ├── notification.service.ts
│   │       ├── operationResult.ts
│   │       ├── repository.service.ts
│   │       ├── score/
│   │       │   ├── index.ts
│   │       │   └── score.service.ts
│   │       ├── stageInterview.service.ts
│   │       ├── student.service.ts
│   │       ├── taskResults.service.ts
│   │       ├── taskVerification.service.ts
│   │       ├── tasks.service.ts
│   │       └── user.service.ts
│   ├── swaggerDef.js
│   ├── tsconfig.json
│   └── vitest.config.mts
├── setup/
│   ├── backup-local.sql
│   ├── cdk/
│   │   ├── App.ts
│   │   ├── DockerFunctionConstruct.ts
│   │   ├── Stack.ts
│   │   ├── cdk.json
│   │   └── package.json
│   ├── docker-compose.yml
│   ├── dump-local.sh
│   ├── dump.sh
│   ├── nginx/
│   │   └── nginx.conf
│   ├── restore-local.sh
│   └── restore.sh
├── skills-lock.json
├── tools/
│   └── sloths/
│       ├── .eslintrc.cjs
│       ├── .gitignore
│       ├── .oxfmtrc.json
│       ├── README.md
│       ├── env.d.ts
│       ├── index.html
│       ├── package.json
│       ├── public/
│       │   └── cdn/
│       │       ├── cleaned/
│       │       │   └── filelist.json
│       │       └── stickers/
│       │           ├── activist/
│       │           │   └── metadata.json
│       │           ├── codewars/
│       │           │   └── metadata.json
│       │           ├── congrats/
│       │           │   └── metadata.json
│       │           └── metadata.json
│       ├── src/
│       │   ├── App.vue
│       │   ├── assets/
│       │   │   ├── locales/
│       │   │   │   └── en.json
│       │   │   └── styles/
│       │   │       ├── base.css
│       │   │       ├── fonts.css
│       │   │       ├── main.css
│       │   │       └── variables.css
│       │   ├── common/
│       │   │   ├── const.ts
│       │   │   └── types.ts
│       │   ├── components/
│       │   │   ├── about/
│       │   │   │   ├── AboutSection.vue
│       │   │   │   └── AboutTeammate.vue
│       │   │   ├── background/
│       │   │   │   └── BackgroundView.vue
│       │   │   ├── buttons/
│       │   │   │   ├── CustomBtn.vue
│       │   │   │   ├── IconBtn.vue
│       │   │   │   └── ImageBtn.vue
│       │   │   ├── catalog/
│       │   │   │   ├── SlothCard.vue
│       │   │   │   └── SlothInfo.vue
│       │   │   ├── controls-list/
│       │   │   │   ├── ControlsList.vue
│       │   │   │   ├── PaginationList.vue
│       │   │   │   ├── SearchText.vue
│       │   │   │   ├── SortingList.vue
│       │   │   │   └── TagCloud.vue
│       │   │   ├── footer/
│       │   │   │   └── FooterView.vue
│       │   │   ├── guess/
│       │   │   │   └── GuessInfo.vue
│       │   │   ├── header/
│       │   │   │   └── HeaderView.vue
│       │   │   ├── home/
│       │   │   │   ├── HomeAbout.vue
│       │   │   │   ├── HomeCatalog.vue
│       │   │   │   └── HomeCategory.vue
│       │   │   ├── loader/
│       │   │   │   └── LoaderView.vue
│       │   │   ├── memory/
│       │   │   │   ├── GameField.vue
│       │   │   │   └── MemoryInfo.vue
│       │   │   ├── mixins/
│       │   │   │   └── sort-mixin.ts
│       │   │   ├── modal/
│       │   │   │   ├── AlertModal.vue
│       │   │   │   └── ModalWindow.vue
│       │   │   └── switchers/
│       │   │       ├── SoundSwitcher.vue
│       │   │       └── ThemeSwitcher.vue
│       │   ├── i18n.ts
│       │   ├── main.ts
│       │   ├── router/
│       │   │   └── index.ts
│       │   ├── services/
│       │   │   ├── error-handler.ts
│       │   │   └── sloths-service.ts
│       │   ├── shims-vue.d.ts
│       │   ├── stores/
│       │   │   ├── alert-modal.ts
│       │   │   ├── audio-on.ts
│       │   │   ├── cleaned.ts
│       │   │   ├── counter.ts
│       │   │   ├── loader.ts
│       │   │   ├── pages-store.ts
│       │   │   ├── pagination.ts
│       │   │   ├── search-text.ts
│       │   │   ├── sloth-info.ts
│       │   │   ├── sloths.ts
│       │   │   ├── sorting-list.ts
│       │   │   ├── tag-cloud.ts
│       │   │   └── theme.ts
│       │   ├── utils/
│       │   │   ├── audio.ts
│       │   │   ├── canvas-utils.ts
│       │   │   ├── game-utils.ts
│       │   │   └── userTheme.ts
│       │   └── views/
│       │       ├── 404.vue
│       │       ├── About.vue
│       │       ├── Catalog.vue
│       │       ├── Create.vue
│       │       ├── Guess.vue
│       │       ├── Home.vue
│       │       ├── Memory.vue
│       │       └── Merch.vue
│       ├── tsconfig.config.json
│       ├── tsconfig.json
│       └── vite.config.ts
├── turbo.json
└── vitest.shared.mts
Download .txt
Showing preview only (433K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4373 symbols across 1085 files)

FILE: .agents/skills/nestjs-best-practices/scripts/build-agents.ts
  constant CATEGORIES (line 24) | const CATEGORIES = [
  type RuleFrontmatter (line 37) | interface RuleFrontmatter {
  type Rule (line 44) | interface Rule {
  function parseFrontmatter (line 52) | function parseFrontmatter(content: string): { frontmatter: RuleFrontmatt...
  function getCategoryForFile (line 105) | function getCategoryForFile(filename: string): { name: string; section: ...
  function readMetadata (line 114) | function readMetadata(): any {
  function readRules (line 119) | function readRules(): Rule[] {
  function generateTableOfContents (line 153) | function generateTableOfContents(rulesByCategory: Map<string, Rule[]>): ...
  function generateAgentsMd (line 176) | function generateAgentsMd(rules: Rule[], metadata: any): string {
  function main (line 264) | function main() {

FILE: client/src/__mocks__/axios.js
  method reset (line 15) | reset() {

FILE: client/src/__mocks__/next/config.ts
  function getConfig (line 1) | function getConfig() {

FILE: client/src/api/api.ts
  type ActivityDto (line 29) | interface ActivityDto {
  type AlertDto (line 48) | interface AlertDto {
  type ApplicantResumeDto (line 97) | interface ApplicantResumeDto {
  type ApplicantResumeDtoEnglishLevelEnum (line 237) | type ApplicantResumeDtoEnglishLevelEnum = typeof ApplicantResumeDtoEngli...
  type ApplicantResumeDtoMilitaryServiceEnum (line 244) | type ApplicantResumeDtoMilitaryServiceEnum = typeof ApplicantResumeDtoMi...
  type ApproveMentorDto (line 251) | interface ApproveMentorDto {
  type Attributes (line 264) | interface Attributes {
  type AuthConnectionDto (line 277) | interface AuthConnectionDto {
  type AuthUserDto (line 296) | interface AuthUserDto {
  type AuthUserDtoRolesEnum (line 346) | type AuthUserDtoRolesEnum = typeof AuthUserDtoRolesEnum[keyof typeof Aut...
  type AuthUserDtoCourses (line 353) | interface AuthUserDtoCourses {
  type AuthUserDtoCoursesRolesEnum (line 371) | type AuthUserDtoCoursesRolesEnum = typeof AuthUserDtoCoursesRolesEnum[ke...
  type AutoTestAttributesDto (line 378) | interface AutoTestAttributesDto {
  type AutoTestTaskDto (line 397) | interface AutoTestTaskDto {
  type AutoTestTaskDtoTypeEnum (line 506) | type AutoTestTaskDtoTypeEnum = typeof AutoTestTaskDtoTypeEnum[keyof type...
  type AvailableReviewStatsDto (line 513) | interface AvailableReviewStatsDto {
  type AvailableStudentDto (line 544) | interface AvailableStudentDto {
  type BadgeDto (line 617) | interface BadgeDto {
  type BadgeEnum (line 656) | type BadgeEnum = typeof BadgeEnum[keyof typeof BadgeEnum];
  type BasicAutoTestTaskDto (line 664) | interface BasicAutoTestTaskDto {
  type ChannelSettings (line 707) | interface ChannelSettings {
  type CheckScheduleChangesDto (line 726) | interface CheckScheduleChangesDto {
  type CheckTasksDeadlineDto (line 739) | interface CheckTasksDeadlineDto {
  type CheckerEnum (line 761) | type CheckerEnum = typeof CheckerEnum[keyof typeof CheckerEnum];
  type CommentMentorRegistryDto (line 769) | interface CommentMentorRegistryDto {
  type ConsentDto (line 782) | interface ConsentDto {
  type ContactsDto (line 795) | interface ContactsDto {
  type ContributorDto (line 856) | interface ContributorDto {
  type ContributorUserDto (line 893) | interface ContributorUserDto {
  type CountriesStatsDto (line 924) | interface CountriesStatsDto {
  type CountryDto (line 937) | interface CountryDto {
  type CountryStatDto (line 950) | interface CountryStatDto {
  type CourseAggregateStatsDto (line 969) | interface CourseAggregateStatsDto {
  type CourseCopyFromDto (line 1012) | interface CourseCopyFromDto {
  type CourseDto (line 1025) | interface CourseDto {
  type CourseEventDto (line 1212) | interface CourseEventDto {
  type CourseEventDtoTypeEnum (line 1277) | type CourseEventDtoTypeEnum = typeof CourseEventDtoTypeEnum[keyof typeof...
  type CourseMentorsStatsDto (line 1284) | interface CourseMentorsStatsDto {
  type CourseRecord (line 1309) | interface CourseRecord {
  type CourseRolesDto (line 1328) | interface CourseRolesDto {
  type CourseScheduleItemDto (line 1359) | interface CourseScheduleItemDto {
  type CourseScheduleItemDtoStatusEnum (line 1451) | type CourseScheduleItemDtoStatusEnum = typeof CourseScheduleItemDtoStatu...
  type CourseScheduleItemDtoTagEnum (line 1463) | type CourseScheduleItemDtoTagEnum = typeof CourseScheduleItemDtoTagEnum[...
  type CourseScheduleItemDtoTypeEnum (line 1470) | type CourseScheduleItemDtoTypeEnum = typeof CourseScheduleItemDtoTypeEnu...
  type CourseScheduleTokenDto (line 1477) | interface CourseScheduleTokenDto {
  type CourseStatsDto (line 1490) | interface CourseStatsDto {
  type CourseTaskDetailedDto (line 1527) | interface CourseTaskDetailedDto {
  type CourseTaskDetailedDtoTypeEnum (line 1678) | type CourseTaskDetailedDtoTypeEnum = typeof CourseTaskDetailedDtoTypeEnu...
  type CourseTaskDetailedDtoCheckerEnum (line 1687) | type CourseTaskDetailedDtoCheckerEnum = typeof CourseTaskDetailedDtoChec...
  type CourseTaskDto (line 1694) | interface CourseTaskDto {
  type CourseTaskDtoTypeEnum (line 1821) | type CourseTaskDtoTypeEnum = typeof CourseTaskDtoTypeEnum[keyof typeof C...
  type CourseTaskDtoCheckerEnum (line 1830) | type CourseTaskDtoCheckerEnum = typeof CourseTaskDtoCheckerEnum[keyof ty...
  type CourseUserDto (line 1837) | interface CourseUserDto {
  type CreateActivityDto (line 1898) | interface CreateActivityDto {
  type CreateActivityWebhookDto (line 1911) | interface CreateActivityWebhookDto {
  type CreateAlertDto (line 1924) | interface CreateAlertDto {
  type CreateContributorDto (line 1955) | interface CreateContributorDto {
  type CreateCourseDto (line 1974) | interface CreateCourseDto {
  type CreateCourseEventDto (line 2119) | interface CreateCourseEventDto {
  type CreateCourseTaskDto (line 2192) | interface CreateCourseTaskDto {
  type CreateCourseTaskDtoTypeEnum (line 2289) | type CreateCourseTaskDtoTypeEnum = typeof CreateCourseTaskDtoTypeEnum[ke...
  type CreateDisciplineDto (line 2296) | interface CreateDisciplineDto {
  type CreateDiscordServerDto (line 2309) | interface CreateDiscordServerDto {
  type CreateEventDto (line 2334) | interface CreateEventDto {
  type CreateGratitudeDto (line 2371) | interface CreateGratitudeDto {
  type CreatePromptDto (line 2402) | interface CreatePromptDto {
  type CreateStudentFeedbackDto (line 2427) | interface CreateStudentFeedbackDto {
  type CreateStudentFeedbackDtoRecommendationEnum (line 2453) | type CreateStudentFeedbackDtoRecommendationEnum = typeof CreateStudentFe...
  type CreateStudentFeedbackDtoEnglishLevelEnum (line 2465) | type CreateStudentFeedbackDtoEnglishLevelEnum = typeof CreateStudentFeed...
  type CreateTaskDto (line 2472) | interface CreateTaskDto {
  type CreateTaskVerificationDto (line 2545) | interface CreateTaskVerificationDto {
  type CreateTeamDistributionDto (line 2558) | interface CreateTeamDistributionDto {
  type CreateTeamDto (line 2625) | interface CreateTeamDto {
  type CreateUserGroupDto (line 2656) | interface CreateUserGroupDto {
  type CreateUserGroupDtoRolesEnum (line 2687) | type CreateUserGroupDtoRolesEnum = typeof CreateUserGroupDtoRolesEnum[ke...
  type CriteriaDto (line 2694) | interface CriteriaDto {
  type CriteriaDtoTypeEnum (line 2733) | type CriteriaDtoTypeEnum = typeof CriteriaDtoTypeEnum[keyof typeof Crite...
  type CrossCheckAuthorDto (line 2740) | interface CrossCheckAuthorDto {
  type CrossCheckCriteriaDataDto (line 2771) | interface CrossCheckCriteriaDataDto {
  type CrossCheckCriteriaDataDtoTypeEnum (line 2816) | type CrossCheckCriteriaDataDtoTypeEnum = typeof CrossCheckCriteriaDataDt...
  type CrossCheckFeedbackDto (line 2823) | interface CrossCheckFeedbackDto {
  type CrossCheckMessageAuthorDto (line 2842) | interface CrossCheckMessageAuthorDto {
  type CrossCheckMessageDto (line 2861) | interface CrossCheckMessageDto {
  type CrossCheckMessageDtoRoleEnum (line 2905) | type CrossCheckMessageDtoRoleEnum = typeof CrossCheckMessageDtoRoleEnum[...
  type CrossCheckPairDto (line 2912) | interface CrossCheckPairDto {
  type CrossCheckPairResponseDto (line 2991) | interface CrossCheckPairResponseDto {
  type CrossCheckSolutionReviewDto (line 3010) | interface CrossCheckSolutionReviewDto {
  type CrossCheckStatusEnum (line 3066) | type CrossCheckStatusEnum = typeof CrossCheckStatusEnum[keyof typeof Cro...
  type DevtoolsUserDto (line 3074) | interface DevtoolsUserDto {
  type DisciplineDto (line 3105) | interface DisciplineDto {
  type DisciplineIdsDto (line 3136) | interface DisciplineIdsDto {
  type Discord (line 3149) | interface Discord {
  type DiscordServerDto (line 3174) | interface DiscordServerDto {
  type Education (line 3217) | interface Education {
  type EndorsementDataDto (line 3242) | interface EndorsementDataDto {
  type EndorsementDto (line 3273) | interface EndorsementDto {
  type EndorsementUserDto (line 3292) | interface EndorsementUserDto {
  type EventDto (line 3323) | interface EventDto {
  type EventDtoTypeEnum (line 3376) | type EventDtoTypeEnum = typeof EventDtoTypeEnum[keyof typeof EventDtoTyp...
  type ExpelCriteriaDto (line 3383) | interface ExpelCriteriaDto {
  type ExpelOptionsDto (line 3402) | interface ExpelOptionsDto {
  type ExpelStatusDto (line 3421) | interface ExpelStatusDto {
  type ExpelledStatsDto (line 3446) | interface ExpelledStatsDto {
  type FeedbackCourseDto (line 3489) | interface FeedbackCourseDto {
  type FeedbackDto (line 3508) | interface FeedbackDto {
  type FeedbackSoftSkill (line 3563) | interface FeedbackSoftSkill {
  type FeedbackSoftSkillValueEnum (line 3587) | type FeedbackSoftSkillValueEnum = typeof FeedbackSoftSkillValueEnum[keyo...
  type FeedbackSoftSkillIdEnum (line 3594) | type FeedbackSoftSkillIdEnum = typeof FeedbackSoftSkillIdEnum[keyof type...
  type FilterMentorRegistryResponse (line 3601) | interface FilterMentorRegistryResponse {
  type FormDataDto (line 3620) | interface FormDataDto {
  type FormDataDtoEnglishLevelEnum (line 3742) | type FormDataDtoEnglishLevelEnum = typeof FormDataDtoEnglishLevelEnum[ke...
  type FormDataDtoMilitaryServiceEnum (line 3749) | type FormDataDtoMilitaryServiceEnum = typeof FormDataDtoMilitaryServiceE...
  type GiveConsentDto (line 3756) | interface GiveConsentDto {
  type GratitudeDto (line 3775) | interface GratitudeDto {
  type HeroRadarDto (line 3818) | interface HeroRadarDto {
  type HeroesRadarBadgeDto (line 3855) | interface HeroesRadarBadgeDto {
  type HeroesRadarDto (line 3886) | interface HeroesRadarDto {
  type HistoricalScoreDto (line 3905) | interface HistoricalScoreDto {
  type IdNameDto (line 3930) | interface IdNameDto {
  type InterviewCommentDto (line 3949) | interface InterviewCommentDto {
  type InterviewDistributeDto (line 3968) | interface InterviewDistributeDto {
  type InterviewDistributeResponseDto (line 3987) | interface InterviewDistributeResponseDto {
  type InterviewDto (line 4030) | interface InterviewDto {
  type InterviewFeedbackDto (line 4091) | interface InterviewFeedbackDto {
  type InterviewPairDto (line 4122) | interface InterviewPairDto {
  type InterviewStatus (line 4165) | type InterviewStatus = typeof InterviewStatus[keyof typeof InterviewStat...
  type InviteMentorsDto (line 4173) | interface InviteMentorsDto {
  type JoinTeamDto (line 4198) | interface JoinTeamDto {
  type LeaveCourseRequestDto (line 4211) | interface LeaveCourseRequestDto {
  type MentorCourseStatsDto (line 4230) | interface MentorCourseStatsDto {
  type MentorDashboardDto (line 4249) | interface MentorDashboardDto {
  type MentorDetailsDto (line 4316) | interface MentorDetailsDto {
  type MentorDetailsDtoStudentsPreferenceEnum (line 4409) | type MentorDetailsDtoStudentsPreferenceEnum = typeof MentorDetailsDtoStu...
  type MentorDto (line 4416) | interface MentorDto {
  type MentorOptionsDto (line 4441) | interface MentorOptionsDto {
  type MentorOptionsDtoPreferedStudentsLocationEnum (line 4468) | type MentorOptionsDtoPreferedStudentsLocationEnum = typeof MentorOptions...
  type MentorRegistryDto (line 4475) | interface MentorRegistryDto {
  type MentorReviewAssignDto (line 4590) | interface MentorReviewAssignDto {
  type MentorReviewDto (line 4615) | interface MentorReviewDto {
  type MentorReviewsDto (line 4694) | interface MentorReviewsDto {
  type MentorStudentDto (line 4713) | interface MentorStudentDto {
  type MentorStudentSummaryDto (line 4780) | interface MentorStudentSummaryDto {
  type NotificationConnectionDto (line 4865) | interface NotificationConnectionDto {
  type NotificationConnectionExistsDto (line 4896) | interface NotificationConnectionExistsDto {
  type NotificationDto (line 4921) | interface NotificationDto {
  type NotificationType (line 4970) | type NotificationType = typeof NotificationType[keyof typeof Notificatio...
  type NotificationUserConnectionsDto (line 4978) | interface NotificationUserConnectionsDto {
  type NotificationUserSettingsDto (line 4991) | interface NotificationUserSettingsDto {
  type Organizer (line 5022) | interface Organizer {
  type PaginationDto (line 5035) | interface PaginationDto {
  type PaginationMetaDto (line 5066) | interface PaginationMetaDto {
  type PersonDto (line 5103) | interface PersonDto {
  type PersonalProfileDto (line 5128) | interface PersonalProfileDto {
  type ProfileCourseDto (line 5159) | interface ProfileCourseDto {
  type ProfileDto (line 5346) | interface ProfileDto {
  type PromptDto (line 5359) | interface PromptDto {
  type PublicAttributesDto (line 5390) | interface PublicAttributesDto {
  type PutInterviewFeedbackDto (line 5427) | interface PutInterviewFeedbackDto {
  type QuestionDto (line 5470) | interface QuestionDto {
  type ResultDto (line 5507) | interface ResultDto {
  type ResumeCourseDto (line 5526) | interface ResumeCourseDto {
  type ResumeCourseMentor (line 5587) | interface ResumeCourseMentor {
  type ResumeDto (line 5612) | interface ResumeDto {
  type ResumeDtoEnglishLevelEnum (line 5770) | type ResumeDtoEnglishLevelEnum = typeof ResumeDtoEnglishLevelEnum[keyof ...
  type ResumeDtoMilitaryServiceEnum (line 5777) | type ResumeDtoMilitaryServiceEnum = typeof ResumeDtoMilitaryServiceEnum[...
  type SaveCertificateDto (line 5784) | interface SaveCertificateDto {
  type SaveTaskSolutionDto (line 5821) | interface SaveTaskSolutionDto {
  type ScoreDto (line 5834) | interface ScoreDto {
  type ScoreStudentDto (line 5853) | interface ScoreStudentDto {
  type SearchMentorDto (line 5950) | interface SearchMentorDto {
  type SelfEducationQuestionSelectedAnswersDto (line 5975) | interface SelfEducationQuestionSelectedAnswersDto {
  type SendUserNotificationDto (line 6018) | interface SendUserNotificationDto {
  type SenderDto (line 6049) | interface SenderDto {
  type SenderLoginDto (line 6062) | interface SenderLoginDto {
  type SoftSkillEntry (line 6075) | interface SoftSkillEntry {
  type SoftSkillEntryIdEnum (line 6096) | type SoftSkillEntryIdEnum = typeof SoftSkillEntryIdEnum[keyof typeof Sof...
  type SoftSkillEntryValueEnum (line 6106) | type SoftSkillEntryValueEnum = typeof SoftSkillEntryValueEnum[keyof type...
  type SolutionItemStatusEnum (line 6120) | type SolutionItemStatusEnum = typeof SolutionItemStatusEnum[keyof typeof...
  type StatusDto (line 6128) | interface StatusDto {
  type StudentDto (line 6141) | interface StudentDto {
  type StudentFeedbackContentDto (line 6196) | interface StudentFeedbackContentDto {
  type StudentFeedbackDto (line 6221) | interface StudentFeedbackDto {
  type StudentFeedbackDtoRecommendationEnum (line 6277) | type StudentFeedbackDtoRecommendationEnum = typeof StudentFeedbackDtoRec...
  type StudentFeedbackDtoEnglishLevelEnum (line 6289) | type StudentFeedbackDtoEnglishLevelEnum = typeof StudentFeedbackDtoEngli...
  type StudentId (line 6296) | interface StudentId {
  type StudentSummaryDto (line 6309) | interface StudentSummaryDto {
  type StudentsDto (line 6352) | interface StudentsDto {
  type TaskCriteriaDto (line 6377) | interface TaskCriteriaDto {
  type TaskDto (line 6390) | interface TaskDto {
  type TaskDtoTypeEnum (line 6499) | type TaskDtoTypeEnum = typeof TaskDtoTypeEnum[keyof typeof TaskDtoTypeEn...
  type TaskPerformanceStatsDto (line 6506) | interface TaskPerformanceStatsDto {
  type TaskResultsDto (line 6555) | interface TaskResultsDto {
  type TaskSolutionDto (line 6574) | interface TaskSolutionDto {
  type TaskVerificationAttemptDto (line 6599) | interface TaskVerificationAttemptDto {
  type TeamDistributionDetailedDto (line 6636) | interface TeamDistributionDetailedDto {
  type TeamDistributionDto (line 6703) | interface TeamDistributionDto {
  type TeamDistributionDtoRegistrationStatusEnum (line 6787) | type TeamDistributionDtoRegistrationStatusEnum = typeof TeamDistribution...
  type TeamDistributionStudentDto (line 6794) | interface TeamDistributionStudentDto {
  type TeamDto (line 6867) | interface TeamDto {
  type TeamInfoDto (line 6916) | interface TeamInfoDto {
  type TeamPasswordDto (line 6959) | interface TeamPasswordDto {
  type TeamsDto (line 6972) | interface TeamsDto {
  type TopMentorDto (line 6991) | interface TopMentorDto {
  type UpdateContributorDto (line 7034) | interface UpdateContributorDto {
  type UpdateCourseDto (line 7053) | interface UpdateCourseDto {
  type UpdateCourseEventDto (line 7210) | interface UpdateCourseEventDto {
  type UpdateCourseTaskDto (line 7277) | interface UpdateCourseTaskDto {
  type UpdateCourseTaskDtoTypeEnum (line 7386) | type UpdateCourseTaskDtoTypeEnum = typeof UpdateCourseTaskDtoTypeEnum[ke...
  type UpdateCourseUserDto (line 7393) | interface UpdateCourseUserDto {
  type UpdateDisciplineDto (line 7430) | interface UpdateDisciplineDto {
  type UpdateDiscordServerDto (line 7443) | interface UpdateDiscordServerDto {
  type UpdateEventDto (line 7468) | interface UpdateEventDto {
  type UpdateNotificationDto (line 7505) | interface UpdateNotificationDto {
  type UpdateNotificationUserSettingsDto (line 7548) | interface UpdateNotificationUserSettingsDto {
  type UpdateProfileInfoDto (line 7573) | interface UpdateProfileInfoDto {
  type UpdatePromptDto (line 7682) | interface UpdatePromptDto {
  type UpdateStudentFeedbackDto (line 7707) | interface UpdateStudentFeedbackDto {
  type UpdateStudentFeedbackDtoRecommendationEnum (line 7733) | type UpdateStudentFeedbackDtoRecommendationEnum = typeof UpdateStudentFe...
  type UpdateStudentFeedbackDtoEnglishLevelEnum (line 7745) | type UpdateStudentFeedbackDtoEnglishLevelEnum = typeof UpdateStudentFeed...
  type UpdateTaskDto (line 7752) | interface UpdateTaskDto {
  type UpdateTeamDistributionDto (line 7825) | interface UpdateTeamDistributionDto {
  type UpdateTeamDto (line 7892) | interface UpdateTeamDto {
  type UpdateUserDto (line 7923) | interface UpdateUserDto {
  type UpdateUserDtoLanguagesEnum (line 8052) | type UpdateUserDtoLanguagesEnum = typeof UpdateUserDtoLanguagesEnum[keyo...
  type UpdateUserGroupDto (line 8059) | interface UpdateUserGroupDto {
  type UpdateUserGroupDtoRolesEnum (line 8090) | type UpdateUserGroupDtoRolesEnum = typeof UpdateUserGroupDtoRolesEnum[ke...
  type UpsertNotificationConnectionDto (line 8097) | interface UpsertNotificationConnectionDto {
  type UsedCourseDto (line 8128) | interface UsedCourseDto {
  type UserDto (line 8147) | interface UserDto {
  type UserGroupDto (line 8172) | interface UserGroupDto {
  type UserGroupDtoRolesEnum (line 8209) | type UserGroupDtoRolesEnum = typeof UserGroupDtoRolesEnum[keyof typeof U...
  type UserNotificationsDto (line 8216) | interface UserNotificationsDto {
  type UserSearchDto (line 8235) | interface UserSearchDto {
  type UserStudentCourseDto (line 8314) | interface UserStudentCourseDto {
  type UserStudentDto (line 8381) | interface UserStudentDto {
  type UserStudentsDto (line 8472) | interface UserStudentsDto {
  type Validations (line 8491) | interface Validations {
  type VisibilityDto (line 8510) | interface VisibilityDto {
  method createActivity (line 8640) | async createActivity(createActivityDto: CreateActivityDto, options?: Axi...
  method createActivityWebhook (line 8650) | async createActivityWebhook(createActivityWebhookDto: CreateActivityWebh...
  method getActivity (line 8659) | async getActivity(options?: AxiosRequestConfig): Promise<(axios?: AxiosI...
  method createActivity (line 8679) | createActivity(createActivityDto: CreateActivityDto, options?: any): Axi...
  method createActivityWebhook (line 8688) | createActivityWebhook(createActivityWebhookDto: CreateActivityWebhookDto...
  method getActivity (line 8696) | getActivity(options?: any): AxiosPromise<ActivityDto> {
  class ActivityApi (line 8708) | class ActivityApi extends BaseAPI {
    method createActivity (line 8716) | public createActivity(createActivityDto: CreateActivityDto, options?: ...
    method createActivityWebhook (line 8727) | public createActivityWebhook(createActivityWebhookDto: CreateActivityW...
    method getActivity (line 8737) | public getActivity(options?: AxiosRequestConfig) {
  method createAlert (line 8908) | async createAlert(createAlertDto: CreateAlertDto, options?: AxiosRequest...
  method deleteAlert (line 8918) | async deleteAlert(id: number, options?: AxiosRequestConfig): Promise<(ax...
  method getAlerts (line 8928) | async getAlerts(enabled: boolean, options?: AxiosRequestConfig): Promise...
  method updateAlert (line 8939) | async updateAlert(id: number, body: object, options?: AxiosRequestConfig...
  method createAlert (line 8959) | createAlert(createAlertDto: CreateAlertDto, options?: any): AxiosPromise...
  method deleteAlert (line 8968) | deleteAlert(id: number, options?: any): AxiosPromise<void> {
  method getAlerts (line 8977) | getAlerts(enabled: boolean, options?: any): AxiosPromise<Array<AlertDto>> {
  method updateAlert (line 8987) | updateAlert(id: number, body: object, options?: any): AxiosPromise<Alert...
  class AlertsApi (line 8999) | class AlertsApi extends BaseAPI {
    method createAlert (line 9007) | public createAlert(createAlertDto: CreateAlertDto, options?: AxiosRequ...
    method deleteAlert (line 9018) | public deleteAlert(id: number, options?: AxiosRequestConfig) {
    method getAlerts (line 9029) | public getAlerts(enabled: boolean, options?: AxiosRequestConfig) {
    method updateAlert (line 9041) | public updateAlert(id: number, body: object, options?: AxiosRequestCon...
  method authControllerCreateConnectLinkViaGithub (line 9224) | async authControllerCreateConnectLinkViaGithub(authConnectionDto: AuthCo...
  method clearAuthUserSessionCache (line 9234) | async clearAuthUserSessionCache(userId: number, options?: AxiosRequestCo...
  method githubCallback (line 9243) | async githubCallback(options?: AxiosRequestConfig): Promise<(axios?: Axi...
  method githubLogin (line 9252) | async githubLogin(options?: AxiosRequestConfig): Promise<(axios?: AxiosI...
  method githubLogout (line 9261) | async githubLogout(options?: AxiosRequestConfig): Promise<(axios?: Axios...
  method authControllerCreateConnectLinkViaGithub (line 9281) | authControllerCreateConnectLinkViaGithub(authConnectionDto: AuthConnecti...
  method clearAuthUserSessionCache (line 9290) | clearAuthUserSessionCache(userId: number, options?: any): AxiosPromise<v...
  method githubCallback (line 9298) | githubCallback(options?: any): AxiosPromise<void> {
  method githubLogin (line 9306) | githubLogin(options?: any): AxiosPromise<void> {
  method githubLogout (line 9314) | githubLogout(options?: any): AxiosPromise<void> {
  class AuthApi (line 9326) | class AuthApi extends BaseAPI {
    method authControllerCreateConnectLinkViaGithub (line 9334) | public authControllerCreateConnectLinkViaGithub(authConnectionDto: Aut...
    method clearAuthUserSessionCache (line 9345) | public clearAuthUserSessionCache(userId: number, options?: AxiosReques...
    method githubCallback (line 9355) | public githubCallback(options?: AxiosRequestConfig) {
    method githubLogin (line 9365) | public githubLogin(options?: AxiosRequestConfig) {
    method githubLogout (line 9375) | public githubLogout(options?: AxiosRequestConfig) {
  method getAutoTest (line 9465) | async getAutoTest(id: number, options?: AxiosRequestConfig): Promise<(ax...
  method getBasicAutoTests (line 9474) | async getBasicAutoTests(options?: AxiosRequestConfig): Promise<(axios?: ...
  method getAutoTest (line 9494) | getAutoTest(id: number, options?: any): AxiosPromise<AutoTestTaskDto> {
  method getBasicAutoTests (line 9502) | getBasicAutoTests(options?: any): AxiosPromise<Array<BasicAutoTestTaskDt...
  class AutoTestsApi (line 9514) | class AutoTestsApi extends BaseAPI {
    method getAutoTest (line 9522) | public getAutoTest(id: number, options?: AxiosRequestConfig) {
    method getBasicAutoTests (line 9532) | public getBasicAutoTests(options?: AxiosRequestConfig) {
  method getCertificate (line 9661) | async getCertificate(publicId: string, options?: AxiosRequestConfig): Pr...
  method removeCertificate (line 9671) | async removeCertificate(studentId: number, options?: AxiosRequestConfig)...
  method saveCertificate (line 9681) | async saveCertificate(saveCertificateDto: SaveCertificateDto, options?: ...
  method getCertificate (line 9701) | getCertificate(publicId: string, options?: any): AxiosPromise<void> {
  method removeCertificate (line 9710) | removeCertificate(studentId: number, options?: any): AxiosPromise<void> {
  method saveCertificate (line 9719) | saveCertificate(saveCertificateDto: SaveCertificateDto, options?: any): ...
  class CertificateApi (line 9731) | class CertificateApi extends BaseAPI {
    method getCertificate (line 9739) | public getCertificate(publicId: string, options?: AxiosRequestConfig) {
    method removeCertificate (line 9750) | public removeCertificate(studentId: number, options?: AxiosRequestConf...
    method saveCertificate (line 9761) | public saveCertificate(saveCertificateDto: SaveCertificateDto, options...
  method createContributor (line 9958) | async createContributor(createContributorDto: CreateContributorDto, opti...
  method deleteContributor (line 9968) | async deleteContributor(id: number, options?: AxiosRequestConfig): Promi...
  method getContributor (line 9978) | async getContributor(id: number, options?: AxiosRequestConfig): Promise<...
  method getContributors (line 9987) | async getContributors(options?: AxiosRequestConfig): Promise<(axios?: Ax...
  method updateContributor (line 9998) | async updateContributor(id: number, updateContributorDto: UpdateContribu...
  method createContributor (line 10018) | createContributor(createContributorDto: CreateContributorDto, options?: ...
  method deleteContributor (line 10027) | deleteContributor(id: number, options?: any): AxiosPromise<void> {
  method getContributor (line 10036) | getContributor(id: number, options?: any): AxiosPromise<ContributorDto> {
  method getContributors (line 10044) | getContributors(options?: any): AxiosPromise<Array<ContributorDto>> {
  method updateContributor (line 10054) | updateContributor(id: number, updateContributorDto: UpdateContributorDto...
  class ContributorsApi (line 10066) | class ContributorsApi extends BaseAPI {
    method createContributor (line 10074) | public createContributor(createContributorDto: CreateContributorDto, o...
    method deleteContributor (line 10085) | public deleteContributor(id: number, options?: AxiosRequestConfig) {
    method getContributor (line 10096) | public getContributor(id: number, options?: AxiosRequestConfig) {
    method getContributors (line 10106) | public getContributors(options?: AxiosRequestConfig) {
    method updateContributor (line 10118) | public updateContributor(id: number, updateContributorDto: UpdateContr...
  method getMentorsDetails (line 10249) | async getMentorsDetails(courseId: number, options?: AxiosRequestConfig):...
  method getMentorsDetailsCsv (line 10259) | async getMentorsDetailsCsv(courseId: number, options?: AxiosRequestConfi...
  method searchMentors (line 10270) | async searchMentors(courseId: number, searchText: string, options?: Axio...
  method getMentorsDetails (line 10290) | getMentorsDetails(courseId: number, options?: any): AxiosPromise<Array<M...
  method getMentorsDetailsCsv (line 10299) | getMentorsDetailsCsv(courseId: number, options?: any): AxiosPromise<void> {
  method searchMentors (line 10309) | searchMentors(courseId: number, searchText: string, options?: any): Axio...
  class CourseMentorsApi (line 10321) | class CourseMentorsApi extends BaseAPI {
    method getMentorsDetails (line 10329) | public getMentorsDetails(courseId: number, options?: AxiosRequestConfi...
    method getMentorsDetailsCsv (line 10340) | public getMentorsDetailsCsv(courseId: number, options?: AxiosRequestCo...
    method searchMentors (line 10352) | public searchMentors(courseId: number, searchText: string, options?: A...
  method deleteExpelledStat (line 10720) | async deleteExpelledStat(id: string, options?: AxiosRequestConfig): Prom...
  method getCourseExpelledStats (line 10730) | async getCourseExpelledStats(courseId: number, options?: AxiosRequestCon...
  method getCourseMentorCountries (line 10740) | async getCourseMentorCountries(courseId: number, options?: AxiosRequestC...
  method getCourseMentors (line 10750) | async getCourseMentors(courseId: number, options?: AxiosRequestConfig): ...
  method getCourseStats (line 10760) | async getCourseStats(courseId: number, options?: AxiosRequestConfig): Pr...
  method getCourseStudentCertificatesCountries (line 10770) | async getCourseStudentCertificatesCountries(courseId: number, options?: ...
  method getCourseStudentCountries (line 10780) | async getCourseStudentCountries(courseId: number, options?: AxiosRequest...
  method getCoursesStats (line 10791) | async getCoursesStats(ids: Array<number>, year: number, options?: AxiosR...
  method getExpelledStats (line 10800) | async getExpelledStats(options?: AxiosRequestConfig): Promise<(axios?: A...
  method getTaskPerformance (line 10811) | async getTaskPerformance(courseId: number, taskId: number, options?: Axi...
  method deleteExpelledStat (line 10831) | deleteExpelledStat(id: string, options?: any): AxiosPromise<string> {
  method getCourseExpelledStats (line 10840) | getCourseExpelledStats(courseId: number, options?: any): AxiosPromise<Ar...
  method getCourseMentorCountries (line 10849) | getCourseMentorCountries(courseId: number, options?: any): AxiosPromise<...
  method getCourseMentors (line 10858) | getCourseMentors(courseId: number, options?: any): AxiosPromise<CourseMe...
  method getCourseStats (line 10867) | getCourseStats(courseId: number, options?: any): AxiosPromise<CourseStat...
  method getCourseStudentCertificatesCountries (line 10876) | getCourseStudentCertificatesCountries(courseId: number, options?: any): ...
  method getCourseStudentCountries (line 10885) | getCourseStudentCountries(courseId: number, options?: any): AxiosPromise...
  method getCoursesStats (line 10895) | getCoursesStats(ids: Array<number>, year: number, options?: any): AxiosP...
  method getExpelledStats (line 10903) | getExpelledStats(options?: any): AxiosPromise<Array<ExpelledStatsDto>> {
  method getTaskPerformance (line 10913) | getTaskPerformance(courseId: number, taskId: number, options?: any): Axi...
  class CourseStatsApi (line 10925) | class CourseStatsApi extends BaseAPI {
    method deleteExpelledStat (line 10933) | public deleteExpelledStat(id: string, options?: AxiosRequestConfig) {
    method getCourseExpelledStats (line 10944) | public getCourseExpelledStats(courseId: number, options?: AxiosRequest...
    method getCourseMentorCountries (line 10955) | public getCourseMentorCountries(courseId: number, options?: AxiosReque...
    method getCourseMentors (line 10966) | public getCourseMentors(courseId: number, options?: AxiosRequestConfig) {
    method getCourseStats (line 10977) | public getCourseStats(courseId: number, options?: AxiosRequestConfig) {
    method getCourseStudentCertificatesCountries (line 10988) | public getCourseStudentCertificatesCountries(courseId: number, options...
    method getCourseStudentCountries (line 10999) | public getCourseStudentCountries(courseId: number, options?: AxiosRequ...
    method getCoursesStats (line 11011) | public getCoursesStats(ids: Array<number>, year: number, options?: Axi...
    method getExpelledStats (line 11021) | public getExpelledStats(options?: AxiosRequestConfig) {
    method getTaskPerformance (line 11033) | public getTaskPerformance(courseId: number, taskId: number, options?: ...
  method createTaskVerification (line 11143) | async createTaskVerification(courseId: number, courseTaskId: number, bod...
  method getAnswers (line 11154) | async getAnswers(courseId: number, courseTaskId: number, options?: Axios...
  method createTaskVerification (line 11176) | createTaskVerification(courseId: number, courseTaskId: number, body: obj...
  method getAnswers (line 11186) | getAnswers(courseId: number, courseTaskId: number, options?: any): Axios...
  class CourseTaskVerificationsApi (line 11198) | class CourseTaskVerificationsApi extends BaseAPI {
    method createTaskVerification (line 11208) | public createTaskVerification(courseId: number, courseTaskId: number, ...
    method getAnswers (line 11220) | public getAnswers(courseId: number, courseTaskId: number, options?: Ax...
  method getCourseUsers (line 11363) | async getCourseUsers(courseId: number, options?: AxiosRequestConfig): Pr...
  method putCourseUser (line 11375) | async putCourseUser(courseId: number, githubId: string, courseRolesDto: ...
  method putCourseUsers (line 11386) | async putCourseUsers(courseId: number, updateCourseUserDto: Array<Update...
  method getCourseUsers (line 11406) | getCourseUsers(courseId: number, options?: any): AxiosPromise<Array<Cour...
  method putCourseUser (line 11417) | putCourseUser(courseId: number, githubId: string, courseRolesDto: Course...
  method putCourseUsers (line 11427) | putCourseUsers(courseId: number, updateCourseUserDto: Array<UpdateCourse...
  class CourseUsersApi (line 11439) | class CourseUsersApi extends BaseAPI {
    method getCourseUsers (line 11447) | public getCourseUsers(courseId: number, options?: AxiosRequestConfig) {
    method putCourseUser (line 11460) | public putCourseUser(courseId: number, githubId: string, courseRolesDt...
    method putCourseUsers (line 11472) | public putCourseUsers(courseId: number, updateCourseUserDto: Array<Upd...
  method copyCourse (line 11746) | async copyCourse(courseId: number, createCourseDto: CreateCourseDto, opt...
  method createCourse (line 11756) | async createCourse(createCourseDto: CreateCourseDto, options?: AxiosRequ...
  method getCourse (line 11766) | async getCourse(courseId: number, options?: AxiosRequestConfig): Promise...
  method getCourses (line 11775) | async getCourses(options?: AxiosRequestConfig): Promise<(axios?: AxiosIn...
  method leaveCourse (line 11786) | async leaveCourse(courseId: number, leaveCourseRequestDto?: LeaveCourseR...
  method rejoinCourse (line 11796) | async rejoinCourse(courseId: number, options?: AxiosRequestConfig): Prom...
  method updateCourse (line 11807) | async updateCourse(courseId: number, updateCourseDto: UpdateCourseDto, o...
  method copyCourse (line 11828) | copyCourse(courseId: number, createCourseDto: CreateCourseDto, options?:...
  method createCourse (line 11837) | createCourse(createCourseDto: CreateCourseDto, options?: any): AxiosProm...
  method getCourse (line 11846) | getCourse(courseId: number, options?: any): AxiosPromise<CourseDto> {
  method getCourses (line 11854) | getCourses(options?: any): AxiosPromise<Array<CourseDto>> {
  method leaveCourse (line 11864) | leaveCourse(courseId: number, leaveCourseRequestDto?: LeaveCourseRequest...
  method rejoinCourse (line 11873) | rejoinCourse(courseId: number, options?: any): AxiosPromise<void> {
  method updateCourse (line 11883) | updateCourse(courseId: number, updateCourseDto: UpdateCourseDto, options...
  class CoursesApi (line 11895) | class CoursesApi extends BaseAPI {
    method copyCourse (line 11904) | public copyCourse(courseId: number, createCourseDto: CreateCourseDto, ...
    method createCourse (line 11915) | public createCourse(createCourseDto: CreateCourseDto, options?: AxiosR...
    method getCourse (line 11926) | public getCourse(courseId: number, options?: AxiosRequestConfig) {
    method getCourses (line 11936) | public getCourses(options?: AxiosRequestConfig) {
    method leaveCourse (line 11948) | public leaveCourse(courseId: number, leaveCourseRequestDto?: LeaveCour...
    method rejoinCourse (line 11959) | public rejoinCourse(courseId: number, options?: AxiosRequestConfig) {
    method updateCourse (line 11971) | public updateCourse(courseId: number, updateCourseDto: UpdateCourseDto...
  method createCourseEvent (line 12119) | async createCourseEvent(courseId: number, createCourseEventDto: CreateCo...
  method deleteCourseEvent (line 12130) | async deleteCourseEvent(courseEventId: number, courseId: any, options?: ...
  method updateCourseEvent (line 12142) | async updateCourseEvent(courseId: number, courseEventId: number, updateC...
  method createCourseEvent (line 12163) | createCourseEvent(courseId: number, createCourseEventDto: CreateCourseEv...
  method deleteCourseEvent (line 12173) | deleteCourseEvent(courseEventId: number, courseId: any, options?: any): ...
  method updateCourseEvent (line 12184) | updateCourseEvent(courseId: number, courseEventId: number, updateCourseE...
  class CoursesEventsApi (line 12196) | class CoursesEventsApi extends BaseAPI {
    method createCourseEvent (line 12205) | public createCourseEvent(courseId: number, createCourseEventDto: Creat...
    method deleteCourseEvent (line 12217) | public deleteCourseEvent(courseEventId: number, courseId: any, options...
    method updateCourseEvent (line 12230) | public updateCourseEvent(courseId: number, courseEventId: number, upda...
  method createInterviewFeedback (line 12616) | async createInterviewFeedback(courseId: number, interviewId: number, typ...
  method distributeInterviewPairs (line 12628) | async distributeInterviewPairs(courseId: number, courseTaskId: number, i...
  method getAvailableStudents (line 12639) | async getAvailableStudents(courseId: number, interviewId: number, option...
  method getInterview (line 12650) | async getInterview(interviewId: number, courseId: number, options?: Axio...
  method getInterviewFeedback (line 12662) | async getInterviewFeedback(courseId: number, interviewId: number, type: ...
  method getInterviewPairs (line 12673) | async getInterviewPairs(interviewId: number, courseId: number, options?:...
  method getInterviews (line 12685) | async getInterviews(courseId: number, disabled?: boolean, types?: Array<...
  method getStageInterviewsCommentToStudent (line 12695) | async getStageInterviewsCommentToStudent(courseId: number, options?: Axi...
  method registerToInterview (line 12706) | async registerToInterview(courseId: number, interviewId: number, options...
  method createInterviewFeedback (line 12729) | createInterviewFeedback(courseId: number, interviewId: number, type: str...
  method distributeInterviewPairs (line 12740) | distributeInterviewPairs(courseId: number, courseTaskId: number, intervi...
  method getAvailableStudents (line 12750) | getAvailableStudents(courseId: number, interviewId: number, options?: an...
  method getInterview (line 12760) | getInterview(interviewId: number, courseId: number, options?: any): Axio...
  method getInterviewFeedback (line 12771) | getInterviewFeedback(courseId: number, interviewId: number, type: string...
  method getInterviewPairs (line 12781) | getInterviewPairs(interviewId: number, courseId: number, options?: any):...
  method getInterviews (line 12792) | getInterviews(courseId: number, disabled?: boolean, types?: Array<string...
  method getStageInterviewsCommentToStudent (line 12801) | getStageInterviewsCommentToStudent(courseId: number, options?: any): Axi...
  method registerToInterview (line 12811) | registerToInterview(courseId: number, interviewId: number, options?: any...
  class CoursesInterviewsApi (line 12823) | class CoursesInterviewsApi extends BaseAPI {
    method createInterviewFeedback (line 12834) | public createInterviewFeedback(courseId: number, interviewId: number, ...
    method distributeInterviewPairs (line 12847) | public distributeInterviewPairs(courseId: number, courseTaskId: number...
    method getAvailableStudents (line 12859) | public getAvailableStudents(courseId: number, interviewId: number, opt...
    method getInterview (line 12871) | public getInterview(interviewId: number, courseId: number, options?: A...
    method getInterviewFeedback (line 12884) | public getInterviewFeedback(courseId: number, interviewId: number, typ...
    method getInterviewPairs (line 12896) | public getInterviewPairs(interviewId: number, courseId: number, option...
    method getInterviews (line 12909) | public getInterviews(courseId: number, disabled?: boolean, types?: Arr...
    method getStageInterviewsCommentToStudent (line 12920) | public getStageInterviewsCommentToStudent(courseId: number, options?: ...
    method registerToInterview (line 12932) | public registerToInterview(courseId: number, interviewId: number, opti...
  method copySchedule (line 13033) | async copySchedule(courseId: number, courseCopyFromDto: CourseCopyFromDt...
  method getSchedule (line 13043) | async getSchedule(courseId: number, options?: AxiosRequestConfig): Promi...
  method copySchedule (line 13064) | copySchedule(courseId: number, courseCopyFromDto: CourseCopyFromDto, opt...
  method getSchedule (line 13073) | getSchedule(courseId: number, options?: any): AxiosPromise<Array<CourseS...
  class CoursesScheduleApi (line 13085) | class CoursesScheduleApi extends BaseAPI {
    method copySchedule (line 13094) | public copySchedule(courseId: number, courseCopyFromDto: CourseCopyFro...
    method getSchedule (line 13105) | public getSchedule(courseId: number, options?: AxiosRequestConfig) {
  method getScheduleICalendar (line 13212) | async getScheduleICalendar(courseId: number, token: string, timezone: st...
  method getScheduleICalendarToken (line 13222) | async getScheduleICalendarToken(courseId: number, options?: AxiosRequest...
  method getScheduleICalendar (line 13244) | getScheduleICalendar(courseId: number, token: string, timezone: string, ...
  method getScheduleICalendarToken (line 13253) | getScheduleICalendarToken(courseId: number, options?: any): AxiosPromise...
  class CoursesScheduleIcalApi (line 13265) | class CoursesScheduleIcalApi extends BaseAPI {
    method getScheduleICalendar (line 13275) | public getScheduleICalendar(courseId: number, token: string, timezone:...
    method getScheduleICalendarToken (line 13286) | public getScheduleICalendarToken(courseId: number, options?: AxiosRequ...
  method createTaskSolution (line 13359) | async createTaskSolution(courseId: number, courseTaskId: number, saveTas...
  method createTaskSolution (line 13381) | createTaskSolution(courseId: number, courseTaskId: number, saveTaskSolut...
  class CoursesTaskSolutionsApi (line 13393) | class CoursesTaskSolutionsApi extends BaseAPI {
    method createTaskSolution (line 13403) | public createTaskSolution(courseId: number, courseTaskId: number, save...
  method createCourseTask (line 13921) | async createCourseTask(courseId: number, createCourseTaskDto: CreateCour...
  method deleteCourseTask (line 13932) | async deleteCourseTask(courseId: number, courseTaskId: number, options?:...
  method getAvailableCrossCheckReviewStats (line 13942) | async getAvailableCrossCheckReviewStats(courseId: number, options?: Axio...
  method getCourseTask (line 13953) | async getCourseTask(courseId: number, courseTaskId: number, options?: Ax...
  method getCourseTasks (line 13965) | async getCourseTasks(courseId: number, status?: 'started' | 'inprogress'...
  method getCourseTasksDetailed (line 13975) | async getCourseTasksDetailed(courseId: number, options?: AxiosRequestCon...
  method getCourseTasksWithStudentSolution (line 13986) | async getCourseTasksWithStudentSolution(courseId: number, status?: 'star...
  method getCrossCheckCsv (line 13997) | async getCrossCheckCsv(courseId: number, courseTaskId: number, options?:...
  method getCrossCheckPairs (line 14015) | async getCrossCheckPairs(courseId: number, pageSize: number, current: nu...
  method getMyCrossCheckFeedbacks (line 14026) | async getMyCrossCheckFeedbacks(courseId: number, courseTaskId: number, o...
  method notifyTasksDeadlines (line 14036) | async notifyTasksDeadlines(checkTasksDeadlineDto: CheckTasksDeadlineDto,...
  method updateCourseTask (line 14048) | async updateCourseTask(courseId: number, courseTaskId: number, updateCou...
  method createCourseTask (line 14069) | createCourseTask(courseId: number, createCourseTaskDto: CreateCourseTask...
  method deleteCourseTask (line 14079) | deleteCourseTask(courseId: number, courseTaskId: number, options?: any):...
  method getAvailableCrossCheckReviewStats (line 14088) | getAvailableCrossCheckReviewStats(courseId: number, options?: any): Axio...
  method getCourseTask (line 14098) | getCourseTask(courseId: number, courseTaskId: number, options?: any): Ax...
  method getCourseTasks (line 14109) | getCourseTasks(courseId: number, status?: 'started' | 'inprogress' | 'fi...
  method getCourseTasksDetailed (line 14118) | getCourseTasksDetailed(courseId: number, options?: any): AxiosPromise<Ar...
  method getCourseTasksWithStudentSolution (line 14128) | getCourseTasksWithStudentSolution(courseId: number, status?: 'started' |...
  method getCrossCheckCsv (line 14138) | getCrossCheckCsv(courseId: number, courseTaskId: number, options?: any):...
  method getCrossCheckPairs (line 14155) | getCrossCheckPairs(courseId: number, pageSize: number, current: number, ...
  method getMyCrossCheckFeedbacks (line 14165) | getMyCrossCheckFeedbacks(courseId: number, courseTaskId: number, options...
  method notifyTasksDeadlines (line 14174) | notifyTasksDeadlines(checkTasksDeadlineDto: CheckTasksDeadlineDto, optio...
  method updateCourseTask (line 14185) | updateCourseTask(courseId: number, courseTaskId: number, updateCourseTas...
  class CoursesTasksApi (line 14197) | class CoursesTasksApi extends BaseAPI {
    method createCourseTask (line 14206) | public createCourseTask(courseId: number, createCourseTaskDto: CreateC...
    method deleteCourseTask (line 14218) | public deleteCourseTask(courseId: number, courseTaskId: number, option...
    method getAvailableCrossCheckReviewStats (line 14229) | public getAvailableCrossCheckReviewStats(courseId: number, options?: A...
    method getCourseTask (line 14241) | public getCourseTask(courseId: number, courseTaskId: number, options?:...
    method getCourseTasks (line 14254) | public getCourseTasks(courseId: number, status?: 'started' | 'inprogre...
    method getCourseTasksDetailed (line 14265) | public getCourseTasksDetailed(courseId: number, options?: AxiosRequest...
    method getCourseTasksWithStudentSolution (line 14277) | public getCourseTasksWithStudentSolution(courseId: number, status?: 's...
    method getCrossCheckCsv (line 14289) | public getCrossCheckCsv(courseId: number, courseTaskId: number, option...
    method getCrossCheckPairs (line 14308) | public getCrossCheckPairs(courseId: number, pageSize: number, current:...
    method getMyCrossCheckFeedbacks (line 14320) | public getMyCrossCheckFeedbacks(courseId: number, courseTaskId: number...
    method notifyTasksDeadlines (line 14331) | public notifyTasksDeadlines(checkTasksDeadlineDto: CheckTasksDeadlineD...
    method updateCourseTask (line 14344) | public updateCourseTask(courseId: number, courseTaskId: number, update...
  method getDevUserLogin (line 14434) | async getDevUserLogin(githubId: string, options?: AxiosRequestConfig): P...
  method getDevUsers (line 14443) | async getDevUsers(options?: AxiosRequestConfig): Promise<(axios?: AxiosI...
  method getDevUserLogin (line 14463) | getDevUserLogin(githubId: string, options?: any): AxiosPromise<void> {
  method getDevUsers (line 14471) | getDevUsers(options?: any): AxiosPromise<Array<DevtoolsUserDto>> {
  class DevtoolsApi (line 14483) | class DevtoolsApi extends BaseAPI {
    method getDevUserLogin (line 14491) | public getDevUserLogin(githubId: string, options?: AxiosRequestConfig) {
    method getDevUsers (line 14501) | public getDevUsers(options?: AxiosRequestConfig) {
  method createDiscipline (line 14700) | async createDiscipline(createDisciplineDto: CreateDisciplineDto, options...
  method deleteDiscipline (line 14710) | async deleteDiscipline(id: number, options?: AxiosRequestConfig): Promis...
  method getDisciplines (line 14719) | async getDisciplines(options?: AxiosRequestConfig): Promise<(axios?: Axi...
  method getDisciplinesByIds (line 14729) | async getDisciplinesByIds(disciplineIdsDto: DisciplineIdsDto, options?: ...
  method updateDiscipline (line 14740) | async updateDiscipline(id: number, updateDisciplineDto: UpdateDiscipline...
  method createDiscipline (line 14760) | createDiscipline(createDisciplineDto: CreateDisciplineDto, options?: any...
  method deleteDiscipline (line 14769) | deleteDiscipline(id: number, options?: any): AxiosPromise<void> {
  method getDisciplines (line 14777) | getDisciplines(options?: any): AxiosPromise<Array<DisciplineDto>> {
  method getDisciplinesByIds (line 14786) | getDisciplinesByIds(disciplineIdsDto: DisciplineIdsDto, options?: any): ...
  method updateDiscipline (line 14796) | updateDiscipline(id: number, updateDisciplineDto: UpdateDisciplineDto, o...
  class DisciplinesApi (line 14808) | class DisciplinesApi extends BaseAPI {
    method createDiscipline (line 14816) | public createDiscipline(createDisciplineDto: CreateDisciplineDto, opti...
    method deleteDiscipline (line 14827) | public deleteDiscipline(id: number, options?: AxiosRequestConfig) {
    method getDisciplines (line 14837) | public getDisciplines(options?: AxiosRequestConfig) {
    method getDisciplinesByIds (line 14848) | public getDisciplinesByIds(disciplineIdsDto: DisciplineIdsDto, options...
    method updateDiscipline (line 14860) | public updateDiscipline(id: number, updateDisciplineDto: UpdateDiscipl...
  method createDiscordServer (line 15090) | async createDiscordServer(createDiscordServerDto: CreateDiscordServerDto...
  method deleteDiscordServer (line 15100) | async deleteDiscordServer(id: number, options?: AxiosRequestConfig): Pro...
  method getDiscordServers (line 15109) | async getDiscordServers(options?: AxiosRequestConfig): Promise<(axios?: ...
  method getInviteLinkByDiscordServerId (line 15120) | async getInviteLinkByDiscordServerId(courseId: number, id: number, optio...
  method getReducedDiscordServers (line 15129) | async getReducedDiscordServers(options?: AxiosRequestConfig): Promise<(a...
  method updateDiscordServer (line 15140) | async updateDiscordServer(id: number, updateDiscordServerDto: UpdateDisc...
  method createDiscordServer (line 15160) | createDiscordServer(createDiscordServerDto: CreateDiscordServerDto, opti...
  method deleteDiscordServer (line 15169) | deleteDiscordServer(id: number, options?: any): AxiosPromise<DiscordServ...
  method getDiscordServers (line 15177) | getDiscordServers(options?: any): AxiosPromise<Array<DiscordServerDto>> {
  method getInviteLinkByDiscordServerId (line 15187) | getInviteLinkByDiscordServerId(courseId: number, id: number, options?: a...
  method getReducedDiscordServers (line 15195) | getReducedDiscordServers(options?: any): AxiosPromise<Array<IdNameDto>> {
  method updateDiscordServer (line 15205) | updateDiscordServer(id: number, updateDiscordServerDto: UpdateDiscordSer...
  class DiscordServersApi (line 15217) | class DiscordServersApi extends BaseAPI {
    method createDiscordServer (line 15225) | public createDiscordServer(createDiscordServerDto: CreateDiscordServer...
    method deleteDiscordServer (line 15236) | public deleteDiscordServer(id: number, options?: AxiosRequestConfig) {
    method getDiscordServers (line 15246) | public getDiscordServers(options?: AxiosRequestConfig) {
    method getInviteLinkByDiscordServerId (line 15258) | public getInviteLinkByDiscordServerId(courseId: number, id: number, op...
    method getReducedDiscordServers (line 15268) | public getReducedDiscordServers(options?: AxiosRequestConfig) {
    method updateDiscordServer (line 15280) | public updateDiscordServer(id: number, updateDiscordServerDto: UpdateD...
  method createEvent (line 15444) | async createEvent(createEventDto: CreateEventDto, options?: AxiosRequest...
  method deleteEvent (line 15454) | async deleteEvent(id: number, options?: AxiosRequestConfig): Promise<(ax...
  method getEvents (line 15463) | async getEvents(options?: AxiosRequestConfig): Promise<(axios?: AxiosIns...
  method updateEvent (line 15474) | async updateEvent(id: number, updateEventDto: UpdateEventDto, options?: ...
  method createEvent (line 15494) | createEvent(createEventDto: CreateEventDto, options?: any): AxiosPromise...
  method deleteEvent (line 15503) | deleteEvent(id: number, options?: any): AxiosPromise<void> {
  method getEvents (line 15511) | getEvents(options?: any): AxiosPromise<Array<EventDto>> {
  method updateEvent (line 15521) | updateEvent(id: number, updateEventDto: UpdateEventDto, options?: any): ...
  class EventsApi (line 15533) | class EventsApi extends BaseAPI {
    method createEvent (line 15541) | public createEvent(createEventDto: CreateEventDto, options?: AxiosRequ...
    method deleteEvent (line 15552) | public deleteEvent(id: number, options?: AxiosRequestConfig) {
    method getEvents (line 15562) | public getEvents(options?: AxiosRequestConfig) {
    method updateEvent (line 15574) | public updateEvent(id: number, updateEventDto: UpdateEventDto, options...
  method createGratitude (line 15843) | async createGratitude(createGratitudeDto: CreateGratitudeDto, options?: ...
  method getBadges (line 15853) | async getBadges(courseId: number, options?: AxiosRequestConfig): Promise...
  method getHeroesCountries (line 15862) | async getHeroesCountries(options?: AxiosRequestConfig): Promise<(axios?:...
  method getHeroesRadar (line 15878) | async getHeroesRadar(current: number, pageSize: number, courseId?: numbe...
  method getHeroesRadarCsv (line 15894) | async getHeroesRadarCsv(current: number, pageSize: number, courseId?: nu...
  method createGratitude (line 15914) | createGratitude(createGratitudeDto: CreateGratitudeDto, options?: any): ...
  method getBadges (line 15923) | getBadges(courseId: number, options?: any): AxiosPromise<Array<BadgeDto>> {
  method getHeroesCountries (line 15931) | getHeroesCountries(options?: any): AxiosPromise<Array<CountryDto>> {
  method getHeroesRadar (line 15946) | getHeroesRadar(current: number, pageSize: number, courseId?: number, not...
  method getHeroesRadarCsv (line 15961) | getHeroesRadarCsv(current: number, pageSize: number, courseId?: number, ...
  class GratitudesApi (line 15973) | class GratitudesApi extends BaseAPI {
    method createGratitude (line 15981) | public createGratitude(createGratitudeDto: CreateGratitudeDto, options...
    method getBadges (line 15992) | public getBadges(courseId: number, options?: AxiosRequestConfig) {
    method getHeroesCountries (line 16002) | public getHeroesCountries(options?: AxiosRequestConfig) {
    method getHeroesRadar (line 16019) | public getHeroesRadar(current: number, pageSize: number, courseId?: nu...
    method getHeroesRadarCsv (line 16036) | public getHeroesRadarCsv(current: number, pageSize: number, courseId?:...
  method assignReviewer (line 16176) | async assignReviewer(courseId: number, mentorReviewAssignDto: MentorRevi...
  method getMentorReviews (line 16193) | async getMentorReviews(current: string, pageSize: string, courseId: numb...
  method assignReviewer (line 16214) | assignReviewer(courseId: number, mentorReviewAssignDto: MentorReviewAssi...
  method getMentorReviews (line 16230) | getMentorReviews(current: string, pageSize: string, courseId: number, ta...
  class MentorReviewsApi (line 16242) | class MentorReviewsApi extends BaseAPI {
    method assignReviewer (line 16251) | public assignReviewer(courseId: number, mentorReviewAssignDto: MentorR...
    method getMentorReviews (line 16269) | public getMentorReviews(current: string, pageSize: string, courseId: n...
  method getCourseStudentsCount (line 16479) | async getCourseStudentsCount(mentorId: number, courseId: number, options...
  method getMentorDashboardData (line 16490) | async getMentorDashboardData(mentorId: number, courseId: number, options...
  method getMentorOptions (line 16501) | async getMentorOptions(mentorId: number, courseId: number, options?: Axi...
  method getMentorStudents (line 16511) | async getMentorStudents(mentorId: number, options?: AxiosRequestConfig):...
  method getRandomTask (line 16522) | async getRandomTask(mentorId: number, courseId: number, options?: AxiosR...
  method getCourseStudentsCount (line 16543) | getCourseStudentsCount(mentorId: number, courseId: number, options?: any...
  method getMentorDashboardData (line 16553) | getMentorDashboardData(mentorId: number, courseId: number, options?: any...
  method getMentorOptions (line 16563) | getMentorOptions(mentorId: number, courseId: number, options?: any): Axi...
  method getMentorStudents (line 16572) | getMentorStudents(mentorId: number, options?: any): AxiosPromise<Array<M...
  method getRandomTask (line 16582) | getRandomTask(mentorId: number, courseId: number, options?: any): AxiosP...
  class MentorsApi (line 16594) | class MentorsApi extends BaseAPI {
    method getCourseStudentsCount (line 16603) | public getCourseStudentsCount(mentorId: number, courseId: number, opti...
    method getMentorDashboardData (line 16615) | public getMentorDashboardData(mentorId: number, courseId: number, opti...
    method getMentorOptions (line 16627) | public getMentorOptions(mentorId: number, courseId: number, options?: ...
    method getMentorStudents (line 16638) | public getMentorStudents(mentorId: number, options?: AxiosRequestConfi...
    method getRandomTask (line 16650) | public getRandomTask(mentorId: number, courseId: number, options?: Axi...
  method getTopMentors (line 16712) | async getTopMentors(allTime?: boolean, options?: AxiosRequestConfig): Pr...
  method getTopMentors (line 16732) | getTopMentors(allTime?: boolean, options?: any): AxiosPromise<Array<TopM...
  class MentorsHallOfFameApi (line 16744) | class MentorsHallOfFameApi extends BaseAPI {
    method getTopMentors (line 16752) | public getTopMentors(allTime?: boolean, options?: AxiosRequestConfig) {
  method createNotification (line 16912) | async createNotification(updateNotificationDto: UpdateNotificationDto, o...
  method deleteNotification (line 16922) | async deleteNotification(id: string, options?: AxiosRequestConfig): Prom...
  method getNotifications (line 16931) | async getNotifications(options?: AxiosRequestConfig): Promise<(axios?: A...
  method updateNotification (line 16941) | async updateNotification(updateNotificationDto: UpdateNotificationDto, o...
  method createNotification (line 16961) | createNotification(updateNotificationDto: UpdateNotificationDto, options...
  method deleteNotification (line 16970) | deleteNotification(id: string, options?: any): AxiosPromise<void> {
  method getNotifications (line 16978) | getNotifications(options?: any): AxiosPromise<Array<NotificationDto>> {
  method updateNotification (line 16987) | updateNotification(updateNotificationDto: UpdateNotificationDto, options...
  class NotificationsApi (line 16999) | class NotificationsApi extends BaseAPI {
    method createNotification (line 17007) | public createNotification(updateNotificationDto: UpdateNotificationDto...
    method deleteNotification (line 17018) | public deleteNotification(id: string, options?: AxiosRequestConfig) {
    method getNotifications (line 17028) | public getNotifications(options?: AxiosRequestConfig) {
    method updateNotification (line 17039) | public updateNotification(updateNotificationDto: UpdateNotificationDto...
  method createConsent (line 17345) | async createConsent(options?: AxiosRequestConfig): Promise<(axios?: Axio...
  method deleteConsent (line 17354) | async deleteConsent(options?: AxiosRequestConfig): Promise<(axios?: Axio...
  method getApplicants (line 17363) | async getApplicants(options?: AxiosRequestConfig): Promise<(axios?: Axio...
  method getConsent (line 17372) | async getConsent(options?: AxiosRequestConfig): Promise<(axios?: AxiosIn...
  method getPublicResume (line 17382) | async getPublicResume(uuid: string, options?: AxiosRequestConfig): Promi...
  method getResume (line 17392) | async getResume(githubId: string, options?: AxiosRequestConfig): Promise...
  method prolong (line 17401) | async prolong(options?: AxiosRequestConfig): Promise<(axios?: AxiosInsta...
  method saveResume (line 17412) | async saveResume(githubId: string, formDataDto: FormDataDto, options?: A...
  method setVisibility (line 17421) | async setVisibility(options?: AxiosRequestConfig): Promise<(axios?: Axio...
  method createConsent (line 17440) | createConsent(options?: any): AxiosPromise<GiveConsentDto> {
  method deleteConsent (line 17448) | deleteConsent(options?: any): AxiosPromise<ConsentDto> {
  method getApplicants (line 17456) | getApplicants(options?: any): AxiosPromise<Array<ApplicantResumeDto>> {
  method getConsent (line 17464) | getConsent(options?: any): AxiosPromise<ConsentDto> {
  method getPublicResume (line 17473) | getPublicResume(uuid: string, options?: any): AxiosPromise<ResumeDto> {
  method getResume (line 17482) | getResume(githubId: string, options?: any): AxiosPromise<ResumeDto> {
  method prolong (line 17490) | prolong(options?: any): AxiosPromise<StatusDto> {
  method saveResume (line 17500) | saveResume(githubId: string, formDataDto: FormDataDto, options?: any): A...
  method setVisibility (line 17508) | setVisibility(options?: any): AxiosPromise<VisibilityDto> {
  class OpportunitiesApi (line 17520) | class OpportunitiesApi extends BaseAPI {
    method createConsent (line 17527) | public createConsent(options?: AxiosRequestConfig) {
    method deleteConsent (line 17537) | public deleteConsent(options?: AxiosRequestConfig) {
    method getApplicants (line 17547) | public getApplicants(options?: AxiosRequestConfig) {
    method getConsent (line 17557) | public getConsent(options?: AxiosRequestConfig) {
    method getPublicResume (line 17568) | public getPublicResume(uuid: string, options?: AxiosRequestConfig) {
    method getResume (line 17579) | public getResume(githubId: string, options?: AxiosRequestConfig) {
    method prolong (line 17589) | public prolong(options?: AxiosRequestConfig) {
    method saveResume (line 17601) | public saveResume(githubId: string, formDataDto: FormDataDto, options?...
    method setVisibility (line 17611) | public setVisibility(options?: AxiosRequestConfig) {
  method getEndorsement (line 17907) | async getEndorsement(username: string, options?: AxiosRequestConfig): Pr...
  method getEndorsementData (line 17917) | async getEndorsementData(username: string, options?: AxiosRequestConfig)...
  method getPersonalProfile (line 17927) | async getPersonalProfile(username: string, options?: AxiosRequestConfig)...
  method getProfile (line 17937) | async getProfile(username: string, options?: AxiosRequestConfig): Promis...
  method getUserCourses (line 17947) | async getUserCourses(username: string, options?: AxiosRequestConfig): Pr...
  method obfuscateProfile (line 17957) | async obfuscateProfile(username: string, options?: AxiosRequestConfig): ...
  method updateProfileInfoFlat (line 17967) | async updateProfileInfoFlat(updateProfileInfoDto: UpdateProfileInfoDto, ...
  method updateUser (line 17977) | async updateUser(updateUserDto: UpdateUserDto, options?: AxiosRequestCon...
  method getEndorsement (line 17997) | getEndorsement(username: string, options?: any): AxiosPromise<Endorsemen...
  method getEndorsementData (line 18006) | getEndorsementData(username: string, options?: any): AxiosPromise<Endors...
  method getPersonalProfile (line 18015) | getPersonalProfile(username: string, options?: any): AxiosPromise<Person...
  method getProfile (line 18024) | getProfile(username: string, options?: any): AxiosPromise<ProfileDto> {
  method getUserCourses (line 18033) | getUserCourses(username: string, options?: any): AxiosPromise<Array<Prof...
  method obfuscateProfile (line 18042) | obfuscateProfile(username: string, options?: any): AxiosPromise<void> {
  method updateProfileInfoFlat (line 18051) | updateProfileInfoFlat(updateProfileInfoDto: UpdateProfileInfoDto, option...
  method updateUser (line 18060) | updateUser(updateUserDto: UpdateUserDto, options?: any): AxiosPromise<vo...
  class ProfileApi (line 18072) | class ProfileApi extends BaseAPI {
    method getEndorsement (line 18080) | public getEndorsement(username: string, options?: AxiosRequestConfig) {
    method getEndorsementData (line 18091) | public getEndorsementData(username: string, options?: AxiosRequestConf...
    method getPersonalProfile (line 18102) | public getPersonalProfile(username: string, options?: AxiosRequestConf...
    method getProfile (line 18113) | public getProfile(username: string, options?: AxiosRequestConfig) {
    method getUserCourses (line 18124) | public getUserCourses(username: string, options?: AxiosRequestConfig) {
    method obfuscateProfile (line 18135) | public obfuscateProfile(username: string, options?: AxiosRequestConfig) {
    method updateProfileInfoFlat (line 18146) | public updateProfileInfoFlat(updateProfileInfoDto: UpdateProfileInfoDt...
    method updateUser (line 18157) | public updateUser(updateUserDto: UpdateUserDto, options?: AxiosRequest...
  method createPrompt (line 18321) | async createPrompt(createPromptDto: CreatePromptDto, options?: AxiosRequ...
  method deletePrompt (line 18331) | async deletePrompt(id: number, options?: AxiosRequestConfig): Promise<(a...
  method getPrompts (line 18340) | async getPrompts(options?: AxiosRequestConfig): Promise<(axios?: AxiosIn...
  method updatePrompt (line 18351) | async updatePrompt(id: number, updatePromptDto: UpdatePromptDto, options...
  method createPrompt (line 18371) | createPrompt(createPromptDto: CreatePromptDto, options?: any): AxiosProm...
  method deletePrompt (line 18380) | deletePrompt(id: number, options?: any): AxiosPromise<void> {
  method getPrompts (line 18388) | getPrompts(options?: any): AxiosPromise<Array<PromptDto>> {
  method updatePrompt (line 18398) | updatePrompt(id: number, updatePromptDto: UpdatePromptDto, options?: any...
  class PromptsApi (line 18410) | class PromptsApi extends BaseAPI {
    method createPrompt (line 18418) | public createPrompt(createPromptDto: CreatePromptDto, options?: AxiosR...
    method deletePrompt (line 18429) | public deletePrompt(id: number, options?: AxiosRequestConfig) {
    method getPrompts (line 18439) | public getPrompts(options?: AxiosRequestConfig) {
    method updatePrompt (line 18451) | public updatePrompt(id: number, updatePromptDto: UpdatePromptDto, opti...
  method approveMentor (line 18695) | async approveMentor(githubId: string, approveMentorDto: ApproveMentorDto...
  method cancelMentorRegistry (line 18705) | async cancelMentorRegistry(githubId: string, options?: AxiosRequestConfi...
  method commentMentorRegistry (line 18716) | async commentMentorRegistry(githubId: string, commentMentorRegistryDto: ...
  method getMentorRegistries (line 18733) | async getMentorRegistries(status?: 'new' | 'all', pageSize?: number, cur...
  method inviteMentors (line 18743) | async inviteMentors(inviteMentorsDto: InviteMentorsDto, options?: AxiosR...
  method approveMentor (line 18764) | approveMentor(githubId: string, approveMentorDto: ApproveMentorDto, opti...
  method cancelMentorRegistry (line 18773) | cancelMentorRegistry(githubId: string, options?: any): AxiosPromise<void> {
  method commentMentorRegistry (line 18783) | commentMentorRegistry(githubId: string, commentMentorRegistryDto: Commen...
  method getMentorRegistries (line 18799) | getMentorRegistries(status?: 'new' | 'all', pageSize?: number, currentPa...
  method inviteMentors (line 18808) | inviteMentors(inviteMentorsDto: InviteMentorsDto, options?: any): AxiosP...
  class RegistryApi (line 18820) | class RegistryApi extends BaseAPI {
    method approveMentor (line 18829) | public approveMentor(githubId: string, approveMentorDto: ApproveMentor...
    method cancelMentorRegistry (line 18840) | public cancelMentorRegistry(githubId: string, options?: AxiosRequestCo...
    method commentMentorRegistry (line 18852) | public commentMentorRegistry(githubId: string, commentMentorRegistryDt...
    method getMentorRegistries (line 18870) | public getMentorRegistries(status?: 'new' | 'all', pageSize?: number, ...
    method inviteMentors (line 18881) | public inviteMentors(inviteMentorsDto: InviteMentorsDto, options?: Axi...
  method notifyScheduleChanges (line 18944) | async notifyScheduleChanges(checkScheduleChangesDto: CheckScheduleChange...
  method notifyScheduleChanges (line 18964) | notifyScheduleChanges(checkScheduleChangesDto: CheckScheduleChangesDto, ...
  class ScheduleApi (line 18976) | class ScheduleApi extends BaseAPI {
    method notifyScheduleChanges (line 18984) | public notifyScheduleChanges(checkScheduleChangesDto: CheckScheduleCha...
  method getSession (line 19040) | async getSession(options?: AxiosRequestConfig): Promise<(axios?: AxiosIn...
  method getSession (line 19059) | getSession(options?: any): AxiosPromise<AuthUserDto> {
  class SessionApi (line 19071) | class SessionApi extends BaseAPI {
    method getSession (line 19078) | public getSession(options?: AxiosRequestConfig) {
  method expelStudents (line 19284) | async expelStudents(courseId: number, expelStatusDto: ExpelStatusDto, op...
  method getStudent (line 19294) | async getStudent(studentId: number, options?: AxiosRequestConfig): Promi...
  method getStudentSummary (line 19305) | async getStudentSummary(courseId: number, githubId: string, options?: Ax...
  method getUserStudents (line 19321) | async getUserStudents(current: string, pageSize: string, student?: strin...
  method expelStudents (line 19342) | expelStudents(courseId: number, expelStatusDto: ExpelStatusDto, options?...
  method getStudent (line 19351) | getStudent(studentId: number, options?: any): AxiosPromise<StudentDto> {
  method getStudentSummary (line 19361) | getStudentSummary(courseId: number, githubId: string, options?: any): Ax...
  method getUserStudents (line 19376) | getUserStudents(current: string, pageSize: string, student?: string, cou...
  class StudentsApi (line 19388) | class StudentsApi extends BaseAPI {
    method expelStudents (line 19397) | public expelStudents(courseId: number, expelStatusDto: ExpelStatusDto,...
    method getStudent (line 19408) | public getStudent(studentId: number, options?: AxiosRequestConfig) {
    method getStudentSummary (line 19420) | public getStudentSummary(courseId: number, githubId: string, options?:...
    method getUserStudents (line 19437) | public getUserStudents(current: string, pageSize: string, student?: st...
  method createStudentFeedback (line 19585) | async createStudentFeedback(studentId: number, createStudentFeedbackDto:...
  method getStudentFeedback (line 19596) | async getStudentFeedback(studentId: number, id: number, options?: AxiosR...
  method updateStudentFeedback (line 19608) | async updateStudentFeedback(studentId: number, id: number, updateStudent...
  method createStudentFeedback (line 19629) | createStudentFeedback(studentId: number, createStudentFeedbackDto: Creat...
  method getStudentFeedback (line 19639) | getStudentFeedback(studentId: number, id: number, options?: any): AxiosP...
  method updateStudentFeedback (line 19650) | updateStudentFeedback(studentId: number, id: number, updateStudentFeedba...
  class StudentsFeedbacksApi (line 19662) | class StudentsFeedbacksApi extends BaseAPI {
    method createStudentFeedback (line 19671) | public createStudentFeedback(studentId: number, createStudentFeedbackD...
    method getStudentFeedback (line 19683) | public getStudentFeedback(studentId: number, id: number, options?: Axi...
    method updateStudentFeedback (line 19696) | public updateStudentFeedback(studentId: number, id: number, updateStud...
  method getScore (line 19858) | async getScore(activeOnly: string, orderBy: 'rank' | 'totalScore' | 'cro...
  method getStudentScore (line 19869) | async getStudentScore(courseId: number, githubId: string, options?: Axio...
  method getScore (line 19898) | getScore(activeOnly: string, orderBy: 'rank' | 'totalScore' | 'crossChec...
  method getStudentScore (line 19908) | getStudentScore(courseId: number, githubId: string, options?: any): Axio...
  class StudentsScoreApi (line 19920) | class StudentsScoreApi extends BaseAPI {
    method getScore (line 19937) | public getScore(activeOnly: string, orderBy: 'rank' | 'totalScore' | '...
    method getStudentScore (line 19949) | public getStudentScore(courseId: number, githubId: string, options?: A...
  method createTask (line 20113) | async createTask(createTaskDto: CreateTaskDto, options?: AxiosRequestCon...
  method deleteTask (line 20123) | async deleteTask(id: number, options?: AxiosRequestConfig): Promise<(axi...
  method getTasks (line 20132) | async getTasks(options?: AxiosRequestConfig): Promise<(axios?: AxiosInst...
  method updateTask (line 20143) | async updateTask(id: number, updateTaskDto: UpdateTaskDto, options?: Axi...
  method createTask (line 20163) | createTask(createTaskDto: CreateTaskDto, options?: any): AxiosPromise<Ta...
  method deleteTask (line 20172) | deleteTask(id: number, options?: any): AxiosPromise<void> {
  method getTasks (line 20180) | getTasks(options?: any): AxiosPromise<Array<TaskDto>> {
  method updateTask (line 20190) | updateTask(id: number, updateTaskDto: UpdateTaskDto, options?: any): Axi...
  class TasksApi (line 20202) | class TasksApi extends BaseAPI {
    method createTask (line 20210) | public createTask(createTaskDto: CreateTaskDto, options?: AxiosRequest...
    method deleteTask (line 20221) | public deleteTask(id: number, options?: AxiosRequestConfig) {
    method getTasks (line 20231) | public getTasks(options?: AxiosRequestConfig) {
    method updateTask (line 20243) | public updateTask(id: number, updateTaskDto: UpdateTaskDto, options?: ...
  method createTaskCriteria (line 20383) | async createTaskCriteria(taskId: number, taskCriteriaDto: TaskCriteriaDt...
  method getTaskCriteria (line 20393) | async getTaskCriteria(taskId: number, options?: AxiosRequestConfig): Pro...
  method updateTaskCriteria (line 20404) | async updateTaskCriteria(taskId: number, taskCriteriaDto: TaskCriteriaDt...
  method createTaskCriteria (line 20425) | createTaskCriteria(taskId: number, taskCriteriaDto: TaskCriteriaDto, opt...
  method getTaskCriteria (line 20434) | getTaskCriteria(taskId: number, options?: any): AxiosPromise<TaskCriteri...
  method updateTaskCriteria (line 20444) | updateTaskCriteria(taskId: number, taskCriteriaDto: TaskCriteriaDto, opt...
  class TasksCriteriaApi (line 20456) | class TasksCriteriaApi extends BaseAPI {
    method createTaskCriteria (line 20465) | public createTaskCriteria(taskId: number, taskCriteriaDto: TaskCriteri...
    method getTaskCriteria (line 20476) | public getTaskCriteria(taskId: number, options?: AxiosRequestConfig) {
    method updateTaskCriteria (line 20488) | public updateTaskCriteria(taskId: number, taskCriteriaDto: TaskCriteri...
  method changeTeamPassword (line 20836) | async changeTeamPassword(courseId: number, distributionId: number, id: n...
  method createTeam (line 20848) | async createTeam(courseId: number, distributionId: number, createTeamDto...
  method getTeamPassword (line 20860) | async getTeamPassword(courseId: number, distributionId: number, id: numb...
  method getTeams (line 20874) | async getTeams(courseId: number, distributionId: number, pageSize: numbe...
  method joinTeam (line 20887) | async joinTeam(courseId: number, distributionId: number, id: number, joi...
  method leaveTeam (line 20899) | async leaveTeam(courseId: number, distributionId: number, id: number, op...
  method updateTeam (line 20912) | async updateTeam(courseId: number, distributionId: number, id: number, u...
  method changeTeamPassword (line 20934) | changeTeamPassword(courseId: number, distributionId: number, id: number,...
  method createTeam (line 20945) | createTeam(courseId: number, distributionId: number, createTeamDto: Crea...
  method getTeamPassword (line 20956) | getTeamPassword(courseId: number, distributionId: number, id: number, op...
  method getTeams (line 20969) | getTeams(courseId: number, distributionId: number, pageSize: number, cur...
  method joinTeam (line 20981) | joinTeam(courseId: number, distributionId: number, id: number, joinTeamD...
  method leaveTeam (line 20992) | leaveTeam(courseId: number, distributionId: number, id: number, options?...
  method updateTeam (line 21004) | updateTeam(courseId: number, distributionId: number, id: number, updateT...
  class TeamApi (line 21016) | class TeamApi extends BaseAPI {
    method changeTeamPassword (line 21026) | public changeTeamPassword(courseId: number, distributionId: number, id...
    method createTeam (line 21039) | public createTeam(courseId: number, distributionId: number, createTeam...
    method getTeamPassword (line 21052) | public getTeamPassword(courseId: number, distributionId: number, id: n...
    method getTeams (line 21067) | public getTeams(courseId: number, distributionId: number, pageSize: nu...
    method joinTeam (line 21081) | public joinTeam(courseId: number, distributionId: number, id: number, ...
    method leaveTeam (line 21094) | public leaveTeam(courseId: number, distributionId: number, id: number,...
    method updateTeam (line 21108) | public updateTeam(courseId: number, distributionId: number, id: number...
  method createTeamDistribution (line 21577) | async createTeamDistribution(courseId: number, createTeamDistributionDto...
  method deleteTeamDistribution (line 21588) | async deleteTeamDistribution(courseId: number, id: number, options?: Axi...
  method distributeStudentsToTeam (line 21599) | async distributeStudentsToTeam(courseId: number, id: number, options?: A...
  method getCourseTeamDistributionDetailed (line 21610) | async getCourseTeamDistributionDetailed(courseId: number, id: number, op...
  method getCourseTeamDistributions (line 21620) | async getCourseTeamDistributions(courseId: number, options?: AxiosReques...
  method getStudentsWithoutTeam (line 21634) | async getStudentsWithoutTeam(courseId: number, id: number, pageSize: num...
  method submitScore (line 21646) | async submitScore(courseId: number, id: number, taskId: number, options?...
  method teamDistributionControllerDeleteStudentFromDistribution (line 21658) | async teamDistributionControllerDeleteStudentFromDistribution(studentId:...
  method teamDistributionDeleteRegistry (line 21669) | async teamDistributionDeleteRegistry(courseId: number, id: number, optio...
  method teamDistributionRegistry (line 21680) | async teamDistributionRegistry(courseId: number, id: number, options?: A...
  method updateTeamDistribution (line 21692) | async updateTeamDistribution(courseId: number, id: number, updateTeamDis...
  method createTeamDistribution (line 21713) | createTeamDistribution(courseId: number, createTeamDistributionDto: Crea...
  method deleteTeamDistribution (line 21723) | deleteTeamDistribution(courseId: number, id: number, options?: any): Axi...
  method distributeStudentsToTeam (line 21733) | distributeStudentsToTeam(courseId: number, id: number, options?: any): A...
  method getCourseTeamDistributionDetailed (line 21743) | getCourseTeamDistributionDetailed(courseId: number, id: number, options?...
  method getCourseTeamDistributions (line 21752) | getCourseTeamDistributions(courseId: number, options?: any): AxiosPromis...
  method getStudentsWithoutTeam (line 21765) | getStudentsWithoutTeam(courseId: number, id: number, pageSize: number, c...
  method submitScore (line 21776) | submitScore(courseId: number, id: number, taskId: number, options?: any)...
  method teamDistributionControllerDeleteStudentFromDistribution (line 21787) | teamDistributionControllerDeleteStudentFromDistribution(studentId: numbe...
  method teamDistributionDeleteRegistry (line 21797) | teamDistributionDeleteRegistry(courseId: number, id: number, options?: a...
  method teamDistributionRegistry (line 21807) | teamDistributionRegistry(courseId: number, id: number, options?: any): A...
  method updateTeamDistribution (line 21818) | updateTeamDistribution(courseId: number, id: number, updateTeamDistribut...
  class TeamDistributionApi (line 21830) | class TeamDistributionApi extends BaseAPI {
    method createTeamDistribution (line 21839) | public createTeamDistribution(courseId: number, createTeamDistribution...
    method deleteTeamDistribution (line 21851) | public deleteTeamDistribution(courseId: number, id: number, options?: ...
    method distributeStudentsToTeam (line 21863) | public distributeStudentsToTeam(courseId: number, id: number, options?...
    method getCourseTeamDistributionDetailed (line 21875) | public getCourseTeamDistributionDetailed(courseId: number, id: number,...
    method getCourseTeamDistributions (line 21886) | public getCourseTeamDistributions(courseId: number, options?: AxiosReq...
    method getStudentsWithoutTeam (line 21901) | public getStudentsWithoutTeam(courseId: number, id: number, pageSize: ...
    method submitScore (line 21914) | public submitScore(courseId: number, id: number, taskId: number, optio...
    method teamDistributionControllerDeleteStudentFromDistribution (line 21927) | public teamDistributionControllerDeleteStudentFromDistribution(student...
    method teamDistributionDeleteRegistry (line 21939) | public teamDistributionDeleteRegistry(courseId: number, id: number, op...
    method teamDistributionRegistry (line 21951) | public teamDistributionRegistry(courseId: number, id: number, options?...
    method updateTeamDistribution (line 21964) | public updateTeamDistribution(courseId: number, id: number, updateTeam...
  method createUserGroup (line 22128) | async createUserGroup(createUserGroupDto: CreateUserGroupDto, options?: ...
  method deleteUserGroup (line 22138) | async deleteUserGroup(id: number, options?: AxiosRequestConfig): Promise...
  method getUserGroups (line 22147) | async getUserGroups(options?: AxiosRequestConfig): Promise<(axios?: Axio...
  method updateUserGroup (line 22158) | async updateUserGroup(id: number, updateUserGroupDto: UpdateUserGroupDto...
  method createUserGroup (line 22178) | createUserGroup(createUserGroupDto: CreateUserGroupDto, options?: any): ...
  method deleteUserGroup (line 22187) | deleteUserGroup(id: number, options?: any): AxiosPromise<UserGroupDto> {
  method getUserGroups (line 22195) | getUserGroups(options?: any): AxiosPromise<Array<UserGroupDto>> {
  method updateUserGroup (line 22205) | updateUserGroup(id: number, updateUserGroupDto: UpdateUserGroupDto, opti...
  class UserGroupApi (line 22217) | class UserGroupApi extends BaseAPI {
    method createUserGroup (line 22225) | public createUserGroup(createUserGroupDto: CreateUserGroupDto, options...
    method deleteUserGroup (line 22236) | public deleteUserGroup(id: number, options?: AxiosRequestConfig) {
    method getUserGroups (line 22246) | public getUserGroups(options?: AxiosRequestConfig) {
    method updateUserGroup (line 22258) | public updateUserGroup(id: number, updateUserGroupDto: UpdateUserGroup...
  method searchUsers (line 22322) | async searchUsers(query: string, options?: AxiosRequestConfig): Promise<...
  method searchUsers (line 22342) | searchUsers(query: string, options?: any): AxiosPromise<Array<UserSearch...
  class UsersApi (line 22354) | class UsersApi extends BaseAPI {
    method searchUsers (line 22362) | public searchUsers(query: string, options?: AxiosRequestConfig) {
  method getUserNotificationConnections (line 22616) | async getUserNotificationConnections(options?: AxiosRequestConfig): Prom...
  method getUserNotifications (line 22625) | async getUserNotifications(options?: AxiosRequestConfig): Promise<(axios...
  method sendEmailConfirmationLink (line 22634) | async sendEmailConfirmationLink(options?: AxiosRequestConfig): Promise<(...
  method sendNotification (line 22644) | async sendNotification(sendUserNotificationDto: SendUserNotificationDto,...
  method updateUserNotifications (line 22654) | async updateUserNotifications(updateNotificationUserSettingsDto: Array<U...
  method usersNotificationsControllerCreateUserConnection (line 22664) | async usersNotificationsControllerCreateUserConnection(upsertNotificatio...
  method usersNotificationsControllerFindConnection (line 22674) | async usersNotificationsControllerFindConnection(notificationConnectionE...
  method getUserNotificationConnections (line 22693) | getUserNotificationConnections(options?: any): AxiosPromise<Notification...
  method getUserNotifications (line 22701) | getUserNotifications(options?: any): AxiosPromise<UserNotificationsDto> {
  method sendEmailConfirmationLink (line 22709) | sendEmailConfirmationLink(options?: any): AxiosPromise<void> {
  method sendNotification (line 22718) | sendNotification(sendUserNotificationDto: SendUserNotificationDto, optio...
  method updateUserNotifications (line 22727) | updateUserNotifications(updateNotificationUserSettingsDto: Array<UpdateN...
  method usersNotificationsControllerCreateUserConnection (line 22736) | usersNotificationsControllerCreateUserConnection(upsertNotificationConne...
  method usersNotificationsControllerFindConnection (line 22745) | usersNotificationsControllerFindConnection(notificationConnectionExistsD...
  class UsersNotificationsApi (line 22757) | class UsersNotificationsApi extends BaseAPI {
    method getUserNotificationConnections (line 22764) | public getUserNotificationConnections(options?: AxiosRequestConfig) {
    method getUserNotifications (line 22774) | public getUserNotifications(options?: AxiosRequestConfig) {
    method sendEmailConfirmationLink (line 22784) | public sendEmailConfirmationLink(options?: AxiosRequestConfig) {
    method sendNotification (line 22795) | public sendNotification(sendUserNotificationDto: SendUserNotificationD...
    method updateUserNotifications (line 22806) | public updateUserNotifications(updateNotificationUserSettingsDto: Arra...
    method usersNotificationsControllerCreateUserConnection (line 22817) | public usersNotificationsControllerCreateUserConnection(upsertNotifica...
    method usersNotificationsControllerFindConnection (line 22828) | public usersNotificationsControllerFindConnection(notificationConnecti...

FILE: client/src/api/base.ts
  constant BASE_PATH (line 21) | const BASE_PATH = "/api/v2".replace(/\/+$/, "");
  constant COLLECTION_FORMATS (line 27) | const COLLECTION_FORMATS = {
  type RequestArgs (line 39) | interface RequestArgs {
  class BaseAPI (line 49) | class BaseAPI {
    method constructor (line 52) | constructor(configuration?: Configuration, protected basePath: string ...
  class RequiredError (line 66) | class RequiredError extends Error {
    method constructor (line 68) | constructor(public field: string, msg?: string) {

FILE: client/src/api/common.ts
  constant DUMMY_BASE_URL (line 24) | const DUMMY_BASE_URL = 'https://example.com'

FILE: client/src/api/configuration.ts
  type ConfigurationParameters (line 16) | interface ConfigurationParameters {
  class Configuration (line 26) | class Configuration {
    method constructor (line 77) | constructor(param: ConfigurationParameters = {}) {
    method isJsonMime (line 97) | public isJsonMime(mime: string): boolean {

FILE: client/src/components/Analytics.tsx
  function Analytics (line 5) | function Analytics() {

FILE: client/src/components/Comment.tsx
  type CommentProps (line 4) | type CommentProps = {
  function Comment (line 12) | function Comment({ author, avatar, content, datetime, children }: Commen...

FILE: client/src/components/CountBadge/CountBadge.tsx
  type PresetColors (line 3) | type PresetColors = BadgeProps['status'];
  function getStylesByStatus (line 5) | function getStylesByStatus(status?: PresetColors) {
  function CountBadge (line 22) | function CountBadge(props: BadgeProps) {

FILE: client/src/components/CoursePageLayout.tsx
  type Props (line 7) | type Props = {
  function CoursePageLayout (line 16) | function CoursePageLayout(props: Props) {

FILE: client/src/components/DevTools/DevToolsContainer.tsx
  constant STYLE (line 7) | const STYLE: CSSProperties = {
  constant TABS (line 13) | const TABS = [
  function DevToolsContainer (line 24) | function DevToolsContainer({ children }: { children?: ReactNode }) {

FILE: client/src/components/DevTools/DevToolsCurrentUser.tsx
  function DevToolsCurrentUser (line 10) | function DevToolsCurrentUser() {

FILE: client/src/components/DevTools/DevToolsUsers.tsx
  function DevToolsUsers (line 10) | function DevToolsUsers() {

FILE: client/src/components/Footer/Donation.tsx
  type Props (line 4) | type Props = {
  function Donation (line 8) | function Donation(props: Props) {

FILE: client/src/components/Footer/FooterLayout.tsx
  class FooterLayout (line 12) | class FooterLayout extends React.Component {
    method getYear (line 13) | getYear() {
    method render (line 18) | render() {

FILE: client/src/components/Footer/Menu.tsx
  type LinkInfo (line 5) | type LinkInfo = { icon: React.ReactNode; name: string; link: string; new...
  type MenuProps (line 7) | type MenuProps = {
  class Menu (line 12) | class Menu extends React.Component<MenuProps> {
    method render (line 13) | render() {

FILE: client/src/components/Footer/SocialNetworks.tsx
  type LinkInfo (line 37) | type LinkInfo = { icon: React.ReactNode; name: string; link: string; new...
  class SocialNetworks (line 39) | class SocialNetworks extends React.Component {
    method render (line 40) | render() {

FILE: client/src/components/HeaderMiniBannerCarousel.tsx
  type HeaderMiniBannerCarouselItem (line 7) | type HeaderMiniBannerCarouselItem = {
  type Props (line 13) | type Props = {
  constant DEFAULT_INTERVAL_MS (line 19) | const DEFAULT_INTERVAL_MS = 5000;
  function HeaderMiniBannerCarousel (line 21) | function HeaderMiniBannerCarousel({ items = [], intervalMs = DEFAULT_INT...

FILE: client/src/components/Heroes/HeroesCountBadge.tsx
  type HeroesCountBadgeProps (line 6) | type HeroesCountBadgeProps = {
  function HeroesCountBadge (line 11) | function HeroesCountBadge({ badge: { badgeId, count = 0, comment, date }...

FILE: client/src/components/Heroes/HeroesRadarTab.tsx
  type HeroesRadarFormProps (line 12) | type HeroesRadarFormProps = {
  type GetHeroesProps (line 19) | type GetHeroesProps = HeroesRadarFormProps & Partial<IPaginationInfo>;
  type LayoutType (line 21) | type LayoutType = Parameters<typeof Form>[0]['layout'];
  function HeroesRadarTab (line 37) | function HeroesRadarTab({ setLoading }: { setLoading: (arg: boolean) => ...

FILE: client/src/components/Heroes/HeroesRadarTable.tsx
  type HeroesRadarTableProps (line 13) | interface HeroesRadarTableProps {
  constant BADGE_SIZE (line 19) | const BADGE_SIZE = 48;
  constant BADGE_SUM_HORIZONTAL_MARGIN (line 20) | const BADGE_SUM_HORIZONTAL_MARGIN = 2 * 5;
  constant XS_BREAKPOINT_IN_PX (line 21) | const XS_BREAKPOINT_IN_PX = 575;
  function HeroesRadarTable (line 86) | function HeroesRadarTable({ heroes, onChange, setFormLayout }: HeroesRad...

FILE: client/src/components/MentorOptions.tsx
  type Options (line 5) | type Options = {
  constant STUDENTS_NUMBERS (line 12) | const STUDENTS_NUMBERS = [0, 1, 2, 3, 4, 5, 6];
  function MentorOptions (line 14) | function MentorOptions({

FILE: client/src/components/Profile/AboutCard.tsx
  type Props (line 10) | type Props = {

FILE: client/src/components/Profile/CommonCard.tsx
  type Props (line 7) | type Props = {

FILE: client/src/components/Profile/CommonCardWithSettingsModal.tsx
  type Props (line 5) | type Props = {

FILE: client/src/components/Profile/ContactsCard.tsx
  type ConnectionValue (line 16) | type ConnectionValue = {
  type Connections (line 22) | type Connections = Partial<Record<NotificationChannel, ConnectionValue |...
  type Props (line 24) | type Props = {

FILE: client/src/components/Profile/ContactsCardForm.tsx
  type FormProps (line 7) | type FormProps = {

FILE: client/src/components/Profile/DiscordCard.tsx
  type Props (line 11) | type Props = {

FILE: client/src/components/Profile/EducationCard.tsx
  type UniversityProps (line 10) | type UniversityProps = {
  type Props (line 16) | type Props = {

FILE: client/src/components/Profile/EmailConfirmation.tsx
  type Connection (line 6) | type Connection = {
  type Props (line 12) | type Props = {
  function EmailConfirmation (line 17) | function EmailConfirmation({ connection, sendConfirmationEmail }: Props) {

FILE: client/src/components/Profile/InterviewCard.tsx
  type InterviewCardProps (line 20) | type InterviewCardProps = {
  type CardRenderProps (line 25) | type CardRenderProps<T> = {
  function InterviewCardListItem (line 30) | function InterviewCardListItem({
  function renderCoreJsInterviews (line 68) | function renderCoreJsInterviews({ cardData, setModalData }: CardRenderPr...
  function renderPrescreeningInterviewCard (line 104) | function renderPrescreeningInterviewCard({ cardData, setModalData }: Car...
  type ModalProps (line 133) | type ModalProps =
  function InterviewCard (line 146) | function InterviewCard(props: InterviewCardProps) {

FILE: client/src/components/Profile/InterviewModal.tsx
  type InterviewModalProps (line 16) | type InterviewModalProps = {
  function renderCoreJsModal (line 23) | function renderCoreJsModal({ data, idx }: { data: CoreJsInterviewFeedbac...
  function renderPreScreeningModal (line 60) | function renderPreScreeningModal({ data }: { data: StageInterviewDetaile...
  function InterviewModal (line 81) | function InterviewModal({ isVisible, onHide, coreJs, prescreening }: Int...

FILE: client/src/components/Profile/LanguagesCard.tsx
  type Props (line 8) | type Props = {
  type FormData (line 14) | type FormData = {

FILE: client/src/components/Profile/MainCard.tsx
  type Props (line 15) | type Props = {

FILE: client/src/components/Profile/MentorStatsCard.tsx
  type Props (line 12) | type Props = {
  function MentorStatsCard (line 18) | function MentorStatsCard(props: Props) {

FILE: client/src/components/Profile/MentorStatsModal.tsx
  type Props (line 7) | type Props = {

FILE: client/src/components/Profile/ObfuscateConfirmationModal.tsx
  type Props (line 7) | type Props = {

FILE: client/src/components/Profile/ProfileSettingsModal.tsx
  type Props (line 5) | type Props = {

FILE: client/src/components/Profile/PublicFeedbackCard.tsx
  type Props (line 20) | type Props = {
  type State (line 24) | interface State {
  class PublicFeedbackCard (line 31) | class PublicFeedbackCard extends React.Component<Props, State> {
    method componentDidMount (line 62) | componentDidMount() {
    method render (line 67) | render() {

FILE: client/src/components/Profile/PublicFeedbackModal.tsx
  type Props (line 14) | type Props = {
  class PublicFeedbackModal (line 20) | class PublicFeedbackModal extends React.PureComponent<Props> {
    method render (line 21) | render() {

FILE: client/src/components/Profile/StudentLeaveCourse.tsx
  type SurveyResponses (line 6) | type SurveyResponses = {
  type ReasonOption (line 11) | type ReasonOption = {
  type StudentLeaveCourseProps (line 17) | type StudentLeaveCourseProps = {
  function StudentLeaveCourse (line 27) | function StudentLeaveCourse({

FILE: client/src/components/Profile/StudentStatsCard.tsx
  type Props (line 16) | type Props = {
  type State (line 22) | type State = {
  class StudentStatsCard (line 87) | class StudentStatsCard extends React.Component<Props, State> {
    method componentDidMount (line 148) | componentDidMount() {
    method render (line 155) | render() {

FILE: client/src/components/Profile/StudentStatsModal.tsx
  type Props (line 7) | type Props = {
  class StudentStatsModal (line 13) | class StudentStatsModal extends React.PureComponent<Props> {
    method render (line 14) | render() {

FILE: client/src/components/Profile/ui/DateWidget.tsx
  function DateWidget (line 7) | function DateWidget({ date }: { date?: string }) {

FILE: client/src/components/Profile/ui/ExpandButtonWidget.tsx
  function ExpandButtonWidget (line 4) | function ExpandButtonWidget({ onClick }: { onClick: () => void }) {

FILE: client/src/components/Profile/ui/InterviewerWidget.tsx
  function InterviewerWidget (line 6) | function InterviewerWidget({

FILE: client/src/components/Profile/ui/IsGoodCandidateWidget.tsx
  function IsGoodCandidateWidget (line 5) | function IsGoodCandidateWidget({ isGoodCandidate }: { isGoodCandidate: b...

FILE: client/src/components/Profile/ui/LegacyScreeningFeedback.tsx
  type SKILL_NAME (line 9) | enum SKILL_NAME {
  function LegacyScreeningFeedback (line 18) | function LegacyScreeningFeedback({ feedback }: { feedback: LegacyFeedbac...

FILE: client/src/components/Profile/ui/PrescreeningFeedback.tsx
  constant STYLES (line 10) | const STYLES = {
  constant FEEDBACK_CONFIG (line 15) | const FEEDBACK_CONFIG = [
  function PrescreeningFeedback (line 74) | function PrescreeningFeedback({ feedback }: { feedback: StageInterviewDe...
  function SkillSection (line 106) | function SkillSection({
  function SkillTable (line 126) | function SkillTable({ skills, tooltips }: { skills: InterviewQuestion[];...

FILE: client/src/components/Profile/ui/ScoreWidget.tsx
  function ScoreWidget (line 5) | function ScoreWidget({ score }: { score: number }) {

FILE: client/src/components/RegistrationPageLayout.tsx
  type Props (line 9) | type Props = { loading: boolean; title?: string; children?: ReactNode };
  function RegistrationPageLayout (line 13) | function RegistrationPageLayout(props: Props) {

FILE: client/src/components/SelectLanguages.tsx
  function SelectLanguages (line 6) | function SelectLanguages({ placeholder = 'Select languages', ...props }:...
  function getLanguageName (line 21) | function getLanguageName(language: UpdateUserDtoLanguagesEnum) {
  function languagesSorter (line 26) | function languagesSorter(a: UpdateUserDtoLanguagesEnum, b: UpdateUserDto...

FILE: client/src/components/SettingsItem.tsx
  type SettingsItemProps (line 7) | type SettingsItemProps = PropsWithChildren & {

FILE: client/src/components/SlothImage.tsx
  type SlothNames (line 64) | type SlothNames = (typeof slothNames)[number];
  type Props (line 66) | interface Props extends ImageProps {
  function SlothImage (line 73) | function SlothImage({ name, imgExtension = 'svg', ...props }: Props) {

FILE: client/src/components/Student/AssignStudentModal.tsx
  type Props (line 9) | type Props = {
  function AssignStudentModal (line 16) | function AssignStudentModal(props: Props) {

FILE: client/src/components/Student/DashboardDetails.tsx
  type Props (line 16) | type Props = {
  function DashboardDetails (line 31) | function DashboardDetails(props: Props) {

FILE: client/src/components/StudentDiscord.tsx
  type Props (line 5) | type Props = {
  function StudentDiscord (line 10) | function StudentDiscord({ discord, textPrefix }: Props) {

FILE: client/src/components/TabsWithCounter/renderers.tsx
  type LabelItem (line 5) | type LabelItem = {
  type TabItem (line 11) | type TabItem = {

FILE: client/src/components/Warning/index.tsx
  type Props (line 8) | type Props = {
  function Warning (line 15) | function Warning(props: Props) {

FILE: client/src/components/WelcomeCard.tsx
  function WelcomeCard (line 6) | function WelcomeCard() {

FILE: client/src/components/__tests__/CopyToClipboardButton.test.tsx
  constant TEST_VALUE (line 15) | const TEST_VALUE = 'test-value';

FILE: client/src/components/__tests__/GithubUserLink.test.tsx
  constant TEST_VALUE (line 15) | const TEST_VALUE = 'test-value';
  constant TEST_FULL_NAME (line 16) | const TEST_FULL_NAME = 'test-full-name';

FILE: client/src/components/useLoading.tsx
  type CatchHandler (line 4) | type CatchHandler = (e?: unknown) => void;
  function useLoading (line 6) | function useLoading(

FILE: client/src/components/withGoogleMaps.tsx
  function withGoogleMaps (line 7) | function withGoogleMaps<T = object>(WrappedComponent: React.ComponentTyp...

FILE: client/src/components/withSession.tsx
  type CourseInfo (line 3) | interface CourseInfo {
  type Session (line 10) | interface Session {

FILE: client/src/configs/cdn.ts
  constant CDN_AVATARS_URL (line 1) | const CDN_AVATARS_URL = 'https://cdn.rs.school/avatars';

FILE: client/src/configs/course-icons.ts
  constant DEFAULT_COURSE_ICONS (line 1) | const DEFAULT_COURSE_ICONS: Record<string, { active: string; archived: s...

FILE: client/src/configs/registry.ts
  constant TYPES (line 4) | const TYPES = {
  type Props (line 9) | type Props = {

FILE: client/src/configs/timezones.ts
  constant TIMEZONES (line 1) | const TIMEZONES = [
  constant ALL_TIMEZONES (line 118) | const ALL_TIMEZONES = ['UTC', ...europeTimezones, ...asiaTimezones, ...a...
  constant DEFAULT_TIMEZONE (line 120) | const DEFAULT_TIMEZONE = 'Europe/Minsk';

FILE: client/src/data/course-leave-reasons.ts
  type CourseLeaveReason (line 14) | type CourseLeaveReason = (typeof CourseLeaveReason)[keyof typeof CourseL...

FILE: client/src/data/english.ts
  constant ENGLISH_LEVELS (line 1) | const ENGLISH_LEVELS = ['A0', 'A1', 'A1+', 'A2', 'A2+', 'B1', 'B1+', 'B2...

FILE: client/src/data/eventTypes.ts
  constant EVENT_TYPES (line 3) | const EVENT_TYPES: { id: CourseEventDtoTypeEnum; name: string }[] = [
  constant EVENT_TYPES_MAP (line 17) | const EVENT_TYPES_MAP = EVENT_TYPES.reduce(

FILE: client/src/data/index.ts
  constant TASK_EVENT_TYPES_MAP (line 4) | const TASK_EVENT_TYPES_MAP = {

FILE: client/src/data/interviews/technical-screening.tsx
  function TimeForStep (line 6) | function TimeForStep({ minutes }: { minutes: string }) {
  type FeedbackStepId (line 18) | enum FeedbackStepId {
  type Step (line 26) | type Step = {
  type FeedbackStep (line 36) | type FeedbackStep = Step & InterviewFeedbackStepData;
  type Feedback (line 38) | type Feedback = {
  type Decision (line 55) | enum Decision {
  type StepFormItem (line 64) | type StepFormItem = RadioItem | TextItem | InputItem | CheckboxItem | Ra...
  type Field (line 66) | interface Field {
  type RadioItem (line 72) | interface RadioItem extends Field {
  type RadioButtonItem (line 77) | interface RadioButtonItem extends Field {
  type InputItem (line 83) | interface InputItem extends Field {
  type TextItem (line 93) | interface TextItem extends Field {
  type CheckboxItem (line 99) | interface CheckboxItem extends Field {
  type QuestionItem (line 104) | interface QuestionItem {
  constant SKILLS_LEVELS (line 123) | const SKILLS_LEVELS = [
  constant CODING_LEVELS (line 131) | const CODING_LEVELS = [
  type CheckboxOption (line 139) | type CheckboxOption = {
  type RadioOption (line 144) | type RadioOption = {

FILE: client/src/data/interviews/templateValidator.ts
  class TemplateValidationError (line 3) | class TemplateValidationError extends Error {
    method constructor (line 4) | constructor(message: string) {
  function validateInterviewTemplate (line 10) | function validateInterviewTemplate(template: InterviewTemplate) {
  function validateQuestionCategory (line 31) | function validateQuestionCategory(category: QuestionCategory) {

FILE: client/src/data/interviews/types.ts
  type InputType (line 1) | enum InputType {
  type Question (line 10) | type Question = {
  type QuestionCategory (line 16) | type QuestionCategory = {
  type InterviewTemplate (line 23) | type InterviewTemplate = {

FILE: client/src/data/skills.ts
  constant SKILLS (line 1) | const SKILLS = [

FILE: client/src/data/taskTypes.ts
  constant TASK_TYPES (line 3) | const TASK_TYPES: { id: TaskDtoTypeEnum; name: string }[] = [
  constant TASK_TYPES_MAP (line 19) | const TASK_TYPES_MAP = TASK_TYPES.reduce(

FILE: client/src/data/tshirts.ts
  constant TSHIRT_SIZES (line 1) | const TSHIRT_SIZES = [

FILE: client/src/domain/course.ts
  function getTasksTotalScore (line 3) | function getTasksTotalScore(courseTasks: CourseTaskDto[]) {

FILE: client/src/domain/interview.tsx
  function friendlyStageInterviewVerdict (line 13) | function friendlyStageInterviewVerdict(value: StageInterviewFeedbackVerd...
  function getInterviewResult (line 28) | function getInterviewResult(decision: Decision) {
  type InterviewDetails (line 47) | type InterviewDetails = CommonInterviewDetails;
  type InterviewStatus (line 49) | enum InterviewStatus {
  type InterviewResult (line 55) | enum InterviewResult {
  function getInterviewCardResult (line 61) | function getInterviewCardResult(decision: Decision | StageInterviewFeedb...
  function isInterviewRegistrationInProgress (line 84) | function isInterviewRegistrationInProgress(interviewStartDate: string) {
  function isInterviewStarted (line 90) | function isInterviewStarted(interviewStartDate: string) {
  function getInterviewFeedbackUrl (line 94) | function getInterviewFeedbackUrl({
  function isTechnicalScreening (line 117) | function isTechnicalScreening(name: string) {
  function getRating (line 125) | function getRating(score: number, maxScore: number, feedbackVersion: num...
  function DecisionTag (line 136) | function DecisionTag({ decision, status }: { decision?: Decision; status...
  function InterviewPeriod (line 170) | function InterviewPeriod({

FILE: client/src/domain/user.ts
  function hasRole (line 5) | function hasRole(session: Session, courseId: number, role: CourseRole) {
  function isExpelledStudent (line 9) | function isExpelledStudent(session: Session, courseId: number) {
  function hasRoleInAnyCourse (line 13) | function hasRoleInAnyCourse(session: Session, role: CourseRole) {
  function isAdmin (line 17) | function isAdmin(session: Session) {
  function isMentor (line 21) | function isMentor(session: Session, courseId: number) {
  function getMentorId (line 25) | function getMentorId(session: Session, courseId: number) {
  function isAnyMentor (line 29) | function isAnyMentor(session: Session) {
  function isStudent (line 33) | function isStudent(session: Session, courseId: number) {
  function isActiveStudent (line 37) | function isActiveStudent(session: Session, courseId: number) {
  function isCourseManager (line 41) | function isCourseManager(session: Session, courseId: number) {
  function isDementor (line 45) | function isDementor(session: Session, courseId: number) {
  function isPowerUser (line 49) | function isPowerUser(session: Session, courseId: number) {
  function isAnyCourseManager (line 53) | function isAnyCourseManager(session: Session) {
  function isCourseSupervisor (line 57) | function isCourseSupervisor(session: Session, courseId: number) {
  function isAnyCourseSupervisor (line 61) | function isAnyCourseSupervisor(session: Session) {
  function isAnyCoursePowerUser (line 65) | function isAnyCoursePowerUser(session: Session) {
  function isAnyCourseDementor (line 73) | function isAnyCourseDementor(session: Session) {
  function isTaskOwner (line 77) | function isTaskOwner(session: Session, courseId: number) {
  function isHirer (line 81) | function isHirer(session: Session) {
  function getFullName (line 85) | function getFullName(user: { firstName: string | null; lastName: string ...

FILE: client/src/modules/AutoTest/components/AttemptsAnswers/AttemptsAnswers.tsx
  type Props (line 8) | type Props = {
  function AttemptsAnswers (line 15) | function AttemptsAnswers({ attempts, hideAnswers }: Props) {

FILE: client/src/modules/AutoTest/components/AutoTestTaskCard/AutoTestTaskCard.tsx
  type AutoTestTaskCardProps (line 8) | interface AutoTestTaskCardProps {
  function AutoTestTaskCard (line 12) | function AutoTestTaskCard({ courseTask }: AutoTestTaskCardProps) {

FILE: client/src/modules/AutoTest/components/Coding/Coding.test.tsx
  function renderCoding (line 6) | function renderCoding(type: CourseTaskDetailedDtoTypeEnum) {

FILE: client/src/modules/AutoTest/components/Coding/Coding.tsx
  type CodingProps (line 8) | type CodingProps = {
  function getCodewarsUsername (line 15) | async function getCodewarsUsername(githubId: string) {
  function Coding (line 22) | function Coding({ courseTask, githubId }: CodingProps) {

FILE: client/src/modules/AutoTest/components/Exercise/Exercise.tsx
  type ExerciseProps (line 9) | type ExerciseProps = {
  function responsiveColumns (line 16) | function responsiveColumns(type: CourseTaskDetailedDtoTypeEnum): ColProp...
  function Exercise (line 28) | function Exercise({ githubId, courseId, courseTask, finishTask }: Exerci...

FILE: client/src/modules/AutoTest/components/JupyterNotebook/JupyterNotebook.tsx
  function JupyterNotebook (line 5) | function JupyterNotebook() {

FILE: client/src/modules/AutoTest/components/Question/Question.tsx
  type QuestionProps (line 7) | type QuestionProps = {
  function Question (line 11) | function Question({ question: selfEducationQuestion }: QuestionProps): J...

FILE: client/src/modules/AutoTest/components/SelfEducation/SelfEducation.test.tsx
  function renderSelfEducation (line 43) | function renderSelfEducation({ numberOfQuestions = 5, questions = genera...
  function generateQuestion (line 60) | function generateQuestion({
  function generateQuestions (line 76) | function generateQuestions(count = 15): SelfEducationQuestion[] {

FILE: client/src/modules/AutoTest/components/SelfEducation/SelfEducation.tsx
  type SelfEducationProps (line 9) | type SelfEducationProps = {
  function getRandomQuestions (line 15) | function getRandomQuestions(questions: SelfEducationQuestion[]): SelfEdu...
  function SelfEducation (line 20) | function SelfEducation({ courseTask }: SelfEducationProps) {

FILE: client/src/modules/AutoTest/components/StatusTabs/StatusTabs.test.tsx
  function generateStatuses (line 55) | function generateStatuses(count = 3, statusTypeAndCount: Record<string, ...

FILE: client/src/modules/AutoTest/components/StatusTabs/StatusTabs.tsx
  type StatusTabsProps (line 6) | interface StatusTabsProps {

FILE: client/src/modules/AutoTest/components/TaskCard/TaskCard.test.tsx
  constant COURSE_MOCK (line 7) | const COURSE_MOCK = { alias: 'course-alias', id: 100 } as Course;
  function generateCourseTask (line 35) | function generateCourseTask(maxAttemptsNumber?: number): CourseTaskVerif...

FILE: client/src/modules/AutoTest/components/TaskCard/TaskCard.tsx
  type TaskCardProps (line 11) | interface TaskCardProps {
  function getStatusTag (line 16) | function getStatusTag(state: CourseTaskState) {
  function TaskCard (line 27) | function TaskCard({ courseTask, course }: TaskCardProps) {

FILE: client/src/modules/AutoTest/components/TaskCardColumn/TaskCardColumn.tsx
  type TaskCardColumnProps (line 4) | type TaskCardColumnProps = {
  function TaskCardColumn (line 11) | function TaskCardColumn({ label, value }: TaskCardColumnProps) {

FILE: client/src/modules/AutoTest/components/TaskDeadlineDate/TaskDeadlineDate.tsx
  type TaskDeadlineDateProps (line 10) | type TaskDeadlineDateProps = {
  function getTextType (line 17) | function getTextType(state: CourseTaskState): BaseType {
  function TaskDeadlineDate (line 26) | function TaskDeadlineDate({ startDate, endDate, state, format = 'MMM DD'...

FILE: client/src/modules/AutoTest/components/TaskDescription/TaskDescription.tsx
  type TaskDescriptionProps (line 9) | type TaskDescriptionProps = {
  function TaskDescription (line 14) | function TaskDescription({ courseAlias, courseTask }: TaskDescriptionPro...

FILE: client/src/modules/AutoTest/components/VerificationInformation/VerificationInformation.test.tsx
  function renderVerificationInformation (line 6) | function renderVerificationInformation({

FILE: client/src/modules/AutoTest/components/VerificationInformation/VerificationInformation.tsx
  type VerificationInformationProps (line 8) | type VerificationInformationProps = {
  function VerificationInformation (line 19) | function VerificationInformation({

FILE: client/src/modules/AutoTest/components/VerificationsTable/VerificationsTable.test.tsx
  constant PROPS_MOCK (line 5) | const PROPS_MOCK: VerificationsTableProps = {

FILE: client/src/modules/AutoTest/components/VerificationsTable/VerificationsTable.tsx
  type VerificationsTableProps (line 6) | type VerificationsTableProps = {
  function VerificationsTable (line 12) | function VerificationsTable({ maxScore, verifications, loading }: Verifi...

FILE: client/src/modules/AutoTest/components/VerificationsTable/renderers.tsx
  type Breakpoint (line 10) | type Breakpoint = ColumnType<Verification>['responsive'];
  constant DISPLAY_ALL (line 12) | const DISPLAY_ALL: Breakpoint = ['sm'];
  constant DISPLAY_ACCURACY (line 13) | const DISPLAY_ACCURACY: Breakpoint = ['md'];
  constant DISPLAY_MOBILE (line 14) | const DISPLAY_MOBILE: Breakpoint = ['xs'];
  type Metadata (line 16) | type Metadata = {
  function getColumns (line 23) | function getColumns(maxScore: number): ColumnType<Verification>[] {
  function renderDetails (line 65) | function renderDetails(value: string, row: Verification) {
  function renderScore (line 92) | function renderScore(maxScore: number) {
  function renderDate (line 100) | function renderDate(createdDate: string) {
  function renderMobileRow (line 106) | function renderMobileRow(maxScore: number) {

FILE: client/src/modules/AutoTest/hooks/useAttemptsMessage/useAttemptsMessage.test.ts
  constant MAX_ATTEMPTS (line 8) | const MAX_ATTEMPTS = 4;
  function renderUseAttemptsMessage (line 9) | function renderUseAttemptsMessage({

FILE: client/src/modules/AutoTest/hooks/useAttemptsMessage/useAttemptsMessage.ts
  function useAttemptsMessage (line 9) | function useAttemptsMessage(courseTask: CourseTaskVerifications) {

FILE: client/src/modules/AutoTest/hooks/useCourseTaskSubmit/useCourseTaskSubmit.test.ts
  constant FILE_VALUE_MOCK (line 41) | const FILE_VALUE_MOCK = {
  constant SELF_EDUCATION_MOCK (line 48) | const SELF_EDUCATION_MOCK = { ['answer-0']: 1, ['answer-1']: 2 };
  constant CODING_RESULT (line 50) | const CODING_RESULT = {
  constant CODEWARS_RESULT (line 54) | const CODEWARS_RESULT = { deadline: '2022-10-10T00:00.000Z' };
  constant SELF_EDUCATION_RESULT (line 55) | const SELF_EDUCATION_RESULT = [
  constant IPYNB_RESULT (line 59) | const IPYNB_RESULT = { s3Key: expect.any(String), taskName: 'course_task...
  function renderUseCourseTaskSubmit (line 162) | function renderUseCourseTaskSubmit(courseTask: CourseTaskVerifications) {
  function generateCourseTask (line 169) | function generateCourseTask(
  function generateAxiosError (line 188) | function generateAxiosError(code: number): AxiosError {

FILE: client/src/modules/AutoTest/hooks/useCourseTaskSubmit/useCourseTaskSubmit.ts
  type SelfEducationValues (line 15) | type SelfEducationValues = Record<string, number>;
  type IpynbFile (line 16) | type IpynbFile = { upload: { file: InternalUploadFile } };
  type FormValues (line 17) | type FormValues = SelfEducationValues | IpynbFile;
  function isIpynbFile (line 19) | function isIpynbFile(item: unknown): item is IpynbFile {
  function useCourseTaskSubmit (line 23) | function useCourseTaskSubmit(courseId: number, courseTask: CourseTaskVer...
  function readFile (line 157) | function readFile(file: any) {

FILE: client/src/modules/AutoTest/hooks/useCourseTaskVerifications/useCourseTaskVerifications.ts
  function useCourseTaskVerifications (line 12) | function useCourseTaskVerifications(courseId: number) {

FILE: client/src/modules/AutoTest/hooks/useVerificationsAnswers/useVerificationsAnswers.ts
  function useVerificationsAnswers (line 7) | function useVerificationsAnswers(courseId: number, courseTaskId: number) {

FILE: client/src/modules/AutoTest/pages/AutoTests/AutoTests.tsx
  constant RESPONSIVE_COLUMNS (line 10) | const RESPONSIVE_COLUMNS: ColProps = {
  function AutoTests (line 18) | function AutoTests() {

FILE: client/src/modules/AutoTest/pages/Task/Task.tsx
  type AutoTestTaskProps (line 16) | interface AutoTestTaskProps extends CoursePageProps {
  function Task (line 20) | function Task() {

FILE: client/src/modules/AutoTest/types.ts
  type CourseTaskStatus (line 4) | enum CourseTaskStatus {
  constant COURSE_TASK_STATUSES (line 10) | const COURSE_TASK_STATUSES = Object.entries(CourseTaskStatus).map(([key,...
  type CourseTaskState (line 12) | enum CourseTaskState {
  type CourseTaskVerifications (line 18) | interface CourseTaskVerifications extends CourseTaskDetailedDto {

FILE: client/src/modules/AutoTest/utils/map.ts
  function getState (line 6) | function getState(courseTask: CourseTaskDetailedDto, verifications: Veri...
  function getStatus (line 25) | function getStatus(
  function mapTo (line 56) | function mapTo(courseTask: CourseTaskDetailedDto, verifications: Verific...

FILE: client/src/modules/Contributor/components/ContributorModal.tsx
  type Props (line 6) | type Props = {
  type FormData (line 13) | type FormData = {
  function ContributorModal (line 18) | function ContributorModal(props: Props) {

FILE: client/src/modules/Contributor/components/ContributorsTable.tsx
  type Props (line 8) | type Props = {

FILE: client/src/modules/Course/components/CourseNoAccess.tsx
  function CourseNoAccess (line 3) | function CourseNoAccess() {

FILE: client/src/modules/Course/components/NoSubmissionAvailable/index.tsx
  function NoSubmissionAvailable (line 4) | function NoSubmissionAvailable({ courseAlias }: { courseAlias: string }) {

FILE: client/src/modules/Course/contexts/ActiveCourseContext.tsx
  type ActiveCourseContextType (line 12) | type ActiveCourseContextType = {
  type Props (line 30) | type Props = React.PropsWithChildren<{
  function resolveCourse (line 102) | async function resolveCourse(

FILE: client/src/modules/Course/contexts/SessionContext.tsx
  type Props (line 14) | type Props = React.PropsWithChildren<{
  function SessionProvider (line 36) | function SessionProvider(props: Props) {

FILE: client/src/modules/Course/pages/CouseNoAccess/index.tsx
  function CouseNoAccessPage (line 3) | function CouseNoAccessPage() {

FILE: client/src/modules/Course/pages/Student/CrossCheckSubmit/index.tsx
  function CrossCheckSubmit (line 64) | function CrossCheckSubmit() {
  function calculateFinalScore (line 321) | function calculateFinalScore(

FILE: client/src/modules/CourseManagement/components/CertificateCriteriaModal/CertificateCriteriaModal.tsx
  type FormValues (line 5) | type FormValues = {
  type Criteria (line 11) | type Criteria = Partial<FormValues>;
  type Props (line 13) | type Props = {
  constant CERTIFICATE_ALERT_MESSAGE (line 20) | const CERTIFICATE_ALERT_MESSAGE = 'Certificates will be issued to all st...
  function CertificateCriteriaModal (line 22) | function CertificateCriteriaModal({ courseId, onSubmit, onClose, isModal...
  function hasValidCriteria (line 76) | function hasValidCriteria({ minScore, courseTaskIds, minTotalScore }: Fo...

FILE: client/src/modules/CourseManagement/components/CourseEventModal/formState.ts
  function submitEvent (line 53) | async function submitEvent(
  function getInitialValues (line 79) | function getInitialValues(modalData: Partial<CourseEvent>) {

FILE: client/src/modules/CourseManagement/components/CourseEventModal/index.tsx
  type Props (line 19) | type Props = {
  function CourseEventModal (line 30) | function CourseEventModal({ data, onCancel, courseId, onSubmit }: Props) {

FILE: client/src/modules/CourseManagement/components/CourseModal/index.tsx
  type CourseModalProps (line 41) | type CourseModalProps = {
  type FormData (line 49) | type FormData = {
  function CourseModal (line 85) | function CourseModal(props: CourseModalProps) {
  function createRecord (line 447) | function createRecord(values: FormData) {
  function getDateRange (line 488) | function getDateRange(
  function getInitialValues (line 495) | function getInitialValues(modalData: Partial<Course>): FormData {

FILE: client/src/modules/CourseManagement/components/CourseTaskModal/index.tsx
  type Props (line 21) | type Props = {
  function CourseTaskModal (line 30) | function CourseTaskModal(props: Props) {
  function createRecord (line 250) | function createRecord(values: any): CreateCourseTaskDto {
  function getInitialValues (line 272) | function getInitialValues(modalData: Partial<CourseTaskDetails>) {

FILE: client/src/modules/CourseManagement/components/CoursesListModal/index.tsx
  type Props (line 9) | type Props = PropsWithChildren<{
  function CoursesListModal (line 18) | function CoursesListModal(props: Props) {
  function createRecord (line 70) | function createRecord(values: { courseId: number }) {

FILE: client/src/modules/CourseManagement/components/ExpelCriteriaModal/ExpelCriteriaModal.tsx
  type FormValues (line 5) | type FormValues = {
  type Criteria (line 12) | type Criteria = Partial<FormValues> & { reason: string };
  type Props (line 14) | type Props = {
  constant EXPEL_ALERT_MESSAGE (line 21) | const EXPEL_ALERT_MESSAGE = 'All students meeting the criteria below wil...
  function ExpelCriteriaModal (line 23) | function ExpelCriteriaModal({ courseId, onSubmit, onClose, isModalOpen }...
  function hasValidCriteria (line 87) | function hasValidCriteria({ minScore, courseTaskIds }: FormValues) {

FILE: client/src/modules/CourseManagement/components/ExpelledStudentsStats.tsx
  type Props (line 12) | type Props = {

FILE: client/src/modules/CourseManagement/components/SelectCourseTasks/SelectCourseTasks.tsx
  type Props (line 5) | type Props = FormItemProps & {
  function SelectCourseTasks (line 11) | function SelectCourseTasks({ courseId, ...props }: Props) {

FILE: client/src/modules/CourseStatistics/components/CountriesChart/CountriesChart.tsx
  type Props (line 7) | type Props = {
  type Datum (line 20) | type Datum = Parameters<typeof Bar>[0]['data'][number];
  function CountriesChart (line 24) | function CountriesChart({ data, activeCount, xAxisTitle, color = Colors....

FILE: client/src/modules/CourseStatistics/components/DonutChart/DonutChart.tsx
  type Props (line 3) | type Props = {

FILE: client/src/modules/CourseStatistics/components/EpamMentorsStatsCard/EpamMentorsStatsCard.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/CourseStatistics/components/LiquidChart/LiquidChart.tsx
  type Props (line 5) | type Props = {
  function LiquidChart (line 12) | function LiquidChart({ count, total, color = Colors.Blue, background }: ...

FILE: client/src/modules/CourseStatistics/components/MentorsCountriesCard/MentorsCountriesCard.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/CourseStatistics/components/StatCards/StatCards.tsx
  type StatCardsProps (line 16) | type StatCardsProps = {
  function StatCards (line 31) | function StatCards({ coursesData }: StatCardsProps) {

FILE: client/src/modules/CourseStatistics/components/StatScopeSelector/StatScopeSelector.tsx
  type StatScopeSelectorProps (line 6) | type StatScopeSelectorProps = {
  function StatScopeSelector (line 13) | function StatScopeSelector({

FILE: client/src/modules/CourseStatistics/components/StudentsCertificatesCountriesCard/StudentsCertificatesCountriesCard.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/CourseStatistics/components/StudentsCountriesCard/StudentsCountriesCard.tsx
  type Props (line 5) | type Props = {

FILE: client/src/modules/CourseStatistics/components/StudentsEligibleForCertificationCard/StudentsEligibleForCertificationCard.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/CourseStatistics/components/StudentsStatsCard/StudentsStatsCard.tsx
  type Props (line 5) | type Props = {

FILE: client/src/modules/CourseStatistics/components/StudentsWithCertificateCard/StudentsWithCertificateCard.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/CourseStatistics/components/StudentsWithMentorsCard/StudentsWithMentorsCard.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/CourseStatistics/components/TaskPerformanceCard/TaskPerformanceCard.tsx
  type Props (line 12) | type Props = {
  function getPerformanceDescriptionByType (line 62) | function getPerformanceDescriptionByType(type: string) {
  function getChartConfig (line 81) | function getChartConfig(): Partial<PieConfig> {
  function getChartData (line 99) | function getChartData(taskPerformanceStats: TaskPerformanceStatsDto) {

FILE: client/src/modules/CourseStatistics/constants.ts
  type StatScope (line 1) | enum StatScope {

FILE: client/src/modules/CourseStatistics/data.ts
  type Colors (line 1) | enum Colors {
  type StudentPerformanceDescription (line 12) | enum StudentPerformanceDescription {
  type StudentPerformanceType (line 22) | enum StudentPerformanceType {

FILE: client/src/modules/CourseStatistics/hooks/useCourseStats.tsx
  type CourseStatsParams (line 7) | type CourseStatsParams = {
  function fetchCourseStats (line 12) | async function fetchCourseStats({
  function useCoursesStats (line 25) | function useCoursesStats({ ids, year }: CourseStatsParams) {

FILE: client/src/modules/CourseStatistics/pages/CourseStatistics.tsx
  function CourseStatistic (line 13) | function CourseStatistic() {

FILE: client/src/modules/CrossCheck/AddCriteriaForCrossCheck.tsx
  function changeMax (line 48) | function changeMax(value: number | null) {
  function changeMaxPenalty (line 52) | function changeMaxPenalty(value: number | null) {
  function changeType (line 56) | function changeType(value: CrossCheckCriteriaType) {

FILE: client/src/modules/CrossCheck/CriteriaActions.tsx
  type CriteriaActionsProps (line 5) | interface CriteriaActionsProps {

FILE: client/src/modules/CrossCheck/CriteriaTypeSelect.tsx
  type CriteriaTypeSelectProps (line 8) | type CriteriaTypeSelectProps = SelectProps;

FILE: client/src/modules/CrossCheck/DeleteAllCrossCheckCriteriaButton.tsx
  type Props (line 5) | interface Props {
  function DeleteAllCrossCheckCriteriaButton (line 8) | function DeleteAllCrossCheckCriteriaButton({ setDataCriteria }: Props) {

FILE: client/src/modules/CrossCheck/EditableCellForCrossCheck.tsx
  type EditableCellProps (line 7) | interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {

FILE: client/src/modules/CrossCheck/EditableCriteriaInput.tsx
  type EditableCriteriaInputProps (line 7) | interface EditableCriteriaInputProps {

FILE: client/src/modules/CrossCheck/EditableTableForCrossCheck.tsx
  type IEditableTableProps (line 15) | interface IEditableTableProps {

FILE: client/src/modules/CrossCheck/ExportJSONButton.tsx
  type Props (line 8) | interface Props {
  function ExportJSONButton (line 12) | function ExportJSONButton({ dataCriteria }: Props) {

FILE: client/src/modules/CrossCheck/UploadCriteriaJSON.tsx
  type IUploadCriteriaJSON (line 9) | interface IUploadCriteriaJSON {
  type CriteriaJSONType (line 13) | type CriteriaJSONType = {

FILE: client/src/modules/CrossCheck/components/CriteriaForm.tsx
  function RateIcon (line 9) | function RateIcon({ index, value }: { index: number; value: number }) {
  type Review (line 23) | type Review = {
  type ReviewValue (line 28) | enum ReviewValue {
  type Props (line 34) | type Props = {
  function CriteriaForm (line 45) | function CriteriaForm({ authorId, comments, reviewComments, criteria, on...
  function convertPercentageToValue (line 177) | function convertPercentageToValue(percentage: number) {
  function convertValueToPercentage (line 187) | function convertValueToPercentage(value: number) {

FILE: client/src/modules/CrossCheck/components/CrossCheckAssignmentLink.tsx
  type AssignmentLink (line 5) | type AssignmentLink = { student: StudentBasic; url: string };
  function CrossCheckAssignmentLink (line 7) | function CrossCheckAssignmentLink({ assignment }: { assignment?: Assignm...

FILE: client/src/modules/CrossCheck/components/CrossCheckCriteriaForm.tsx
  type CriteriaFormProps (line 14) | interface CriteriaFormProps {
  function CrossCheckCriteriaForm (line 25) | function CrossCheckCriteriaForm({

FILE: client/src/modules/CrossCheck/components/CrossCheckHistory.tsx
  type CrossCheckHistoryState (line 11) | type CrossCheckHistoryState = {
  type Props (line 16) | type Props = {
  function CrossCheckHistory (line 26) | function CrossCheckHistory(props: Props) {

FILE: client/src/modules/CrossCheck/components/DragSortTable.tsx
  type RowProps (line 7) | interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {

FILE: client/src/modules/CrossCheck/components/SolutionReview/Message/Message.tsx
  type MessageProps (line 13) | type MessageProps = {
  function Message (line 20) | function Message(props: MessageProps) {
  function getBadgeDotVisibility (line 93) | function getBadgeDotVisibility(props: MessageProps): boolean {

FILE: client/src/modules/CrossCheck/components/SolutionReview/MessageSendingPanel/MessageSendingPanel.tsx
  type MessageSendingPanelProps (line 13) | type MessageSendingPanelProps = {
  function MessageSendingPanel (line 21) | function MessageSendingPanel(props: MessageSendingPanelProps) {

FILE: client/src/modules/CrossCheck/components/SolutionReview/SolutionReview.tsx
  type SolutionReviewProps (line 22) | type SolutionReviewProps = {
  function SolutionReview (line 37) | function SolutionReview(props: SolutionReviewProps) {

FILE: client/src/modules/CrossCheck/components/SolutionReview/UserAvatar/UserAvatar.tsx
  type UserAvatarProps (line 7) | type UserAvatarProps = {
  function UserAvatar (line 14) | function UserAvatar(props: UserAvatarProps) {
  function createAvatarPath (line 20) | function createAvatarPath(props: UserAvatarProps): string {

FILE: client/src/modules/CrossCheck/components/SolutionReview/Username/Username.tsx
  type UsernameProps (line 8) | type UsernameProps = {
  function Username (line 15) | function Username(props: UsernameProps) {
  function createFakeUsername (line 25) | function createFakeUsername(props: UsernameProps): string {

FILE: client/src/modules/CrossCheck/components/SolutionReviewSettingsPanel/SolutionReviewSettingsPanel.tsx
  type SolutionReviewSettingsPanelProps (line 6) | type SolutionReviewSettingsPanelProps = {
  function SolutionReviewSettingsPanel (line 10) | function SolutionReviewSettingsPanel(props: SolutionReviewSettingsPanelP...

FILE: client/src/modules/CrossCheck/components/SubmittedStatus.tsx
  type Props (line 5) | type Props = {
  function SubmittedStatus (line 11) | function SubmittedStatus(props: Props) {

FILE: client/src/modules/CrossCheck/components/criteria/CrossCheckCriteria.tsx
  type Props (line 8) | type Props = {
  function CrossCheckCriteria (line 12) | function CrossCheckCriteria({ criteria }: Props) {

FILE: client/src/modules/CrossCheck/components/criteria/CrossCheckCriteriaModal.tsx
  type Props (line 5) | type Props = {
  function CrossCheckCriteriaModal (line 11) | function CrossCheckCriteriaModal({ modalInfo, isModalVisible, showModal ...

FILE: client/src/modules/CrossCheck/components/criteria/PenaltyCriteria.tsx
  type HasPenalty (line 7) | enum HasPenalty {
  type PenaltyCriteriaProps (line 12) | interface PenaltyCriteriaProps {
  function PenaltyCriteria (line 17) | function PenaltyCriteria({ penaltyData, updateCriteriaData }: PenaltyCri...

FILE: client/src/modules/CrossCheck/components/criteria/SubtaskCriteria.tsx
  type SubtaskCriteriaProps (line 11) | interface SubtaskCriteriaProps {
  function SubtaskCriteria (line 16) | function SubtaskCriteria({ subtaskData, updateCriteriaData }: SubtaskCri...

FILE: client/src/modules/CrossCheck/components/criteria/TitleCriteria.tsx
  type TitleCriteriaProps (line 4) | interface TitleCriteriaProps {
  function TitleCriteria (line 9) | function TitleCriteria({ titleData }: TitleCriteriaProps) {

FILE: client/src/modules/CrossCheck/constants.ts
  type LocalStorageKey (line 3) | enum LocalStorageKey {
  type SolutionReviewSettings (line 7) | interface SolutionReviewSettings {
  constant AVATAR_ICON_PATH (line 12) | const AVATAR_ICON_PATH = {
  constant ROLE_TAG_COLOR (line 17) | const ROLE_TAG_COLOR = {
  type EditableTableColumnsDataIndex (line 22) | enum EditableTableColumnsDataIndex {
  type TaskType (line 29) | enum TaskType {

FILE: client/src/modules/CrossCheck/hooks/useSolutionReviewSettings.ts
  function useSolutionReviewSettings (line 4) | function useSolutionReviewSettings(): SolutionReviewSettings {

FILE: client/src/modules/CrossCheck/utils/arrayMoveImmutable.tsx
  function arrayMoveMutable (line 3) | function arrayMoveMutable(array: CriteriaDto[], fromIndex: number, toInd...
  function arrayMoveImmutable (line 16) | function arrayMoveImmutable(array: CriteriaDto[], fromIndex: number, toI...

FILE: client/src/modules/CrossCheck/utils/getCriteriaStatusColor.ts
  function getCriteriaStatusColor (line 3) | function getCriteriaStatusColor(score: number, maxScore?: number) {

FILE: client/src/modules/CrossCheckPairs/components/BadReview/BadReviewControllers.tsx
  type IBadReviewControllersProps (line 7) | interface IBadReviewControllersProps {
  type IBadReview (line 12) | interface IBadReview {
  type checkType (line 21) | type checkType = 'Bad comment' | 'Did not check' | 'No type';
  function BadReviewControllers (line 23) | function BadReviewControllers({ courseTasks, courseId }: IBadReviewContr...

FILE: client/src/modules/CrossCheckPairs/components/BadReview/BadReviewTable.tsx
  type IBadReviewTableProps (line 5) | interface IBadReviewTableProps {

FILE: client/src/modules/CrossCheckPairs/components/CrossCheckPairsTable/CrossCheckPairsTable.tsx
  type Filters (line 12) | type Filters = Omit<typeof fields, 'score' | 'submittedDate' | 'reviewed...
  type CustomSorterResult (line 14) | interface CustomSorterResult<RecordType> extends SorterResult<RecordType> {
  type Sorter (line 18) | type Sorter<RecordType> = CustomSorterResult<RecordType> | CustomSorterR...
  type CrossCheckTableProps (line 20) | type CrossCheckTableProps = {

FILE: client/src/modules/CrossCheckPairs/data/getCrossCheckPairsColumns.tsx
  type CustomColumnType (line 19) | interface CustomColumnType<RecordType> extends ColumnType<RecordType> {

FILE: client/src/modules/CrossCheckPairs/pages/CrossCheckPairs/CrossCheckPairs.tsx
  type OrderDirection (line 21) | enum OrderDirection {
  constant DEFAULT_ORDER_BY (line 26) | const DEFAULT_ORDER_BY = 'task';
  constant DEFAULT_ORDER_DIRECTION (line 27) | const DEFAULT_ORDER_DIRECTION = OrderDirection.ASC;
  function Page (line 31) | function Page() {

FILE: client/src/modules/Discipline/components/DisciplineModal.tsx
  type IDisciplineModal (line 5) | interface IDisciplineModal {
  function DisciplineModal (line 13) | function DisciplineModal({ isModalVisible, onCancel, loadDisciplines, di...

FILE: client/src/modules/Discipline/components/DisciplineTable.tsx
  type IDisciplineTable (line 7) | interface IDisciplineTable {
  method onOk (line 19) | async onOk() {

FILE: client/src/modules/DiscordAdmin/components/DiscordServersModal.tsx
  type Props (line 5) | type Props = {
  function DiscordServersModal (line 14) | function DiscordServersModal({ data, title, submit, cancel, getInitialVa...

FILE: client/src/modules/DiscordAdmin/components/DiscordServersTable.tsx
  type Props (line 6) | type Props = {
  function DiscordServersTable (line 12) | function DiscordServersTable({ data, onEdit, onDelete }: Props) {
  function getColumns (line 25) | function getColumns(handleEditItem: (record: DiscordServerDto) => void, ...

FILE: client/src/modules/DiscordAdmin/hooks/useDiscordServers.ts
  function useDiscordServers (line 7) | function useDiscordServers() {

FILE: client/src/modules/DiscordAdmin/pages/DiscordAdminPage/DiscordAdminPage.tsx
  type ModalAction (line 12) | enum ModalAction {
  function DiscordAdminPage (line 17) | function DiscordAdminPage() {

FILE: client/src/modules/EventsAdmin/components/EventsModal.tsx
  type Props (line 6) | type Props = {
  function EventsModal (line 15) | function EventsModal({ data, title, submit, cancel, getInitialValues, di...

FILE: client/src/modules/EventsAdmin/components/EventsTable.tsx
  type Props (line 7) | type Props = {
  function EventsTable (line 13) | function EventsTable({ data, onEdit, onDelete }: Props) {
  function getColumns (line 26) | function getColumns(handleEditItem: (record: EventDto) => void, handleDe...

FILE: client/src/modules/EventsAdmin/hooks/useEvents.ts
  function useEvents (line 8) | function useEvents() {

FILE: client/src/modules/EventsAdmin/pages/EventsAdminPage/EventsAdminPage.tsx
  function EventsAdminPage (line 13) | function EventsAdminPage() {

FILE: client/src/modules/Feedback/components/FeedbackForm.tsx
  type FormValues (line 14) | type FormValues = Record<SoftSkillEntryIdEnum, number> & {
  type FeedbackFormProps (line 31) | type FeedbackFormProps = {

FILE: client/src/modules/Home/components/CourseLinks/CourseLinks.tsx
  type CourseLinksProps (line 5) | type CourseLinksProps = {
  function CourseLinks (line 9) | function CourseLinks({ courseLinks }: CourseLinksProps) {

FILE: client/src/modules/Home/components/CourseSelector/index.tsx
  type Props (line 6) | type Props = {
  function CourseSelector (line 12) | function CourseSelector(props: Props) {

FILE: client/src/modules/Home/components/HomeSummary/HomeSummary.tsx
  type HomeSummaryProps (line 5) | type HomeSummaryProps = {
  function HomeSummary (line 10) | function HomeSummary({ summary, courseTasks }: HomeSummaryProps) {

FILE: client/src/modules/Home/components/NoCourse/index.tsx
  type Props (line 5) | type Props = {
  function NoCourse (line 10) | function NoCourse({ courses, preselectedCourses }: Props) {

FILE: client/src/modules/Home/components/RegistryBanner/index.tsx
  function RegistryBanner (line 3) | function RegistryBanner(props: Partial<AlertProps>) {

FILE: client/src/modules/Home/components/SystemAlerts/index.tsx
  type Props (line 4) | type Props = {
  function SystemAlerts (line 8) | function SystemAlerts({ alerts }: Props) {

FILE: client/src/modules/Home/data/links.tsx
  type LinkData (line 39) | type LinkData = {
  type LinkRenderData (line 48) | type LinkRenderData = Pick<LinkData, 'icon' | 'name'> & { url: string };
  function getCourseLinks (line 140) | function getCourseLinks(session: Session, activeCourse: Course | null): ...
  function getNavigationItems (line 152) | function getNavigationItems(session: Session, activeCourse: Course | nul...

FILE: client/src/modules/Home/data/loadHomeData.ts
  function loadHomeData (line 4) | async function loadHomeData(courseId: number, githubId: string) {

FILE: client/src/modules/Home/hooks/useActiveCourse.tsx
  function useActiveCourse (line 5) | function useActiveCourse(courses: Course[]): [Course | null, (courseId: ...

FILE: client/src/modules/Home/hooks/useStudentSummary.tsx
  function useStudentSummary (line 9) | function useStudentSummary(session: Session, course: Course | null) {

FILE: client/src/modules/Home/pages/HomePage/index.tsx
  function HomePage (line 27) | function HomePage() {

FILE: client/src/modules/Interview/Student/data/getInterviewCardDetails.tsx
  type StudentInterviewDetails (line 4) | interface StudentInterviewDetails {

FILE: client/src/modules/Interviews/data/getInterviewData.ts
  type FeedbackProps (line 6) | type FeedbackProps = CourseOnlyPageProps & {
  function getInterviewData (line 17) | async function getInterviewData({

FILE: client/src/modules/Interviews/data/getStageInterviewData.ts
  type StageFeedbackProps (line 14) | type StageFeedbackProps = CourseOnlyPageProps & {
  function getStageInterviewData (line 28) | async function getStageInterviewData({
  function validateQueryParams (line 69) | function validateQueryParams(query: ParsedUrlQuery, params: string[]) {

FILE: client/src/modules/Interviews/data/index.ts
  type PageProps (line 7) | type PageProps = FeedbackProps | StageFeedbackProps;

FILE: client/src/modules/Interviews/pages/InterviewFeedback/index.tsx
  type FormAnswer (line 14) | type FormAnswer = {
  function InterviewFeedback (line 20) | function InterviewFeedback({ course, type, interviewTaskId, githubId }: ...

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/CustomQuestion.tsx
  type Props (line 4) | type Props = {
  function CustomQuestion (line 9) | function CustomQuestion({ cancel, save }: Props) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/FormItem.tsx
  function FormItem (line 12) | function FormItem({ item, form, stepId }: { item: StepFormItem; form: Fo...

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/NestedRadio.tsx
  function NestedRadio (line 11) | function NestedRadio({

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/QuestionCard.tsx
  type Props (line 4) | type Props = {
  function QuestionCard (line 14) | function QuestionCard({ content, fieldName, required, tooltips }: Props) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/QuestionList.tsx
  type Props (line 14) | type Props = {
  function QuestionList (line 20) | function QuestionList({ form, question, stepId }: Props) {
  function generateId (line 105) | function generateId() {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/QuestionsPicker.tsx
  function QuestionsPicker (line 6) | function QuestionsPicker({

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/StageInterviewFeedback.tsx
  function StageInterviewFeedback (line 17) | function StageInterviewFeedback(props: StageFeedbackProps) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/StepContext.tsx
  type ContextProps (line 15) | type ContextProps = {
  type StepApi (line 23) | type StepApi = {
  function StepContextProvider (line 35) | function StepContextProvider(props: PropsWithChildren<ContextProps>) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/StepForm.tsx
  type Values (line 9) | type Values = Record<string, string>;
  type Props (line 11) | type Props = {
  function StepForm (line 20) | function StepForm({ step, next, back, isFirst, isLast, onValuesChange }:...
  function getInitialQuestions (line 53) | function getInitialQuestions(step: FeedbackStep) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/Steps.tsx
  function Steps (line 5) | function Steps() {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/StepsContent.tsx
  function StepsContent (line 6) | function StepsContent() {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/StudentInfo.tsx
  type Props (line 6) | type Props = {
  function StudentInfo (line 16) | function StudentInfo(props: Props) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/SubHeader.tsx
  type Props (line 6) | type Props = {
  function SubHeader (line 10) | function SubHeader(props: Props) {

FILE: client/src/modules/Interviews/pages/StageInterviewFeedback/feedbackTemplateHandler.ts
  type FeedbackData (line 5) | type FeedbackData = {
  function getFeedbackFromTemplate (line 12) | function getFeedbackFromTemplate(interviewFeedback: InterviewFeedbackDto...
  function getDefaultStep (line 38) | function getDefaultStep(feedback: Feedback) {
  function isInterviewCanceled (line 56) | function isInterviewCanceled(stepId: FeedbackStepId, stepValues: Intervi...
  function mergeFeedbackValuesToTemplate (line 63) | function mergeFeedbackValuesToTemplate(feedback: Feedback, data: Feedbac...
  function applyDefaultFinalScore (line 87) | function applyDefaultFinalScore(mergedFeedback: Feedback, interviewMaxSc...
  function getUpdatedFeedback (line 111) | function getUpdatedFeedback({
  function generateFeedbackValues (line 142) | function generateFeedbackValues(
  function getInterviewSummary (line 172) | function getInterviewSummary(feedback: Feedback) {
  function isInterviewCompleted (line 205) | function isInterviewCompleted(feedback: Feedback) {
  function calculateFinalScore (line 214) | function calculateFinalScore(steps: Feedback['steps']) {
  function calculateStepScore (line 224) | function calculateStepScore(step: FeedbackStep, interviewMaxScore: numbe...

FILE: client/src/modules/Mentor/components/Instructions/Instructions.tsx
  type InstructionsProps (line 7) | interface InstructionsProps {
  function Instructions (line 17) | function Instructions({ courseId, discordServerId }: InstructionsProps) {

FILE: client/src/modules/Mentor/components/Instructions/constants.ts
  constant INSTRUCTIONS_TEXT (line 1) | const INSTRUCTIONS_TEXT = {

FILE: client/src/modules/Mentor/components/MentorDashboard/MentorDashboard.tsx
  function MentorDashboard (line 7) | function MentorDashboard() {

FILE: client/src/modules/Mentor/components/Notification/Notification.tsx
  function Notification (line 5) | function Notification() {

FILE: client/src/modules/Mentor/components/ReviewRandomTask/ReviewRandomTask.tsx
  type Props (line 7) | interface Props {
  function ReviewRandomTask (line 13) | function ReviewRandomTask({ mentorId, courseId, onClick }: Props) {

FILE: client/src/modules/Mentor/components/SubmitReviewModal/SubmitReviewModal.test.tsx
  method reset (line 24) | reset() {
  constant MODAL_DATA_MOCK (line 33) | const MODAL_DATA_MOCK = {
  constant PROPS_MOCK (line 44) | const PROPS_MOCK: SubmitReviewModalProps = {

FILE: client/src/modules/Mentor/components/SubmitReviewModal/SubmitReviewModal.tsx
  type SubmitReviewModalProps (line 10) | interface SubmitReviewModalProps {
  constant MODAL_TITLE (line 19) | const MODAL_TITLE = 'Submit Score for';
  constant SUCCESS_MESSAGE (line 20) | const SUCCESS_MESSAGE = 'Your review has been successfully submitted';
  function SubmitReviewModal (line 22) | function SubmitReviewModal({ data, courseId, onClose, onSubmit }: Submit...

FILE: client/src/modules/Mentor/components/TaskSolutionsTable/TaskSolutionsTable.test.tsx
  function generateData (line 8) | function generateData(count = 3): MentorDashboardDto[] {

FILE: client/src/modules/Mentor/components/TaskSolutionsTable/TaskSolutionsTable.tsx
  type TaskSolutionsTableProps (line 10) | interface TaskSolutionsTableProps {
  function TaskSolutionsTable (line 20) | function TaskSolutionsTable({ mentorId, onChange, data, loading, courseI...

FILE: client/src/modules/Mentor/components/TaskSolutionsTable/renderers.tsx
  type Breakpoint (line 10) | type Breakpoint = ColumnType<MentorDashboardDto>['responsive'];
  constant FORMAT (line 12) | const FORMAT = 'YYYY-MM-DD HH:mm';
  constant TIMEZONE (line 13) | const TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;
  constant DISPLAY_TABLE_BREAKPOINTS (line 14) | const DISPLAY_TABLE_BREAKPOINTS: Breakpoint = ['sm'];
  constant DISPLAY_TABLE_MOBILE_BREAKPOINT (line 15) | const DISPLAY_TABLE_MOBILE_BREAKPOINT: Breakpoint = ['xs'];
  function renderName (line 77) | function renderName(value: string, { studentName, studentGithubId }: Men...
  function renderTask (line 87) | function renderTask(value: string, { taskDescriptionUrl }: MentorDashboa...
  function renderSolutionUrl (line 97) | function renderSolutionUrl(value: string, { solutionUrl }: MentorDashboa...
  function renderScore (line 107) | function renderScore(_v: string, { maxScore, resultScore }: MentorDashbo...
  function renderSubmitButton (line 117) | function renderSubmitButton(row: MentorDashboardDto, handleSubmitClick: ...
  function renderMobile (line 125) | function renderMobile(row: MentorDashboardDto) {
  function renderDate (line 137) | function renderDate(value: string, { endDate, resultScore }: MentorDashb...

FILE: client/src/modules/Mentor/components/TaskStatusTabs/TaskStatusTabs.test.tsx
  constant PROPS_MOCK (line 5) | const PROPS_MOCK = {
  function generateStatuses (line 56) | function generateStatuses(count = 3, status = SolutionItemStatus.InRevie...

FILE: client/src/modules/Mentor/components/TaskStatusTabs/TaskStatusTabs.tsx
  type Status (line 6) | type Status = SolutionItemStatus;
  type TaskStatusTabsProps (line 8) | interface TaskStatusTabsProps {

FILE: client/src/modules/Mentor/components/TaskStatusTabs/renderers.tsx
  type TabItem (line 7) | type TabItem = {

FILE: client/src/modules/Mentor/constants.ts
  constant INFO_MESSAGE (line 1) | const INFO_MESSAGE =
  type TaskSolutionsTableColumnKey (line 4) | enum TaskSolutionsTableColumnKey {
  type TaskSolutionsTableColumnName (line 14) | enum TaskSolutionsTableColumnName {
  type SolutionItemStatus (line 24) | enum SolutionItemStatus {
  constant TASKS_STATUSES (line 30) | const TASKS_STATUSES = Object.entries(SolutionItemStatus).map(([key, val...

FILE: client/src/modules/Mentor/hooks/useMentorDashboard.tsx
  function useMentorDashboard (line 6) | function useMentorDashboard(mentorId: number | undefined, courseId: numb...

FILE: client/src/modules/Mentor/hooks/useMentorStudents.tsx
  function useMentorStudents (line 5) | function useMentorStudents(mentorId: number | null) {

FILE: client/src/modules/Mentor/pages/InterviewWaitingList/index.tsx
  type PageProps (line 29) | type PageProps = CoursePageProps & { interview: InterviewDto };
  function InterviewWaitingList (line 31) | function InterviewWaitingList() {

FILE: client/src/modules/Mentor/pages/Interviews/components/InterviewCard.tsx
  function InterviewCard (line 9) | function InterviewCard(props: {

FILE: client/src/modules/Mentor/pages/Interviews/components/InterviewDetails.tsx
  function InterviewDetails (line 9) | function InterviewDetails(props: {

FILE: client/src/modules/Mentor/pages/Interviews/components/InterviewsList.tsx
  type StudentsListProps (line 13) | type StudentsListProps = {
  function InterviewsList (line 20) | function InterviewsList(props: StudentsListProps) {

FILE: client/src/modules/Mentor/pages/Interviews/components/InterviewsSummary.tsx
  function InterviewsSummary (line 11) | function InterviewsSummary({

FILE: client/src/modules/Mentor/pages/Interviews/components/MentorPreferencesModal.tsx
  type Props (line 10) | type Props = {
  type MentorOptionsContextApi (line 15) | type MentorOptionsContextApi = {
  function MentorOptionsProvider (line 21) | function MentorOptionsProvider({ children, course, session }: React.Prop...
  function MentorOptionsModal (line 35) | function MentorOptionsModal({ course, close, session }: Props & { close:...

FILE: client/src/modules/Mentor/pages/Interviews/components/RegistrationNoticeAlert.tsx
  function RegistrationNoticeAlert (line 10) | function RegistrationNoticeAlert(props: { interview: InterviewDto; start...

FILE: client/src/modules/Mentor/pages/Interviews/components/SelectMentorModal.tsx
  type Props (line 7) | type Props = {
  function SelectMentorModal (line 14) | function SelectMentorModal(props: Props) {

FILE: client/src/modules/Mentor/pages/Interviews/components/StudentInterview.tsx
  function StudentInterview (line 12) | function StudentInterview(props: {

FILE: client/src/modules/Mentor/pages/Interviews/components/WaitListAlert.tsx
  function WaitListAlert (line 8) | function WaitListAlert({

FILE: client/src/modules/Mentor/pages/Interviews/hooks/useAlert.ts
  function useAlert (line 4) | function useAlert(key: string) {

FILE: client/src/modules/Mentor/pages/Interviews/index.tsx
  function Interviews (line 14) | function Interviews() {

FILE: client/src/modules/Mentor/pages/StudentFeedback/index.tsx
  function StudentFeedback (line 13) | function StudentFeedback() {

FILE: client/src/modules/Mentor/pages/Students/index.tsx
  function Students (line 19) | function Students() {

FILE: client/src/modules/MentorRegistry/components/InviteMentorsModal.tsx
  type Props (line 13) | type Props = {
  function InviteMentorsModal (line 19) | function InviteMentorsModal({ onCancel }: Props) {

FILE: client/src/modules/MentorRegistry/components/MentorRegistryDeleteModal.tsx
  type MentorRegistryModalProps (line 4) | interface MentorRegistryModalProps {

FILE: client/src/modules/MentorRegistry/components/MentorRegistryResendModal.tsx
  type MentorRegistryModalProps (line 5) | interface MentorRegistryModalProps {

FILE: client/src/modules/MentorRegistry/components/MentorRegistryTable.tsx
  type Props (line 9) | type Props = {
  function MentorRegistryTable (line 25) | function MentorRegistryTable(props: Props) {

FILE: client/src/modules/MentorRegistry/components/MentorRegistryTableContainer.tsx
  type ChildrenProp (line 24) | interface ChildrenProp {
  type Props (line 37) | interface Props {
  type CombinedFilter (line 53) | interface CombinedFilter {

FILE: client/src/modules/MentorRegistry/constants.ts
  constant PAGINATION (line 1) | const PAGINATION = 100;
  type MentorsRegistryColumnKey (line 3) | enum MentorsRegistryColumnKey {
  type MentorsRegistryColumnName (line 18) | enum MentorsRegistryColumnName {
  type MentorRegistryTabsMode (line 33) | enum MentorRegistryTabsMode {
  constant TABS (line 38) | const TABS = {

FILE: client/src/modules/MentorTasksReview/components/AssignReviewerModal/AssignReviewerModal.tsx
  type AssignReviewerModalProps (line 12) | interface AssignReviewerModalProps {
  constant MODAL_TITLE (line 20) | const MODAL_TITLE = 'Assign Reviewer for';
  constant SUCCESS_MESSAGE (line 21) | const SUCCESS_MESSAGE = 'Reviewer has been successfully assigned';
  function AssignReviewerModal (line 23) | function AssignReviewerModal({ review, onClose, onSubmit }: AssignReview...

FILE: client/src/modules/MentorTasksReview/components/ReviewsTable/index.tsx
  type Props (line 7) | type Props = {
  function MentorReviewsTable (line 17) | function MentorReviewsTable({

FILE: client/src/modules/MentorTasksReview/components/ReviewsTable/renderers.tsx
  type ColumnKey (line 17) | enum ColumnKey {
  type ColumnName (line 28) | enum ColumnName {

FILE: client/src/modules/MentorTasksReview/pages/MentorTasksReview.tsx
  type ReviewsState (line 22) | type ReviewsState = {

FILE: client/src/modules/MentorsHallOfFame/components/MentorCard/MentorCard.tsx
  type MentorCardProps (line 10) | interface MentorCardProps {
  function MentorCard (line 14) | function MentorCard({ mentor }: MentorCardProps) {

FILE: client/src/modules/MentorsHallOfFame/pages/MentorsHallOfFamePage.test.tsx
  method getTopMentors (line 9) | getTopMentors(...args: unknown[]) {

FILE: client/src/modules/MentorsHallOfFame/pages/MentorsHallOfFamePage.tsx
  type TimePeriod (line 12) | type TimePeriod = 'lastYear' | 'allTime';
  function MentorsHallOfFamePage (line 14) | function MentorsHallOfFamePage() {

FILE: client/src/modules/MentorsHallOfFame/services/mentors-hall-of-fame.service.ts
  class MentorsHallOfFameService (line 5) | class MentorsHallOfFameService {
    method getTopMentors (line 6) | async getTopMentors(allTime = false): Promise<TopMentorDto[]> {

FILE: client/src/modules/MentorsHallOfFame/types.ts
  type TopMentor (line 4) | type TopMentor = TopMentorDto;
  type CourseStats (line 5) | type CourseStats = MentorCourseStatsDto;

FILE: client/src/modules/NotAccess/NotAccess.tsx
  function NotAccess (line 4) | function NotAccess() {

FILE: client/src/modules/Notifications/components/Consents.tsx
  type Connection (line 10) | type Connection = {
  function Consents (line 16) | function Consents({

FILE: client/src/modules/Notifications/components/NotificationSettingsModal.tsx
  type Props (line 9) | type Props = {
  function NotificationSettingsModal (line 16) | function NotificationSettingsModal(props: Props) {

FILE: client/src/modules/Notifications/components/NotificationSettingsTable.tsx
  function NotificationSettingsTable (line 8) | function NotificationSettingsTable({
  function buildColumns (line 33) | function buildColumns(onEdit: (record: NotificationDto) => void, onDelet...

FILE: client/src/modules/Notifications/components/NotificationsUserSettingsTable.tsx
  function NotificationsTable (line 9) | function NotificationsTable({
  function buildColumns (line 32) | function buildColumns(

FILE: client/src/modules/Notifications/pages/AdminNotificationsPage/AdminNotificationsSettingsPage.tsx
  function AdminNotificationsPage (line 11) | function AdminNotificationsPage() {

FILE: client/src/modules/Notifications/pages/AdminNotificationsPage/index.tsx
  function AdminPage (line 6) | function AdminPage() {

FILE: client/src/modules/Notifications/pages/ConnectionConfirmedPage.tsx
  function ConnectionConfirmed (line 7) | function ConnectionConfirmed() {

FILE: client/src/modules/Notifications/pages/UserNotificationsSettingsPage.tsx
  function UserNotificationsPage (line 17) | function UserNotificationsPage() {

FILE: client/src/modules/Notifications/services/notifications.ts
  class NotificationsService (line 10) | class NotificationsService {
    method constructor (line 11) | constructor(
    method getNotifications (line 17) | async getNotifications(): Promise<NotificationDto[]> {
    method saveNotification (line 23) | async saveNotification(notification: UpdateNotificationDto) {
    method createNotification (line 27) | async createNotification(notification: UpdateNotificationDto) {
    method deleteNotification (line 31) | deleteNotification(id: string) {
    method saveUserNotifications (line 36) | async saveUserNotifications(notifications: UpdateNotificationUserSetti...
    method getUserNotificationSettings (line 40) | async getUserNotificationSettings() {
    method getUserConnections (line 45) | async getUserConnections() {
  type UserNotificationSettings (line 51) | type UserNotificationSettings = NotificationUserSettingsDto;
  type NotificationChannel (line 53) | enum NotificationChannel {
  type MessagePayload (line 59) | type MessagePayload = EmailPayload | TelegramPayload;
  type EmailPayload (line 61) | type EmailPayload = {
  type TelegramPayload (line 67) | type TelegramPayload = {
  type NotificationTemlate (line 72) | type NotificationTemlate = TelegramTemplate | EmailTemplate | DiscordTem...
  type TelegramTemplate (line 74) | type TelegramTemplate = {
  type EmailTemplate (line 78) | type EmailTemplate = {
  type DiscordTemplate (line 83) | type DiscordTemplate = {

FILE: client/src/modules/Opportunities/components/AvatarCv/index.tsx
  type Props (line 4) | type Props = {
  constant AVATAR_SIZE (line 8) | const AVATAR_SIZE = 80;

FILE: client/src/modules/Opportunities/components/EditCv/ContactsForm/index.tsx
  type Props (line 9) | type Props = {

FILE: client/src/modules/Opportunities/components/EditCv/GeneralInfoForm/index.tsx
  type Props (line 23) | type Props = {

FILE: client/src/modules/Opportunities/components/EditCv/VisibleCoursesForm/index.tsx
  type Props (line 9) | type Props = {

FILE: client/src/modules/Opportunities/components/EditCv/form-validation.ts
  method validator (line 19) | async validator(_, value) {
  method validator (line 81) | async validator(_, value) {

FILE: client/src/modules/Opportunities/components/EditCv/index.test.tsx
  type EditCvForms (line 17) | const enum EditCvForms {

FILE: client/src/modules/Opportunities/components/EditCv/index.tsx
  type Props (line 24) | type Props = {

FILE: client/src/modules/Opportunities/components/EditViewCv/index.test.tsx
  type CvComponents (line 4) | const enum CvComponents {

FILE: client/src/modules/Opportunities/components/EditViewCv/index.tsx
  type ResumeProps (line 7) | type ResumeProps = {

FILE: client/src/modules/Opportunities/components/ExpirationTooltip/index.tsx
  type Props (line 18) | type Props = {

FILE: client/src/modules/Opportunities/components/Link/index.tsx
  type Props (line 1) | type Props = {

FILE: client/src/modules/Opportunities/components/NameTitle/index.tsx
  type Props (line 4) | type Props = {

FILE: client/src/modules/Opportunities/components/NoConsentView/index.tsx
  type Props (line 7) | type Props = {
  method onOk (line 72) | onOk() {

FILE: client/src/modules/Opportunities/components/PublicLink/index.tsx
  type Props (line 5) | type Props = {

FILE: client/src/modules/Opportunities/components/ViewCv/AboutSection/index.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/Opportunities/components/ViewCv/ActionButtons/index.tsx
  type Props (line 11) | type Props = {

FILE: client/src/modules/Opportunities/components/ViewCv/BaseSection/index.tsx
  type Props (line 6) | type Props = React.PropsWithChildren<{

FILE: client/src/modules/Opportunities/components/ViewCv/ContactsSection/ContactsList/index.tsx
  type Props (line 22) | type Props = {
  type AllowedContacts (line 61) | type AllowedContacts = {

FILE: client/src/modules/Opportunities/components/ViewCv/ContactsSection/index.tsx
  type Props (line 4) | type Props = {

FILE: client/src/modules/Opportunities/components/ViewCv/CoursesSection/index.tsx
  type Props (line 13) | type Props = {
  function renderItem (line 33) | function renderItem(record: ResumeCourseDto) {

FILE: client/src/modules/Opportunities/components/ViewCv/FeedbackSection/index.tsx
  type Props (line 8) | type Props = {

FILE: client/src/modules/Opportunities/components/ViewCv/GratitudeSection/GratitudeList/index.tsx
  type Props (line 11) | type Props = {
  function GratitudeList (line 16) | function GratitudeList({ feedback, showCount }: Props) {

FILE: client/src/modules/Opportunities/components/ViewCv/GratitudeSection/index.tsx
  type Props (line 8) | type Props = {

FILE: client/src/modules/Opportunities/components/ViewCv/PersonalSection/index.tsx
  type Props (line 7) | type Props = {
  function PersonalSection (line 11) | function PersonalSection({ user }: Props) {

FILE: client/src/modules/Opportunities/components/ViewCv/index.tsx
  type Props (line 18) | type Props = {

FILE: client/src/modules/Opportunities/constants.ts
  type ExpirationState (line 1) | const enum ExpirationState {

FILE: client/src/modules/Opportunities/data/getContactsToRender.ts
  type EntryOf (line 3) | type EntryOf<T extends object> = { [K in keyof T]: [K, T[K]] }[keyof T];

FILE: client/src/modules/Opportunities/data/getPersonalToRender.tsx
  function getPersonalToRender (line 5) | function getPersonalToRender(user: UserData) {

FILE: client/src/modules/Opportunities/hooks/useResumeData.tsx
  type Props (line 5) | type Props = {
  function useResumeData (line 12) | function useResumeData({ githubId, actualTime }: Props) {

FILE: client/src/modules/Opportunities/hooks/useViewData.tsx
  type Props (line 6) | type Props = {
  function useViewData (line 10) | function useViewData({ initialData: resume }: Props) {

FILE: client/src/modules/Opportunities/models.ts
  type CourseData (line 4) | interface CourseData {
  type VisibleCourses (line 18) | type VisibleCourses = number[];
  type CourseDataShortened (line 20) | interface CourseDataShortened {
  type VisibleCoursesFormData (line 25) | interface VisibleCoursesFormData {
  type ContactType (line 29) | type ContactType = 'phone' | 'email' | 'skype' | 'telegram' | 'linkedin'...
  type UserData (line 31) | interface UserData {
  type Contacts (line 44) | type Contacts = {
  type FieldData (line 48) | interface FieldData {
  type AllUserCVData (line 56) | interface AllUserCVData extends Omit<UserData, 'uuid'>, Contacts {
  type UserDataToSubmit (line 60) | interface UserDataToSubmit extends Omit<UserData, 'startFrom'> {
  type AllDataToSubmit (line 65) | interface AllDataToSubmit extends UserDataToSubmit, Contacts {}
  type EditCVData (line 67) | interface EditCVData extends AllUserCVData {
  type GetFullCVData (line 73) | interface GetFullCVData extends AllUserCVData {
  type CVStudentStats (line 79) | interface CVStudentStats {
  type JobSeekerStudentStats (line 92) | interface JobSeekerStudentStats extends CVStudentStats {
  type JobSeekerData (line 96) | interface JobSeekerData {
  type CVFeedback (line 110) | interface CVFeedback {
  type JobSeekerFeedback (line 115) | interface JobSeekerFeedback {

FILE: client/src/modules/Opportunities/pages/EditPage/index.tsx
  function EditPage (line 18) | function EditPage() {

FILE: client/src/modules/Opportunities/pages/PublicPage/getServerSideProps.ts
  function getNestJsServerAxiosProps (line 9) | function getNestJsServerAxiosProps(token?: string): Partial<AxiosRequest...
  function getApiConfiguration (line 16) | function getApiConfiguration(token?: string): Configuration {

FILE: client/src/modules/Opportunities/pages/PublicPage/index.tsx
  type Props (line 7) | type Props = { data: ResumeDto };
  function PublicPage (line 9) | function PublicPage({ data }: PropsWithChildren<Props>) {

FILE: client/src/modules/Opportunities/transformers/transformFieldsData.ts
  constant LOCATIONS_COUNT (line 4) | const LOCATIONS_COUNT = 3;

FILE: client/src/modules/Profile/components/MentorEndorsement/MentorEndorsement.tsx
  type Props (line 9) | interface Props {
  function MentorEndorsement (line 17) | function MentorEndorsement(props: Props) {
  function removeNull (line 72) | function removeNull(obj: object) {
  function cleanData (line 76) | function cleanData(obj: object) {

FILE: client/src/modules/Prompts/components/PromptModal.tsx
  type Props (line 5) | type Props = {
  function PromptModal (line 13) | function PromptModal({ open, onCancel, loadData, data }: Props) {

FILE: client/src/modules/Prompts/components/PromptTable.tsx
  type Props (line 7) | type Props = {

FILE: client/src/modules/Registry/components/Cards/AdditionalInfo/AdditionalInfo.test.tsx
  type Values (line 25) | type Values = typeof mockValues;

FILE: client/src/modules/Registry/components/Cards/AdditionalInfo/AdditionalInfo.tsx
  type Props (line 12) | type Props = {
  function AdditionalInfo (line 21) | function AdditionalInfo({ courses, onPrevious }: Props) {

FILE: client/src/modules/Registry/components/Cards/ContactInfo/ContactInfo.test.tsx
  type Values (line 15) | type Values = typeof mockValues | Record<string, unknown>;

FILE: client/src/modules/Registry/components/Cards/ContactInfo/ContactInfo.tsx
  function ContactInfo (line 23) | function ContactInfo() {

FILE: client/src/modules/Registry/components/Cards/CourseDetails/CourseDetails.tsx
  type Props (line 8) | type Props = {
  function CourseDetails (line 12) | function CourseDetails({ courses }: Props) {

FILE: client/src/modules/Registry/components/Cards/Disciplines/Disciplines.tsx
  type Props (line 6) | type Props = {
  function Disciplines (line 14) | function Disciplines({ disciplines }: Props) {

FILE: client/src/modules/Registry/components/Cards/PersonalInfo/PersonalInfo.test.tsx
  type Values (line 28) | type Values = typeof mockValues | Record<string, unknown>;

FILE: client/src/modules/Registry/components/Cards/PersonalInfo/PersonalInfo.tsx
  type Props (line 16) | type Props = {
  function PersonalInfo (line 24) | function PersonalInfo({ location, setLocation, isStudentForm }: Props) {

FILE: client/src/modules/Registry/components/Cards/Preferences/Preferences.tsx
  function Preferences (line 26) | function Preferences() {

FILE: client/src/modules/Registry/components/CourseCertificateAlert/CourseCertificateAlert.tsx
  type CourseCertificateAlertProps (line 3) | type CourseCertificateAlertProps = {
  function CourseCertificateAlert (line 7) | function CourseCertificateAlert({ certificateDiscipline = 'any' }: Cours...

FILE: client/src/modules/Registry/components/CourseLabel/CourseLabel.tsx
  type Props (line 6) | type Props = {
  function CourseLabel (line 11) | function CourseLabel({ course, isStudentForm }: Props) {

FILE: client/src/modules/Registry/components/DataProcessingCheckbox/DataProcessingCheckbox.test.tsx
  type Checkbox (line 7) | enum Checkbox {

FILE: client/src/modules/Registry/components/DataProcessingCheckbox/DataProcessingCheckbox.tsx
  type Props (line 6) | type Props = {
  function DataProcessingCheckbox (line 10) | function DataProcessingCheckbox({ isStudentForm }: Props) {

FILE: client/src/modules/Registry/components/Footer/Footer.tsx
  function Footer (line 7) | function Footer() {

FILE: client/src/modules/Registry/components/FormButtons/FormButtons.test.tsx
  type Props (line 6) | type Props = {

FILE: client/src/modules/Registry/components/FormButtons/FormButtons.tsx
  type Props (line 4) | type Props = {
  function FormButtons (line 9) | function FormButtons({ onPrevious, submitTitle = 'Submit' }: Props) {

FILE: client/src/modules/Registry/components/FormCard/FormCard.tsx
  type Props (line 4) | type Props = {
  function FormCard (line 9) | function FormCard({ title, children }: Props) {

FILE: client/src/modules/Registry/components/FormSections/DoneSection/DoneSection.tsx
  type Props (line 7) | type Props = {
  function DoneSection (line 13) | function DoneSection({ courseName }: Props) {
  function svg (line 76) | function svg() {
  function ArrowIcon (line 87) | function ArrowIcon(props: Partial<CustomIconComponentProps>) {

FILE: client/src/modules/Registry/components/FormSections/GeneralSection/GeneralSection.tsx
  type Props (line 7) | type Props = {
  function GeneralSection (line 13) | function GeneralSection({ location, setLocation, courses }: Props) {

FILE: client/src/modules/Registry/components/FormSections/MentorshipSection/MentorshipSection.tsx
  type Props (line 6) | type Props = {
  function MentorshipSection (line 12) | function MentorshipSection({ courses, disciplines, onPrevious }: Props) {

FILE: client/src/modules/Registry/components/Header/Header.tsx
  type Props (line 6) | type Props = {
  function Header (line 10) | function Header({ title }: Props) {

FILE: client/src/modules/Registry/components/LanguagesMentoring/LanguagesMentoring.tsx
  type Props (line 5) | type Props = {
  function LanguagesMentoring (line 9) | function LanguagesMentoring({ isStudentForm }: Props) {

FILE: client/src/modules/Registry/components/NoCourses/NoCourses.tsx
  function NoCourses (line 4) | function NoCourses() {

FILE: client/src/modules/Registry/components/RegistrationForm/RegistrationForm.tsx
  type Props (line 9) | type Props = {
  function RegistrationForm (line 21) | function RegistrationForm({ form, handleSubmit, steps, currentStep, init...

FILE: client/src/modules/Registry/constants/index.ts
  constant RSSCHOOL_BOT_LINK (line 3) | const RSSCHOOL_BOT_LINK = 'https://t.me/rsschool_bot?start';
  constant DATA_PROCESSING_TEXT (line 4) | const DATA_PROCESSING_TEXT =
  constant ERROR_MESSAGES (line 11) | const ERROR_MESSAGES = {
  constant TOOLTIPS (line 22) | const TOOLTIPS = {
  constant FORM_TITLES (line 29) | const FORM_TITLES = {
  constant PLACEHOLDERS (line 34) | const PLACEHOLDERS = {
  constant EXTRAS (line 49) | const EXTRAS = {
  constant LABELS (line 54) | const LABELS = {
  constant CARD_TITLES (line 77) | const CARD_TITLES = {
  constant VALIDATION_RULES (line 86) | const VALIDATION_RULES: Rule[] = [
  constant DEFAULT_FORM_ITEM_LAYOUT (line 126) | const DEFAULT_FORM_ITEM_LAYOUT = {

FILE: client/src/modules/Registry/hooks/useFormLayout/useFormLayout.ts
  function useFormLayout (line 6) | function useFormLayout() {

FILE: client/src/modules/Registry/hooks/useMentorData/useMentorData.tsx
  type FormData (line 18) | type FormData = ReturnType<typeof getInitialValues>;
  function useMentorData (line 25) | function useMentorData(courseAlias?: string | string[]) {
  function getInitialValues (line 146) | function getInitialValues(
  function getActiveCourses (line 195) | function getActiveCourses(courses: CourseDto[], courseAlias?: string | s...

FILE: client/src/modules/Registry/hooks/useStudentData/useStudentData.tsx
  type StudentFormData (line 19) | type StudentFormData = ReturnType<typeof getInitialValues>;
  type IdName (line 21) | type IdName = {
  function useStudentData (line 31) | function useStudentData(githubId: string, courseAlias?: string) {
  function getInitialValues (line 202) | function getInitialValues(
  function enrolledOtherCourses (line 218) | function enrolledOtherCourses(studentStats: StudentStats[] | undefined, ...
  function isCourseOpenForRegistry (line 230) | function isCourseOpenForRegistry(registeredCourses: IdName[]) {
  function isCourseOpenForRegistryWithAlias (line 240) | function isCourseOpenForRegistryWithAlias(courseAlias?: string) {
  function isCourseAvailableForRegistration (line 244) | function isCourseAvailableForRegistration(course: Course, registeredCour...
  function sortByStartDate (line 261) | function sortByStartDate(a: Course, b: Course) {
  function getStatus (line 265) | function getStatus(course: Course) {
  function getMissingDisciplines (line 269) | async function getMissingDisciplines(

FILE: client/src/modules/Registry/pages/Mentor/Mentor.tsx
  function MentorRegistry (line 6) | function MentorRegistry() {

FILE: client/src/modules/Registry/pages/Student/Student.tsx
  function StudentRegistry (line 8) | function StudentRegistry() {

FILE: client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.test.tsx
  constant PROPS_MOCK (line 15) | const PROPS_MOCK: AdditionalActionsProps = {
  function generateMenuItems (line 78) | function generateMenuItems(): MenuItemType[] {

FILE: client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.tsx
  type MenuItemType (line 9) | type MenuItemType = Required<MenuProps>['items'][number];
  type MenuItemClickHandler (line 10) | type MenuItemClickHandler = Required<MenuProps>['onClick'];
  type AdditionalActionsProps (line 12) | interface AdditionalActionsProps {
  function onCalendarCopyLink (line 50) | function onCalendarCopyLink() {

FILE: client/src/modules/Schedule/components/EventDetails/EventDetails.tsx
  type EventDetailsProps (line 13) | interface EventDetailsProps {
  function EventDetails (line 21) | function EventDetails({ eventData, alias, isAdmin, isPreview, onEdit }: ...

FILE: client/src/modules/Schedule/components/FilteredTags/FilteredTags.test.tsx
  function getTagLabel (line 91) | function getTagLabel(tag: CourseScheduleItemDto['tag']) {

FILE: client/src/modules/Schedule/components/FilteredTags/FilteredTags.tsx
  type FilteredTagsProps (line 6) | type FilteredTagsProps = {

FILE: client/src/modules/Schedule/components/SettingsDrawer/ChangeTagColors.tsx
  type ChangeTagColorProps (line 10) | interface ChangeTagColorProps {

FILE: client/src/modules/Schedule/components/SettingsDrawer/SettingsDrawer.tsx
  type SettingsDrawerProps (line 10) | interface SettingsDrawerProps {
  constant TITLE (line 15) | const TITLE = 'Schedule settings';
  function SettingsDrawer (line 17) | function SettingsDrawer({ settings, tags }: SettingsDrawerProps) {

FILE: client/src/modules/Schedule/components/SettingsDrawer/ShowTableColumns.tsx
  constant AVAILABLE_COLUMNS (line 10) | const AVAILABLE_COLUMNS = COLUMNS.filter(column => CONFIGURABLE_COLUMNS....
  type ShowTableColumnsProps (line 12) | interface ShowTableColumnsProps {
  function ShowTableColumns (line 17) | function ShowTableColumns({ columnsHidden, setColumnsHidden }: ShowTable...

FILE: client/src/modules/Schedule/components/SettingsDrawer/TimeZone.tsx
  type TimeZoneProps (line 9) | interface TimeZoneProps {
  function TimeZone (line 14) | function TimeZone({ timezone, setTimezone }: TimeZoneProps) {

FILE: client/src/modules/Schedule/components/SettingsPanel/SettingsPanel.test.tsx
  constant PROPS_MOCK (line 4) | const PROPS_MOCK: SettingsPanelProps = {

FILE: client/src/modules/Schedule/components/SettingsPanel/SettingsPanel.tsx
  type SettingsPanelProps (line 16) | interface SettingsPanelProps {
  type SettingsButtons (line 30) | enum SettingsButtons {
  function SettingsPanel (line 40) | function SettingsPanel({

FILE: client/src/modules/Schedule/components/StatusTabs/StatusTabs.test.tsx
  function generateStatuses (line 131) | function generateStatuses(count = 3, statusTypeAndCount: Record<string, ...

FILE: client/src/modules/Schedule/components/StatusTabs/StatusTabs.tsx
  type Status (line 6) | type Status = string;
  type StatusTabsProps (line 8) | type StatusTabsProps = PropsWithChildren & {

FILE: client/src/modules/Schedule/components/TableView/TableView.test.tsx
  constant PROPS_SETTINGS_MOCK (line 13) | const PROPS_SETTINGS_MOCK: ScheduleSettings = {
  function generateCourseData (line 220) | function generateCourseData(

FILE: client/src/modules/Schedule/components/TableView/TableView.tsx
  type TableViewProps (line 132) | interface TableViewProps {
  type CombinedFilter (line 139) | type CombinedFilter = {
  type FilterTag (line 146) | type FilterTag = {
  function TableView (line 155) | function TableView({ data, settings, statusFilter = ALL_TAB_KEY, mobileV...

FILE: client/src/modules/Schedule/components/TableView/renderers.tsx
  function statusRenderer (line 7) | function statusRenderer(value: CourseScheduleItemDtoStatusEnum) {
  function renderStatusWithStyle (line 14) | function renderStatusWithStyle(statusName: CourseScheduleItemDtoStatusEn...
  function renderTagWithStyle (line 22) | function renderTagWithStyle(tagName: CourseScheduleItemDto['tag'], tagCo...

FILE: client/src/modules/Schedule/constants.ts
  type ColumnName (line 3) | enum ColumnName {
  type ColumnKey (line 15) | enum ColumnKey {
  constant COLUMNS (line 26) | const COLUMNS: { key: ColumnKey; name: ColumnName }[] = [
  type LocalStorageKeys (line 37) | enum LocalStorageKeys {
  constant TAG_NAME_MAP (line 48) | const TAG_NAME_MAP: Record<CourseScheduleItemDto['tag'], string> = {
  constant SCHEDULE_STATUSES (line 59) | const SCHEDULE_STATUSES = Object.keys(CourseScheduleItemDtoStatusEnum).m...
  constant TAGS (line 64) | const TAGS = Object.values(CourseScheduleItemDtoTagEnum).map((value: Cou...
  constant CONFIGURABLE_COLUMNS (line 69) | const CONFIGURABLE_COLUMNS = [
  constant DEADLINE_COLOR (line 78) | const DEADLINE_COLOR = '#ff0000';
  constant DEFAULT_COLOR (line 79) | const DEFAULT_COLOR = '#308e00';
  constant DEFAULT_TAG_COLOR_MAP (line 81) | const DEFAULT_TAG_COLOR_MAP: Record<CourseScheduleItemDto['tag'], string...
  constant SPECIAL_TASK_TYPES (line 92) | const SPECIAL_TASK_TYPES = {
  constant SPECIAL_ENTITY_TAGS (line 97) | const SPECIAL_ENTITY_TAGS = [
  constant CHECKER_TYPES (line 115) | const CHECKER_TYPES = {
  constant ALL_TAB_KEY (line 123) | const ALL_TAB_KEY = 'all';
  constant ALL_TAB_LABEL (line 124) | const ALL_TAB_LABEL = 'All';

FILE: client/src/modules/Schedule/hooks/useScheduleSettings.ts
  type ScheduleSettings (line 5) | interface ScheduleSettings {

FILE: client/src/modules/Schedule/pages/SchedulePage/index.tsx
  function SchedulePage (line 30) | function SchedulePage() {

FILE: client/src/modules/Schedule/utils.ts
  function getTaskStatusColor (line 15) | function getTaskStatusColor(value: CourseScheduleItemDtoStatusEnum) {

FILE: client/src/modules/Score/components/ExportCsvButton/index.tsx
  type Props (line 4) | type Props = {
  function ExportCsvButton (line 9) | function ExportCsvButton(props: Props) {

FILE: client/src/modules/Score/components/ScoreTable/ScoreTableTabs.tsx
  type Props (line 12) | type Props = {

FILE: client/src/modules/Score/components/ScoreTable/Summary.tsx
  type SummaryProps (line 6) | type SummaryProps = {

FILE: client/src/modules/Score/components/ScoreTable/index.tsx
  type Props (line 22) | type Props = CoursePageProps & {
  type TableScoreOrder (line 29) | type TableScoreOrder = SorterResult<ScoreStudentDto> | SorterResult<Scor...
  type ScoreTableFiltersModified (line 31) | interface ScoreTableFiltersModified extends Omit<ScoreTableFilters, 'act...
  type StudentsState (line 34) | type StudentsState = {
  function ScoreTable (line 43) | function ScoreTable(props: Props) {
  function getTableWidth (line 260) | function getTableWidth(columnsCount: number) {

FILE: client/src/modules/Score/components/SettingsDrawer/index.tsx
  type Props (line 13) | type Props = {
  function SettingsDrawer (line 20) | function SettingsDrawer(props: Props) {

FILE: client/src/modules/Score/data/getColumns.tsx
  type Props (line 8) | type Props = {
  function getColumns (line 21) | function getColumns(props: Props): ColumnType<ScoreStudentDto>[] {

FILE: client/src/modules/Score/data/getExportCsvUrl.ts
  function getExportCsvUrl (line 3) | function getExportCsvUrl(courseId: number, cityName?: string | string[],...

FILE: client/src/modules/Score/data/getTaskColumns.tsx
  function getTaskColumns (line 7) | function getTaskColumns(courseTasks: CourseTaskDto[]) {

FILE: client/src/modules/Score/data/isExportEnabled.ts
  function isExportEnabled (line 6) | function isExportEnabled({ session, course }: { session?: Session; cours...

FILE: client/src/modules/Score/hooks/types.ts
  type ScoreTableFilters (line 1) | type ScoreTableFilters = {
  type ScoreOrderField (line 9) | type ScoreOrderField =
  type ScoreOrder (line 20) | type ScoreOrder = {

FILE: client/src/modules/Score/hooks/useScorePaging.tsx
  function useScorePaging (line 9) | function useScorePaging(router: NextRouter, courseService: CourseService...

FILE: client/src/modules/Score/pages/ScorePage/index.tsx
  function ScorePage (line 7) | function ScorePage() {

FILE: client/src/modules/StudentDashboard/components/AvailableReviewCard/AvailableReviewCard.tsx
  type Props (line 5) | type Props = {
  function AvailableReviewCard (line 11) | function AvailableReviewCard({ availableReviews, courseAlias }: Props) {

FILE: client/src/modules/StudentDashboard/components/CommonDashboardCard.tsx
  type Props (line 8) | type Props = Omit<CardProps, 'content'> & {
  type State (line 14) | type State = {
  class CommonCard (line 18) | class CommonCard extends React.Component<Props, State> {
    method render (line 24) | render() {

FILE: client/src/modules/StudentDashboard/components/MainStatsCard.tsx
  constant DEFAULT_POSITION (line 6) | const DEFAULT_POSITION = 999999;
  type Props (line 10) | type Props = {
  function MainStatsCard (line 18) | function MainStatsCard({ totalScore, position, maxCourseScore, totalStud...
  constant STYLE (line 62) | const STYLE: Record<string, React.CSSProperties> = {

FILE: client/src/modules/StudentDashboard/components/MentorCard/MentorCard.test.tsx
  constant MENTOR_MOCK (line 4) | const MENTOR_MOCK = {
  constant PROPS_MOCK (line 19) | const PROPS_MOCK: MentorCardProps = {

FILE: client/src/modules/StudentDashboard/components/MentorCard/MentorCard.tsx
  type MentorCardProps (line 7) | type MentorCardProps = {
  constant ASSERTION (line 14) | const ASSERTION =
  function MentorCard (line 17) | function MentorCard({ mentor, courseId }: MentorCardProps) {

FILE: client/src/modules/StudentDashboard/components/MentorInfo/MentorInfo.tsx
  type MentorContact (line 9) | interface MentorContact {
  type Props (line 17) | interface Props {
  function MentorInfo (line 21) | function MentorInfo({ mentor }: Props) {

FILE: client/src/modules/StudentDashboard/components/NextEventCard/NextEventCard.test.tsx
  constant NEXT_EVENTS (line 5) | const NEXT_EVENTS = generateAvailableTasks();
  constant PROPS_MOCK (line 7) | const PROPS_MOCK = {
  function generateAvailableTasks (line 28) | function generateAvailableTasks(count = 3): CourseScheduleItemDto[] {

FILE: client/src/modules/StudentDashboard/components/NextEventCard/NextEventCard.tsx
  type Props (line 10) | type Props = {
  function NextEventCard (line 15) | function NextEventCard({ nextEvents, courseAlias }: Props) {

FILE: client/src/modules/StudentDashboard/components/NextEventCard/renderers.tsx
  type AvailableTasksColumnKey (line 8) | enum AvailableTasksColumnKey {
  function getAvailableTasksColumns (line 14) | function getAvailableTasksColumns(): ColumnType<CourseScheduleItemDto>[] {
  function renderEndDate (line 36) | function renderEndDate(value: string, row: CourseScheduleItemDto) {

FILE: client/src/modules/StudentDashboard/components/RepositoryCard.tsx
  type Props (line 6) | type Props = {
  function RepositoryCard (line 15) | function RepositoryCard(props: Props) {

FILE: client/src/modules/StudentDashboard/components/SubmitTaskSolution/SubmitTaskSolution.tsx
  type TaskSolutionModalProps (line 7) | interface TaskSolutionModalProps {
  function SubmitTaskSolution (line 11) | function SubmitTaskSolution({ courseId }: TaskSolutionModalProps) {

FILE: client/src/modules/StudentDashboard/components/TasksChart.tsx
  type Item (line 7) | type Item = { status: string; value: number };
  type Props (line 9) | type Props = {
  function TasksChart (line 14) | function TasksChart({ data, onItemSelected }: Props) {

FILE: client/src/modules/StudentDashboard/components/TasksStatsCard.tsx
  type TaskStat (line 11) | type TaskStat = CourseScheduleItemDto & { comment?: string; githubPrUri?...
  type Props (line 13) | type Props = {
  function TasksStatsCard (line 18) | function TasksStatsCard(props: Props) {

FILE: client/src/modules/StudentDashboard/components/TasksStatsModal.tsx
  type Props (line 7) | type Props = {
  function TasksStatsModal (line 15) | function TasksStatsModal(props: Props) {

FILE: client/src/modules/StudentDashboard/hooks/useDashboardData.ts
  function useDashboardData (line 21) | function useDashboardData(courseId: number, githubId: string) {

FILE: client/src/modules/StudentDashboard/hooks/useSubmitTaskSolution.test.ts
  constant COURSE_ID (line 6) | const COURSE_ID = 10;
  function generateCourseTasks (line 87) | function generateCourseTasks(count = 3): CourseTaskDto[] {

FILE: client/src/modules/StudentDashboard/hooks/useSubmitTaskSolution.ts
  type Action (line 11) | type Action = {
  type State (line 16) | type State = {
  function reducer (line 24) | function reducer(state: State, action: Action): State {
  function useSubmitTaskSolution (line 43) | function useSubmitTaskSolution(courseId: number) {

FILE: client/src/modules/Students/Pages/Students.tsx
  type StudentsState (line 16) | type StudentsState = {

FILE: client/src/modules/Students/components/CourseItem/index.tsx
  type Props (line 7) | type Props = {

FILE: client/src/modules/Students/components/StudentInfo/index.tsx
  type Props (line 13) | type Props = {
  function StudentInfo (line 21) | function StudentInfo(props: Props) {

FILE: client/src/modules/Students/components/StudentsTable/index.tsx
  type Props (line 5) | type Props = {
  function StudentsTable (line 14) | function StudentsTable({

FILE: client/src/modules/Students/components/StudentsTable/renderers.tsx
  type ColumnKey (line 7) | enum ColumnKey {
  type ColumnName (line 16) | enum ColumnName {

FILE: client/src/modules/Tasks/components/CrossCheckTaskCriteriaPanel/CrossCheckTaskCriteriaPanel.tsx
  type Props (line 14) | type Props = {
  function CrossCheckTaskCriteriaPanel (line 19) | function CrossCheckTaskCriteriaPanel({ dataCriteria, setDataCriteria }: ...

FILE: client/src/modules/Tasks/components/GitHubPanel/GitHubPanel.tsx
  function GitHubPanel (line 5) | function GitHubPanel() {

FILE: client/src/modules/Tasks/components/JsonAttributesPanel/JsonAttributesPanel.tsx
  function JsonAttributesPanel (line 4) | function JsonAttributesPanel() {

FILE: client/src/modules/Tasks/components/TaskModal/TaskModal.test.tsx
  function generateData (line 137) | function generateData(isEmpty = false): ModalProps {

FILE: client/src/modules/Tasks/components/TaskModal/TaskModal.tsx
  type ModalProps (line 20) | type ModalProps = {
  function TaskModal (line 32) | function TaskModal({

FILE: client/src/modules/Tasks/components/TaskSettings/TaskSettings.tsx
  type Props (line 10) | type Props = {
  function TaskSettings (line 18) | function TaskSettings({ dataCriteria, taskType, setDataCriteria }: Props) {
  function getSettings (line 82) | function getSettings(taskType?: TaskDtoTypeEnum): Settings {
  function isCollapsible (line 94) | function isCollapsible(isPanelEnabled: boolean) {

FILE: client/src/modules/Tasks/components/TasksTable/TasksTable.tsx
  function getColumns (line 16) | function getColumns(
  type Props (line 95) | type Props = {

FILE: client/src/modules/Tasks/constants.ts
  constant LABELS (line 3) | const LABELS = {
  constant TASK_SETTINGS_HEADERS (line 17) | const TASK_SETTINGS_HEADERS = {
  constant PLACEHOLDERS (line 23) | const PLACEHOLDERS = {
  constant ERROR_MESSAGES (line 36) | const ERROR_MESSAGES = {
  constant MODAL_TITLES (line 46) | const MODAL_TITLES: Record<ModalFormMode, string> = {

FILE: client/src/modules/Tasks/pages/TasksPage/TasksPage.tsx
  function TasksPage (line 26) | function TasksPage() {
  function createRecord (line 138) | function createRecord({
  function prepareValues (line 175) | function prepareValues(task: TaskDto) {

FILE: client/src/modules/Tasks/types.ts
  type FormValues (line 4) | type FormValues = Partial<Omit<TaskDto, 'discipline' | 'attributes'> & {...
  type ColumnName (line 6) | const enum ColumnName {
  type Criteria (line 20) | const enum Criteria {
  type Settings (line 26) | type Settings = Record<Criteria, boolean>;
  type SettingsSet (line 28) | type SettingsSet = Record<Criteria, TaskDtoTypeEnum[]>;

FILE: client/src/modules/Tasks/utils/test-utils.ts
  constant COURSE_NAME_MOCK (line 4) | const COURSE_NAME_MOCK = 'RS2023';
  function generateTasksData (line 6) | function generateTasksData(count = 3): TaskDto[] {

FILE: client/src/modules/TeamDistribution/components/SubmitScoreModal/SubmitScoreModal.tsx
  type Props (line 11) | type Props = {
  function SubmitScoreModal (line 18) | function SubmitScoreModal({ distribution, onClose }: Props) {

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/Actions.test.tsx
  function renderActions (line 15) | function renderActions(distribution: TeamDistributionDto, isManager = fa...

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/Actions.tsx
  type Props (line 11) | type Props = {
  function Actions (line 30) | function Actions({

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/CardTitle.tsx
  type Props (line 7) | type Props = {
  function CardTitle (line 13) | function CardTitle({ distribution }: Props) {

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/DistributionPeriod.tsx
  type Props (line 5) | type Props = {
  function DistributionPeriod (line 12) | function DistributionPeriod({ startDate, endDate }: Props) {

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/TeamDistributionCard.test.tsx
  function renderCard (line 20) | function renderCard(distribution: TeamDistributionDto, isManager = false) {

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/TeamDistributionCard.tsx
  type Props (line 7) | type Props = {
  function TeamDistributionCard (line 19) | function TeamDistributionCard({

FILE: client/src/modules/TeamDistribution/components/TeamDistributionCard/renderers.tsx
  type RegistrationStatusProps (line 7) | type RegistrationStatusProps = {
  type MinScoreProps (line 25) | type MinScoreProps = {

FILE: client/src/modules/TeamDistribution/components/TeamDistributionModal/TeamDistributionModal.tsx
  type Props (line 13) | type Props = {
  type FormState (line 27) | interface FormState extends TeamDistributionDto {
  function getInitialValues (line 36) | function getInitialValues(data: TeamDistributionDto) {
  function TeamDistributionModal (line 81) | function TeamDistributionModal({ data, onCancel, courseId, onSubmit }: P...

FILE: client/src/modules/TeamDistribution/components/WelcomeCard/WelcomeCard.tsx
  type Props (line 8) | type Props = {
  function WelcomeCard (line 13) | function WelcomeCard({ isManager, handleCreateTeamDistribution }: Props) {

FILE: client/src/modules/TeamDistribution/hooks/useSubmitTeamScore.tsx
  function useSubmitTeamScore (line 7) | function useSubmitTeamScore(courseId: number, teamDistributionId: number) {

FILE: client/src/modules/TeamDistribution/pages/TeamDistributions/TeamDistributions.tsx
  function TeamDistributions (line 15) | function TeamDistributions() {

FILE: client/src/modules/Teams/Pages/Teams.tsx
  function Teams (line 27) | function Teams() {

FILE: client/src/modules/Teams/components/JoinTeamModal/JoinTeamModal.tsx
  type Props (line 5) | type Props = {
  function JoinTeamModal (line 17) | function JoinTeamModal({ onCancel, onSubmit }: Props) {

FILE: client/src/modules/Teams/components/MyTeamSection/MyTeamSection.tsx
  type Props (line 11) | type Props = {
  function MyTeamSection (line 23) | function MyTeamSection({

FILE: client/src/modules/Teams/components/StudentsTable/StudentsTable.tsx
  type Props (line 7) | type Props = {
  function StudentsTable (line 17) | function StudentsTable({

FILE: client/src/modules/Teams/components/StudentsTable/renderers.tsx
  function renderName (line 10) | function renderName({ fullName, cvUuid, id }: TeamDistributionStudentDto...
  function renderGithub (line 34) | function renderGithub(_v: string, { githubId }: TeamDistributionStudentD...
  function renderPosition (line 42) | function renderPosition(_v: string, { rank }: TeamDistributionStudentDto) {
  function renderLocation (line 46) | function renderLocation(_v: string, { location }: TeamDistributionStuden...
  function renderEmail (line 50) | function renderEmail(_v: string, { email }: TeamDistributionStudentDto) {
  function renderDiscord (line 54) | function renderDiscord(_v: string, { discord }: TeamDistributionStudentD...
  function renderStudent (line 58) | function renderStudent(_v: string, student: TeamDistributionStudentDto) {
  function renderContacts (line 68) | function renderContacts(_v: string, student: TeamDistributionStudentDto) {
  function renderDeleteAction (line 77) | function renderDeleteAction(
  constant DISPLAY_TABLE_BREAKPOINTS (line 85) | const DISPLAY_TABLE_BREAKPOINTS: Breakpoint[] = ['md'];
  constant DISPLAY_TABLE_MOBILE_BREAKPOINT (line 86) | const DISPLAY_TABLE_MOBILE_BREAKPOINT: Breakpoint[] = ['xs'];

FILE: client/src/modules/Teams/components/StudentsWithoutTeamSection/StudentsWithoutTeamSection.tsx
  type Props (line 11) | type Props = {
  type StudentsState (line 17) | type StudentsState = {
  function StudentsWithoutTeamSection (line 28) | function StudentsWithoutTeamSection({ distribution, isManager, reloadDis...

FILE: client/src/modules/Teams/components/TeamModal/TeamModal.test.tsx
  function renderModal (line 7) | function renderModal() {

FILE: client/src/modules/Teams/components/TeamModal/TeamModal.tsx
  type Props (line 9) | type Props = {
  function TeamModal (line 26) | function TeamModal({ onCancel, onSubmit, data, courseId, isManager, maxS...

FILE: client/src/modules/Teams/components/TeamsHeader/ActionCard.tsx
  type Props (line 5) | type Props = {
  function ActionCard (line 12) | function ActionCard({ title, text, buttonCaption, onClick }: Props) {

FILE: client/src/modules/Teams/components/TeamsHeader/TeamsHeader.tsx
  type Props (line 11) | type Props = {
  function TeamsHeader (line 23) | function TeamsHeader({

FILE: client/src/modules/Teams/components/TeamsSection/TeamsSection.tsx
  type Props (line 11) | type Props = {
  type TeamsState (line 17) | type TeamsState = {
  function TeamSection (line 26) | function TeamSection({ distribution, toggleTeamModal, isManager }: Props) {

FILE: client/src/modules/Teams/components/TeamsSection/renderers.tsx
  function renderName (line 10) | function renderName(_v: string, { name }: TeamDto) {
  function renderDescription (line 14) | function renderDescription(_v: string, { description }: TeamDto) {
  function renderMemberCount (line 18) | function renderMemberCount({ students }: TeamDto, membersCount: number) {
  function renderAction (line 26) | function renderAction(onEditTeam: () => void) {
  function renderTeam (line 39) | function renderTeam(team: TeamDto, distribution: TeamDistributionDetaile...
  constant DISPLAY_TABLE_BREAKPOINTS (line 49) | const DISPLAY_TABLE_BREAKPOINTS: Breakpoint[] = ['sm'];
  constant DISPLAY_TABLE_MOBILE_BREAKPOINT (line 50) | const DISPLAY_TABLE_MOBILE_BREAKPOINT: Breakpoint[] = ['xs'];

FILE: client/src/modules/Teams/constants.ts
  type TeamsTableColumnKey (line 1) | enum TeamsTableColumnKey {
  type TeamsTableColumnName (line 9) | enum TeamsTableColumnName {
  type StudentsTableColumnKey (line 17) | enum StudentsTableColumnKey {
  type StudentsTableColumnName (line 29) | enum StudentsTableColumnName {

FILE: client/src/modules/Teams/hooks/useDistribution/useDistribution.ts
  function useDistribution (line 7) | function useDistribution(courseId: number, teamDistributionId: number) {

FILE: client/src/modules/UserGroupsAdmin/components/UserGroupsModal.tsx
  type Props (line 7) | type Props = {
  function UserGroupsModal (line 19) | function UserGroupsModal({ data, title, submit, cancel, getInitialValues...

FILE: client/src/modules/UserGroupsAdmin/components/UserGroupsTable.tsx
  type Props (line 7) | type Props = {
  function UserGroupsTable (line 18) | function UserGroupsTable({ data, onEdit, onDelete }: Props) {
  function getColumns (line 31) | function getColumns(handleEditItem: (record: UserGroupDto) => void, hand...

FILE: client/src/modules/UserGroupsAdmin/hooks/useUserGroups.ts
  function useUserGroups (line 9) | function useUserGroups() {

FILE: client/src/modules/UserGroupsAdmin/pages/UserGroupsAdminPage/UserGroupsAdminPage.tsx
  type ModalAction (line 12) | enum ModalAction {
  function UserGroupsAdminPage (line 17) | function UserGroupsAdminPage() {

FILE: client/src/modules/UsersAdmin/hooks/useUsersSearch.ts
  function useUsersSearch (line 6) | function useUsersSearch() {

FILE: client/src/modules/UsersAdmin/pages/UsersAdminPage/UsersAdminPage.tsx
  function UsersAdminPage (line 10) | function UsersAdminPage() {
  function UserField (line 74) | function UserField({ label, value }: { label?: string; value: string | s...

FILE: client/src/pages/404.tsx
  function NotFoundPage (line 6) | function NotFoundPage() {
  function Page (line 22) | function Page() {

FILE: client/src/pages/_app.tsx
  class RsSchoolApp (line 11) | class RsSchoolApp extends App {
    method render (line 12) | render() {

FILE: client/src/pages/_document.tsx
  class AppDocument (line 3) | class AppDocument extends Document {
    method render (line 4) | render() {

FILE: client/src/pages/admin/auto-test-task/[taskId].tsx
  function Page (line 13) | function Page() {

FILE: client/src/pages/admin/auto-test.tsx
  constant RESPONSIVE_COLUMNS (line 10) | const RESPONSIVE_COLUMNS: ColProps = {
  function Page (line 20) | function Page() {

FILE: client/src/pages/admin/courses.tsx
  function Page (line 22) | function Page() {
  function getColumns (line 69) | function getColumns(handleEditItem: any) {

FILE: client/src/pages/admin/mentor-registry.tsx
  type NotificationType (line 33) | type NotificationType = 'success' | 'info' | 'warning' | 'error';
  type ModalDataMode (line 35) | enum ModalDataMode {
  type ModalData (line 43) | type ModalData = Partial<{
  type FormData (line 48) | type FormData = {
  function Page (line 56) | function Page() {

FILE: client/src/pages/admin/registrations.tsx
  constant PAGINATION (line 13) | const PAGINATION = 200;
  constant DEFAULT_STATISTICS (line 14) | const DEFAULT_STATISTICS = { approved: 0, rejected: 0, pending: 0 };
  type Stats (line 16) | type Stats = {
  type Registration (line 22) | interface Registration {
  function Page (line 33) | function Page() {

FILE: client/src/pages/applicants/index.tsx
  function ApplicantsPage (line 14) | function ApplicantsPage() {
  function Page (line 141) | function Page() {

FILE: client/src/pages/course/admin/events.tsx
  function Page (line 25) | function Page() {
  function getColumns (line 110) | function getColumns(

FILE: client/src/pages/course/admin/interviews.tsx
  function Page (line 22) | function Page() {

FILE: client/src/pages/course/admin/mentors.tsx
  type Stats (line 15) | type 
Condensed preview — 1783 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,601K chars).
[
  {
    "path": ".agents/skills/nestjs-best-practices/.github/workflows/branch-protection.yml",
    "chars": 760,
    "preview": "name: Branch Protection\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  check-branch:\n    runs-on: ubuntu-latest\n    "
  },
  {
    "path": ".agents/skills/nestjs-best-practices/.github/workflows/deploy.yml",
    "chars": 1273,
    "preview": "name: Deploy to GitHub Pages\n\non:\n  push:\n    branches: [docs]\n    paths:\n      - 'website/**'\n  workflow_dispatch:\n\nper"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/.gitignore",
    "chars": 237,
    "preview": "# Dependencies\nnode_modules/\n\n# Website (lives on docs branch)\nwebsite/\n\n# Build outputs\ndist/\n*.js\n*.d.ts\n*.js.map\n\n# I"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/AGENTS.md",
    "chars": 161923,
    "preview": "# NestJS Best Practices\n\n**Version 1.1.0**\nNestJS Best Practices\nJanuary 2026\n\n> **Note:**\n> This document is mainly for"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/README.md",
    "chars": 4793,
    "preview": "# NestJS Best Practices\n\n📖 [For Humans <3](https://kadajett.github.io/agent-nestjs-skills/)\n\nA structured repository for"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/SKILL.md",
    "chars": 4901,
    "preview": "---\nname: nestjs-best-practices\ndescription: NestJS best practices and architecture patterns for building production-rea"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md",
    "chars": 4384,
    "preview": "---\ntitle: Use DTOs and Serialization for API Responses\nimpact: MEDIUM\nimpactDescription: Response DTOs prevent accident"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/api-use-interceptors.md",
    "chars": 5517,
    "preview": "---\ntitle: Use Interceptors for Cross-Cutting Concerns\nimpact: MEDIUM-HIGH\nimpactDescription: Interceptors provide clean"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/api-use-pipes.md",
    "chars": 5385,
    "preview": "---\ntitle: Use Pipes for Input Transformation\nimpact: MEDIUM\nimpactDescription: Pipes ensure clean, validated data reach"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/api-versioning.md",
    "chars": 4972,
    "preview": "---\ntitle: Use API Versioning for Breaking Changes\nimpact: MEDIUM\nimpactDescription: Versioning allows you to evolve API"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md",
    "chars": 2020,
    "preview": "---\ntitle: Avoid Circular Dependencies\nimpact: CRITICAL\nimpactDescription: '#1 cause of runtime crashes'\ntags: architect"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/arch-feature-modules.md",
    "chars": 2045,
    "preview": "---\ntitle: Organize by Feature Modules\nimpact: CRITICAL\nimpactDescription: '3-5x faster onboarding and development'\ntags"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/arch-module-sharing.md",
    "chars": 3875,
    "preview": "---\ntitle: Use Proper Module Sharing Patterns\nimpact: CRITICAL\nimpactDescription: Prevents duplicate instances, memory l"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/arch-single-responsibility.md",
    "chars": 2921,
    "preview": "---\ntitle: Single Responsibility for Services\nimpact: CRITICAL\nimpactDescription: '40%+ improvement in testability'\ntags"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/arch-use-events.md",
    "chars": 3031,
    "preview": "---\ntitle: Use Event-Driven Architecture for Decoupling\nimpact: MEDIUM-HIGH\nimpactDescription: Enables async processing "
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/arch-use-repository-pattern.md",
    "chars": 2842,
    "preview": "---\ntitle: Use Repository Pattern for Data Access\nimpact: HIGH\nimpactDescription: Decouples business logic from database"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/db-avoid-n-plus-one.md",
    "chars": 3887,
    "preview": "---\ntitle: Avoid N+1 Query Problems\nimpact: HIGH\nimpactDescription: N+1 queries are one of the most common performance k"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/db-use-migrations.md",
    "chars": 3836,
    "preview": "---\ntitle: Use Database Migrations\nimpact: HIGH\nimpactDescription: Enables safe, repeatable database schema changes\ntags"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/db-use-transactions.md",
    "chars": 3872,
    "preview": "---\ntitle: Use Transactions for Multi-Step Operations\nimpact: HIGH\nimpactDescription: Ensures data consistency in multi-"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/devops-graceful-shutdown.md",
    "chars": 5856,
    "preview": "---\ntitle: Implement Graceful Shutdown\nimpact: MEDIUM-HIGH\nimpactDescription: Proper shutdown handling ensures zero-down"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/devops-use-config-module.md",
    "chars": 4414,
    "preview": "---\ntitle: Use ConfigModule for Environment Configuration\nimpact: LOW-MEDIUM\nimpactDescription: Proper configuration pre"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/devops-use-logging.md",
    "chars": 5638,
    "preview": "---\ntitle: Use Structured Logging\nimpact: MEDIUM-HIGH\nimpactDescription: Structured logging enables effective debugging "
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/di-avoid-service-locator.md",
    "chars": 2980,
    "preview": "---\ntitle: Avoid Service Locator Anti-Pattern\nimpact: HIGH\nimpactDescription: Hides dependencies and breaks testability\n"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/di-interface-segregation.md",
    "chars": 5188,
    "preview": "---\ntitle: Apply Interface Segregation Principle\nimpact: HIGH\nimpactDescription: Reduces coupling and improves testabili"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/di-liskov-substitution.md",
    "chars": 7251,
    "preview": "---\ntitle: Honor Liskov Substitution Principle\nimpact: HIGH\nimpactDescription: Ensures implementations are truly interch"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md",
    "chars": 2308,
    "preview": "---\ntitle: Prefer Constructor Injection\nimpact: CRITICAL\nimpactDescription: Required for proper DI and testing\ntags: dep"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/di-scope-awareness.md",
    "chars": 2617,
    "preview": "---\ntitle: Understand Provider Scopes\nimpact: CRITICAL\nimpactDescription: Prevents data leaks and performance issues\ntag"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/di-use-interfaces-tokens.md",
    "chars": 2568,
    "preview": "---\ntitle: Use Injection Tokens for Interfaces\nimpact: HIGH\nimpactDescription: Enables interface-based DI at runtime\ntag"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/error-handle-async-errors.md",
    "chars": 3526,
    "preview": "---\ntitle: Handle Async Errors Properly\nimpact: HIGH\nimpactDescription: Prevents process crashes from unhandled rejectio"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/error-throw-http-exceptions.md",
    "chars": 3180,
    "preview": "---\ntitle: Throw HTTP Exceptions from Services\nimpact: HIGH\nimpactDescription: Keeps controllers thin and simplifies err"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/error-use-exception-filters.md",
    "chars": 3624,
    "preview": "---\ntitle: Use Exception Filters for Error Handling\nimpact: HIGH\nimpactDescription: Consistent, centralized error handli"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/micro-use-health-checks.md",
    "chars": 5984,
    "preview": "---\ntitle: Implement Health Checks for Microservices\nimpact: MEDIUM-HIGH\nimpactDescription: Health checks enable orchest"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/micro-use-patterns.md",
    "chars": 5101,
    "preview": "---\ntitle: Use Message and Event Patterns Correctly\nimpact: MEDIUM\nimpactDescription: Proper patterns ensure reliable mi"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/micro-use-queues.md",
    "chars": 6179,
    "preview": "---\ntitle: Use Message Queues for Background Jobs\nimpact: MEDIUM-HIGH\nimpactDescription: Queues enable reliable backgrou"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/perf-async-hooks.md",
    "chars": 2917,
    "preview": "---\ntitle: Use Async Lifecycle Hooks Correctly\nimpact: HIGH\nimpactDescription: Improper async handling blocks applicatio"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/perf-lazy-loading.md",
    "chars": 3808,
    "preview": "---\ntitle: Use Lazy Loading for Large Modules\nimpact: MEDIUM\nimpactDescription: Improves startup time for large applicat"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/perf-optimize-database.md",
    "chars": 3271,
    "preview": "---\ntitle: Optimize Database Queries\nimpact: HIGH\nimpactDescription: Database queries are typically the largest source o"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/perf-use-caching.md",
    "chars": 3483,
    "preview": "---\ntitle: Use Caching Strategically\nimpact: HIGH\nimpactDescription: Dramatically reduces database load and response tim"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/security-auth-jwt.md",
    "chars": 4082,
    "preview": "---\ntitle: Implement Secure JWT Authentication\nimpact: CRITICAL\nimpactDescription: Essential for secure APIs\ntags: secur"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/security-rate-limiting.md",
    "chars": 3323,
    "preview": "---\ntitle: Implement Rate Limiting\nimpact: HIGH\nimpactDescription: Protects against abuse and ensures fair resource usag"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/security-sanitize-output.md",
    "chars": 3814,
    "preview": "---\ntitle: Sanitize Output to Prevent XSS\nimpact: HIGH\nimpactDescription: XSS vulnerabilities can compromise user sessio"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/security-use-guards.md",
    "chars": 3606,
    "preview": "---\ntitle: Use Guards for Authentication and Authorization\nimpact: HIGH\nimpactDescription: Enforces access control befor"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/security-validate-all-input.md",
    "chars": 3355,
    "preview": "---\ntitle: Validate All Input with DTOs and Pipes\nimpact: HIGH\nimpactDescription: First line of defense against attacks\n"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/test-e2e-supertest.md",
    "chars": 4761,
    "preview": "---\ntitle: Use Supertest for E2E Testing\nimpact: HIGH\nimpactDescription: Validates the full request/response cycle\ntags:"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/test-mock-external-services.md",
    "chars": 4574,
    "preview": "---\ntitle: Mock External Services in Tests\nimpact: HIGH\nimpactDescription: Ensures fast, reliable, deterministic tests\nt"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/rules/test-use-testing-module.md",
    "chars": 4374,
    "preview": "---\ntitle: Use Testing Module for Unit Tests\nimpact: HIGH\nimpactDescription: Enables proper isolated testing with mocked"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/scripts/build-agents.ts",
    "chars": 8654,
    "preview": "#!/usr/bin/env npx ts-node\n\n/**\n * Build script for generating AGENTS.md from individual rule files\n *\n * Usage: npx ts-"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/scripts/build.sh",
    "chars": 369,
    "preview": "#!/bin/bash\n\n# Build script for generating AGENTS.md\n# Usage: ./build.sh\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}"
  },
  {
    "path": ".agents/skills/nestjs-best-practices/scripts/package.json",
    "chars": 428,
    "preview": "{\n  \"name\": \"nestjs-best-practices-scripts\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"description\": \"Build scripts f"
  },
  {
    "path": ".agents/skills/typeorm/SKILL.md",
    "chars": 13895,
    "preview": "---\nname: typeorm\ndescription: Guidelines for developing with TypeORM, a full-featured ORM for TypeScript and JavaScript"
  },
  {
    "path": ".agents/skills/typescript-advanced-types/SKILL.md",
    "chars": 16989,
    "preview": "---\nname: typescript-advanced-types\ndescription: Master TypeScript's advanced type system including generics, conditiona"
  },
  {
    "path": ".dockerignore",
    "chars": 179,
    "preview": "client/.next/cache\n# Keep empty dir. Next.js scans it on startup even with CDN assets\nclient/.next/static/**\n!client/.ne"
  },
  {
    "path": ".editorconfig",
    "chars": 244,
    "preview": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert"
  },
  {
    "path": ".eslintignore",
    "chars": 129,
    "preview": "# don't ever lint node_modules\nnode_modules\n# don't lint build output (make sure it's set to your correct build folder n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 611,
    "preview": "# These are supported funding model platforms\n\ngithub: [dzmitry-varabei]\npatreon: # Replace with a single Patreon userna"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 650,
    "preview": "---\nname: 🐞 Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\n---\n\n**Describe the bug**\nA clear"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/data-issue-report.md",
    "chars": 178,
    "preview": "---\nname: 🗃 Data issue\nabout: Create a issue to fix data\ntitle: ''\nlabels: data issue\n---\n\n**Course**\nSpecify your cours"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 241,
    "preview": "---\nname: 🚀 Feature request\nabout: Request a feature to implement\ntitle: ''\nlabels: feature\n---\n\n**Describe the feature*"
  },
  {
    "path": ".github/auto-label.json",
    "chars": 125,
    "preview": "{\n  \"rules\": {\n    \"code:client\": [\"client/\"],\n    \"code:server\": [\"server/\"],\n    \"⛓ dependencies\": \"**/package.json\"\n "
  },
  {
    "path": ".github/copilot-instructions.md",
    "chars": 53,
    "preview": "Use instructions from `AGENTS.md` to guide your work."
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 484,
    "preview": "[Pull Request Guidelines](https://github.com/rolling-scopes/rsschool-app/blob/master/CONTRIBUTING.md#pull-requests)\n\n**I"
  },
  {
    "path": ".github/workflows/deploy-sloths.yaml",
    "chars": 1390,
    "preview": "name: Deploy sloths.rs.school\non:\n  push:\n    branches: [master]\n    paths:\n      - 'tools/sloths/**'\n      - '.github/w"
  },
  {
    "path": ".github/workflows/deploy.yaml",
    "chars": 8975,
    "preview": "name: Deploy RS School App\n\non:\n  push:\n    branches: [master]\n\nenv:\n  DO_NOT_TRACK: '1'\n  NODE_OPTIONS: '--no-warnings'"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "chars": 10163,
    "preview": "name: Pull Request\n\non:\n  pull_request:\n    branches: [master]\n    types: [opened, synchronize, reopened, labeled, unlab"
  },
  {
    "path": ".github/workflows/pull_request_close.yml",
    "chars": 1427,
    "preview": "name: Pull Request Delete\n\non:\n  pull_request:\n    types: [closed]\n    branches: [master]\n\njobs:\n  pr_delete:\n    runs-o"
  },
  {
    "path": ".github/workflows/renovate.yml",
    "chars": 396,
    "preview": "name: Renovate\non:\n  schedule:\n    # once a month\n    - cron: '0 0 1 * *'\n  workflow_dispatch:\njobs:\n  renovate:\n    run"
  },
  {
    "path": ".gitignore",
    "chars": 226,
    "preview": ".DS_Store\n.env\n.history/\n.idea/\n.next/\n.sentryclirc\n.swc/\n.turbo\n.vscode\napp/\ncoverage\ndist/\nnode_modules/\nout\nplaywrigh"
  },
  {
    "path": ".oxfmtrc.json",
    "chars": 251,
    "preview": "{\n  \"trailingComma\": \"all\",\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": true,\n  \"printWidth\": 120,\n  \"arrowParens\""
  },
  {
    "path": "AGENTS.md",
    "chars": 1891,
    "preview": "# LLM Agents Instructions\n\n## General\n\n- Read `README.md` first for project overview and architecture\n- Read `CONTRIBUTI"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6088,
    "preview": "# How To Contribute\n\n## Local development\n\n### Prerequisites\n\n- [Git 2.10+](https://git-scm.com/downloads)\n- [NodeJS LTS"
  },
  {
    "path": "DOMAIN.md",
    "chars": 5536,
    "preview": "# Domain Model\n\nThis document describes the core domain model implemented in `server/src/models` and how the entities re"
  },
  {
    "path": "GUIDELINES.md",
    "chars": 6907,
    "preview": "# Guidelines\n\n## Project Structure\n\n- `client` - Next.js frontend (active)\n- `nestjs` - NestJS backend (active)\n- `serve"
  },
  {
    "path": "LICENSE",
    "chars": 16725,
    "preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
  },
  {
    "path": "README.md",
    "chars": 4146,
    "preview": "[![Deploy](https://github.com/rolling-scopes/rsschool-app/actions/workflows/deploy.yaml/badge.svg?branch=master)](https:"
  },
  {
    "path": "VITEST.md",
    "chars": 10143,
    "preview": "# Vitest Migration Plan\n\n## Goal\n\nMigrate all automated tests in this repository from Jest to latest Vitest with no feat"
  },
  {
    "path": "client/.dockerignore",
    "chars": 130,
    "preview": ".next/cache\n# Keep empty dir. Next.js scans it on startup even with CDN assets\n.next/static/**\n!.next/static/\nnode_modul"
  },
  {
    "path": "client/Dockerfile",
    "chars": 466,
    "preview": "FROM node:24-alpine\n\nEXPOSE 8080\n\nENV NODE_ENV=production\nENV NODE_PORT=8080\n\nWORKDIR /app\n\nCOPY client/next.config.mjs "
  },
  {
    "path": "client/Dockerfile.lambda",
    "chars": 797,
    "preview": "FROM node:24-bullseye-slim AS builder\n\nENV NEXT_RUNTIME=nodejs\n\nWORKDIR /container_out\n\nCOPY package.json package.json\nC"
  },
  {
    "path": "client/README.md",
    "chars": 3168,
    "preview": "# Client\n\nThis document defines the unified client architecture for the project.\n\n## Core Principles\n\n- Feature ownershi"
  },
  {
    "path": "client/eslint.config.mjs",
    "chars": 2209,
    "preview": "import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport boundaries from 'eslint-plugin-boundaries"
  },
  {
    "path": "client/next-env.d.ts",
    "chars": 249,
    "preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\nimport './.next/types/routes.d.ts';\n\n//"
  },
  {
    "path": "client/next.config.mjs",
    "chars": 836,
    "preview": "import prodConfig from './next.config.prod.mjs';\n\nconst isProd = process.env.NODE_ENV === 'production';\n\nconst server = "
  },
  {
    "path": "client/next.config.prod.mjs",
    "chars": 463,
    "preview": "const isProd = process.env.NODE_ENV === 'production';\n\nconst nextConfig = {\n  assetPrefix: isProd ? 'https://cdn.rs.scho"
  },
  {
    "path": "client/package.json",
    "chars": 1637,
    "preview": "{\n  \"name\": \"client\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"license\": \"Mozilla Public License 2.0\",\n  \"browserslis"
  },
  {
    "path": "client/playwright.config.ts",
    "chars": 1630,
    "preview": "import type { PlaywrightTestConfig } from '@playwright/test';\nimport { devices } from '@playwright/test';\n\n/**\n * Read e"
  },
  {
    "path": "client/public/static/empty.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/specs/smoke.spec.ts",
    "chars": 1204,
    "preview": "import { test, expect } from '@playwright/test';\n\nconst url = process.env.BASE_URL || 'http://localhost:3000';\n\ntest.bef"
  },
  {
    "path": "client/src/__mocks__/axios.js",
    "chars": 512,
    "preview": "import { vi } from 'vitest';\n\nconst mockAxios = {\n  get: vi.fn(),\n  post: vi.fn(),\n  put: vi.fn(),\n  patch: vi.fn(),\n  d"
  },
  {
    "path": "client/src/__mocks__/hooks/index.ts",
    "chars": 82,
    "preview": "export { useMessage } from './useMessage';\nexport { useTheme } from './useTheme';\n"
  },
  {
    "path": "client/src/__mocks__/hooks/useMessage.tsx",
    "chars": 315,
    "preview": "import { vi } from 'vitest';\n\nexport const useMessage = () => ({\n  message: {\n    success: vi.fn(),\n    error: vi.fn(),\n"
  },
  {
    "path": "client/src/__mocks__/hooks/useTheme.tsx",
    "chars": 156,
    "preview": "import { vi } from 'vitest';\n\nexport const useTheme = () => ({\n  theme: 'light',\n  themeChange: vi.fn(),\n  autoTheme: tr"
  },
  {
    "path": "client/src/__mocks__/next/config.ts",
    "chars": 53,
    "preview": "export default function getConfig() {\n  return {};\n}\n"
  },
  {
    "path": "client/src/__tests__/ProfilePage.test.tsx",
    "chars": 1428,
    "preview": "import { Session } from '@client/components/withSession';\nimport ProfilePage from '@client/pages/profile';\nimport { rend"
  },
  {
    "path": "client/src/__tests__/__snapshots__/ProfilePage.test.tsx.snap",
    "chars": 1318,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`ProfilePage > Should render correctly > if full "
  },
  {
    "path": "client/src/api/.gitignore",
    "chars": 39,
    "preview": "wwwroot/*.js\nnode_modules\ntypings\ndist\n"
  },
  {
    "path": "client/src/api/.npmignore",
    "chars": 94,
    "preview": "# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm"
  },
  {
    "path": "client/src/api/.openapi-generator/FILES",
    "chars": 85,
    "preview": ".gitignore\n.npmignore\napi.ts\nbase.ts\ncommon.ts\nconfiguration.ts\ngit_push.sh\nindex.ts\n"
  },
  {
    "path": "client/src/api/.openapi-generator/VERSION",
    "chars": 5,
    "preview": "5.4.0"
  },
  {
    "path": "client/src/api/.openapi-generator-ignore",
    "chars": 1040,
    "preview": "# OpenAPI Generator Ignore\n# Generated by openapi-generator https://github.com/openapitools/openapi-generator\n\n# Use thi"
  },
  {
    "path": "client/src/api/api.ts",
    "chars": 803492,
    "preview": "/* tslint:disable */\n/* eslint-disable */\n/**\n * \n * No description provided (generated by Openapi Generator https://git"
  },
  {
    "path": "client/src/api/base.ts",
    "chars": 1559,
    "preview": "/* tslint:disable */\n/* eslint-disable */\n/**\n * \n * No description provided (generated by Openapi Generator https://git"
  },
  {
    "path": "client/src/api/common.ts",
    "chars": 4245,
    "preview": "/* tslint:disable */\n/* eslint-disable */\n/**\n * \n * No description provided (generated by Openapi Generator https://git"
  },
  {
    "path": "client/src/api/configuration.ts",
    "chars": 3210,
    "preview": "/* tslint:disable */\n/* eslint-disable */\n/**\n * \n * No description provided (generated by Openapi Generator https://git"
  },
  {
    "path": "client/src/api/git_push.sh",
    "chars": 1830,
    "preview": "#!/bin/sh\n# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/\n#\n# Usage"
  },
  {
    "path": "client/src/api/index.ts",
    "chars": 441,
    "preview": "/* tslint:disable */\n/* eslint-disable */\n/**\n * \n * No description provided (generated by Openapi Generator https://git"
  },
  {
    "path": "client/src/components/Analytics.tsx",
    "chars": 722,
    "preview": "import Script from 'next/script';\n\nconst enableAnalytics = process.env.NODE_ENV === 'production';\n\nexport function Analy"
  },
  {
    "path": "client/src/components/Comment.tsx",
    "chars": 947,
    "preview": "import { ReactNode } from 'react';\nimport { theme } from 'antd';\n\ntype CommentProps = {\n  author?: ReactNode;\n  avatar?:"
  },
  {
    "path": "client/src/components/CountBadge/CountBadge.tsx",
    "chars": 605,
    "preview": "import { Badge, BadgeProps } from 'antd';\n\ntype PresetColors = BadgeProps['status'];\n\nfunction getStylesByStatus(status?"
  },
  {
    "path": "client/src/components/CountBadge/index.tsx",
    "chars": 54,
    "preview": "export { default as CountBadge } from './CountBadge';\n"
  },
  {
    "path": "client/src/components/CoursePageLayout.tsx",
    "chars": 885,
    "preview": "import { Layout, Spin, theme } from 'antd';\nimport { Course } from '@client/services/models';\nimport { CourseNoAccess } "
  },
  {
    "path": "client/src/components/DevTools/DevToolsContainer.tsx",
    "chars": 1612,
    "preview": "import { Button, Card, FloatButton } from 'antd';\nimport { CSSProperties, ReactNode, useState } from 'react';\nimport { B"
  },
  {
    "path": "client/src/components/DevTools/DevToolsCurrentUser.tsx",
    "chars": 979,
    "preview": "import useRequest from 'ahooks/lib/useRequest';\nimport { Descriptions, Typography } from 'antd';\nimport { SessionApi } f"
  },
  {
    "path": "client/src/components/DevTools/DevToolsUsers.tsx",
    "chars": 2168,
    "preview": "import { Button, Flex, Table, Typography } from 'antd';\nimport { useEffect, useMemo, useState } from 'react';\nimport { D"
  },
  {
    "path": "client/src/components/DevTools/index.ts",
    "chars": 57,
    "preview": "export { DevToolsContainer } from './DevToolsContainer';\n"
  },
  {
    "path": "client/src/components/Footer/Donation.tsx",
    "chars": 828,
    "preview": "import { Button } from 'antd';\nimport HeartTwoTone from '@ant-design/icons/HeartTwoTone';\n\ntype Props = {\n  maxDonatorsS"
  },
  {
    "path": "client/src/components/Footer/Feedback.tsx",
    "chars": 720,
    "preview": "import { Menu } from './Menu';\nimport { HeartOutlined, LikeOutlined, TrophyOutlined } from '@ant-design/icons';\n\nconst p"
  },
  {
    "path": "client/src/components/Footer/FooterLayout.tsx",
    "chars": 1242,
    "preview": "import * as React from 'react';\nimport { Col, Layout, Row } from 'antd';\nimport { Feedback } from './Feedback';\nimport {"
  },
  {
    "path": "client/src/components/Footer/Help.tsx",
    "chars": 854,
    "preview": "import { Menu } from './Menu';\nimport { BookOutlined, BugOutlined, HddOutlined } from '@ant-design/icons';\n\nconst github"
  },
  {
    "path": "client/src/components/Footer/Menu.tsx",
    "chars": 828,
    "preview": "import React from 'react';\nimport { List } from 'antd';\nimport Link from 'next/link';\n\ntype LinkInfo = { icon: React.Rea"
  },
  {
    "path": "client/src/components/Footer/SocialNetworks.tsx",
    "chars": 1750,
    "preview": "import * as React from 'react';\nimport { Row, Col, Space } from 'antd';\nimport YoutubeFilled from '@ant-design/icons/You"
  },
  {
    "path": "client/src/components/Footer/index.tsx",
    "chars": 47,
    "preview": "export { FooterLayout } from './FooterLayout';\n"
  },
  {
    "path": "client/src/components/HeaderMiniBannerCarousel.module.css",
    "chars": 2028,
    "preview": ".carousel {\n  position: relative;\n  width: 284px;\n  height: 56px;\n  border-radius: 6px;\n}\n\n.carouselViewport {\n  width: "
  },
  {
    "path": "client/src/components/HeaderMiniBannerCarousel.test.tsx",
    "chars": 2366,
    "preview": "import { render, screen } from '@testing-library/react';\nimport { HeaderMiniBannerCarousel } from './HeaderMiniBannerCar"
  },
  {
    "path": "client/src/components/HeaderMiniBannerCarousel.tsx",
    "chars": 3562,
    "preview": "import { useMemo, useRef } from 'react';\nimport { Carousel, theme } from 'antd';\nimport type { CarouselRef } from 'antd/"
  },
  {
    "path": "client/src/components/Heroes/HeroesCountBadge.tsx",
    "chars": 1132,
    "preview": "import heroesBadges from '@client/configs/heroes-badges';\nimport { Avatar, Badge, Tooltip } from 'antd';\nimport { Heroes"
  },
  {
    "path": "client/src/components/Heroes/HeroesRadarTab.tsx",
    "chars": 6082,
    "preview": "import { FileExcelOutlined } from '@ant-design/icons';\nimport { SessionContext, useActiveCourseContext } from '@client/m"
  },
  {
    "path": "client/src/components/Heroes/HeroesRadarTable.tsx",
    "chars": 3529,
    "preview": "import { Table, TableProps, Tag } from 'antd';\nimport { ColumnType } from 'antd/lib/table';\nimport { HeroRadarDto, Heroe"
  },
  {
    "path": "client/src/components/LoadingScreen.module.css",
    "chars": 54,
    "preview": ".loadingScreen {\n  z-index: 1;\n  top: 0;\n  left: 0;\n}\n"
  },
  {
    "path": "client/src/components/MentorOptions.tsx",
    "chars": 2892,
    "preview": "import { Button, Form, FormInstance, Select } from 'antd';\nimport { StudentSearch } from '@client/shared/components/Stud"
  },
  {
    "path": "client/src/components/Profile/AboutCard.tsx",
    "chars": 1957,
    "preview": "import { ChangeEvent, useEffect, useState } from 'react';\nimport { Typography, Input } from 'antd';\nimport InfoCircleOut"
  },
  {
    "path": "client/src/components/Profile/CommonCard.tsx",
    "chars": 1119,
    "preview": "import { ReactNode } from 'react';\nimport { Card, Typography, Empty } from 'antd';\nimport EditOutlined from '@ant-design"
  },
  {
    "path": "client/src/components/Profile/CommonCardWithSettingsModal.tsx",
    "chars": 1770,
    "preview": "import { ReactNode, useState } from 'react';\nimport ProfileSettingsModal from './ProfileSettingsModal';\nimport CommonCar"
  },
  {
    "path": "client/src/components/Profile/ContactsCard.tsx",
    "chars": 5492,
    "preview": "import { useEffect, useMemo, useState } from 'react';\nimport { List, theme, Typography } from 'antd';\nimport ContactsOut"
  },
  {
    "path": "client/src/components/Profile/ContactsCardForm.tsx",
    "chars": 1429,
    "preview": "import { Form, Input, List, Typography } from 'antd';\nimport { Contacts } from '@common/models/profile';\nimport { Contac"
  },
  {
    "path": "client/src/components/Profile/DiscordCard.tsx",
    "chars": 1614,
    "preview": "import { Typography } from 'antd';\nimport { WarningTwoTone } from '@ant-design/icons';\nimport { Discord } from '@common/"
  },
  {
    "path": "client/src/components/Profile/EducationCard.tsx",
    "chars": 5258,
    "preview": "import { ChangeEvent, useMemo, useState } from 'react';\nimport { Typography, List, Input, Button } from 'antd';\nimport {"
  },
  {
    "path": "client/src/components/Profile/EmailConfirmation.tsx",
    "chars": 1540,
    "preview": "import { Alert } from 'antd';\nimport { Timer } from '@client/shared/components/Timer';\nimport dayjs from 'dayjs';\nimport"
  },
  {
    "path": "client/src/components/Profile/InterviewCard.tsx",
    "chars": 6047,
    "preview": "import CommonCard from '@client/components/Profile/CommonCard';\nimport { QuestionCircleOutlined } from '@ant-design/icon"
  },
  {
    "path": "client/src/components/Profile/InterviewModal.tsx",
    "chars": 3076,
    "preview": "import { Flex, Modal, Space, Table, Tag, Typography } from 'antd';\nimport { CoreJsInterviewFeedback, LegacyFeedback, Sta"
  },
  {
    "path": "client/src/components/Profile/LanguagesCard.tsx",
    "chars": 2046,
    "preview": "import TranslationOutlined from '@ant-design/icons/TranslationOutlined';\nimport { Form, Space, Tag, Typography } from 'a"
  },
  {
    "path": "client/src/components/Profile/MainCard.tsx",
    "chars": 6047,
    "preview": "import { ChangeEvent, useEffect, useState } from 'react';\nimport { Card, Typography, Input, Row, Col, Button } from 'ant"
  },
  {
    "path": "client/src/components/Profile/MentorStatsCard.tsx",
    "chars": 4085,
    "preview": "import { useMemo, useState } from 'react';\nimport { Button, Card, Flex, List, Space, Typography } from 'antd';\nimport Co"
  },
  {
    "path": "client/src/components/Profile/MentorStatsModal.tsx",
    "chars": 1901,
    "preview": "import { MentorStats } from '@common/models/profile';\nimport { Card, Flex, Modal, Space } from 'antd';\nimport { GithubAv"
  },
  {
    "path": "client/src/components/Profile/ObfuscateConfirmationModal.tsx",
    "chars": 2025,
    "preview": "import { useState } from 'react';\nimport { Modal, Input, Typography, Space } from 'antd';\nimport { ProfileApi } from '@c"
  },
  {
    "path": "client/src/components/Profile/ProfileSettingsModal.module.css",
    "chars": 159,
    "preview": ".modal :global(.ant-modal-content) {\n  height: inherit !important;\n}\n\n.modal :global(.ant-modal-body) {\n  max-height: ca"
  },
  {
    "path": "client/src/components/Profile/ProfileSettingsModal.tsx",
    "chars": 833,
    "preview": "import { Modal } from 'antd';\n\nimport styles from './ProfileSettingsModal.module.css';\n\ntype Props = {\n  isSettingsVisib"
  },
  {
    "path": "client/src/components/Profile/PublicFeedbackCard.tsx",
    "chars": 4233,
    "preview": "import * as React from 'react';\nimport isEqual from 'lodash/isEqual';\nimport { Typography, Tooltip } from 'antd';\nimport"
  },
  {
    "path": "client/src/components/Profile/PublicFeedbackModal.tsx",
    "chars": 2042,
    "preview": "import * as React from 'react';\nimport dayjs from 'dayjs';\nimport relative from 'dayjs/plugin/relativeTime';\nimport { Pu"
  },
  {
    "path": "client/src/components/Profile/StudentLeaveCourse.tsx",
    "chars": 2560,
    "preview": "import { WarningOutlined } from '@ant-design/icons';\nimport { Divider, Modal, theme, Typography, Checkbox, Space, Form, "
  },
  {
    "path": "client/src/components/Profile/StudentStatsCard.tsx",
    "chars": 9050,
    "preview": "import * as React from 'react';\nimport isEqual from 'lodash/isEqual';\nimport { Typography, List, Button, Progress } from"
  },
  {
    "path": "client/src/components/Profile/StudentStatsModal.tsx",
    "chars": 3486,
    "preview": "import * as React from 'react';\nimport { StudentStats } from '@common/models/profile';\nimport { Modal, Table, Typography"
  },
  {
    "path": "client/src/components/Profile/__test__/AboutCard.test.tsx",
    "chars": 637,
    "preview": "import { render } from '@testing-library/react';\nimport AboutCard from '../AboutCard';\n\ndescribe('AboutCard', () => {\n  "
  },
  {
    "path": "client/src/components/Profile/__test__/CommonCard.test.tsx",
    "chars": 582,
    "preview": "import { render } from '@testing-library/react';\nimport CommonCard from '../CommonCard';\n\ndescribe('CommonCard', () => {"
  },
  {
    "path": "client/src/components/Profile/__test__/CommonCardWithSettingsModal.test.tsx",
    "chars": 1142,
    "preview": "import { render } from '@testing-library/react';\nimport CommonCardWithSettingsModal from '../CommonCardWithSettingsModal"
  },
  {
    "path": "client/src/components/Profile/__test__/ContactsCard.test.tsx",
    "chars": 1431,
    "preview": "import { render } from '@testing-library/react';\nimport ContactsCard from '../ContactsCard';\n\ndescribe('ContactsCard', ("
  },
  {
    "path": "client/src/components/Profile/__test__/ContactsCardForm.test.tsx",
    "chars": 1037,
    "preview": "import { render } from '@testing-library/react';\nimport ContactsCardForm from '../ContactsCardForm';\nimport { Contact, C"
  },
  {
    "path": "client/src/components/Profile/__test__/EducationCard.test.tsx",
    "chars": 1293,
    "preview": "import { render } from '@testing-library/react';\nimport EducationCard from '../EducationCard';\n\ndescribe('EducationCard'"
  },
  {
    "path": "client/src/components/Profile/__test__/InterviewCard.test.tsx",
    "chars": 3499,
    "preview": "import { render, screen } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport Int"
  },
  {
    "path": "client/src/components/Profile/__test__/InterviewModal.test.tsx",
    "chars": 4997,
    "preview": "import { render, screen, within } from '@testing-library/react';\nimport InterviewModal from '../InterviewModal';\nimport "
  },
  {
    "path": "client/src/components/Profile/__test__/MainCard.test.tsx",
    "chars": 956,
    "preview": "import { render } from '@testing-library/react';\nimport { ProfileMainCardData } from '@client/services/user';\nimport Mai"
  },
  {
    "path": "client/src/components/Profile/__test__/MentorStatsCard.test.tsx",
    "chars": 4464,
    "preview": "import { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport { MentorStatsCard } from '../MentorS"
  },
  {
    "path": "client/src/components/Profile/__test__/MentorStatsModal.test.tsx",
    "chars": 2086,
    "preview": "import { fireEvent, render, screen } from '@testing-library/react';\nimport MentorStatsModal from '../MentorStatsModal';\n"
  },
  {
    "path": "client/src/components/Profile/__test__/ProfileSettingsModal.test.tsx",
    "chars": 881,
    "preview": "import { render, screen } from '@testing-library/react';\nimport ProfileSettingsModal from '../ProfileSettingsModal';\n\nde"
  },
  {
    "path": "client/src/components/Profile/__test__/PublicFeedbackCard.test.tsx",
    "chars": 1884,
    "preview": "import { render } from '@testing-library/react';\nimport PublicFeedbackCard from '../PublicFeedbackCard';\n\ndescribe('Publ"
  },
  {
    "path": "client/src/components/Profile/__test__/PublicFeedbackModal.test.tsx",
    "chars": 1960,
    "preview": "import { render } from '@testing-library/react';\nimport PublicFeedbackModal from '../PublicFeedbackModal';\n\ndescribe('Pu"
  },
  {
    "path": "client/src/components/Profile/__test__/StudentStatsCard.test.tsx",
    "chars": 2975,
    "preview": "import { render } from '@testing-library/react';\nimport StudentStatsCard from '../StudentStatsCard';\nimport { StudentSta"
  },
  {
    "path": "client/src/components/Profile/__test__/StudentStatsModal.test.tsx",
    "chars": 1610,
    "preview": "import { render } from '@testing-library/react';\nimport StudentStatsModal from '../StudentStatsModal';\nimport { StudentS"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/AboutCard.test.tsx.snap",
    "chars": 5217,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`AboutCard > Should render correctly > if \"data\" "
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/CommonCard.test.tsx.snap",
    "chars": 3241,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`CommonCard > Should render correctly > if is nul"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/CommonCardWithSettingsModal.test.tsx.snap",
    "chars": 4240,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`CommonCardWithSettingsModal > Should render corr"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/ContactsCard.test.tsx.snap",
    "chars": 13083,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`ContactsCard > Should render correctly > if edit"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/ContactsCardForm.test.tsx.snap",
    "chars": 6519,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`ContactsCardForm > Should render correctly > if "
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/EducationCard.test.tsx.snap",
    "chars": 15332,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`EducationCard > Should render correctly > if \"da"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/MainCard.test.tsx.snap",
    "chars": 9057,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`MainCard > Should render correctly > if editing "
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/ProfileSettingsModal.test.tsx.snap",
    "chars": 2545,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`ProfileSettingsModal > should render correctly 1"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/PublicFeedbackCard.test.tsx.snap",
    "chars": 9398,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`PublicFeedbackCard > should render correctly 1`]"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/PublicFeedbackModal.test.tsx.snap",
    "chars": 135,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`PublicFeedbackModal > Should render correctly 1`"
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/StudentStatsCard.test.tsx.snap",
    "chars": 13981,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`StudentStatsCard > should render correctly 1`] ="
  },
  {
    "path": "client/src/components/Profile/__test__/__snapshots__/StudentStatsModal.test.tsx.snap",
    "chars": 133,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`StudentStatsModal > Should render correctly 1`] "
  },
  {
    "path": "client/src/components/Profile/ui/DateWidget.tsx",
    "chars": 622,
    "preview": "import { Flex, Space, theme, Typography } from 'antd';\nimport { formatDate } from '@client/services/formatter';\nimport C"
  },
  {
    "path": "client/src/components/Profile/ui/ExpandButtonWidget.tsx",
    "chars": 420,
    "preview": "import { FullscreenOutlined } from '@ant-design/icons';\nimport { Button } from 'antd';\n\nexport function ExpandButtonWidg"
  },
  {
    "path": "client/src/components/Profile/ui/InterviewerWidget.tsx",
    "chars": 980,
    "preview": "import { Flex, Space, theme, Typography } from 'antd';\nimport { GithubAvatar } from '@client/shared/components/GithubAva"
  },
  {
    "path": "client/src/components/Profile/ui/IsGoodCandidateWidget.tsx",
    "chars": 353,
    "preview": "import { Tag, Typography } from 'antd';\n\nconst { Text } = Typography;\n\nexport function IsGoodCandidateWidget({ isGoodCan"
  },
  {
    "path": "client/src/components/Profile/ui/LegacyScreeningFeedback.tsx",
    "chars": 2517,
    "preview": "import { Tag, Typography, Table } from 'antd';\nimport { LegacyFeedback } from '@common/models/profile';\nimport { ENGLISH"
  },
  {
    "path": "client/src/components/Profile/ui/PrescreeningFeedback.tsx",
    "chars": 4439,
    "preview": "import { Row, Space, Table, Typography } from 'antd';\nimport { StageInterviewDetailedFeedback } from '@common/models/pro"
  },
  {
    "path": "client/src/components/Profile/ui/ScoreWidget.tsx",
    "chars": 300,
    "preview": "import { Tag, theme, Typography } from 'antd';\n\nconst { Text } = Typography;\n\nexport function ScoreWidget({ score }: { s"
  },
  {
    "path": "client/src/components/Profile/ui/__tests__/DateWidget.test.tsx",
    "chars": 912,
    "preview": "import { render, screen } from '@testing-library/react';\nimport { DateWidget } from '@client/components/Profile/ui';\n\nde"
  },
  {
    "path": "client/src/components/Profile/ui/__tests__/ExpandButtonWidget.test.tsx",
    "chars": 743,
    "preview": "import { render, screen } from '@testing-library/react';\nimport { ExpandButtonWidget } from '@client/components/Profile/"
  },
  {
    "path": "client/src/components/Profile/ui/__tests__/InterviewerWidget.test.tsx",
    "chars": 1114,
    "preview": "import { render, screen } from '@testing-library/react';\nimport { InterviewerWidget } from '@client/components/Profile/u"
  },
  {
    "path": "client/src/components/Profile/ui/__tests__/IsGoodCandidateWidget.test.tsx",
    "chars": 845,
    "preview": "import { render, screen } from '@testing-library/react';\nimport { IsGoodCandidateWidget } from '@client/components/Profi"
  },
  {
    "path": "client/src/components/Profile/ui/__tests__/ScoreWidget.test.tsx",
    "chars": 716,
    "preview": "import { render, screen } from '@testing-library/react';\nimport { ScoreWidget } from '@client/components/Profile/ui';\n\nd"
  },
  {
    "path": "client/src/components/Profile/ui/index.ts",
    "chars": 401,
    "preview": "export { ExpandButtonWidget } from './ExpandButtonWidget';\nexport { InterviewerWidget } from './InterviewerWidget';\nexpo"
  },
  {
    "path": "client/src/components/RegistrationPageLayout.tsx",
    "chars": 821,
    "preview": "import { Layout, Spin } from 'antd';\nimport { mapsApiKey } from '@client/configs/gcp';\nimport Script from 'next/script';"
  },
  {
    "path": "client/src/components/SelectLanguages.tsx",
    "chars": 985,
    "preview": "import { Select, SelectProps } from 'antd';\nimport { UpdateUserDtoLanguagesEnum } from '@client/api';\n\nconst languages ="
  },
  {
    "path": "client/src/components/SettingsItem.tsx",
    "chars": 1072,
    "preview": "import { PropsWithChildren, ReactNode, CSSProperties, ComponentType } from 'react';\nimport { Collapse, Divider, Flex, th"
  },
  {
    "path": "client/src/components/SlothImage.tsx",
    "chars": 1621,
    "preview": "import { Image, ImageProps } from 'antd';\n\nexport const slothNames = [\n  'activist',\n  'aws-teamwork',\n  'codewars',\n  '"
  },
  {
    "path": "client/src/components/Student/AssignStudentModal.tsx",
    "chars": 1399,
    "preview": "import { Modal, Typography } from 'antd';\nimport { StudentSearch } from '@client/shared/components/StudentSearch';\nimpor"
  },
  {
    "path": "client/src/components/Student/DashboardDetails.module.css",
    "chars": 68,
    "preview": ".studentDetailsActions :global(.ant-btn) {\n  margin: 0 8px 8px 0;\n}\n"
  },
  {
    "path": "client/src/components/Student/DashboardDetails.tsx",
    "chars": 4020,
    "preview": "import {\n  BranchesOutlined,\n  CloseCircleOutlined,\n  FileExcelOutlined,\n  SolutionOutlined,\n  UndoOutlined,\n} from '@an"
  },
  {
    "path": "client/src/components/Student/index.ts",
    "chars": 114,
    "preview": "export { AssignStudentModal } from './AssignStudentModal';\nexport { DashboardDetails } from './DashboardDetails';\n"
  }
]

// ... and 1583 more files (download for full content)

About this extraction

This page contains the full source code of the rolling-scopes/rsschool-app GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1783 files (5.0 MB), approximately 1.4M tokens, and a symbol index with 4373 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!