diff --git a/gitnexus/src/core/ingestion/pipeline-phases/routes.ts b/gitnexus/src/core/ingestion/pipeline-phases/routes.ts index 0d526bb5c..5c377b4db 100644 --- a/gitnexus/src/core/ingestion/pipeline-phases/routes.ts +++ b/gitnexus/src/core/ingestion/pipeline-phases/routes.ts @@ -545,9 +545,11 @@ export const routesPhase: PipelinePhase = { // Unicode property classes make the boundary cover non-ASCII identifier // characters too — ASCII `\w` would let `caféget('/x')` match `get` // (#1852 review F10). + // An optional TypeScript type argument list may sit between the name and + // the call (`client.get('/x')`). const alternation = [...wrapperNames].map(escapeRegex).join('|'); const wrapperCallRegex = new RegExp( - `(?\\s*)?\\(\\s*['"\`](/[^'"\`\\s)]+)['"\`]`, 'gu', ); const scanContent = (filePath: string, content: string): void => { diff --git a/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/lib/http.ts b/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/lib/http.ts index 9d27dda22..d2bf0a3ff 100644 --- a/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/lib/http.ts +++ b/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/lib/http.ts @@ -6,6 +6,6 @@ const API_BASE = process.env.API_BASE || ''; // `fetch()`, so the parse-phase auto-detector cannot flag it. Listing // "doRequest" in `.gitnexusrc` `fetchWrappers` is what lets the routes phase // trace its consumers (#1589/#1852 residual). -export async function doRequest(path: string, opts?: Record) { - return axios.get(`${API_BASE}${path}`, opts); +export async function doRequest(path: string, opts?: Record) { + return axios.get(`${API_BASE}${path}`, opts); } diff --git a/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/pages/TypedThings.tsx b/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/pages/TypedThings.tsx new file mode 100644 index 000000000..95864a78c --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/configurable-fetch-wrapper/pages/TypedThings.tsx @@ -0,0 +1,11 @@ +import { doRequest } from '../lib/http'; + +type Thing = { id: number; name: string }; + +export default function TypedThings() { + const loadThings = async () => { + const res = await doRequest('/api/things'); + return res.data; + }; + return null; +} diff --git a/gitnexus/test/integration/resolvers/configurable-fetch-wrapper.test.ts b/gitnexus/test/integration/resolvers/configurable-fetch-wrapper.test.ts index e9730e7eb..7657ddaee 100644 --- a/gitnexus/test/integration/resolvers/configurable-fetch-wrapper.test.ts +++ b/gitnexus/test/integration/resolvers/configurable-fetch-wrapper.test.ts @@ -42,6 +42,14 @@ describe('Configurable fetch wrapper consumer extraction', () => { expect(thingsEdge).toBeDefined(); }); + it('traces a configured wrapper called with type arguments', () => { + const edges = getRelationships(withConfig, 'FETCHES'); + const thingsEdge = edges.find( + (e) => e.sourceFilePath.includes('TypedThings') && e.target === '/api/things', + ); + expect(thingsEdge).toBeDefined(); + }); + it('does NOT match a configured bare name inside a longer non-ASCII identifier (#1852 review F10)', () => { // Accented.tsx calls `cafédoRequest('/api/things')` — `doRequest` preceded by // the non-ASCII letter `é`. The Unicode-aware lookbehind must reject it.