args.ts 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /**
  2. * Commander adapter for the dsh-sdk subcommand surface.
  3. *
  4. * @module @deepseek-ai/dsh-scripts/args
  5. */
  6. import { parseArgs as parseNodeArgs } from 'node:util'
  7. import { Command } from 'commander'
  8. /** Commands implemented by the dsh-sdk launcher. */
  9. type DshSdkCommand = 'start' | 'dev' | 'build' | 'config' | 'create'
  10. /** Parsed dsh-sdk invocation. */
  11. export interface DshSdkArgs {
  12. command?: DshSdkCommand
  13. target?: string
  14. source?: string
  15. forwarded: readonly string[]
  16. help: boolean
  17. }
  18. /** Parse arbitrary project flags through Node's zero-schema argument parser. */
  19. export function parseSdkBootArgs(argv: readonly string[]): Record<string, string | boolean | undefined> {
  20. return parseNodeArgs({
  21. args: [...argv],
  22. strict: false,
  23. allowPositionals: true,
  24. allowNegative: true,
  25. }).values
  26. }
  27. /** Parse one launcher invocation through real Commander subcommands. */
  28. export function parseDshSdkArgs(argv: readonly string[]): DshSdkArgs {
  29. if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
  30. return { forwarded: [], help: true }
  31. }
  32. const separator = argv.indexOf('--')
  33. const launcherArgv = separator === -1 ? argv : argv.slice(0, separator)
  34. const passthrough = separator === -1 ? [] : argv.slice(separator + 1)
  35. let parsed: DshSdkArgs | undefined
  36. const program = new Command()
  37. .name('dsh-sdk')
  38. .helpOption(false)
  39. .showHelpAfterError(false)
  40. .exitOverride()
  41. .configureOutput({
  42. /* v8 ignore next -- the command wrapper renders the package-owned usage template */
  43. writeOut: () => {},
  44. /* v8 ignore next -- Commander errors are returned to the command wrapper */
  45. writeErr: () => {},
  46. })
  47. program.command('start [target]').helpOption(false).action((target?: string) => {
  48. parsed = { command: 'start', ...target ? { target } : {}, forwarded: [], help: false }
  49. })
  50. program.command('dev [target]').helpOption(false).action((target?: string) => {
  51. parsed = { command: 'dev', ...target ? { target } : {}, forwarded: [], help: false }
  52. })
  53. program.command('build [args...]').helpOption(false).allowUnknownOption(true).action((args: string[] = []) => {
  54. parsed = { command: 'build', forwarded: args, help: false }
  55. })
  56. program.command('config').helpOption(false).action(() => {
  57. parsed = { command: 'config', forwarded: [], help: false }
  58. })
  59. program.command('create <source>').helpOption(false).action((source: string) => {
  60. parsed = { command: 'create', source, forwarded: [], help: false }
  61. })
  62. program.parse([...launcherArgv], { from: 'user' })
  63. /* v8 ignore next -- every registered Commander action above assigns parsed or Commander throws */
  64. if (!parsed) throw new Error('dsh-sdk command did not resolve')
  65. if (parsed.command === 'config' && passthrough.length > 0) {
  66. throw new Error('dsh-sdk config does not accept forwarded arguments')
  67. }
  68. return { ...parsed, forwarded: [...parsed.forwarded, ...passthrough] }
  69. }