Skip to content

feat!: replace axios with native fetch#366

Open
rhamzeh wants to merge 6 commits intomainfrom
feat/drop-axios
Open

feat!: replace axios with native fetch#366
rhamzeh wants to merge 6 commits intomainfrom
feat/drop-axios

Conversation

@rhamzeh
Copy link
Copy Markdown
Member

@rhamzeh rhamzeh commented Mar 31, 2026

The global fetch API is built into Node 20+, browsers, Deno, Cloudflare Workers, and Vercel Edge.

On modern versions of node that use undici internally, this should result in improved performance.

Warning

BREAKING CHANGE: The $response property type changes from AxiosResponse<T> to FgaResponse<T>. The constructor now accepts an optional HttpClient instead of AxiosInstance.
baseOptions.httpAgent/httpsAgent are no longer applicable as fetch handles connection pooling natively.

Description

What problem is being solved?

How is it being solved?

What changes are made to solve it?

References

closes #18
unblocks #17

Review Checklist

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev [Provide a link to any relevant PRs in the references section above]
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

Summary by CodeRabbit

  • Breaking Changes

    • Replaced axios with native fetch-based HTTP layer; $response now uses FgaResponse and injection uses HttpClient instead of previous axios instance. Public constructors/signatures updated to accept HttpClient.
  • New Features

    • Custom HTTP client support (custom fetch, default headers, default timeout).
    • Exposed FgaResponse, HttpClient and related types.
  • Documentation

    • README and runtime docs updated with Custom HTTP Client and streaming/ReadableStream guidance.
  • Chores

    • RequestBuilderOptions now typed with timeout and retry params.

rhamzeh added 3 commits March 31, 2026 09:01
The global fetch API is built into Node 20+, browsers, Deno, Cloudflare
Workers, and Vercel Edge.

On modern versions of node taht use undici internally, this should result
in improved perfomance.

BREAKING CHANGE: The `$response` property type changes from
`AxiosResponse<T>` to `FgaResponse<T>`. The constructor
now accepts an optional `HttpClient` instead of `AxiosInstance`.
`baseOptions.httpAgent`/`httpsAgent` are no longer applicable as fetch
handles connection pooling natively.
@rhamzeh rhamzeh requested a review from a team as a code owner March 31, 2026 22:58
Copilot AI review requested due to automatic review settings March 31, 2026 22:58
@rhamzeh rhamzeh requested review from a team as code owners March 31, 2026 22:58
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

Walkthrough

This PR replaces axios with a fetch-based HttpClient across the SDK, introducing FgaResponse<T> and HttpClient, changing injected/constructed client types (AxiosInstance → HttpClient), updating request/timeout/retry plumbing to use AbortSignal/fetch, and updating docs/tests accordingly.

Changes

Cohort / File(s) Summary
Documentation
CHANGELOG.md, README.md, SUPPORTED_RUNTIMES.md
Documented axios→fetch migration, new HttpClient interface and FgaResponse shape, added "Custom HTTP Client" docs and runtime support updates.
HTTP Abstraction Layer
src/common.ts
Introduced FgaResponse<T>, HttpClient, globalHttpClient; replaced axios request/response/error handling with fetch-based attemptHttpRequest, header normalization, timeout via AbortSignal.timeout, and retry/error mapping using HttpErrorContext. Updated request factories and RequestBuilderOptions.
API Layer
src/api.ts
Replaced AxiosInstance parameters with HttpClient across request builders and factory; typed options as RequestBuilderOptions; wired globalHttpClient into execution.
Core Client
src/base.ts, src/client.ts, src/configuration.ts
BaseAPI and OpenFgaClient now accept httpClient?: HttpClient; BaseAPI stores protected httpClient; default fetch-based client created when none provided; BaseOptions exported/optional header typing updated.
Error Handling
src/errors.ts
Added HttpErrorContext; refactored FgaApiError and subclasses to accept `HttpErrorContext
Authentication & Credentials
src/credentials/credentials.ts
Credentials.init and constructor changed to accept httpClient?: HttpClient; token refresh flow uses fetch-based request wiring; safe header access updated.
Public Exports
src/index.ts
Re-exported FgaResponse, HttpClient, CallResult, and PromiseResult.
Dependencies
package.json
Removed axios dependency.
Tests
tests/fetch-http-client.test.ts, tests/errors-authentication.test.ts, tests/index.test.ts, tests/errors.test.ts
Added comprehensive fetch-http-client tests covering parsing, timeout, retries, error mapping, header merging, streaming, and injection; updated existing tests to use HttpErrorContext and httpClient.fetch mocking.

Sequence Diagram

sequenceDiagram
    participant Client as OpenFgaClient
    participant API as OpenFgaApi / executeApiRequest
    participant HC as HttpClient
    participant Fetch as globalThis.fetch
    participant Retry as RetryLogic

    Client->>API: call API method (options, httpClient?)
    API->>HC: resolve injected or globalHttpClient
    API->>Retry: execute attemptHttpRequest(config, hc)
    Retry->>HC: merge headers, build FetchRequestConfig (method, body, timeout, responseType)
    HC->>Fetch: fetch(url, {method, headers, body, signal})
    alt Success 2xx
        Fetch->>HC: Response
        HC->>API: parse JSON/text or return stream -> FgaResponse{status,statusText,headers,data}
        API->>Client: resolve CallResult with $response: FgaResponse
    else Retryable (429/5xx/network)
        Fetch->>Retry: Error/status
        Retry->>Retry: backoff and retry attempts
        Retry->>HC: re-attempt fetch
    else Non-retryable (4xx, auth, not-found)
        Fetch->>HC: Response
        HC->>API: build HttpErrorContext and throw typed FgaApiError subclass
        API->>Client: reject with error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • SoulPancake
  • ewanharris
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat!: replace axios with native fetch' clearly and accurately summarizes the primary breaking change in the PR, matching the core objective to replace axios dependency with the native fetch API.
Linked Issues check ✅ Passed The PR fulfills issue #18's core requirements: replaces axios with a cross-platform HTTP solution (native fetch), supports Node.js 18+, has no new dependencies, is promise-based, includes streaming support, and now supports Deno/Cloudflare Workers/Vercel Edge through cross-platform fetch compatibility.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the axios-to-fetch migration objective: HTTP client abstraction (FgaResponse, HttpClient), error handling updates, SDK imports/exports, and comprehensive test coverage for the new fetch layer and error handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/drop-axios

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.

@dosubot
Copy link
Copy Markdown

dosubot bot commented Mar 31, 2026

Related Documentation

1 document(s) may need updating based on files changed in this PR:

OpenFGA's Space

StreamedListObjects Feature Overview
View Suggested Changes
@@ -115,7 +115,7 @@
 ### JS SDK
 The JS SDK supports StreamedListObjects in v0.9.3 and later. The method streams results using async iterators, allowing you to process each object as it arrives. See the [documentation](#streamed-list-objects) for usage details.
 
-**Runtime Requirements:** The JS SDK requires Node.js v20.19.0 or higher. Tested and supported versions include Node.js 20.x, 22.x, 24.x, and 25.x. For detailed information about supported Node.js versions and the support policy, see [SUPPORTED_RUNTIMES.md](https://github.com/openfga/js-sdk/blob/main/SUPPORTED_RUNTIMES.md).
+**Runtime Requirements:** The JS SDK requires a runtime with native `fetch` and `ReadableStream` support. Supported runtimes include Node.js 20+, modern browsers, Deno, Cloudflare Workers, and Vercel Edge. The primary CI-tested Node.js versions are 20.x, 22.x, 24.x, and 25.x. For detailed information about supported runtimes and the support policy, see [SUPPORTED_RUNTIMES.md](https://github.com/openfga/js-sdk/blob/main/SUPPORTED_RUNTIMES.md).
 
 Additionally, the JS SDK provides `executeApiRequest` and `executeStreamedApiRequest` methods on `OpenFgaClient` that can be used to call arbitrary API endpoints that don't yet have dedicated SDK methods. Use `executeApiRequest` for regular endpoints and `executeStreamedApiRequest` for streaming endpoints like `/streamed-list-objects`. These methods act as an escape hatch while still providing SDK benefits like authentication, configuration, retries, and error handling.
 

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the SDK’s transport layer from Axios to the native fetch API to improve cross-runtime support (Node.js, browsers, Deno/edge-like environments) and reduce dependencies, while updating the public response surface ($response) and HTTP injection mechanism.

Changes:

  • Replaces Axios usage with a fetch-based HttpClient abstraction and introduces FgaResponse<T> as the new $response type.
  • Refactors retry/timeout/error handling to work with fetch + AbortSignal.timeout(), including streamed responses via ReadableStream.
  • Updates docs and tests to reflect the new HTTP stack and breaking API changes.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
common.ts Core migration: implements fetch-based request execution, retries, response parsing, and new HttpClient/FgaResponse types.
api.ts Updates generated API surface to accept HttpClient injection and uses fetch-based request functions.
base.ts Replaces Axios setup with HttpClient initialization and passes it into credentials/API layers.
client.ts Switches client $response types to FgaResponse and adjusts streaming behavior to ReadableStream.
errors.ts Decouples errors from Axios by introducing HttpErrorContext and updating error constructors.
credentials/credentials.ts Migrates token exchange to fetch-based requests via HttpClient.
configuration.ts Tightens typing for baseOptions and updates comments to reflect HTTP (not Axios) semantics.
index.ts Re-exports new HTTP/response types from common.ts.
package.json Removes axios dependency.
tests/fetch-http-client.test.ts Adds focused tests for fetch client behavior (headers, retries, timeout, parsing, injection).
tests/index.test.ts Updates retry/non-network error test to mock fetch instead of Axios.
tests/errors-authentication.test.ts Updates authentication error test to use HttpErrorContext.
README.md Documents custom HTTP client usage and the new $response type.
SUPPORTED_RUNTIMES.md Broadens runtime support documentation beyond Node.js.
CHANGELOG.md Records breaking changes and migration notes for the Axios → fetch switch.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 75.00000% with 70 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.29%. Comparing base (d09bb3d) to head (ef3a638).

Files with missing lines Patch % Lines
api.ts 59.22% 42 Missing ⚠️
common.ts 81.96% 16 Missing and 6 partials ⚠️
errors.ts 87.80% 0 Missing and 5 partials ⚠️
client.ts 83.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #366      +/-   ##
==========================================
+ Coverage   85.80%   86.29%   +0.48%     
==========================================
  Files          26       26              
  Lines        1268     1335      +67     
  Branches      225      274      +49     
==========================================
+ Hits         1088     1152      +64     
- Misses        110      115       +5     
+ Partials       70       68       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@socket-security
Copy link
Copy Markdown

socket-security bot commented Mar 31, 2026

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

Copy link
Copy Markdown

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api.ts`:
- Around line 487-490: The FP streaming function signature is incorrect: update
executeStreamedApiRequest's returned inner function type from PromiseResult<any>
to Promise<any> to reflect that createStreamingRequestFunction (the
implementation) returns the raw response.data stream; likewise change the
OO/public streaming method's return type from Promise<CallResult<any>> to
Promise<any> so callers don't expect a $response property—locate the
executeStreamedApiRequest implementation that calls RequestBuilder and
createStreamingRequestFunction (and the public method that wraps it where
TelemetryAttribute.FgaClientRequestMethod is set) and adjust their declared
return types to Promise<any>.

In `@common.ts`:
- Around line 376-382: Replace the naive JSON check with the existing MIME
helper: instead of using contentType.includes("application/json") check the full
JSON MIME family by calling isJsonMime(contentType) (use the local contentType
variable and keep the existing branches that set data via response.json() or
response.text()); update the conditional in the block that inspects
response.headers/get("content-type") so responses like application/problem+json,
vendor+json, or mixed-case types are parsed with response.json().
- Around line 721-724: The call to attemptHttpRequest currently omits the
telemetry block so streaming requests (and retries) don't emit
histogramHttpRequestDuration; update the call where wrappedResponse is assigned
to pass the telemetry through (e.g., include telemetry in the options object
alongside maxRetry and minWaitInMs or as the appropriate parameter expected by
attemptHttpRequest) so attemptHttpRequest receives the telemetry and can emit
histogramHttpRequestDuration; reference the existing symbols attemptHttpRequest,
wrappedResponse, fetchRequestConfig, maxRetry, minWaitInMs, and client to locate
and modify the call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8225e0a3-58cf-42ce-9769-864c555633b7

📥 Commits

Reviewing files that changed from the base of the PR and between d09bb3d and debd645.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • README.md
  • SUPPORTED_RUNTIMES.md
  • api.ts
  • base.ts
  • client.ts
  • common.ts
  • configuration.ts
  • credentials/credentials.ts
  • errors.ts
  • index.ts
  • package.json
  • tests/errors-authentication.test.ts
  • tests/fetch-http-client.test.ts
  • tests/index.test.ts
💤 Files with no reviewable changes (1)
  • package.json

@rhamzeh rhamzeh requested a review from Copilot March 31, 2026 23:40
@rhamzeh
Copy link
Copy Markdown
Member Author

rhamzeh commented Mar 31, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@common.ts`:
- Around line 750-773: createStreamingRequestFunction currently returns the raw
stream (response?.data) while client code (executeStreamedApiRequest and the
handler that checks stream.$response.data) expects a PromiseResult/$response
envelope; standardize by changing createStreamingRequestFunction to return the
same envelope shape as other requests (e.g., an object with $response containing
the full response and data as the stream), and
update/createStreamingRequestFunction's public signature/docs to
PromiseResult<any>, plus adjust any consumer code in client.ts that expects
stream.$response.data to use the unified envelope returned by
createStreamingRequestFunction (references: createStreamingRequestFunction,
executeStreamedApiRequest, and the handler that inspects stream.$response.data).
- Around line 306-320: The current logic always attaches an AbortSignal
(timeoutMs) which will abort even after fetch resolves and thus cuts off
streaming responses; modify the timeout creation to skip adding the implicit
default timeout when the request is a streamed response (check
request.responseType === "stream" or similar) unless the caller explicitly
provided request.timeout; i.e., only set signal when request.timeout is defined
or request.responseType !== "stream" (keep using timeoutMs, AbortSignal.timeout
fallback and AbortController fallback as before), and add a regression test that
issues a streaming request that remains open past the default 10s to ensure
streams are not aborted by HttpClient.defaultTimeout.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4bc75d66-f8e3-4796-90b1-84a6bc52480c

📥 Commits

Reviewing files that changed from the base of the PR and between debd645 and ef3a638.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • CHANGELOG.md
  • README.md
  • SUPPORTED_RUNTIMES.md
  • api.ts
  • client.ts
  • common.ts
  • errors.ts
  • tests/errors.test.ts
  • tests/fetch-http-client.test.ts
✅ Files skipped from review due to trivial changes (4)
  • SUPPORTED_RUNTIMES.md
  • CHANGELOG.md
  • README.md
  • api.ts

Comment on lines +306 to +320
const timeoutMs = request.timeout ?? httpClient.defaultTimeout ?? 10000;
let signal: AbortSignal | undefined;
if (typeof AbortSignal !== "undefined" && typeof (AbortSignal as any).timeout === "function") {
// Use native AbortSignal.timeout when available.
signal = (AbortSignal as any).timeout(timeoutMs);
} else if (typeof AbortController !== "undefined") {
// Fallback for environments without AbortSignal.timeout.
const controller = new AbortController();
setTimeout(() => controller.abort(), timeoutMs);
signal = controller.signal;
}
const fetchInit: RequestInit = {
method: request.method || "GET",
headers: fetchHeaders,
signal,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "common.ts" | head -5

Repository: openfga/js-sdk

Length of output: 69


🏁 Script executed:

wc -l ./common.ts

Repository: openfga/js-sdk

Length of output: 73


🏁 Script executed:

sed -n '300,325p' ./common.ts

Repository: openfga/js-sdk

Length of output: 1096


🏁 Script executed:

sed -n '405,420p' ./common.ts

Repository: openfga/js-sdk

Length of output: 603


🏁 Script executed:

sed -n '260,290p' ./common.ts

Repository: openfga/js-sdk

Length of output: 763


🏁 Script executed:

rg "responseType.*stream" ./common.ts -B 2 -A 2

Repository: openfga/js-sdk

Length of output: 375


🏁 Script executed:

sed -n '290,345p' ./common.ts

Repository: openfga/js-sdk

Length of output: 2374


🏁 Script executed:

rg "createStreamingRequestFunction\|responseType.*stream" ./common.ts -B 5 -A 5

Repository: openfga/js-sdk

Length of output: 40


🏁 Script executed:

rg "responseType" ./common.ts -B 3 -A 3

Repository: openfga/js-sdk

Length of output: 579


🏁 Script executed:

sed -n '435,455p' ./common.ts

Repository: openfga/js-sdk

Length of output: 755


🏁 Script executed:

rg "streaming\|stream" ./common.ts -i | head -20

Repository: openfga/js-sdk

Length of output: 40


🏁 Script executed:

sed -n '750,817p' ./common.ts

Repository: openfga/js-sdk

Length of output: 2311


🏁 Script executed:

find . -type f -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "stream\|timeout" 2>/dev/null | head -10

Repository: openfga/js-sdk

Length of output: 140


🏁 Script executed:

grep -n "timeout\|stream" ./tests/streaming.test.ts | head -30

Repository: openfga/js-sdk

Length of output: 1119


🏁 Script executed:

grep -n "timeout" ./tests/streaming.test.ts

Repository: openfga/js-sdk

Length of output: 40


🏁 Script executed:

grep -n "timeout" ./tests/fetch-http-client.test.ts -B 2 -A 5

Repository: openfga/js-sdk

Length of output: 1059


Don't inherit the default 10s timeout into streamed bodies.

The abort signal created at line 306 remains attached after fetch() resolves, so responseType: "stream" requests will be cut off once HttpClient.defaultTimeout elapses. With the default client, a slow or large stream can fail after ~10 seconds even though the HTTP request itself succeeded. Skip the implicit timeout for streams unless the caller explicitly opts into one, and add a regression test that keeps a stream open past the default timeout.

Suggested direction
-      const timeoutMs = request.timeout ?? httpClient.defaultTimeout ?? 10000;
+      const timeoutMs =
+        request.responseType === "stream" && request.timeout == null
+          ? undefined
+          : request.timeout ?? httpClient.defaultTimeout ?? 10000;
       let signal: AbortSignal | undefined;
-      if (typeof AbortSignal !== "undefined" && typeof (AbortSignal as any).timeout === "function") {
+      if (typeof timeoutMs === "number" && typeof AbortSignal !== "undefined" && typeof (AbortSignal as any).timeout === "function") {
         // Use native AbortSignal.timeout when available.
         signal = (AbortSignal as any).timeout(timeoutMs);
-      } else if (typeof AbortController !== "undefined") {
+      } else if (typeof timeoutMs === "number" && typeof AbortController !== "undefined") {
         // Fallback for environments without AbortSignal.timeout.
         const controller = new AbortController();
         setTimeout(() => controller.abort(), timeoutMs);
         signal = controller.signal;
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common.ts` around lines 306 - 320, The current logic always attaches an
AbortSignal (timeoutMs) which will abort even after fetch resolves and thus cuts
off streaming responses; modify the timeout creation to skip adding the implicit
default timeout when the request is a streamed response (check
request.responseType === "stream" or similar) unless the caller explicitly
provided request.timeout; i.e., only set signal when request.timeout is defined
or request.responseType !== "stream" (keep using timeoutMs, AbortSignal.timeout
fallback and AbortController fallback as before), and add a regression test that
issues a streaming request that remains open past the default 10s to ensure
streams are not aborted by HttpClient.defaultTimeout.

Comment on lines +750 to +773
return async (client: HttpClient = httpClient): Promise<any> => {
await setBearerAuthToObject(axiosArgs.options.headers, credentials!);

const url = configuration.getBasePath() + axiosArgs.url;

const axiosRequestArgs = { ...axiosArgs.options, responseType: "stream", url: url };
const wrappedResponse = await attemptHttpRequest(axiosRequestArgs, {
const fetchRequestConfig: FetchRequestConfig = {
url,
method: axiosArgs.options.method,
headers: axiosArgs.options.headers,
data: axiosArgs.options.data,
responseType: "stream",
timeout: axiosArgs.options.timeout,
};

const wrappedResponse = await attemptHttpRequest(fetchRequestConfig, {
maxRetry,
minWaitInMs,
}, axios);
}, client, {
telemetry: configuration.telemetry,
userAgent: configuration.baseOptions?.headers?.["User-Agent"],
});
const response = wrappedResponse?.response;

const result: any = response?.data; // raw stream
const result: any = response?.data; // raw ReadableStream
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep one public return contract for streamed requests.

createStreamingRequestFunction() now returns response?.data directly, but client.ts Line 882 has to defensively handle both stream.$response.data and the raw stream, while executeStreamedApiRequest() at client.ts Lines 1066-1070 still advertises PromiseResult<any>. That leaves the streaming API with an unstable shape for consumers. Please standardize on one contract—either always return the $response envelope or update the public signatures/docs to return the raw stream explicitly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common.ts` around lines 750 - 773, createStreamingRequestFunction currently
returns the raw stream (response?.data) while client code
(executeStreamedApiRequest and the handler that checks stream.$response.data)
expects a PromiseResult/$response envelope; standardize by changing
createStreamingRequestFunction to return the same envelope shape as other
requests (e.g., an object with $response containing the full response and data
as the stream), and update/createStreamingRequestFunction's public
signature/docs to PromiseResult<any>, plus adjust any consumer code in client.ts
that expects stream.$response.data to use the unified envelope returned by
createStreamingRequestFunction (references: createStreamingRequestFunction,
executeStreamedApiRequest, and the handler that inspects stream.$response.data).

@SoulPancake SoulPancake self-requested a review April 2, 2026 07:15
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.

Replace axios

4 participants