@lenne.tech/cli
Version:
lenne.Tech CLI: lt
204 lines (203 loc) • 6.15 kB
JavaScript
;
/**
* Input validation utilities for CLI commands
* Provides consistent validation patterns across all commands
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidationRules = void 0;
exports.sanitizeInput = sanitizeInput;
exports.sanitizePath = sanitizePath;
exports.toCamelCase = toCamelCase;
exports.toKebabCase = toKebabCase;
exports.toPascalCase = toPascalCase;
exports.validateBranchName = validateBranchName;
exports.validateClassName = validateClassName;
exports.validateEmail = validateEmail;
exports.validateFileName = validateFileName;
exports.validateKebabCase = validateKebabCase;
exports.validateLength = validateLength;
exports.validateNpmPackage = validateNpmPackage;
exports.validatePattern = validatePattern;
exports.validatePropertyName = validatePropertyName;
exports.validateRequired = validateRequired;
/**
* Validation rules for common input types
*/
exports.ValidationRules = {
/**
* Valid branch name pattern (git-compatible)
*/
branchName: /^(?![-./])(?!.*[-./]$)(?!.*[-./]{2})[a-zA-Z0-9._/-]+$/,
/**
* Valid module/class name (PascalCase)
*/
className: /^[A-Z][a-zA-Z0-9]*$/,
/**
* Valid email address pattern
*/
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
/**
* Valid file/directory name (no special chars)
*/
fileName: /^[a-zA-Z0-9._-]+$/,
/**
* Valid kebab-case name
*/
kebabCase: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,
/**
* Valid npm package name
*/
npmPackage: /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,
/**
* Valid property name (camelCase)
*/
propertyName: /^[a-z][a-zA-Z0-9]*$/,
/**
* Valid semver version
*/
semver: /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/,
};
/**
* Sanitize input by removing potentially dangerous characters
*/
function sanitizeInput(input) {
if (!input)
return '';
return (input
.trim()
// Remove shell special characters
.replace(/[;&|`$(){}[\]<>\\'"]/g, '')
// Remove control characters
.replace(/[\x00-\x1F\x7F]/g, '')
// Collapse multiple spaces
.replace(/\s+/g, ' '));
}
/**
* Sanitize a file path to prevent directory traversal
*/
function sanitizePath(input) {
if (!input)
return '';
return (input
.trim()
// Remove directory traversal attempts
.replace(/\.\./g, '')
// Remove double slashes
.replace(/\/+/g, '/')
// Remove leading slashes (make relative)
.replace(/^\/+/, '')
// Remove shell special characters
.replace(/[;&|`$(){}[\]<>\\'"]/g, ''));
}
/**
* Convert string to camelCase
*/
function toCamelCase(input) {
if (!input)
return '';
const pascal = toPascalCase(input);
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
}
/**
* Convert string to kebab-case
*/
function toKebabCase(input) {
if (!input)
return '';
return input
.trim()
.replace(/([a-z])([A-Z])/g, '$1-$2')
.replace(/[\s_]+/g, '-')
.toLowerCase();
}
/**
* Convert string to PascalCase
*/
function toPascalCase(input) {
if (!input)
return '';
return input
.trim()
.replace(/[-_\s]+(.)?/g, (_, char) => (char ? char.toUpperCase() : ''))
.replace(/^(.)/, (char) => char.toUpperCase());
}
/**
* Validate a branch name
*/
function validateBranchName(input) {
return validatePattern(input, exports.ValidationRules.branchName, 'Invalid branch name. Use alphanumeric characters, dots, underscores, or hyphens.');
}
/**
* Validate a module/class name (PascalCase)
*/
function validateClassName(input) {
return validatePattern(input, exports.ValidationRules.className, 'Invalid class name. Must start with uppercase letter and contain only alphanumeric characters.');
}
/**
* Validate an email address
*/
function validateEmail(input) {
return validatePattern(input, exports.ValidationRules.email, 'Invalid email address format.');
}
/**
* Validate a file/directory name
*/
function validateFileName(input) {
return validatePattern(input, exports.ValidationRules.fileName, 'Invalid file name. Use only alphanumeric characters, dots, underscores, or hyphens.');
}
/**
* Validate a kebab-case name
*/
function validateKebabCase(input) {
return validatePattern(input, exports.ValidationRules.kebabCase, 'Invalid name. Must be lowercase with hyphens (kebab-case).');
}
/**
* Validate input length
*/
function validateLength(input, min, max, fieldName = 'Input') {
if (!input || input.trim() === '') {
return { error: `${fieldName} is required`, valid: false };
}
const trimmed = input.trim();
if (trimmed.length < min) {
return { error: `${fieldName} must be at least ${min} characters`, valid: false };
}
if (trimmed.length > max) {
return { error: `${fieldName} must be at most ${max} characters`, valid: false };
}
return { valid: true, value: trimmed };
}
/**
* Validate an npm package name
*/
function validateNpmPackage(input) {
return validatePattern(input, exports.ValidationRules.npmPackage, 'Invalid npm package name.');
}
/**
* Validate input against a pattern
*/
function validatePattern(input, pattern, errorMessage) {
if (!input || input.trim() === '') {
return { error: 'Input is required', valid: false };
}
const trimmed = input.trim();
if (!pattern.test(trimmed)) {
return { error: errorMessage, valid: false };
}
return { valid: true, value: trimmed };
}
/**
* Validate a property name (camelCase)
*/
function validatePropertyName(input) {
return validatePattern(input, exports.ValidationRules.propertyName, 'Invalid property name. Must start with lowercase letter (camelCase).');
}
/**
* Validate required input with custom validator
*/
function validateRequired(value, fieldName) {
if (value === null || value === undefined || value === '') {
return { error: `${fieldName} is required`, valid: false };
}
return { valid: true, value: String(value) };
}