inspect.js 3.3 KB

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