Skip to content

Conversation

@JoShMiQueL
Copy link

@JoShMiQueL JoShMiQueL commented Nov 30, 2025

Summary

Fixes #163

This PR adds new API endpoints to manage hideout progression, mirroring the existing task progress API while keeping the current data model and conventions.

  • Add types and validation for hideout module/part updates.
  • Add service methods in ProgressService to update hideout modules and parts in a game-mode-aware way.
  • Add HTTP handlers and OpenAPI documentation comments for the new endpoints.
  • Register the new routes under both /api and /api/v2.

Changes

1. API types

File: functions/src/types/api.ts

  • Add hideout validation types:
    • HideoutModuleStatus = 'completed' | 'uncompleted'
    • HideoutModuleUpdateRequest { state: HideoutModuleStatus }
    • HideoutPartUpdateRequest { state?: 'completed' | 'uncompleted'; count?: number }

These mirror the existing TaskStatus / TaskUpdateRequest / ObjectiveUpdateRequest types but for hideout modules and parts.

2. ValidationService

File: functions/src/services/ValidationService.ts

  • Extend imports to include the new hideout types.
  • Add validators:
    • validateHideoutModuleStatus(status)
    • validateHideoutModuleUpdate(body)
    • validateHideoutPartUpdate(body)
    • validateModuleId(moduleId)
    • validatePartId(partId)

These follow the same patterns and error messages as:

  • validateTaskStatus
  • validateTaskUpdate
  • validateObjectiveUpdate
  • validateTaskId / validateObjectiveId

3. ProgressService

File: functions/src/services/ProgressService.ts

  • Extend imports from ../types/api.js to include:

    • HideoutModuleStatus
    • HideoutModuleUpdateRequest
    • HideoutPartUpdateRequest
  • Add methods:

    • updateHideoutModule(userId, moduleId, state, gameMode)

      • Writes to ${gameMode}.hideoutModules.${moduleId}.
      • completedcomplete = true, timestamp = now.
      • uncompletedcomplete = false, timestamp deleted.
    • updateHideoutPart(userId, partId, update, gameMode)

      • Writes to ${gameMode}.hideoutParts.${partId}.
      • If state is provided, toggles complete and timestamp the same way as task objectives.
      • If count is provided, updates ${baseKey}.count.

Both methods use the same logging and error patterns as updateTaskObjective.

4. HTTP handlers and OpenAPI

File: functions/src/handlers/progressHandler.ts

  • Add handler: updateHideoutModule

    • Route: POST /progress/hideout/module/{moduleId}

    • Permission: requires WP.

    • Uses:

      • validateUserId
      • validateModuleId
      • validateHideoutModuleUpdate
    • Resolves gameMode the same way as updateSingleTask.

    • Calls progressService.updateHideoutModule and returns:

      {
        "success": true,
        "data": {
          "moduleId": "...",
          "state": "completed | uncompleted",
          "message": "Hideout module updated successfully"
        }
      }
    • Includes a full @openapi block similar to the existing task update endpoint.

  • Add handler: updateHideoutPart

    • Route: POST /progress/hideout/part/{partId}

    • Permission: requires WP.

    • Uses:

      • validateUserId
      • validatePartId
      • validateHideoutPartUpdate
    • Same gameMode resolution as other progress endpoints.

    • Calls progressService.updateHideoutPart and returns:

      {
        "success": true,
        "data": {
          "partId": "...",
          "state": "completed | uncompleted | undefined",
          "count": 0,
          "message": "Hideout part updated successfully"
        }
      }
    • Includes a full @openapi block similar to updateTaskObjective.

  • Update the default export to include the two new handlers:

    • updateHideoutModule
    • updateHideoutPart

5. Route registration

File: functions/src/index.ts

  • Under /api scope:

    • POST /api/progress/hideout/module/:moduleIdprogressHandler.updateHideoutModule
    • POST /api/progress/hideout/part/:partIdprogressHandler.updateHideoutPart
  • Under /api/v2 scope:

    • POST /api/v2/progress/hideout/module/:moduleIdprogressHandler.updateHideoutModule
    • POST /api/v2/progress/hideout/part/:partIdprogressHandler.updateHideoutPart

These mirror the existing task progress routes so that hideout progression can be managed in both API versions.

Rationale

  • Hideout progression is already exposed in the formatted progress (hideoutModulesProgress, hideoutPartsProgress), but there was no public API to update this state in a controlled way.
  • These endpoints mirror the existing task progress API patterns (single item + objective/part) and reuse the same error handling, logging and game mode handling.
  • This enables external tools (like TarkovTracker clients or integrations) to manage hideout upgrades and their item requirements via the official API.

Notes

  • The new types and validators are additive and should be backwards compatible.
  • No changes were made to the internal progress formatting logic (formatProgress), only to the write path.
  • If you prefer different route shapes (e.g. /progress/hideout/{moduleId} instead of /progress/hideout/module/{moduleId}), I am happy to adjust the paths to match your naming conventions.

- Add POST /progress/hideout/module/:moduleId endpoint for module completion tracking
- Add POST /progress/hideout/part/:partId endpoint for part progress and item counts
- Implement game mode support (pvp/pve/dual) for hideout progress
- Add validation for hideout module IDs, part IDs, and update payloads
- Add OpenAPI documentation for new hideout endpoints
- Update ProgressService with hideout-specific update methods
- Add hideout-relate
@coderabbitai
Copy link

coderabbitai bot commented Nov 30, 2025

📝 Walkthrough

Walkthrough

This pull request introduces two new HTTP endpoints (POST /api/progress/hideout/module/:moduleId and POST /api/progress/hideout/part/:partId) that allow updating hideout module and part completion states in the progress service. Both endpoints include corresponding v2 API routes, validation handlers, and service layer methods backed by Firestore updates.

Changes

Cohort / File(s) Change Summary
API Route Definitions
functions/src/index.ts
Added four new POST endpoints for hideout updates: two for standard API (/api/progress/hideout/module/:moduleId, /api/progress/hideout/part/:partId) and two for v2 API (/api/v2/progress/hideout/...), wired to new handler methods.
Request Handlers
functions/src/handlers/progressHandler.ts
Added two new public endpoints: updateHideoutModule and updateHideoutPart. Each performs permission validation, ID extraction, gameMode determination with optional dual-token query override, service invocation, and standardized API response formatting with OpenAPI documentation.
Service Layer
functions/src/services/ProgressService.ts
Added two new public methods: updateHideoutModule (sets/clears completion state and timestamp for a module) and updateHideoutPart (updates part state and optional count). Both perform Firestore updates scoped by gameMode and include event logging.
Request Validation
functions/src/services/ValidationService.ts
Added hideout-specific validators: validateHideoutModuleStatus, validateHideoutModuleUpdate, validateHideoutPartUpdate, validateModuleId, and validatePartId. These enforce type narrowing and non-empty string constraints.
Type Definitions
functions/src/types/api.ts
Added three new public types: HideoutModuleStatus (union of 'completed' | 'uncompleted'), HideoutModuleUpdateRequest (with state field), and HideoutPartUpdateRequest (with optional state and count fields).

Sequence Diagram

sequenceDiagram
    participant Client
    participant Handler as updateHideoutModule<br/>Handler
    participant Validator as ValidationService
    participant Service as ProgressService
    participant DB as Firestore

    Client->>Handler: POST /api/progress/hideout/module/:moduleId<br/>{state: 'completed'}
    
    Handler->>Handler: Extract & validate auth token
    Handler->>Validator: validateHideoutModuleUpdate(body)
    Validator-->>Handler: validated state
    Handler->>Validator: validateModuleId(moduleId)
    Validator-->>Handler: moduleId confirmed
    
    Handler->>Handler: Determine gameMode<br/>(from token or query override)
    
    Handler->>Service: updateHideoutModule(userId, moduleId,<br/>state, gameMode)
    
    Service->>DB: Update user progress doc<br/>with module state & timestamp<br/>(scoped by gameMode)
    DB-->>Service: Success
    Service->>Service: Log success event
    Service-->>Handler: Promise resolved
    
    Handler->>Handler: Build ApiResponse
    Handler-->>Client: 200 OK<br/>{moduleId, state, message}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • ValidationService additions: Multiple new validator functions with type narrowing—verify logic for state/count constraints and error handling consistency.
  • Service layer methods: Confirm Firestore path construction (gameMode scoping) and timestamp handling align with existing patterns.
  • Handler endpoint logic: Check permission validation, gameMode override logic, and response formatting consistency across both endpoints.

Suggested labels

type:enhancement

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely summarizes the main change: adding new hideout progress endpoints for managing modules and parts.
Description check ✅ Passed The PR description is directly related to the changeset, detailing hideout progression API endpoints with specific file changes, validation patterns, service methods, and route registration that align with the actual code modifications.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
functions/src/handlers/progressHandler.ts (1)

141-166: Consider validating gameMode query parameter for dual tokens.

The handler correctly follows the established pattern for other progress endpoints. However, when gameMode === 'dual', the query parameter is used directly without validating it's one of ['pvp', 'pve']. An invalid value like ?gameMode=invalid would propagate to the service layer.

This is a pre-existing pattern across all handlers (lines 325-328, 416-419, 498-501, 597-600), so it's not introduced by this PR. Consider addressing this in a follow-up for all endpoints.

If you choose to address this:

   // Use token's game mode if specified, otherwise allow query parameter override (for dual tokens)
   let gameMode = req.apiToken?.gameMode || 'pvp';
   if (gameMode === 'dual') {
-    gameMode = req.query.gameMode as string || 'pvp';
+    const queryGameMode = req.query.gameMode as string;
+    gameMode = (queryGameMode === 'pvp' || queryGameMode === 'pve') ? queryGameMode : 'pvp';
   }
functions/src/services/ProgressService.ts (1)

14-16: Minor: HideoutModuleUpdateRequest is imported but unused.

Only HideoutModuleStatus is used in the updateHideoutModule method signature (line 259). However, keeping the import may be intentional for completeness or future use, so this is a very minor observation.

 import { 
   ProgressDocument, 
   FormattedProgress, 
   TaskStatus, 
   MultipleTaskUpdateRequest, 
   ObjectiveUpdateRequest,
   HideoutModuleStatus,
-  HideoutModuleUpdateRequest,
   HideoutPartUpdateRequest,
   ServiceOptions,
   TaskCompletion
 } from '../types/api.js';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 93f0e41 and 6bce790.

📒 Files selected for processing (5)
  • functions/src/handlers/progressHandler.ts (2 hunks)
  • functions/src/index.ts (2 hunks)
  • functions/src/services/ProgressService.ts (2 hunks)
  • functions/src/services/ValidationService.ts (3 hunks)
  • functions/src/types/api.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-25T16:14:25.438Z
Learnt from: CR
Repo: tarkovtracker-org/TarkovTracker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-25T16:14:25.438Z
Learning: Applies to functions/src/middleware/**/*.ts : Implement authentication and error handling as Express middleware under /functions/src/middleware/

Applied to files:

  • functions/src/index.ts
🧬 Code graph analysis (1)
functions/src/services/ProgressService.ts (2)
functions/src/types/api.ts (3)
  • HideoutModuleStatus (148-148)
  • ProgressDocument (82-95)
  • HideoutPartUpdateRequest (154-157)
functions/src/middleware/errorHandler.ts (1)
  • errors (114-123)
🔇 Additional comments (13)
functions/src/types/api.ts (1)

147-157: LGTM!

The new hideout types are well-defined and consistent with existing patterns (TaskStatus, ObjectiveUpdateRequest). The HideoutModuleStatus correctly excludes the 'failed' state since hideout modules don't have a failure concept, and HideoutPartUpdateRequest mirrors the existing ObjectiveUpdateRequest structure.

functions/src/services/ValidationService.ts (4)

122-128: LGTM!

The validateHideoutModuleStatus type guard correctly narrows to the HideoutModuleStatus union type using direct equality checks, which is consistent with how state validation is done inline in validateHideoutPartUpdate.


130-151: LGTM!

The validateHideoutModuleUpdate method correctly mirrors the existing validateTaskUpdate pattern, with proper null/type checks and appropriate error messages.


153-184: LGTM!

The validateHideoutPartUpdate method mirrors the existing validateObjectiveUpdate pattern exactly, maintaining consistency across the codebase. Both state and count validation logic are correctly implemented with proper type narrowing and error messages.


196-214: LGTM!

The validateModuleId and validatePartId methods follow the established patterns from validateTaskId and validateObjectiveId, with consistent null checks, type validation, and trimming behavior.

functions/src/index.ts (2)

97-98: LGTM!

The new hideout routes are correctly registered after the verifyBearer middleware (line 89), ensuring authentication is enforced. The route naming pattern (/progress/hideout/module/:moduleId) is consistent with existing progress routes.


118-119: LGTM!

The v2 API routes mirror the non-v2 routes and point to the same handlers, maintaining consistency with how other endpoints are structured (e.g., lines 114-117 for task endpoints).

functions/src/handlers/progressHandler.ts (4)

76-140: OpenAPI documentation is comprehensive.

The OpenAPI block correctly documents the endpoint, parameters, request body, and response schemas. The security requirement for bearerAuth and the game mode query parameter documentation are accurate.


168-240: OpenAPI documentation for hideout part endpoint is accurate.

The documentation correctly describes the optional nature of both state and count fields, matching the validation logic that requires at least one to be provided.


241-266: LGTM!

The updateHideoutPart handler correctly mirrors the pattern from updateTaskObjective (lines 589-614), including spreading updateData into the response to return whichever fields were provided.


622-623: LGTM!

The new handlers are correctly added to the default export, making them available for route registration.

functions/src/services/ProgressService.ts (2)

253-293: LGTM!

The updateHideoutModule method correctly mirrors the state-handling pattern from updateTaskObjective, with appropriate logging and error handling. The use of FieldValue.delete() for the timestamp when uncompleting is consistent with existing behavior.


295-341: LGTM!

The updateHideoutPart method is a clean implementation that mirrors updateTaskObjective (lines 207-251). Both state and count updates are handled correctly, and the error handling follows established patterns.

@DysektAI DysektAI self-assigned this Nov 30, 2025
@DysektAI
Copy link
Member

Thank you for the PR I will check it and migrate it over to the new project since we are modularizing the functions and backend from the frontend and going to be deprecating the usage of firebase (Also this main branch is behind due to technical issues which will trigger a domino effect of lost fixes and features that got lost after deployment of the latest version so can't deploy this or merge without causing more issues to resurface.)

@DysektAI DysektAI added status:blocked Progress is blocked by another issue or dependency type:feature Type label for PR's ONLY use "Types" instead for Issues. priority:medium Important but not blocking - should be scheduled soon. status:never-stale Do not auto-stale or auto-close. Long-lived placeholder. labels Nov 30, 2025
@JoShMiQueL
Copy link
Author

Thank you for the PR I will check it and migrate it over to the new project since we are modularizing the functions and backend from the frontend and going to be deprecating the usage of firebase (Also this main branch is behind due to technical issues which will trigger a domino effect of lost fixes and features that got lost after deployment of the latest version so can't deploy this or merge without causing more issues to resurface.)

Thanks for the explanation! I completely understand the situation regarding the migration/refactor and the state of the main branch.

It sounds like a solid plan to move this over to the new project once it's ready. Please do tag me when the migration is stable enough, and I'll be happy to port these changes or reopen the PR there.

Good luck with the migration!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority:medium Important but not blocking - should be scheduled soon. status:blocked Progress is blocked by another issue or dependency status:never-stale Do not auto-stale or auto-close. Long-lived placeholder. type:enhancement type:feature Type label for PR's ONLY use "Types" instead for Issues.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add API endpoint for Hideout progress updates

2 participants