@synet/path
v1.0.0
Published
Cross-platform path manipulation with immutable operations
Readme
Path Unit
_____ _ _ _ _ _ _
| __ \ | | | | | | | | (_) |
| |__) |_ _| |_| |__ | | | |_ __ _| |_
| ___/ _` | __| '_ \ | | | | '_ \| | __|
| | | (_| | |_| | | | | |__| | | | | | |_
|_| \__,_|\__|_| |_| \____/|_| |_|_|\__|
version: 1.0.0 Cross-platform path manipulation with immutable operations
Simple, pure, and composable path operations for Node.js and browser environments. Built with immutable design principles - no mutation, maximum reliability, zero external dependencies.
Quick Start
import { Path, createPath, join, parse } from '@synet/path';
// Object-oriented API
const path = Path.create({ path: '/home/user/documents' });
const file = path.join('projects', 'readme.txt');
console.log(file.toString()); // '/home/user/documents/projects/readme.txt'
// Functional API
const joined = join('home', 'user', 'documents');
const info = parse('/home/user/file.txt');
console.log(info.directory); // '/home/user'
console.log(info.extension); // '.txt'Features
Immutable Design
- No state mutation - every operation returns new instances
- Thread-safe by design
- Functional programming friendly
Cross-Platform
- Handles both POSIX (
/) and Windows (\) paths - Automatic separator detection
- Consistent behavior across platforms
Pure Functions
- Zero external dependencies
- Predictable, testable operations
- Composable function library
Type Safety
- Full TypeScript support
- Comprehensive type definitions
- Compile-time path validation
Installation
npm install @synet/pathCore API
Path Creation
import { Path, createPath, createPosixPath, createWindowsPath } from '@synet/path';
// Auto-detect separator
const path = Path.create({ path: '/home/user/docs' });
// Force POSIX
const posixPath = createPosixPath('home\\user\\docs'); // Normalized to 'home/user/docs'
// Force Windows
const winPath = createWindowsPath('home/user/docs'); // Normalized to 'home\\user\\docs'
// With metadata
const pathWithMeta = Path.create({
path: '/project/src',
metadata: { project: 'myapp', version: '1.0' }
});Path Operations
const basePath = createPath('/home/user');
// Join segments (immutable)
const docs = basePath.join('documents', 'projects');
console.log(docs.path); // '/home/user/documents/projects'
console.log(basePath.path); // '/home/user' (unchanged)
// Resolve relative paths
const resolved = docs.resolve('../images/photo.jpg');
console.log(resolved.path); // '/home/user/documents/images/photo.jpg'
// Get relative path
const relative = docs.relative('/home/user/downloads');
console.log(relative.path); // '../downloads'
// Parent directory
const parent = docs.parent();
console.log(parent.path); // '/home/user/documents'
// Change extension
const filePath = createPath('/docs/readme.txt');
const markdown = filePath.withExtension('.md');
console.log(markdown.path); // '/docs/readme.md'Path Information
const path = createPath('/home/user/projects/app/src/index.ts');
// Basic info
console.log(path.directory); // '/home/user/projects/app/src'
console.log(path.filename); // 'index.ts'
console.log(path.basename); // 'index'
console.log(path.extension); // '.ts'
console.log(path.isAbsolute); // true
console.log(path.separator); // '/'
// Parsed information
const parsed = path.getParsed();
console.log(parsed);
// {
// full: '/home/user/projects/app/src/index.ts',
// directory: '/home/user/projects/app/src',
// name: 'index.ts',
// base: 'index',
// extension: '.ts',
// isAbsolute: true,
// separator: '/'
// }Pure Functional API
For functional programming enthusiasts:
import {
joinPath,
resolvePath,
relativePath,
normalizePath,
parsePath,
getExtension,
getBasename,
getFilename,
getDirectory,
PathSeparator
} from '@synet/path';
// Pure functions - no state, easy to test
const joined = joinPath('home', 'user', 'docs');
const normalized = normalizePath('home\\user', PathSeparator.POSIX);
const resolved = resolvePath('/home/user', '../shared/file.txt', PathSeparator.POSIX);
const parsed = parsePath('/home/user/file.txt', PathSeparator.POSIX);
const relative = relativePath('/home/user', '/home/shared', PathSeparator.POSIX);
// Utility functions
const extension = getExtension('/docs/file.txt'); // '.txt'
const basename = getBasename('/docs/file.txt'); // 'file'
const filename = getFilename('/docs/file.txt'); // 'file.txt'
const directory = getDirectory('/docs/file.txt', PathSeparator.POSIX); // '/docs'Convenience Functions
import { join, normalize, parse } from '@synet/path';
// Quick operations
const joined = join('app', 'src', 'utils'); // 'app/src/utils'
const normalized = normalize('app\\src\\utils'); // 'app/src/utils'
const info = parse('/home/user/file.txt');
// { directory: '/home/user', name: 'file.txt', extension: '.txt', ... }Cross-Platform Examples
Development Workflow
import { createPath, PathSeparator } from '@synet/path';
// Works on any platform
const projectRoot = createPath(process.cwd());
const srcDir = projectRoot.join('src');
const testDir = projectRoot.join('test');
const buildDir = projectRoot.join('dist');
// Get relative paths for build tools
const srcRelative = srcDir.relative(buildDir.path);
console.log(`Source: ${srcRelative}`); // '../src'
// Handle different platforms
const windowsPath = createPath('C:\\Projects\\MyApp', PathSeparator.WINDOWS);
const posixPath = windowsPath.resolve('src/index.ts');
// Maintains Windows separators: 'C:\\Projects\\MyApp\\src\\index.ts'File Processing
import { Path } from '@synet/path';
function processFiles(inputDir: string, outputDir: string) {
const input = Path.create({ path: inputDir });
const output = Path.create({ path: outputDir });
// Process TypeScript files
const srcFiles = ['index.ts', 'utils.ts', 'types.ts'];
srcFiles.forEach(file => {
const sourcePath = input.join(file);
const outputPath = output.join(sourcePath.withExtension('.js').filename);
console.log(`Compile: ${sourcePath} -> ${outputPath}`);
});
}
processFiles('/project/src', '/project/dist');Asset Management
import { createPath } from '@synet/path';
class AssetManager {
constructor(private rootPath: string) {}
getAssetPath(category: string, filename: string) {
const root = createPath(this.rootPath);
return root.join('assets', category, filename);
}
getRelativeAssetPath(fromPath: string, assetPath: string) {
const from = createPath(fromPath);
const asset = createPath(assetPath);
return from.relative(asset.path);
}
}
const assets = new AssetManager('/var/www/myapp');
const imagePath = assets.getAssetPath('images', 'logo.png');
// Result: Path('/var/www/myapp/assets/images/logo.png')
const relativePath = assets.getRelativeAssetPath('/var/www/myapp/pages', imagePath.path);
// Result: Path('../assets/images/logo.png')Unit Interface
The Path unit implements a consistent interface:
const path = createPath('/home/user/project');
// Self-documentation
console.log(path.whoami());
// "Path Unit - /home/user/project ([email protected])"
console.log(path.capabilities());
// ['join', 'resolve', 'relative', 'parent', 'withExtension', 'cross-platform', ...]
console.log(path.help());
// Comprehensive help information
// JSON export
const exported = path.toJSON();
// {
// unitType: 'path',
// version: '1.0.0',
// path: '/home/user/project',
// separator: '/',
// parsed: { ... },
// created: '2025-07-30T15:18:00.000Z'
// }Advanced Usage
Custom Path Processing
import { Path, PathSeparator } from '@synet/path';
// Chain operations immutably
const result = Path
.create({ path: '/project' })
.join('src', 'components')
.resolve('../utils')
.join('helper.ts')
.withExtension('.js');
console.log(result.path); // '/project/src/utils/helper.js'Path Validation
import { isAbsolutePath, detectSeparator } from '@synet/path';
function validatePath(pathString: string) {
return {
isAbsolute: isAbsolutePath(pathString),
separator: detectSeparator(pathString),
isValid: pathString.length > 0,
platform: detectSeparator(pathString) === PathSeparator.WINDOWS ? 'Windows' : 'POSIX'
};
}
console.log(validatePath('/home/user')); // { isAbsolute: true, platform: 'POSIX' }
console.log(validatePath('C:\\Users\\Admin')); // { isAbsolute: true, platform: 'Windows' }Batch Path Operations
import { createPath } from '@synet/path';
function processProjectPaths(projectRoot: string, files: string[]) {
const root = createPath(projectRoot);
return files.map(file => {
const fullPath = root.join(file);
return {
original: file,
full: fullPath.path,
directory: fullPath.directory,
filename: fullPath.filename,
extension: fullPath.extension,
isSource: fullPath.extension === '.ts' || fullPath.extension === '.js',
relative: root.relative(fullPath.path).path
};
});
}
const results = processProjectPaths('/project', [
'src/index.ts',
'test/unit.test.ts',
'docs/readme.md'
]);TypeScript Support
Full TypeScript support with strict typing:
import { Path, PathInfo, PathSeparator, PathConfig } from '@synet/path';
// Type-safe configuration
const config: PathConfig = {
path: '/home/user',
separator: PathSeparator.POSIX,
caseSensitive: true,
metadata: { source: 'user-input' }
};
const path: Path = Path.create(config);
const info: PathInfo = path.getParsed();
// All operations are typed
const joined: Path = path.join('documents', 'file.txt');
const extension: string = path.extension;
const isAbsolute: boolean = path.isAbsolute;Performance
The Path unit is designed for performance:
- Zero dependencies - No external library overhead
- Immutable operations - Predictable memory usage
- Pure functions - Easy optimization and caching
- Minimal allocations - Efficient string operations
import { measure } from '@synet/timer'; // If you have timer unit
// Benchmark path operations
const { duration } = measure(() => {
let path = createPath('/base');
for (let i = 0; i < 1000; i++) {
path = path.join(`segment-${i}`);
}
return path;
}, 'path-operations');
console.log(`1000 path operations: ${duration.toFixed(2)}ms`);Contributing
Built with love by the SYNET team. Part of the larger Unit Architecture ecosystem.
- Issues: GitHub Issues
- Docs: Unit Architecture Guide
License
MIT - Build amazing things!
