0
# Utilities and Parsing
1
2
Utility functions for GraphQL document parsing, request creation, result processing, and various helper operations that support the core functionality of @urql/core.
3
4
## Capabilities
5
6
### GraphQL Document Parsing
7
8
Parse GraphQL documents with fragment merging and caching optimizations.
9
10
```typescript { .api }
11
/**
12
* Parse GraphQL documents with fragment merging and deduplication
13
* @param strings - Template strings array
14
* @param interpolations - Interpolated document fragments or strings
15
* @returns Parsed and cached TypedDocumentNode
16
*/
17
function gql<Data = any, Variables extends AnyVariables = AnyVariables>(
18
strings: TemplateStringsArray,
19
...interpolations: Array<TypedDocumentNode | DocumentNode | string>
20
): TypedDocumentNode<Data, Variables>;
21
22
/**
23
* Parse GraphQL document from string
24
* @param string - GraphQL document string
25
* @returns Parsed TypedDocumentNode
26
*/
27
function gql<Data = any, Variables extends AnyVariables = AnyVariables>(
28
string: string
29
): TypedDocumentNode<Data, Variables>;
30
```
31
32
**Usage Examples:**
33
34
```typescript
35
import { gql } from "@urql/core";
36
37
// Template literal parsing with fragments
38
const UserFragment = gql`
39
fragment UserInfo on User {
40
id
41
name
42
43
}
44
`;
45
46
const GetUserQuery = gql`
47
query GetUser($id: ID!) {
48
user(id: $id) {
49
...UserInfo
50
}
51
}
52
${UserFragment}
53
`;
54
55
// String parsing
56
const simpleQuery = gql(`
57
query GetPosts {
58
posts {
59
id
60
title
61
}
62
}
63
`);
64
65
// With TypeScript generics
66
interface User {
67
id: string;
68
name: string;
69
email: string;
70
}
71
72
interface GetUserData {
73
user: User;
74
}
75
76
interface GetUserVars {
77
id: string;
78
}
79
80
const typedQuery = gql<GetUserData, GetUserVars>`
81
query GetUser($id: ID!) {
82
user(id: $id) {
83
id
84
name
85
86
}
87
}
88
`;
89
```
90
91
### String Utilities
92
93
Stable string representations for GraphQL variables and documents.
94
95
```typescript { .api }
96
/**
97
* A stable stringifier for GraphQL variables objects
98
* @param x - Any JSON-like data
99
* @param includeFiles - Whether to include File/Blob objects
100
* @returns A stable JSON string
101
*/
102
function stringifyVariables(x: any, includeFiles?: boolean): string;
103
104
/**
105
* A cached printing function for GraphQL documents
106
* @param node - A string of a document or a DocumentNode
107
* @returns A normalized printed string of the passed GraphQL document
108
*/
109
function stringifyDocument(node: string | DefinitionNode | DocumentNode): string;
110
```
111
112
**Usage Examples:**
113
114
```typescript
115
import { stringifyVariables, stringifyDocument, gql } from "@urql/core";
116
117
// Stable variable stringification (for caching keys)
118
const variables = { id: "123", filters: { name: "Alice" } };
119
const key = stringifyVariables(variables);
120
console.log(key); // {"filters":{"name":"Alice"},"id":"123"}
121
122
// Same variables always produce same string
123
const sameKey = stringifyVariables({ filters: { name: "Alice" }, id: "123" });
124
console.log(key === sameKey); // true
125
126
// Document stringification with comment removal
127
const query = gql`
128
# This is a comment
129
query GetUser($id: ID!) {
130
user(id: $id) {
131
id
132
name
133
}
134
}
135
`;
136
137
const queryString = stringifyDocument(query);
138
console.log(queryString); // Clean query without comments
139
```
140
141
### Request Creation
142
143
Create GraphQL requests with automatic key generation and caching.
144
145
```typescript { .api }
146
/**
147
* Create a GraphQL request with generated key for caching
148
* @param query - GraphQL document or string
149
* @param variables - Variables for the request
150
* @param extensions - Optional request extensions (APQ, etc.)
151
* @returns GraphQL request with unique key
152
*/
153
function createRequest<Data = any, Variables extends AnyVariables = AnyVariables>(
154
query: DocumentInput<Data, Variables>,
155
variables: Variables,
156
extensions?: RequestExtensions | undefined
157
): GraphQLRequest<Data, Variables>;
158
159
/**
160
* Extract operation name from GraphQL document
161
* @param document - GraphQL document
162
* @returns Operation name or undefined
163
*/
164
function getOperationName(document: DocumentNode): string | undefined;
165
```
166
167
**Usage Examples:**
168
169
```typescript
170
import { createRequest, getOperationName, gql } from "@urql/core";
171
172
const GetUserQuery = gql`
173
query GetUser($id: ID!) {
174
user(id: $id) {
175
id
176
name
177
}
178
}
179
`;
180
181
// Create request with variables
182
const request = createRequest(GetUserQuery, { id: "123" });
183
console.log(request.key); // Unique hash for caching
184
console.log(request.variables); // { id: "123" }
185
186
// Extract operation name
187
const operationName = getOperationName(GetUserQuery);
188
console.log(operationName); // "GetUser"
189
190
// Use with client operations
191
const result = await client.executeQuery(request).toPromise();
192
```
193
194
### Operation Management
195
196
Create and manipulate operations with context and metadata.
197
198
```typescript { .api }
199
/**
200
* Create or copy an operation with context
201
* @param kind - Type of operation
202
* @param request - GraphQL request
203
* @param context - Operation context
204
* @returns Operation ready for execution
205
*/
206
function makeOperation<Data = any, Variables extends AnyVariables = AnyVariables>(
207
kind: OperationType,
208
request: GraphQLRequest<Data, Variables>,
209
context: OperationContext
210
): Operation<Data, Variables>;
211
```
212
213
**Usage Examples:**
214
215
```typescript
216
import { makeOperation, createRequest } from "@urql/core";
217
218
const request = createRequest(GetUserQuery, { id: "123" });
219
220
// Create a query operation
221
const operation = makeOperation('query', request, {
222
url: "https://api.example.com/graphql",
223
requestPolicy: 'cache-first',
224
fetchOptions: {
225
headers: { authorization: 'Bearer token' }
226
}
227
});
228
229
// Use in custom exchange
230
const result = await client.executeRequestOperation(operation).toPromise();
231
```
232
233
### Result Processing
234
235
Convert and manipulate GraphQL execution results.
236
237
```typescript { .api }
238
/**
239
* Convert ExecutionResult to OperationResult
240
* @param operation - Source operation
241
* @param result - Raw GraphQL execution result
242
* @param response - Optional fetch response
243
* @returns Processed OperationResult
244
*/
245
function makeResult<Data = any, Variables extends AnyVariables = AnyVariables>(
246
operation: Operation<Data, Variables>,
247
result: ExecutionResult,
248
response?: Response
249
): OperationResult<Data, Variables>;
250
251
/**
252
* Create an error OperationResult
253
* @param operation - Source operation
254
* @param error - Error instance
255
* @param response - Optional execution result
256
* @returns Error OperationResult
257
*/
258
function makeErrorResult<Data = any, Variables extends AnyVariables = AnyVariables>(
259
operation: Operation<Data, Variables>,
260
error: Error | CombinedError,
261
response?: ExecutionResult
262
): OperationResult<Data, Variables>;
263
264
/**
265
* Merge incremental delivery patches into result data
266
* @param prevResult - Previous result to patch
267
* @param nextResult - New execution result with incremental data
268
* @param response - Optional response object
269
* @param pending - Optional pending execution result
270
* @returns Merged result with combined data
271
*/
272
function mergeResultPatch(
273
prevResult: OperationResult,
274
nextResult: ExecutionResult,
275
response?: any,
276
pending?: ExecutionResult['pending']
277
): OperationResult;
278
```
279
280
**Usage Examples:**
281
282
```typescript
283
import { makeResult, makeErrorResult, mergeResultPatch } from "@urql/core";
284
285
// Convert raw API response to OperationResult
286
const executionResult = {
287
data: { user: { id: "123", name: "Alice" } }
288
};
289
290
const result = makeResult(operation, executionResult);
291
292
// Create error result
293
const errorResult = makeErrorResult(
294
operation,
295
new Error("Network failure")
296
);
297
298
// Handle incremental delivery (@defer/@stream)
299
const initialResult = makeResult(operation, { data: { user: { id: "123" } } });
300
const patch = makeResult(operation, {
301
incremental: [{
302
path: ['user'],
303
data: { name: "Alice", email: "alice@example.com" }
304
}]
305
});
306
307
const mergedResult = mergeResultPatch(initialResult, patch);
308
```
309
310
### Document Processing
311
312
Process GraphQL documents for enhanced functionality.
313
314
```typescript { .api }
315
/**
316
* Add __typename fields and process directives in GraphQL documents
317
* @param document - GraphQL document to format
318
* @returns Formatted document with __typename fields
319
*/
320
function formatDocument<T extends DocumentNode>(document: T): FormattedNode<T>;
321
322
/**
323
* Collect all __typename values from result data
324
* @param data - GraphQL result data
325
* @returns Array of typename strings found
326
*/
327
function collectTypenames(data: any): string[];
328
```
329
330
**Usage Examples:**
331
332
```typescript
333
import { formatDocument, collectTypenames, gql } from "@urql/core";
334
335
const query = gql`
336
query GetUser($id: ID!) {
337
user(id: $id) {
338
id
339
name
340
profile {
341
bio
342
}
343
}
344
}
345
`;
346
347
// Add __typename fields automatically
348
const formattedQuery = formatDocument(query);
349
// Result will include __typename fields for caching
350
351
// Extract typenames from result data
352
const resultData = {
353
user: {
354
__typename: "User",
355
id: "123",
356
profile: {
357
__typename: "Profile",
358
bio: "Software developer"
359
}
360
}
361
};
362
363
const typenames = collectTypenames(resultData);
364
console.log(typenames); // ["User", "Profile"]
365
```
366
367
### Variable Processing
368
369
Handle variable serialization and processing for GraphQL requests.
370
371
```typescript { .api }
372
/**
373
* Stable JSON stringify for GraphQL variables
374
* @param variables - Variables object to stringify
375
* @returns Stable string representation
376
*/
377
function stringifyVariables(variables: any): string;
378
379
/**
380
* Stable string representation of GraphQL documents
381
* @param document - Document to stringify
382
* @returns Cached string representation
383
*/
384
function stringifyDocument(document: DocumentNode): string;
385
```
386
387
**Usage Examples:**
388
389
```typescript
390
import { stringifyVariables, stringifyDocument } from "@urql/core";
391
392
// Consistent variable serialization (key generation)
393
const vars1 = { id: "123", name: "Alice" };
394
const vars2 = { name: "Alice", id: "123" };
395
396
console.log(stringifyVariables(vars1) === stringifyVariables(vars2)); // true
397
398
// Document caching
399
const query = gql`query GetUser { user { id } }`;
400
const docString = stringifyDocument(query);
401
// Cached for performance on subsequent calls
402
```
403
404
## Types
405
406
### Document Types
407
408
```typescript { .api }
409
type DocumentInput<Result = { [key: string]: any }, Variables = { [key: string]: any }> =
410
string | DocumentNode | TypedDocumentNode<Result, Variables>;
411
412
interface TypedDocumentNode<Result = { [key: string]: any }, Variables = { [key: string]: any }>
413
extends DocumentNode {
414
__apiType?: (variables: Variables) => Result;
415
__ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;
416
}
417
418
interface PersistedDocument extends DocumentNode {
419
documentId?: string;
420
}
421
422
type FormattedNode<Node> = Node extends readonly (infer Child)[]
423
? readonly FormattedNode<Child>[]
424
: Node extends ValueNode | TypeNode
425
? Node
426
: Node extends { kind: Kind }
427
? {
428
[K in Exclude<keyof Node, 'directives' | 'loc'>]: FormattedNode<
429
Node[K]
430
>;
431
} extends infer Node
432
? Node extends {
433
kind: Kind.FIELD | Kind.INLINE_FRAGMENT | Kind.FRAGMENT_SPREAD;
434
}
435
? Node & {
436
_generated?: boolean;
437
_directives?: Record<string, DirectiveNode> | undefined;
438
}
439
: Node
440
: Node
441
: Node;
442
```
443
444
### Request Types
445
446
```typescript { .api }
447
interface GraphQLRequest<Data = any, Variables extends AnyVariables = AnyVariables> {
448
/** Unique cache key for the request */
449
key: number;
450
/** GraphQL document to execute */
451
query: DocumentNode | PersistedDocument | TypedDocumentNode<Data, Variables>;
452
/** Variables for the operation */
453
variables: Variables;
454
/** Additional request extensions */
455
extensions?: RequestExtensions | undefined;
456
}
457
458
type AnyVariables = { [prop: string]: any } | void | undefined;
459
```
460
461
### Result Types
462
463
```typescript { .api }
464
interface ExecutionResult {
465
/** GraphQL response data */
466
data?: null | Record<string, any>;
467
/** GraphQL errors from execution */
468
errors?: ErrorLike[] | readonly ErrorLike[];
469
/** Additional metadata */
470
extensions?: Extensions;
471
/** Incremental delivery patches */
472
incremental?: IncrementalPayload[];
473
/** Whether more results will follow */
474
hasNext?: boolean;
475
/** Pending incremental results */
476
pending?: readonly PendingIncrementalResult[];
477
}
478
479
type ErrorLike = Partial<GraphQLError> | Error;
480
```
481
482
### Incremental Delivery Types
483
484
```typescript { .api }
485
interface IncrementalPayload {
486
/** Label for the incremental payload */
487
label?: string | null;
488
/** Path where to apply the patch */
489
path?: readonly (string | number)[];
490
/** ID for pending deferred results */
491
id?: string;
492
/** Sub-path from defer/stream fragment */
493
subPath?: readonly (string | number)[];
494
/** Data to patch into result */
495
data?: Record<string, unknown> | null;
496
/** Items to patch into array */
497
items?: readonly unknown[] | null;
498
/** Errors from incremental payload */
499
errors?: ErrorLike[] | readonly ErrorLike[];
500
/** Additional metadata */
501
extensions?: Extensions;
502
}
503
```
504
505
### Internal Fetch Utilities
506
507
Advanced HTTP transport utilities for custom fetch implementations and exchanges.
508
509
```typescript { .api }
510
/**
511
* Create GraphQL HTTP request body from operation
512
* @param operation - GraphQL operation to convert
513
* @returns Request body for HTTP transport
514
*/
515
function makeFetchBody(operation: Operation): FetchBody;
516
517
/**
518
* Create request URL for GraphQL operation (with GET support)
519
* @param operation - GraphQL operation
520
* @param body - Request body (for URL encoding in GET requests)
521
* @returns Complete request URL
522
*/
523
function makeFetchURL(operation: Operation, body?: FetchBody): string;
524
525
/**
526
* Create fetch RequestInit options for GraphQL operation
527
* @param operation - GraphQL operation
528
* @param body - Request body
529
* @returns RequestInit options for fetch call
530
*/
531
function makeFetchOptions(operation: Operation, body?: FetchBody): RequestInit;
532
533
/**
534
* HTTP transport with streaming and multipart response support
535
* @param operation - GraphQL operation to execute
536
* @param url - GraphQL endpoint URL
537
* @param fetchOptions - Fetch request options
538
* @param fetch - Fetch implementation
539
* @returns Source of ExecutionResults
540
*/
541
function makeFetchSource(
542
operation: Operation,
543
url: string,
544
fetchOptions: RequestInit,
545
fetch: typeof globalThis.fetch
546
): Source<ExecutionResult>;
547
548
interface FetchBody {
549
query: string;
550
variables?: any;
551
operationName?: string;
552
extensions?: any;
553
}
554
```
555
556
**Usage Examples:**
557
558
```typescript
559
import {
560
makeFetchBody,
561
makeFetchURL,
562
makeFetchOptions,
563
makeFetchSource
564
} from "@urql/core/internal";
565
566
// Custom fetch exchange implementation
567
const customFetchExchange: Exchange = ({ forward }) => ops$ => {
568
return pipe(
569
ops$,
570
filter(operation => operation.kind !== 'teardown'),
571
mergeMap(operation => {
572
// Create request components
573
const body = makeFetchBody(operation);
574
const url = makeFetchURL(operation, body);
575
const fetchOptions = makeFetchOptions(operation, body);
576
577
// Use streaming fetch source
578
return makeFetchSource(
579
operation,
580
url,
581
fetchOptions,
582
operation.context.fetch || fetch
583
);
584
})
585
);
586
};
587
588
// GET request handling
589
const operation = makeOperation('query', request, {
590
url: "https://api.example.com/graphql",
591
preferGetMethod: true
592
});
593
594
const body = makeFetchBody(operation);
595
const getUrl = makeFetchURL(operation, body);
596
// URL will include query and variables as parameters
597
```