refactor!: share a single HttpMethod enum across the packages - #1678
Conversation
📝 WalkthroughWalkthroughThe pull request introduces a shared ChangesShared HTTP method migration
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
QuintinWillison
left a comment
There was a problem hiding this comment.
My Dart's not good enough to comment fully on correctness there, but fully support the reduction of repetition! 💪
functions_client and postgrest each declared their own HttpMethod, with different values and a different order, so the umbrella library had to export postgrest with `hide HttpMethod` and the capability matrix could not tell the two apart in its flat symbol registry. Both now re-export one enum from supabase_common, taking postgrest's shape: the six methods plus the value getter that functions_client used to open-code as name.toUpperCase(). Nothing changes for callers of either package, and supabase can export postgrest whole again. functions.invocation.method_override registers FunctionsClient.invoke, since the shared enum lives outside the scanned public API surface.
gotrue had its own @internal RequestMethodType with the same five values, and storage_client passed bare method strings around, including a `method != 'GET'` check to decide on a JSON content type. Both now use the shared enum, so there is one representation of an HTTP method across the packages. Both declarations were internal, so no public API changes. gotrue's dispatch switch gains a head branch to stay exhaustive, and skips the JSON content type for it as well as for get.
a9bf54e to
d34fb96
Compare
The shared HttpMethod enum moves into supabase_common (#1678), which the public API scan excludes, so registering it here would leave a dangling entry once that lands. FunctionsClient.invoke is the entry point a caller actually reaches for anyway.
Typing the parameter as HttpMethod turned the interpolation in the log line into the enum's default toString, so it printed HttpMethod.get where it used to print GET.
d34fb96 to
0a85ab9
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/functions_client/test/functions_dart_test.dart (1)
8-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a
HEADrequest test.The package tests cover GET, PUT, DELETE, and PATCH, but not
HttpMethod.head. Add a request-capturing test that assertsrequest.method == 'HEAD'. The test does not need to read a response body.As per coding guidelines,
packages/*/test/**/*.dartmust add or maintain tests for modified package behavior and run the package's test suite.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/functions_client/test/functions_dart_test.dart` at line 8, Add a request-capturing test in the functions client test suite for HttpMethod.head, asserting the captured request method is 'HEAD' without reading a response body. Follow the existing GET/PUT/DELETE/PATCH test patterns and run the package test suite.Source: Coding guidelines
packages/gotrue/test/fetch_test.dart (1)
201-226: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover the new
HttpMethod.headbehavior.The fetch implementation adds a
HEADdispatch branch and changes automatic JSONContent-Typehandling forGETandHEAD. This test file exercises onlyHttpMethod.get. Add a focused mock-client test that verifies theHEADpath and confirms that automatic JSON content metadata is not added. Run the GoTrue test suite. Usedart test -j 1for backend-dependent tests.As per coding guidelines:
packages/*/test/**/*.dartmust add or maintain tests for modified package behavior and run the package's test suite; backend-dependent GoTrue tests must run sequentially withdart test -j 1.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/gotrue/test/fetch_test.dart` around lines 201 - 226, Add a focused mock-client test near _testFetchRequest that calls GotrueFetch.request with HttpMethod.head, verifies the HEAD dispatch behavior, and asserts automatic JSON Content-Type metadata is absent. Follow existing test conventions, then run the GoTrue package suite with backend-dependent tests executed via dart test -j 1.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/functions_client/test/functions_dart_test.dart`:
- Line 8: Add a request-capturing test in the functions client test suite for
HttpMethod.head, asserting the captured request method is 'HEAD' without reading
a response body. Follow the existing GET/PUT/DELETE/PATCH test patterns and run
the package test suite.
In `@packages/gotrue/test/fetch_test.dart`:
- Around line 201-226: Add a focused mock-client test near _testFetchRequest
that calls GotrueFetch.request with HttpMethod.head, verifies the HEAD dispatch
behavior, and asserts automatic JSON Content-Type metadata is absent. Follow
existing test conventions, then run the GoTrue package suite with
backend-dependent tests executed via dart test -j 1.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a75debce-1200-4924-86e3-baa5c3059361
📒 Files selected for processing (24)
examples/edge_functions/integration_test/invoke_test.dartpackages/functions_client/lib/functions_client.dartpackages/functions_client/lib/src/functions_client.dartpackages/functions_client/lib/src/types.dartpackages/functions_client/test/functions_dart_test.dartpackages/gotrue/lib/src/fetch.dartpackages/gotrue/lib/src/gotrue_admin_api.dartpackages/gotrue/lib/src/gotrue_admin_custom_providers_api.dartpackages/gotrue/lib/src/gotrue_admin_mfa_api.dartpackages/gotrue/lib/src/gotrue_admin_oauth_api.dartpackages/gotrue/lib/src/gotrue_admin_passkey_api.dartpackages/gotrue/lib/src/gotrue_client.dartpackages/gotrue/lib/src/gotrue_mfa_api.dartpackages/gotrue/lib/src/gotrue_oauth_api.dartpackages/gotrue/lib/src/gotrue_passkey_api.dartpackages/gotrue/test/fetch_test.dartpackages/postgrest/lib/postgrest.dartpackages/postgrest/lib/src/postgrest_builder.dartpackages/storage_client/lib/src/fetch.dartpackages/storage_client/lib/src/iceberg/iceberg_rest_catalog.dartpackages/supabase/lib/supabase.dartpackages/supabase_common/lib/src/http_method.dartpackages/supabase_common/lib/supabase_common.dartsdk-compliance.yaml
💤 Files with no reviewable changes (2)
- packages/postgrest/lib/src/postgrest_builder.dart
- packages/functions_client/lib/src/types.dart
The functions_client enum gained head and reordered its values when it merged with postgrest's (#1678), so an exhaustive switch stops compiling and index shifts for post, put and delete.
Follow-up to #1678, which landed without a migration note. ## Why Merging the two `HttpMethod` enums changed the one that `functions_client` exported, and both effects are things a caller can hit: - `head` joined the enum, so an exhaustive `switch` over `HttpMethod` in user code stops compiling. Verified: the analyzer reports `non_exhaustive_switch_expression`. - The declaration order changed, so `index` moved for `post`, `put` and `delete`. That one is silent, which is exactly the kind of change this guide flags. Nothing changes for callers who only used postgrest's enum, and no import paths change, since the shared enum is re-exported from both packages. ## What changed One section added to the v3 list in `MIGRATION.md`: 13 lines, two bullets, no snippets. The shifted indices were read off the runtime output of iterating the merged enum (`get=0 head=1 post=2 put=3 patch=4 delete=5`) rather than derived by hand. Docs only, no code changes. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for the `HEAD` HTTP method. * Standardized HTTP method handling across Functions and PostgREST integrations. * Added uppercase wire-format values for HTTP methods. * Improved compatibility for sharing HTTP method definitions across integrations. * **Documentation** * Added migration guidance for updating method-based switches. * Documented replacing persisted numeric method indices with stable method names. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Why
Four different representations of an HTTP method coexisted across the packages:
functions_clientenum HttpMethodmethod.name.toUpperCase(), open-coded at two call sitespostgrestenum HttpMethodString get value => name.toUpperCase()gotrue@internal enum RequestMethodTypehttp.Client'sget/post/ …storage_clientString'GET','POST','PUT','DELETE','HEAD'The two public enums shared a name while disagreeing on contents, which forced
supabase.dartto export postgrest withhide HttpMethod, making postgrest's enum unreachable through the umbrella library. It also confused the capability matrix, which keys symbols by bare name: it registeredHttpMethodfor functions andHttpMethod.valuefor postgrest as if they were one type.The stringly-typed side had its own cost.
storage_clientcomparedmethod != 'GET'to decide whether to set a JSON content type, in both itsFetchhelper and its Iceberg REST catalog.What changed
One
HttpMethodinsupabase_common, taking postgrest's shape: the six methods plus thevaluegetter thatfunctions_clientused to open-code.Public surface:
functions_clientandpostgrestre-export the shared enum, so callers of either library see no change.supabase.dartexports postgrest whole again.functions.invocation.method_overrideregistersFunctionsClient.invoke, since the shared enum lives insupabase_common, which.sdk-parse-ignoreexcludes from the scanned public API surface. A note records that the Dart enum also offershead, which supabase-js does not expose for function invocation.edge_functionsexample's "every HTTP method" test skipshead, whose response carries no body for the echo function to reflect, and asserts againstmethod.value.Internal adoption, no public API change since both declarations were
@internal:gotrue:RequestMethodTypeis gone and its roughly 65 call sites use the shared enum.GotrueFetch's dispatch switch gains aheadbranch to stay exhaustive over six values, wired tohttp.Client.head, and now skips the JSON content type forheadas well as forget. No gotrue call site issues a HEAD today, so that branch is currently unexercised.storage_client:Fetch's private request helpers and the Iceberg catalog's_requesttake anHttpMethodinstead of aString, the wire strings come from.value, and the content-type branch compares enum values. The public wrapper method names (get,post,head, and so on) are unchanged.Every log line that interpolates a method uses
.value, so they keep printingGETrather than the enum's defaulttoString.The
supabase_commonpins stay at0.1.2;melos versionrewrites dependents' pins at release time.Merge order
This targets
maindirectly and does not depend on #1673 or #1677, though it came out of the same review thread. #1673 previously registeredHttpMethodandHttpMethod.value, which this PR makes dangling; those registrations have been pruned on that branch, so the two can merge in either order.Verification
dart analyzeclean across all packages and examples.dcm analyzereports no issues in any file this PR touches.--concurrency=1the workflow uses:gotrue(479),storage_client(210),postgrest(196),functions_client(48).mainas the base.Summary by CodeRabbit
New Features
HttpMethodAPI covering GET, HEAD, POST, PUT, PATCH, and DELETE.HttpMethodavailable through the relevant client libraries.Bug Fixes