1import type {
2 AnyVariables,
3 GraphQLRequest,
4 Operation,
5 OperationContext,
6 OperationType,
7} from '../types';
8
9/** Creates a {@link Operation} from the given parameters.
10 *
11 * @param kind - The {@link OperationType} of GraphQL operation, i.e. `query`, `mutation`, or `subscription`.
12 * @param request - The {@link GraphQLRequest} or {@link Operation} used as a template for the new `Operation`.
13 * @param context - The {@link OperationContext} `context` data for the `Operation`.
14 * @returns A new {@link Operation}.
15 *
16 * @remarks
17 * This method is both used to create new {@link Operation | Operations} as well as copy and modify existing
18 * operations. While it’s not required to use this function to copy an `Operation`, it is recommended, in case
19 * additional dynamic logic is added to them in the future.
20 *
21 * Hint: When an {@link Operation} is passed to the `request` argument, the `context` argument does not have to be
22 * a complete {@link OperationContext} and will instead be combined with passed {@link Operation.context}.
23 *
24 * @example
25 * An example of copying an existing `Operation` to modify its `context`:
26 *
27 * ```ts
28 * makeOperation(
29 * operation.kind,
30 * operation,
31 * { requestPolicy: 'cache-first' },
32 * );
33 * ```
34 */
35function makeOperation<
36 Data = any,
37 Variables extends AnyVariables = AnyVariables,
38>(
39 kind: OperationType,
40 request: GraphQLRequest<Data, Variables>,
41 context: OperationContext
42): Operation<Data, Variables>;
43
44function makeOperation<
45 Data = any,
46 Variables extends AnyVariables = AnyVariables,
47>(
48 kind: OperationType,
49 request: Operation<Data, Variables>,
50 context?: Partial<OperationContext>
51): Operation<Data, Variables>;
52
53function makeOperation(kind, request, context) {
54 return {
55 ...request,
56 kind,
57 context: request.context
58 ? {
59 ...request.context,
60 ...context,
61 }
62 : context || request.context,
63 };
64}
65
66export { makeOperation };
67
68/** Adds additional metadata to an `Operation`'s `context.meta` property while copying it.
69 * @see {@link OperationDebugMeta} for more information on the {@link OperationContext.meta} property.
70 */
71export const addMetadata = (
72 operation: Operation,
73 meta: OperationContext['meta']
74) => {
75 return makeOperation(operation.kind, operation, {
76 meta: {
77 ...operation.context.meta,
78 ...meta,
79 },
80 });
81};