The forge-tree tool provides comprehensive path handling capabilities through three main components:
- Path Validation
- Path Normalization
- Conflict Resolution
The PathValidationRules configuration allows you to define constraints for file and directory paths:
{
maxDepth: 32, // Maximum directory depth
maxPathLength: 260, // Maximum path length
maxNameLength: 255, // Maximum file/directory name length
allowedChars: "^[a-zA-Z0-9-_.]+$", // Regex for allowed characters
disallowedNames: ["CON", "PRN", "AUX", ...], // Reserved names
enforceCase: "any", // "lower", "upper", or "any"
allowDots: false, // Allow dots in directory names
allowSpaces: false, // Allow spaces in paths
requireExtensions: false, // Require file extensions
allowedExtensions: [], // List of allowed extensions
uniqueNames: true, // Require unique names within directories
uniquePaths: true, // Require globally unique paths
normalizeSlashes: true, // Normalize path separators
trimWhitespace: true, // Trim whitespace from names
resolveRelative: false // Resolve relative paths (../foo)
}The PathConflictStrategy configuration defines how to handle various path-related conflicts:
When a path already exists:
{
onDuplicatePath: "numbered", // How to handle duplicate paths
renamePattern: "{name}-{n}", // Pattern for numbered duplicates
counterStart: 1, // Starting number for duplicates
counterPadding: 3, // Padding for numbers (e.g., 001)
}Options for onDuplicatePath:
"error": Throw an error (default)"warn": Log a warning but continue"rename": Auto-rename using the pattern"merge": Use mergeStrategy to combine content"skip": Skip the duplicate"numbered": Add incremental numbers"timestamp": Add timestamps- Custom function:
(path, conflict) => string
When paths contain invalid characters:
{
onInvalidChars: "replace", // How to handle invalid characters
replacementChar: "_", // Character to use for replacement
transliterationMap: { // Custom character mappings
"é": "e",
"ñ": "n",
"@": "at"
}
}Options for onInvalidChars:
"error": Throw an error (default)"warn": Log a warning but continue"replace": Replace with replacementChar"strip": Remove invalid characters"encode": URL-encode invalid characters"transliterate": Use transliterationMap- Custom function:
(path, conflict) => string
When paths exceed maximum length:
{
onLongPath: "truncate", // How to handle long paths
preserveExtension: true, // Keep file extensions when shortening
hashAlgorithm: "sha256" // Algorithm for hash-based shortening
}Options for onLongPath:
"error": Throw an error (default)"warn": Log a warning but continue"truncate": Cut off excess characters"hash": Replace with short hash"shorten": Intelligently shorten- Custom function:
(path, conflict) => string
When merging duplicate paths:
{
mergeStrategy: {
files: "keep-newer", // How to merge duplicate files
directories: "merge-recursive" // How to merge directories
}
}Options for files:
"keep-both": Keep both files (rename one)"keep-newer": Keep the newer file"keep-larger": Keep the larger file"concatenate": Combine file contents- Custom function:
(path, conflict) => string
Options for directories:
"merge-recursive": Combine contents recursively"keep-both": Keep both directories (rename one)"keep-newer": Keep the newer directory- Custom function:
(path, conflict) => string
The pathNormalization configuration controls how paths are standardized:
{
style: "unix", // "unix", "windows", or "mixed"
base: "root", // "root", "relative", or "absolute"
case: "preserve" // "preserve", "lower", or "upper"
}const config = {
pathValidation: {
maxPathLength: 200,
allowedChars: "^[a-z0-9-]+$",
enforceCase: "lower",
uniquePaths: true
}
};const config = {
pathConflict: {
onDuplicatePath: "numbered",
renamePattern: "{name}-copy-{n}",
counterStart: 1,
counterPadding: 2
}
};const config = {
pathConflict: {
onInvalidChars: "transliterate",
transliterationMap: {
"é": "e",
"ñ": "n",
"ü": "u",
"@": "at",
"&": "and"
}
}
};const config = {
pathConflict: {
onLongPath: "shorten",
preserveExtension: true
}
};const config = {
pathConflict: {
onDuplicatePath: "merge",
mergeStrategy: {
files: "keep-newer",
directories: "merge-recursive"
}
}
};const config = {
pathConflict: {
onDuplicatePath: (path, conflict) => {
if (conflict.type === "duplicate") {
return path + ".backup";
}
return path;
}
}
};-
Start Strict: Begin with strict validation rules and loosen them if needed:
{ pathValidation: { allowedChars: "^[a-z0-9-]+$", enforceCase: "lower", uniquePaths: true } }
-
Safe Defaults: Use safe conflict resolution strategies:
{ pathConflict: { onDuplicatePath: "numbered", onInvalidChars: "replace", onLongPath: "truncate" } }
-
Preserve Extensions: When shortening paths:
{ pathConflict: { preserveExtension: true } }
-
Consistent Style: Use consistent path normalization:
{ pathNormalization: { style: "unix", case: "lower" } }
Path validation errors include:
duplicatePath: Path already existsinvalidChars: Contains invalid characterslongPath: Exceeds maximum lengthmaxDepth: Too many directory levelsreservedName: Uses reserved namewrongCase: Incorrect casedotsInDir: Dots in directory namespacesInPath: Contains spacesmissingExtension: No file extensioninvalidExtension: Disallowed extension
Each error includes:
type: "error" or "warning"code: Error codemessage: Human-readable messagepath: Affected pathdetails: Additional contextresolvedPath: Suggested fix (if available)