shopify-cli 2.7.2 → 2.9.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +2 -2
  3. data/.github/workflows/shopify.yml +1 -1
  4. data/.gitignore +1 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +52 -0
  7. data/Codespace.dockerfile +2 -2
  8. data/Gemfile.lock +4 -4
  9. data/RELEASING.md +4 -3
  10. data/Tests.dockerfile +2 -2
  11. data/dev.yml +3 -3
  12. data/ext/javy/hashes/javy-arm-macos-v0.1.0.gz.sha256 +1 -0
  13. data/ext/javy/hashes/javy-x86_64-linux-v0.1.0.gz.sha256 +1 -0
  14. data/ext/javy/hashes/javy-x86_64-macos-v0.1.0.gz.sha256 +1 -0
  15. data/ext/javy/hashes/javy-x86_64-windows-v0.1.0.gz.sha256 +1 -0
  16. data/ext/javy/javy.rb +31 -13
  17. data/lib/graphql/get_extension_registrations.graphql +27 -0
  18. data/lib/project_types/extension/cli.rb +27 -2
  19. data/lib/project_types/extension/commands/build.rb +10 -10
  20. data/lib/project_types/extension/commands/create.rb +2 -3
  21. data/lib/project_types/extension/commands/push.rb +36 -8
  22. data/lib/project_types/extension/extension_project.rb +1 -1
  23. data/lib/project_types/extension/features/argo_serve.rb +6 -5
  24. data/lib/project_types/extension/forms/questions/ask_registration.rb +6 -2
  25. data/lib/project_types/extension/loaders/project.rb +29 -0
  26. data/lib/project_types/extension/loaders/specification_handler.rb +22 -0
  27. data/lib/project_types/extension/messages/messages.rb +4 -0
  28. data/lib/project_types/extension/models/app.rb +1 -1
  29. data/lib/project_types/extension/models/development_server.rb +2 -4
  30. data/lib/project_types/extension/models/specification_handlers/default.rb +4 -0
  31. data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
  32. data/lib/project_types/extension/tasks/execute_commands/base.rb +13 -0
  33. data/lib/project_types/extension/tasks/execute_commands/build.rb +29 -0
  34. data/lib/project_types/extension/tasks/execute_commands/create.rb +33 -0
  35. data/lib/project_types/extension/tasks/execute_commands/serve.rb +35 -0
  36. data/lib/project_types/extension/tasks/merge_server_config.rb +33 -22
  37. data/lib/project_types/rails/commands/create.rb +1 -1
  38. data/lib/project_types/rails/gem.rb +1 -2
  39. data/lib/project_types/script/cli.rb +8 -1
  40. data/lib/project_types/script/commands/connect.rb +19 -0
  41. data/lib/project_types/script/commands/create.rb +8 -2
  42. data/lib/project_types/script/commands/push.rb +35 -12
  43. data/lib/project_types/script/config/extension_points.yml +10 -2
  44. data/lib/project_types/script/graphql/app_script_set.graphql +2 -2
  45. data/lib/project_types/script/layers/application/connect_app.rb +15 -3
  46. data/lib/project_types/script/layers/application/create_script.rb +17 -17
  47. data/lib/project_types/script/layers/application/extension_points.rb +50 -26
  48. data/lib/project_types/script/layers/application/push_script.rb +6 -3
  49. data/lib/project_types/script/layers/domain/errors.rb +1 -4
  50. data/lib/project_types/script/layers/domain/extension_point.rb +14 -0
  51. data/lib/project_types/script/layers/domain/push_package.rb +3 -3
  52. data/lib/project_types/script/layers/domain/{script_json.rb → script_config.rb} +2 -2
  53. data/lib/project_types/script/layers/domain/script_project.rb +1 -1
  54. data/lib/project_types/script/layers/infrastructure/errors.rb +30 -5
  55. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +2 -2
  56. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +125 -27
  57. data/lib/project_types/script/layers/infrastructure/script_service.rb +11 -11
  58. data/lib/project_types/script/loaders/project.rb +44 -0
  59. data/lib/project_types/script/loaders/specification_handler.rb +22 -0
  60. data/lib/project_types/script/messages/messages.rb +34 -3
  61. data/lib/project_types/script/ui/error_handler.rb +35 -15
  62. data/lib/project_types/theme/commands/pull.rb +39 -16
  63. data/lib/project_types/theme/commands/push.rb +60 -29
  64. data/lib/project_types/theme/commands/serve.rb +5 -0
  65. data/lib/project_types/theme/messages/messages.rb +30 -18
  66. data/lib/shopify_cli/command.rb +6 -0
  67. data/lib/shopify_cli/commands/login.rb +11 -5
  68. data/lib/shopify_cli/commands/switch.rb +1 -1
  69. data/lib/shopify_cli/constants.rb +5 -0
  70. data/lib/shopify_cli/context.rb +66 -11
  71. data/lib/shopify_cli/environment.rb +15 -4
  72. data/lib/shopify_cli/form.rb +2 -0
  73. data/lib/shopify_cli/git.rb +2 -0
  74. data/lib/shopify_cli/identity_auth.rb +1 -0
  75. data/lib/shopify_cli/messages/messages.rb +10 -2
  76. data/lib/shopify_cli/partners_api/app_extensions/job.rb +36 -0
  77. data/lib/shopify_cli/partners_api/app_extensions.rb +46 -0
  78. data/lib/shopify_cli/partners_api/organizations.rb +2 -5
  79. data/lib/shopify_cli/partners_api.rb +1 -0
  80. data/lib/shopify_cli/project.rb +8 -7
  81. data/lib/shopify_cli/resources/env_file.rb +18 -6
  82. data/lib/shopify_cli/services/app/create/rails_service.rb +1 -1
  83. data/lib/shopify_cli/theme/dev_server/cdn_fonts.rb +73 -0
  84. data/lib/shopify_cli/theme/dev_server/hot-reload.js +57 -10
  85. data/lib/shopify_cli/theme/dev_server/hot_reload.rb +18 -2
  86. data/lib/shopify_cli/theme/dev_server/proxy/template_param_builder.rb +84 -0
  87. data/lib/shopify_cli/theme/dev_server/proxy.rb +10 -15
  88. data/lib/shopify_cli/theme/dev_server/reload_mode.rb +34 -0
  89. data/lib/shopify_cli/theme/dev_server.rb +8 -21
  90. data/lib/shopify_cli/theme/theme.rb +26 -4
  91. data/lib/shopify_cli/thread_pool/job.rb +27 -0
  92. data/lib/shopify_cli/thread_pool.rb +37 -0
  93. data/lib/shopify_cli/tunnel.rb +1 -0
  94. data/lib/shopify_cli/version.rb +1 -1
  95. data/lib/shopify_cli.rb +4 -0
  96. data/shopify-cli.gemspec +1 -1
  97. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +3 -1
  98. metadata +26 -7
  99. data/lib/graphql/all_orgs_with_extensions.graphql +0 -37
  100. data/lib/project_types/extension/tasks/run_extension_command.rb +0 -82
@@ -89,6 +89,9 @@ module Extension
89
89
  help: <<~HELP,
90
90
  Push the current extension to Shopify.
91
91
  Usage: {{command:%s extension push}}
92
+ Options:
93
+ {{command:--api-key=API_KEY}} Connect your extension and app by inserting your app's API key (which you can get from your app setup page on shopify.dev).
94
+ {{command:--extension-id=EXTENSION_ID}} The id of the extension's registration.
92
95
  HELP
93
96
  frame_title: "Pushing your extension to Shopify",
94
97
  waiting_text: "Pushing code to Shopify…",
@@ -173,6 +176,7 @@ module Extension
173
176
  errors: {
174
177
  unknown_type: "Unknown extension type %s",
175
178
  package_not_found: "`%s` package not found.",
179
+ missing_api_key: "Missing api_key.",
176
180
  module_not_found: "Unable to find module %s. Ensure your dependencies are up-to-date and try again.",
177
181
  },
178
182
  warnings: {
@@ -6,7 +6,7 @@ module Extension
6
6
  include SmartProperties
7
7
 
8
8
  property! :api_key, accepts: String
9
- property! :secret, accepts: String
9
+ property :secret, accepts: String
10
10
  property :title, accepts: String
11
11
  property :business_name, accepts: String
12
12
  end
@@ -40,7 +40,7 @@ module Extension
40
40
 
41
41
  def serve(context, server_config)
42
42
  CLI::Kit::System.popen3(executable, "serve", "-") do |input, out, err, status|
43
- context.puts("Sending configuration data …")
43
+ context.debug("Sending configuration data to extension development server …")
44
44
  input << server_config.to_yaml
45
45
  input.close
46
46
 
@@ -57,17 +57,15 @@ module Extension
57
57
  private
58
58
 
59
59
  def forward_output_to_user(out, err, ctx)
60
- ctx.puts("Starting monitoring threads …")
60
+ ctx.debug("Starting message processing threads to relay output produced by the extension development server …")
61
61
 
62
62
  Thread.new do
63
- ctx.puts("Ready to process standard output")
64
63
  while (line = out.gets)
65
64
  ctx.puts(line)
66
65
  end
67
66
  end
68
67
 
69
68
  Thread.new do
70
- ctx.puts("Ready to process standard error")
71
69
  while (error = err.gets)
72
70
  ctx.puts(error)
73
71
  end
@@ -103,6 +103,10 @@ module Extension
103
103
  raise NotImplementedError
104
104
  end
105
105
 
106
+ def server_config_path(base_dir = Dir.pwd)
107
+ File.join(base_dir, server_config_file)
108
+ end
109
+
106
110
  def server_config_file
107
111
  "shopifile.yml"
108
112
  end
@@ -9,11 +9,12 @@ module Extension
9
9
  property! :api_key, accepts: String
10
10
  property! :context, accepts: ShopifyCLI::Context
11
11
  property! :hash, accepts: Hash
12
+ property :port, accepts: Integer, default: ShopifyCLI::Constants::Extension::DEFAULT_PORT
12
13
  property! :registration_uuid, accepts: String
13
14
  property :resource_url, accepts: String
14
15
  property! :store, accepts: String
15
16
  property! :title, accepts: String
16
- property :tunnel_url, accepts: String
17
+ property :tunnel_url, accepts: String
17
18
  property! :type, accepts: String
18
19
 
19
20
  def self.call(*args)
@@ -46,6 +47,7 @@ module Extension
46
47
  end
47
48
  server_config = Models::ServerConfig::Root.new(
48
49
  extensions: [extension],
50
+ port: port,
49
51
  public_url: tunnel_url,
50
52
  store: store
51
53
  )
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Tasks
6
+ module ExecuteCommands
7
+ class Base
8
+ include SmartProperties
9
+ property! :type, accepts: Models::DevelopmentServerRequirements::SUPPORTED_EXTENSION_TYPES
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Tasks
6
+ module ExecuteCommands
7
+ class Build < Base
8
+ property! :context, accepts: ShopifyCLI::Context
9
+ property! :config_file_path, accepts: String
10
+
11
+ def call
12
+ ShopifyCLI::Result
13
+ .call(&method(:merge_server_config))
14
+ .then { |server_config| Models::DevelopmentServer.new.build(server_config) }
15
+ end
16
+
17
+ private
18
+
19
+ def merge_server_config
20
+ Tasks::MergeServerConfig.call(
21
+ context: context,
22
+ file_path: config_file_path,
23
+ type: type
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Tasks
6
+ module ExecuteCommands
7
+ class Create < Base
8
+ property! :template, accepts: Models::ServerConfig::Development::VALID_TEMPLATES
9
+ property! :root_dir, accepts: String
10
+
11
+ def call
12
+ ShopifyCLI::Result.success(generate_config)
13
+ .then { |server_config| Models::DevelopmentServer.new.create(server_config) }
14
+ .unwrap do |error|
15
+ raise error unless error.nil?
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def generate_config
22
+ extension = Models::ServerConfig::Extension.build(
23
+ template: template,
24
+ type: type,
25
+ root_dir: root_dir,
26
+ )
27
+
28
+ Models::ServerConfig::Root.new(extensions: [extension])
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Tasks
6
+ module ExecuteCommands
7
+ class Serve < Base
8
+ property! :context, accepts: ShopifyCLI::Context
9
+ property! :config_file_path, accepts: String
10
+ property :port, accepts: Integer, default: ShopifyCLI::Constants::Extension::DEFAULT_PORT
11
+ property :resource_url, accepts: String
12
+ property! :tunnel_url, accepts: String
13
+
14
+ def call
15
+ ShopifyCLI::Result
16
+ .call(&method(:merge_server_config))
17
+ .then { |server_config| Models::DevelopmentServer.new.serve(context, server_config) }
18
+ end
19
+
20
+ private
21
+
22
+ def merge_server_config
23
+ Tasks::MergeServerConfig.call(
24
+ context: context,
25
+ file_path: config_file_path,
26
+ port: port,
27
+ resource_url: resource_url,
28
+ tunnel_url: tunnel_url,
29
+ type: type
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -4,28 +4,39 @@ require "yaml"
4
4
 
5
5
  module Extension
6
6
  module Tasks
7
- class MergeServerConfig < ShopifyCLI::Task
8
- class << self
9
- def call(context:, file_name:, resource_url:, tunnel_url:, type:)
10
- config = YAML.load_file(file_name)
11
- project = ExtensionProject.current
12
- Tasks::ConvertServerConfig.call(
13
- api_key: project.env.api_key,
14
- context: context,
15
- hash: config,
16
- registration_uuid: project.registration_uuid,
17
- resource_url: resource_url || project.resource_url,
18
- store: project.env.shop || "",
19
- title: project.title,
20
- tunnel_url: tunnel_url,
21
- type: type
22
- )
23
- rescue Psych::SyntaxError => e
24
- raise(
25
- ShopifyCLI::Abort,
26
- ShopifyCLI::Context.message("core.yaml.error.invalid", file_name, e.message)
27
- )
28
- end
7
+ class MergeServerConfig
8
+ include SmartProperties
9
+
10
+ property! :context, accepts: ShopifyCLI::Context
11
+ property! :file_path, accepts: ->(path) { Pathname(path).yield_self { |pn| pn.absolute? && pn.file? } }
12
+ property :port, accepts: Integer, default: ShopifyCLI::Constants::Extension::DEFAULT_PORT
13
+ property :resource_url, accepts: String
14
+ property :tunnel_url, accepts: String
15
+ property! :type, accepts: Models::DevelopmentServerRequirements::SUPPORTED_EXTENSION_TYPES
16
+
17
+ def self.call(*args)
18
+ new(*args).call
19
+ end
20
+
21
+ def call
22
+ config = YAML.load_file(file_path)
23
+ project = ExtensionProject.current
24
+ Tasks::ConvertServerConfig.call(
25
+ api_key: project.env.api_key,
26
+ context: context,
27
+ hash: config,
28
+ registration_uuid: project.registration_uuid,
29
+ resource_url: resource_url || project.resource_url,
30
+ store: project.env.shop || "",
31
+ title: project.title,
32
+ tunnel_url: tunnel_url,
33
+ type: type
34
+ )
35
+ rescue Psych::SyntaxError => e
36
+ raise(
37
+ ShopifyCLI::Abort,
38
+ ShopifyCLI::Context.message("core.yaml.error.invalid", file_name, e.message)
39
+ )
29
40
  end
30
41
  end
31
42
  end
@@ -156,10 +156,10 @@ module Rails
156
156
 
157
157
  CLI::UI::Frame.open(@ctx.message("rails.create.generating_app", name)) do
158
158
  new_command = %w(rails new)
159
+ new_command << name
159
160
  new_command += DEFAULT_RAILS_FLAGS
160
161
  new_command << "--database=#{db}"
161
162
  new_command += options.flags[:rails_opts].split unless options.flags[:rails_opts].nil?
162
- new_command << name
163
163
 
164
164
  syscall(new_command)
165
165
  end
@@ -79,8 +79,7 @@ module Rails
79
79
  def install!
80
80
  spin = CLI::UI::SpinGroup.new
81
81
  spin.add(ctx.message("rails.gem.installing", name)) do |spinner|
82
- args = %w(gem install)
83
- args.push(name)
82
+ args = ["#{ENV["RUBY_BINDIR"]}gem", "install", name]
84
83
  unless version.nil?
85
84
  if ctx.windows? && version.include?("~")
86
85
  args.push("-v", "\"#{version}\"")
@@ -13,6 +13,7 @@ module Script
13
13
  hidden_feature(feature_set: :script_project)
14
14
  subcommand :Create, "create", Project.project_filepath("commands/create")
15
15
  subcommand :Push, "push", Project.project_filepath("commands/push")
16
+ subcommand :Connect, "connect", Project.project_filepath("commands/connect")
16
17
  subcommand :Javy, "javy", Project.project_filepath("commands/javy")
17
18
  end
18
19
  ShopifyCLI::Commands.register("Script::Command", "script")
@@ -24,6 +25,7 @@ module Script
24
25
  autoload :AskScriptUuid, Project.project_filepath("forms/ask_script_uuid")
25
26
  autoload :RunAgainstShopifyOrg, Project.project_filepath("forms/run_against_shopify_org")
26
27
  autoload :Create, Project.project_filepath("forms/create")
28
+ autoload :Connect, Project.project_filepath("forms/connect")
27
29
  autoload :ScriptForm, Project.project_filepath("forms/script_form")
28
30
  end
29
31
 
@@ -46,7 +48,7 @@ module Script
46
48
  autoload :PushPackage, Project.project_filepath("layers/domain/push_package")
47
49
  autoload :Metadata, Project.project_filepath("layers/domain/metadata")
48
50
  autoload :ExtensionPoint, Project.project_filepath("layers/domain/extension_point")
49
- autoload :ScriptJson, Project.project_filepath("layers/domain/script_json")
51
+ autoload :ScriptConfig, Project.project_filepath("layers/domain/script_config")
50
52
  autoload :ScriptProject, Project.project_filepath("layers/domain/script_project")
51
53
  end
52
54
 
@@ -90,5 +92,10 @@ module Script
90
92
 
91
93
  autoload :Errors, Project.project_filepath("errors")
92
94
 
95
+ module Loaders
96
+ autoload :Project, Script::Project.project_filepath("loaders/project")
97
+ autoload :SpecificationHandler, Script::Project.project_filepath("loaders/specification_handler")
98
+ end
99
+
93
100
  class ScriptProjectError < StandardError; end
94
101
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module Script
3
+ class Command
4
+ class Connect < ShopifyCLI::Command::SubCommand
5
+ prerequisite_task :ensure_authenticated
6
+ prerequisite_task ensure_project_type: :script
7
+
8
+ def call(_args, _)
9
+ Layers::Application::ConnectApp.call(ctx: @ctx, force: true)
10
+ rescue StandardError => e
11
+ UI::ErrorHandler.pretty_print_and_raise(e, failed_op: @ctx.message("script.connect.error.operation_failed"))
12
+ end
13
+
14
+ def self.help
15
+ ShopifyCLI::Context.new.message("connect.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -33,8 +33,14 @@ module Script
33
33
  end
34
34
 
35
35
  def self.help
36
- allowed_values = Script::Layers::Application::ExtensionPoints.available_types.map { |type| "{{cyan:#{type}}}" }
37
- ShopifyCLI::Context.message("script.create.help", ShopifyCLI::TOOL_NAME, allowed_values.join(", "))
36
+ allowed_apis = Layers::Application::ExtensionPoints.available_types.map { |type| "{{cyan:#{type}}}" }
37
+ allowed_languages = Layers::Application::ExtensionPoints.all_languages.map { |lang| "{{cyan:#{lang}}}" }
38
+ ShopifyCLI::Context.message(
39
+ "script.create.help",
40
+ ShopifyCLI::TOOL_NAME,
41
+ allowed_apis.join(", "),
42
+ allowed_languages.join(", ")
43
+ )
38
44
  end
39
45
  end
40
46
  end
@@ -7,25 +7,48 @@ module Script
7
7
 
8
8
  options do |parser, flags|
9
9
  parser.on("--force") { |t| flags[:force] = t }
10
+ parser.on("--api-key=API_KEY") { |api_key| flags[:api_key] = api_key.gsub('"', "") }
11
+ parser.on("--api-secret=API_SECRET") { |api_secret| flags[:api_secret] = api_secret.gsub('"', "") }
12
+ parser.on("--uuid=UUID") do |uuid|
13
+ flags[:uuid] = uuid.gsub('""', "")
14
+ end
10
15
  end
11
16
 
12
17
  def call(_args, _name)
13
- fresh_env = Layers::Application::ConnectApp.call(ctx: @ctx)
14
-
15
- force = options.flags.key?(:force) || !!fresh_env
18
+ connect_to_app
19
+ project = load_project
20
+ push(project: project)
21
+ rescue StandardError => e
22
+ UI::ErrorHandler.pretty_print_and_raise(e,
23
+ failed_op: @ctx.message("script.push.error.operation_failed_no_api_key"))
24
+ end
16
25
 
17
- api_key = Layers::Infrastructure::ScriptProjectRepository.new(ctx: @ctx).get.api_key
18
- return @ctx.puts(self.class.help) unless api_key
26
+ def push(project:)
27
+ force = options.flags.key?(:force)
28
+ api_key = project.env[:api_key]
29
+ uuid = project.env[:extra]["UUID"]
19
30
 
20
- Layers::Application::PushScript.call(ctx: @ctx, force: force)
21
- @ctx.puts(@ctx.message("script.push.script_pushed", api_key: api_key))
22
- rescue StandardError => e
23
- msg = if api_key
24
- @ctx.message("script.push.error.operation_failed_with_api_key", api_key: api_key)
31
+ if ShopifyCLI::Environment.interactive? || (uuid && !uuid.empty?)
32
+ Layers::Application::PushScript.call(ctx: @ctx, force: force, project: project)
33
+ @ctx.puts(@ctx.message("script.push.script_pushed", api_key: api_key))
25
34
  else
26
- @ctx.message("script.push.error.operation_failed_no_api_key")
35
+ raise ShopifyCLI::Abort, @ctx.message("script.push.error.operation_failed_no_uuid")
36
+ end
37
+ end
38
+
39
+ def load_project
40
+ Script::Loaders::Project.load(
41
+ directory: Dir.pwd,
42
+ api_key: options.flags[:api_key],
43
+ api_secret: options.flags[:api_secret],
44
+ uuid: options.flags[:uuid]
45
+ )
46
+ end
47
+
48
+ def connect_to_app
49
+ if ShopifyCLI::Environment.interactive?
50
+ Layers::Application::ConnectApp.call(ctx: @ctx)
27
51
  end
28
- UI::ErrorHandler.pretty_print_and_raise(e, failed_op: msg)
29
52
  end
30
53
 
31
54
  def self.help
@@ -18,11 +18,19 @@ shipping_methods:
18
18
  beta: true
19
19
  package: "@shopify/scripts-checkout-apis"
20
20
  repo: "https://github.com/Shopify/scripts-apis-examples"
21
- discount_types:
21
+ merchandise_discount_types:
22
22
  beta: true
23
23
  domain: 'discounts'
24
24
  libraries:
25
25
  typescript:
26
26
  beta: true
27
- package: "@shopify/scripts-discount-apis"
27
+ package: "@shopify/scripts-discounts-apis"
28
+ repo: "https://github.com/Shopify/scripts-apis-examples"
29
+ delivery_discount_types:
30
+ beta: true
31
+ domain: 'discounts'
32
+ libraries:
33
+ typescript:
34
+ beta: true
35
+ package: "@shopify/scripts-discounts-apis"
28
36
  repo: "https://github.com/Shopify/scripts-apis-examples"
@@ -6,7 +6,7 @@ mutation AppScriptSet(
6
6
  $force: Boolean,
7
7
  $schemaMajorVersion: String,
8
8
  $schemaMinorVersion: String,
9
- $scriptJsonVersion: String!,
9
+ $scriptConfigVersion: String!,
10
10
  $configurationUi: Boolean!,
11
11
  $configurationDefinition: String!,
12
12
  $moduleUploadUrl: String!,
@@ -20,7 +20,7 @@ mutation AppScriptSet(
20
20
  force: $force
21
21
  schemaMajorVersion: $schemaMajorVersion
22
22
  schemaMinorVersion: $schemaMinorVersion,
23
- scriptJsonVersion: $scriptJsonVersion,
23
+ scriptConfigVersion: $scriptConfigVersion,
24
24
  configurationUi: $configurationUi,
25
25
  configurationDefinition: $configurationDefinition,
26
26
  moduleUploadUrl: $moduleUploadUrl,
@@ -7,10 +7,11 @@ module Script
7
7
  module Application
8
8
  class ConnectApp
9
9
  class << self
10
- def call(ctx:)
10
+ def call(ctx:, force: false)
11
11
  script_project_repo = Layers::Infrastructure::ScriptProjectRepository.new(ctx: ctx)
12
12
  script_project = script_project_repo.get
13
- return false if script_project.env_valid?
13
+
14
+ return false if script_project.env_valid? && !force
14
15
 
15
16
  if ShopifyCLI::Shopifolk.check && Forms::RunAgainstShopifyOrg.ask(ctx, nil, nil).response
16
17
  ShopifyCLI::Shopifolk.act_as_shopify_organization
@@ -37,15 +38,26 @@ module Script
37
38
  extension_point_type = script_project.extension_point_type
38
39
  scripts = script_service.get_app_scripts(extension_point_type: extension_point_type)
39
40
 
40
- uuid = Forms::AskScriptUuid.ask(ctx, scripts, nil).uuid
41
+ uuid = Forms::AskScriptUuid.ask(ctx, scripts, nil)&.uuid
41
42
 
42
43
  script_project_repo.create_env(
43
44
  api_key: app["apiKey"],
44
45
  secret: app["apiSecretKeys"].first["secret"],
45
46
  uuid: uuid
46
47
  )
48
+ ctx.done(ctx.message("script.connect.connected", app["title"]))
47
49
 
48
50
  true
51
+ rescue SmartProperties::InitializationError, SmartProperties::InvalidValueError => error
52
+ handle_error(error, context: ctx)
53
+ end
54
+
55
+ def handle_error(error, context:)
56
+ properties_hash = { api_key: "SHOPIFY_API_KEY", secret: "SHOPIFY_API_SECRET" }
57
+ missing_env_variables = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
58
+ raise ShopifyCLI::Abort,
59
+ context.message("script.connect.error.missing_env_file_variables", missing_env_variables,
60
+ ShopifyCLI::TOOL_NAME)
49
61
  end
50
62
 
51
63
  private
@@ -8,11 +8,14 @@ module Script
8
8
  class CreateScript
9
9
  class << self
10
10
  def call(ctx:, language:, sparse_checkout_branch:, script_name:, extension_point_type:)
11
- raise Infrastructure::Errors::ScriptProjectAlreadyExistsError, script_name if ctx.dir_exist?(script_name)
11
+ script_project_repo = Infrastructure::ScriptProjectRepository.new(
12
+ ctx: ctx,
13
+ directory: script_name,
14
+ initial_directory: ctx.root
15
+ )
12
16
 
13
- in_new_directory_context(ctx, script_name) do
17
+ in_new_directory_context(script_project_repo) do
14
18
  extension_point = ExtensionPoints.get(type: extension_point_type)
15
- script_project_repo = Infrastructure::ScriptProjectRepository.new(ctx: ctx)
16
19
  project = script_project_repo.create(
17
20
  script_name: script_name,
18
21
  extension_point_type: extension_point_type,
@@ -36,7 +39,7 @@ module Script
36
39
  )
37
40
 
38
41
  install_dependencies(ctx, language, script_name, project_creator)
39
- script_project_repo.update_or_create_script_json(title: script_name)
42
+ script_project_repo.update_script_config(title: script_name)
40
43
  project
41
44
  end
42
45
  end
@@ -62,19 +65,16 @@ module Script
62
65
  ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
63
66
  end
64
67
 
65
- def in_new_directory_context(ctx, directory)
66
- initial_directory = ctx.root
67
- begin
68
- ctx.mkdir_p(directory)
69
- ctx.chdir(directory)
70
- yield
71
- rescue
72
- ctx.chdir(initial_directory)
73
- ctx.rm_r(directory)
74
- raise
75
- ensure
76
- ctx.chdir(initial_directory)
77
- end
68
+ def in_new_directory_context(script_project_repo)
69
+ script_project_repo.create_project_directory
70
+ yield
71
+ rescue Infrastructure::Errors::ScriptProjectAlreadyExistsError
72
+ raise
73
+ rescue
74
+ script_project_repo.delete_project_directory
75
+ raise
76
+ ensure
77
+ script_project_repo.change_to_initial_directory
78
78
  end
79
79
  end
80
80
  end
@@ -4,37 +4,61 @@ module Script
4
4
  module Layers
5
5
  module Application
6
6
  class ExtensionPoints
7
- def self.get(type:)
8
- Infrastructure::ExtensionPointRepository.new.get_extension_point(type)
9
- end
7
+ class << self
8
+ def get(type:)
9
+ extension_point_repository.get_extension_point(type)
10
+ end
10
11
 
11
- def self.types
12
- Infrastructure::ExtensionPointRepository.new.extension_point_types
13
- end
12
+ def types
13
+ extension_point_repository.extension_point_types
14
+ end
14
15
 
15
- def self.available_types
16
- Infrastructure::ExtensionPointRepository.new.extension_points.select do |ep|
17
- next false if ep.deprecated?
18
- !ep.beta? || ShopifyCLI::Feature.enabled?(:scripts_beta_extension_points)
19
- end.map(&:type)
20
- end
16
+ def available_types
17
+ available_extension_points.map(&:type)
18
+ end
21
19
 
22
- def self.deprecated_types
23
- Infrastructure::ExtensionPointRepository.new
24
- .extension_points
25
- .select(&:deprecated?)
26
- .map(&:type)
27
- end
20
+ def deprecated_types
21
+ extension_point_repository
22
+ .extension_points
23
+ .select(&:deprecated?)
24
+ .map(&:type)
25
+ end
28
26
 
29
- def self.languages(type:)
30
- get(type: type).libraries.all.map do |library|
31
- next nil if library.beta? && !ShopifyCLI::Feature.enabled?(:scripts_beta_languages)
32
- library.language
33
- end.compact
34
- end
27
+ def all_languages
28
+ available_extension_points
29
+ .map { |ep| ep.library_languages(include_betas: include_beta_languages?) }
30
+ .flatten
31
+ .uniq
32
+ end
33
+
34
+ def languages(type:)
35
+ get(type: type).library_languages(include_betas: include_beta_languages?)
36
+ end
37
+
38
+ def supported_language?(type:, language:)
39
+ languages(type: type).include?(language.downcase)
40
+ end
41
+
42
+ private
43
+
44
+ def available_extension_points
45
+ extension_point_repository.extension_points.select do |ep|
46
+ next false if ep.deprecated?
47
+ ep.stable? || include_beta_extension_points?
48
+ end
49
+ end
50
+
51
+ def extension_point_repository
52
+ Infrastructure::ExtensionPointRepository.new
53
+ end
54
+
55
+ def include_beta_languages?
56
+ ShopifyCLI::Feature.enabled?(:scripts_beta_languages)
57
+ end
35
58
 
36
- def self.supported_language?(type:, language:)
37
- languages(type: type).include?(language.downcase)
59
+ def include_beta_extension_points?
60
+ ShopifyCLI::Feature.enabled?(:scripts_beta_extension_points)
61
+ end
38
62
  end
39
63
  end
40
64
  end