shopify-cli 2.6.6 → 2.7.3

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 (206) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer.json +5 -0
  3. data/.github/CODEOWNERS +2 -2
  4. data/.github/DESIGN.md +1 -1
  5. data/.github/ISSUE_TEMPLATE.md +7 -0
  6. data/.github/workflows/shopify.yml +1 -1
  7. data/.gitignore +1 -0
  8. data/.ruby-version +1 -1
  9. data/.vscode/extensions.json +5 -0
  10. data/.vscode/settings.json +9 -0
  11. data/CHANGELOG.md +44 -4
  12. data/CONTRIBUTING.md +1 -29
  13. data/{Dockerfile → Codespace.dockerfile} +2 -2
  14. data/Gemfile.lock +5 -5
  15. data/README.md +20 -99
  16. data/Rakefile +27 -0
  17. data/Tests.dockerfile +35 -0
  18. data/assets/logo.png +0 -0
  19. data/dev.yml +1 -4
  20. data/docs/README.md +13 -0
  21. data/docs/contributors/testing.md +27 -0
  22. data/docs/users/installation.md +46 -0
  23. data/{THEMEKIT_MIGRATION.md → docs/users/migrate-from-themekit.md} +1 -1
  24. data/ext/javy/hashes/javy-arm-macos-v0.1.0.gz.sha256 +1 -0
  25. data/ext/javy/hashes/javy-x86_64-linux-v0.1.0.gz.sha256 +1 -0
  26. data/ext/javy/hashes/javy-x86_64-macos-v0.1.0.gz.sha256 +1 -0
  27. data/ext/javy/hashes/javy-x86_64-windows-v0.1.0.gz.sha256 +1 -0
  28. data/ext/javy/javy.rb +205 -0
  29. data/ext/javy/version +1 -0
  30. data/lib/project_types/extension/cli.rb +6 -3
  31. data/lib/project_types/extension/commands/build.rb +4 -8
  32. data/lib/project_types/extension/commands/create.rb +2 -5
  33. data/lib/project_types/extension/commands/extension_command.rb +1 -1
  34. data/lib/project_types/extension/features/argo_serve.rb +9 -23
  35. data/lib/project_types/extension/forms/questions/ask_template.rb +1 -5
  36. data/lib/project_types/extension/messages/messages.rb +0 -2
  37. data/lib/project_types/extension/models/development_server.rb +2 -2
  38. data/lib/project_types/extension/models/development_server_requirements.rb +2 -3
  39. data/lib/project_types/extension/models/server_config/app.rb +13 -0
  40. data/lib/project_types/extension/models/server_config/development.rb +5 -4
  41. data/lib/project_types/extension/models/server_config/development_renderer.rb +1 -1
  42. data/lib/project_types/extension/models/server_config/development_resource.rb +13 -0
  43. data/lib/project_types/extension/models/server_config/extension.rb +3 -1
  44. data/lib/project_types/extension/models/server_config/root.rb +4 -1
  45. data/lib/project_types/extension/tasks/convert_server_config.rb +65 -0
  46. data/lib/project_types/extension/tasks/ensure_resource_url.rb +39 -0
  47. data/lib/project_types/extension/tasks/merge_server_config.rb +32 -0
  48. data/lib/project_types/extension/tasks/run_extension_command.rb +11 -10
  49. data/lib/project_types/node/cli.rb +0 -16
  50. data/lib/project_types/node/forms/create.rb +5 -5
  51. data/lib/project_types/node/messages/messages.rb +2 -144
  52. data/lib/project_types/php/cli.rb +0 -11
  53. data/lib/project_types/php/forms/create.rb +5 -6
  54. data/lib/project_types/php/messages/messages.rb +2 -161
  55. data/lib/project_types/rails/cli.rb +0 -16
  56. data/lib/project_types/rails/commands/create.rb +3 -5
  57. data/lib/project_types/rails/forms/create.rb +5 -6
  58. data/lib/project_types/rails/messages/messages.rb +6 -151
  59. data/lib/project_types/script/cli.rb +8 -2
  60. data/lib/project_types/script/commands/create.rb +2 -4
  61. data/lib/project_types/script/commands/javy.rb +29 -0
  62. data/lib/project_types/script/commands/push.rb +3 -2
  63. data/lib/project_types/script/config/extension_points.yml +12 -30
  64. data/lib/project_types/script/forms/ask_app.rb +32 -0
  65. data/lib/project_types/script/forms/ask_org.rb +30 -0
  66. data/lib/project_types/script/forms/ask_script_uuid.rb +22 -0
  67. data/lib/project_types/script/forms/run_against_shopify_org.rb +14 -0
  68. data/lib/project_types/script/graphql/app_script_set.graphql +2 -2
  69. data/lib/project_types/script/layers/application/build_script.rb +0 -1
  70. data/lib/project_types/script/layers/application/connect_app.rb +73 -0
  71. data/lib/project_types/script/layers/application/create_script.rb +1 -1
  72. data/lib/project_types/script/layers/application/push_script.rb +1 -1
  73. data/lib/project_types/script/layers/domain/errors.rb +1 -4
  74. data/lib/project_types/script/layers/domain/push_package.rb +3 -3
  75. data/lib/project_types/script/layers/domain/{script_json.rb → script_config.rb} +2 -2
  76. data/lib/project_types/script/layers/domain/script_project.rb +5 -1
  77. data/lib/project_types/script/layers/infrastructure/errors.rb +36 -7
  78. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +0 -4
  79. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +0 -4
  80. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +2 -2
  81. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +104 -27
  82. data/lib/project_types/script/layers/infrastructure/script_service.rb +11 -11
  83. data/lib/project_types/script/messages/messages.rb +21 -4
  84. data/lib/project_types/script/ui/error_handler.rb +31 -21
  85. data/lib/project_types/theme/cli.rb +1 -1
  86. data/lib/project_types/theme/commands/check.rb +1 -1
  87. data/lib/project_types/theme/commands/delete.rb +1 -1
  88. data/lib/project_types/theme/commands/init.rb +1 -1
  89. data/lib/project_types/theme/commands/language_server.rb +1 -1
  90. data/lib/project_types/theme/commands/package.rb +1 -1
  91. data/lib/project_types/theme/commands/publish.rb +1 -1
  92. data/lib/project_types/theme/commands/pull.rb +4 -1
  93. data/lib/project_types/theme/commands/push.rb +5 -1
  94. data/lib/project_types/theme/commands/serve.rb +9 -3
  95. data/lib/project_types/theme/messages/messages.rb +39 -2
  96. data/lib/project_types/theme/ui/sync_progress_bar.rb +2 -2
  97. data/lib/shopify_cli/admin_api/populate_resource_command.rb +1 -1
  98. data/lib/shopify_cli/api.rb +7 -2
  99. data/lib/shopify_cli/app_type_detector.rb +24 -20
  100. data/lib/shopify_cli/command/app_sub_command.rb +10 -0
  101. data/lib/shopify_cli/command/project_command.rb +31 -0
  102. data/lib/shopify_cli/command/sub_command.rb +19 -0
  103. data/lib/shopify_cli/command.rb +7 -2
  104. data/lib/shopify_cli/commands/app/connect.rb +22 -0
  105. data/lib/shopify_cli/commands/app/create/node.rb +36 -0
  106. data/lib/shopify_cli/commands/app/create/php.rb +36 -0
  107. data/lib/shopify_cli/commands/app/create/rails.rb +38 -0
  108. data/lib/shopify_cli/commands/app/create.rb +28 -0
  109. data/lib/shopify_cli/commands/app/deploy.rb +49 -0
  110. data/lib/shopify_cli/commands/app/open.rb +19 -0
  111. data/lib/shopify_cli/commands/app/serve.rb +49 -0
  112. data/lib/shopify_cli/commands/app/tunnel.rb +43 -0
  113. data/lib/shopify_cli/commands/app.rb +29 -0
  114. data/lib/shopify_cli/commands/config.rb +2 -2
  115. data/lib/shopify_cli/commands.rb +1 -0
  116. data/lib/shopify_cli/constants.rb +7 -0
  117. data/lib/shopify_cli/context.rb +10 -0
  118. data/lib/shopify_cli/environment.rb +4 -0
  119. data/lib/shopify_cli/exception_reporter.rb +3 -4
  120. data/lib/shopify_cli/git.rb +14 -1
  121. data/lib/shopify_cli/github/issue_url_generator.rb +19 -0
  122. data/lib/shopify_cli/github.rb +5 -0
  123. data/lib/shopify_cli/identity_auth.rb +18 -0
  124. data/lib/shopify_cli/messages/messages.rb +254 -9
  125. data/lib/shopify_cli/partners_api.rb +1 -8
  126. data/lib/shopify_cli/project.rb +5 -1
  127. data/lib/shopify_cli/project_commands.rb +1 -1
  128. data/lib/shopify_cli/services/app/connect_service.rb +25 -0
  129. data/lib/shopify_cli/services/app/create/node_service.rb +155 -0
  130. data/lib/shopify_cli/services/app/create/php_service.rb +152 -0
  131. data/lib/shopify_cli/services/app/create/rails_service.rb +215 -0
  132. data/lib/shopify_cli/services/app/deploy/heroku/node_service.rb +101 -0
  133. data/lib/shopify_cli/services/app/deploy/heroku/php_service.rb +135 -0
  134. data/lib/shopify_cli/services/app/deploy/heroku/rails_service.rb +120 -0
  135. data/lib/shopify_cli/services/app/open_service.rb +19 -0
  136. data/lib/shopify_cli/services/app/serve/node_service.rb +42 -0
  137. data/lib/shopify_cli/services/app/serve/php_service.rb +46 -0
  138. data/lib/shopify_cli/services/app/serve/rails_service.rb +48 -0
  139. data/lib/shopify_cli/services/app/tunnel/auth_service.rb +21 -0
  140. data/lib/shopify_cli/services/app/tunnel/start_service.rb +20 -0
  141. data/lib/shopify_cli/services/app/tunnel/stop_service.rb +20 -0
  142. data/lib/shopify_cli/services.rb +31 -0
  143. data/lib/shopify_cli/tasks/ensure_authenticated.rb +9 -3
  144. data/lib/shopify_cli/theme/dev_server/cdn_fonts.rb +73 -0
  145. data/lib/shopify_cli/theme/dev_server/hot-reload.js +25 -9
  146. data/lib/shopify_cli/theme/dev_server/local_assets.rb +1 -1
  147. data/lib/shopify_cli/theme/dev_server.rb +37 -18
  148. data/lib/shopify_cli/theme/syncer/error_reporter.rb +45 -0
  149. data/lib/shopify_cli/theme/syncer/operation.rb +56 -0
  150. data/lib/shopify_cli/theme/syncer/standard_reporter.rb +32 -0
  151. data/lib/shopify_cli/theme/syncer.rb +40 -39
  152. data/lib/shopify_cli/theme/theme.rb +31 -19
  153. data/lib/shopify_cli/tunnel.rb +26 -22
  154. data/lib/shopify_cli/version.rb +1 -1
  155. data/lib/shopify_cli.rb +1 -2
  156. data/shopify-cli.gemspec +1 -1
  157. data/shopify-dev +18 -0
  158. data/utilities/constants.rb +7 -0
  159. data/utilities/docker/container.rb +10 -3
  160. data/utilities/docker.rb +2 -2
  161. data/utilities/utilities.rb +1 -0
  162. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +1 -1
  163. metadata +66 -50
  164. data/docs/_config.yml +0 -2
  165. data/docs/app/node/commands/index.md +0 -4
  166. data/docs/app/node/index.md +0 -4
  167. data/docs/app/rails/commands/index.md +0 -4
  168. data/docs/app/rails/index.md +0 -4
  169. data/docs/core/index.md +0 -4
  170. data/docs/getting-started/index.md +0 -4
  171. data/docs/getting-started/install/index.md +0 -4
  172. data/docs/getting-started/migrate/index.md +0 -4
  173. data/docs/getting-started/uninstall/index.md +0 -4
  174. data/docs/getting-started/upgrade/index.md +0 -4
  175. data/docs/help/start-app/index.md +0 -4
  176. data/docs/index.md +0 -4
  177. data/install.sh +0 -7
  178. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +0 -30
  179. data/lib/project_types/extension/tasks/load_server_config.rb +0 -28
  180. data/lib/project_types/node/commands/connect.rb +0 -21
  181. data/lib/project_types/node/commands/create.rb +0 -125
  182. data/lib/project_types/node/commands/deploy/heroku.rb +0 -96
  183. data/lib/project_types/node/commands/deploy.rb +0 -32
  184. data/lib/project_types/node/commands/generate.rb +0 -22
  185. data/lib/project_types/node/commands/open.rb +0 -18
  186. data/lib/project_types/node/commands/serve.rb +0 -45
  187. data/lib/project_types/node/commands/tunnel.rb +0 -41
  188. data/lib/project_types/php/commands/connect.rb +0 -19
  189. data/lib/project_types/php/commands/create.rb +0 -143
  190. data/lib/project_types/php/commands/deploy/heroku.rb +0 -129
  191. data/lib/project_types/php/commands/deploy.rb +0 -32
  192. data/lib/project_types/php/commands/open.rb +0 -16
  193. data/lib/project_types/php/commands/serve.rb +0 -48
  194. data/lib/project_types/php/commands/tunnel.rb +0 -37
  195. data/lib/project_types/rails/commands/connect.rb +0 -21
  196. data/lib/project_types/rails/commands/deploy/heroku.rb +0 -115
  197. data/lib/project_types/rails/commands/deploy.rb +0 -32
  198. data/lib/project_types/rails/commands/generate/webhook.rb +0 -42
  199. data/lib/project_types/rails/commands/generate.rb +0 -60
  200. data/lib/project_types/rails/commands/open.rb +0 -18
  201. data/lib/project_types/rails/commands/serve.rb +0 -51
  202. data/lib/project_types/rails/commands/tunnel.rb +0 -41
  203. data/lib/project_types/script/tasks/ensure_env.rb +0 -106
  204. data/lib/shopify_cli/sub_command.rb +0 -17
  205. data/shopify.fish +0 -12
  206. data/shopify.sh +0 -11
@@ -0,0 +1,135 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Deploy
5
+ module Heroku
6
+ class PHPService < BaseService
7
+ attr_reader :context
8
+
9
+ def initialize(context:)
10
+ @context = context
11
+ super()
12
+ end
13
+
14
+ def call
15
+ spin_group = CLI::UI::SpinGroup.new
16
+ heroku_service = ShopifyCLI::Heroku.new(context)
17
+
18
+ spin_group.add(context.message("core.app.deploy.heroku.downloading")) do |spinner|
19
+ heroku_service.download
20
+ spinner.update_title(context.message("core.app.deploy.heroku.downloaded"))
21
+ end
22
+ spin_group.wait
23
+
24
+ install_message = context.message(
25
+ context.windows? ? "core.app.deploy.heroku.installing_windows" : "core.app.deploy.heroku.installing"
26
+ )
27
+ spin_group.add(install_message) do |spinner|
28
+ heroku_service.install
29
+ spinner.update_title(context.message("core.app.deploy.heroku.installed"))
30
+ end
31
+ spin_group.wait
32
+
33
+ spin_group.add(context.message("core.app.deploy.heroku.git.checking")) do |spinner|
34
+ ShopifyCLI::Git.init(context)
35
+ spinner.update_title(context.message("core.app.deploy.heroku.git.initialized"))
36
+ end
37
+ spin_group.wait
38
+
39
+ if (account = heroku_service.whoami)
40
+ context.puts(context.message("core.app.deploy.heroku.authenticated_with_account", account))
41
+ else
42
+ CLI::UI::Frame.open(
43
+ context.message("core.app.deploy.heroku.authenticating"),
44
+ success_text: context.message("core.app.deploy.heroku.authenticated")
45
+ ) do
46
+ heroku_service.authenticate
47
+ end
48
+ end
49
+
50
+ if (app_name = heroku_service.app)
51
+ context.puts(context.message("core.app.deploy.heroku.app.selected", app_name))
52
+ else
53
+ app_type = CLI::UI::Prompt.ask(context.message("core.app.deploy.heroku.app.no_apps_found")) do |handler|
54
+ handler.option(context.message("core.app.deploy.heroku.app.create")) { :new }
55
+ handler.option(context.message("core.app.deploy.heroku.app.select")) { :existing }
56
+ end
57
+
58
+ if app_type == :existing
59
+ app_name = CLI::UI::Prompt.ask(context.message("core.app.deploy.heroku.app.name"))
60
+ CLI::UI::Frame.open(
61
+ context.message("core.app.deploy.heroku.app.selecting", app_name),
62
+ success_text: context.message("core.app.deploy.heroku.app.selected", app_name)
63
+ ) do
64
+ heroku_service.select_existing_app(app_name)
65
+ end
66
+ elsif app_type == :new
67
+ CLI::UI::Frame.open(
68
+ context.message("core.app.deploy.heroku.app.creating"),
69
+ success_text: context.message("core.app.deploy.heroku.app.created")
70
+ ) do
71
+ heroku_service.create_new_app
72
+ app_name = heroku_service.app
73
+ end
74
+ end
75
+ end
76
+
77
+ branches = ShopifyCLI::Git.branches(context)
78
+ if branches.length == 1
79
+ branch_to_deploy = branches[0]
80
+ context.puts(context.message("core.app.deploy.heroku.git.branch_selected", branch_to_deploy))
81
+ else
82
+ prompt_question = context.message("core.app.deploy.heroku.git.what_branch")
83
+ branch_to_deploy = CLI::UI::Prompt.ask(prompt_question) do |handler|
84
+ branches.each do |branch|
85
+ handler.option(branch) { branch }
86
+ end
87
+ end
88
+ end
89
+
90
+ app_url = "https://#{app_name}.herokuapp.com"
91
+
92
+ CLI::UI::Frame.open(
93
+ context.message("core.app.deploy.heroku.app.setting_configs"),
94
+ success_text: context.message("core.app.deploy.heroku.app.configs_set")
95
+ ) do
96
+ allowed_configs = [/SHOPIFY_API_KEY/, /SHOPIFY_API_SECRET/, /SCOPES/, /HOST/]
97
+
98
+ ShopifyCLI::Project.current.env.to_h.each do |config, value|
99
+ next unless allowed_configs.any? { |pattern| pattern.match?(config) }
100
+
101
+ value = app_url if config == "HOST"
102
+
103
+ current = heroku_service.get_config(config)
104
+ heroku_service.set_config(config, value) if current.nil? || current != value
105
+ end
106
+
107
+ current_key = heroku_service.get_config("APP_KEY")
108
+ if current_key.nil? || current_key.empty?
109
+ output, status = context.capture2e("php", "artisan", "key:generate", "--show")
110
+
111
+ abort_message = context.message("core.app.deploy.heroku.php.error.generate_app_key")
112
+ context.abort(abort_message) unless status.success?
113
+
114
+ heroku_service.set_config("APP_KEY", output.strip) if status.success?
115
+ end
116
+
117
+ heroku_service.add_buildpacks(["heroku/php", "heroku/nodejs"])
118
+ end
119
+
120
+ CLI::UI::Frame.open(
121
+ context.message("core.app.deploy.heroku.deploying"),
122
+ success_text: context.message("core.app.deploy.heroku.deployed")
123
+ ) do
124
+ heroku_service.deploy(branch_to_deploy)
125
+ end
126
+
127
+ heroku_command = heroku_service.heroku_command
128
+ context.puts(context.message("core.app.deploy.heroku.php.post_deploy", app_url, heroku_command))
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,120 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Deploy
5
+ module Heroku
6
+ class RailsService < BaseService
7
+ DB_CHECK_CMD = 'bundle exec rails runner "puts ActiveRecord::Base.connection.adapter_name.downcase"'
8
+
9
+ attr_reader :context
10
+
11
+ def initialize(context:)
12
+ @context = context
13
+ super()
14
+ end
15
+
16
+ def call
17
+ CLI::UI::Frame.open(context.message("core.app.deploy.heroku.rails.db_check.validating")) do
18
+ CLI::UI::Spinner.spin(context.message("core.app.deploy.heroku.rails.db_check.checking")) do |spinner|
19
+ db_type, err = check_db(context)
20
+ context.abort(context.message(err)) unless err.nil?
21
+ spinner.update_title(context.message("core.app.deploy.heroku.rails.db_check.validated", db_type))
22
+ end
23
+ true
24
+ end
25
+
26
+ spin_group = CLI::UI::SpinGroup.new
27
+ heroku_service = ShopifyCLI::Heroku.new(context)
28
+
29
+ spin_group.add(context.message("core.app.deploy.heroku.downloading")) do |spinner|
30
+ heroku_service.download
31
+ spinner.update_title(context.message("core.app.deploy.heroku.downloaded"))
32
+ end
33
+ spin_group.wait
34
+
35
+ spin_group.add(context.message("core.app.deploy.heroku.installing")) do |spinner|
36
+ heroku_service.install
37
+ spinner.update_title(context.message("core.app.deploy.heroku.installed"))
38
+ end
39
+ spin_group.add(context.message("core.app.deploy.heroku.git.checking")) do |spinner|
40
+ ShopifyCLI::Git.init(context)
41
+ spinner.update_title(context.message("core.app.deploy.heroku.git.initialized"))
42
+ end
43
+ spin_group.wait
44
+
45
+ if (account = heroku_service.whoami)
46
+ context.puts(context.message("core.app.deploy.heroku.authenticated_with_account", account))
47
+ else
48
+ CLI::UI::Frame.open(
49
+ context.message("core.app.deploy.heroku.authenticating"),
50
+ success_text: context.message("core.app.deploy.heroku.authenticated")
51
+ ) do
52
+ heroku_service.authenticate
53
+ end
54
+ end
55
+
56
+ if (app_name = heroku_service.app)
57
+ context.puts(context.message("core.app.deploy.heroku.app.selected", app_name))
58
+ else
59
+ app_type = CLI::UI::Prompt.ask(context.message("core.app.deploy.heroku.app.no_apps_found")) do |handler|
60
+ handler.option(context.message("core.app.deploy.heroku.app.create")) { :new }
61
+ handler.option(context.message("core.app.deploy.heroku.app.select")) { :existing }
62
+ end
63
+
64
+ if app_type == :existing
65
+ app_name = CLI::UI::Prompt.ask(context.message("core.app.deploy.heroku.app.name"))
66
+ CLI::UI::Frame.open(
67
+ context.message("core.app.deploy.heroku.app.selecting", app_name),
68
+ success_text: context.message("core.app.deploy.heroku.app.selected", app_name)
69
+ ) do
70
+ heroku_service.select_existing_app(app_name)
71
+ end
72
+ elsif app_type == :new
73
+ CLI::UI::Frame.open(
74
+ context.message("core.app.deploy.heroku.app.creating"),
75
+ success_text: context.message("core.app.deploy.heroku.app.created")
76
+ ) do
77
+ heroku_service.create_new_app
78
+ end
79
+ end
80
+ end
81
+
82
+ branches = ShopifyCLI::Git.branches(context)
83
+ if branches.length == 1
84
+ branch_to_deploy = branches[0]
85
+ context.puts(context.message("core.app.deploy.heroku.git.branch_selected", branch_to_deploy))
86
+ else
87
+ prompt_question = context.message("core.app.deploy.heroku.git.what_branch")
88
+ branch_to_deploy = CLI::UI::Prompt.ask(prompt_question) do |handler|
89
+ branches.each do |branch|
90
+ handler.option(branch) { branch }
91
+ end
92
+ end
93
+ end
94
+
95
+ CLI::UI::Frame.open(
96
+ context.message("core.app.deploy.heroku.deploying"),
97
+ success_text: context.message("core.app.deploy.heroku.deployed")
98
+ ) do
99
+ heroku_service.deploy(branch_to_deploy)
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ def check_db(context)
106
+ out, stat = context.capture2e(DB_CHECK_CMD)
107
+ if stat.success? && out.strip == "sqlite"
108
+ ["sqlite", "core.app.deploy.heroku.rails.db_check.sqlite"]
109
+ elsif !stat.success?
110
+ [nil, "core.app.deploy.heroku.rails.db_check.problem"]
111
+ else
112
+ [out.strip, nil]
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,19 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ class OpenService < BaseService
5
+ attr_reader :project, :context
6
+
7
+ def initialize(project:, context:)
8
+ @project = project
9
+ @context = context
10
+ super()
11
+ end
12
+
13
+ def call
14
+ context.open_url!("#{project.env.host}/login?shop=#{project.env.shop}")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Serve
5
+ class NodeService < BaseService
6
+ attr_accessor :host, :port, :context
7
+
8
+ def initialize(host:, port:, context:)
9
+ @host = host
10
+ @port = port
11
+ @context = context
12
+ super()
13
+ end
14
+
15
+ def call
16
+ project = ShopifyCLI::Project.current
17
+ url = host || ShopifyCLI::Tunnel.start(context, port: port)
18
+ raise ShopifyCLI::Abort,
19
+ context.message("core.app.serve.error.host_must_be_https") if url.match(/^https/i).nil?
20
+ project.env.update(context, :host, url)
21
+ ShopifyCLI::Tasks::UpdateDashboardURLS.call(
22
+ context,
23
+ url: url,
24
+ callback_url: "/auth/callback",
25
+ )
26
+
27
+ if project.env.shop
28
+ project_url = "#{project.env.host}/auth?shop=#{project.env.shop}"
29
+ context.puts("\n" + context.message("core.app.serve.open_info", project_url) + "\n")
30
+ end
31
+
32
+ CLI::UI::Frame.open(context.message("core.app.serve.running_server")) do
33
+ env = project.env.to_h
34
+ env["PORT"] = port.to_s
35
+ context.system("npm run dev", env: env)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,46 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Serve
5
+ class PHPService < BaseService
6
+ attr_accessor :host, :port, :context
7
+
8
+ def initialize(host:, port:, context:)
9
+ @host = host
10
+ @port = port
11
+ @context = context
12
+ super()
13
+ end
14
+
15
+ def call
16
+ project = ShopifyCLI::Project.current
17
+ url = host || ShopifyCLI::Tunnel.start(context, port: port)
18
+ raise ShopifyCLI::Abort,
19
+ context.message("core.app.serve.error.host_must_be_https") if url.match(/^https/i).nil?
20
+ project.env.update(context, :host, url)
21
+ ShopifyCLI::Tasks::UpdateDashboardURLS.call(
22
+ context,
23
+ url: url,
24
+ callback_url: "/auth/callback",
25
+ )
26
+
27
+ if project.env.shop
28
+ project_url = "#{project.env.host}/login?shop=#{project.env.shop}"
29
+ context.puts("\n" + context.message("core.app.serve.open_info", project_url) + "\n")
30
+ end
31
+
32
+ CLI::UI::Frame.open(context.message("core.app.serve.running_server")) do
33
+ if ShopifyCLI::ProcessSupervision.running?(:npm_watch)
34
+ ShopifyCLI::ProcessSupervision.stop(:npm_watch)
35
+ end
36
+ ShopifyCLI::ProcessSupervision.start(:npm_watch, "npm run watch", force_spawn: true)
37
+
38
+ env = project.env.to_h
39
+ context.system("php", "artisan", "serve", "--port", port.to_s, env: env)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,48 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Serve
5
+ class RailsService < BaseService
6
+ attr_accessor :host, :port, :context
7
+
8
+ def initialize(host:, port:, context:)
9
+ @host = host
10
+ @port = port
11
+ @context = context
12
+ super()
13
+ end
14
+
15
+ def call
16
+ project = ShopifyCLI::Project.current
17
+ url = host || ShopifyCLI::Tunnel.start(context, port: port)
18
+ raise ShopifyCLI::Abort,
19
+ context.message("core.app.serve.error.host_must_be_https") if url.match(/^https/i).nil?
20
+ project.env.update(context, :host, url)
21
+ ShopifyCLI::Tasks::UpdateDashboardURLS.call(
22
+ context,
23
+ url: url,
24
+ callback_url: "/auth/shopify/callback",
25
+ )
26
+
27
+ if project.env.shop
28
+ project_url = "#{project.env.host}/login?shop=#{project.env.shop}"
29
+ context.puts("\n" + context.message("core.app.serve.open_info", project_url) + "\n")
30
+ end
31
+
32
+ CLI::UI::Frame.open(context.message("core.app.serve.running_server")) do
33
+ env = ShopifyCLI::Project.current.env.to_h
34
+ env.delete("HOST")
35
+ env["PORT"] = port.to_s
36
+ env["GEM_PATH"] = Rails::Gem.gem_path(context)
37
+ if context.windows?
38
+ context.system("ruby bin\\rails server", env: env)
39
+ else
40
+ context.system("bin/rails server", env: env)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Tunnel
5
+ class AuthService < BaseService
6
+ attr_accessor :context, :token
7
+
8
+ def initialize(token:, context:)
9
+ @context = context
10
+ @token = token
11
+ super()
12
+ end
13
+
14
+ def call
15
+ ShopifyCLI::Tunnel.auth(context, token)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Tunnel
5
+ class StartService < BaseService
6
+ attr_accessor :context
7
+
8
+ def initialize(context:)
9
+ @context = context
10
+ super()
11
+ end
12
+
13
+ def call
14
+ ShopifyCLI::Tunnel.start(context)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module ShopifyCLI
2
+ module Services
3
+ module App
4
+ module Tunnel
5
+ class StopService < BaseService
6
+ attr_accessor :context
7
+
8
+ def initialize(context:)
9
+ @context = context
10
+ super()
11
+ end
12
+
13
+ def call
14
+ ShopifyCLI::Tunnel.stop(context)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,5 +2,36 @@ module ShopifyCLI
2
2
  module Services
3
3
  autoload :BaseService, "shopify_cli/services/base_service"
4
4
  autoload :ReportingService, "shopify_cli/services/reporting_service"
5
+
6
+ module App
7
+ module Serve
8
+ autoload :NodeService, "shopify_cli/services/app/serve/node_service"
9
+ autoload :RailsService, "shopify_cli/services/app/serve/rails_service"
10
+ autoload :PHPService, "shopify_cli/services/app/serve/php_service"
11
+ end
12
+
13
+ module Create
14
+ autoload :NodeService, "shopify_cli/services/app/create/node_service"
15
+ autoload :RailsService, "shopify_cli/services/app/create/rails_service"
16
+ autoload :PHPService, "shopify_cli/services/app/create/php_service"
17
+ end
18
+
19
+ module Deploy
20
+ module Heroku
21
+ autoload :NodeService, "shopify_cli/services/app/deploy/heroku/node_service"
22
+ autoload :RailsService, "shopify_cli/services/app/deploy/heroku/rails_service"
23
+ autoload :PHPService, "shopify_cli/services/app/deploy/heroku/php_service"
24
+ end
25
+ end
26
+
27
+ module Tunnel
28
+ autoload :StartService, "shopify_cli/services/app/tunnel/start_service"
29
+ autoload :StopService, "shopify_cli/services/app/tunnel/stop_service"
30
+ autoload :AuthService, "shopify_cli/services/app/tunnel/auth_service"
31
+ end
32
+
33
+ autoload :ConnectService, "shopify_cli/services/app/connect_service"
34
+ autoload :OpenService, "shopify_cli/services/app/open_service"
35
+ end
5
36
  end
6
37
  end
@@ -4,9 +4,15 @@ module ShopifyCLI
4
4
  module Tasks
5
5
  class EnsureAuthenticated < ShopifyCLI::Task
6
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) }
7
+ return if ShopifyCLI::Environment.acceptance_test?
8
+ unless ShopifyCLI::IdentityAuth.authenticated?
9
+ raise ShopifyCLI::Abort,
10
+ ctx.message("core.identity_auth.login_prompt", ShopifyCLI::TOOL_NAME)
11
+ end
12
+ if ShopifyCLI::IdentityAuth.environment_auth_token?
13
+ ctx.puts(ctx.message("core.identity_auth.token_authentication",
14
+ ShopifyCLI::Constants::EnvironmentVariables::AUTH_TOKEN))
15
+ end
10
16
  end
11
17
  end
12
18
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyCLI
4
+ module Theme
5
+ module DevServer
6
+ class CdnFonts
7
+ FONTS_PATH = "/fonts"
8
+ FONTS_CDN = "https://fonts.shopifycdn.com"
9
+ FONTS_REGEX = %r{#{FONTS_CDN}}
10
+
11
+ def initialize(app, theme:)
12
+ @app = app
13
+ @theme = theme
14
+ end
15
+
16
+ def call(env)
17
+ path = env["PATH_INFO"]
18
+
19
+ # Serve from fonts CDN
20
+ return serve_font(env) if path.start_with?(FONTS_PATH)
21
+
22
+ # Proxy the request, and replace the URLs in the response
23
+ status, headers, body = @app.call(env)
24
+ body = replace_font_urls(body)
25
+ [status, headers, body]
26
+ end
27
+
28
+ private
29
+
30
+ def serve_font(env)
31
+ parameters = %w(PATH_INFO QUERY_STRING REQUEST_METHOD rack.input)
32
+ path, query, method, body_stream = *env.slice(*parameters).values
33
+
34
+ uri = fonts_cdn_uri(path, query)
35
+
36
+ response = Net::HTTP.start(uri.host, 443, use_ssl: true) do |http|
37
+ req_class = Net::HTTP.const_get(method.capitalize)
38
+ req = req_class.new(uri)
39
+ req.initialize_http_header(fonts_cdn_headers)
40
+ req.body_stream = body_stream
41
+ http.request(req)
42
+ end
43
+
44
+ [
45
+ response.code.to_s,
46
+ {
47
+ "Content-Type" => response.content_type,
48
+ "Content-Length" => response.content_length.to_s,
49
+ },
50
+ [response.body],
51
+ ]
52
+ end
53
+
54
+ def fonts_cdn_headers
55
+ {
56
+ "Referer" => "https://#{@theme.shop}",
57
+ "Transfer-Encoding" => "chunked",
58
+ }
59
+ end
60
+
61
+ def fonts_cdn_uri(path, query)
62
+ uri = URI.join("#{FONTS_CDN}/", path.gsub(%r{^#{FONTS_PATH}\/}, ""))
63
+ uri.query = query.split("&").last
64
+ uri
65
+ end
66
+
67
+ def replace_font_urls(body)
68
+ [body.join.gsub(FONTS_REGEX, FONTS_PATH)]
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -17,19 +17,35 @@
17
17
 
18
18
  connect();
19
19
 
20
+ function isRefreshRequired(files) {
21
+ return files.some((file) => !isCssFile(file) && !isSectionFile(file));
22
+ }
23
+
24
+ function refreshFile(file) {
25
+ if (isCssFile(file)) {
26
+ reloadCssFile(file);
27
+ return;
28
+ }
29
+
30
+ if (isSectionFile(file)) {
31
+ reloadSection(file);
32
+ return;
33
+ }
34
+ }
35
+
36
+ function refreshPage() {
37
+ console.log('[HotReload] Refreshing entire page');
38
+ window.location.reload();
39
+ }
40
+
20
41
  function handleUpdate(message) {
21
42
  var data = JSON.parse(message.data);
43
+ var modifiedFiles = data.modified;
22
44
 
23
- // Assume only one file is modified at a time
24
- var modified = data.modified[0];
25
-
26
- if (isCssFile(modified)) {
27
- reloadCssFile(modified)
28
- } else if (isSectionFile(modified)) {
29
- reloadSection(modified);
45
+ if (isRefreshRequired(modifiedFiles)) {
46
+ refreshPage();
30
47
  } else {
31
- console.log(`[HotReload] Refreshing entire page`);
32
- window.location.reload();
48
+ modifiedFiles.forEach(refreshFile);
33
49
  }
34
50
  }
35
51
 
@@ -4,7 +4,7 @@ module ShopifyCLI
4
4
  module Theme
5
5
  module DevServer
6
6
  class LocalAssets
7
- ASSET_REGEX = %r{//cdn.shopify.com/s/.*?/(assets/.+\.(?:css|js))}
7
+ ASSET_REGEX = %r{//cdn\.shopify\.com/s/.+?/(assets/.+?\.(?:css|js))}
8
8
 
9
9
  class FileBody
10
10
  def initialize(path)