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
data/ext/javy/javy.rb ADDED
@@ -0,0 +1,205 @@
1
+ require "rbconfig"
2
+ require "open-uri"
3
+ require "zlib"
4
+ require "open3"
5
+ require "digest/sha2"
6
+
7
+ module Javy
8
+ ROOT = __dir__
9
+ BIN_FOLDER = File.join(ROOT, "bin")
10
+ HASH_FOLDER = File.join(ROOT, "hashes")
11
+ VERSION = File.read(File.join(ROOT, "version")).strip
12
+ TARGET = File.join(BIN_FOLDER, "javy-#{VERSION}")
13
+
14
+ class << self
15
+ def install
16
+ ShopifyCLI::Result
17
+ .wrap { Installer.call(target: target, platform: platform, version: VERSION) }
18
+ .call
19
+ end
20
+
21
+ def build(source:, dest: nil)
22
+ optional_args = []
23
+ optional_args += ["-o", dest] unless dest.nil?
24
+
25
+ ShopifyCLI::Result
26
+ .wrap { ensure_installed }
27
+ .call
28
+ .then { exec(source, *optional_args) }
29
+ end
30
+
31
+ private
32
+
33
+ def exec(*args, **kwargs)
34
+ out_and_err, stat = CLI::Kit::System.capture2e(target, *args, **kwargs)
35
+ raise ExecutionError, out_and_err unless stat.success?
36
+ true
37
+ end
38
+
39
+ def platform
40
+ Platform.new
41
+ end
42
+
43
+ def target
44
+ platform.format_executable_path(TARGET)
45
+ end
46
+
47
+ def ensure_installed
48
+ delete_outdated_installations
49
+ install.unwrap { |e| raise e } unless Installer.installed?(target: target)
50
+ true
51
+ end
52
+
53
+ def delete_outdated_installations
54
+ installed_binaries
55
+ .reject { |v| v == target }
56
+ .each { |file| File.delete(file) }
57
+ end
58
+
59
+ def installed_binaries
60
+ Dir[File.join(BIN_FOLDER, "javy-*")]
61
+ end
62
+
63
+ module Installer
64
+ def self.call(target:, platform:, version:)
65
+ asset = Asset.new(
66
+ platform: platform,
67
+ version: version,
68
+ owner: "Shopify",
69
+ repository: "javy",
70
+ basename: "javy"
71
+ )
72
+
73
+ downloaded = asset.download(target: target)
74
+ raise InstallationError.asset_not_found(platform: platform, version: version, url: asset.url) unless downloaded
75
+
76
+ true
77
+ end
78
+
79
+ def self.installed?(target:)
80
+ File.executable?(target)
81
+ end
82
+ end
83
+ end
84
+
85
+ class Error < RuntimeError; end
86
+ class ExecutionError < Error; end
87
+
88
+ class InstallationError < Error
89
+ def self.cpu_unsupported
90
+ new("Javy is not supported on this CPU")
91
+ end
92
+
93
+ def self.asset_not_found(platform:, version:, url:)
94
+ new(format(
95
+ "Unable to download javy %{version} for %{os} (%{cpu}) at %{url}",
96
+ version: version,
97
+ os: platform.os,
98
+ cpu: platform.cpu,
99
+ url: url
100
+ ))
101
+ end
102
+
103
+ def self.invalid_binary
104
+ new("Invalid Javy binary downloaded.")
105
+ end
106
+ end
107
+
108
+ Asset = Struct.new(:platform, :version, :owner, :repository, :basename, keyword_init: true) do
109
+ def download(target:)
110
+ FileUtils.mkdir_p(BIN_FOLDER)
111
+
112
+ source_file = url.open
113
+ validate_sha!(source_file)
114
+ source_file.seek(0)
115
+
116
+ Dir.chdir(File.dirname(target)) do
117
+ File.open(File.basename(target), "wb") do |target_file|
118
+ decompress(source_file, target_file)
119
+ end
120
+
121
+ File.chmod(0755, target)
122
+ end
123
+
124
+ true
125
+ rescue OpenURI::HTTPError
126
+ false
127
+ end
128
+
129
+ def url
130
+ URI.parse(format(
131
+ "https://github.com/%{owner}/%{repository}/releases/download/%{version}/%{filename}",
132
+ owner: owner,
133
+ repository: repository,
134
+ version: version,
135
+ filename: filename
136
+ ))
137
+ end
138
+
139
+ def filename
140
+ format(
141
+ "%{basename}-%{cpu}-%{os}-%{version}.gz",
142
+ basename: basename,
143
+ cpu: platform.cpu,
144
+ os: platform.os,
145
+ version: version
146
+ )
147
+ end
148
+
149
+ private
150
+
151
+ def decompress(source, target)
152
+ zlib = Zlib::GzipReader.new(source)
153
+ target << zlib.read
154
+ ensure
155
+ zlib.close
156
+ end
157
+
158
+ def validate_sha!(source)
159
+ generated_hash = Digest::SHA256.hexdigest(source.read).strip
160
+ expected_hash = File.read(File.join(HASH_FOLDER, "#{filename}.sha256")).strip
161
+ raise InstallationError.invalid_binary unless generated_hash == expected_hash
162
+ end
163
+ end
164
+
165
+ Platform = Struct.new(:ruby_config) do
166
+ def initialize(ruby_config = RbConfig::CONFIG)
167
+ super(ruby_config)
168
+ end
169
+
170
+ def to_s
171
+ format("%{cpu}-%{os}", cpu: cpu, os: os)
172
+ end
173
+
174
+ def os
175
+ case ruby_config.fetch("host_os")
176
+ when /linux/
177
+ "linux"
178
+ when /darwin/
179
+ "macos"
180
+ else
181
+ "windows"
182
+ end
183
+ end
184
+
185
+ def cpu
186
+ case ruby_config.fetch("host_cpu")
187
+ when "x64", "x86_64"
188
+ "x86_64"
189
+ when "arm"
190
+ "arm"
191
+ else
192
+ raise InstallationError.cpu_unsupported
193
+ end
194
+ end
195
+
196
+ def format_executable_path(path)
197
+ case os
198
+ when "windows"
199
+ File.extname(path) != ".exe" ? path + ".exe" : path
200
+ else
201
+ path
202
+ end
203
+ end
204
+ end
205
+ end
data/ext/javy/version ADDED
@@ -0,0 +1 @@
1
+ v0.1.0
@@ -12,7 +12,7 @@ module Extension
12
12
  register_messages(Extension::Messages::MessageLoading.load)
13
13
  end
14
14
 
15
- class Command < ShopifyCLI::ProjectCommands
15
+ class Command < ShopifyCLI::Command::ProjectCommand
16
16
  hidden_feature
17
17
  autoload :ExtensionCommand, Project.project_filepath("commands/extension_command")
18
18
 
@@ -42,8 +42,10 @@ module Extension
42
42
  autoload :GetExtensions, Project.project_filepath("tasks/get_extensions")
43
43
  autoload :GetProduct, Project.project_filepath("tasks/get_product")
44
44
  autoload :RunExtensionCommand, Project.project_filepath("tasks/run_extension_command")
45
- autoload :LoadServerConfig, Project.project_filepath("tasks/load_server_config")
45
+ autoload :MergeServerConfig, Project.project_filepath("tasks/merge_server_config")
46
46
  autoload :FindPackageFromJson, Project.project_filepath("tasks/find_package_from_json.rb")
47
+ autoload :EnsureResourceUrl, Project.project_filepath("tasks/ensure_resource_url.rb")
48
+ autoload :ConvertServerConfig, Project.project_filepath("tasks/convert_server_config")
47
49
 
48
50
  module Converters
49
51
  autoload :RegistrationConverter, Project.project_filepath("tasks/converters/registration_converter")
@@ -51,7 +53,6 @@ module Extension
51
53
  autoload :ValidationErrorConverter, Project.project_filepath("tasks/converters/validation_error_converter")
52
54
  autoload :AppConverter, Project.project_filepath("tasks/converters/app_converter")
53
55
  autoload :ProductConverter, Project.project_filepath("tasks/converters/product_converter")
54
- autoload :ServerConfigConverter, Project.project_filepath("tasks/converters/server_config_converter")
55
56
  end
56
57
  end
57
58
 
@@ -94,9 +95,11 @@ module Extension
94
95
 
95
96
  module ServerConfig
96
97
  autoload :Base, Project.project_filepath("models/server_config/base")
98
+ autoload :App, Project.project_filepath("models/server_config/app")
97
99
  autoload :Development, Project.project_filepath("models/server_config/development")
98
100
  autoload :DevelopmentEntries, Project.project_filepath("models/server_config/development_entries")
99
101
  autoload :DevelopmentRenderer, Project.project_filepath("models/server_config/development_renderer")
102
+ autoload :DevelopmentResource, Project.project_filepath("models/server_config/development_resource")
100
103
  autoload :Extension, Project.project_filepath("models/server_config/extension")
101
104
  autoload :Root, Project.project_filepath("models/server_config/root")
102
105
  autoload :User, Project.project_filepath("models/server_config/user")
@@ -24,20 +24,16 @@ module Extension
24
24
  private
25
25
 
26
26
  def run_new_flow(project)
27
- Tasks::RunExtensionCommand.new(
27
+ output = Tasks::RunExtensionCommand.new(
28
28
  type: project.specification_identifier.downcase,
29
29
  command: "build",
30
30
  config_file_name: specification_handler.server_config_file,
31
+ context: @ctx,
31
32
  ).call
32
33
 
33
- @ctx.puts(@ctx.message("build.build_success_message"))
34
+ @ctx.puts(output)
34
35
  rescue => error
35
- if error.message.include?("no such file or directory")
36
- @ctx.abort(@ctx.message("build.directory_not_found"))
37
- else
38
- @ctx.debug(error)
39
- @ctx.abort(@ctx.message("build.build_failure_message"))
40
- end
36
+ raise ShopifyCLI::Abort, error.message
41
37
  end
42
38
 
43
39
  def run_legacy_flow
@@ -2,11 +2,7 @@
2
2
 
3
3
  module Extension
4
4
  class Command
5
- class Create < ShopifyCLI::SubCommand
6
- DEVELOPMENT_SERVER_SUPPORTED_TYPES = [
7
- "checkout_ui_extension",
8
- ]
9
-
5
+ class Create < ShopifyCLI::Command::SubCommand
10
6
  prerequisite_task :ensure_authenticated
11
7
 
12
8
  options do |parser, flags|
@@ -66,6 +62,7 @@ module Extension
66
62
  @ctx.chdir(form.directory_name)
67
63
  write_env_file(form)
68
64
  rescue => error
65
+ @ctx.debug(error)
69
66
  raise error
70
67
  end
71
68
 
@@ -3,7 +3,7 @@ require "shopify_cli"
3
3
 
4
4
  module Extension
5
5
  class Command
6
- class ExtensionCommand < ShopifyCLI::SubCommand
6
+ class ExtensionCommand < ShopifyCLI::Command::SubCommand
7
7
  def project
8
8
  @project ||= ExtensionProject.current
9
9
  end
@@ -63,7 +63,9 @@ module Extension
63
63
  ShopifyCLI::Tasks::EnsureDevStore.call(context) if required_fields.include?(:shop)
64
64
 
65
65
  project = ExtensionProject.current
66
- ensure_resource_resource_url! if specification_handler.supplies_resource_url? && !supports_development_server?
66
+ if resource_url_required?
67
+ Tasks::EnsureResourceUrl.call(context: context, specification_handler: specification_handler)
68
+ end
67
69
 
68
70
  return if required_fields.all? do |field|
69
71
  value = project.env.public_send(field)
@@ -73,6 +75,10 @@ module Extension
73
75
  context.abort(context.message("serve.serve_missing_information"))
74
76
  end
75
77
 
78
+ def resource_url_required?
79
+ specification_handler.supplies_resource_url? && resource_url.nil?
80
+ end
81
+
76
82
  def options
77
83
  project = ExtensionProject.current
78
84
 
@@ -88,28 +94,6 @@ module Extension
88
94
  end
89
95
  end
90
96
 
91
- def ensure_resource_resource_url!
92
- project = ExtensionProject.current(force_reload: true)
93
-
94
- ShopifyCLI::Result
95
- .wrap(project.resource_url)
96
- .rescue { specification_handler.build_resource_url(shop: project.env.shop, context: context) }
97
- .then(&method(:persist_resource_url))
98
- .unwrap do |nil_or_exception|
99
- case nil_or_exception
100
- when nil
101
- context.warn(context.message("warnings.resource_url_auto_generation_failed", project.env.shop))
102
- else
103
- context.abort(nil_or_exception)
104
- end
105
- end
106
- end
107
-
108
- def persist_resource_url(resource_url)
109
- ExtensionProject.update_env_file(context: context, resource_url: resource_url)
110
- resource_url
111
- end
112
-
113
97
  def new_serve_flow
114
98
  Tasks::RunExtensionCommand.new(
115
99
  type: specification_handler.specification.identifier,
@@ -117,6 +101,8 @@ module Extension
117
101
  context: context,
118
102
  port: port,
119
103
  config_file_name: specification_handler.server_config_file,
104
+ resource_url: resource_url,
105
+ tunnel_url: tunnel_url
120
106
  ).call
121
107
  end
122
108
 
@@ -4,10 +4,6 @@ module Extension
4
4
  class AskTemplate
5
5
  include ShopifyCLI::MethodObject
6
6
 
7
- TEMPLATE_REQUIRED_TYPES = [
8
- "checkout_ui_extension",
9
- ]
10
-
11
7
  property! :ctx
12
8
  property :template, accepts: Models::ServerConfig::Development::VALID_TEMPLATES
13
9
  property :prompt,
@@ -25,7 +21,7 @@ module Extension
25
21
  def template_required?(project_details)
26
22
  return false unless extension_server_beta?
27
23
  type = project_details&.type&.identifier
28
- TEMPLATE_REQUIRED_TYPES.include?(type.downcase)
24
+ Models::DevelopmentServerRequirements::SUPPORTED_EXTENSION_TYPES.include?(type.downcase)
29
25
  end
30
26
 
31
27
  def extension_server_beta?
@@ -68,8 +68,6 @@ module Extension
68
68
  HELP
69
69
  frame_title: "Building extension with: %s…",
70
70
  build_failure_message: "Failed to build extension code.",
71
- build_success_message: "Build was successful!",
72
- directory_not_found: "Build directory not found.",
73
71
  },
74
72
  register: {
75
73
  help: <<~HELP,
@@ -33,8 +33,8 @@ module Extension
33
33
  end
34
34
 
35
35
  def build(server_config)
36
- _, error, status = CLI::Kit::System.capture3(executable, "build", "-", stdin_data: server_config.to_yaml)
37
- return if status.success?
36
+ output, error, status = CLI::Kit::System.capture3(executable, "build", "-", stdin_data: server_config.to_yaml)
37
+ return output if status.success?
38
38
  raise DevelopmentServerError, error
39
39
  end
40
40
 
@@ -6,11 +6,10 @@ module Extension
6
6
  class DevelopmentServerRequirements
7
7
  SUPPORTED_EXTENSION_TYPES = [
8
8
  "checkout_ui_extension",
9
+ "checkout_post_purchase",
10
+ "product_subscription",
9
11
  ]
10
12
 
11
- UNIX_NAME = "shopify-extensions"
12
- WINDOWS_NAME = "shopify-extensions.exe"
13
-
14
13
  class << self
15
14
  def supported?(type)
16
15
  binary_installed? && type_supported?(type) && beta_enabled?
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class App < Base
7
+ include SmartProperties
8
+
9
+ property! :api_key, accepts: String
10
+ end
11
+ end
12
+ end
13
+ end
@@ -12,11 +12,12 @@ module Extension
12
12
 
13
13
  CURRENT_DIRECTORY = "."
14
14
 
15
- property :root_dir, accepts: String, default: CURRENT_DIRECTORY
15
+ property :root_dir, accepts: String, default: CURRENT_DIRECTORY
16
16
  property! :build_dir, accepts: String, default: "build"
17
- property :template, accepts: VALID_TEMPLATES
18
- property :renderer, accepts: ServerConfig::DevelopmentRenderer
19
- property :entries, accepts: ServerConfig::DevelopmentEntries
17
+ property :template, accepts: VALID_TEMPLATES
18
+ property :renderer, accepts: ServerConfig::DevelopmentRenderer
19
+ property :entries, accepts: ServerConfig::DevelopmentEntries
20
+ property :resource, accepts: ServerConfig::DevelopmentResource
20
21
  end
21
22
  end
22
23
  end
@@ -16,7 +16,7 @@ module Extension
16
16
 
17
17
  def self.find(type)
18
18
  case type.downcase
19
- when "admin_ui_extension"
19
+ when "product_subscription"
20
20
  new(name: "@shopify/admin-ui-extensions")
21
21
  when "checkout_ui_extension"
22
22
  new(name: "@shopify/checkout-ui-extensions")
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class DevelopmentResource < Base
7
+ include SmartProperties
8
+
9
+ property! :url, accepts: String
10
+ end
11
+ end
12
+ end
13
+ end
@@ -10,7 +10,9 @@ module Extension
10
10
  property! :type, accepts: String
11
11
  property! :user, accepts: ServerConfig::User
12
12
  property! :development, accepts: ServerConfig::Development
13
- property :extension_points, accepts: Array
13
+ property :extension_points, accepts: Array
14
+ property :version, accepts: String
15
+ property :title, accepts: String
14
16
 
15
17
  def self.build(uuid: "", template:, type:, root_dir:)
16
18
  renderer = ServerConfig::DevelopmentRenderer.find(type)
@@ -6,8 +6,11 @@ module Extension
6
6
  class Root < Base
7
7
  include SmartProperties
8
8
 
9
- property! :port, accepts: Integer, default: 39351
9
+ property :app, accepts: ServerConfig::App
10
10
  property! :extensions, accepts: Array, default: -> { [] }
11
+ property! :port, accepts: Integer, default: 39351
12
+ property :public_url, accepts: String
13
+ property :store, accepts: String
11
14
 
12
15
  def to_yaml
13
16
  to_h.to_yaml.gsub("---\n", "")
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Tasks
6
+ class ConvertServerConfig
7
+ include SmartProperties
8
+
9
+ property! :api_key, accepts: String
10
+ property! :context, accepts: ShopifyCLI::Context
11
+ property! :hash, accepts: Hash
12
+ property! :registration_uuid, accepts: String
13
+ property :resource_url, accepts: String
14
+ property! :store, accepts: String
15
+ property! :title, accepts: String
16
+ property :tunnel_url, accepts: String
17
+ property! :type, accepts: String
18
+
19
+ def self.call(*args)
20
+ new(*args).call
21
+ end
22
+
23
+ def call
24
+ context.abort(context.message("tasks.errors.parse_error")) if hash.nil?
25
+
26
+ renderer = Models::ServerConfig::DevelopmentRenderer.find(type)
27
+
28
+ extension = Models::ServerConfig::Extension.new(
29
+ uuid: registration_uuid,
30
+ type: type.upcase,
31
+ user: Models::ServerConfig::User.new,
32
+ development: Models::ServerConfig::Development.new(
33
+ build_dir: hash.dig("development", "build_dir"),
34
+ renderer: renderer,
35
+ entries: Models::ServerConfig::DevelopmentEntries.new(
36
+ main: hash.dig("development", "entries", "main")
37
+ )
38
+ ),
39
+ extension_points: hash.dig("extension_points"),
40
+ version: version(renderer.name, context),
41
+ title: title
42
+ )
43
+
44
+ unless resource_url.nil?
45
+ extension.development.resource = Models::ServerConfig::DevelopmentResource.new(url: resource_url)
46
+ end
47
+ server_config = Models::ServerConfig::Root.new(
48
+ extensions: [extension],
49
+ public_url: tunnel_url,
50
+ store: store
51
+ )
52
+
53
+ unless api_key.nil?
54
+ server_config.app = Models::ServerConfig::App.new(api_key: api_key)
55
+ end
56
+
57
+ server_config
58
+ end
59
+
60
+ def version(renderer, context)
61
+ Tasks::FindPackageFromJson.call(renderer, context: context).version
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Tasks
6
+ class EnsureResourceUrl < ShopifyCLI::Task
7
+ include SmartProperties
8
+
9
+ property! :context, accepts: ShopifyCLI::Context
10
+ property! :specification_handler, accepts: Extension::Models::SpecificationHandlers::Default
11
+
12
+ def self.call(*args)
13
+ new(*args).call
14
+ end
15
+
16
+ def call
17
+ project = ExtensionProject.current(force_reload: true)
18
+
19
+ ShopifyCLI::Result
20
+ .wrap(project.resource_url)
21
+ .rescue { specification_handler.build_resource_url(shop: project.env.shop, context: context) }
22
+ .then(&method(:persist_resource_url))
23
+ .unwrap do |nil_or_exception|
24
+ case nil_or_exception
25
+ when nil
26
+ context.warn(context.message("warnings.resource_url_auto_generation_failed", project.env.shop))
27
+ else
28
+ context.abort(nil_or_exception)
29
+ end
30
+ end
31
+ end
32
+
33
+ def persist_resource_url(resource_url)
34
+ ExtensionProject.update_env_file(context: context, resource_url: resource_url)
35
+ resource_url
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+ require "yaml"
4
+
5
+ module Extension
6
+ module Tasks
7
+ class MergeServerConfig < ShopifyCLI::Task
8
+ class << self
9
+ def call(context:, file_name:, resource_url:, tunnel_url:, type:)
10
+ config = YAML.load_file(file_name)
11
+ project = ExtensionProject.current
12
+ Tasks::ConvertServerConfig.call(
13
+ api_key: project.env.api_key,
14
+ context: context,
15
+ hash: config,
16
+ registration_uuid: project.registration_uuid,
17
+ resource_url: resource_url || project.resource_url,
18
+ store: project.env.shop || "",
19
+ title: project.title,
20
+ tunnel_url: tunnel_url,
21
+ type: type
22
+ )
23
+ rescue Psych::SyntaxError => e
24
+ raise(
25
+ ShopifyCLI::Abort,
26
+ ShopifyCLI::Context.message("core.yaml.error.invalid", file_name, e.message)
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end