Skip to content

Conversation

@gulivan
Copy link

@gulivan gulivan commented Nov 26, 2025

Summary

  • Fix bug where async headers config functions were not being awaited
  • The Promise object was being passed through instead of the resolved header values
  • This aligns headers behavior with onRequest which already properly awaits async functions

Changes

  • Make processHeaders async and await function results
  • Move config header processing inside async IIFE
  • Update TypeScript type to allow MaybePromise return from header functions
  • Add test for async headers configuration

Test plan

  • Added test case for async headers configuration
  • All existing tests pass (89 pass, 0 fail)

Summary by CodeRabbit

  • New Features

    • Headers configuration now supports asynchronous resolution, allowing headers to be dynamically determined through async operations without blocking initialization.
  • Tests

    • Added test coverage for asynchronous header configuration scenarios with async response handlers.

✏️ Tip: You can customize this high-level summary in your review settings.

The `headers` config option was not awaiting async functions, causing
Promise objects to be passed through instead of resolved header values.

- Make `processHeaders` async and await function results
- Move config header processing inside async IIFE
- Update type to allow `MaybePromise` return from header functions
- Add test for async headers configuration
@coderabbitai
Copy link

coderabbitai bot commented Nov 26, 2025

Walkthrough

The pull request converts header processing from synchronous to asynchronous operations. The processHeaders function now returns a promise, and all invocation sites use await to resolve headers. The Config.headers callback type is updated to support both synchronous and promise-returning functions via MaybePromise.

Changes

Cohort / File(s) Change Summary
Type Definition Updates
src/treaty2/types.ts
Updated Treaty.Config.headers callback signature to return MaybePromise<RequestInit['headers'] | void> instead of RequestInit['headers'] | void, enabling async header resolution.
Async Header Processing
src/treaty2/index.ts
Converted processHeaders function from synchronous to asynchronous with Promise return type; updated all internal recursive calls and invocation sites within createProxy to use await, affecting header merging and fetch initialization flows.
Test Coverage
test/treaty2.test.ts
Added new test case "accept async headers configuration" that validates async headers callbacks and async response interception together.

Sequence Diagram

sequenceDiagram
    participant Client
    participant createProxy
    participant processHeaders as processHeaders<br/>(async)
    participant onRequest
    participant fetch

    rect rgba(100, 150, 200, 0.2)
    Note over Client,fetch: New Async Flow
    Client->>createProxy: Request with async headers callback
    createProxy->>processHeaders: await processHeaders()
    activate processHeaders
    processHeaders-->>createProxy: Promise<headers>
    deactivate processHeaders
    createProxy->>createProxy: await Promise resolution
    createProxy->>onRequest: invoke with resolved headers
    onRequest->>fetch: initiate fetch with merged headers
    fetch-->>Client: Response
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • src/treaty2/index.ts: Requires careful verification that all processHeaders call sites correctly use await and that the async control flow properly cascades through header merging branches and fetch initialization.
  • src/treaty2/types.ts: Straightforward type signature update with MaybePromise wrapper.
  • test/treaty2.test.ts: New async test case validation is clear but should be cross-checked against existing synchronous header test expectations.

Poem

🐰 Headers once synchronous, now dance with time,
Awaiting promises in asynchronous rhyme,
Promise-wrapped callbacks spring forth with grace,
While fetch races onward, keeping steady pace! 🎉

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: properly await async headers functions in treaty' clearly and specifically describes the main change: fixing async headers functions by properly awaiting them.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/treaty2/index.ts (1)

91-98: Wrap the case 'function' declaration in a block.

The static analysis correctly identifies that const v declared inside a switch case can be erroneously accessed from other cases. Wrap the case body in a block to restrict scope.

         case 'function':
             if (h instanceof Headers)
                 return processHeaders(h, path, options, headers)
-
-            const v = await h(path, options)
-            if (v) return processHeaders(v, path, options, headers)
-            return headers
+            {
+                const v = await h(path, options)
+                if (v) return processHeaders(v, path, options, headers)
+                return headers
+            }
🧹 Nitpick comments (2)
src/treaty2/index.ts (1)

397-406: Duplicate onRequest processing block.

This block (lines 387-407) duplicates the earlier onRequest processing (lines 292-312). Both iterate over onRequest handlers and merge headers identically. Consider consolidating to avoid code duplication and potential inconsistencies if one block is updated but not the other.

#!/bin/bash
# Verify the duplicate onRequest blocks
rg -n -A 15 'if \(onRequest\)' src/treaty2/index.ts
src/treaty2/types.ts (1)

246-246: Duplicate MaybePromise type definition.

MaybePromise is defined identically at line 59 (module scope) and line 246 (within Treaty namespace). Consider removing the duplicate and using the module-level definition.

-    type MaybePromise<T> = T | Promise<T>
+    // Use module-level MaybePromise defined at line 59
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5441e9 and a17808a.

📒 Files selected for processing (3)
  • src/treaty2/index.ts (6 hunks)
  • src/treaty2/types.ts (1 hunks)
  • test/treaty2.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/treaty2/index.ts (1)
src/treaty2/types.ts (1)
  • Config (175-193)
test/treaty2.test.ts (2)
src/treaty2/index.ts (1)
  • treaty (517-543)
example/a.ts (1)
  • app (4-19)
🪛 Biome (2.1.2)
src/treaty2/index.ts

[error] 96-96: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (5)
src/treaty2/index.ts (3)

67-72: LGTM! Correct async conversion of processHeaders.

The function signature is properly updated to be async and return a Promise. This aligns with the PR objective to properly await async header functions.


260-278: LGTM! Proper async header resolution.

The config headers and per-request headers are both correctly awaited before being merged into fetchInit. The sequential processing ensures headers are fully resolved before the request is made.


302-311: LGTM! Consistent async handling in onRequest handlers.

Headers from onRequest callbacks are properly awaited and merged, maintaining consistency with the config header processing.

test/treaty2.test.ts (1)

575-604: LGTM! Good test coverage for async headers.

The test properly validates the async header configuration fix by:

  1. Using an async function with a simulated delay
  2. Conditionally returning headers based on path
  3. Verifying the resolved header value is correctly applied

This directly tests the bug fix described in the PR objectives.

src/treaty2/types.ts (1)

178-184: LGTM! Type correctly updated to support async headers.

The MaybePromise wrapper allows header functions to return either synchronous or promise-based results, aligning with the runtime implementation changes.

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