Skip to content

Commit 4528794

Browse files
EmrysMyrddingithub-actions[bot]ardatan
authored
feat(utils): Add instruments to wrapFetchWithHooks (#8456)
* feat(utils): Add instruments to `wrapFetchWithHooks` * chore(dependencies): updated changesets for modified dependencies * changeset * lazy instauments * Add tests --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Arda TANRIKULU <[email protected]>
1 parent b970e06 commit 4528794

File tree

6 files changed

+84
-173
lines changed

6 files changed

+84
-173
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@graphql-mesh/utils": patch
3+
---
4+
dependencies updates:
5+
- Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)

.changeset/silent-wolves-spend.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@graphql-mesh/utils': minor
3+
---
4+
5+
Add compatibility with new `Instruments` API of Hive Gateway. See
6+
[Hive Gateway documentation](https://the-guild.dev/graphql/hive/docs/gateway/other-features/custom-plugins#instruments)
7+
for more details.

packages/legacy/utils/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"graphql": "*"
3636
},
3737
"dependencies": {
38+
"@envelop/instruments": "^1.0.0",
3839
"@graphql-mesh/cross-helpers": "^0.4.10",
3940
"@graphql-mesh/string-interpolation": "^0.5.8",
4041
"@graphql-mesh/types": "^0.103.21",

packages/legacy/utils/src/wrapFetchWithHooks.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getInstrumented } from '@envelop/instruments';
12
import type { Logger, MeshFetch, OnFetchHook, OnFetchHookDone } from '@graphql-mesh/types';
23
import { type ExecutionRequest, type MaybePromise } from '@graphql-tools/utils';
34
import { handleMaybePromise, iterateAsync } from '@whatwg-node/promise-helpers';
@@ -6,8 +7,18 @@ import { DefaultLogger } from './logger.js';
67
export const requestIdByRequest = new WeakMap<Request, string>();
78
export const loggerForExecutionRequest = new WeakMap<ExecutionRequest, Logger>();
89

9-
export function wrapFetchWithHooks<TContext>(onFetchHooks: OnFetchHook<TContext>[]): MeshFetch {
10-
return function wrappedFetchFn(url, options, context, info) {
10+
export type FetchInstruments = {
11+
fetch?: (
12+
payload: { executionRequest: ExecutionRequest },
13+
wrapped: () => MaybePromise<void>,
14+
) => MaybePromise<void>;
15+
};
16+
17+
export function wrapFetchWithHooks<TContext>(
18+
onFetchHooks: OnFetchHook<TContext>[],
19+
instruments?: () => FetchInstruments | undefined,
20+
): MeshFetch {
21+
let wrappedFetchFn = function wrappedFetchFn(url, options, context, info) {
1122
let fetchFn: MeshFetch;
1223
let response$: MaybePromise<Response>;
1324
const onFetchDoneHooks: OnFetchHookDone[] = [];
@@ -91,4 +102,22 @@ export function wrapFetchWithHooks<TContext>(onFetchHooks: OnFetchHook<TContext>
91102
},
92103
);
93104
} as MeshFetch;
105+
106+
if (instruments) {
107+
const originalWrappedFetch = wrappedFetchFn;
108+
wrappedFetchFn = function wrappedFetchFn(url, options, context, info) {
109+
const fetchInstrument = instruments()?.fetch;
110+
const instrumentedFetch = fetchInstrument
111+
? getInstrumented({
112+
get executionRequest() {
113+
return info?.executionRequest;
114+
},
115+
}).asyncFn(fetchInstrument, originalWrappedFetch)
116+
: originalWrappedFetch;
117+
118+
return instrumentedFetch(url, options, context, info);
119+
};
120+
}
121+
122+
return wrappedFetchFn;
94123
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { GraphQLResolveInfo } from 'graphql';
2+
import { createServerAdapter, Response } from '@whatwg-node/server';
3+
import { wrapFetchWithHooks, type FetchInstruments } from '../src/wrapFetchWithHooks';
4+
5+
describe('Fetch instruments', () => {
6+
it('should wrap fetch instruments', async () => {
7+
await using adapter = createServerAdapter(() => Response.json({ hello: 'world' }));
8+
let receivedExecutionRequest;
9+
const fetchInstruments: FetchInstruments = {
10+
fetch: async ({ executionRequest }, wrapped) => {
11+
receivedExecutionRequest = executionRequest;
12+
await wrapped();
13+
},
14+
};
15+
const wrappedFetch = wrapFetchWithHooks(
16+
[
17+
({ setFetchFn }) => {
18+
setFetchFn(adapter.fetch);
19+
},
20+
],
21+
() => fetchInstruments,
22+
);
23+
const executionRequest = {};
24+
const res = await wrappedFetch('http://localhost:4000', {}, {}, {
25+
executionRequest,
26+
} as GraphQLResolveInfo);
27+
expect(await res.json()).toEqual({ hello: 'world' });
28+
expect(receivedExecutionRequest).toBe(executionRequest);
29+
});
30+
});

0 commit comments

Comments
 (0)