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
@@ -1,40 +1,29 @@
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 :Init, "init", Project.project_filepath("commands/init")
10
+ subcommand :Serve, "serve", Project.project_filepath("commands/serve")
11
+ subcommand :Pull, "pull", Project.project_filepath("commands/pull")
12
+ subcommand :Push, "push", Project.project_filepath("commands/push")
13
+ subcommand :Delete, "delete", Project.project_filepath("commands/delete")
14
+ subcommand :Check, "check", Project.project_filepath("commands/check")
15
+ subcommand :Publish, "publish", Project.project_filepath("commands/publish")
16
+ subcommand :Package, "package", Project.project_filepath("commands/package")
17
+ subcommand :LanguageServer, "language-server", Project.project_filepath("commands/language_server")
32
18
  end
19
+ ShopifyCli::Commands.register("Theme::Command", "theme")
33
20
 
34
21
  module Forms
35
- autoload :Create, Project.project_filepath("forms/create")
36
- autoload :Connect, Project.project_filepath("forms/connect")
22
+ autoload :ConfirmStore, Project.project_filepath("forms/confirm_store")
23
+ autoload :Select, Project.project_filepath("forms/select")
37
24
  end
38
25
 
39
- autoload :Themekit, Project.project_filepath("themekit")
26
+ module UI
27
+ autoload :SyncProgressBar, Project.project_filepath("ui/sync_progress_bar")
28
+ end
40
29
  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,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Theme
4
+ class Command
5
+ class Init < ShopifyCli::SubCommand
6
+ options do |parser, flags|
7
+ parser.on("-u", "--clone-url URL") { |url| flags[:clone_url] = url }
8
+ end
9
+
10
+ DEFAULT_CLONE_URL = "https://github.com/Shopify/dawn.git"
11
+
12
+ def call(args, _name)
13
+ name = args.first || ask_name
14
+ clone_url = options.flags[:clone_url] || DEFAULT_CLONE_URL
15
+ clone(clone_url, name)
16
+ end
17
+
18
+ def self.help
19
+ ShopifyCli::Context.message("theme.init.help", ShopifyCli::TOOL_NAME, ShopifyCli::TOOL_NAME)
20
+ end
21
+
22
+ private
23
+
24
+ def ask_name
25
+ CLI::UI::Prompt.ask(@ctx.message("theme.init.ask_name"))
26
+ end
27
+
28
+ def clone(url, name)
29
+ ShopifyCli::Git.clone(url, name)
30
+
31
+ @ctx.root = File.join(@ctx.root, name)
32
+
33
+ begin
34
+ @ctx.rm_r(".git")
35
+ @ctx.rm_r(".github")
36
+ rescue Errno::ENOENT => e
37
+ @ctx.debug(e)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ 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