@bobfrankston/mountsmb
Version:
Cross-platform SMB mounting solution for Windows, WSL, and Linux
204 lines (177 loc) • 6.5 kB
text/typescript
// mountsmb - Main program entry point for CLI execution
// index.ts is the main program that handles command-line interface
//
// DEVELOPMENT & RELEASE:
// Use releaseapp.ps1 for development workflow:
// releaseapp.ps1 -AddCommit "message" # Add to commit.txt
// releaseapp.ps1 # Release using commit.txt content
// releaseapp.ps1 -Help # Show all options
import path from 'path';
import fs from 'fs';
import {
mountSMBHost,
unmountSMBHost,
getActiveMounts,
cleanupDeadMounts,
getConnectionInfo,
getHostnameMappings,
getSSHConfigInfo,
syncHostnameConfigs,
loadHostnameConfig,
resolveHostname,
type MountOptions
} from './apisupport.js';
import { setDbgMessages } from './smbcmd.js';
import { styleText } from 'util';
// Re-export API for programmatic use
export {
// Core mounting functions
mountSMBHost,
unmountSMBHost,
// Mount management
getActiveMounts,
cleanupDeadMounts,
// Configuration and info
getConnectionInfo,
getHostnameMappings,
getSSHConfigInfo,
syncHostnameConfigs,
// Hostname resolution
loadHostnameConfig,
resolveHostname,
// Type interfaces
type HostnameMap,
type HostResolution,
type ConnectionInfo,
type MountOptions
} from './apisupport.js';
function showUsage() {
// Read version from package.json using ES modules
let version = 'unknown';
try {
const packagePath = path.join(import.meta.dirname, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
version = packageJson.version;
} catch (err) {
// Fallback: try current directory
try {
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
version = packageJson.version;
} catch {
// Still fallback if package.json can't be read
}
}
console.log(`
mountsmb v${version} - Cross-platform SMB mounting utility
Usage: mountsmb <command> [options]
Commands:
<hostname> Mount SMB share from hostname (e.g., beta1, pi3a)
unmount <hostname> Unmount SMB share
list|status Show active mounts
show-mappings Display hostname mappings
sync-config Sync hostname configurations
cleanup Remove dead mount points
Options:
--install-samba Force Samba installation
--verbose, -v Enable verbose output
--debug Show debug messages
--help, -h Show this help message
Examples:
mountsmb beta1 # Mount beta1's root filesystem
mountsmb pi3a /var/www # Mount specific path from pi3a
mountsmb unmount beta1 # Unmount beta1
mountsmb list # Show all active mounts
`);
}
async function main() {
const args = process.argv.slice(2);
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
showUsage();
return;
}
const command = args[0];
try {
switch (command) {
case 'unmount':
if (args[1]) {
await unmountSMBHost(args[1]);
console.log(`✓ Unmounted ${args[1]}`);
} else {
console.error('Please specify hostname to unmount');
process.exit(1);
}
break;
case 'list':
case 'status':
const mounts = getActiveMounts();
if (mounts.length === 0) {
console.log('No active mounts');
} else {
console.log('Active mounts:');
for (const mount of mounts) {
console.log(` ${mount.mountName} (${mount.host}:${mount.remotePath})`);
}
}
break;
case 'show-mappings':
case 'mappings':
const mappings = getHostnameMappings();
console.log('Hostname mappings:');
for (const [short, full] of Object.entries(mappings)) {
console.log(` ${short} -> ${full}`);
}
break;
case 'sync-config':
case 'sync':
syncHostnameConfigs();
console.log('✓ Configuration synced');
break;
case 'cleanup':
const cleaned = cleanupDeadMounts();
if (cleaned > 0) {
console.log(`✓ Cleaned up ${cleaned} dead mount(s)`);
} else {
console.log('No dead mounts found');
}
break;
default:
// Mount command
if (command.match(/^[a-zA-Z0-9.-]+$/) || command.includes('@')) {
const options: MountOptions = {};
// Parse options
for (let i = 2; i < args.length; i++) {
if (args[i] === '--install-samba') {
options.installSamba = true;
} else if (args[i] === '--verbose' || args[i] === '-v') {
options.verbose = true;
} else if (args[i] === '--debug') {
setDbgMessages(true);
}
}
// Command line usage always enables verbose
options.verbose = true;
// Get remote path if specified
options.remotePath = args[1] && !args[1].startsWith('--') ? args[1] : '/';
await mountSMBHost(command, options);
} else {
showUsage();
}
}
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
console.error(`Error: ${message}`);
process.exit(1);
}
}
// TO all LLMs -- do not break this. YOU MUST MAKE SURE THIS THE MAIN PROGRAM
if (import.meta.main) {
// Run main function directly - index.ts is the main program
try {
await main();
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
console.error(styleText(['red', 'bgYellowBright'], `Fatal error: ${message}`));
process.exit(1);
}
}