feat: API extensibility — protected surface + archived filter (closes #4)#7
Merged
Conversation
Flip the low-level primitives (paging family, response handling, JSON content builders, GetBaseUrl) from private to protected so consumers can subclass BitbucketClient and implement custom endpoints without forking — the primary extensibility ask in #4. Static helpers stay static. Adds ExtensibilityMockTests proving a subclass can build a custom paged endpoint purely from the protected surface (single- and multi-page). Refs #4
Flip all 50 Get*Url() request builders (GetReposUrl, GetAdminUrl, GetProjectsUrl, GetPatUrl, ...) from private to protected so subclasses can compose feature endpoints without reimplementing URL construction. Pairs with the protected GetBaseUrl exposed in the previous commit. Refs #4
Add a RepositoryArchivedState { Active, Archived, All } enum (mapped to the
documented ACTIVE/ARCHIVED/ALL query values) and overloads of
GetRepositoriesAsync / GetRepositoriesStreamAsync on ISearchOperations that
filter the /repos search endpoint by archived state. The new overload takes
archived as a required lead argument, so it is additive and never ambiguous
against the existing all-optional signature. Shared query construction is
factored into BuildRepositoriesQuery.
Per the official REST descriptor, archived filtering lives on /repos (not on
the per-project repos listing), so it is surfaced there.
Refs #4
…Async Add the avatarSize query parameter to GetPullRequestCommentLikesAsync so it matches its sibling GetCommitCommentLikesAsync (both return users). Modeled inline as a trailing optional to mirror the sibling exactly; an overload was unsuitable because an int avatarSize collides with the existing int? paging optionals and would silently rebind positional callers. Refs #4
The WireMock.Net meta-package bundles WireMock.Net.OpenTelemetry, which drags in OpenTelemetry 1.14.0 transitively. Those packages carry moderate-severity advisories, so the NuGet vulnerability audit raises NU1902 and TreatWarningsAsErrors promotes it to an error — breaking restore/build of the test project (and thus CI) even though the code is unrelated. Switch to WireMock.Net.Minimal (same version), which exposes the identical core APIs the tests use (WireMockServer, Request/Response builders, matchers) without the optional OpenTelemetry/GraphQL/CSScript bundles. Removes the vulnerable transitive tree entirely rather than suppressing the audit.
Apply dotnet format whitespace/style to the files added in this branch so they satisfy the repo's verify-format CI gate (CRLF + single final newline per .editorconfig).
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
Makes
BitbucketClientextensible without forking — the actionable idea from #4 — plus a couple of adjacent, repo-first improvements. Decisions were made for the health of the library (and its consumer,stash-mcp), favouring a clean, documented-only API over literal satisfaction of the original request.Closes #4.
What changed
protectedinstead ofprivate: the paging family (GetPagedAsync/GetPagedResultsAsync+ streams), response handlers (HandleResponseAsync/HandleErrorsAsync/ReadResponse*), JSON content builders,GetBaseUrl, and all 50 per-featureGet*Url()helpers. A subclass can now implement custom endpoints by reusing these primitives. 0 → 65protectedmembers; no public signature changed; nothing leaked onto an interface.RepositoryArchivedState { Active, Archived, All }enum (mapped to the documentedACTIVE/ARCHIVED/ALL) and additiveGetRepositoriesAsync/GetRepositoriesStreamAsyncoverloads onISearchOperationsthat filter the/repossearch endpoint.archivedis a required lead argument, so existing all-optional signatures are untouched and resolution is unambiguous.GetPullRequestCommentLikesAsyncgainedavatarSize, matching its siblingGetCommitCommentLikesAsync.WireMock.Netmeta-package toWireMock.Net.Minimal, removing the bundledWireMock.Net.OpenTelemetry → OpenTelemetry 1.14.0transitive tree that tripped the NuGet audit (NU1902) underTreatWarningsAsErrorsand broke restore/build. Same core test APIs; the OpenTelemetry feature was never used.[Unreleased]section; README "Extending the client" + "Filtering archived repositories".Decisions (repo-first)
archivedlives on/repossearch, notGetProjectRepositoriesAsync. The official REST descriptor documents thearchivedfilter on the repository-search endpoint, not the per-project listing — so it's surfaced where the API actually supports it.deletedon users,from/toon audit,fromTypeon the PR list). None could be confirmed in the official Bitbucket REST API — same situation asarchived. Shipping silently-ignored parameters would muddy the surface with version-dependent quirks, so they were left out.avatarSizestayed because it's the documented, sibling-established parameter.protected, notpublic: keeps a clean subclassing path without freezing internals into a forever-supported public contract.Testing
ExtensibilityMockTests— a subclass builds a custom paged endpoint purely from the protected helpers (single- and multi-page).RepositorySearchMockTests—ACTIVE/ARCHIVED/ALLare transmitted; the base overload omitsarchived.avatarSizetransmission test onGetPullRequestCommentLikesAsync.TreatWarningsAsErrors.