shopify-cli 1.13.1 → 2.1.0

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 (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