shopify-cli 2.9.0 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
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