feat(api): implement extensible uri and header versioning (#92) - #224
Merged
mijinummi merged 1 commit intoAug 24, 2026
Merged
Conversation
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the API versioning architecture defined in #92, introducing a centralized, extensible version-resolution layer that supports both URI-based and HTTP-header-based version negotiation.
The implementation separates version dispatching from controller/domain logic, allowing multiple API versions to run concurrently while preserving backward compatibility with the existing V1 API.
What Changed
API Version Resolution
Added a centralized
versionResolvermiddleware.Added Strategy Pattern-based version resolution.
Supports version selection through:
/api/v1/...,/api/v2/...X-API-Versionheaderapplication/vnd.company.v2+jsonAdded fallback to the configured default version (
V1) when no explicit version is provided.Added validation for unsupported/invalid API versions.
Versioned Routing
Added version-specific API namespaces:
src/api/v1/src/api/v2/Introduced reusable
createVersionedRouter()route factory.Decoupled version routing from domain/controller logic.
Maintained strict separation between V1 and V2 controllers, DTOs, and response transformations.
Deprecation Management
Added centralized deprecation handling for legacy API routes.
Deprecated endpoints now return standardized response metadata:
Deprecation: trueSunset: Sun, 31 Dec 2028 23:59:59 GMTLink: <...>; rel="successor-version"This allows clients to identify deprecated endpoints and migrate to their successor versions without embedding deprecation logic inside individual controllers.
OpenAPI Documentation
Added version-scoped OpenAPI documentation.
Added independent specifications for:
/docs/v1/swagger.json/docs/v2/swagger.jsonAdded version-specific Swagger UI:
/docs/v1/docs/v2Version Resolution Precedence
The resolver follows a deterministic precedence order:
For example:
The URI version takes precedence and resolves the request against V2.
When no URI version is provided:
the request resolves against V2.
When neither mechanism is provided:
the request falls back to V1.
Backward Compatibility
Existing unversioned endpoints continue to execute within the V1 context.
This preserves existing client integrations while allowing V2 endpoints to be introduced incrementally without forcing synchronized client migrations.
Error Handling
Unsupported or invalid version requests are explicitly rejected rather than silently routed to an unintended controller.
The implementation covers:
Depending on the validation path, invalid negotiation requests return
400 Bad Requestor406 Not Acceptable.Testing
Added/updated unit and integration coverage for:
X-API-Versionheader resolution.Acceptance Criteria
X-API-Versionheader resolution is supported.Review Notes
Please pay particular attention to:
Related Issue
Closes #92
Suggested Test Commands
npm test npm run test:e2e npm run build