shopify-cli 1.6.0 → 1.7.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 (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