Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(core): Support GraphQLRequest.extensions and update subscriptionExchange (#3054)

authored by

Phil Pluckthun and committed by
GitHub
de15c14a d80fea87

+35 -38
+5
.changeset/clever-plants-greet.md
··· 1 + --- 2 + '@urql/core': major 3 + --- 4 + 5 + Update `subscriptionExchange` to receive `FetchBody` instead. In the usual usage of `subscriptionExchange` (for instance with `graphql-ws`) you can expect no breaking changes. However, the `key` and `extensions` field has been removed and instead the `forwardSubscription` function receives the full `Operation` as a second argument.
+5
.changeset/slow-glasses-attend.md
··· 1 + --- 2 + '@urql/core': minor 3 + --- 4 + 5 + Support `GraphQLRequest.extensions` as spec-extensions input to GraphQL requests.
+4 -7
docs/advanced/subscriptions.md
··· 57 57 exchanges: [ 58 58 ...defaultExchanges, 59 59 subscriptionExchange({ 60 - forwardSubscription: (operation) => ({ 61 - subscribe: (sink) => ({ 62 - unsubscribe: wsClient.subscribe( 63 - { query: operation.query, variables: operation.variables }, 64 - sink 65 - ), 60 + forwardSubscription: request => ({ 61 + subscribe: sink => ({ 62 + unsubscribe: wsClient.subscribe(request, sink), 66 63 }), 67 64 }), 68 65 }), ··· 94 91 exchanges: [ 95 92 ...defaultExchanges, 96 93 subscriptionExchange({ 97 - forwardSubscription: (operation) => subscriptionClient.request(operation) 94 + forwardSubscription: request => subscriptionClient.request(request), 98 95 }), 99 96 ], 100 97 });
-1
packages/core/src/exchanges/subscription.test.ts
··· 29 29 stringifyDocument(subscriptionOperation.query) 30 30 ); 31 31 expect(operation.variables).toBe(subscriptionOperation.variables); 32 - expect(operation.context).toEqual(subscriptionOperation.context); 33 32 34 33 return { 35 34 subscribe(observer) {
+12 -23
packages/core/src/exchanges/subscription.ts
··· 11 11 } from 'wonka'; 12 12 13 13 import { 14 - stringifyDocument, 15 14 makeResult, 15 + mergeResultPatch, 16 16 makeErrorResult, 17 17 makeOperation, 18 - mergeResultPatch, 19 18 } from '../utils'; 20 19 21 20 import { 22 21 Exchange, 23 22 ExecutionResult, 24 23 Operation, 25 - OperationContext, 26 24 OperationResult, 27 25 } from '../types'; 26 + 27 + import { FetchBody, makeFetchBody } from '../internal'; 28 28 29 29 /** An abstract observer-like interface. 30 30 * ··· 65 65 }; 66 66 } 67 67 68 - /** A more cross-compatible version of the {@link Operation} structure. 69 - * 70 - * @remarks 71 - * When the `subscriptionExchange` was first created, some transports needed a specific shape 72 - * of {@link GraphQLRequest} objects to be passed to them. This is a shim that is as compatible 73 - * with most transports out of the box as possible. 68 + /** A more cross-compatible version of the {@link GraphQLRequest} structure. 69 + * {@link FetchBody} for more details 74 70 */ 75 - export interface SubscriptionOperation { 76 - query: string; 77 - variables: Record<string, unknown> | undefined; 78 - key: string; 79 - context: OperationContext; 80 - } 71 + export type SubscriptionOperation = FetchBody; 81 72 82 73 /** A subscription forwarding function, which must accept a {@link SubscriptionOperation}. 83 74 * ··· 85 76 * @returns An {@link ObservableLike} object issuing {@link ExecutionResult | ExecutionResults}. 86 77 */ 87 78 export type SubscriptionForwarder = ( 88 - operation: SubscriptionOperation 79 + request: FetchBody, 80 + operation: Operation 89 81 ) => ObservableLike<ExecutionResult>; 90 82 91 83 /** This is called to create a subscription and needs to be hooked up to a transport client. */ ··· 148 140 const createSubscriptionSource = ( 149 141 operation: Operation 150 142 ): Source<OperationResult> => { 151 - // This excludes the query's name as a field although subscription-transport-ws does accept it since it's optional 152 - const observableish = forwardSubscription({ 153 - key: operation.key.toString(36), 154 - query: stringifyDocument(operation.query), 155 - variables: operation.variables!, 156 - context: { ...operation.context }, 157 - }); 143 + const observableish = forwardSubscription( 144 + makeFetchBody(operation), 145 + operation 146 + ); 158 147 159 148 return make<OperationResult>(({ next, complete }) => { 160 149 let isComplete = false;
+1 -1
packages/core/src/internal/fetchOptions.ts
··· 28 28 query: stringifyDocument(request.query), 29 29 operationName: getOperationName(request.query), 30 30 variables: request.variables || undefined, 31 - extensions: undefined, 31 + extensions: request.extensions, 32 32 }; 33 33 } 34 34
+4
packages/core/src/types.ts
··· 236 236 * generic, are sent to the GraphQL API to execute a request. 237 237 */ 238 238 variables: Variables; 239 + /** Additional metadata that a GraphQL API may accept for spec extensions. 240 + * @see {@link https://github.com/graphql/graphql-over-http/blob/1928447/spec/GraphQLOverHTTP.md#request-parameters} for the GraphQL over HTTP spec 241 + */ 242 + extensions?: Record<string, any> | undefined; 239 243 } 240 244 241 245 /** Parameters from which {@link GraphQLRequest | GraphQLRequests} are created from.
+1 -4
packages/core/src/utils/operation.ts
··· 49 49 50 50 function makeOperation(kind, request, context) { 51 51 if (!context) context = request.context; 52 - 53 52 return { 54 - key: request.key, 55 - query: request.query, 56 - variables: request.variables, 53 + ...request, 57 54 kind, 58 55 context, 59 56 };
+3 -2
packages/core/src/utils/request.ts
··· 152 152 Variables extends AnyVariables = AnyVariables 153 153 >( 154 154 _query: string | DocumentNode | TypedDocumentNode<Data, Variables>, 155 - _variables: Variables 155 + _variables: Variables, 156 + extensions?: Record<string, any> | undefined 156 157 ): GraphQLRequest<Data, Variables> => { 157 158 const variables = _variables || ({} as Variables); 158 159 const query = keyDocument(_query); 159 160 const printedVars = stringifyVariables(variables); 160 161 let key = query.__key; 161 162 if (printedVars !== '{}') key = phash(printedVars, key); 162 - return { key, query, variables }; 163 + return { key, query, variables, extensions }; 163 164 }; 164 165 165 166 /** Returns the name of the `DocumentNode`'s operation, if any.