shopify-cli 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile +12 -12
  4. data/Rakefile +32 -30
  5. data/bin/load_shopify.rb +6 -6
  6. data/bin/shopify +2 -2
  7. data/ext/shopify-cli/extconf.rb +7 -7
  8. data/lib/docgen/markdown.rb +11 -11
  9. data/lib/{project_types/extension/graphql → graphql}/get_app_by_api_key.graphql +0 -0
  10. data/lib/project_types/extension/cli.rb +52 -45
  11. data/lib/project_types/extension/commands/build.rb +3 -3
  12. data/lib/project_types/extension/commands/create.rb +16 -9
  13. data/lib/project_types/extension/commands/extension_command.rb +8 -5
  14. data/lib/project_types/extension/commands/push.rb +8 -8
  15. data/lib/project_types/extension/commands/register.rb +19 -30
  16. data/lib/project_types/extension/commands/serve.rb +2 -2
  17. data/lib/project_types/extension/commands/tunnel.rb +12 -12
  18. data/lib/project_types/extension/extension_project.rb +4 -4
  19. data/lib/project_types/extension/extension_project_keys.rb +4 -4
  20. data/lib/project_types/extension/features/argo.rb +13 -13
  21. data/lib/project_types/extension/features/argo_config.rb +5 -5
  22. data/lib/project_types/extension/features/argo_dependencies.rb +5 -5
  23. data/lib/project_types/extension/features/argo_setup.rb +2 -2
  24. data/lib/project_types/extension/features/argo_setup_steps.rb +4 -4
  25. data/lib/project_types/extension/forms/create.rb +28 -34
  26. data/lib/project_types/extension/forms/questions/ask_app.rb +53 -0
  27. data/lib/project_types/extension/forms/questions/ask_name.rb +40 -0
  28. data/lib/project_types/extension/forms/questions/ask_type.rb +36 -0
  29. data/lib/project_types/extension/messages/messages.rb +53 -52
  30. data/lib/project_types/extension/models/lazy_specification_handler.rb +12 -0
  31. data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +1 -1
  32. data/lib/project_types/extension/models/specification_handlers/default.rb +2 -2
  33. data/lib/project_types/extension/models/specifications.rb +3 -3
  34. data/lib/project_types/extension/tasks/configure_features.rb +4 -4
  35. data/lib/project_types/extension/tasks/converters/app_converter.rb +6 -6
  36. data/lib/project_types/extension/tasks/converters/registration_converter.rb +6 -6
  37. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +4 -4
  38. data/lib/project_types/extension/tasks/converters/version_converter.rb +7 -7
  39. data/lib/project_types/extension/tasks/create_extension.rb +4 -4
  40. data/lib/project_types/extension/tasks/fetch_specifications.rb +4 -4
  41. data/lib/project_types/extension/tasks/get_app.rb +4 -4
  42. data/lib/project_types/extension/tasks/get_apps.rb +3 -3
  43. data/lib/project_types/extension/tasks/update_draft.rb +4 -4
  44. data/lib/project_types/extension/tasks/user_errors.rb +4 -4
  45. data/lib/project_types/node/cli.rb +19 -19
  46. data/lib/project_types/node/commands/connect.rb +3 -3
  47. data/lib/project_types/node/commands/create.rb +40 -38
  48. data/lib/project_types/node/commands/deploy.rb +4 -4
  49. data/lib/project_types/node/commands/deploy/heroku.rb +24 -24
  50. data/lib/project_types/node/commands/generate.rb +8 -8
  51. data/lib/project_types/node/commands/open.rb +2 -2
  52. data/lib/project_types/node/commands/populate.rb +6 -6
  53. data/lib/project_types/node/commands/populate/customer.rb +5 -5
  54. data/lib/project_types/node/commands/populate/draft_order.rb +5 -5
  55. data/lib/project_types/node/commands/populate/product.rb +5 -5
  56. data/lib/project_types/node/commands/serve.rb +9 -9
  57. data/lib/project_types/node/commands/tunnel.rb +7 -7
  58. data/lib/project_types/node/forms/create.rb +7 -7
  59. data/lib/project_types/node/messages/messages.rb +3 -3
  60. data/lib/project_types/rails/cli.rb +21 -21
  61. data/lib/project_types/rails/commands/connect.rb +3 -3
  62. data/lib/project_types/rails/commands/create.rb +51 -48
  63. data/lib/project_types/rails/commands/deploy.rb +4 -4
  64. data/lib/project_types/rails/commands/deploy/heroku.rb +30 -30
  65. data/lib/project_types/rails/commands/generate.rb +7 -7
  66. data/lib/project_types/rails/commands/generate/webhook.rb +6 -6
  67. data/lib/project_types/rails/commands/open.rb +2 -2
  68. data/lib/project_types/rails/commands/populate.rb +6 -6
  69. data/lib/project_types/rails/commands/populate/customer.rb +5 -5
  70. data/lib/project_types/rails/commands/populate/draft_order.rb +5 -5
  71. data/lib/project_types/rails/commands/populate/product.rb +5 -5
  72. data/lib/project_types/rails/commands/serve.rb +11 -11
  73. data/lib/project_types/rails/commands/tunnel.rb +7 -7
  74. data/lib/project_types/rails/forms/create.rb +23 -23
  75. data/lib/project_types/rails/gem.rb +23 -23
  76. data/lib/project_types/rails/messages/messages.rb +4 -4
  77. data/lib/project_types/rails/ruby.rb +2 -2
  78. data/lib/project_types/script/cli.rb +40 -40
  79. data/lib/project_types/script/commands/create.rb +9 -8
  80. data/lib/project_types/script/commands/disable.rb +3 -3
  81. data/lib/project_types/script/commands/enable.rb +9 -7
  82. data/lib/project_types/script/commands/push.rb +5 -4
  83. data/lib/project_types/script/errors.rb +17 -0
  84. data/lib/project_types/script/forms/create.rb +5 -5
  85. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +2 -0
  86. data/lib/project_types/script/layers/application/build_script.rb +6 -8
  87. data/lib/project_types/script/layers/application/create_script.rb +2 -2
  88. data/lib/project_types/script/layers/application/disable_script.rb +2 -2
  89. data/lib/project_types/script/layers/application/enable_script.rb +2 -2
  90. data/lib/project_types/script/layers/application/project_dependencies.rb +4 -4
  91. data/lib/project_types/script/layers/application/push_script.rb +4 -12
  92. data/lib/project_types/script/layers/domain/push_package.rb +5 -1
  93. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +3 -3
  94. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +10 -10
  95. data/lib/project_types/script/layers/infrastructure/errors.rb +1 -1
  96. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +2 -2
  97. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +12 -17
  98. data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +4 -4
  99. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +1 -1
  100. data/lib/project_types/script/layers/infrastructure/script_service.rb +18 -16
  101. data/lib/project_types/script/messages/messages.rb +14 -8
  102. data/lib/project_types/script/script_project.rb +27 -5
  103. data/lib/project_types/script/ui/error_handler.rb +80 -68
  104. data/lib/project_types/script/ui/printing_spinner.rb +1 -1
  105. data/lib/project_types/script/ui/strict_spinner.rb +1 -1
  106. data/lib/project_types/theme/cli.rb +19 -19
  107. data/lib/project_types/theme/commands/connect.rb +12 -12
  108. data/lib/project_types/theme/commands/create.rb +11 -11
  109. data/lib/project_types/theme/commands/deploy.rb +8 -8
  110. data/lib/project_types/theme/commands/generate.rb +3 -3
  111. data/lib/project_types/theme/commands/generate/env.rb +15 -15
  112. data/lib/project_types/theme/commands/push.rb +15 -15
  113. data/lib/project_types/theme/commands/serve.rb +5 -5
  114. data/lib/project_types/theme/forms/connect.rb +4 -4
  115. data/lib/project_types/theme/forms/create.rb +5 -5
  116. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +22 -22
  117. data/lib/project_types/theme/themekit.rb +15 -15
  118. data/lib/rubygems_plugin.rb +3 -3
  119. data/lib/shopify-cli/admin_api.rb +11 -11
  120. data/lib/shopify-cli/admin_api/populate_resource_command.rb +17 -17
  121. data/lib/shopify-cli/admin_api/schema.rb +3 -3
  122. data/lib/shopify-cli/api.rb +10 -10
  123. data/lib/shopify-cli/command.rb +1 -1
  124. data/lib/shopify-cli/commands.rb +9 -9
  125. data/lib/shopify-cli/commands/config.rb +28 -52
  126. data/lib/shopify-cli/commands/connect.rb +10 -10
  127. data/lib/shopify-cli/commands/create.rb +5 -5
  128. data/lib/shopify-cli/commands/help.rb +6 -6
  129. data/lib/shopify-cli/commands/logout.rb +3 -3
  130. data/lib/shopify-cli/commands/system.rb +32 -32
  131. data/lib/shopify-cli/commands/version.rb +2 -2
  132. data/lib/shopify-cli/context.rb +23 -23
  133. data/lib/shopify-cli/core.rb +4 -4
  134. data/lib/shopify-cli/core/entry_point.rb +5 -5
  135. data/lib/shopify-cli/core/executor.rb +1 -1
  136. data/lib/shopify-cli/core/help_resolver.rb +2 -2
  137. data/lib/shopify-cli/core/monorail.rb +16 -16
  138. data/lib/shopify-cli/db.rb +2 -2
  139. data/lib/shopify-cli/feature.rb +1 -1
  140. data/lib/shopify-cli/form.rb +1 -1
  141. data/lib/shopify-cli/git.rb +17 -17
  142. data/lib/shopify-cli/helpers.rb +1 -1
  143. data/lib/shopify-cli/helpers/haikunator.rb +1 -1
  144. data/lib/shopify-cli/heroku.rb +28 -28
  145. data/lib/shopify-cli/http_request.rb +2 -2
  146. data/lib/shopify-cli/js_deps.rb +12 -12
  147. data/lib/shopify-cli/js_system.rb +5 -5
  148. data/lib/shopify-cli/lazy_delegator.rb +55 -0
  149. data/lib/shopify-cli/messages/messages.rb +4 -14
  150. data/lib/shopify-cli/oauth.rb +25 -25
  151. data/lib/shopify-cli/oauth/servlet.rb +9 -9
  152. data/lib/shopify-cli/options.rb +3 -3
  153. data/lib/shopify-cli/packager.rb +24 -24
  154. data/lib/shopify-cli/partners_api.rb +16 -16
  155. data/lib/shopify-cli/partners_api/organizations.rb +10 -10
  156. data/lib/shopify-cli/process_supervision.rb +7 -7
  157. data/lib/shopify-cli/project.rb +16 -16
  158. data/lib/shopify-cli/project_type.rb +3 -3
  159. data/lib/shopify-cli/resources.rb +1 -1
  160. data/lib/shopify-cli/resources/env_file.rb +9 -9
  161. data/lib/shopify-cli/result.rb +8 -8
  162. data/lib/shopify-cli/shopifolk.rb +6 -9
  163. data/lib/shopify-cli/sub_command.rb +1 -1
  164. data/lib/shopify-cli/task.rb +3 -3
  165. data/lib/shopify-cli/tasks.rb +7 -7
  166. data/lib/shopify-cli/tasks/create_api_client.rb +5 -5
  167. data/lib/shopify-cli/tasks/ensure_dev_store.rb +11 -11
  168. data/lib/shopify-cli/tasks/ensure_env.rb +15 -15
  169. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +4 -4
  170. data/lib/shopify-cli/tasks/select_org_and_shop.rb +19 -19
  171. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +10 -10
  172. data/lib/shopify-cli/transform_data_structure.rb +86 -0
  173. data/lib/shopify-cli/tunnel.rb +30 -30
  174. data/lib/shopify-cli/version.rb +1 -1
  175. data/lib/shopify_cli.rb +56 -54
  176. data/shopify-cli.gemspec +6 -6
  177. data/vendor/gen/template/bin/update-deps +9 -9
  178. metadata +9 -4
  179. data/lib/project_types/extension/forms/register.rb +0 -47
@@ -44,7 +44,7 @@ module Script
44
44
  class PackagesOutdatedError < ScriptProjectError
45
45
  attr_reader :outdated_packages
46
46
  def initialize(outdated_packages)
47
- super("EP packages are outdated and need to be updated: #{outdated_packages.join(', ')}")
47
+ super("EP packages are outdated and need to be updated: #{outdated_packages.join(", ")}")
48
48
  @outdated_packages = outdated_packages
49
49
  end
50
50
  end
@@ -27,8 +27,8 @@ module Script
27
27
 
28
28
  def extension_point_configs
29
29
  @extension_points ||= begin
30
- require 'yaml'
31
- YAML.load_file(Project.project_filepath('config/extension_points.yml'))
30
+ require "yaml"
31
+ YAML.load_file(Project.project_filepath("config/extension_points.yml"))
32
32
  end
33
33
  end
34
34
  end
@@ -7,42 +7,37 @@ module Script
7
7
  include SmartProperties
8
8
  property! :ctx, accepts: ShopifyCli::Context
9
9
 
10
- def create_push_package(
11
- extension_point_type:,
12
- script_name:,
13
- description:,
14
- script_content:,
15
- compiled_type:,
16
- metadata:
17
- )
18
- build_file_path = file_path(script_name, compiled_type)
10
+ def create_push_package(script_project:, script_content:, compiled_type:, metadata:)
11
+ build_file_path = file_path(script_project.script_name, compiled_type)
19
12
  write_to_path(build_file_path, script_content)
20
13
 
21
14
  Domain::PushPackage.new(
22
15
  id: build_file_path,
23
- extension_point_type: extension_point_type,
24
- script_name: script_name,
25
- description: description,
16
+ extension_point_type: script_project.extension_point_type,
17
+ script_name: script_project.script_name,
18
+ description: script_project.description,
26
19
  script_content: script_content,
27
20
  compiled_type: compiled_type,
28
21
  metadata: metadata,
22
+ config_ui: script_project.config_ui,
29
23
  )
30
24
  end
31
25
 
32
- def get_push_package(extension_point_type:, script_name:, description:, compiled_type:, metadata:)
33
- build_file_path = file_path(script_name, compiled_type)
26
+ def get_push_package(script_project:, compiled_type:, metadata:)
27
+ build_file_path = file_path(script_project.script_name, compiled_type)
34
28
  raise Domain::PushPackageNotFoundError unless ctx.file_exist?(build_file_path)
35
29
 
36
30
  script_content = File.read(build_file_path)
37
31
 
38
32
  Domain::PushPackage.new(
39
33
  id: build_file_path,
40
- extension_point_type: extension_point_type,
41
- script_name: script_name,
42
- description: description,
34
+ extension_point_type: script_project.extension_point_type,
35
+ script_name: script_project.script_name,
36
+ description: script_project.description,
43
37
  script_content: script_content,
44
38
  compiled_type: compiled_type,
45
39
  metadata: metadata,
40
+ config_ui: script_project.config_ui,
46
41
  )
47
42
  end
48
43
 
@@ -10,8 +10,8 @@ module Script
10
10
  property! :script_name, accepts: String
11
11
  property! :path_to_project, accepts: String
12
12
 
13
- ORIGIN_BRANCH = 'main'
14
- SAMPLE_PATH = 'default'
13
+ ORIGIN_BRANCH = "main"
14
+ SAMPLE_PATH = "default"
15
15
 
16
16
  def setup_dependencies
17
17
  git_init
@@ -60,8 +60,8 @@ module Script
60
60
  end
61
61
 
62
62
  def set_script_name
63
- config_file = 'Cargo.toml'
64
- upstream_name = "#{extension_point.type.gsub('_', '-')}-default"
63
+ config_file = "Cargo.toml"
64
+ upstream_name = "#{extension_point.type.gsub("_", "-")}-default"
65
65
  contents = File.read(config_file)
66
66
  new_contents = contents.sub(upstream_name, script_name)
67
67
  File.write(config_file, new_contents)
@@ -31,7 +31,7 @@ module Script
31
31
 
32
32
  def metadata
33
33
  unless @ctx.file_exist?(METADATA_FILE)
34
- msg = @ctx.message('script.error.metadata_not_found_cause', METADATA_FILE)
34
+ msg = @ctx.message("script.error.metadata_not_found_cause", METADATA_FILE)
35
35
  raise Domain::Errors::MetadataNotFoundError, msg
36
36
  end
37
37
 
@@ -18,13 +18,15 @@ module Script
18
18
  description: nil,
19
19
  api_key: nil,
20
20
  force: false,
21
- metadata:
21
+ metadata:,
22
+ config_ui:
22
23
  )
23
24
  query_name = "app_script_update_or_create"
24
25
  variables = {
25
26
  extensionPointName: extension_point_type.upcase,
26
27
  title: script_name,
27
28
  description: description,
29
+ configUi: config_ui,
28
30
  sourceCode: Base64.encode64(script_content),
29
31
  language: compiled_type,
30
32
  force: force,
@@ -37,7 +39,7 @@ module Script
37
39
 
38
40
  return resp_hash if user_errors.empty?
39
41
 
40
- if user_errors.any? { |e| e['tag'] == 'already_exists_error' }
42
+ if user_errors.any? { |e| e["tag"] == "already_exists_error" }
41
43
  raise Errors::ScriptRepushError, api_key
42
44
  else
43
45
  raise Errors::ScriptServiceUserError.new(query_name, user_errors.to_s)
@@ -62,11 +64,11 @@ module Script
62
64
 
63
65
  return resp_hash if user_errors.empty?
64
66
 
65
- if user_errors.any? { |e| e['tag'] == 'app_script_not_found' }
67
+ if user_errors.any? { |e| e["tag"] == "app_script_not_found" }
66
68
  raise Errors::AppScriptUndefinedError, api_key
67
- elsif user_errors.any? { |e| e['tag'] == 'shop_script_conflict' }
69
+ elsif user_errors.any? { |e| e["tag"] == "shop_script_conflict" }
68
70
  raise Errors::ShopScriptConflictError
69
- elsif user_errors.any? { |e| e['tag'] == 'app_script_not_pushed' }
71
+ elsif user_errors.any? { |e| e["tag"] == "app_script_not_pushed" }
70
72
  raise Errors::AppScriptNotPushedError
71
73
  else
72
74
  raise Errors::ScriptServiceUserError.new(query_name, user_errors.to_s)
@@ -88,7 +90,7 @@ module Script
88
90
  user_errors = resp_hash["data"]["shopScriptDelete"]["userErrors"]
89
91
  return resp_hash if user_errors.empty?
90
92
 
91
- if user_errors.any? { |e| e['tag'] == 'shop_script_not_found' }
93
+ if user_errors.any? { |e| e["tag"] == "shop_script_not_found" }
92
94
  raise Errors::ShopScriptUndefinedError, api_key
93
95
  else
94
96
  raise Errors::ScriptServiceUserError.new(query_name, user_errors.to_s)
@@ -112,8 +114,8 @@ module Script
112
114
  def self.api_client(ctx, api_key, shop_domain)
113
115
  new(
114
116
  ctx: ctx,
115
- url: 'https://script-service.myshopify.io/graphql',
116
- token: '',
117
+ url: "https://script-service.myshopify.io/graphql",
118
+ token: "",
117
119
  api_key: api_key,
118
120
  shop_id: shop_domain&.to_i
119
121
  )
@@ -148,28 +150,28 @@ module Script
148
150
  options[:variables] = variables.to_json if variables
149
151
  resp = PartnersProxyAPI.query(ctx, query_name, **options)
150
152
  raise_if_graphql_failed(resp)
151
- JSON.parse(resp['data']['scriptServiceProxy'])
153
+ JSON.parse(resp["data"]["scriptServiceProxy"])
152
154
  end
153
155
 
154
156
  def raise_if_graphql_failed(response)
155
157
  raise Errors::EmptyResponseError if response.nil?
156
158
 
157
- return unless response.key?('errors')
158
- case error_code(response['errors'])
159
- when 'forbidden'
159
+ return unless response.key?("errors")
160
+ case error_code(response["errors"])
161
+ when "forbidden"
160
162
  raise Errors::ForbiddenError
161
- when 'forbidden_on_shop'
163
+ when "forbidden_on_shop"
162
164
  raise Errors::ShopAuthenticationError
163
- when 'app_not_installed_on_shop'
165
+ when "app_not_installed_on_shop"
164
166
  raise Errors::AppNotInstalledError
165
167
  else
166
- raise Errors::GraphqlError, response['errors'].map { |e| e['message'] }
168
+ raise Errors::GraphqlError, response["errors"].map { |e| e["message"] }
167
169
  end
168
170
  end
169
171
 
170
172
  def error_code(errors)
171
173
  errors.map do |e|
172
- code = e.dig('extensions', 'code')
174
+ code = e.dig("extensions", "code")
173
175
  return code if code
174
176
  end
175
177
  end
@@ -21,20 +21,20 @@ module Script
21
21
  invalid_context_cause: "Your .shopify-cli.yml file is not correct.",
22
22
  invalid_context_help: "See https://help.shopify.com",
23
23
 
24
- invalid_config_props_cause: "{{command:--config_props}} is formatted incorrectly.",
24
+ invalid_config_props_cause: "{{command:--config-props}} is formatted incorrectly.",
25
25
  invalid_config_props_help: "Try again using this format: "\
26
- "{{cyan:--config_props='name1:value1, name2:value2'}}",
26
+ "{{cyan:--config-props='name1:value1, name2:value2'}}",
27
27
 
28
28
  invalid_script_name_cause: "Invalid script name.",
29
29
  invalid_script_name_help: "Replace or remove unsupported characters. Valid characters "\
30
30
  "are numbers, letters, hyphens, or underscores.",
31
31
 
32
32
  no_existing_apps_cause: "You don't have any apps.",
33
- no_existing_apps_help: "Please create an app with {{command:shopify create}} or "\
33
+ no_existing_apps_help: "Create an app with {{command:shopify create}} or "\
34
34
  "visit https://partners.shopify.com/.",
35
35
 
36
36
  no_existing_orgs_cause: "You don't have any partner organizations.",
37
- no_existing_orgs_help: "Please visit https://partners.shopify.com/ to create a partners account.",
37
+ no_existing_orgs_help: "Visit https://partners.shopify.com/ to create a partners account.",
38
38
 
39
39
  no_existing_stores_cause: "You don't have any stores.",
40
40
  no_existing_stores_help: "Visit https://partners.shopify.com/%{organization_id}/stores/ to create one.",
@@ -51,6 +51,12 @@ module Script
51
51
  invalid_config: "Can't change the configuration values because %1$s is missing or "\
52
52
  "it is not formatted properly.",
53
53
 
54
+ invalid_config_ui_definition_cause: "The UI configuration file %s contains invalid YAML.",
55
+ invalid_config_ui_definition_help: "Fix the errors and try again.",
56
+
57
+ missing_config_ui_definition_cause: "You are missing the UI configuration file %s.",
58
+ missing_config_ui_definition_help: "Create this file and try again.",
59
+
54
60
  script_not_found_cause: "Couldn't find script %s for extension point %s",
55
61
 
56
62
  service_failure_cause: "Internal service error.",
@@ -129,7 +135,7 @@ module Script
129
135
  Options:
130
136
  {{command:--name=NAME}} Script project name. Use any string.
131
137
  {{command:--description=DESCRIPTION}} Description of the project. Use any string.
132
- {{command:--extension_point=TYPE}} Extension point name. Allowed values: %2$s.
138
+ {{command:--extension-point=TYPE}} Extension point name. Allowed values: %2$s.
133
139
  HELP
134
140
 
135
141
  error: {
@@ -150,7 +156,7 @@ module Script
150
156
  HELP
151
157
 
152
158
  error: {
153
- operation_failed: "Couldn't push script to app.",
159
+ operation_failed: "Couldn't push script to app (API key: %{api_key}).",
154
160
  },
155
161
 
156
162
  script_pushed: "{{v}} Script pushed to app (API key: %{api_key}).",
@@ -174,8 +180,8 @@ module Script
174
180
  Turn on script in store.
175
181
  Usage: {{command:%s enable}}
176
182
  Options:
177
- {{command:--config_props='name1:value1, name2:value2'}} Optional. Define the configuration of your script by passing individual name and value pairs. If used with --config_file, then matching values in --config_props will override those set in the file.
178
- {{command:--config_file=<path/to/YAMLFilename>}} Optional. Define the configuration of your script using a YAML formatted file. --config_props values override properties in this file.
183
+ {{command:--config-props='name1:value1, name2:value2'}} Optional. Define the configuration of your script by passing individual name and value pairs. If used with --config_file, then matching values in --config-props will override those set in the file.
184
+ {{command:--config_file=<path/to/YAMLFilename>}} Optional. Define the configuration of your script using a YAML formatted file. --config-props values override properties in this file.
179
185
  HELP
180
186
 
181
187
  info: "{{*}} A script always remains enabled until you disable it - even after pushing "\
@@ -2,14 +2,15 @@
2
2
 
3
3
  module Script
4
4
  class ScriptProject < ShopifyCli::Project
5
- attr_reader :extension_point_type, :script_name, :language, :description
5
+ attr_reader :extension_point_type, :script_name, :language, :description, :config_ui
6
6
 
7
7
  def initialize(*args)
8
8
  super
9
- @extension_point_type = lookup_config!('extension_point_type')
9
+ @extension_point_type = lookup_config!("extension_point_type")
10
10
  raise Errors::DeprecatedEPError, @extension_point_type if deprecated?(@extension_point_type)
11
- @script_name = lookup_config!('script_name')
12
- @description = lookup_config('description')
11
+ @script_name = lookup_config!("script_name")
12
+ @description = lookup_config("description")
13
+ @config_ui = lookup_config_ui
13
14
  @language = lookup_language
14
15
  ShopifyCli::Core::Monorail.metadata = {
15
16
  "script_name" => @script_name,
@@ -38,8 +39,21 @@ module Script
38
39
  config[key]
39
40
  end
40
41
 
42
+ def lookup_config_ui
43
+ filename = lookup_config("config_ui_file")
44
+ return nil unless filename
45
+
46
+ path = File.join(directory, filename)
47
+ raise Errors::MissingSpecifiedConfigUiDefinitionError, filename unless File.exist?(path)
48
+
49
+ contents = File.read(path)
50
+ raise Errors::InvalidConfigUiDefinitionError, filename unless valid_config_ui?(contents)
51
+
52
+ contents
53
+ end
54
+
41
55
  def lookup_language
42
- lang = lookup_config('language')&.downcase || Layers::Domain::ExtensionPointAssemblyScriptSDK.language
56
+ lang = lookup_config("language")&.downcase || Layers::Domain::ExtensionPointAssemblyScriptSDK.language
43
57
  if Layers::Application::ExtensionPoints.supported_language?(type: extension_point_type, language: lang)
44
58
  lang
45
59
  else
@@ -47,6 +61,14 @@ module Script
47
61
  end
48
62
  end
49
63
 
64
+ def valid_config_ui?(raw_yaml)
65
+ require "yaml" # takes 20ms, so deferred as late as possible.
66
+ YAML.safe_load(raw_yaml)
67
+ true
68
+ rescue Psych::SyntaxError
69
+ false
70
+ end
71
+
50
72
  class << self
51
73
  def create(ctx, dir)
52
74
  raise Errors::ScriptProjectAlreadyExistsError, dir if ctx.dir_exist?(dir)
@@ -1,10 +1,10 @@
1
- require 'cli/ui'
1
+ require "cli/ui"
2
2
 
3
3
  module Script
4
4
  module UI
5
5
  module ErrorHandler
6
6
  def self.display(failed_op:, cause_of_error:, help_suggestion:)
7
- $stderr.puts(CLI::UI.fmt(ShopifyCli::Context.message('script.error.generic')))
7
+ $stderr.puts(CLI::UI.fmt(ShopifyCli::Context.message("script.error.generic")))
8
8
  full_msg = failed_op ? failed_op.dup : ""
9
9
  full_msg << " #{cause_of_error}" if cause_of_error
10
10
  full_msg << " #{help_suggestion}" if help_suggestion
@@ -26,187 +26,199 @@ module Script
26
26
  case e
27
27
  when Errno::EACCES
28
28
  {
29
- cause_of_error: ShopifyCli::Context.message('script.error.eacces_cause'),
30
- help_suggestion: ShopifyCli::Context.message('script.error.eacces_help'),
29
+ cause_of_error: ShopifyCli::Context.message("script.error.eacces_cause"),
30
+ help_suggestion: ShopifyCli::Context.message("script.error.eacces_help"),
31
31
  }
32
32
  when Errno::ENOSPC
33
33
  {
34
- cause_of_error: ShopifyCli::Context.message('script.error.enospc_cause'),
35
- help_suggestion: ShopifyCli::Context.message('script.error.enospc_help'),
34
+ cause_of_error: ShopifyCli::Context.message("script.error.enospc_cause"),
35
+ help_suggestion: ShopifyCli::Context.message("script.error.enospc_help"),
36
36
  }
37
37
  when ShopifyCli::OAuth::Error
38
38
  {
39
- cause_of_error: ShopifyCli::Context.message('script.error.oauth_cause'),
40
- help_suggestion: ShopifyCli::Context.message('script.error.oauth_help'),
39
+ cause_of_error: ShopifyCli::Context.message("script.error.oauth_cause"),
40
+ help_suggestion: ShopifyCli::Context.message("script.error.oauth_help"),
41
41
  }
42
42
  when Errors::InvalidContextError
43
43
  {
44
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_context_cause'),
45
- help_suggestion: ShopifyCli::Context.message('script.error.invalid_context_help'),
44
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_context_cause"),
45
+ help_suggestion: ShopifyCli::Context.message("script.error.invalid_context_help"),
46
46
  }
47
47
  when Errors::InvalidConfigProps
48
48
  {
49
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_config_props_cause'),
50
- help_suggestion: ShopifyCli::Context.message('script.error.invalid_config_props_help'),
49
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_config_props_cause"),
50
+ help_suggestion: ShopifyCli::Context.message("script.error.invalid_config_props_help"),
51
51
  }
52
52
  when Errors::InvalidConfigYAMLError
53
53
  {
54
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_config', e.config_file),
54
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_config", e.config_file),
55
55
  }
56
56
  when Errors::InvalidLanguageError
57
57
  {
58
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_language_cause', e.language),
58
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_language_cause", e.language),
59
59
  help_suggestion: ShopifyCli::Context.message(
60
- 'script.error.invalid_language_help',
61
- Script::Layers::Application::ExtensionPoints.languages(type: e.extension_point_type).join(', ')
60
+ "script.error.invalid_language_help",
61
+ Script::Layers::Application::ExtensionPoints.languages(type: e.extension_point_type).join(", ")
62
62
  ),
63
63
  }
64
+ when Errors::InvalidConfigUiDefinitionError
65
+ {
66
+ cause_of_error: ShopifyCli::Context
67
+ .message("script.error.invalid_config_ui_definition_cause", e.filename),
68
+ help_suggestion: ShopifyCli::Context.message("script.error.invalid_config_ui_definition_help"),
69
+ }
70
+ when Errors::MissingSpecifiedConfigUiDefinitionError
71
+ {
72
+ cause_of_error: ShopifyCli::Context
73
+ .message("script.error.missing_config_ui_definition_cause", e.filename),
74
+ help_suggestion: ShopifyCli::Context.message("script.error.missing_config_ui_definition_help"),
75
+ }
64
76
  when Errors::InvalidScriptNameError
65
77
  {
66
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_script_name_cause'),
67
- help_suggestion: ShopifyCli::Context.message('script.error.invalid_script_name_help'),
78
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_script_name_cause"),
79
+ help_suggestion: ShopifyCli::Context.message("script.error.invalid_script_name_help"),
68
80
  }
69
81
  when Errors::NoExistingAppsError
70
82
  {
71
- cause_of_error: ShopifyCli::Context.message('script.error.no_existing_apps_cause'),
72
- help_suggestion: ShopifyCli::Context.message('script.error.no_existing_apps_help'),
83
+ cause_of_error: ShopifyCli::Context.message("script.error.no_existing_apps_cause"),
84
+ help_suggestion: ShopifyCli::Context.message("script.error.no_existing_apps_help"),
73
85
  }
74
86
  when Errors::NoExistingOrganizationsError
75
87
  {
76
- cause_of_error: ShopifyCli::Context.message('script.error.no_existing_orgs_cause'),
77
- help_suggestion: ShopifyCli::Context.message('script.error.no_existing_orgs_help'),
88
+ cause_of_error: ShopifyCli::Context.message("script.error.no_existing_orgs_cause"),
89
+ help_suggestion: ShopifyCli::Context.message("script.error.no_existing_orgs_help"),
78
90
  }
79
91
  when Errors::NoExistingStoresError
80
92
  {
81
- cause_of_error: ShopifyCli::Context.message('script.error.no_existing_stores_cause'),
93
+ cause_of_error: ShopifyCli::Context.message("script.error.no_existing_stores_cause"),
82
94
  help_suggestion: ShopifyCli::Context.message(
83
- 'script.error.no_existing_stores_help',
95
+ "script.error.no_existing_stores_help",
84
96
  organization_id: e.organization_id
85
97
  ),
86
98
  }
87
99
  when Errors::ScriptProjectAlreadyExistsError
88
100
  {
89
- cause_of_error: ShopifyCli::Context.message('script.error.project_exists_cause'),
90
- help_suggestion: ShopifyCli::Context.message('script.error.project_exists_help'),
101
+ cause_of_error: ShopifyCli::Context.message("script.error.project_exists_cause"),
102
+ help_suggestion: ShopifyCli::Context.message("script.error.project_exists_help"),
91
103
  }
92
104
  when Errors::DeprecatedEPError
93
105
  {
94
- cause_of_error: ShopifyCli::Context.message('script.error.deprecated_ep', e.ep),
95
- help_suggestion: ShopifyCli::Context.message('script.error.deprecated_ep_cause'),
106
+ cause_of_error: ShopifyCli::Context.message("script.error.deprecated_ep", e.ep),
107
+ help_suggestion: ShopifyCli::Context.message("script.error.deprecated_ep_cause"),
96
108
  }
97
109
  when Layers::Domain::Errors::InvalidExtensionPointError
98
110
  {
99
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_extension_cause', e.type),
111
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_extension_cause", e.type),
100
112
  help_suggestion: ShopifyCli::Context.message(
101
- 'script.error.invalid_extension_help',
102
- Script::Layers::Application::ExtensionPoints.types.join(', ')
113
+ "script.error.invalid_extension_help",
114
+ Script::Layers::Application::ExtensionPoints.types.join(", ")
103
115
  ),
104
116
  }
105
117
  when Layers::Domain::Errors::ScriptNotFoundError
106
118
  {
107
119
  cause_of_error: ShopifyCli::Context.message(
108
- 'script.error.script_not_found_cause',
120
+ "script.error.script_not_found_cause",
109
121
  e.script_name,
110
122
  e.extension_point_type
111
123
  ),
112
124
  }
113
125
  when Layers::Domain::Errors::ServiceFailureError
114
126
  {
115
- cause_of_error: ShopifyCli::Context.message('script.error.service_failure_cause'),
116
- help_suggestion: ShopifyCli::Context.message('script.error.service_failure_help'),
127
+ cause_of_error: ShopifyCli::Context.message("script.error.service_failure_cause"),
128
+ help_suggestion: ShopifyCli::Context.message("script.error.service_failure_help"),
117
129
  }
118
130
  when Layers::Domain::Errors::MetadataValidationError
119
131
  {
120
- cause_of_error: ShopifyCli::Context.message('script.error.metadata_validation_cause'),
121
- help_suggestion: ShopifyCli::Context.message('script.error.metadata_validation_help'),
132
+ cause_of_error: ShopifyCli::Context.message("script.error.metadata_validation_cause"),
133
+ help_suggestion: ShopifyCli::Context.message("script.error.metadata_validation_help"),
122
134
  }
123
135
  when Layers::Domain::Errors::MetadataNotFoundError
124
136
  {
125
- cause_of_error: ShopifyCli::Context.message('script.error.metadata_not_found_cause'),
126
- help_suggestion: ShopifyCli::Context.message('script.error.metadata_not_found_help'),
137
+ cause_of_error: ShopifyCli::Context.message("script.error.metadata_not_found_cause"),
138
+ help_suggestion: ShopifyCli::Context.message("script.error.metadata_not_found_help"),
127
139
  }
128
140
  when Layers::Infrastructure::Errors::AppNotInstalledError
129
141
  {
130
- cause_of_error: ShopifyCli::Context.message('script.error.app_not_installed_cause'),
142
+ cause_of_error: ShopifyCli::Context.message("script.error.app_not_installed_cause"),
131
143
  }
132
144
  when Layers::Infrastructure::Errors::AppScriptNotPushedError,
133
145
  Layers::Infrastructure::Errors::AppScriptUndefinedError
134
146
  {
135
- cause_of_error: ShopifyCli::Context.message('script.error.app_script_not_pushed_help'),
147
+ cause_of_error: ShopifyCli::Context.message("script.error.app_script_not_pushed_help"),
136
148
  }
137
149
  when Layers::Infrastructure::Errors::BuildError
138
150
  {
139
- cause_of_error: ShopifyCli::Context.message('script.error.build_error_cause'),
140
- help_suggestion: ShopifyCli::Context.message('script.error.build_error_help'),
151
+ cause_of_error: ShopifyCli::Context.message("script.error.build_error_cause"),
152
+ help_suggestion: ShopifyCli::Context.message("script.error.build_error_help"),
141
153
  }
142
154
  when Layers::Infrastructure::Errors::DependencyInstallError
143
155
  {
144
- cause_of_error: ShopifyCli::Context.message('script.error.dependency_install_cause'),
145
- help_suggestion: ShopifyCli::Context.message('script.error.dependency_install_help'),
156
+ cause_of_error: ShopifyCli::Context.message("script.error.dependency_install_cause"),
157
+ help_suggestion: ShopifyCli::Context.message("script.error.dependency_install_help"),
146
158
  }
147
159
  when Layers::Infrastructure::Errors::EmptyResponseError
148
160
  {
149
- cause_of_error: ShopifyCli::Context.message('script.error.failed_api_request_cause'),
150
- help_suggestion: ShopifyCli::Context.message('script.error.failed_api_request_help'),
161
+ cause_of_error: ShopifyCli::Context.message("script.error.failed_api_request_cause"),
162
+ help_suggestion: ShopifyCli::Context.message("script.error.failed_api_request_help"),
151
163
  }
152
164
  when Layers::Infrastructure::Errors::ForbiddenError
153
165
  {
154
- cause_of_error: ShopifyCli::Context.message('script.error.forbidden_error_cause'),
166
+ cause_of_error: ShopifyCli::Context.message("script.error.forbidden_error_cause"),
155
167
  }
156
168
  when Layers::Infrastructure::Errors::GraphqlError
157
169
  {
158
- cause_of_error: ShopifyCli::Context.message('script.error.graphql_error_cause', e.errors.join(', ')),
159
- help_suggestion: ShopifyCli::Context.message('script.error.graphql_error_help'),
170
+ cause_of_error: ShopifyCli::Context.message("script.error.graphql_error_cause", e.errors.join(", ")),
171
+ help_suggestion: ShopifyCli::Context.message("script.error.graphql_error_help"),
160
172
  }
161
173
  when Layers::Infrastructure::Errors::ScriptRepushError
162
174
  {
163
- cause_of_error: ShopifyCli::Context.message('script.error.script_repush_cause', e.api_key),
164
- help_suggestion: ShopifyCli::Context.message('script.error.script_repush_help'),
175
+ cause_of_error: ShopifyCli::Context.message("script.error.script_repush_cause", e.api_key),
176
+ help_suggestion: ShopifyCli::Context.message("script.error.script_repush_help"),
165
177
  }
166
178
  when Layers::Infrastructure::Errors::ScriptServiceUserError
167
179
  {
168
- cause_of_error: ShopifyCli::Context.message('script.error.user_error_cause'),
169
- help_suggestion: ShopifyCli::Context.message('script.error.user_error_help'),
180
+ cause_of_error: ShopifyCli::Context.message("script.error.user_error_cause"),
181
+ help_suggestion: ShopifyCli::Context.message("script.error.user_error_help"),
170
182
  }
171
183
  when Layers::Infrastructure::Errors::ShopAuthenticationError
172
184
  {
173
- cause_of_error: ShopifyCli::Context.message('script.error.shop_auth_cause'),
174
- help_suggestion: ShopifyCli::Context.message('script.error.shop_auth_help'),
185
+ cause_of_error: ShopifyCli::Context.message("script.error.shop_auth_cause"),
186
+ help_suggestion: ShopifyCli::Context.message("script.error.shop_auth_help"),
175
187
  }
176
188
  when Layers::Infrastructure::Errors::ShopScriptConflictError
177
189
  {
178
- cause_of_error: ShopifyCli::Context.message('script.error.shop_script_conflict_cause'),
179
- help_suggestion: ShopifyCli::Context.message('script.error.shop_script_conflict_help'),
190
+ cause_of_error: ShopifyCli::Context.message("script.error.shop_script_conflict_cause"),
191
+ help_suggestion: ShopifyCli::Context.message("script.error.shop_script_conflict_help"),
180
192
  }
181
193
  when Layers::Infrastructure::Errors::ShopScriptUndefinedError
182
194
  {
183
- cause_of_error: ShopifyCli::Context.message('script.error.shop_script_undefined_cause'),
195
+ cause_of_error: ShopifyCli::Context.message("script.error.shop_script_undefined_cause"),
184
196
  }
185
197
  when Layers::Infrastructure::Errors::PackagesOutdatedError
186
198
  {
187
199
  cause_of_error: ShopifyCli::Context.message(
188
- 'script.error.packages_outdated_cause',
189
- e.outdated_packages.join(', ')
200
+ "script.error.packages_outdated_cause",
201
+ e.outdated_packages.join(", ")
190
202
  ),
191
203
  help_suggestion: ShopifyCli::Context.message(
192
- 'script.error.packages_outdated_help',
193
- e.outdated_packages.collect { |package| "#{package}@latest" }.join(' ')
204
+ "script.error.packages_outdated_help",
205
+ e.outdated_packages.collect { |package| "#{package}@latest" }.join(" ")
194
206
  ),
195
207
  }
196
208
  when Layers::Infrastructure::Errors::BuildScriptNotFoundError
197
209
  {
198
- cause_of_error: ShopifyCli::Context.message('script.error.build_script_not_found'),
199
- help_suggestion: ShopifyCli::Context.message('script.error.build_script_suggestion'),
210
+ cause_of_error: ShopifyCli::Context.message("script.error.build_script_not_found"),
211
+ help_suggestion: ShopifyCli::Context.message("script.error.build_script_suggestion"),
200
212
  }
201
213
  when Layers::Infrastructure::Errors::InvalidBuildScriptError
202
214
  {
203
- cause_of_error: ShopifyCli::Context.message('script.error.invalid_build_script'),
204
- help_suggestion: ShopifyCli::Context.message('script.error.build_script_suggestion'),
215
+ cause_of_error: ShopifyCli::Context.message("script.error.invalid_build_script"),
216
+ help_suggestion: ShopifyCli::Context.message("script.error.build_script_suggestion"),
205
217
  }
206
218
  when Layers::Infrastructure::Errors::WebAssemblyBinaryNotFoundError
207
219
  {
208
- cause_of_error: ShopifyCli::Context.message('script.error.web_assembly_binary_not_found'),
209
- help_suggestion: ShopifyCli::Context.message('script.error.web_assembly_binary_not_found_suggestion'),
220
+ cause_of_error: ShopifyCli::Context.message("script.error.web_assembly_binary_not_found"),
221
+ help_suggestion: ShopifyCli::Context.message("script.error.web_assembly_binary_not_found_suggestion"),
210
222
  }
211
223
  end
212
224
  end