@masuidrive/ticket
Version:
Real-time ticket tracking viewer with Vite + Express
184 lines (155 loc) • 5.54 kB
JavaScript
#!/usr/bin/env node
const path = require('path');
const fs = require('fs');
// Check Node.js version
const requiredVersion = '18.0.0';
const currentVersion = process.version.slice(1); // Remove 'v' prefix
function versionCompare(v1, v2) {
const parts1 = v1.split('.').map(Number);
const parts2 = v2.split('.').map(Number);
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
const part1 = parts1[i] || 0;
const part2 = parts2[i] || 0;
if (part1 < part2) return -1;
if (part1 > part2) return 1;
}
return 0;
}
if (versionCompare(currentVersion, requiredVersion) < 0) {
console.error(`❌ Error: Node.js ${requiredVersion} or higher is required. You have ${process.version}`);
console.error('Please update Node.js: https://nodejs.org/');
process.exit(1);
}
// Parse command line arguments
function parseArgs() {
const args = process.argv.slice(2);
const options = {
port: 4932,
host: 'localhost',
dir: process.cwd(),
help: false
};
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg === '--help') {
options.help = true;
} else if (arg === '-h' || arg === '--host') {
const host = args[i + 1];
if (!host) {
console.error('❌ Error: Host address is required');
process.exit(1);
}
options.host = host;
i++; // Skip next argument
} else if (arg === '-p' || arg === '--port') {
const port = parseInt(args[i + 1], 10);
if (isNaN(port) || port < 1 || port > 65535) {
console.error('❌ Error: Invalid port number');
process.exit(1);
}
options.port = port;
i++; // Skip next argument
} else if (arg === '-d' || arg === '--dir') {
const dir = args[i + 1];
if (!dir) {
console.error('❌ Error: Directory path is required');
process.exit(1);
}
if (!fs.existsSync(dir)) {
console.error(`❌ Error: Directory does not exist: ${dir}`);
process.exit(1);
}
options.dir = path.resolve(dir);
i++; // Skip next argument
} else if (arg.startsWith('-')) {
console.error(`❌ Error: Unknown option: ${arg}`);
showHelp();
process.exit(1);
} else {
// Assume it's a directory path
if (fs.existsSync(arg)) {
options.dir = path.resolve(arg);
} else {
console.error(`❌ Error: Directory does not exist: ${arg}`);
process.exit(1);
}
}
}
return options;
}
function showHelp() {
console.log(`
🎫 Ticket Viewer - Real-time ticket tracking for development workflow
Usage: npx @masuidrive/ticket [options] [directory]
Options:
-p, --port <number> Server port (default: 4932)
-h, --host <address> Server host address (default: localhost)
-d, --dir <path> Project directory containing current-ticket.md (default: current directory)
--help Show this help message
Examples:
npx @masuidrive/ticket # Start in current directory
npx @masuidrive/ticket ./my-project # Start in specific directory
npx @masuidrive/ticket -p 3000 # Start on port 3000
npx @masuidrive/ticket -h 0.0.0.0 # Listen on all interfaces
npx @masuidrive/ticket -h 0.0.0.0 -p 3000 -d ./my-project
The ticket viewer will:
- Look for current-ticket.md in the specified directory
- Start a web server at http://localhost:<port>
- Provide real-time updates when ticket files change
- Support mermaid diagrams and HTML previews
For more information, visit: https://github.com/masuidrive/ticket-sh-viewer
`);
}
async function main() {
const options = parseArgs();
if (options.help) {
showHelp();
return;
}
console.log('🎫 Starting Ticket Viewer...');
console.log(`📁 Project directory: ${options.dir}`);
console.log(`🌐 Host: ${options.host}`);
console.log(`🌐 Port: ${options.port}`);
// Set environment variables
process.env.PORT = options.port.toString();
process.env.NODE_ENV = 'production';
// Change to project directory
process.chdir(options.dir);
// Check if dist directory exists
const distPath = path.join(__dirname, '..', 'dist');
if (!fs.existsSync(distPath)) {
console.error('❌ Error: Frontend build not found. Please ensure the package is properly installed.');
process.exit(1);
}
try {
// Import and start the server
const { UnifiedServerSSE } = require('../server/dist/unified-server.js');
const server = new UnifiedServerSSE(options.dir, options.host, options.port);
await server.start();
console.log('✅ Ticket Viewer started successfully!');
console.log(`🚀 Open your browser to: http://${options.host}:${options.port}`);
// Handle graceful shutdown
process.on('SIGINT', () => {
console.log('\n🛑 Shutting down Ticket Viewer...');
server.stop();
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('\n🛑 Shutting down Ticket Viewer...');
server.stop();
process.exit(0);
});
} catch (error) {
console.error('❌ Error starting Ticket Viewer:', error.message);
console.error('\nTroubleshooting:');
console.error('- Ensure Node.js 18+ is installed');
console.error('- Check if the port is already in use');
console.error('- Verify the directory exists and is accessible');
process.exit(1);
}
}
// Run the CLI
main().catch((error) => {
console.error('❌ Unexpected error:', error);
process.exit(1);
});