UNPKG

3.21 kBJavaScriptView Raw
1// Taken from graphql-js
2// https://github.com/graphql/graphql-js/blob/main/src/jsutils/inspect.ts
3import { GraphQLError } from 'graphql';
4import { isAggregateError } from './AggregateError.js';
5const MAX_RECURSIVE_DEPTH = 3;
6/**
7 * Used to print values in error messages.
8 */
9export function inspect(value) {
10 return formatValue(value, []);
11}
12function formatValue(value, seenValues) {
13 switch (typeof value) {
14 case 'string':
15 return JSON.stringify(value);
16 case 'function':
17 return value.name ? `[function ${value.name}]` : '[function]';
18 case 'object':
19 return formatObjectValue(value, seenValues);
20 default:
21 return String(value);
22 }
23}
24function formatError(value) {
25 if (value instanceof GraphQLError) {
26 return value.toString();
27 }
28 return `${value.name}: ${value.message};\n ${value.stack}`;
29}
30function formatObjectValue(value, previouslySeenValues) {
31 if (value === null) {
32 return 'null';
33 }
34 if (value instanceof Error) {
35 if (isAggregateError(value)) {
36 return formatError(value) + '\n' + formatArray(value.errors, previouslySeenValues);
37 }
38 return formatError(value);
39 }
40 if (previouslySeenValues.includes(value)) {
41 return '[Circular]';
42 }
43 const seenValues = [...previouslySeenValues, value];
44 if (isJSONable(value)) {
45 const jsonValue = value.toJSON();
46 // check for infinite recursion
47 if (jsonValue !== value) {
48 return typeof jsonValue === 'string' ? jsonValue : formatValue(jsonValue, seenValues);
49 }
50 }
51 else if (Array.isArray(value)) {
52 return formatArray(value, seenValues);
53 }
54 return formatObject(value, seenValues);
55}
56function isJSONable(value) {
57 return typeof value.toJSON === 'function';
58}
59function formatObject(object, seenValues) {
60 const entries = Object.entries(object);
61 if (entries.length === 0) {
62 return '{}';
63 }
64 if (seenValues.length > MAX_RECURSIVE_DEPTH) {
65 return '[' + getObjectTag(object) + ']';
66 }
67 const properties = entries.map(([key, value]) => key + ': ' + formatValue(value, seenValues));
68 return '{ ' + properties.join(', ') + ' }';
69}
70function formatArray(array, seenValues) {
71 if (array.length === 0) {
72 return '[]';
73 }
74 if (seenValues.length > MAX_RECURSIVE_DEPTH) {
75 return '[Array]';
76 }
77 const len = array.length;
78 const remaining = array.length;
79 const items = [];
80 for (let i = 0; i < len; ++i) {
81 items.push(formatValue(array[i], seenValues));
82 }
83 if (remaining === 1) {
84 items.push('... 1 more item');
85 }
86 else if (remaining > 1) {
87 items.push(`... ${remaining} more items`);
88 }
89 return '[' + items.join(', ') + ']';
90}
91function getObjectTag(object) {
92 const tag = Object.prototype.toString
93 .call(object)
94 .replace(/^\[object /, '')
95 .replace(/]$/, '');
96 if (tag === 'Object' && typeof object.constructor === 'function') {
97 const name = object.constructor.name;
98 if (typeof name === 'string' && name !== '') {
99 return name;
100 }
101 }
102 return tag;
103}