-
-
Notifications
You must be signed in to change notification settings - Fork 460
/
Copy pathrequest.ts
120 lines (103 loc) · 2.99 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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 { AnyVariables, GraphQLRequest } from '../types';
interface WritableLocation {
loc: Location | undefined;
}
export interface KeyedDocumentNode extends DocumentNode {
__key: number;
}
const GRAPHQL_STRING_RE = /("{3}[\s\S]*"{3}|"(?:\\.|[^"])*")/g;
const REPLACE_CHAR_RE = /([\s,]|#[^\n\r]+)+/g;
const replaceOutsideStrings = (str: string, idx: number) =>
idx % 2 === 0 ? str.replace(REPLACE_CHAR_RE, ' ').trim() : str;
export const stringifyDocument = (
node: string | DefinitionNode | DocumentNode
): string => {
let str = (typeof node !== 'string'
? (node.loc && node.loc.source.body) || print(node)
: node
)
.split(GRAPHQL_STRING_RE)
.map(replaceOutsideStrings)
.join('');
if (typeof node !== 'string') {
const operationName = 'definitions' in node && getOperationName(node);
if (operationName) {
str = `# ${operationName}\n${str}`;
}
if (!node.loc) {
(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 extends AnyVariables = AnyVariables
>(
q: string | DocumentNode | TypedDocumentNode<Data, Variables>,
vars: Variables
): GraphQLRequest<Data, Variables> => {
if (!vars) vars = {} as Variables;
const query = keyDocument(q);
return {
key: phash(query.__key, stringifyVariables(vars)) >>> 0,
query,
variables: vars as Variables,
};
};
/**
* Finds the Name value from the OperationDefinition of a Document
*/
export const getOperationName = (query: DocumentNode): string | undefined => {
for (const node of query.definitions) {
if (node.kind === Kind.OPERATION_DEFINITION && node.name) {
return node.name.value;
}
}
};
/**
* Finds the operation-type
*/
export const getOperationType = (query: DocumentNode): string | undefined => {
for (const node of query.definitions) {
if (node.kind === Kind.OPERATION_DEFINITION) {
return node.operation;
}
}
};