HTTP Repository Skill
Standardize how HTTP-based repositories are implemented and tested in Shell
(e.g., HTTPItemsRepository, HTTPUserProfileRepository).
When to use
- •When creating a new HTTP repository.
- •When refactoring network code into repository implementations.
- •During Epic 3 (API integration) and beyond.
Design principles
- •Repositories:
- •Implement existing repository protocols from Domain/Contracts.
- •Use a shared
HTTPClientabstraction (e.g., based onURLSession). - •Map raw JSON to domain models via dedicated mappers/adapters.
- •Handle error mapping (status codes → domain errors) consistently.
Steps
- •
Ask the user which repository to create or update:
- •Examples: "Items", "UserProfile", "Auth".
- •
Identify or create the protocol in Domain:
- •Locate
Shell/Features/<Feature>/Domain/Contracts/*Repository.swift. - •If missing, define a protocol with async methods aligned to domain needs.
- •Locate
- •
Create the HTTP repository file:
- •
Path:
Shell/Features/<Feature>/Infrastructure/Repositories/HTTP<Feature>Repository.swift - •
Structure:
swiftactor HTTP<Feature>Repository: <Feature>Repository { private let httpClient: HTTPClient private let baseURL: URL init(httpClient: HTTPClient, baseURL: URL) { self.httpClient = httpClient self.baseURL = baseURL } // Implement protocol methods: fetch, create, update, delete, etc. }
- •
- •
Define DTOs and mappers:
- •Create a
DTOsorRemoteModelsnamespace/file if appropriate. - •Map between JSON and domain types using small, pure mappers.
- •Keep mapping logic out of ViewModels and controllers.
- •Create a
- •
Implement error handling:
- •Map HTTP status codes and network failures to domain-specific errors.
- •Example mapping:
- •400 →
.invalidRequest - •401/403 →
.unauthorized - •404 →
.notFound - •500+ or connectivity issues →
.serverError/.networkError(underlying:)
- •400 →
- •
Wire repository into
AppDependencyContainer:- •
Add configuration to select between in-memory and HTTP repos.
- •
Example:
swiftif environment.useHTTPItems { itemsRepository = HTTPItemsRepository(httpClient: httpClient, baseURL: baseURL) } else { itemsRepository = InMemoryItemsRepository() }
- •
- •
Generate tests using
URLProtocolstubs:- •Path:
ShellTests/Features/<Feature>/Infrastructure/Repositories/HTTP<Feature>RepositoryTests.swift - •Use a custom
URLProtocolsubclass to:- •Intercept requests.
- •Provide canned responses and errors.
- •Test:
- •Success paths (correct JSON → correct domain objects).
- •Error mapping (status codes → domain errors).
- •Edge cases (empty responses, invalid JSON).
- •Path:
- •
Summarize:
- •Files created/updated.
- •Next steps (e.g., "Update use cases or feature flags to use this repository").