(argv: string[])
| 19 | } |
| 20 | |
| 21 | function parseArgs(argv: string[]): ParsedArgs { |
| 22 | // Default: help. Recognized positional commands: grant | revoke | list. |
| 23 | let command: ParsedArgs['command'] = 'help'; |
| 24 | let identity: string | null = null; |
| 25 | let capability: Capability = 'interact'; |
| 26 | let ttlSeconds: number | null = null; |
| 27 | let note: string | null = null; |
| 28 | let path = defaultAllowlistPath(); |
| 29 | |
| 30 | for (let i = 0; i < argv.length; i++) { |
| 31 | const a = argv[i]; |
| 32 | switch (a) { |
| 33 | case 'grant': command = 'grant'; break; |
| 34 | case 'revoke': command = 'revoke'; break; |
| 35 | case 'list': command = 'list'; break; |
| 36 | case '--help': |
| 37 | case '-h': command = 'help'; break; |
| 38 | case '--remote': |
| 39 | case '--identity': |
| 40 | identity = argv[++i] ?? null; |
| 41 | break; |
| 42 | case '--capability': |
| 43 | case '--cap': { |
| 44 | const v = argv[++i]; |
| 45 | if (!CAPABILITIES.includes(v as Capability)) { |
| 46 | process.stderr.write(`unknown capability: ${v} (want one of ${CAPABILITIES.join(', ')})\n`); |
| 47 | process.exit(2); |
| 48 | } |
| 49 | capability = v as Capability; |
| 50 | break; |
| 51 | } |
| 52 | case '--ttl': { |
| 53 | const v = parseInt(argv[++i] ?? '', 10); |
| 54 | if (!Number.isFinite(v) || v <= 0) { |
| 55 | process.stderr.write('--ttl must be a positive integer (seconds)\n'); |
| 56 | process.exit(2); |
| 57 | } |
| 58 | ttlSeconds = v; |
| 59 | break; |
| 60 | } |
| 61 | case '--note': note = argv[++i] ?? null; break; |
| 62 | case '--allowlist-path': path = argv[++i] ?? path; break; |
| 63 | } |
| 64 | } |
| 65 | return { command, identity, capability, ttlSeconds, note, path }; |
| 66 | } |
| 67 | |
| 68 | function printHelp() { |
| 69 | const help = `gstack-ios-qa-mint — manage the tailnet allowlist for remote iOS QA agents |
no test coverage detected