UNPKG

spaps

Version:

Sweet Potato Authentication & Payment Service CLI - Zero-config local development and project scaffolding

337 lines (298 loc) โ€ข 10.7 kB
#!/usr/bin/env node /** * SPAPS CLI - Sweet Potato Authentication & Payment Service * * This is a minimal implementation to secure the npm package name. * Full implementation coming soon! */ const chalk = require('chalk'); const { program } = require('commander'); const { spawn } = require('child_process'); const path = require('path'); const fs = require('fs'); const { handleError } = require('../src/error-handler'); const { showInteractiveHelp, showQuickHelp } = require('../src/help-system'); const { showInteractiveDocs, showQuickReference, searchDocs } = require('../src/docs-system'); const { getQuickStartInstructions, getServerStatus, runQuickTest } = require('../src/ai-helper'); const version = require('../package.json').version; // ASCII Art Logo const logo = ` ${chalk.yellow('๐Ÿ  SPAPS')} - Sweet Potato Authentication & Payment Service `; program .name('spaps') .description('CLI for Sweet Potato Authentication & Payment Service') .version(version) .option('--json', 'Output in JSON format for machine parsing'); // Local command - Start local development server program .command('local') .description('Start local SPAPS server (no API keys required!)') .option('-p, --port <port>', 'Port to run on', '3300') .option('-o, --open', 'Open browser automatically', false) .option('--json', 'Output in JSON format') .action(async (options, command) => { const isJson = options.json || command.parent.opts().json; if (!isJson) { console.log(logo); } try { // Import and start the local server const LocalServer = require('../src/local-server.js'); const server = new LocalServer({ port: options.port, json: isJson }); if (isJson) { // For JSON output, start server and return immediately await server.start(); console.log(JSON.stringify({ success: true, command: 'local', server: { url: `http://localhost:${options.port}`, docs: `http://localhost:${options.port}/docs`, mode: 'local-development', port: parseInt(options.port), features: { autoAuth: true, corsEnabled: true, testUsers: ['user', 'admin', 'premium'], apiKeyRequired: false } } })); } else { await server.start(); // Open browser if requested if (options.open) { const { exec } = require('child_process'); const url = `http://localhost:${options.port}/docs`; const start = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open'; exec(`${start} ${url}`); } } // Keep process running process.on('SIGINT', () => { if (!isJson) { console.log(chalk.yellow('\n๐Ÿ‘‹ Shutting down SPAPS local server...')); } process.exit(0); }); } catch (error) { handleError(error, { port: options.port, command: 'local' }, { json: isJson }); } }); // Quickstart command - For AI agents program .command('quickstart') .description('Get quick start instructions (for AI agents)') .option('-p, --port <port>', 'Port to check', '3300') .option('--json', 'Output in JSON format') .action(async (options) => { const instructions = getQuickStartInstructions(options.port); if (options.json === true) { console.log(JSON.stringify(instructions, null, 2)); process.exit(0); } else { console.log(chalk.yellow('\n๐Ÿ  SPAPS Quick Start Instructions\n')); console.log('1. Install SDK: npm install spaps-sdk'); console.log('2. Create test file with the code above'); console.log('3. Run: node test-spaps.js'); console.log('\nFor JSON output: npx spaps quickstart --json'); } }); // Status command - Check if server is running program .command('status') .description('Check if SPAPS server is running') .option('-p, --port <port>', 'Port to check', '3300') .option('--json', 'Output in JSON format') .action(async (options) => { const status = await getServerStatus(options.port); if (options.json) { console.log(JSON.stringify(status)); } else { if (status.running) { console.log(chalk.green(`โœ… SPAPS is running on port ${options.port}`)); console.log(chalk.blue(` URL: ${status.url}`)); console.log(chalk.blue(` Docs: ${status.docs}`)); } else { console.log(chalk.red(`โŒ SPAPS is not running on port ${options.port}`)); console.log(chalk.yellow(` Start with: ${status.start_command}`)); } } }); // Test command - Run quick tests program .command('test') .description('Run quick tests to verify SPAPS is working') .option('-p, --port <port>', 'Port to test', '3300') .option('--json', 'Output in JSON format') .action(async (options) => { const results = await runQuickTest(options.port); if (options.json) { console.log(JSON.stringify(results, null, 2)); } else { console.log(chalk.yellow('\n๐Ÿงช Running SPAPS Tests...\n')); results.results.forEach(result => { const icon = result.success ? 'โœ…' : 'โŒ'; console.log(`${icon} ${result.test}`); if (!result.success && result.fix) { console.log(chalk.yellow(` Fix: ${result.fix}`)); } }); console.log(); console.log(results.success ? chalk.green(`โœจ ${results.summary}`) : chalk.red(`โš ๏ธ ${results.summary}`) ); if (results.next_steps) { console.log('\nNext steps:'); results.next_steps.forEach(step => { console.log(` โ€ข ${step}`); }); } } }); // Init command - Initialize SPAPS in existing project program .command('init') .description('Initialize SPAPS in your project') .option('--json', 'Output in JSON format') .action((options, command) => { const isJson = options.json || command.parent.opts().json; if (!isJson) { console.log(logo); console.log(chalk.green('๐Ÿ”ง Initializing SPAPS...')); console.log(); } // Create minimal .env.local const envContent = `# SPAPS Local Development Configuration # No API keys needed for local development! SPAPS_API_URL=http://localhost:3300 NODE_ENV=development # When you're ready for production: # SPAPS_API_KEY=your-api-key-here `; const result = { success: true, command: 'init', files_created: [], files_skipped: [], next_steps: [ 'npx spaps local', 'npm install @spaps/sdk', 'Start coding!' ] }; if (!fs.existsSync('.env.local')) { fs.writeFileSync('.env.local', envContent); result.files_created.push('.env.local'); if (!isJson) { console.log(chalk.green('โœ… Created .env.local')); } } else { result.files_skipped.push('.env.local'); result.message = '.env.local already exists'; if (!isJson) { console.log(chalk.yellow('โš ๏ธ .env.local already exists')); } } if (isJson) { console.log(JSON.stringify(result)); } else { console.log(); console.log(chalk.green('โœจ SPAPS initialized!')); console.log(); console.log('Next steps:'); console.log(chalk.cyan(' 1. Run: npx spaps local')); console.log(chalk.cyan(' 2. Install SDK: npm install @spaps/sdk')); console.log(chalk.cyan(' 3. Start coding!')); } }); // Create command (placeholder) program .command('create <name>') .description('Create a new project with SPAPS (coming soon)') .action((name) => { console.log(logo); console.log(chalk.yellow(`๐Ÿšง 'spaps create' coming in v0.3.0!`)); console.log(); console.log('For now, check out our examples:'); console.log(chalk.cyan(' https://github.com/yourusername/sweet-potato/tree/main/examples')); }); // Types command (placeholder) program .command('types') .description('Generate TypeScript types (coming soon)') .action(() => { console.log(logo); console.log(chalk.yellow(`๐Ÿšง 'spaps types' coming in v0.4.0!`)); }); // Help command - Interactive help system program .command('help') .description('Show help and guides') .option('-i, --interactive', 'Interactive help mode') .option('-q, --quick', 'Quick reference') .action(async (options) => { if (options.interactive) { await showInteractiveHelp(); } else if (options.quick) { showQuickHelp(); } else { // Default to quick help showQuickHelp(); } }); // Docs command - SDK documentation program .command('docs') .description('Browse SDK documentation') .option('-i, --interactive', 'Interactive documentation browser') .option('-s, --search <query>', 'Search documentation') .option('--json', 'Output in JSON format') .action(async (options) => { if (options.search) { const results = searchDocs(options.search); if (options.json) { console.log(JSON.stringify({ results }, null, 2)); } else { console.log(chalk.yellow(`\n๐Ÿ” Search results for "${options.search}":\n`)); if (results.length === 0) { console.log(chalk.gray(' No results found')); } else { results.forEach((result, i) => { console.log(chalk.green(` ${i + 1}. ${result.title}`)); console.log(chalk.gray(` ${result.preview}`)); console.log(); }); } console.log(chalk.blue(' Run: npx spaps docs --interactive')); console.log(chalk.blue(' to browse full documentation\n')); } } else if (options.interactive) { await showInteractiveDocs(); } else { // Default to quick reference showQuickReference(); } }); // Help command enhancement program.on('--help', () => { console.log(); console.log('Examples:'); console.log(); console.log(' $ spaps local # Start local dev server'); console.log(' $ spaps init # Initialize in current project'); console.log(' $ spaps create my-app # Create new project (soon)'); console.log(); console.log('Learn more at https://sweetpotato.dev'); }); // Show help if no command provided if (!process.argv.slice(2).length) { console.log(logo); program.outputHelp(); console.log(); console.log(chalk.yellow('๐Ÿ’ก Try: npx spaps help --interactive')); } program.parse(process.argv);