shopify-cli 1.14.0 → 2.0.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 (179) 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 +35 -29
  10. data/Gemfile +4 -0
  11. data/Gemfile.lock +32 -0
  12. data/LICENSE +4 -1
  13. data/README.md +92 -26
  14. data/RELEASING.md +29 -7
  15. data/Rakefile +2 -2
  16. data/SECURITY.md +1 -1
  17. data/bin/load_shopify.rb +1 -1
  18. data/bin/shopify +3 -3
  19. data/dev.yml +1 -1
  20. data/docs/app/node/index.md +1 -1
  21. data/docs/app/rails/index.md +1 -1
  22. data/docs/core/index.md +1 -1
  23. data/docs/getting-started/index.md +1 -1
  24. data/docs/getting-started/install/index.md +1 -1
  25. data/docs/getting-started/migrate/index.md +1 -1
  26. data/docs/getting-started/uninstall/index.md +1 -1
  27. data/docs/getting-started/upgrade/index.md +1 -1
  28. data/docs/help/start-app/index.md +1 -1
  29. data/docs/index.md +1 -1
  30. data/ext/shopify-cli/extconf.rb +17 -5
  31. data/install.sh +1 -1
  32. data/lib/docgen/index_template.md.erb +2 -2
  33. data/lib/graphql/all_orgs_with_extensions.graphql +37 -0
  34. data/lib/graphql/find_organization.graphql +2 -1
  35. data/lib/project_types/extension/cli.rb +18 -15
  36. data/lib/project_types/extension/commands/build.rb +4 -5
  37. data/lib/project_types/extension/commands/connect.rb +35 -0
  38. data/lib/project_types/extension/commands/create.rb +12 -16
  39. data/lib/project_types/extension/commands/extension_command.rb +2 -2
  40. data/lib/project_types/extension/commands/info.rb +86 -0
  41. data/lib/project_types/extension/commands/push.rb +8 -7
  42. data/lib/project_types/extension/commands/register.rb +4 -5
  43. data/lib/project_types/extension/commands/serve.rb +5 -8
  44. data/lib/project_types/extension/commands/tunnel.rb +3 -1
  45. data/lib/project_types/extension/errors.rb +9 -0
  46. data/lib/project_types/extension/extension_project.rb +5 -0
  47. data/lib/project_types/extension/features/argo.rb +6 -6
  48. data/lib/project_types/extension/features/argo_runtime.rb +22 -66
  49. data/lib/project_types/extension/features/argo_serve.rb +25 -18
  50. data/lib/project_types/extension/forms/connect.rb +42 -0
  51. data/lib/project_types/extension/forms/questions/ask_name.rb +14 -6
  52. data/lib/project_types/extension/forms/questions/ask_registration.rb +51 -0
  53. data/lib/project_types/extension/messages/messages.rb +75 -11
  54. data/lib/project_types/extension/models/specification.rb +1 -0
  55. data/lib/project_types/extension/models/specification_handlers/{checkout_argo_extension.rb → checkout_ui_extension.rb} +3 -1
  56. data/lib/project_types/extension/models/specification_handlers/default.rb +13 -3
  57. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +86 -0
  58. data/lib/project_types/extension/models/specifications.rb +1 -0
  59. data/lib/project_types/extension/tasks/configure_features.rb +6 -7
  60. data/lib/project_types/extension/tasks/configure_options.rb +20 -0
  61. data/lib/project_types/extension/tasks/get_extensions.rb +32 -0
  62. data/lib/project_types/node/cli.rb +9 -21
  63. data/lib/project_types/node/commands/connect.rb +8 -2
  64. data/lib/project_types/node/commands/create.rb +9 -5
  65. data/lib/project_types/node/commands/deploy.rb +15 -5
  66. data/lib/project_types/node/commands/deploy/heroku.rb +29 -29
  67. data/lib/project_types/node/commands/generate.rb +4 -2
  68. data/lib/project_types/node/commands/open.rb +4 -2
  69. data/lib/project_types/node/commands/serve.rb +3 -2
  70. data/lib/project_types/node/commands/tunnel.rb +4 -2
  71. data/lib/project_types/node/messages/messages.rb +46 -89
  72. data/lib/project_types/rails/cli.rb +9 -21
  73. data/lib/project_types/rails/commands/connect.rb +8 -2
  74. data/lib/project_types/rails/commands/create.rb +10 -6
  75. data/lib/project_types/rails/commands/deploy.rb +15 -5
  76. data/lib/project_types/rails/commands/deploy/heroku.rb +84 -82
  77. data/lib/project_types/rails/commands/generate.rb +15 -5
  78. data/lib/project_types/rails/commands/generate/webhook.rb +28 -26
  79. data/lib/project_types/rails/commands/open.rb +4 -2
  80. data/lib/project_types/rails/commands/serve.rb +3 -2
  81. data/lib/project_types/rails/commands/tunnel.rb +4 -2
  82. data/lib/project_types/rails/messages/messages.rb +54 -101
  83. data/lib/project_types/script/cli.rb +5 -7
  84. data/lib/project_types/script/commands/create.rb +3 -1
  85. data/lib/project_types/script/commands/push.rb +4 -2
  86. data/lib/project_types/script/messages/messages.rb +52 -45
  87. data/lib/project_types/script/ui/error_handler.rb +2 -2
  88. data/lib/project_types/theme/cli.rb +15 -27
  89. data/lib/project_types/theme/commands/check.rb +33 -0
  90. data/lib/project_types/theme/commands/delete.rb +64 -0
  91. data/lib/project_types/theme/commands/language_server.rb +16 -0
  92. data/lib/project_types/theme/commands/package.rb +55 -0
  93. data/lib/project_types/theme/commands/publish.rb +43 -0
  94. data/lib/project_types/theme/commands/pull.rb +51 -0
  95. data/lib/project_types/theme/commands/push.rb +58 -32
  96. data/lib/project_types/theme/commands/serve.rb +7 -17
  97. data/lib/project_types/theme/forms/confirm_store.rb +15 -0
  98. data/lib/project_types/theme/forms/select.rb +59 -0
  99. data/lib/project_types/theme/messages/messages.rb +110 -106
  100. data/lib/project_types/theme/ui/sync_progress_bar.rb +20 -0
  101. data/lib/shopify-cli/admin_api.rb +53 -38
  102. data/lib/shopify-cli/admin_api/populate_resource_command.rb +6 -14
  103. data/lib/shopify-cli/admin_api/schema.rb +1 -10
  104. data/lib/shopify-cli/api.rb +29 -14
  105. data/lib/shopify-cli/command.rb +15 -3
  106. data/lib/shopify-cli/commands.rb +7 -2
  107. data/lib/shopify-cli/commands/help.rb +2 -29
  108. data/lib/shopify-cli/commands/login.rb +95 -0
  109. data/lib/shopify-cli/commands/logout.rb +24 -8
  110. data/lib/shopify-cli/commands/populate.rb +23 -0
  111. data/lib/{project_types/node → shopify-cli}/commands/populate/customer.rb +2 -8
  112. data/lib/{project_types/node → shopify-cli}/commands/populate/draft_order.rb +2 -2
  113. data/lib/{project_types/node → shopify-cli}/commands/populate/product.rb +2 -8
  114. data/lib/shopify-cli/commands/store.rb +15 -0
  115. data/lib/shopify-cli/commands/switch.rb +39 -0
  116. data/lib/shopify-cli/commands/system.rb +12 -0
  117. data/lib/shopify-cli/commands/whoami.rb +28 -0
  118. data/lib/shopify-cli/connect.rb +32 -0
  119. data/lib/shopify-cli/context.rb +52 -4
  120. data/lib/shopify-cli/core/entry_point.rb +3 -22
  121. data/lib/shopify-cli/db.rb +4 -4
  122. data/lib/shopify-cli/http_request.rb +10 -0
  123. data/lib/shopify-cli/identity_auth.rb +282 -0
  124. data/lib/shopify-cli/{oauth → identity_auth}/servlet.rb +11 -12
  125. data/lib/shopify-cli/messages/messages.rb +132 -39
  126. data/lib/shopify-cli/partners_api.rb +21 -44
  127. data/lib/shopify-cli/partners_api/organizations.rb +8 -0
  128. data/lib/shopify-cli/project_commands.rb +16 -0
  129. data/lib/shopify-cli/project_type.rb +0 -31
  130. data/lib/shopify-cli/shopifolk.rb +8 -11
  131. data/lib/shopify-cli/sub_command.rb +1 -0
  132. data/lib/shopify-cli/tasks.rb +3 -0
  133. data/lib/shopify-cli/tasks/confirm_store.rb +18 -0
  134. data/lib/shopify-cli/tasks/create_api_client.rb +2 -2
  135. data/lib/shopify-cli/tasks/ensure_authenticated.rb +13 -0
  136. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +1 -1
  137. data/lib/shopify-cli/tasks/ensure_project_type.rb +12 -0
  138. data/lib/shopify-cli/tasks/select_org_and_shop.rb +0 -3
  139. data/lib/shopify-cli/theme/dev_server.rb +98 -0
  140. data/lib/shopify-cli/theme/dev_server/certificate_manager.rb +79 -0
  141. data/lib/shopify-cli/theme/dev_server/header_hash.rb +94 -0
  142. data/lib/shopify-cli/theme/dev_server/hot-reload.js +93 -0
  143. data/lib/shopify-cli/theme/dev_server/hot_reload.rb +76 -0
  144. data/lib/shopify-cli/theme/dev_server/local_assets.rb +87 -0
  145. data/lib/shopify-cli/theme/dev_server/proxy.rb +205 -0
  146. data/lib/shopify-cli/theme/dev_server/sse.rb +75 -0
  147. data/lib/shopify-cli/theme/dev_server/watcher.rb +59 -0
  148. data/lib/shopify-cli/theme/dev_server/web_server.rb +140 -0
  149. data/lib/shopify-cli/theme/development_theme.rb +69 -0
  150. data/lib/shopify-cli/theme/file.rb +112 -0
  151. data/lib/shopify-cli/theme/ignore_filter.rb +109 -0
  152. data/lib/shopify-cli/theme/mime_type.rb +34 -0
  153. data/lib/shopify-cli/theme/syncer.rb +328 -0
  154. data/lib/shopify-cli/theme/theme.rb +204 -0
  155. data/lib/shopify-cli/version.rb +1 -1
  156. data/lib/shopify_cli.rb +18 -11
  157. data/shopify-cli.gemspec +12 -5
  158. data/shopify.fish +1 -1
  159. data/shopify.sh +1 -1
  160. metadata +88 -34
  161. data/.github/workflows/release.yml +0 -59
  162. data/lib/project_types/extension/features/argo_serve_options.rb +0 -42
  163. data/lib/project_types/node/commands/populate.rb +0 -23
  164. data/lib/project_types/rails/commands/populate.rb +0 -23
  165. data/lib/project_types/rails/commands/populate/customer.rb +0 -31
  166. data/lib/project_types/rails/commands/populate/draft_order.rb +0 -28
  167. data/lib/project_types/rails/commands/populate/product.rb +0 -30
  168. data/lib/project_types/theme/commands/connect.rb +0 -54
  169. data/lib/project_types/theme/commands/create.rb +0 -48
  170. data/lib/project_types/theme/commands/deploy.rb +0 -38
  171. data/lib/project_types/theme/commands/generate.rb +0 -20
  172. data/lib/project_types/theme/commands/generate/env.rb +0 -79
  173. data/lib/project_types/theme/forms/connect.rb +0 -34
  174. data/lib/project_types/theme/forms/create.rb +0 -22
  175. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +0 -78
  176. data/lib/project_types/theme/themekit.rb +0 -113
  177. data/lib/shopify-cli/commands/connect.rb +0 -64
  178. data/lib/shopify-cli/commands/create.rb +0 -50
  179. data/lib/shopify-cli/oauth.rb +0 -198
@@ -34,7 +34,7 @@ module Script
34
34
  cause_of_error: ShopifyCli::Context.message("script.error.enospc_cause"),
35
35
  help_suggestion: ShopifyCli::Context.message("script.error.enospc_help"),
36
36
  }
37
- when ShopifyCli::OAuth::Error
37
+ when ShopifyCli::IdentityAuth::Error
38
38
  {
39
39
  cause_of_error: ShopifyCli::Context.message("script.error.oauth_cause"),
40
40
  help_suggestion: ShopifyCli::Context.message("script.error.oauth_help"),
@@ -214,7 +214,7 @@ module Script
214
214
  }
215
215
  when Layers::Infrastructure::Errors::ScriptRepushError
216
216
  {
217
- cause_of_error: ShopifyCli::Context.message("script.error.script_repush_cause", e.uuid),
217
+ cause_of_error: ShopifyCli::Context.message("script.error.script_repush_cause"),
218
218
  help_suggestion: ShopifyCli::Context.message("script.error.script_repush_help"),
219
219
  }
220
220
  when Layers::Infrastructure::Errors::ShopAuthenticationError
@@ -1,40 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
  module Theme
3
3
  class Project < ShopifyCli::ProjectType
4
- hidden_feature
5
-
6
- title("Theme")
7
- creator("Theme::Commands::Create")
8
- connector("Theme::Commands::Connect")
9
-
10
- register_command("Theme::Commands::Deploy", "deploy")
11
- register_command("Theme::Commands::Generate", "generate")
12
- register_command("Theme::Commands::Push", "push")
13
- register_command("Theme::Commands::Serve", "serve")
14
-
15
- register_task("Theme::Tasks::EnsureThemekitInstalled", :ensure_themekit_installed)
16
-
17
4
  require Project.project_filepath("messages/messages")
18
5
  register_messages(Theme::Messages::MESSAGES)
19
6
  end
20
7
 
21
- module Commands
22
- autoload :Connect, Project.project_filepath("commands/connect")
23
- autoload :Create, Project.project_filepath("commands/create")
24
- autoload :Deploy, Project.project_filepath("commands/deploy")
25
- autoload :Generate, Project.project_filepath("commands/generate")
26
- autoload :Push, Project.project_filepath("commands/push")
27
- autoload :Serve, Project.project_filepath("commands/serve")
28
- end
29
-
30
- module Tasks
31
- autoload :EnsureThemekitInstalled, Project.project_filepath("tasks/ensure_themekit_installed")
8
+ class Command < ShopifyCli::ProjectCommands
9
+ subcommand :Serve, "serve", Project.project_filepath("commands/serve")
10
+ subcommand :Pull, "pull", Project.project_filepath("commands/pull")
11
+ subcommand :Push, "push", Project.project_filepath("commands/push")
12
+ subcommand :Delete, "delete", Project.project_filepath("commands/delete")
13
+ subcommand :Check, "check", Project.project_filepath("commands/check")
14
+ subcommand :Publish, "publish", Project.project_filepath("commands/publish")
15
+ subcommand :Package, "package", Project.project_filepath("commands/package")
16
+ subcommand :LanguageServer, "language-server", Project.project_filepath("commands/language_server")
32
17
  end
18
+ ShopifyCli::Commands.register("Theme::Command", "theme")
33
19
 
34
20
  module Forms
35
- autoload :Create, Project.project_filepath("forms/create")
36
- autoload :Connect, Project.project_filepath("forms/connect")
21
+ autoload :ConfirmStore, Project.project_filepath("forms/confirm_store")
22
+ autoload :Select, Project.project_filepath("forms/select")
37
23
  end
38
24
 
39
- autoload :Themekit, Project.project_filepath("themekit")
25
+ module UI
26
+ autoload :SyncProgressBar, Project.project_filepath("ui/sync_progress_bar")
27
+ end
40
28
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ require "theme_check"
3
+
4
+ module Theme
5
+ class Command
6
+ class Check < ShopifyCli::SubCommand
7
+ class Options < ShopifyCli::Options
8
+ def initialize(theme_check)
9
+ super()
10
+ @theme_check = theme_check
11
+ end
12
+
13
+ def parse(_options_block, args)
14
+ @theme_check.parse(args)
15
+ end
16
+ end
17
+
18
+ def initialize(*)
19
+ super
20
+ @theme_check = ThemeCheck::Cli.new
21
+ self.options = Options.new(@theme_check)
22
+ end
23
+
24
+ def call(*)
25
+ @theme_check.run
26
+ end
27
+
28
+ def self.help
29
+ ShopifyCli::Context.message("theme.check.help", ShopifyCli::TOOL_NAME)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+ require "shopify-cli/theme/theme"
3
+ require "shopify-cli/theme/development_theme"
4
+
5
+ module Theme
6
+ class Command
7
+ class Delete < ShopifyCli::SubCommand
8
+ options do |parser, flags|
9
+ parser.on("-d", "--development") { flags[:development] = true }
10
+ parser.on("-a", "--show-all") { flags[:show_all] = true }
11
+ parser.on("-f", "--force") { flags[:force] = true }
12
+ end
13
+
14
+ def call(args, _name)
15
+ themes = if options.flags[:development]
16
+ [ShopifyCli::Theme::DevelopmentTheme.new(@ctx)]
17
+ elsif args.any?
18
+ args.map { |id| ShopifyCli::Theme::Theme.new(@ctx, id: id) }
19
+ else
20
+ form = Forms::Select.ask(
21
+ @ctx,
22
+ [],
23
+ title: @ctx.message("theme.delete.select"),
24
+ exclude_roles: ["live"],
25
+ include_foreign_developments: options.flags[:show_all],
26
+ )
27
+ return unless form
28
+ [form.theme]
29
+ end
30
+
31
+ deleted = 0
32
+ themes.each do |theme|
33
+ if theme.live?
34
+ @ctx.puts(@ctx.message("theme.delete.live", theme.id))
35
+ next
36
+ elsif !confirm?(theme)
37
+ next
38
+ end
39
+ theme.delete
40
+ deleted += 1
41
+ rescue ShopifyCli::API::APIRequestNotFoundError
42
+ @ctx.puts(@ctx.message("theme.delete.not_found", theme.id))
43
+ end
44
+
45
+ @ctx.done(@ctx.message("theme.delete.done", deleted))
46
+ end
47
+
48
+ def self.help
49
+ ShopifyCli::Context.message("theme.delete.help", ShopifyCli::TOOL_NAME, ShopifyCli::TOOL_NAME)
50
+ end
51
+
52
+ private
53
+
54
+ def confirm?(theme)
55
+ Forms::ConfirmStore.ask(
56
+ @ctx,
57
+ [],
58
+ title: @ctx.message("theme.delete.confirm", theme.name, theme.shop),
59
+ force: options.flags[:force],
60
+ ).confirmed?
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ require "theme_check"
3
+
4
+ module Theme
5
+ class Command
6
+ class LanguageServer < ShopifyCli::SubCommand
7
+ def call(*)
8
+ ThemeCheck::LanguageServer.start
9
+ end
10
+
11
+ def self.help
12
+ ShopifyCli::Context.message("theme.language_server.help", ShopifyCli::TOOL_NAME)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ require "pathname"
3
+ require "json"
4
+
5
+ module Theme
6
+ class Command
7
+ class Package < ShopifyCli::SubCommand
8
+ THEME_DIRECTORIES = %w[
9
+ assets
10
+ config
11
+ layout
12
+ locales
13
+ sections
14
+ snippets
15
+ templates
16
+ ]
17
+
18
+ def call(args, _name)
19
+ path = args.first || "."
20
+
21
+ check_prereq_command("zip")
22
+ zip_name = theme_name(path) + ".zip"
23
+ zip(zip_name, path, THEME_DIRECTORIES)
24
+ @ctx.done(@ctx.message("theme.package.done", zip_name))
25
+ end
26
+
27
+ def self.help
28
+ ShopifyCli::Context.message("theme.package.help", ShopifyCli::TOOL_NAME, ShopifyCli::TOOL_NAME)
29
+ end
30
+
31
+ private
32
+
33
+ def check_prereq_command(command)
34
+ cmd_path = @ctx.which(command)
35
+ @ctx.abort(@ctx.message("theme.package.error.prereq_command_required", command)) if cmd_path.nil?
36
+ end
37
+
38
+ def zip(zip_name, path, files)
39
+ @ctx.system("zip", "-r", zip_name, *files, chdir: path)
40
+ end
41
+
42
+ def theme_name(path)
43
+ settings_schema = Pathname.new(path).join("config/settings_schema.json")
44
+ @ctx.abort(@ctx.message("theme.package.error.missing_config")) unless settings_schema.file?
45
+
46
+ content = settings_schema.read
47
+ theme_info = JSON.parse(content).find { |section| section["name"] == "theme_info" }
48
+ theme_name = theme_info&.dig("theme_name")
49
+ @ctx.abort(@ctx.message("theme.package.error.missing_theme_name")) unless theme_name
50
+
51
+ [theme_name, theme_info["theme_version"]].compact.join("-")
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ require "shopify-cli/theme/theme"
3
+
4
+ module Theme
5
+ class Command
6
+ class Publish < ShopifyCli::SubCommand
7
+ options do |parser, flags|
8
+ parser.on("-f", "--force") { flags[:force] = true }
9
+ end
10
+
11
+ def call(args, *)
12
+ theme = if (theme_id = args.first)
13
+ ShopifyCli::Theme::Theme.new(@ctx, id: theme_id)
14
+ else
15
+ form = Forms::Select.ask(
16
+ @ctx,
17
+ [],
18
+ title: @ctx.message("theme.publish.select"),
19
+ exclude_roles: ["live", "development", "demo"],
20
+ )
21
+ return unless form
22
+ form.theme
23
+ end
24
+
25
+ return unless Forms::ConfirmStore.ask(
26
+ @ctx,
27
+ [],
28
+ title: @ctx.message("theme.publish.confirm", theme.name, theme.shop),
29
+ force: options.flags[:force],
30
+ ).confirmed?
31
+
32
+ theme.publish
33
+ @ctx.done(@ctx.message("theme.publish.done", theme.preview_url))
34
+ rescue ShopifyCli::API::APIRequestNotFoundError
35
+ @ctx.puts(@ctx.message("theme.publish.not_found", theme.id))
36
+ end
37
+
38
+ def self.help
39
+ ShopifyCli::Context.message("theme.publish.help", ShopifyCli::TOOL_NAME, ShopifyCli::TOOL_NAME)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ require "shopify-cli/theme/theme"
3
+ require "shopify-cli/theme/ignore_filter"
4
+ require "shopify-cli/theme/syncer"
5
+
6
+ module Theme
7
+ class Command
8
+ class Pull < ShopifyCli::SubCommand
9
+ options do |parser, flags|
10
+ parser.on("-n", "--nodelete") { flags[:nodelete] = true }
11
+ parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
12
+ end
13
+
14
+ def call(args, _name)
15
+ root = args.first || "."
16
+ delete = !options.flags[:nodelete]
17
+
18
+ theme = if (theme_id = options.flags[:theme_id])
19
+ ShopifyCli::Theme::Theme.new(@ctx, root: root, id: theme_id)
20
+ else
21
+ form = Forms::Select.ask(
22
+ @ctx,
23
+ [],
24
+ title: @ctx.message("theme.pull.select"),
25
+ root: root,
26
+ )
27
+ return unless form
28
+ form.theme
29
+ end
30
+
31
+ ignore_filter = ShopifyCli::Theme::IgnoreFilter.from_path(root)
32
+ syncer = ShopifyCli::Theme::Syncer.new(@ctx, theme: theme, ignore_filter: ignore_filter)
33
+ begin
34
+ syncer.start_threads
35
+ CLI::UI::Frame.open(@ctx.message("theme.pull.pulling", theme.name, theme.id, theme.shop)) do
36
+ UI::SyncProgressBar.new(syncer).progress(:download_theme!, delete: delete)
37
+ end
38
+ @ctx.done(@ctx.message("theme.pull.done"))
39
+ rescue ShopifyCli::API::APIRequestNotFoundError
40
+ @ctx.abort(@ctx.message("theme.pull.theme_not_found", theme.id))
41
+ ensure
42
+ syncer.shutdown
43
+ end
44
+ end
45
+
46
+ def self.help
47
+ ShopifyCli::Context.message("theme.pull.help", ShopifyCli::TOOL_NAME, ShopifyCli::TOOL_NAME)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,49 +1,75 @@
1
1
  # frozen_string_literal: true
2
- module Theme
3
- module Commands
4
- class Push < ShopifyCli::Command
5
- prerequisite_task :ensure_themekit_installed
2
+ require "shopify-cli/theme/theme"
3
+ require "shopify-cli/theme/development_theme"
4
+ require "shopify-cli/theme/ignore_filter"
5
+ require "shopify-cli/theme/syncer"
6
6
 
7
+ module Theme
8
+ class Command
9
+ class Push < ShopifyCli::SubCommand
7
10
  options do |parser, flags|
8
- parser.on("--remove") { flags["remove"] = true }
9
- parser.on("--nodelete") { flags["nodelete"] = true }
10
- parser.on("--allow-live") { flags["allow-live"] = true }
11
- parser.on("--env=ENV") { |env| flags[:env] = env }
11
+ parser.on("-n", "--nodelete") { flags[:nodelete] = true }
12
+ parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
13
+ parser.on("-d", "--development") { flags[:development] = true }
14
+ parser.on("-u", "--unpublished") { flags[:unpublished] = true }
15
+ parser.on("-j", "--json") { flags[:json] = true }
16
+ parser.on("-a", "--allow-live") { flags[:allow_live] = true }
17
+ parser.on("-p", "--publish") { flags[:publish] = true }
12
18
  end
13
19
 
14
20
  def call(args, _name)
15
- if options.flags["remove"]
16
- remove = true
17
- options.flags.delete("remove")
18
- end
21
+ root = args.first || "."
22
+ delete = !options.flags[:nodelete]
19
23
 
20
- if options.flags[:env]
21
- env = options.flags[:env]
22
- options.flags.delete(:env)
24
+ theme = if (theme_id = options.flags[:theme_id])
25
+ ShopifyCli::Theme::Theme.new(@ctx, root: root, id: theme_id)
26
+ elsif options.flags[:development]
27
+ theme = ShopifyCli::Theme::DevelopmentTheme.new(@ctx, root: root)
28
+ theme.ensure_exists!
29
+ theme
30
+ elsif options.flags[:unpublished]
31
+ name = CLI::UI::Prompt.ask(@ctx.message("theme.push.name"), allow_empty: false)
32
+ theme = ShopifyCli::Theme::Theme.new(@ctx, root: root, name: name, role: "unpublished")
33
+ theme.create
34
+ theme
35
+ else
36
+ form = Forms::Select.ask(
37
+ @ctx,
38
+ [],
39
+ title: @ctx.message("theme.push.select"),
40
+ root: root,
41
+ )
42
+ return unless form
43
+ form.theme
23
44
  end
24
45
 
25
- flags = Themekit.add_flags(options.flags)
26
-
27
- if remove
28
- CLI::UI::Frame.open(@ctx.message("theme.push.remove")) do
29
- unless CLI::UI::Prompt.confirm(@ctx.message("theme.push.remove_confirm"))
30
- @ctx.abort(@ctx.message("theme.push.remove_abort"))
31
- end
46
+ if theme.live? && !options.flags[:allow_live]
47
+ return unless CLI::UI::Prompt.confirm(@ctx.message("theme.push.live"))
48
+ end
32
49
 
33
- unless Themekit.push(@ctx, files: args, flags: flags, remove: remove, env: env)
34
- @ctx.abort(@ctx.message("theme.push.error.remove_error"))
50
+ ignore_filter = ShopifyCli::Theme::IgnoreFilter.from_path(root)
51
+ syncer = ShopifyCli::Theme::Syncer.new(@ctx, theme: theme, ignore_filter: ignore_filter)
52
+ begin
53
+ syncer.start_threads
54
+ if options.flags[:json]
55
+ syncer.upload_theme!(delete: delete)
56
+ puts(JSON.generate(theme: theme.to_h))
57
+ else
58
+ CLI::UI::Frame.open(@ctx.message("theme.push.info.pushing", theme.name, theme.id, theme.shop)) do
59
+ UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delete: delete)
35
60
  end
36
- end
37
61
 
38
- @ctx.done(@ctx.message("theme.push.info.remove", @ctx.root))
39
- else
40
- CLI::UI::Frame.open(@ctx.message("theme.push.push")) do
41
- unless Themekit.push(@ctx, files: args, flags: flags, remove: remove, env: env)
42
- @ctx.abort(@ctx.message("theme.push.error.push_error"))
62
+ if options.flags[:publish]
63
+ theme.publish
64
+ @ctx.done(@ctx.message("theme.publish.done", theme.preview_url))
65
+ else
66
+ @ctx.done(@ctx.message("theme.push.done", theme.preview_url, theme.editor_url))
43
67
  end
44
68
  end
45
-
46
- @ctx.done(@ctx.message("theme.push.info.push", @ctx.root))
69
+ rescue ShopifyCli::API::APIRequestNotFoundError
70
+ @ctx.abort(@ctx.message("theme.push.theme_not_found", theme.id))
71
+ ensure
72
+ syncer.shutdown
47
73
  end
48
74
  end
49
75