forked from Shopify/shopify-api-ruby
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9416acf
commit 1dbff64
Showing
5 changed files
with
281 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env ruby | ||
require File.expand_path('../../lib/shopify_api',__FILE__) | ||
require File.expand_path('../../lib/shopify_api/cli',__FILE__) | ||
ShopifyAPI::Cli.start(ARGV) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
require 'thor' | ||
|
||
module ShopifyAPI | ||
class Cli < Thor | ||
include Thor::Actions | ||
|
||
class ConfigFileError < StandardError | ||
end | ||
|
||
desc "list", "list available connections" | ||
def list | ||
available_connections.each do |c| | ||
prefix = default?(c) ? " * " : " " | ||
puts prefix + c | ||
end | ||
end | ||
|
||
desc "add CONNECTION", "create a config file for a connection named CONNECTION" | ||
def add(connection) | ||
file = config_file(connection) | ||
if File.exist?(file) | ||
raise ConfigFileError, "There is already a config file at #{file}" | ||
else | ||
config = {'protocol' => 'https'} | ||
config['domain'] = ask("Domain? (leave blank for #{connection}.myshopify.com)") | ||
config['domain'] = "#{connection}.myshopify.com" if config['domain'].blank? | ||
puts "\nopen https://#{config['domain']}/admin/api in your browser to get API credentials\n" | ||
config['api_key'] = ask("API key?") | ||
config['password'] = ask("Password?") | ||
create_file(file, config.to_yaml) | ||
end | ||
if available_connections.one? | ||
default(connection) | ||
end | ||
end | ||
|
||
desc "remove CONNECTION", "remove the config file for CONNECTION" | ||
def remove(connection) | ||
file = config_file(connection) | ||
if File.exist?(file) | ||
remove_file(default_symlink) if default?(connection) | ||
remove_file(file) | ||
else | ||
no_config_file_error(file) | ||
end | ||
end | ||
|
||
desc "edit [CONNECTION]", "open the config file for CONNECTION with your default editor" | ||
def edit(connection=nil) | ||
file = config_file(connection) | ||
if File.exist?(file) | ||
if ENV['EDITOR'].present? | ||
`#{ENV['EDITOR']} #{file}` | ||
else | ||
puts "Please set an editor in the EDITOR environment variable" | ||
end | ||
else | ||
no_config_file_error(file) | ||
end | ||
end | ||
|
||
desc "show [CONNECTION]", "output the location and contents of the CONNECTION's config file" | ||
def show(connection=nil) | ||
connection ||= default_connection | ||
file = config_file(connection) | ||
if File.exist?(file) | ||
puts file | ||
puts `cat #{file}` | ||
else | ||
no_config_file_error(file) | ||
end | ||
end | ||
|
||
desc "default [CONNECTION]", "show the default connection, or make CONNECTION the default" | ||
def default(connection=nil) | ||
if connection | ||
target = config_file(connection) | ||
if File.exist?(target) | ||
remove_file(default_symlink) | ||
`ln -s #{target} #{default_symlink}` | ||
else | ||
no_config_file_error(file) | ||
end | ||
end | ||
if File.exist?(default_symlink) | ||
puts "Default connection is #{default_connection}" | ||
else | ||
puts "There is no default connection set" | ||
end | ||
end | ||
|
||
desc "console [CONNECTION]", "start an API console for CONNECTION" | ||
def console(connection=nil) | ||
file = config_file(connection) | ||
|
||
config = YAML.load(File.read(file)) | ||
puts "using #{config['domain']}" | ||
ShopifyAPI::Base.site = site_from_config(config) | ||
|
||
require 'irb' | ||
require 'irb/completion' | ||
ARGV.clear | ||
IRB.start | ||
end | ||
|
||
private | ||
|
||
def shop_config_dir | ||
@shop_config_dir ||= File.join(ENV['HOME'], '.shopify', 'shops') | ||
end | ||
|
||
def default_symlink | ||
@default_symlink ||= File.join(shop_config_dir, 'default') | ||
end | ||
|
||
def config_file(connection) | ||
if connection | ||
File.join(shop_config_dir, "#{connection}.yml") | ||
else | ||
default_symlink | ||
end | ||
end | ||
|
||
def site_from_config(config) | ||
protocol = config['protocol'] || 'https' | ||
api_key = config['api_key'] | ||
password = config['password'] | ||
domain = config['domain'] | ||
|
||
ShopifyAPI::Base.site = "#{protocol}://#{api_key}:#{password}@#{domain}/admin" | ||
end | ||
|
||
def available_connections | ||
@available_connections ||= begin | ||
pattern = File.join(shop_config_dir, "*.yml") | ||
Dir.glob(pattern).map { |f| File.basename(f, ".yml") } | ||
end | ||
end | ||
|
||
def default_connection_target | ||
@default_connection_target ||= File.readlink(default_symlink) | ||
end | ||
|
||
def default_connection | ||
@default_connection ||= File.basename(default_connection_target, ".yml") | ||
end | ||
|
||
def default?(connection) | ||
default_connection == connection | ||
end | ||
|
||
def no_config_file_error(filename) | ||
raise ConfigFileError, "There is no config file at #{file}" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
require 'test_helper' | ||
require 'shopify_api/cli' | ||
require 'fileutils' | ||
|
||
class CliTest < Test::Unit::TestCase | ||
def setup | ||
@test_home = File.join(File.expand_path(File.dirname(__FILE__)), 'files', 'home') | ||
@shop_config_dir = File.join(@test_home, '.shopify', 'shops') | ||
@default_symlink = File.join(@shop_config_dir, 'default') | ||
`rm -rf #{@test_home}` | ||
ENV['HOME'] = @test_home | ||
@cli = ShopifyAPI::Cli.new | ||
|
||
FileUtils.mkdir_p(@shop_config_dir) | ||
File.open(config_file('foo'), 'w') do |file| | ||
file.puts valid_options.merge('domain' => 'foo.myshopify.com').to_yaml | ||
end | ||
File.symlink(config_file('foo'), @default_symlink) | ||
File.open(config_file('bar'), 'w') do |file| | ||
file.puts valid_options.merge('domain' => 'bar.myshopify.com').to_yaml | ||
end | ||
end | ||
|
||
def teardown | ||
`rm -rf #{@test_home}` | ||
end | ||
|
||
test "add with blank domain" do | ||
`rm -rf #{@shop_config_dir}/*` | ||
$stdout.expects(:print).with("Domain? (leave blank for foo.myshopify.com) ") | ||
$stdout.expects(:print).with("API key? ") | ||
$stdout.expects(:print).with("Password? ") | ||
$stdin.expects(:gets).times(3).returns("", "key", "pass") | ||
@cli.expects(:puts).with("\nopen https://foo.myshopify.com/admin/api in your browser to get API credentials\n") | ||
@cli.expects(:puts).with("Default connection is foo") | ||
|
||
@cli.add('foo') | ||
|
||
config = YAML.load(File.read(config_file('foo'))) | ||
assert_equal 'foo.myshopify.com', config['domain'] | ||
assert_equal 'key', config['api_key'] | ||
assert_equal 'pass', config['password'] | ||
assert_equal 'https', config['protocol'] | ||
assert_equal config_file('foo'), File.readlink(@default_symlink) | ||
end | ||
|
||
test "add with explicit domain" do | ||
`rm -rf #{@shop_config_dir}/*` | ||
$stdout.expects(:print).with("Domain? (leave blank for foo.myshopify.com) ") | ||
$stdout.expects(:print).with("API key? ") | ||
$stdout.expects(:print).with("Password? ") | ||
$stdin.expects(:gets).times(3).returns("bar.myshopify.com", "key", "pass") | ||
@cli.expects(:puts).with("\nopen https://bar.myshopify.com/admin/api in your browser to get API credentials\n") | ||
@cli.expects(:puts).with("Default connection is foo") | ||
|
||
@cli.add('foo') | ||
|
||
config = YAML.load(File.read(config_file('foo'))) | ||
assert_equal 'bar.myshopify.com', config['domain'] | ||
end | ||
|
||
test "list" do | ||
@cli.expects(:puts).with(" bar") | ||
@cli.expects(:puts).with(" * foo") | ||
|
||
@cli.list | ||
end | ||
|
||
test "show default" do | ||
@cli.expects(:puts).with("Default connection is foo") | ||
|
||
@cli.default | ||
end | ||
|
||
test "set default" do | ||
@cli.expects(:puts).with("Default connection is bar") | ||
|
||
@cli.default('bar') | ||
|
||
assert_equal config_file('bar'), File.readlink(@default_symlink) | ||
end | ||
|
||
test "remove default connection" do | ||
@cli.remove('foo') | ||
|
||
assert !File.exist?(@default_symlink) | ||
assert !File.exist?(config_file('foo')) | ||
assert File.exist?(config_file('bar')) | ||
end | ||
|
||
test "remove non-default connection" do | ||
@cli.remove('bar') | ||
|
||
assert_equal config_file('foo'), File.readlink(@default_symlink) | ||
assert File.exist?(config_file('foo')) | ||
assert !File.exist?(config_file('bar')) | ||
end | ||
|
||
private | ||
|
||
def valid_options | ||
{'domain' => 'snowdevil.myshopify.com', 'api_key' => 'key', 'password' => 'pass', 'protocol' => 'https'} | ||
end | ||
|
||
def config_file(connection) | ||
File.join(@shop_config_dir, "#{connection}.yml") | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters