Spaces:
Running
Running
| export const SUPPORTED_TYPES = ['kiro', 'codex', 'opencode', 'claude-code', 'openclaw', 'cursor', 'openspec']; | |
| export function parseArgs(argv) { | |
| let inputPath = ''; | |
| let port = 3000; | |
| let open = true; | |
| let watch = true; | |
| let init = false; | |
| let full = false; | |
| let command = 'help'; | |
| let type; | |
| let i = 0; | |
| while (i < argv.length) { | |
| const arg = argv[i]; | |
| if (arg === '--help' || arg === '-h') { | |
| command = 'help'; | |
| i++; | |
| } | |
| else if (arg === '--preview') { | |
| command = 'preview'; | |
| i++; | |
| if (i < argv.length && !argv[i].startsWith('-')) { | |
| inputPath = argv[i]; | |
| i++; | |
| } | |
| } | |
| else if (arg.startsWith('--preview=')) { | |
| command = 'preview'; | |
| inputPath = arg.slice('--preview='.length); | |
| i++; | |
| } | |
| else if (arg === '--create-md') { | |
| command = 'create-md'; | |
| i++; | |
| // Optional: next argument is the target path (if not a flag) | |
| if (i < argv.length && !argv[i].startsWith('-')) { | |
| inputPath = argv[i]; | |
| i++; | |
| } | |
| } | |
| else if (arg.startsWith('--create-md=')) { | |
| command = 'create-md'; | |
| inputPath = arg.slice('--create-md='.length); | |
| i++; | |
| } | |
| else if (arg === '--analyze') { | |
| command = 'analyze'; | |
| i++; | |
| // Optional: next argument is the target path (if not a flag) | |
| if (i < argv.length && !argv[i].startsWith('-')) { | |
| inputPath = argv[i]; | |
| i++; | |
| } | |
| } | |
| else if (arg.startsWith('--analyze=')) { | |
| command = 'analyze'; | |
| inputPath = arg.slice('--analyze='.length); | |
| i++; | |
| } | |
| else if (arg === '--full') { | |
| full = true; | |
| i++; | |
| } | |
| else if (arg === '--type') { | |
| i++; | |
| if (i < argv.length) { | |
| const val = argv[i]; | |
| if (SUPPORTED_TYPES.includes(val)) { | |
| type = val; | |
| } | |
| else { | |
| return { success: false, error: `Invalid type: "${argv[i]}". Supported types: ${SUPPORTED_TYPES.join(', ')}` }; | |
| } | |
| i++; | |
| } | |
| else { | |
| return { success: false, error: `Missing value for --type. Supported types: ${SUPPORTED_TYPES.join(', ')}` }; | |
| } | |
| } | |
| else if (arg.startsWith('--type=')) { | |
| const val = arg.slice('--type='.length); | |
| if (SUPPORTED_TYPES.includes(val)) { | |
| type = val; | |
| } | |
| else { | |
| return { success: false, error: `Invalid type: "${val}". Supported types: ${SUPPORTED_TYPES.join(', ')}` }; | |
| } | |
| i++; | |
| } | |
| else if (arg === '--no-open') { | |
| open = false; | |
| i++; | |
| } | |
| else if (arg === '--no-watch') { | |
| watch = false; | |
| i++; | |
| } | |
| else if (arg === '--init') { | |
| init = true; | |
| i++; | |
| } | |
| else if (arg === '--port') { | |
| i++; | |
| const portValue = argv[i]; | |
| const parsed = parsePort(portValue); | |
| if (parsed === null) { | |
| return { success: false, error: `Invalid port: ${portValue ?? ''}. Must be a number between 1 and 65535` }; | |
| } | |
| port = parsed; | |
| i++; | |
| } | |
| else if (arg.startsWith('--port=')) { | |
| const portValue = arg.slice('--port='.length); | |
| const parsed = parsePort(portValue); | |
| if (parsed === null) { | |
| return { success: false, error: `Invalid port: ${portValue}. Must be a number between 1 and 65535` }; | |
| } | |
| port = parsed; | |
| i++; | |
| } | |
| else if (arg.startsWith('-')) { | |
| // Unknown flag — ignore (forward-compatible) | |
| i++; | |
| } | |
| else { | |
| // Positional argument — ignore | |
| i++; | |
| } | |
| } | |
| // Validation | |
| if (command === 'preview' && !inputPath) { | |
| return { success: false, error: 'Missing required path for --preview. Usage: project-understand --preview <path>' }; | |
| } | |
| return { | |
| success: true, | |
| options: { | |
| command, | |
| inputPath, | |
| port, | |
| open, | |
| watch, | |
| init, | |
| full, | |
| type, | |
| }, | |
| }; | |
| } | |
| function parsePort(value) { | |
| if (value === undefined || value === '') { | |
| return null; | |
| } | |
| const num = Number(value); | |
| if (!Number.isInteger(num) || num < 1 || num > 65535) { | |
| return null; | |
| } | |
| return num; | |
| } | |
| export function getUsageText() { | |
| return `Usage: project-understand [command] [options] | |
| Commands: | |
| --preview <path> Start a local preview server for dashboard files | |
| --create-md [path] Generate agent config files for the target directory (default: current dir) | |
| --analyze [path] Run static code analysis and generate a knowledge graph (default: current dir) | |
| Options: | |
| --type <type> Template type for --create-md (required) | |
| Supported: kiro, codex, opencode, claude-code, openclaw, cursor, openspec | |
| --init Install openspec globally and run 'openspec init' before generating files | |
| --full Force full rebuild when running --analyze (skip incremental mode) | |
| --port <number> Port for the preview server (default: 3000) | |
| --no-open Do not open the browser automatically | |
| --no-watch Do not watch for file changes | |
| --help, -h Show this help message | |
| Examples: | |
| project-understand --preview ./dashboards | |
| project-understand --preview ./my-dashboard.json --port 8080 | |
| project-understand --create-md --type kiro | |
| project-understand --create-md ./my-project --type codex | |
| project-understand --create-md --type openspec --init | |
| project-understand --analyze | |
| project-understand --analyze ./my-project | |
| project-understand --analyze ./my-project --full`; | |
| } | |