feat(DRC-3149): migrate Recce OSS from Axios to native Fetch#1264
Merged
kentwelcome merged 17 commits intomainfrom Apr 2, 2026
Merged
Conversation
…ttpError Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…ApiResponse Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…o createFetchClient Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…o QueryParams Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
Remove axios mocking entirely, stub global fetch instead. Replace interceptors assertion with HTTP method checks. Add middleware integration tests for apiPrefix URL rewriting and auth token injection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
Replace all AxiosError fixture creation with HttpError constructor. Add vitest alias for @datarecce/ui/lib/fetchClient. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…pter
Replace the entire vi.mock("axios") block with a single
vi.stubGlobal("fetch") call to prevent real network requests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…eryClient Remove axios from all package.json files (dependencies and pnpm.overrides), rename axiosClient.ts to queryClient.ts, and update all imports throughout the codebase. This completes the axios-to-fetch migration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
- Fix empty baseURL crash (CRITICAL): handle baseURL='' by using path directly - Add brand property to HttpError for cross-module instanceof safety - Wrap response body parsing to convert SyntaxError to HttpError - Delete Content-Type header for FormData bodies - Add tests for empty baseURL, malformed JSON, brand check Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
… with Axios Network-level failures (TypeError for DNS/connection, AbortError for timeouts) are now wrapped in HttpError with status=0, so isHttpError() returns true for ALL request failures — matching Axios behavior where isAxiosError() returned true for network errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…ssing tests - Fix middleware crash when baseURL is empty and apiPrefix/authToken is set: new URL() requires absolute URL, switched to string manipulation matching the original Axios interceptor approach - Add ApiContext middleware tests: exact /api rewrite, non-/api passthrough, combined apiPrefix+authToken, empty baseUrl with authToken, no-middleware - Add fetchClient tests: POST with no body, FormData removing default Content-Type, empty baseURL with params Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
Node 22+ provides a built-in localStorage that is a plain object without standard Storage API methods (getItem, setItem, clear, etc.). This caused Filename.test.tsx to fail with localStorage.clear is not a function. Add a Storage polyfill in vitest.setup.mts that detects the incomplete built-in and replaces it with a Map-backed implementation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@datarecce.io>
…s-to-native-fetch
…s-to-native-fetch
…s-to-native-fetch
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
@datarecce/uiwith a thin nativefetchwrapper (fetchClient.ts), eliminating Axios as a supply-chain dependency after the npm compromiseApiClientinterfacelocalStorage.cleartest failure in Node 22+ environmentsWhat Changed
New:
fetchClient.tsmodule (js/packages/ui/src/lib/fetchClient.ts)A thin wrapper around native
fetchthat provides the same call patterns as the Axios subset we used:ApiClientinterfaceget/post/patch/deletemethods matching Axios signaturesApiResponse<T>data,status,headersHttpError<T>status,data,responsegetter (backward compat)isHttpError()isAxiosError()with bothinstanceofand brand property for cross-module safetycreateFetchClient()baseURL,headers,timeout,middleware(replaces interceptors)Features: auto JSON parse/serialize, FormData detection, query param serialization,
AbortSignal.timeout, request middleware, network error wrapping (status: 0).Core migration (3 files)
ApiContext.tsx:axios.create()+interceptors.request.use()replaced withcreateFetchClient()+middleware. URL rewriting uses string ops (notnew URL()) to handle both absolute and relative URLs.useApiConfig.ts: Default fallback client usescreateFetchClient({ baseURL: PUBLIC_API_URL })RecceProvider.tsx: Props type changed fromAxiosInstancetoApiClientAPI module migration (22 files)
15 type-only files:
AxiosInstancetoApiClient,AxiosResponsetoApiResponse7 instance-creation files:
axios.create()tocreateFetchClient()Error handling migration (3 files)
state.ts:isAxiosErrortoisHttpError,error.response?.statustoerror.statusFilename.tsx: same pattern +error.response?.data?.detailtoerror.data?.detailLineageViewOss.tsx:AxiosErrorinstanceof toHttpErrorinstanceofTest migration (3 files)
ApiContext.test.tsx: Removedvi.mock("axios"), stub globalfetch, added 7 middleware behavior testsFilename.test.tsx:AxiosErrorfixtures toHttpErrorfixturesLineageGraphAdapter.test.tsx: 22-line axios mock to singlefetchstubCleanup
axiosfrompackage.jsondependencies andpnpm.overridesAxiosQueryParamstoQueryParams(deprecated alias kept)axiosClient.tstoqueryClient.tsBonus fix: localStorage polyfill for Node 22+
Node 22+ ships a built-in
localStoragethat lacks standard Storage API methods. Added a polyfill invitest.setup.mts, fixing 48 pre-existing test failures inFilename.test.tsx.Code Review Findings Addressed
new URL(path, "")crashes when baseURL is emptyisHttpErrorinstanceof fragile across modules__isHttpErrorbrand propertyHttpError(0, null, message)headers.delete("Content-Type")new URL()crashes on relative pathsTest plan
pnpm type:check- 0 errorspnpm lint:fix- cleanpnpm test- 3592 passed, 0 failed (146 files)pnpm run build- successfulaxiosimports in source codeaxiosremoved from package.json and lockfileIncidental formatting (non-functional)
Pre-commit hooks auto-formatted two files outside the migration scope:
recce/adapter/dbt_adapter/__init__.py(single→double quotes ingetattr()calls) andtests/adapter/dbt_adapter/test_dbt_cll.py(line wrapping for long assertions). No logic changes — just style normalization triggered by the commit hooks.Closes DRC-3149
🤖 Generated with Claude Code