shopify-cli 2.9.0 → 2.11.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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.yaml +117 -0
  3. data/.github/ISSUE_TEMPLATE/enhancement.yaml +38 -0
  4. data/.github/ISSUE_TEMPLATE/feature.yaml +47 -0
  5. data/.github/ISSUE_TEMPLATE.md +18 -0
  6. data/CHANGELOG.md +38 -5
  7. data/Gemfile.lock +1 -1
  8. data/dev.yml +3 -0
  9. data/lib/project_types/extension/commands/build.rb +3 -0
  10. data/lib/project_types/extension/commands/check.rb +3 -0
  11. data/lib/project_types/extension/commands/create.rb +3 -0
  12. data/lib/project_types/extension/commands/push.rb +3 -0
  13. data/lib/project_types/extension/commands/serve.rb +3 -0
  14. data/lib/project_types/extension/models/specification_handlers/default.rb +1 -1
  15. data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
  16. data/lib/project_types/script/cli.rb +5 -0
  17. data/lib/project_types/script/commands/connect.rb +3 -1
  18. data/lib/project_types/script/commands/create.rb +2 -0
  19. data/lib/project_types/script/commands/push.rb +6 -0
  20. data/lib/project_types/script/config/extension_points.yml +12 -0
  21. data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
  22. data/lib/project_types/script/graphql/module_upload_url_generate.graphql +5 -1
  23. data/lib/project_types/script/layers/application/build_script.rb +6 -3
  24. data/lib/project_types/script/layers/application/project_dependencies.rb +1 -1
  25. data/lib/project_types/script/layers/application/push_script.rb +38 -30
  26. data/lib/project_types/script/layers/domain/errors.rb +10 -3
  27. data/lib/project_types/script/layers/domain/extension_point.rb +2 -2
  28. data/lib/project_types/script/layers/domain/push_package.rb +0 -3
  29. data/lib/project_types/script/layers/domain/script_config.rb +6 -4
  30. data/lib/project_types/script/layers/domain/script_project.rb +1 -0
  31. data/lib/project_types/script/layers/infrastructure/errors.rb +47 -24
  32. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +2 -12
  33. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +1 -0
  34. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -0
  35. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +2 -12
  36. data/lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb +15 -0
  37. data/lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb +36 -0
  38. data/lib/project_types/script/layers/infrastructure/metadata_repository.rb +18 -0
  39. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +7 -8
  40. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +45 -54
  41. data/lib/project_types/script/layers/infrastructure/script_service.rb +35 -12
  42. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +22 -9
  43. data/lib/project_types/script/loaders/project.rb +2 -1
  44. data/lib/project_types/script/messages/messages.rb +94 -88
  45. data/lib/project_types/script/ui/error_handler.rb +75 -38
  46. data/lib/project_types/theme/commands/check.rb +3 -0
  47. data/lib/project_types/theme/commands/delete.rb +3 -0
  48. data/lib/project_types/theme/commands/init.rb +3 -0
  49. data/lib/project_types/theme/commands/language_server.rb +3 -0
  50. data/lib/project_types/theme/commands/package.rb +3 -0
  51. data/lib/project_types/theme/commands/publish.rb +3 -0
  52. data/lib/project_types/theme/commands/pull.rb +12 -1
  53. data/lib/project_types/theme/commands/push.rb +12 -1
  54. data/lib/project_types/theme/commands/serve.rb +3 -0
  55. data/lib/project_types/theme/messages/messages.rb +4 -0
  56. data/lib/shopify_cli/command/sub_command.rb +2 -0
  57. data/lib/shopify_cli/command.rb +66 -0
  58. data/lib/shopify_cli/commands/app/create/node.rb +3 -0
  59. data/lib/shopify_cli/commands/app/create/rails.rb +3 -0
  60. data/lib/shopify_cli/commands/app/create.rb +3 -0
  61. data/lib/shopify_cli/commands/app/deploy.rb +3 -0
  62. data/lib/shopify_cli/commands/app/serve.rb +3 -0
  63. data/lib/shopify_cli/commands/login.rb +4 -10
  64. data/lib/shopify_cli/constants.rb +18 -2
  65. data/lib/shopify_cli/core/executor.rb +4 -4
  66. data/lib/shopify_cli/environment.rb +61 -16
  67. data/lib/shopify_cli/exception_reporter.rb +9 -0
  68. data/lib/shopify_cli/github/issue_url_generator.rb +19 -8
  69. data/lib/shopify_cli/identity_auth/env_auth_token.rb +34 -0
  70. data/lib/shopify_cli/identity_auth.rb +36 -18
  71. data/lib/shopify_cli/messages/messages.rb +2 -2
  72. data/lib/shopify_cli/method_object.rb +21 -9
  73. data/lib/shopify_cli/partners_api.rb +7 -2
  74. data/lib/shopify_cli/result.rb +61 -59
  75. data/lib/shopify_cli/services/app/create/rails_service.rb +37 -13
  76. data/lib/shopify_cli/task.rb +5 -3
  77. data/lib/shopify_cli/theme/file.rb +2 -2
  78. data/lib/shopify_cli/theme/filter/path_matcher.rb +38 -0
  79. data/lib/shopify_cli/theme/ignore_filter.rb +14 -18
  80. data/lib/shopify_cli/theme/include_filter.rb +65 -0
  81. data/lib/shopify_cli/theme/syncer.rb +17 -2
  82. data/lib/shopify_cli/utilities.rb +7 -0
  83. data/lib/shopify_cli/version.rb +1 -1
  84. data/lib/shopify_cli.rb +3 -1
  85. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +11 -6
  86. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +5 -1
  87. data/vendor/deps/cli-ui/lib/cli/ui/os.rb +6 -4
  88. data/vendor/deps/ruby2_keywords/LICENSE +22 -0
  89. data/vendor/deps/ruby2_keywords/README.md +67 -0
  90. data/vendor/deps/ruby2_keywords/Rakefile +54 -0
  91. data/vendor/deps/ruby2_keywords/lib/ruby2_keywords.rb +57 -0
  92. data/vendor/deps/ruby2_keywords/ruby2_keywords.gemspec +18 -0
  93. data/vendor/deps/ruby2_keywords/test/test_keyword.rb +41 -0
  94. data/vendor/lib/semantic/version.rb +0 -1
  95. metadata +18 -3
  96. data/lib/project_types/rails/commands/create.rb +0 -210
@@ -10,6 +10,7 @@ module Script
10
10
  property :initial_directory, accepts: String
11
11
 
12
12
  MUTABLE_ENV_VALUES = %i(uuid)
13
+ INPUT_QUERY_PATH = "input.graphql"
13
14
 
14
15
  def create_project_directory
15
16
  raise Infrastructure::Errors::ScriptProjectAlreadyExistsError, directory if ctx.dir_exist?(directory)
@@ -38,13 +39,7 @@ module Script
38
39
  language: language
39
40
  )
40
41
 
41
- Domain::ScriptProject.new(
42
- id: ctx.root,
43
- env: project.env,
44
- script_name: script_name,
45
- extension_point_type: extension_point_type,
46
- language: language
47
- )
42
+ build_script_project(script_config: nil)
48
43
  end
49
44
 
50
45
  def get
@@ -56,7 +51,8 @@ module Script
56
51
  script_name: script_name,
57
52
  extension_point_type: extension_point_type,
58
53
  language: language,
59
- script_config: script_config_repository.get!
54
+ script_config: script_config_repository.get!,
55
+ input_query: read_input_query,
60
56
  )
61
57
  end
62
58
 
@@ -68,14 +64,7 @@ module Script
68
64
  end
69
65
  end
70
66
 
71
- Domain::ScriptProject.new(
72
- id: ctx.root,
73
- env: project.env,
74
- script_name: script_name,
75
- extension_point_type: extension_point_type,
76
- language: language,
77
- script_config: script_config_repository.get!,
78
- )
67
+ build_script_project
79
68
  end
80
69
 
81
70
  def create_env(api_key:, secret:, uuid:)
@@ -87,19 +76,19 @@ module Script
87
76
  }
88
77
  ).write(ctx)
89
78
 
90
- Domain::ScriptProject.new(
91
- id: ctx.root,
92
- env: project.env,
93
- script_name: script_name,
94
- extension_point_type: extension_point_type,
95
- language: language,
96
- script_config: script_config_repository.get!,
97
- )
79
+ build_script_project
98
80
  end
99
81
 
100
82
  def update_script_config(title:)
101
83
  script_config = script_config_repository.update!(title: title)
84
+ build_script_project(script_config: script_config)
85
+ end
86
+
87
+ private
102
88
 
89
+ def build_script_project(
90
+ script_config: script_config_repository.get!
91
+ )
103
92
  Domain::ScriptProject.new(
104
93
  id: ctx.root,
105
94
  env: project.env,
@@ -110,8 +99,6 @@ module Script
110
99
  )
111
100
  end
112
101
 
113
- private
114
-
115
102
  def change_directory(directory:)
116
103
  ctx.chdir(directory)
117
104
  end
@@ -160,16 +147,23 @@ module Script
160
147
 
161
148
  def script_config_repository
162
149
  @script_config_repository ||= begin
150
+ script_config_yml_repo = ScriptConfigYmlRepository.new(ctx: ctx)
163
151
  supported_repos = [
164
- ScriptConfigYmlRepository.new(ctx: ctx),
152
+ script_config_yml_repo,
165
153
  ScriptJsonRepository.new(ctx: ctx),
166
154
  ]
167
155
  repo = supported_repos.find(&:active?)
168
- raise Infrastructure::Errors::NoScriptConfigYmlFileError if repo.nil?
156
+ if repo.nil?
157
+ raise Infrastructure::Errors::NoScriptConfigFileError, script_config_yml_repo.filename
158
+ end
169
159
  repo
170
160
  end
171
161
  end
172
162
 
163
+ def read_input_query
164
+ ctx.read(INPUT_QUERY_PATH) if ctx.file_exist?(INPUT_QUERY_PATH)
165
+ end
166
+
173
167
  class ScriptConfigRepository
174
168
  include SmartProperties
175
169
  property! :ctx, accepts: ShopifyCLI::Context
@@ -179,7 +173,7 @@ module Script
179
173
  end
180
174
 
181
175
  def get!
182
- raise Infrastructure::Errors::NoScriptConfigFileError unless active?
176
+ raise Infrastructure::Errors::NoScriptConfigFileError, filename unless active?
183
177
 
184
178
  content = ctx.read(filename)
185
179
  hash = file_content_to_hash(content)
@@ -196,6 +190,10 @@ module Script
196
190
  from_h(hash)
197
191
  end
198
192
 
193
+ def filename
194
+ raise NotImplementedError
195
+ end
196
+
199
197
  private
200
198
 
201
199
  def update_hash(hash:, title:)
@@ -204,14 +202,7 @@ module Script
204
202
  end
205
203
 
206
204
  def from_h(hash)
207
- Domain::ScriptConfig.new(content: hash)
208
- rescue Domain::Errors::MissingScriptConfigFieldError => e
209
- raise missing_field_error, e.field
210
- end
211
-
212
- # to be implemented by subclasses
213
- def filename
214
- raise NotImplementedError
205
+ Domain::ScriptConfig.new(content: hash, filename: filename)
215
206
  end
216
207
 
217
208
  def file_content_to_hash(file_content)
@@ -221,26 +212,22 @@ module Script
221
212
  def hash_to_file_content(hash)
222
213
  raise NotImplementedError
223
214
  end
224
-
225
- def missing_field_error
226
- raise NotImplementedError
227
- end
228
215
  end
229
216
 
230
217
  class ScriptConfigYmlRepository < ScriptConfigRepository
231
- private
232
-
233
218
  def filename
234
219
  "script.config.yml"
235
220
  end
236
221
 
222
+ private
223
+
237
224
  def file_content_to_hash(file_content)
238
225
  begin
239
226
  hash = YAML.load(file_content)
240
227
  rescue Psych::SyntaxError
241
- raise Errors::InvalidScriptConfigYmlDefinitionError
228
+ raise parse_error
242
229
  end
243
- raise Errors::InvalidScriptConfigYmlDefinitionError unless hash.is_a?(Hash)
230
+ raise parse_error unless hash.is_a?(Hash)
244
231
  hash
245
232
  end
246
233
 
@@ -248,30 +235,34 @@ module Script
248
235
  YAML.dump(hash)
249
236
  end
250
237
 
251
- def missing_field_error
252
- Errors::MissingScriptConfigYmlFieldError
238
+ def parse_error
239
+ Errors::ScriptConfigParseError.new(filename: filename, serialization_format: "YAML")
253
240
  end
254
241
  end
255
242
 
256
243
  class ScriptJsonRepository < ScriptConfigRepository
257
- private
258
-
259
244
  def filename
260
245
  "script.json"
261
246
  end
262
247
 
248
+ private
249
+
263
250
  def file_content_to_hash(file_content)
264
- JSON.parse(file_content)
265
- rescue JSON::ParserError
266
- raise Errors::InvalidScriptJsonDefinitionError
251
+ begin
252
+ hash = JSON.parse(file_content)
253
+ rescue JSON::ParserError
254
+ raise parse_error
255
+ end
256
+ raise parse_error unless hash.is_a?(Hash)
257
+ hash
267
258
  end
268
259
 
269
260
  def hash_to_file_content(hash)
270
261
  JSON.pretty_generate(hash)
271
262
  end
272
263
 
273
- def missing_field_error
274
- Errors::MissingScriptJsonFieldError
264
+ def parse_error
265
+ Errors::ScriptConfigParseError.new(filename: filename, serialization_format: "JSON")
275
266
  end
276
267
  end
277
268
  end
@@ -19,7 +19,8 @@ module Script
19
19
  metadata:,
20
20
  script_config:,
21
21
  module_upload_url:,
22
- library:
22
+ library:,
23
+ input_query: nil
23
24
  )
24
25
  query_name = "app_script_set"
25
26
  variables = {
@@ -34,11 +35,14 @@ module Script
34
35
  configurationUi: script_config.configuration_ui,
35
36
  configurationDefinition: script_config.configuration&.to_json,
36
37
  moduleUploadUrl: module_upload_url,
37
- library: {
38
- language: library[:language],
39
- version: library[:version],
40
- },
38
+ inputQuery: input_query,
41
39
  }
40
+
41
+ variables[:library] = {
42
+ language: library[:language],
43
+ version: library[:version],
44
+ } if library
45
+
42
46
  resp_hash = make_request(query_name: query_name, variables: variables)
43
47
  user_errors = resp_hash["data"]["appScriptSet"]["userErrors"]
44
48
 
@@ -46,20 +50,37 @@ module Script
46
50
 
47
51
  if user_errors.any? { |e| e["tag"] == "already_exists_error" }
48
52
  raise Errors::ScriptRepushError, uuid
53
+ elsif (errors = user_errors.select { |err| err["tag"] == "configuration_definition_error" }).any?
54
+ raise Errors::ScriptConfigurationDefinitionError.new(
55
+ messages: errors.map { |e| e["message"] },
56
+ filename: script_config.filename,
57
+ )
49
58
  elsif (e = user_errors.any? { |err| err["tag"] == "configuration_definition_syntax_error" })
50
- raise Errors::ScriptConfigSyntaxError
59
+ raise Errors::ScriptConfigSyntaxError, script_config.filename
51
60
  elsif (e = user_errors.find { |err| err["tag"] == "configuration_definition_missing_keys_error" })
52
- raise Errors::ScriptConfigMissingKeysError, e["message"]
61
+ raise Errors::ScriptConfigMissingKeysError.new(
62
+ missing_keys: e["message"],
63
+ filename: script_config.filename,
64
+ )
53
65
  elsif (e = user_errors.find { |err| err["tag"] == "configuration_definition_invalid_value_error" })
54
- raise Errors::ScriptConfigInvalidValueError, e["message"]
66
+ raise Errors::ScriptConfigInvalidValueError.new(
67
+ valid_input_modes: e["message"],
68
+ filename: script_config.filename,
69
+ )
55
70
  elsif (e = user_errors.find do |err|
56
71
  err["tag"] == "configuration_definition_schema_field_missing_keys_error"
57
72
  end)
58
- raise Errors::ScriptConfigFieldsMissingKeysError, e["message"]
73
+ raise Errors::ScriptConfigFieldsMissingKeysError.new(
74
+ missing_keys: e["message"],
75
+ filename: script_config.filename,
76
+ )
59
77
  elsif (e = user_errors.find do |err|
60
78
  err["tag"] == "configuration_definition_schema_field_invalid_value_error"
61
79
  end)
62
- raise Errors::ScriptConfigFieldsInvalidValueError, e["message"]
80
+ raise Errors::ScriptConfigFieldsInvalidValueError.new(
81
+ valid_types: e["message"],
82
+ filename: script_config.filename,
83
+ )
63
84
  elsif user_errors.find { |err| %w(not_use_msgpack_error schema_version_argument_error).include?(err["tag"]) }
64
85
  raise Domain::Errors::MetadataValidationError
65
86
  else
@@ -74,14 +95,16 @@ module Script
74
95
  response["data"]["appScripts"]
75
96
  end
76
97
 
77
- def generate_module_upload_url
98
+ def generate_module_upload_details
78
99
  query_name = "module_upload_url_generate"
79
100
  variables = {}
80
101
  response = make_request(query_name: query_name, variables: variables)
81
102
  user_errors = response["data"]["moduleUploadUrlGenerate"]["userErrors"]
82
103
 
83
104
  raise Errors::GraphqlError, user_errors if user_errors.any?
84
- response["data"]["moduleUploadUrlGenerate"]["url"]
105
+
106
+ data = response["data"]["moduleUploadUrlGenerate"]["details"]
107
+ { url: data["url"], headers: data["headers"], max_size: data["humanizedMaxSize"] }
85
108
  end
86
109
 
87
110
  private
@@ -7,19 +7,32 @@ module Script
7
7
  end
8
8
 
9
9
  def upload(script_content)
10
- @script_service.generate_module_upload_url.tap do |url|
11
- url = URI(url)
10
+ upload_details = @script_service.generate_module_upload_details
11
+ url = URI(upload_details[:url])
12
12
 
13
- https = Net::HTTP.new(url.host, url.port)
14
- https.use_ssl = true
13
+ https = Net::HTTP.new(url.host, url.port)
14
+ https.use_ssl = true
15
15
 
16
- request = Net::HTTP::Put.new(url)
17
- request["Content-Type"] = "application/wasm"
18
- request.body = script_content
16
+ request = Net::HTTP::Put.new(url)
17
+ request["Content-Type"] = "application/wasm"
19
18
 
20
- response = https.request(request)
21
- raise Errors::ScriptUploadError unless response.code == "200"
19
+ upload_details[:headers].each do |header, value|
20
+ request[header] = value
22
21
  end
22
+
23
+ request.body = script_content
24
+
25
+ response = https.request(request)
26
+ raise Errors::ScriptTooLargeError, upload_details[:max_size] if script_too_large?(response)
27
+ raise Errors::ScriptUploadError unless response.code == "200"
28
+
29
+ upload_details[:url]
30
+ end
31
+
32
+ private
33
+
34
+ def script_too_large?(response)
35
+ response.code == "400" && response.body.include?("EntityTooLarge")
23
36
  end
24
37
  end
25
38
  end
@@ -32,7 +32,8 @@ module Script
32
32
  else
33
33
  properties_hash = { api_key: "--api-key", secret: "--api-secret" }
34
34
  missing_options = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
35
- raise ShopifyCLI::Abort, context.message("script.error.missing_push_options", missing_options)
35
+ raise ShopifyCLI::Abort, context.message("script.error.missing_push_options", missing_options,
36
+ ShopifyCli::TOOL_NAME)
36
37
  end
37
38
  end
38
39