shopify-cli 1.0.0 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/CHANGELOG.md +20 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +13 -13
  6. data/docs/Gemfile.lock +23 -13
  7. data/docs/getting-started/install/index.md +37 -1
  8. data/docs/getting-started/migrate/index.md +34 -1
  9. data/lib/project_types/extension/cli.rb +1 -1
  10. data/lib/project_types/extension/commands/build.rb +1 -1
  11. data/lib/project_types/extension/models/type.rb +1 -0
  12. data/lib/project_types/extension/tasks/create_extension.rb +1 -1
  13. data/lib/project_types/extension/tasks/get_app.rb +1 -1
  14. data/lib/project_types/extension/tasks/update_draft.rb +1 -1
  15. data/lib/project_types/node/forms/create.rb +3 -54
  16. data/lib/project_types/node/messages/messages.rb +3 -14
  17. data/lib/project_types/rails/cli.rb +0 -1
  18. data/lib/project_types/rails/forms/create.rb +3 -52
  19. data/lib/project_types/rails/messages/messages.rb +2 -13
  20. data/lib/project_types/script/cli.rb +2 -3
  21. data/lib/project_types/script/commands/create.rb +5 -9
  22. data/lib/project_types/script/commands/disable.rb +4 -15
  23. data/lib/project_types/script/commands/enable.rb +37 -13
  24. data/lib/project_types/script/commands/push.rb +8 -13
  25. data/lib/project_types/script/config/extension_points.yml +9 -3
  26. data/lib/project_types/script/errors.rb +8 -0
  27. data/lib/project_types/script/forms/script_form.rb +5 -2
  28. data/lib/project_types/script/layers/application/create_script.rb +7 -6
  29. data/lib/project_types/script/layers/application/disable_script.rb +9 -7
  30. data/lib/project_types/script/layers/application/enable_script.rb +11 -9
  31. data/lib/project_types/script/layers/application/push_script.rb +6 -4
  32. data/lib/project_types/script/layers/domain/errors.rb +2 -0
  33. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +2 -2
  34. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +2 -2
  35. data/lib/project_types/script/layers/infrastructure/errors.rb +2 -0
  36. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
  37. data/lib/project_types/script/layers/infrastructure/script_repository.rb +1 -1
  38. data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -0
  39. data/lib/project_types/script/messages/messages.rb +25 -31
  40. data/lib/project_types/script/script_project.rb +8 -4
  41. data/lib/project_types/script/templates/ts/as-pect.config.js +6 -0
  42. data/lib/project_types/script/ui/error_handler.rb +8 -0
  43. data/lib/project_types/script/ui/printing_spinner.rb +75 -0
  44. data/lib/shopify-cli/admin_api.rb +1 -2
  45. data/lib/shopify-cli/admin_api/populate_resource_command.rb +10 -1
  46. data/lib/shopify-cli/admin_api/schema.rb +20 -8
  47. data/lib/shopify-cli/command.rb +14 -11
  48. data/lib/shopify-cli/commands.rb +1 -0
  49. data/lib/shopify-cli/commands/config.rb +44 -0
  50. data/lib/shopify-cli/commands/connect.rb +8 -69
  51. data/lib/shopify-cli/commands/create.rb +2 -2
  52. data/lib/shopify-cli/commands/help.rb +1 -1
  53. data/lib/shopify-cli/commands/system.rb +14 -6
  54. data/lib/shopify-cli/context.rb +10 -1
  55. data/lib/shopify-cli/core.rb +0 -1
  56. data/lib/shopify-cli/core/entry_point.rb +7 -1
  57. data/lib/shopify-cli/core/executor.rb +3 -5
  58. data/lib/shopify-cli/core/finalize.rb +13 -0
  59. data/lib/shopify-cli/core/monorail.rb +1 -1
  60. data/lib/shopify-cli/db.rb +1 -1
  61. data/lib/shopify-cli/feature.rb +97 -0
  62. data/lib/shopify-cli/heroku.rb +4 -4
  63. data/lib/shopify-cli/messages/messages.rb +51 -12
  64. data/lib/shopify-cli/partners_api/organizations.rb +7 -7
  65. data/lib/shopify-cli/process_supervision.rb +8 -6
  66. data/lib/shopify-cli/project_type.rb +5 -7
  67. data/lib/shopify-cli/sub_command.rb +1 -0
  68. data/lib/shopify-cli/task.rb +2 -2
  69. data/lib/shopify-cli/tasks.rb +12 -4
  70. data/lib/shopify-cli/tasks/ensure_env.rb +72 -16
  71. data/lib/shopify-cli/tasks/select_org_and_shop.rb +77 -0
  72. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +4 -3
  73. data/lib/shopify-cli/tunnel.rb +38 -14
  74. data/lib/shopify-cli/version.rb +1 -1
  75. data/lib/shopify_cli.rb +32 -9
  76. metadata +7 -4
  77. data/lib/project_types/script/forms/enable.rb +0 -24
  78. data/lib/project_types/script/forms/push.rb +0 -19
@@ -0,0 +1,77 @@
1
+ require 'shopify_cli'
2
+
3
+ module ShopifyCli
4
+ module Tasks
5
+ class SelectOrgAndShop < ShopifyCli::Task
6
+ attr_reader :ctx
7
+
8
+ def call(ctx, organization_id: nil, shop_domain: nil)
9
+ @ctx = ctx
10
+ return response(organization_id.to_i, shop_domain) unless organization_id.nil? || shop_domain.nil?
11
+ org = get_organization(organization_id)
12
+ shop_domain ||= get_shop_domain(org)
13
+ response(org["id"].to_i, shop_domain)
14
+ end
15
+
16
+ private
17
+
18
+ def response(organization_id, shop_domain)
19
+ {
20
+ organization_id: organization_id,
21
+ shop_domain: shop_domain,
22
+ }
23
+ end
24
+
25
+ def organizations
26
+ @organizations ||= ShopifyCli::PartnersAPI::Organizations.fetch_all(ctx)
27
+ end
28
+
29
+ def get_organization(organization_id)
30
+ @organization ||= if !organization_id.nil?
31
+ org = ShopifyCli::PartnersAPI::Organizations.fetch(ctx, id: organization_id)
32
+ if org.nil?
33
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.error.authentication_issue', ShopifyCli::TOOL_NAME))
34
+ ctx.abort(ctx.message('core.tasks.select_org_and_shop.error.organization_not_found'))
35
+ end
36
+ org
37
+ elsif organizations.count == 0
38
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.error.partners_notice'))
39
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.authentication_issue', ShopifyCli::TOOL_NAME))
40
+ ctx.abort(ctx.message('core.tasks.select_org_and_shop.error.no_organizations'))
41
+ elsif organizations.count == 1
42
+ org = organizations.first
43
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.organization', org['businessName'], org['id']))
44
+ org
45
+ else
46
+ org_id = CLI::UI::Prompt.ask(ctx.message('core.tasks.select_org_and_shop.organization_select')) do |handler|
47
+ organizations.each do |o|
48
+ handler.option(ctx.message('core.partners_api.org_name_and_id', o['businessName'], o['id'])) { o['id'] }
49
+ end
50
+ end
51
+ organizations.find { |o| o['id'] == org_id }
52
+ end
53
+ end
54
+
55
+ def get_shop_domain(organization)
56
+ valid_stores = organization['stores'].select do |store|
57
+ store['transferDisabled'] == true || store['convertableToPartnerTest'] == true
58
+ end
59
+
60
+ if valid_stores.count == 0
61
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.error.no_development_stores'))
62
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.create_store', organization['id']))
63
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.authentication_issue', ShopifyCli::TOOL_NAME))
64
+ elsif valid_stores.count == 1
65
+ domain = valid_stores.first['shopDomain']
66
+ ctx.puts(ctx.message('core.tasks.select_org_and_shop.development_store', domain))
67
+ domain
68
+ else
69
+ CLI::UI::Prompt.ask(
70
+ ctx.message('core.tasks.select_org_and_shop.development_store_select'),
71
+ options: valid_stores.map { |s| s['shopDomain'] }
72
+ )
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -28,16 +28,17 @@ module ShopifyCli
28
28
  end
29
29
 
30
30
  def construct_redirect_urls(urls, new_url, callback_url)
31
- urls.map do |url|
31
+ new_urls = urls.map do |url|
32
32
  if (match = url.match(NGROK_REGEX))
33
33
  "#{new_url}#{match[2]}"
34
34
  else
35
35
  url
36
36
  end
37
37
  end
38
- if urls.grep(/#{new_url}#{callback_url}/).empty?
39
- urls.push("#{new_url}#{callback_url}")
38
+ if new_urls.grep(/#{new_url}#{callback_url}/).empty?
39
+ new_urls.push("#{new_url}#{callback_url}")
40
40
  end
41
+ new_urls.uniq
41
42
  end
42
43
  end
43
44
  end
@@ -62,14 +62,19 @@ module ShopifyCli
62
62
  #
63
63
  def start(ctx, port: PORT)
64
64
  install(ctx)
65
- process = ShopifyCli::ProcessSupervision.start(:ngrok, ngrok_command(port))
66
- log = fetch_url(ctx, process.log_path)
67
- if log.account
68
- ctx.puts(ctx.message('core.tunnel.start_with_account', log.url, log.account))
65
+ url, account, seconds_remaining = start_ngrok(ctx, port)
66
+ if account
67
+ ctx.puts(ctx.message('core.tunnel.start_with_account', url, account))
69
68
  else
70
- ctx.puts(ctx.message('core.tunnel.start', log.url))
69
+ if seconds_remaining <= 0
70
+ ctx.puts(ctx.message('core.tunnel.timed_out'))
71
+ url, _account, seconds_remaining = restart_ngrok(ctx, port)
72
+ end
73
+ ctx.puts(ctx.message('core.tunnel.start', url))
74
+ ctx.puts(ctx.message('core.tunnel.will_timeout', seconds_to_hm(seconds_remaining)))
75
+ ctx.puts(ctx.message('core.tunnel.signup_suggestion', ShopifyCli::TOOL_NAME))
71
76
  end
72
- log.url
77
+ url
73
78
  end
74
79
 
75
80
  ##
@@ -83,7 +88,7 @@ module ShopifyCli
83
88
  #
84
89
  def auth(ctx, token)
85
90
  install(ctx)
86
- ctx.system(File.join(ShopifyCli::CACHE_DIR, 'ngrok'), 'authtoken', token)
91
+ ctx.system(File.join(ShopifyCli.cache_dir, 'ngrok'), 'authtoken', token)
87
92
  end
88
93
 
89
94
  ##
@@ -117,14 +122,14 @@ module ShopifyCli
117
122
  private
118
123
 
119
124
  def install(ctx)
120
- return if File.exist?(File.join(ShopifyCli::CACHE_DIR, 'ngrok'))
125
+ return if File.exist?(File.join(ShopifyCli.cache_dir, 'ngrok'))
121
126
  spinner = CLI::UI::SpinGroup.new
122
127
  spinner.add('Installing ngrok...') do
123
- zip_dest = File.join(ShopifyCli::CACHE_DIR, 'ngrok.zip')
128
+ zip_dest = File.join(ShopifyCli.cache_dir, 'ngrok.zip')
124
129
  unless File.exist?(zip_dest)
125
- ctx.system('curl', '-o', zip_dest, DOWNLOAD_URLS[ctx.os], chdir: ShopifyCli::CACHE_DIR)
130
+ ctx.system('curl', '-o', zip_dest, DOWNLOAD_URLS[ctx.os], chdir: ShopifyCli.cache_dir)
126
131
  end
127
- ctx.system('unzip', '-u', zip_dest, chdir: ShopifyCli::CACHE_DIR)
132
+ ctx.system('unzip', '-u', zip_dest, chdir: ShopifyCli.cache_dir)
128
133
  ctx.rm(zip_dest)
129
134
  end
130
135
  spinner.wait
@@ -138,13 +143,30 @@ module ShopifyCli
138
143
  end
139
144
 
140
145
  def ngrok_command(port)
141
- "exec #{File.join(ShopifyCli::CACHE_DIR, 'ngrok')} http -log=stdout -log-level=debug #{port}"
146
+ "exec #{File.join(ShopifyCli.cache_dir, 'ngrok')} http -inspect=false -log=stdout -log-level=debug #{port}"
142
147
  end
143
148
 
149
+ def seconds_to_hm(seconds)
150
+ format("%d hours %d minutes", seconds / 3600, seconds / 60 % 60)
151
+ end
152
+
153
+ def start_ngrok(ctx, port)
154
+ process = ShopifyCli::ProcessSupervision.start(:ngrok, ngrok_command(port))
155
+ log = fetch_url(ctx, process.log_path)
156
+ seconds_remaining = (process.time.to_i + log.timeout) - Time.now.to_i
157
+ [log.url, log.account, seconds_remaining]
158
+ end
159
+
160
+ def restart_ngrok(ctx, port)
161
+ unless ShopifyCli::ProcessSupervision.stop(:ngrok)
162
+ ctx.abort(ctx.message('core.tunnel.error.stop'))
163
+ end
164
+ start_ngrok(ctx, port)
165
+ end
144
166
  class LogParser # :nodoc:
145
167
  TIMEOUT = 10
146
168
 
147
- attr_reader :url, :account
169
+ attr_reader :url, :account, :timeout
148
170
 
149
171
  def initialize(log_path)
150
172
  @log_path = log_path
@@ -173,7 +195,9 @@ module ShopifyCli
173
195
  end
174
196
 
175
197
  def parse_account
176
- @account, _ = @log.match(/AccountName:([\w\s]+) SessionDuration/)&.captures
198
+ account, timeout, _ = @log.match(/AccountName:([\w\s]*) SessionDuration:([\d]+) PlanName/)&.captures
199
+ @account = account&.empty? ? nil : account
200
+ @timeout = timeout&.empty? ? 0 : timeout.to_i
177
201
  end
178
202
 
179
203
  def error
@@ -1,3 +1,3 @@
1
1
  module ShopifyCli
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.5'
3
3
  end
@@ -44,10 +44,6 @@ module ShopifyCli
44
44
  ROOT = File.expand_path('../..', __FILE__)
45
45
  PROJECT_TYPES_DIR = File.join(ROOT, 'lib', 'project_types')
46
46
  TEMP_DIR = File.join(ROOT, '.tmp')
47
- CACHE_DIR = File.join(File.expand_path(ENV.fetch('XDG_CACHE_HOME', '~/.cache')), TOOL_NAME)
48
- TOOL_CONFIG_PATH = File.join(File.expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config')), TOOL_NAME)
49
- LOG_FILE = File.join(TOOL_CONFIG_PATH, 'logs', 'log.log')
50
- DEBUG_LOG_FILE = File.join(TOOL_CONFIG_PATH, 'logs', 'debug.log')
51
47
 
52
48
  # programmer emoji if default install location, else wrench emoji
53
49
  EMOJI = ROOT == '/opt/shopify' ? "\u{1f469}\u{200d}\u{1f4bb}" : "\u{1f527}"
@@ -82,7 +78,7 @@ module ShopifyCli
82
78
  # ShopifyCli::Config
83
79
  autocall(:Config) { CLI::Kit::Config.new(tool_name: TOOL_NAME) }
84
80
  # ShopifyCli::Logger
85
- autocall(:Logger) { CLI::Kit::Logger.new(debug_log_file: DEBUG_LOG_FILE) }
81
+ autocall(:Logger) { CLI::Kit::Logger.new(debug_log_file: ShopifyCli.debug_log_file) }
86
82
  # ShopifyCli::Resolver
87
83
  autocall(:Resolver) do
88
84
  ShopifyCli::Core::HelpResolver.new(
@@ -93,7 +89,7 @@ module ShopifyCli
93
89
  # ShopifyCli::ErrorHandler
94
90
  autocall(:ErrorHandler) do
95
91
  CLI::Kit::ErrorHandler.new(
96
- log_file: ShopifyCli::LOG_FILE,
92
+ log_file: ShopifyCli.log_file,
97
93
  exception_reporter: nil,
98
94
  )
99
95
  end
@@ -105,6 +101,7 @@ module ShopifyCli
105
101
  autoload :Context, 'shopify-cli/context'
106
102
  autoload :Core, 'shopify-cli/core'
107
103
  autoload :DB, 'shopify-cli/db'
104
+ autoload :Feature, 'shopify-cli/feature'
108
105
  autoload :Form, 'shopify-cli/form'
109
106
  autoload :Git, 'shopify-cli/git'
110
107
  autoload :Helpers, 'shopify-cli/helpers'
@@ -126,7 +123,33 @@ module ShopifyCli
126
123
 
127
124
  require 'shopify-cli/messages/messages'
128
125
  Context.load_messages(ShopifyCli::Messages::MESSAGES)
129
- end
130
126
 
131
- # Make sure the cache dir always exists
132
- FileUtils.mkdir_p(ShopifyCli::CACHE_DIR)
127
+ def self.cache_dir
128
+ cache_dir = if ENV.key?('RUNNING_SHOPIFY_CLI_TESTS')
129
+ TEMP_DIR
130
+ else
131
+ File.join(File.expand_path(ENV.fetch('XDG_CACHE_HOME', '~/.cache')), TOOL_NAME)
132
+ end
133
+
134
+ # Make sure the cache dir always exists
135
+ @cache_dir_exists ||= FileUtils.mkdir_p(cache_dir)
136
+
137
+ cache_dir
138
+ end
139
+
140
+ def self.tool_config_path
141
+ if ENV.key?('RUNNING_SHOPIFY_CLI_TESTS')
142
+ TEMP_DIR
143
+ else
144
+ File.join(File.expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config')), TOOL_NAME)
145
+ end
146
+ end
147
+
148
+ def self.log_file
149
+ File.join(tool_config_path, 'logs', 'log.log')
150
+ end
151
+
152
+ def self.debug_log_file
153
+ File.join(tool_config_path, 'logs', 'debug.log')
154
+ end
155
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-14 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -216,8 +216,6 @@ files:
216
216
  - lib/project_types/script/config/extension_points.yml
217
217
  - lib/project_types/script/errors.rb
218
218
  - lib/project_types/script/forms/create.rb
219
- - lib/project_types/script/forms/enable.rb
220
- - lib/project_types/script/forms/push.rb
221
219
  - lib/project_types/script/forms/script_form.rb
222
220
  - lib/project_types/script/graphql/app_script_update_or_create.graphql
223
221
  - lib/project_types/script/graphql/script_service_proxy.graphql
@@ -249,6 +247,7 @@ files:
249
247
  - lib/project_types/script/templates/ts/as-pect.config.js
250
248
  - lib/project_types/script/templates/ts/as-pect.d.ts
251
249
  - lib/project_types/script/ui/error_handler.rb
250
+ - lib/project_types/script/ui/printing_spinner.rb
252
251
  - lib/project_types/script/ui/strict_spinner.rb
253
252
  - lib/rubygems_plugin.rb
254
253
  - lib/shopify-cli/admin_api.rb
@@ -257,6 +256,7 @@ files:
257
256
  - lib/shopify-cli/api.rb
258
257
  - lib/shopify-cli/command.rb
259
258
  - lib/shopify-cli/commands.rb
259
+ - lib/shopify-cli/commands/config.rb
260
260
  - lib/shopify-cli/commands/connect.rb
261
261
  - lib/shopify-cli/commands/create.rb
262
262
  - lib/shopify-cli/commands/help.rb
@@ -267,9 +267,11 @@ files:
267
267
  - lib/shopify-cli/core.rb
268
268
  - lib/shopify-cli/core/entry_point.rb
269
269
  - lib/shopify-cli/core/executor.rb
270
+ - lib/shopify-cli/core/finalize.rb
270
271
  - lib/shopify-cli/core/help_resolver.rb
271
272
  - lib/shopify-cli/core/monorail.rb
272
273
  - lib/shopify-cli/db.rb
274
+ - lib/shopify-cli/feature.rb
273
275
  - lib/shopify-cli/form.rb
274
276
  - lib/shopify-cli/git.rb
275
277
  - lib/shopify-cli/helpers.rb
@@ -296,6 +298,7 @@ files:
296
298
  - lib/shopify-cli/tasks/ensure_dev_store.rb
297
299
  - lib/shopify-cli/tasks/ensure_env.rb
298
300
  - lib/shopify-cli/tasks/ensure_loopback_url.rb
301
+ - lib/shopify-cli/tasks/select_org_and_shop.rb
299
302
  - lib/shopify-cli/tasks/update_dashboard_urls.rb
300
303
  - lib/shopify-cli/tunnel.rb
301
304
  - lib/shopify-cli/version.rb
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Script
4
- module Forms
5
- class Enable < ScriptForm
6
- flag_arguments :api_key, :shop_domain
7
-
8
- def ask
9
- self.api_key ||= ask_api_key
10
- self.shop_domain ||= ask_shop_domain
11
- end
12
-
13
- private
14
-
15
- def ask_api_key
16
- ask_app_api_key(organization['apps'], message: ctx.message('script.forms.enable.ask_app_api_key'))
17
- end
18
-
19
- def ask_shop_domain
20
- super(organization, message: ctx.message('script.forms.enable.ask_shop_domain'))
21
- end
22
- end
23
- end
24
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Script
4
- module Forms
5
- class Push < ScriptForm
6
- flag_arguments :api_key, :force
7
-
8
- def ask
9
- self.api_key ||= ask_api_key
10
- end
11
-
12
- private
13
-
14
- def ask_api_key
15
- ask_app_api_key(organization['apps'])
16
- end
17
- end
18
- end
19
- end