cli.rb 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. require 'thor'
  2. require 'abbrev'
  3. module ShopifyAPI
  4. class Cli < Thor
  5. include Thor::Actions
  6. class ConfigFileError < StandardError
  7. end
  8. desc "list", "list available connections"
  9. def list
  10. available_connections.each do |c|
  11. prefix = default?(c) ? " * " : " "
  12. puts prefix + c
  13. end
  14. end
  15. desc "add CONNECTION", "create a config file for a connection named CONNECTION"
  16. def add(connection)
  17. file = config_file(connection)
  18. if File.exist?(file)
  19. raise ConfigFileError, "There is already a config file at #{file}"
  20. else
  21. config = {'protocol' => 'https'}
  22. config['domain'] = ask("Domain? (leave blank for #{connection}.myshopify.com)")
  23. config['domain'] = "#{connection}.myshopify.com" if config['domain'].blank?
  24. config['domain'] = "#{config['domain']}.myshopify.com" unless config['domain'].match(/[.:]/)
  25. puts "\nopen https://#{config['domain']}/admin/api in your browser to get API credentials\n"
  26. config['api_key'] = ask("API key?")
  27. config['password'] = ask("Password?")
  28. create_file(file, config.to_yaml)
  29. end
  30. if available_connections.one?
  31. default(connection)
  32. end
  33. end
  34. desc "remove CONNECTION", "remove the config file for CONNECTION"
  35. def remove(connection)
  36. file = config_file(connection)
  37. if File.exist?(file)
  38. remove_file(default_symlink) if default?(connection)
  39. remove_file(file)
  40. else
  41. no_config_file_error(file)
  42. end
  43. end
  44. desc "edit [CONNECTION]", "open the config file for CONNECTION with your default editor"
  45. def edit(connection=nil)
  46. file = config_file(connection)
  47. if File.exist?(file)
  48. if ENV['EDITOR'].present?
  49. system(ENV['EDITOR'], file)
  50. else
  51. puts "Please set an editor in the EDITOR environment variable"
  52. end
  53. else
  54. no_config_file_error(file)
  55. end
  56. end
  57. desc "show [CONNECTION]", "output the location and contents of the CONNECTION's config file"
  58. def show(connection=nil)
  59. connection ||= default_connection
  60. file = config_file(connection)
  61. if File.exist?(file)
  62. puts file
  63. puts `cat #{file}`
  64. else
  65. no_config_file_error(file)
  66. end
  67. end
  68. desc "default [CONNECTION]", "show the default connection, or make CONNECTION the default"
  69. def default(connection=nil)
  70. if connection
  71. target = config_file(connection)
  72. if File.exist?(target)
  73. remove_file(default_symlink)
  74. `ln -s #{target} #{default_symlink}`
  75. else
  76. no_config_file_error(target)
  77. end
  78. end
  79. if File.exist?(default_symlink)
  80. puts "Default connection is #{default_connection}"
  81. else
  82. puts "There is no default connection set"
  83. end
  84. end
  85. desc "console [CONNECTION]", "start an API console for CONNECTION"
  86. def console(connection=nil)
  87. file = config_file(connection)
  88. config = YAML.load(File.read(file))
  89. puts "using #{config['domain']}"
  90. ShopifyAPI::Base.site = site_from_config(config)
  91. require 'irb'
  92. require 'irb/completion'
  93. ARGV.clear
  94. IRB.start
  95. end
  96. tasks.keys.abbrev.each do |shortcut, command|
  97. map shortcut => command.to_sym
  98. end
  99. private
  100. def shop_config_dir
  101. @shop_config_dir ||= File.join(ENV['HOME'], '.shopify', 'shops')
  102. end
  103. def default_symlink
  104. @default_symlink ||= File.join(shop_config_dir, 'default')
  105. end
  106. def config_file(connection)
  107. if connection
  108. File.join(shop_config_dir, "#{connection}.yml")
  109. else
  110. default_symlink
  111. end
  112. end
  113. def site_from_config(config)
  114. protocol = config['protocol'] || 'https'
  115. api_key = config['api_key']
  116. password = config['password']
  117. domain = config['domain']
  118. ShopifyAPI::Base.site = "#{protocol}://#{api_key}:#{password}@#{domain}/admin"
  119. end
  120. def available_connections
  121. @available_connections ||= begin
  122. pattern = File.join(shop_config_dir, "*.yml")
  123. Dir.glob(pattern).map { |f| File.basename(f, ".yml") }
  124. end
  125. end
  126. def default_connection_target
  127. @default_connection_target ||= File.readlink(default_symlink)
  128. end
  129. def default_connection
  130. @default_connection ||= File.basename(default_connection_target, ".yml")
  131. end
  132. def default?(connection)
  133. default_connection == connection
  134. end
  135. def no_config_file_error(filename)
  136. raise ConfigFileError, "There is no config file at #{filename}"
  137. end
  138. end
  139. end