urlHandler.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { createParserConfig } from './cli'
  2. import { parse as parseShellCommand } from 'shell-quote'
  3. export function isTabbyURL (arg: string): boolean {
  4. return arg.toLowerCase().startsWith('tabby://')
  5. }
  6. export function parseTabbyURL (url: string, cwd: string = process.cwd()): any {
  7. try {
  8. if (!isTabbyURL(url)) {
  9. return null
  10. }
  11. // NOTE: the url host may be lowercased (xdg-open), need to use the original command
  12. const urlInstance = new URL(url)
  13. const command = urlInstance.host || urlInstance.pathname.replace(/^\/+/, '')
  14. const config = createParserConfig(cwd)
  15. const commandConfig = config.commands.find(cmd => {
  16. const primaryCommand = Array.isArray(cmd.command) ? cmd.command[0] : cmd.command
  17. return command.toLowerCase() === primaryCommand.split(/\s+/)[0].toLowerCase()
  18. })
  19. if (!commandConfig) {
  20. console.error(`Unknown command in tabby:// URL: ${command}`)
  21. return null
  22. }
  23. const primaryCommand = Array.isArray(commandConfig.command) ? commandConfig.command[0] : commandConfig.command
  24. const actualCommand = primaryCommand.split(/\s+/)[0]
  25. const argv: any = {
  26. _: [actualCommand],
  27. }
  28. for (const [key, value] of urlInstance.searchParams.entries()) {
  29. let parsedValue: any = value
  30. const optionConfig = commandConfig.options?.[key] ?? commandConfig.positionals?.[key]
  31. if (optionConfig) {
  32. switch (optionConfig.type) {
  33. case 'boolean':
  34. parsedValue = value === 'true' || value === ''
  35. break
  36. case 'number':
  37. parsedValue = parseInt(value, 10)
  38. break
  39. case 'array':
  40. parsedValue = parseShellCommand(value).filter(item => typeof item === 'string')
  41. break
  42. case 'string':
  43. default:
  44. parsedValue = value
  45. break
  46. }
  47. } else {
  48. parsedValue = value
  49. }
  50. argv[key] = parsedValue
  51. }
  52. console.log(`URL Handler - Safely parsed [${url}] to:`, JSON.stringify(argv))
  53. return argv
  54. } catch (e) {
  55. console.error('Failed to parse tabby:// URL:', e)
  56. return null
  57. }
  58. }