shopify-cli 1.13.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/CONTRIBUTING.md +7 -7
  4. data/.github/DESIGN.md +3 -3
  5. data/.github/workflows/build.yml +1 -1
  6. data/.gitignore +3 -0
  7. data/.rubocop.yml +3 -1
  8. data/.ruby-version +1 -1
  9. data/CHANGELOG.md +60 -26
  10. data/Gemfile +4 -0
  11. data/Gemfile.lock +32 -0
  12. data/LICENSE +4 -1
  13. data/README.md +94 -26
  14. data/RELEASING.md +31 -7
  15. data/Rakefile +2 -2
  16. data/SECURITY.md +1 -1
  17. data/THEMEKIT_MIGRATION.md +18 -0
  18. data/bin/load_shopify.rb +1 -1
  19. data/bin/shopify +3 -3
  20. data/dev.yml +1 -1
  21. data/docs/app/node/index.md +1 -1
  22. data/docs/app/rails/index.md +1 -1
  23. data/docs/core/index.md +1 -1
  24. data/docs/getting-started/index.md +1 -1
  25. data/docs/getting-started/install/index.md +1 -1
  26. data/docs/getting-started/migrate/index.md +1 -1
  27. data/docs/getting-started/uninstall/index.md +1 -1
  28. data/docs/getting-started/upgrade/index.md +1 -1
  29. data/docs/help/start-app/index.md +1 -1
  30. data/docs/index.md +1 -1
  31. data/ext/shopify-cli/extconf.rb +17 -5
  32. data/install.sh +1 -1
  33. data/lib/docgen/index_template.md.erb +2 -2
  34. data/lib/graphql/all_orgs_with_extensions.graphql +37 -0
  35. data/lib/graphql/api_versions.graphql +1 -1
  36. data/lib/graphql/find_organization.graphql +2 -1
  37. data/lib/project_types/extension/cli.rb +19 -15
  38. data/lib/project_types/extension/commands/build.rb +4 -5
  39. data/lib/project_types/extension/commands/check.rb +44 -0
  40. data/lib/project_types/extension/commands/connect.rb +35 -0
  41. data/lib/project_types/extension/commands/create.rb +12 -16
  42. data/lib/project_types/extension/commands/extension_command.rb +2 -2
  43. data/lib/project_types/extension/commands/info.rb +86 -0
  44. data/lib/project_types/extension/commands/push.rb +8 -7
  45. data/lib/project_types/extension/commands/register.rb +4 -5
  46. data/lib/project_types/extension/commands/serve.rb +5 -8
  47. data/lib/project_types/extension/commands/tunnel.rb +3 -1
  48. data/lib/project_types/extension/errors.rb +9 -0
  49. data/lib/project_types/extension/extension_project.rb +24 -1
  50. data/lib/project_types/extension/extension_project_keys.rb +1 -0
  51. data/lib/project_types/extension/features/argo.rb +6 -6
  52. data/lib/project_types/extension/features/argo_runtime.rb +22 -66
  53. data/lib/project_types/extension/features/argo_serve.rb +25 -18
  54. data/lib/project_types/extension/forms/connect.rb +42 -0
  55. data/lib/project_types/extension/forms/questions/ask_name.rb +14 -6
  56. data/lib/project_types/extension/forms/questions/ask_registration.rb +51 -0
  57. data/lib/project_types/extension/messages/messages.rb +84 -16
  58. data/lib/project_types/extension/models/specification.rb +1 -0
  59. data/lib/project_types/extension/models/specification_handlers/{checkout_argo_extension.rb → checkout_ui_extension.rb} +3 -1
  60. data/lib/project_types/extension/models/specification_handlers/default.rb +13 -3
  61. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +89 -0
  62. data/lib/project_types/extension/models/specifications.rb +1 -0
  63. data/lib/project_types/extension/tasks/configure_features.rb +6 -7
  64. data/lib/project_types/extension/tasks/configure_options.rb +20 -0
  65. data/lib/project_types/extension/tasks/get_extensions.rb +32 -0
  66. data/lib/project_types/node/cli.rb +9 -21
  67. data/lib/project_types/node/commands/connect.rb +8 -2
  68. data/lib/project_types/node/commands/create.rb +9 -5
  69. data/lib/project_types/node/commands/deploy.rb +15 -5
  70. data/lib/project_types/node/commands/deploy/heroku.rb +29 -29
  71. data/lib/project_types/node/commands/generate.rb +4 -2
  72. data/lib/project_types/node/commands/open.rb +4 -2
  73. data/lib/project_types/node/commands/serve.rb +3 -2
  74. data/lib/project_types/node/commands/tunnel.rb +4 -2
  75. data/lib/project_types/node/messages/messages.rb +47 -90
  76. data/lib/project_types/rails/cli.rb +9 -21
  77. data/lib/project_types/rails/commands/connect.rb +8 -2
  78. data/lib/project_types/rails/commands/create.rb +10 -6
  79. data/lib/project_types/rails/commands/deploy.rb +15 -5
  80. data/lib/project_types/rails/commands/deploy/heroku.rb +84 -82
  81. data/lib/project_types/rails/commands/generate.rb +15 -5
  82. data/lib/project_types/rails/commands/generate/webhook.rb +28 -26
  83. data/lib/project_types/rails/commands/open.rb +4 -2
  84. data/lib/project_types/rails/commands/serve.rb +3 -2
  85. data/lib/project_types/rails/commands/tunnel.rb +4 -2
  86. data/lib/project_types/rails/messages/messages.rb +72 -119
  87. data/lib/project_types/script/cli.rb +6 -8
  88. data/lib/project_types/script/commands/create.rb +3 -1
  89. data/lib/project_types/script/commands/push.rb +7 -4
  90. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +9 -3
  91. data/lib/project_types/script/layers/application/create_script.rb +4 -3
  92. data/lib/project_types/script/layers/domain/errors.rb +6 -11
  93. data/lib/project_types/script/layers/domain/push_package.rb +4 -8
  94. data/lib/project_types/script/layers/domain/script_json.rb +32 -0
  95. data/lib/project_types/script/layers/domain/script_project.rb +1 -1
  96. data/lib/project_types/script/layers/infrastructure/errors.rb +13 -17
  97. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +29 -21
  98. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +2 -4
  99. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +45 -34
  100. data/lib/project_types/script/layers/infrastructure/script_service.rb +37 -16
  101. data/lib/project_types/script/messages/messages.rb +64 -54
  102. data/lib/project_types/script/tasks/ensure_env.rb +3 -1
  103. data/lib/project_types/script/ui/error_handler.rb +32 -32
  104. data/lib/project_types/theme/cli.rb +16 -27
  105. data/lib/project_types/theme/commands/check.rb +33 -0
  106. data/lib/project_types/theme/commands/delete.rb +64 -0
  107. data/lib/project_types/theme/commands/init.rb +42 -0
  108. data/lib/project_types/theme/commands/language_server.rb +16 -0
  109. data/lib/project_types/theme/commands/package.rb +55 -0
  110. data/lib/project_types/theme/commands/publish.rb +43 -0
  111. data/lib/project_types/theme/commands/pull.rb +51 -0
  112. data/lib/project_types/theme/commands/push.rb +58 -32
  113. data/lib/project_types/theme/commands/serve.rb +8 -16
  114. data/lib/project_types/theme/forms/confirm_store.rb +15 -0
  115. data/lib/project_types/theme/forms/select.rb +59 -0
  116. data/lib/project_types/theme/messages/messages.rb +118 -103
  117. data/lib/project_types/theme/ui/sync_progress_bar.rb +20 -0
  118. data/lib/shopify-cli/admin_api.rb +57 -38
  119. data/lib/shopify-cli/admin_api/populate_resource_command.rb +6 -14
  120. data/lib/shopify-cli/admin_api/schema.rb +1 -10
  121. data/lib/shopify-cli/api.rb +29 -14
  122. data/lib/shopify-cli/command.rb +15 -3
  123. data/lib/shopify-cli/commands.rb +7 -2
  124. data/lib/shopify-cli/commands/help.rb +2 -29
  125. data/lib/shopify-cli/commands/login.rb +95 -0
  126. data/lib/shopify-cli/commands/logout.rb +24 -8
  127. data/lib/shopify-cli/commands/populate.rb +23 -0
  128. data/lib/{project_types/node → shopify-cli}/commands/populate/customer.rb +2 -8
  129. data/lib/{project_types/node → shopify-cli}/commands/populate/draft_order.rb +2 -2
  130. data/lib/{project_types/node → shopify-cli}/commands/populate/product.rb +2 -8
  131. data/lib/shopify-cli/commands/store.rb +15 -0
  132. data/lib/shopify-cli/commands/switch.rb +39 -0
  133. data/lib/shopify-cli/commands/system.rb +12 -0
  134. data/lib/shopify-cli/commands/whoami.rb +28 -0
  135. data/lib/shopify-cli/connect.rb +32 -0
  136. data/lib/shopify-cli/context.rb +65 -4
  137. data/lib/shopify-cli/core/entry_point.rb +3 -22
  138. data/lib/shopify-cli/core/monorail.rb +6 -2
  139. data/lib/shopify-cli/db.rb +4 -4
  140. data/lib/shopify-cli/http_request.rb +16 -0
  141. data/lib/shopify-cli/identity_auth.rb +282 -0
  142. data/lib/shopify-cli/{oauth → identity_auth}/servlet.rb +11 -12
  143. data/lib/shopify-cli/messages/messages.rb +140 -46
  144. data/lib/shopify-cli/packager.rb +5 -5
  145. data/lib/shopify-cli/partners_api.rb +21 -44
  146. data/lib/shopify-cli/partners_api/organizations.rb +8 -0
  147. data/lib/shopify-cli/project_commands.rb +16 -0
  148. data/lib/shopify-cli/project_type.rb +0 -31
  149. data/lib/shopify-cli/shopifolk.rb +8 -11
  150. data/lib/shopify-cli/sub_command.rb +1 -0
  151. data/lib/shopify-cli/tasks.rb +3 -0
  152. data/lib/shopify-cli/tasks/confirm_store.rb +18 -0
  153. data/lib/shopify-cli/tasks/create_api_client.rb +2 -2
  154. data/lib/shopify-cli/tasks/ensure_authenticated.rb +13 -0
  155. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +1 -1
  156. data/lib/shopify-cli/tasks/ensure_project_type.rb +12 -0
  157. data/lib/shopify-cli/tasks/select_org_and_shop.rb +0 -3
  158. data/lib/shopify-cli/theme/dev_server.rb +98 -0
  159. data/lib/shopify-cli/theme/dev_server/certificate_manager.rb +79 -0
  160. data/lib/shopify-cli/theme/dev_server/header_hash.rb +94 -0
  161. data/lib/shopify-cli/theme/dev_server/hot-reload.js +93 -0
  162. data/lib/shopify-cli/theme/dev_server/hot_reload.rb +76 -0
  163. data/lib/shopify-cli/theme/dev_server/local_assets.rb +87 -0
  164. data/lib/shopify-cli/theme/dev_server/proxy.rb +205 -0
  165. data/lib/shopify-cli/theme/dev_server/sse.rb +75 -0
  166. data/lib/shopify-cli/theme/dev_server/watcher.rb +59 -0
  167. data/lib/shopify-cli/theme/dev_server/web_server.rb +140 -0
  168. data/lib/shopify-cli/theme/development_theme.rb +69 -0
  169. data/lib/shopify-cli/theme/file.rb +112 -0
  170. data/lib/shopify-cli/theme/ignore_filter.rb +109 -0
  171. data/lib/shopify-cli/theme/mime_type.rb +34 -0
  172. data/lib/shopify-cli/theme/syncer.rb +332 -0
  173. data/lib/shopify-cli/theme/theme.rb +204 -0
  174. data/lib/shopify-cli/tunnel.rb +1 -1
  175. data/lib/shopify-cli/version.rb +1 -1
  176. data/lib/shopify_cli.rb +18 -11
  177. data/shopify-cli.gemspec +12 -5
  178. data/shopify.fish +1 -1
  179. data/shopify.sh +1 -1
  180. metadata +92 -35
  181. data/.github/workflows/release.yml +0 -59
  182. data/lib/project_types/extension/features/argo_serve_options.rb +0 -42
  183. data/lib/project_types/node/commands/populate.rb +0 -23
  184. data/lib/project_types/rails/commands/populate.rb +0 -23
  185. data/lib/project_types/rails/commands/populate/customer.rb +0 -31
  186. data/lib/project_types/rails/commands/populate/draft_order.rb +0 -28
  187. data/lib/project_types/rails/commands/populate/product.rb +0 -30
  188. data/lib/project_types/script/layers/domain/config_ui.rb +0 -16
  189. data/lib/project_types/theme/commands/connect.rb +0 -54
  190. data/lib/project_types/theme/commands/create.rb +0 -48
  191. data/lib/project_types/theme/commands/deploy.rb +0 -38
  192. data/lib/project_types/theme/commands/generate.rb +0 -20
  193. data/lib/project_types/theme/commands/generate/env.rb +0 -79
  194. data/lib/project_types/theme/forms/connect.rb +0 -34
  195. data/lib/project_types/theme/forms/create.rb +0 -22
  196. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +0 -78
  197. data/lib/project_types/theme/themekit.rb +0 -113
  198. data/lib/shopify-cli/commands/connect.rb +0 -64
  199. data/lib/shopify-cli/commands/create.rb +0 -50
  200. data/lib/shopify-cli/oauth.rb +0 -198
@@ -16,7 +16,7 @@ module ShopifyCli
16
16
 
17
17
  puts "\nBuilding Debian package"
18
18
 
19
- puts "Generating metadata files..."
19
+ puts "Generating metadata files"
20
20
  Dir.glob("#{debian_dir}/*").each { |file| File.delete(file) }
21
21
 
22
22
  metadata_files = %w(control preinst prerm)
@@ -28,7 +28,7 @@ module ShopifyCli
28
28
  File.open(file_path, "w", 0775) { |f| f.write(file_contents) }
29
29
  end
30
30
 
31
- puts "Building package..."
31
+ puts "Building package"
32
32
  Dir.chdir(root_dir)
33
33
  raise "Failed to build package" unless system("dpkg-deb", "-b", "shopify-cli")
34
34
 
@@ -49,14 +49,14 @@ module ShopifyCli
49
49
  spec_path = File.join(root_dir, "shopify-cli.spec")
50
50
  puts "\nBuilding RPM package"
51
51
 
52
- puts "Generating spec file..."
52
+ puts "Generating spec file"
53
53
  File.delete(spec_path) if File.exist?(spec_path)
54
54
 
55
55
  spec_contents = File.read(File.join(root_dir, "shopify-cli.spec.base"))
56
56
  spec_contents = spec_contents.gsub("SHOPIFY_CLI_VERSION", ShopifyCli::VERSION)
57
57
  File.write(spec_path, spec_contents)
58
58
 
59
- puts "Building package..."
59
+ puts "Building package"
60
60
  Dir.chdir(root_dir)
61
61
  system("rpmbuild", "-bb", File.basename(spec_path))
62
62
 
@@ -72,7 +72,7 @@ module ShopifyCli
72
72
  build_path = File.join(BUILDS_DIR, "shopify-cli.rb")
73
73
  puts "\nBuilding Homebrew package"
74
74
 
75
- puts "Generating formula..."
75
+ puts "Generating formula"
76
76
  File.delete(build_path) if File.exist?(build_path)
77
77
 
78
78
  spec_contents = File.read(File.join(root_dir, "shopify-cli.base.rb"))
@@ -45,9 +45,18 @@ module ShopifyCli
45
45
  # ShopifyCli::PartnersAPI.query(@ctx, 'all_organizations')
46
46
  #
47
47
  def query(ctx, query_name, **variables)
48
- authenticated_req(ctx) do
48
+ CLI::Kit::Util.begin do
49
49
  api_client(ctx).query(query_name, variables: variables)
50
+ end.retry_after(API::APIRequestUnauthorizedError, retries: 1) do
51
+ ShopifyCli::IdentityAuth.new(ctx: ctx).reauthenticate
50
52
  end
53
+ rescue API::APIRequestUnauthorizedError => e
54
+ if (request_info = auth_failure_info(ctx, e))
55
+ ctx.puts(ctx.message("core.api.error.failed_auth_debugging", request_info))
56
+ end
57
+ ctx.abort(ctx.message("core.api.error.failed_auth"))
58
+ rescue API::APIRequestNotFoundError
59
+ ctx.puts(ctx.message("core.partners_api.error.account_not_found", ShopifyCli::TOOL_NAME))
51
60
  end
52
61
 
53
62
  def partners_url_for(organization_id, api_client_id, local_debug)
@@ -59,18 +68,6 @@ module ShopifyCli
59
68
 
60
69
  private
61
70
 
62
- def authenticated_req(ctx, &block)
63
- CLI::Kit::Util
64
- .begin(&block)
65
- .retry_after(API::APIRequestUnauthorizedError, retries: 1) do
66
- authenticate(ctx)
67
- end
68
- rescue API::APIRequestUnauthorizedError
69
- ctx.abort(ctx.message("core.api.error.failed_auth"))
70
- rescue API::APIRequestNotFoundError
71
- ctx.puts(ctx.message("core.partners_api.error.account_not_found", ShopifyCli::TOOL_NAME))
72
- end
73
-
74
71
  def api_client(ctx)
75
72
  new(
76
73
  ctx: ctx,
@@ -80,37 +77,12 @@ module ShopifyCli
80
77
  end
81
78
 
82
79
  def access_token(ctx)
83
- ShopifyCli::DB.get(:identity_exchange_token) do
84
- authenticate(ctx)
85
- ShopifyCli::DB.get(:identity_exchange_token)
80
+ ShopifyCli::DB.get(:partners_exchange_token) do
81
+ IdentityAuth.new(ctx: ctx).authenticate
82
+ ShopifyCli::DB.get(:partners_exchange_token)
86
83
  end
87
84
  end
88
85
 
89
- def authenticate(ctx)
90
- OAuth.new(
91
- ctx: ctx,
92
- service: "identity",
93
- client_id: cli_id,
94
- scopes: scopes.join(" "),
95
- request_exchange: partners_id,
96
- ).authenticate("#{auth_endpoint}/oauth")
97
- end
98
-
99
- def partners_id
100
- return "271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6" if ENV[LOCAL_DEBUG].nil?
101
- "df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978"
102
- end
103
-
104
- def cli_id
105
- return "fbdb2649-e327-4907-8f67-908d24cfd7e3" if ENV[LOCAL_DEBUG].nil?
106
- "e5380e02-312a-7408-5718-e07017e9cf52"
107
- end
108
-
109
- def auth_endpoint
110
- return "https://accounts.shopify.com" if ENV[LOCAL_DEBUG].nil?
111
- "https://identity.myshopify.io"
112
- end
113
-
114
86
  def endpoint
115
87
  return "https://partners.shopify.com" if ENV[LOCAL_DEBUG].nil?
116
88
  "https://partners.myshopify.io/"
@@ -125,10 +97,15 @@ module ShopifyCli
125
97
  "https://#{domain}"
126
98
  end
127
99
 
128
- def scopes
129
- %w[openid https://api.shopify.com/auth/partners.app.cli.access].tap do |result|
130
- result << "employee" if ShopifyCli::Shopifolk.acting_as_shopify_organization?
100
+ def auth_failure_info(ctx, error)
101
+ if error.response
102
+ headers = %w(www-authenticate x-request-id)
103
+ request_info = headers.map { |h| "#{h}: #{error.response[h]}" if error.response.key?(h) }.join("\n")
104
+ ctx.debug("Full headers: #{error.response.each_header.to_h}")
105
+ request_info
131
106
  end
107
+ rescue => e
108
+ ctx.debug("Couldn't fetch auth failure information from #{error}: #{e}")
132
109
  end
133
110
  end
134
111
 
@@ -26,6 +26,14 @@ module ShopifyCli
26
26
  org
27
27
  end
28
28
  end
29
+
30
+ def fetch_with_extensions(ctx, type)
31
+ resp = PartnersAPI.query(ctx, "all_orgs_with_extensions", type: type)
32
+ (resp&.dig("data", "organizations", "nodes") || []).map do |org|
33
+ org["apps"] = (org.dig("apps", "nodes") || [])
34
+ org
35
+ end
36
+ end
29
37
  end
30
38
  end
31
39
  end
@@ -0,0 +1,16 @@
1
+ module ShopifyCli
2
+ class ProjectCommands < Command
3
+ def call(*)
4
+ @ctx.puts(self.class.help)
5
+ end
6
+
7
+ def self.help
8
+ project_type = name.split("::")[0].downcase
9
+ ShopifyCli::Context.message(
10
+ "#{project_type}.help",
11
+ ShopifyCli::TOOL_NAME,
12
+ subcommand_registry.command_names.join(" | ")
13
+ )
14
+ end
15
+ end
16
+ end
@@ -5,7 +5,6 @@ module ShopifyCli
5
5
  class << self
6
6
  attr_accessor :project_type,
7
7
  :project_name,
8
- :project_creator_command_class,
9
8
  :project_load_shallow
10
9
 
11
10
  def repository
@@ -49,36 +48,6 @@ module ShopifyCli
49
48
  @project_name = name
50
49
  end
51
50
 
52
- def creator(command_const)
53
- @project_creator_command_class = command_const
54
- ShopifyCli::Commands::Create.subcommand(command_const, @project_type)
55
- end
56
-
57
- def create_command
58
- const_get(@project_creator_command_class)
59
- end
60
-
61
- def connector(command_const)
62
- @project_connector_command_class = command_const
63
- ShopifyCli::Commands::Connect.subcommand(command_const, @project_type)
64
- end
65
-
66
- def connect_command
67
- if @project_connector_command_class.nil?
68
- nil
69
- else
70
- const_get(@project_connector_command_class)
71
- end
72
- end
73
-
74
- def register_command(const, cmd)
75
- return if project_load_shallow
76
- Context.new.abort(
77
- Context.message("core.project_type.error.cannot_override_core", cmd, const)
78
- ) if Commands.core_command?(cmd)
79
- Commands.register(const, cmd)
80
- end
81
-
82
51
  def register_task(task, name)
83
52
  return if project_load_shallow
84
53
  ShopifyCli::Tasks.register(task, name)
@@ -11,8 +11,6 @@ module ShopifyCli
11
11
  FEATURE_NAME = "shopifolk"
12
12
 
13
13
  class << self
14
- attr_writer :acting_as_shopify_organization
15
-
16
14
  ##
17
15
  # will return if the user appears to be a Shopify employee, based on several heuristics
18
16
  #
@@ -29,15 +27,16 @@ module ShopifyCli
29
27
  end
30
28
 
31
29
  def act_as_shopify_organization
32
- @acting_as_shopify_organization = true
30
+ DB.set(acting_as_shopify_organization: true)
33
31
  end
34
32
 
35
33
  def acting_as_shopify_organization?
36
- !!(@acting_as_shopify_organization || (Project.has_current? && Project.current.config["shopify_organization"]))
34
+ !!(DB.get(:acting_as_shopify_organization) ||
35
+ (Project.has_current? && Project.current.config["shopify_organization"]))
37
36
  end
38
37
 
39
38
  def reset
40
- @acting_as_shopify_organization = nil
39
+ DB.del(:acting_as_shopify_organization)
41
40
  end
42
41
  end
43
42
 
@@ -72,12 +71,10 @@ module ShopifyCli
72
71
  end
73
72
 
74
73
  def ini
75
- @ini ||= begin
76
- if File.exist?(GCLOUD_CONFIG_FILE)
77
- CLI::Kit::Ini
78
- .new(GCLOUD_CONFIG_FILE, default_section: "[#{SECTION}]", convert_types: false)
79
- .tap(&:parse).ini
80
- end
74
+ @ini ||= if File.exist?(GCLOUD_CONFIG_FILE)
75
+ CLI::Kit::Ini
76
+ .new(GCLOUD_CONFIG_FILE, default_section: "[#{SECTION}]", convert_types: false)
77
+ .tap(&:parse).ini
81
78
  end
82
79
  end
83
80
  end
@@ -9,6 +9,7 @@ module ShopifyCli
9
9
  args = cmd.options.parse(@_options, args[1..-1] || [])
10
10
  return call_help(parent_command, command_name) if cmd.options.help
11
11
  run_prerequisites
12
+
12
13
  cmd.call(args, command_name)
13
14
  end
14
15
  end
@@ -30,9 +30,12 @@ module ShopifyCli
30
30
  Registry.add(-> () { const_get(task) }, name)
31
31
  end
32
32
 
33
+ register :ConfirmStore, :confirm_store, "shopify-cli/tasks/confirm_store"
33
34
  register :CreateApiClient, :create_api_client, "shopify-cli/tasks/create_api_client"
35
+ register :EnsureAuthenticated, :ensure_authenticated, "shopify-cli/tasks/ensure_authenticated"
34
36
  register :EnsureEnv, :ensure_env, "shopify-cli/tasks/ensure_env"
35
37
  register :EnsureLoopbackURL, :ensure_loopback_url, "shopify-cli/tasks/ensure_loopback_url"
38
+ register :EnsureProjectType, :ensure_project_type, "shopify-cli/tasks/ensure_project_type"
36
39
  register :EnsureDevStore, :ensure_dev_store, "shopify-cli/tasks/ensure_dev_store"
37
40
  register :SelectOrgAndShop, :select_org_and_shop, "shopify-cli/tasks/select_org_and_shop"
38
41
  register :UpdateDashboardURLS, :update_dashboard_urls, "shopify-cli/tasks/update_dashboard_urls"
@@ -0,0 +1,18 @@
1
+ require "shopify_cli"
2
+
3
+ module ShopifyCli
4
+ module Tasks
5
+ class ConfirmStore < ShopifyCli::Task
6
+ def call(ctx)
7
+ @ctx = ctx
8
+ store = ShopifyCli::AdminAPI.get_shop_or_abort(ctx)
9
+ if CLI::UI::Prompt.confirm(ctx.message("core.tasks.confirm_store.prompt", store), default: false)
10
+ ctx.puts(ctx.message("core.tasks.confirm_store.confirmation", store))
11
+ else
12
+ ctx.puts(ctx.message("core.tasks.confirm_store.cancelling"))
13
+ raise AbortSilent
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -4,7 +4,7 @@ module ShopifyCli
4
4
  module Tasks
5
5
  class CreateApiClient < ShopifyCli::Task
6
6
  VALID_APP_TYPES = %w(public custom)
7
- DEFAULT_APP_URL = "https://shopify.github.io/shopify-app-cli/help/start-app/"
7
+ DEFAULT_APP_URL = "https://shopify.github.io/shopify-cli/help/start-app/"
8
8
 
9
9
  def call(ctx, org_id:, title:, type:)
10
10
  resp = ShopifyCli::PartnersAPI.query(
@@ -14,7 +14,7 @@ module ShopifyCli
14
14
  title: title,
15
15
  type: type,
16
16
  app_url: DEFAULT_APP_URL,
17
- redir: [OAuth::REDIRECT_HOST]
17
+ redir: [IdentityAuth::REDIRECT_HOST]
18
18
  )
19
19
 
20
20
  unless resp
@@ -0,0 +1,13 @@
1
+ require "shopify_cli"
2
+
3
+ module ShopifyCli
4
+ module Tasks
5
+ class EnsureAuthenticated < ShopifyCli::Task
6
+ def call(ctx)
7
+ ctx.abort(
8
+ ctx.message("core.identity_auth.login_prompt", ShopifyCli::TOOL_NAME)
9
+ ) unless ShopifyCli::IdentityAuth::IDENTITY_ACCESS_TOKENS.all? { |key| ShopifyCli::DB.exists?(key) }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -5,7 +5,7 @@ module ShopifyCli
5
5
  @ctx = ctx
6
6
  api_key = Project.current.env.api_key
7
7
  result = ShopifyCli::PartnersAPI.query(ctx, "get_app_urls", apiKey: api_key)
8
- loopback = OAuth::REDIRECT_HOST
8
+ loopback = IdentityAuth::REDIRECT_HOST
9
9
  app = result["data"]["app"]
10
10
  urls = app["redirectUrlWhitelist"]
11
11
  if urls.grep(/#{loopback}/).empty?
@@ -0,0 +1,12 @@
1
+ require "shopify_cli"
2
+
3
+ module ShopifyCli
4
+ module Tasks
5
+ class EnsureProjectType < ShopifyCli::Task
6
+ def call(ctx, project_type)
7
+ return true if project_type.to_sym == ShopifyCli::Project.current_project_type
8
+ ctx.abort(ctx.message("core.tasks.ensure_project_type.wrong_project_type", project_type))
9
+ end
10
+ end
11
+ end
12
+ end
@@ -8,9 +8,6 @@ module ShopifyCli
8
8
  def call(ctx, organization_id: nil, shop_domain: nil)
9
9
  @ctx = ctx
10
10
  return response(organization_id.to_i, shop_domain) unless organization_id.nil? || shop_domain.nil?
11
- if Shopifolk.check && wants_to_run_against_shopify_org?
12
- Shopifolk.act_as_shopify_organization
13
- end
14
11
  org = get_organization(organization_id)
15
12
  unless Shopifolk.acting_as_shopify_organization?
16
13
  shop_domain ||= get_shop_domain(org)
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+ require_relative "development_theme"
3
+ require_relative "ignore_filter"
4
+ require_relative "syncer"
5
+
6
+ require_relative "dev_server/hot_reload"
7
+ require_relative "dev_server/header_hash"
8
+ require_relative "dev_server/local_assets"
9
+ require_relative "dev_server/proxy"
10
+ require_relative "dev_server/sse"
11
+ require_relative "dev_server/watcher"
12
+ require_relative "dev_server/web_server"
13
+ require_relative "dev_server/certificate_manager"
14
+
15
+ require "pathname"
16
+
17
+ module ShopifyCli
18
+ module Theme
19
+ module DevServer
20
+ class << self
21
+ attr_accessor :ctx
22
+
23
+ def start(ctx, root, port: 9292)
24
+ @ctx = ctx
25
+ theme = DevelopmentTheme.new(ctx, root: root)
26
+ ignore_filter = IgnoreFilter.from_path(root)
27
+ @syncer = Syncer.new(ctx, theme: theme, ignore_filter: ignore_filter)
28
+ watcher = Watcher.new(ctx, theme: theme, syncer: @syncer, ignore_filter: ignore_filter)
29
+
30
+ # Setup the middleware stack. Mimics Rack::Builder / config.ru, but in reverse order
31
+ @app = Proxy.new(ctx, theme: theme, syncer: @syncer)
32
+ @app = LocalAssets.new(ctx, @app, theme: theme)
33
+ @app = HotReload.new(ctx, @app, theme: theme, watcher: watcher, ignore_filter: ignore_filter)
34
+ stopped = false
35
+
36
+ theme.ensure_exists!
37
+
38
+ trap("INT") do
39
+ stopped = true
40
+ stop
41
+ end
42
+
43
+ CLI::UI::Frame.open(@ctx.message("theme.serve.serve")) do
44
+ ctx.print_task("Syncing theme ##{theme.id} on #{theme.shop}")
45
+ @syncer.start_threads
46
+ if block_given?
47
+ yield @syncer
48
+ else
49
+ @syncer.upload_theme!(delay_low_priority_files: true)
50
+ end
51
+
52
+ return if stopped
53
+
54
+ ctx.puts("")
55
+ ctx.puts("Serving #{theme.root}")
56
+ ctx.puts("")
57
+ ctx.open_url!("http://127.0.0.1:#{port}")
58
+ ctx.puts("")
59
+ ctx.puts("Customize this theme in the Online Store Editor:")
60
+ ctx.puts("{{green:#{theme.editor_url}}}")
61
+ ctx.puts("")
62
+ ctx.puts("Share this theme preview:")
63
+ ctx.puts("{{green:#{theme.preview_url}}}")
64
+ ctx.puts("")
65
+ ctx.puts("(Use Ctrl-C to stop)")
66
+ end
67
+
68
+ logger = if ctx.debug?
69
+ WEBrick::Log.new(nil, WEBrick::BasicLog::INFO)
70
+ else
71
+ WEBrick::Log.new(nil, WEBrick::BasicLog::FATAL)
72
+ end
73
+
74
+ watcher.start
75
+ WebServer.run(
76
+ @app,
77
+ Port: port,
78
+ Logger: logger,
79
+ AccessLog: [],
80
+ )
81
+ watcher.stop
82
+
83
+ rescue ShopifyCli::API::APIRequestForbiddenError,
84
+ ShopifyCli::API::APIRequestUnauthorizedError
85
+ @ctx.abort("You are not authorized to edit themes on #{theme.shop}.\n" \
86
+ "Make sure you are a user of that store, and allowed to edit themes.")
87
+ end
88
+
89
+ def stop
90
+ @ctx.puts("Stopping…")
91
+ @app.close
92
+ @syncer.shutdown
93
+ WebServer.shutdown
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end