-
-
Notifications
You must be signed in to change notification settings - Fork 459
/
request.ts
99 lines (86 loc) · 2.51 KB
/
request.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { TypedDocumentNode } from '@graphql-typed-document-node/core';
import {
Location,
DefinitionNode,
DocumentNode,
Kind,
parse,
print,
} from 'graphql';
import { hash, phash } from './hash';
import { stringifyVariables } from './stringifyVariables';
import { GraphQLRequest } from '../types';
interface WritableLocation {
loc: Location | undefined;
}
export interface KeyedDocumentNode extends DocumentNode {
__key: number;
}
export const stringifyDocument = (
node: string | DefinitionNode | DocumentNode
): string => {
let str = (typeof node !== 'string'
? (node.loc && node.loc.source.body) || print(node)
: node
)
.replace(/([\s,]|#[^\n\r]+)+/g, ' ')
.trim();
if (typeof node !== 'string') {
if (node.loc) {
const operationName = 'definitions' in node && getOperationName(node);
if (operationName) str = `# ${operationName}\n${str}`;
} else {
(node as WritableLocation).loc = {
start: 0,
end: str.length,
source: {
body: str,
name: 'gql',
locationOffset: { line: 1, column: 1 },
},
} as Location;
}
}
return str;
};
const docs = new Map<number, KeyedDocumentNode>();
export const keyDocument = (q: string | DocumentNode): KeyedDocumentNode => {
let key: number;
let query: DocumentNode;
if (typeof q === 'string') {
key = hash(stringifyDocument(q));
query = docs.get(key) || parse(q, { noLocation: true });
} else {
key = (q as KeyedDocumentNode).__key || hash(stringifyDocument(q));
query = docs.get(key) || q;
}
// Add location information if it's missing
if (!query.loc) stringifyDocument(query);
(query as KeyedDocumentNode).__key = key;
docs.set(key, query as KeyedDocumentNode);
return query as KeyedDocumentNode;
};
export const createRequest = <Data = any, Variables = object>(
q: string | DocumentNode | TypedDocumentNode<Data, Variables>,
vars?: Variables
): GraphQLRequest<Data, Variables> => {
const query = keyDocument(q);
return {
key: vars
? phash(query.__key, stringifyVariables(vars)) >>> 0
: query.__key,
query,
variables: vars || ({} as Variables),
};
};
/**
* Finds the Name value from the OperationDefinition of a Document
*/
export const getOperationName = (query: DocumentNode): string | undefined => {
for (let i = 0, l = query.definitions.length; i < l; i++) {
const node = query.definitions[i];
if (node.kind === Kind.OPERATION_DEFINITION && node.name) {
return node.name.value;
}
}
};