Skip to content

feat!: drop GlobalOptions.session in favor of URLSessionTransport(session:) - #1326

Merged
grdsdev merged 1 commit into
guilhermesouza/sdk-1786-expose-one-public-transport-protocol-and-middleware-chainfrom
guilhermesouza/sdk-1820-drop-globaloptionssession-the-http-session-lives-on
Sep 14, 2026
Merged

grdsdev merged 1 commit into
guilhermesouza/sdk-1786-expose-one-public-transport-protocol-and-middleware-chainfrom
guilhermesouza/sdk-1820-drop-globaloptionssession-the-http-session-lives-on

Conversation

@grdsdev

@grdsdev grdsdev commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

What

Removes SupabaseClientOptions.GlobalOptions.session. The URLSession HTTP goes through is now configured on the transport only:

// Before
global: .init(session: mySession)

// After
global: .init(http: .init(transport: URLSessionTransport(session: mySession)))
  • Sources/Supabase/Types.swift: property and init parameter removed, docs updated.
  • Sources/Supabase/SupabaseClient.swift: the resolved transport is http.transport ?? URLSessionTransport(); the copy of the global session into RealtimeClientOptions.session is gone.
  • Realtime's WebSocket session is configured only on RealtimeClientOptions.session. It no longer inherits a global one.
  • V3_MIGRATION.md: new section "SupabaseClientOptions.GlobalOptions.session is removed"; the earlier "GlobalOptions.session stays" note under the transport section is deleted.
  • README and the OpenTelemetryDemo example use the transport form.

Why

After #1325, GlobalOptions had two knobs for HTTP. session backed the default transport only while http.transport was nil, so a caller who set both silently lost the session for HTTP. It was also copied into Realtime for the WebSocket, which never goes through ClientTransport. One knob now configures HTTP, and Realtime's socket session is set where it lives.

Stacked on #1325 (base branch guilhermesouza/sdk-1786-expose-one-public-transport-protocol-and-middleware-chain). Retarget to main once that merges.

Test plan

  • SupabaseClientTests: the two realtime-session propagation tests are replaced by one that checks a Realtime-specific session is preserved and that the HTTP transport's session does not leak into Realtime. Seven other test call sites move from GlobalOptions(session:) to the transport form with no behavior change.

Verification

swift test --no-parallel
━ Test run with 1418 tests in 141 suites passed after 13.272 seconds with 1 known issue.

./scripts/format.sh        # no changes
./scripts/spell-check.sh   # Files checked: 394, Issues found: 0
./scripts/test-docs.sh     # exit 0, 0 warnings

Fixes SDK-1820

@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • develop

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 911925a8-b480-432a-9849-d98edae714dc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

⚠️ Capability matrix drift detected

The following capabilities are marked implemented in the matrix but could not be found in swift:

  • client.session_management.persist_session → expected symbol: AuthLocalStorage.defaultLocalStorage
  • functions.invocation.streaming_response → expected symbol: FunctionsClient._invokeWithStreamedResponse

The following capabilities are marked implemented in swift but have no registered symbols to verify:

  • auth.passkey.register_passkey (no symbols list — cannot confirm implementation exists)
  • auth.passkey.sign_in_with_passkey (no symbols list — cannot confirm implementation exists)
  • client.observability.trace_propagation (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.request_cancellation (no symbols list — cannot confirm implementation exists)
  • functions.invocation.request_cancellation (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.url_cache_nonce (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.request_cancellation (no symbols list — cannot confirm implementation exists)

These may have been renamed, removed, or never registered. Please update the capability matrix.
See: https://github.com/supabase/sdk/blob/main/packages/capability-matrix/docs/capability-matrix.md

@grdsdev
grdsdev force-pushed the guilhermesouza/sdk-1786-expose-one-public-transport-protocol-and-middleware-chain branch from b5fd555 to 0f227f3 Compare September 14, 2026 09:41
@grdsdev
grdsdev force-pushed the guilhermesouza/sdk-1820-drop-globaloptionssession-the-http-session-lives-on branch from de46518 to 5631925 Compare September 14, 2026 09:43
…sion:)

`SupabaseClientOptions.GlobalOptions` had two ways to configure HTTP: `session`
backed the default transport only while `http.transport` was nil, and was also
copied into Realtime's WebSocket options. One knob now configures HTTP: pass
`URLSessionTransport(session:)` as `GlobalOptions.http.transport`. Realtime's
WebSocket session is configured only on `RealtimeClientOptions.session` and no
longer inherits a global one.

BREAKING CHANGE: `GlobalOptions.init` has no `session:` parameter and
`GlobalOptions.session` is removed. See V3_MIGRATION.md.

Fixes SDK-1820

Co-Authored-By: Claude <noreply@anthropic.com>
@grdsdev
grdsdev force-pushed the guilhermesouza/sdk-1820-drop-globaloptionssession-the-http-session-lives-on branch from 5631925 to 59db72b Compare September 14, 2026 09:48
@grdsdev
grdsdev marked this pull request as ready for review September 14, 2026 12:53
@grdsdev
grdsdev requested a review from a team as a code owner September 14, 2026 12:53
@grdsdev
grdsdev merged commit 16e90b1 into guilhermesouza/sdk-1786-expose-one-public-transport-protocol-and-middleware-chain Sep 14, 2026
5 of 6 checks passed
@grdsdev
grdsdev deleted the guilhermesouza/sdk-1820-drop-globaloptionssession-the-http-session-lives-on branch September 14, 2026 12:53
grdsdev added a commit that referenced this pull request Sep 14, 2026
…sion:) (#1326)

`SupabaseClientOptions.GlobalOptions` had two ways to configure HTTP: `session`
backed the default transport only while `http.transport` was nil, and was also
copied into Realtime's WebSocket options. One knob now configures HTTP: pass
`URLSessionTransport(session:)` as `GlobalOptions.http.transport`. Realtime's
WebSocket session is configured only on `RealtimeClientOptions.session` and no
longer inherits a global one.

BREAKING CHANGE: `GlobalOptions.init` has no `session:` parameter and
`GlobalOptions.session` is removed. See V3_MIGRATION.md.

Fixes SDK-1820

Co-authored-by: Claude <noreply@anthropic.com>
grdsdev added a commit that referenced this pull request Sep 14, 2026
…ss all modules (#1325)

* feat(helpers): add HTTPBody, the streaming body for the public transport

* docs(helpers): add missing DocC comments to HTTPBody public API

* feat(helpers): add ClientTransport, ClientMiddleware and URLSessionTransport

* fix(helpers): address review feedback on URLSessionTransport

Add missing DocC on send(), clarify the streamed-response buffering
comments (unbounded stream, bounded chunk size), document why
Content-Length is set explicitly, simplify makeBody, note the
buffered-vs-streamed iterationBehavior split on the type doc, and
strengthen the buffered-GET test to assert length/iterationBehavior.

* refactor(helpers): run HTTPClient over ClientTransport and ClientMiddleware

* fix(helpers): drain a discarded response body before retrying

* feat(auth)!: replace fetch with transport and middlewares

AuthClient.Configuration now takes transport: any ClientTransport and
middlewares: [any ClientMiddleware] instead of a raw fetch closure, matching
the ClientTransport/ClientMiddleware seam introduced in Helpers. Auth's
internal HTTPClient no longer goes through the temporary FetchTransport
adapter for its own configuration.

SupabaseClient keeps wiring its OpenTelemetry-tracing fetch closure into
AuthClient through FetchTransport for now; SupabaseClientOptions.global gains
its own transport/middlewares in a follow-up.

* feat(postgrest)!: replace fetch with transport and middlewares

* fix(postgrest): capture nil body on bodiless requests in test helpers

QueryCapture/RequestCapture only called capturedBody.setValue when the
request had a body, so a capture instance reused for a later bodiless
request kept returning the previous request's body from bodyString.

* feat(functions)!: replace fetch with transport and stream responses through it

* feat(storage)!: replace StorageHTTPSession with transport and middlewares

* feat(realtime)!: replace fetch with transport and middlewares

* feat(supabase)!: add global.transport and global.middlewares

* fix(supabase): keep caller realtime middlewares and prove middleware ordering

* refactor!: delete HTTPRuntime, superseded by the public ClientTransport

* docs!: migration guide and compliance for the public transport

* fix(helpers): harden logger and file body streaming, serialize Mocker suite, add chunk-split tests

* refactor!: group transport and middlewares into HTTPClientConfiguration

* docs(helpers): update transport samples for HTTPClientConfiguration

* fix(helpers): import FoundationNetworking in HTTPClientTests and register transport symbols

`HTTPClientTests` reads `HTTPURLResponse.url`, which lives in FoundationNetworking on
Linux; the missing import broke the Linux and Linux integration CI jobs.

The capability-matrix check flagged every public member of the new transport API as
unregistered. They are now listed under `client.request_configuration.custom_http_client`:
the per-module `http` configuration properties as entry points, and the `HTTPBody`,
`HTTPClientConfiguration`, `ClientTransport`, `ClientMiddleware` and `URLSessionTransport`
members as supporting symbols.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(helpers): skip the file-body mock assertion on Linux

swift-corelibs-foundation keeps a file upload on the URLSessionTask, not on the
`URLRequest` that `MockingURLProtocol` observes, so the mock sees no body there and the
assertion failed on the Linux CI job. The status and response-body checks still run on
every platform.

Co-Authored-By: Claude <noreply@anthropic.com>

* feat!: drop GlobalOptions.session in favor of URLSessionTransport(session:) (#1326)

`SupabaseClientOptions.GlobalOptions` had two ways to configure HTTP: `session`
backed the default transport only while `http.transport` was nil, and was also
copied into Realtime's WebSocket options. One knob now configures HTTP: pass
`URLSessionTransport(session:)` as `GlobalOptions.http.transport`. Realtime's
WebSocket session is configured only on `RealtimeClientOptions.session` and no
longer inherits a global one.

BREAKING CHANGE: `GlobalOptions.init` has no `session:` parameter and
`GlobalOptions.session` is removed. See V3_MIGRATION.md.

Fixes SDK-1820

Co-authored-by: Claude <noreply@anthropic.com>

* perf(helpers): stream responses from a task delegate instead of per-byte AsyncBytes

`URLSessionTransport` iterated `URLSession.AsyncBytes` one byte at a time and yielded a
chunk at every newline. Against a local Storage server a 200 MiB download took 10 s where
curl takes 0.6 s, and the unbounded chunk backlog cost 29 to 44 MB even for a consumer
that discards every chunk.

The Darwin path now runs a `URLSessionDataDelegate` on the data task: the head is handed
back as soon as `didReceive(response:)` fires and every `didReceive(data:)` delivery is one
chunk. Same download now takes 0.65 s with a 1 to 2 MB streaming floor. Chunk boundaries
follow the network rather than the payload, so the migration note tells SSE consumers to
reassemble on the frame separator; the newline-split test is replaced by one that asserts
chunks are passed through as received, plus a failure-path test.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant