1// These are guards that are used throughout the codebase to warn or error on
2// unexpected behaviour or conditions.
3// Every warning and error comes with a number that uniquely identifies them.
4// You can read more about the messages themselves in `docs/graphcache/errors.md`
5
6import type {
7 ExecutableDefinitionNode,
8 InlineFragmentNode,
9} from '@0no-co/graphql.web';
10import type { Logger } from '../types';
11import { Kind } from '@0no-co/graphql.web';
12
13export type ErrorCode =
14 | 1
15 | 2
16 | 3
17 | 4
18 | 5
19 | 6
20 | 7
21 | 8
22 | 9
23 | 10
24 | 11
25 | 12
26 | 13
27 | 14
28 | 15
29 | 16
30 | 17
31 | 18
32 | 19
33 | 20
34 | 21
35 | 22
36 | 23
37 | 24
38 | 25
39 | 26
40 | 27
41 | 28;
42
43type DebugNode = ExecutableDefinitionNode | InlineFragmentNode;
44
45// URL unfurls to https://formidable.com/open-source/urql/docs/graphcache/errors/
46const helpUrl = '\nhttps://bit.ly/2XbVrpR#';
47const cache = new Set<string>();
48
49export const currentDebugStack: string[] = [];
50
51export const popDebugNode = () => currentDebugStack.pop();
52
53export const pushDebugNode = (typename: void | string, node: DebugNode) => {
54 let identifier = '';
55 if (node.kind === Kind.INLINE_FRAGMENT) {
56 identifier = typename
57 ? `Inline Fragment on "${typename}"`
58 : 'Inline Fragment';
59 } else if (node.kind === Kind.OPERATION_DEFINITION) {
60 const name = node.name ? `"${node.name.value}"` : 'Unnamed';
61 identifier = `${name} ${node.operation}`;
62 } else if (node.kind === Kind.FRAGMENT_DEFINITION) {
63 identifier = `"${node.name.value}" Fragment`;
64 }
65
66 if (identifier) {
67 currentDebugStack.push(identifier);
68 }
69};
70
71const getDebugOutput = (): string =>
72 currentDebugStack.length
73 ? '\n(Caused At: ' + currentDebugStack.join(', ') + ')'
74 : '';
75
76export function invariant(
77 condition: any,
78 message: string,
79 code: ErrorCode
80): asserts condition {
81 if (!condition) {
82 let errorMessage = message || 'Minfied Error #' + code + '\n';
83 if (process.env.NODE_ENV !== 'production') {
84 errorMessage += getDebugOutput();
85 }
86
87 const error = new Error(errorMessage + helpUrl + code);
88 error.name = 'Graphcache Error';
89 throw error;
90 }
91}
92
93export function warn(
94 message: string,
95 code: ErrorCode,
96 logger: Logger | undefined
97) {
98 if (!cache.has(message)) {
99 if (logger) {
100 logger('warn', message + getDebugOutput() + helpUrl + code);
101 } else {
102 console.warn(message + getDebugOutput() + helpUrl + code);
103 }
104 cache.add(message);
105 }
106}