grafast
Version:
Cutting edge GraphQL planning and execution engine
270 lines • 9.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports._grafastPrint = _grafastPrint;
exports.recursivePrintBucket = recursivePrintBucket;
exports.printStore = printStore;
exports.grafastColor = grafastColor;
exports.grafastPrint = grafastPrint;
exports.ansiPad = ansiPad;
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const constants_js_1 = require("./constants.js");
const executeBucket_js_1 = require("./engine/executeBucket.js");
const LayerPlan_js_1 = require("./engine/LayerPlan.js");
const OutputPlan_js_1 = require("./engine/OutputPlan.js");
const inspect_js_1 = require("./inspect.js");
const step_js_1 = require("./step.js");
const stripAnsi_js_1 = require("./stripAnsi.js");
const utils_js_1 = require("./utils.js");
/*
* This file contains utilities used with the `debug` module primarily (but
* also used elsewhere) that are useful for outputting Grafast stuff in a
* more helpful way - typically with more relevant detail and colours to help
* you (me) digest things.
*/
const COLORS = [
//chalk.black,
chalk_1.default.yellow,
chalk_1.default.magenta,
//chalk.cyan,
chalk_1.default.red,
//chalk.white,
//chalk.blackBright,
chalk_1.default.greenBright,
chalk_1.default.yellowBright,
chalk_1.default.blueBright,
chalk_1.default.magentaBright,
chalk_1.default.cyanBright,
chalk_1.default.redBright,
chalk_1.default.blue,
chalk_1.default.green,
//chalk.whiteBright,
];
const BG_COLORS = [
// chalk.bgRgb(53, 0, 0),
// chalk.bgRgb(0, 53, 0),
// chalk.bgRgb(0, 0, 53),
chalk_1.default.visible,
chalk_1.default.underline,
];
function _grafastPrint(symbol, seen) {
if ((0, utils_js_1.isDeferred)(symbol)) {
return chalk_1.default.gray `<Deferred>`;
}
if ((0, utils_js_1.isPromise)(symbol)) {
return chalk_1.default.gray `<Promise>`;
}
if (symbol === utils_js_1.ROOT_VALUE_OBJECT) {
return chalk_1.default.gray `(blank)`;
}
if (symbol instanceof step_js_1.Step) {
return String(symbol);
}
if (symbol instanceof LayerPlan_js_1.LayerPlan) {
return String(symbol);
}
if (Array.isArray(symbol)) {
if (seen.has(symbol)) {
return chalk_1.default.gray `(loop)`;
}
seen.add(symbol);
return `[${symbol
.map((value, i) => BG_COLORS[i % BG_COLORS.length](_grafastPrint(value, new Set(seen))))
.join(", ")}]`;
}
if (symbol instanceof Map) {
if (seen.has(symbol)) {
return chalk_1.default.gray `(loop)`;
}
seen.add(symbol);
const pairs = [];
let i = 0;
for (const [key, value] of symbol.entries()) {
pairs.push(BG_COLORS[i % BG_COLORS.length](`${_grafastPrint(key, new Set(seen))}: ${_grafastPrint(value, new Set(seen))}`));
i++;
}
return `Map{${pairs.join(", ")}}`;
}
if (isBucket(symbol)) {
return recursivePrintBucket(symbol);
}
if (typeof symbol === "object" && symbol) {
if (symbol instanceof Error) {
return chalk_1.default.red(`ERROR<${(0, stripAnsi_js_1.stripAnsi)(String(symbol.message))
.replace(/\s+/g, " ")
.substring(0, 30) + "..."}>`);
}
if (symbol instanceof OutputPlan_js_1.OutputPlan) {
return symbol.print();
}
if (![null, Object.prototype, utils_js_1.sharedNull].includes(Object.getPrototypeOf(symbol))) {
return chalk_1.default.red(`OBJECT<${(0, stripAnsi_js_1.stripAnsi)(String(symbol))}>`);
}
if (seen.has(symbol)) {
return chalk_1.default.gray `(loop)`;
}
seen.add(symbol);
return `{${[...Object.keys(symbol), ...Object.getOwnPropertySymbols(symbol)]
.map((key, i) => BG_COLORS[i % BG_COLORS.length](`${_grafastPrint(key, new Set(seen))}: ${_grafastPrint(symbol[key], new Set(seen))}`))
.join(", ")}}`;
}
if (typeof symbol !== "symbol") {
return (0, inspect_js_1.inspect)(symbol, { colors: true });
}
return grafastPrintSymbol(symbol);
}
function isBucket(thing) {
return (typeof thing === "object" &&
thing !== null &&
thing.toString === executeBucket_js_1.bucketToString);
}
function _grafastSymbolDescription(symbol) {
if (!symbol.description) {
return chalk_1.default.green("Symbol()");
}
const nStr = symbol.description?.replace(/[^0-9]/g, "") || "";
const n = parseInt(nStr, 10) || 0;
if (n > 0) {
return grafastColor(symbol.description, n);
}
else {
return chalk_1.default.cyan(`$$${symbol.description}`);
}
}
function indent(level, string) {
return " ".repeat(level) + string.replace(/\n/g, `\n${" ".repeat(level)}`);
}
function recursivePrintBucket(bucket, indentLevel = 0) {
return indent(indentLevel, `Bucket for ${bucket.layerPlan} (size = ${bucket.size}):${bucket.polymorphicPathList.some((p) => p != null)
? `
${bucket.polymorphicPathList.map((p, i) => `${String(i).padStart(4, " ")}: ${p}`)}`
: ""}
Store:
${indent(4, printStore(bucket))}
Children:
${Object.entries(bucket.children)
.map(([_id, { bucket }]) => indent(4, recursivePrintBucket(bucket)))
.join("\n")}`);
}
const PRINT_STORE_INSPECT_OPTIONS = {
colors: true,
depth: 0,
showHidden: false,
maxArrayLength: 5,
maxStringLength: 50,
};
function indentIfMultiline(string) {
if (string.includes("\n")) {
return indent(4, "\n" + string);
}
else {
return string;
}
}
function printStore(bucket) {
const output = [];
for (const [key, val] of bucket.store) {
const printKey = String(key).padStart(3, " ");
if (bucket.layerPlan.copyStepIds.includes(key)) {
output.push(`${printKey} (copy)`);
}
else if (val.isBatch) {
const step = bucket.layerPlan.operationPlan.stepTracker.getStepById(key, true);
output.push(`${printKey} (BATCH): ${step ?? "-"} ${[...(step?.polymorphicPaths ?? [])]}\n${indent(2, val.entries
.map((e, i) => `${String(i).padStart(3, " ")}: flags=${printFlags(val._flagsAt(i))} value=${indentIfMultiline((0, inspect_js_1.inspect)(val.at(i), PRINT_STORE_INSPECT_OPTIONS))}`)
.join("\n"))}`);
}
else {
const step = bucket.layerPlan.operationPlan.stepTracker.getStepById(key, true);
output.push(`${printKey} (UNARY/${printFlags(val._entryFlags)}) ${step ?? "-"} ${[...(step?.polymorphicPaths ?? [])]}\n${indent(4, (0, inspect_js_1.inspect)(val.value, PRINT_STORE_INSPECT_OPTIONS))}`);
}
}
return output.join("\n") || "EMPTY";
}
function grafastColor(text, n) {
const color = COLORS[Math.abs(n) % COLORS.length];
return color(text);
}
const symbolsByAlias = new Map();
let symbolClear = null;
/**
* Returns a text description for a symbol that helps differentiate similar
* symbols by keeping track of the symbols/descriptions it has seen and adding
* numeric identifiers to the output. Only tracks symbols over a short period
* so counts will reset very frequently.
*/
function grafastPrintSymbol(symbol) {
const description = _grafastSymbolDescription(symbol);
if (!symbolClear) {
// Only cache symbols for a few milliseconds, we don't want a memory leak!
symbolClear = setTimeout(() => {
symbolClear = null;
symbolsByAlias.clear();
}, 200);
}
const symbols = symbolsByAlias.get(description);
if (!symbols) {
symbolsByAlias.set(description, [symbol]);
return description;
}
let idx = symbols.indexOf(symbol);
if (idx === 0) {
return description;
}
if (idx < 0) {
idx = symbols.push(symbol) - 1;
}
return `${description}${chalk_1.default.gray(`:${idx + 1}`)}`;
}
/**
* Prints something grafast-style (i.e. concise, coloured, with helpful detail)
*/
function grafastPrint(symbol) {
return _grafastPrint(symbol, new Set());
}
/**
* An ANSI-aware pad function; strips ANSI sequences from the string, figures
* out how much it needs to pad it by, and then pads the original string by
* that amount.
*/
function ansiPad(ansiString, targetLength, fill, position) {
const string = (0, stripAnsi_js_1.stripAnsi)(ansiString);
const fillLength = targetLength - string.length;
if (fillLength >= 0) {
const fillString = fill.repeat(fillLength);
if (position === "start") {
return fillString + ansiString;
}
else {
return ansiString + fillString;
}
}
else {
return ansiString;
}
}
function printFlags(flags) {
if (flags === undefined)
return " ? ";
if (flags === 0)
return " ";
// This should not fire, added in case we add future flags and forget to update this
if (flags !==
(flags &
(constants_js_1.FLAG_POLY_SKIPPED |
constants_js_1.FLAG_ERROR |
constants_js_1.FLAG_NULL |
constants_js_1.FLAG_INHIBITED |
constants_js_1.FLAG_STOPPED))) {
return String(flags).padStart(5, " ");
}
let flagString = "";
// Alphabetically sorted to avoid an unfortunate word they would spell
flagString += flags & constants_js_1.FLAG_ERROR ? "E" : " ";
flagString += flags & constants_js_1.FLAG_INHIBITED ? "I" : " ";
flagString += flags & constants_js_1.FLAG_NULL ? "N" : " ";
flagString += flags & constants_js_1.FLAG_POLY_SKIPPED ? "P" : " ";
flagString += flags & constants_js_1.FLAG_STOPPED ? "S" : " ";
return flagString;
}
//# sourceMappingURL=grafastPrint.js.map