mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 14:16:58 +10:00
148 lines
19 KiB
TypeScript
148 lines
19 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
||
|
|
import setWith from 'lodash-es/setWith.js';
|
||
|
|
import * as React from 'react';
|
||
|
|
import { Box, Text, useTheme } from '../ink.js';
|
||
|
|
import type { ValidationError } from '../utils/settings/validation.js';
|
||
|
|
import { type TreeNode, treeify } from '../utils/treeify.js';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Builds a nested tree structure from dot-notation paths
|
||
|
|
* Uses lodash setWith to avoid automatic array creation
|
||
|
|
*/
|
||
|
|
function buildNestedTree(errors: ValidationError[]): TreeNode {
|
||
|
|
const tree: TreeNode = {};
|
||
|
|
errors.forEach(error => {
|
||
|
|
if (!error.path) {
|
||
|
|
// Root level error - use empty string as key
|
||
|
|
tree[''] = error.message;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try to enhance the path with meaningful values
|
||
|
|
const pathParts = error.path.split('.');
|
||
|
|
let modifiedPath = error.path;
|
||
|
|
|
||
|
|
// If we have an invalid value, try to make the path more readable
|
||
|
|
if (error.invalidValue !== null && error.invalidValue !== undefined && pathParts.length > 0) {
|
||
|
|
const newPathParts: string[] = [];
|
||
|
|
for (let i = 0; i < pathParts.length; i++) {
|
||
|
|
const part = pathParts[i];
|
||
|
|
if (!part) continue;
|
||
|
|
const numericPart = parseInt(part, 10);
|
||
|
|
|
||
|
|
// If this is a numeric index and it's the last part where we have the invalid value
|
||
|
|
if (!isNaN(numericPart) && i === pathParts.length - 1) {
|
||
|
|
// Format the value for display
|
||
|
|
let displayValue: string;
|
||
|
|
if (typeof error.invalidValue === 'string') {
|
||
|
|
displayValue = `"${error.invalidValue}"`;
|
||
|
|
} else if (error.invalidValue === null) {
|
||
|
|
displayValue = 'null';
|
||
|
|
} else if (error.invalidValue === undefined) {
|
||
|
|
displayValue = 'undefined';
|
||
|
|
} else {
|
||
|
|
displayValue = String(error.invalidValue);
|
||
|
|
}
|
||
|
|
newPathParts.push(displayValue);
|
||
|
|
} else {
|
||
|
|
// Keep other parts as-is
|
||
|
|
newPathParts.push(part);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
modifiedPath = newPathParts.join('.');
|
||
|
|
}
|
||
|
|
setWith(tree, modifiedPath, error.message, Object);
|
||
|
|
});
|
||
|
|
return tree;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Groups and displays validation errors using treeify with deduplication
|
||
|
|
*/
|
||
|
|
export function ValidationErrorsList(t0) {
|
||
|
|
const $ = _c(9);
|
||
|
|
const {
|
||
|
|
errors
|
||
|
|
} = t0;
|
||
|
|
const [themeName] = useTheme();
|
||
|
|
if (errors.length === 0) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
let T0;
|
||
|
|
let t1;
|
||
|
|
let t2;
|
||
|
|
if ($[0] !== errors || $[1] !== themeName) {
|
||
|
|
const errorsByFile = errors.reduce(_temp, {});
|
||
|
|
const sortedFiles = Object.keys(errorsByFile).sort();
|
||
|
|
T0 = Box;
|
||
|
|
t1 = "column";
|
||
|
|
t2 = sortedFiles.map(file_0 => {
|
||
|
|
const fileErrors = errorsByFile[file_0] || [];
|
||
|
|
fileErrors.sort(_temp2);
|
||
|
|
const errorTree = buildNestedTree(fileErrors);
|
||
|
|
const suggestionPairs = new Map();
|
||
|
|
fileErrors.forEach(error_0 => {
|
||
|
|
if (error_0.suggestion || error_0.docLink) {
|
||
|
|
const key = `${error_0.suggestion || ""}|${error_0.docLink || ""}`;
|
||
|
|
if (!suggestionPairs.has(key)) {
|
||
|
|
suggestionPairs.set(key, {
|
||
|
|
suggestion: error_0.suggestion,
|
||
|
|
docLink: error_0.docLink
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
const treeOutput = treeify(errorTree, {
|
||
|
|
showValues: true,
|
||
|
|
themeName,
|
||
|
|
treeCharColors: {
|
||
|
|
treeChar: "inactive",
|
||
|
|
key: "text",
|
||
|
|
value: "inactive"
|
||
|
|
}
|
||
|
|
});
|
||
|
|
return <Box key={file_0} flexDirection="column"><Text>{file_0}</Text><Box marginLeft={1}><Text dimColor={true}>{treeOutput}</Text></Box>{suggestionPairs.size > 0 && <Box flexDirection="column" marginTop={1}>{Array.from(suggestionPairs.values()).map(_temp3)}</Box>}</Box>;
|
||
|
|
});
|
||
|
|
$[0] = errors;
|
||
|
|
$[1] = themeName;
|
||
|
|
$[2] = T0;
|
||
|
|
$[3] = t1;
|
||
|
|
$[4] = t2;
|
||
|
|
} else {
|
||
|
|
T0 = $[2];
|
||
|
|
t1 = $[3];
|
||
|
|
t2 = $[4];
|
||
|
|
}
|
||
|
|
let t3;
|
||
|
|
if ($[5] !== T0 || $[6] !== t1 || $[7] !== t2) {
|
||
|
|
t3 = <T0 flexDirection={t1}>{t2}</T0>;
|
||
|
|
$[5] = T0;
|
||
|
|
$[6] = t1;
|
||
|
|
$[7] = t2;
|
||
|
|
$[8] = t3;
|
||
|
|
} else {
|
||
|
|
t3 = $[8];
|
||
|
|
}
|
||
|
|
return t3;
|
||
|
|
}
|
||
|
|
function _temp3(pair, index) {
|
||
|
|
return <Box key={`suggestion-pair-${index}`} flexDirection="column" marginBottom={1}>{pair.suggestion && <Text dimColor={true} wrap="wrap">{pair.suggestion}</Text>}{pair.docLink && <Text dimColor={true} wrap="wrap">Learn more: {pair.docLink}</Text>}</Box>;
|
||
|
|
}
|
||
|
|
function _temp2(a, b) {
|
||
|
|
if (!a.path && b.path) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (a.path && !b.path) {
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
return (a.path || "").localeCompare(b.path || "");
|
||
|
|
}
|
||
|
|
function _temp(acc, error) {
|
||
|
|
const file = error.file || "(file not specified)";
|
||
|
|
if (!acc[file]) {
|
||
|
|
acc[file] = [];
|
||
|
|
}
|
||
|
|
acc[file].push(error);
|
||
|
|
return acc;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJzZXRXaXRoIiwiUmVhY3QiLCJCb3giLCJUZXh0IiwidXNlVGhlbWUiLCJWYWxpZGF0aW9uRXJyb3IiLCJUcmVlTm9kZSIsInRyZWVpZnkiLCJidWlsZE5lc3RlZFRyZWUiLCJlcnJvcnMiLCJ0cmVlIiwiZm9yRWFjaCIsImVycm9yIiwicGF0aCIsIm1lc3NhZ2UiLCJwYXRoUGFydHMiLCJzcGxpdCIsIm1vZGlmaWVkUGF0aCIsImludmFsaWRWYWx1ZSIsInVuZGVmaW5lZCIsImxlbmd0aCIsIm5ld1BhdGhQYXJ0cyIsImkiLCJwYXJ0IiwibnVtZXJpY1BhcnQiLCJwYXJzZUludCIsImlzTmFOIiwiZGlzcGxheVZhbHVlIiwiU3RyaW5nIiwicHVzaCIsImpvaW4iLCJPYmplY3QiLCJWYWxpZGF0aW9uRXJyb3JzTGlzdCIsInQwIiwiJCIsIl9jIiwidGhlbWVOYW1lIiwiVDAiLCJ0MSIsInQyIiwiZXJyb3JzQnlGaWxlIiwicmVkdWNlIiwiX3RlbXAiLCJzb3J0ZWRGaWxlcyIsImtleXMiLCJzb3J0IiwibWFwIiwiZmlsZV8wIiwiZmlsZUVycm9ycyIsImZpbGUiLCJfdGVtcDIiLCJlcnJvclRyZWUiLCJzdWdnZXN0aW9uUGFpcnMiLCJNYXAiLCJlcnJvcl8wIiwic3VnZ2VzdGlvbiIsImRvY0xpbmsiLCJrZXkiLCJoYXMiLCJzZXQiLCJ0cmVlT3V0cHV0Iiwic2hvd1ZhbHVlcyIsInRyZWVDaGFyQ29sb3JzIiwidHJlZUNoYXIiLCJ2YWx1ZSIsInNpemUiLCJBcnJheSIsImZyb20iLCJ2YWx1ZXMiLCJfdGVtcDMiLCJ0MyIsInBhaXIiLCJpbmRleCIsImEiLCJiIiwibG9jYWxlQ29tcGFyZSIsImFjYyJdLCJzb3VyY2VzIjpbIlZhbGlkYXRpb25FcnJvcnNMaXN0LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgc2V0V2l0aCBmcm9tICdsb2Rhc2gtZXMvc2V0V2l0aC5qcydcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgQm94LCBUZXh0LCB1c2VUaGVtZSB9IGZyb20gJy4uL2luay5qcydcbmltcG9ydCB0eXBlIHsgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vdXRpbHMvc2V0dGluZ3MvdmFsaWRhdGlvbi5qcydcbmltcG9ydCB7IHR5cGUgVHJlZU5vZGUsIHRyZWVpZnkgfSBmcm9tICcuLi91dGlscy90cmVlaWZ5LmpzJ1xuXG4vKipcbiAqIEJ1aWxkcyBhIG5lc3RlZCB0cmVlIHN0cnVjdHVyZSBmcm9tIGRvdC1ub3RhdGlvbiBwYXRoc1xuICogVXNlcyBsb2Rhc2ggc2V0V2l0aCB0byBhdm9pZCBhdXRvbWF0aWMgYXJyYXkgY3JlYXRpb25cbiAqL1xuZnVuY3Rpb24gYnVpbGROZXN0ZWRUcmVlKGVycm9yczogVmFsaWRhdGlvbkVycm9yW10pOiBUcmVlTm9kZSB7XG4gIGNvbnN0IHRyZWU6IFRyZWVOb2RlID0ge31cblxuICBlcnJvcnMuZm9yRWFjaChlcnJvciA9PiB7XG4gICAgaWYgKCFlcnJvci5wYXRoKSB7XG4gICAgICAvLyBSb290IGxldmVsIGVycm9yIC0gdXNlIGVtcHR5IHN0cmluZyBhcyBrZXlcbiAgICAgIHRyZWVbJyddID0gZXJyb3IubWVzc2FnZVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIGVuaGFuY2UgdGhlIHBhdGggd2l0aCBtZWFuaW5nZnVsIHZhbHVlc1xuICAgIGNvbnN0IHBhdGhQYXJ0cyA9IGVycm9yLnBhdGguc3BsaXQoJy4nKVxuICAgIGxldCBtb2RpZmllZFBhdGggPSBlcnJvci5wYXRoXG5cbiAgICAvLyBJZiB3ZSBoYXZlIGFuIGludmFsaWQgdmFsdWUsIHRyeSB0byBtYWtlIHRoZSBwYXRoIG1vcmUgcmVhZGFibGVcbiAgICBpZiAoXG4gICAgICBlcnJvci5pbnZhbGlkVmFsdWUgIT09IG51bGwgJiZcbiAgICAgIGVycm9yLmludmFsaWRWYWx1ZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBwYXRoUGFydHMubGVuZ3RoID4gMFxuICAgICkge1xuICAgICAgY29uc3QgbmV3UGF0aFBhcnRzOiBzdHJpbmdbXSA9IFtdXG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0aFBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHBhcnQgPSBwYXRoUGFydHNbaV1cbiAgICAgICAgaWYgKCFwYXJ0KSBjb250aW51ZVxuXG4gICAgICAgIGNvbnN0IG51bWVyaWNQYXJ0ID0gcGFyc2VJbnQocGFydCwgMTApXG5cbiAgICAgICAgLy8gSWYgdGhpcyBpcyBhIG51bWVyaWMgaW5kZXggYW5kIGl0J3MgdGhlIGxhc3QgcGFydCB3aGVyZSB3ZSBoYXZlIHRoZSBpbnZhbGlkIHZhbHVlXG4gICAgICAgIGlmICghaXNOYU4obnVtZXJpY1BhcnQpICYmIGkgPT09IHBhdGhQYXJ0cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgLy8gRm9ybWF0IHRoZSB2YWx1ZSBmb3IgZGlzcGxheVxuICAgICAgICAgIGxldCBkaXNwbGF5VmFsdWU6IHN0cmluZ1xuICAgICAgICAgIGlmICh0eXBlb2YgZXJyb3IuaW52YWxpZFZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgZGlzcGxheVZhbHVlID0gYFwiJHtlcnJvci5pbnZhbGlkVmFsdWV9XCJgXG4gICAgICAgICAgfSBlbHNlIGlmIChlcnJvci5pbnZhbGlkVmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGRpc3BsYXlWYWx1ZSA9ICdudWxsJ1xuICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IuaW52YWxpZFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGRpc3BsYXlWYWx1ZSA9ICd1bmRlZmluZWQnXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRpc3BsYXlWYWx1ZSA9IFN0cmluZyhlcnJvci5pbnZhbGlkVmFsdWUpXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbmV3UGF0aFBhcnRzLnB1c2goZGlzcGxheVZhbHVlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEtlZXAgb3RoZXIgcGFydHMgYXMtaXNcbiAgICAgICAgICBuZXdQYXRoUGFydHMucHVzaChwYXJ0KVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG1vZGlmaWVkUGF0aCA9IG5ld1BhdGhQYXJ0cy5qb2luKCcuJylcbiAgICB9XG5cbiAgICBzZXRXaXRoKHRyZWUsIG1vZGlmaWVkUGF0aCwgZXJyb3IubWVzc2FnZSwgT2JqZWN0KVxuICB9KVxuXG4gIHJldHVybiB0cmVlXG59XG5cbi8qKlxuICogR3JvdXBzIGFuZCBkaXNwbGF5cyB2YWxpZGF0aW9uIGVycm9ycyB1c2luZyB0cmVlaWZ5IHdpdGggZGVkdXBsaWNhdGlvblxuICovXG5leHBvcnQgZnV
|