vde-layout
Version:
Terminal multiplexer layout management tool for VDE (Vibe Coding Development Environment)
168 lines • 7.01 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateYAML = validateYAML;
const YAML = __importStar(require("yaml"));
const zod_1 = require("zod");
const schema_1 = require("../models/schema");
const errors_1 = require("../utils/errors");
function parseYAML(yamlText) {
if (!yamlText || typeof yamlText !== "string") {
throw new errors_1.ValidationError("YAML text not provided", errors_1.ErrorCodes.CONFIG_PARSE_ERROR, {
received: typeof yamlText,
});
}
try {
return YAML.parse(yamlText);
}
catch (error) {
throw new errors_1.ValidationError("Failed to parse YAML", errors_1.ErrorCodes.CONFIG_PARSE_ERROR, {
parseError: error instanceof Error ? error.message : String(error),
yamlSnippet: yamlText.substring(0, 200),
});
}
}
function validateConfigStructure(parsed) {
if (parsed === null || parsed === undefined || typeof parsed !== "object") {
throw new errors_1.ValidationError("YAML is empty or invalid format", errors_1.ErrorCodes.CONFIG_PARSE_ERROR, {
parsed: parsed,
});
}
const parsedObj = parsed;
if (!("presets" in parsedObj) || parsedObj.presets === undefined || parsedObj.presets === null) {
throw new errors_1.ValidationError("presets field is required", errors_1.ErrorCodes.INVALID_PRESET, {
availableFields: Object.keys(parsedObj),
});
}
const presetsObj = parsedObj.presets;
if (typeof presetsObj !== "object" || presetsObj === null || Object.keys(presetsObj).length === 0) {
throw new errors_1.ValidationError("At least one preset is required", errors_1.ErrorCodes.INVALID_PRESET, {
presets: presetsObj,
});
}
}
function formatZodErrors(error) {
return error.issues.map((issue) => {
const path = issue.path.join(".");
let message = issue.message;
if (issue.code === "invalid_type") {
if (issue.path.includes("command") && issue.expected === "string") {
message = "command field must be a string";
}
else if (issue.path.includes("workingDirectory") && issue.expected === "string") {
message = "workingDirectory field must be a string";
}
else if (issue.received === "number" && issue.expected === "string") {
message = `${path} must be a string`;
}
else if (issue.received === "array" && issue.expected === "string") {
message = `${path} must be a string`;
}
}
else if (issue.code === "invalid_union") {
const unionIssue = issue;
if (unionIssue.unionErrors !== undefined) {
const terminalError = unionIssue.unionErrors.find((e) => e.issues?.some((i) => i.path.includes("command") && i.code === "invalid_type") === true);
if (terminalError !== undefined) {
message = "command field is required";
}
else {
const splitError = unionIssue.unionErrors.find((e) => e.issues?.some((i) => i.path.includes("panes") && i.code === "invalid_type") === true);
if (splitError !== undefined) {
message = "panes field is required";
}
else {
message = 'Pane type must be "terminal" or "split"';
}
}
}
else {
message = 'Pane type must be "terminal" or "split"';
}
}
else if (issue.code === "invalid_literal") {
if (issue.path.includes("direction")) {
message = 'direction must be "horizontal" or "vertical"';
}
}
else if (issue.message.includes("required")) {
message = issue.message;
}
else if (issue.code === "custom" && issue.message.includes("ratio array")) {
message = issue.message;
}
else if (issue.code === "too_small" && issue.message.includes("Array must contain at least")) {
if (path.includes("panes")) {
message = "panes array must contain at least 2 elements";
}
else if (path.includes("ratio")) {
message = "ratio array must contain at least 2 elements";
}
else {
message = issue.message;
}
}
return {
path,
message,
code: issue.code,
};
});
}
function validateYAML(yamlText) {
const parsed = parseYAML(yamlText);
validateConfigStructure(parsed);
try {
const validated = schema_1.ConfigSchema.parse(parsed);
return validated;
}
catch (error) {
if (error instanceof zod_1.z.ZodError) {
const issues = formatZodErrors(error);
const primaryMessage = issues.length > 0 && issues[0] ? issues[0].message : "Configuration validation failed";
throw new errors_1.ValidationError(primaryMessage, errors_1.ErrorCodes.CONFIG_PARSE_ERROR, {
issues,
rawErrors: error.issues,
});
}
if (error instanceof errors_1.ValidationError) {
throw error;
}
throw new errors_1.ValidationError("Unexpected validation error occurred", errors_1.ErrorCodes.CONFIG_PARSE_ERROR, {
error: error instanceof Error ? error.message : String(error),
});
}
}
//# sourceMappingURL=validator.js.map