shopify-cli 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/workflows/shopify.yml +106 -0
  4. data/.gitignore +2 -0
  5. data/CHANGELOG.md +6 -0
  6. data/CONTRIBUTING.md +23 -0
  7. data/Dockerfile +19 -0
  8. data/Gemfile +1 -0
  9. data/Gemfile.lock +50 -13
  10. data/Rakefile +66 -0
  11. data/dev.yml +11 -1
  12. data/ext/shopify-extensions/extconf.rb +21 -0
  13. data/ext/shopify-extensions/shopify_extensions.rb +152 -0
  14. data/ext/shopify-extensions/version +1 -0
  15. data/lib/project_types/extension/cli.rb +14 -0
  16. data/lib/project_types/extension/commands/build.rb +30 -2
  17. data/lib/project_types/extension/commands/create.rb +25 -0
  18. data/lib/project_types/extension/forms/create.rb +4 -1
  19. data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
  20. data/lib/project_types/extension/messages/messages.rb +3 -0
  21. data/lib/project_types/extension/models/development_server.rb +35 -0
  22. data/lib/project_types/extension/models/development_server_requirements.rb +17 -0
  23. data/lib/project_types/extension/models/server_config/base.rb +31 -0
  24. data/lib/project_types/extension/models/server_config/development.rb +23 -0
  25. data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
  26. data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
  27. data/lib/project_types/extension/models/server_config/extension.rb +35 -0
  28. data/lib/project_types/extension/models/server_config/root.rb +18 -0
  29. data/lib/project_types/extension/models/server_config/user.rb +10 -0
  30. data/lib/project_types/extension/tasks/choose_next_available_port.rb +1 -1
  31. data/lib/project_types/extension/tasks/run_extension_command.rb +58 -0
  32. data/lib/project_types/node/commands/create.rb +1 -5
  33. data/lib/project_types/rails/commands/create.rb +1 -5
  34. data/lib/project_types/script/cli.rb +2 -0
  35. data/lib/project_types/script/layers/application/push_script.rb +10 -1
  36. data/lib/project_types/script/layers/domain/push_package.rb +0 -12
  37. data/lib/project_types/script/layers/infrastructure/api_clients.rb +89 -0
  38. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +1 -1
  39. data/lib/project_types/script/layers/infrastructure/script_service.rb +26 -141
  40. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
  41. data/lib/project_types/script/tasks/ensure_env.rb +2 -2
  42. data/lib/project_types/script/ui/error_handler.rb +1 -1
  43. data/lib/shopify-cli/constants.rb +26 -0
  44. data/lib/shopify-cli/environment.rb +60 -0
  45. data/lib/shopify-cli/git.rb +2 -2
  46. data/lib/shopify-cli/identity_auth.rb +16 -23
  47. data/lib/shopify-cli/partners_api.rb +3 -27
  48. data/lib/shopify-cli/theme/dev_server/hot_reload.rb +4 -5
  49. data/lib/shopify-cli/theme/development_theme.rb +16 -2
  50. data/lib/shopify-cli/version.rb +1 -1
  51. data/lib/shopify_cli.rb +4 -2
  52. data/shopify-cli.gemspec +3 -3
  53. metadata +29 -9
  54. data/.github/workflows/build.yml +0 -28
@@ -3,6 +3,10 @@
3
3
  module Extension
4
4
  class Command
5
5
  class Create < ShopifyCli::SubCommand
6
+ DEVELOPMENT_SERVER_SUPPORTED_TYPES = [
7
+ "checkout_ui_extension",
8
+ ]
9
+
6
10
  prerequisite_task :ensure_authenticated
7
11
 
8
12
  options do |parser, flags|
@@ -18,6 +22,8 @@ module Extension
18
22
  @ctx.abort(message_for_extension["create.errors.directory_exists", form.directory_name])
19
23
  end
20
24
 
25
+ return use_new_create_flow(form, message_for_extension) if supports_development_server?(form.type)
26
+
21
27
  if form.type.create(form.directory_name, @ctx, getting_started: options.flags[:getting_started])
22
28
  ExtensionProject.write_cli_file(context: @ctx, type: form.type.identifier)
23
29
  ExtensionProject.write_env_file(
@@ -47,6 +53,25 @@ module Extension
47
53
 
48
54
  yield form, form.type.method(:message_for_extension)
49
55
  end
56
+
57
+ def supports_development_server?(type)
58
+ Models::DevelopmentServerRequirements.supported?(type.identifier)
59
+ end
60
+
61
+ def use_new_create_flow(form, msg)
62
+ Tasks::RunExtensionCommand.new(
63
+ root_dir: form.directory_name,
64
+ template: form.template,
65
+ type: form.type.identifier.downcase,
66
+ command: "create"
67
+ ).call
68
+
69
+ @ctx.puts(msg["create.ready_to_start", form.directory_name, form.name])
70
+ @ctx.puts(msg["create.learn_more", form.type.name])
71
+ rescue => error
72
+ @ctx.debug(error)
73
+ @ctx.puts(msg["create.try_again"])
74
+ end
50
75
  end
51
76
  end
52
77
  end
@@ -3,7 +3,7 @@
3
3
  module Extension
4
4
  module Forms
5
5
  class Create < ShopifyCli::Form
6
- flag_arguments :name, :type, :api_key
6
+ flag_arguments :name, :type, :api_key, :template
7
7
 
8
8
  attr_reader :app
9
9
 
@@ -13,6 +13,7 @@ module Extension
13
13
  property :app, accepts: Models::App
14
14
  property :name, accepts: String
15
15
  property :type, accepts: Models::SpecificationHandlers::Default
16
+ property :template, accepts: String
16
17
 
17
18
  def complete?
18
19
  !!(app && name && type)
@@ -23,6 +24,7 @@ module Extension
23
24
  ShopifyCli::Result.wrap(ExtensionProjectDetails.new)
24
25
  .then(&Questions::AskApp.new(ctx: ctx, api_key: api_key))
25
26
  .then(&Questions::AskType.new(ctx: ctx, type: type))
27
+ .then(&Questions::AskTemplate.new(ctx: ctx))
26
28
  .then(&Questions::AskName.new(ctx: ctx, name: name))
27
29
  .unwrap { |e| raise e }
28
30
  .tap do |project_details|
@@ -30,6 +32,7 @@ module Extension
30
32
 
31
33
  self.app = project_details.app
32
34
  self.type = project_details.type
35
+ self.template = project_details.template
33
36
  self.name = project_details.name
34
37
  end
35
38
  end
@@ -0,0 +1,44 @@
1
+ module Extension
2
+ module Forms
3
+ module Questions
4
+ class AskTemplate
5
+ include ShopifyCli::MethodObject
6
+
7
+ TEMPLATE_REQUIRED_TYPES = [
8
+ "checkout_ui_extension",
9
+ ]
10
+
11
+ property! :ctx
12
+ property :prompt,
13
+ accepts: ->(prompt) { prompt.respond_to?(:call) },
14
+ default: -> { CLI::UI::Prompt.method(:ask) }
15
+
16
+ def call(project_details)
17
+ return project_details unless template_required?(project_details)
18
+ project_details.template = choose_interactively
19
+ project_details
20
+ end
21
+
22
+ private
23
+
24
+ def template_required?(project_details)
25
+ return false unless extension_server_beta?
26
+ type = project_details&.type&.identifier
27
+ TEMPLATE_REQUIRED_TYPES.include?(type.downcase)
28
+ end
29
+
30
+ def extension_server_beta?
31
+ ShopifyCli::Shopifolk.check && ShopifyCli::Feature.enabled?(:extension_server_beta)
32
+ end
33
+
34
+ def choose_interactively
35
+ prompt.call(ctx.message("create.ask_template")) do |handler|
36
+ Models::ServerConfig::Development::VALID_TEMPLATES.each do |template|
37
+ handler.option(template) { template }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -45,6 +45,7 @@ module Extension
45
45
  "or try creating a new app using {{command:shopify [node|rails] create}}.",
46
46
  loading_apps: "Loading your apps…",
47
47
  no_available_extensions: "{{x}} There are no available extensions for this app.",
48
+ ask_template: "Select a template to use for your extension",
48
49
  },
49
50
  connect: {
50
51
  connected: "Project now connected to {{green:%s: %s}}",
@@ -67,6 +68,8 @@ module Extension
67
68
  HELP
68
69
  frame_title: "Building extension with: %s…",
69
70
  build_failure_message: "Failed to build extension code.",
71
+ build_success_message: "Build was successful!",
72
+ directory_not_found: "Build directory not found.",
70
73
  },
71
74
  register: {
72
75
  help: <<~HELP,
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ class DevelopmentServer
6
+ class DevelopmentServerError < StandardError; end
7
+
8
+ include SmartProperties
9
+
10
+ EXECUTABLE_PATH = "../../../../../ext/shopify-cli/shopify-extensions/shopify-extensions"
11
+
12
+ property! :executable, converts: :to_s, default: File.expand_path(EXECUTABLE_PATH, __FILE__)
13
+
14
+ def create(server_config)
15
+ CLI::Kit::System.capture3(executable, "create", "-", stdin_data: server_config.to_yaml)
16
+ rescue StandardError => error
17
+ raise error
18
+ end
19
+
20
+ def build(server_config)
21
+ _, error, pid = CLI::Kit::System.capture3(executable, "build", "-", stdin_data: server_config.to_yaml)
22
+ return if pid.success?
23
+ raise DevelopmentServerError, error
24
+ end
25
+
26
+ def serve
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def version
31
+ raise NotImplementedError
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Models
6
+ class DevelopmentServerRequirements
7
+ SUPPORTED_EXTENSION_TYPES = [
8
+ "checkout_ui_extension",
9
+ ]
10
+
11
+ def self.supported?(type)
12
+ return false unless SUPPORTED_EXTENSION_TYPES.include?(type.downcase)
13
+ ShopifyCli::Shopifolk.check && ShopifyCli::Feature.enabled?(:extension_server_beta)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class Base
7
+ def to_h
8
+ to_hash
9
+ end
10
+
11
+ def to_hash
12
+ is_hashable = ->(obj) { obj.respond_to?(:to_hash) }
13
+ is_collection_of_hashables = ->(obj) { obj.is_a?(Enumerable) && obj.all?(&is_hashable) }
14
+
15
+ self.class.properties.each.reduce({}) do |data, (_, property)|
16
+ data.merge(property.name.to_s => send(property.reader).yield_self do |value|
17
+ case value
18
+ when is_collection_of_hashables
19
+ value.map { |element| element.to_hash.transform_keys(&:to_s) }
20
+ when is_hashable
21
+ value.to_hash.transform_keys(&:to_s)
22
+ else
23
+ value
24
+ end
25
+ end)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ module Extension
2
+ module Models
3
+ module ServerConfig
4
+ class Development < Base
5
+ include SmartProperties
6
+ VALID_TEMPLATES = [
7
+ "javascript",
8
+ "javascript-react",
9
+ "typescript",
10
+ "typescript-react",
11
+ ]
12
+
13
+ CURRENT_DIRECTORY = "."
14
+
15
+ property :root_dir, accepts: String, default: CURRENT_DIRECTORY
16
+ property! :build_dir, accepts: String, default: "build"
17
+ property :template, accepts: VALID_TEMPLATES
18
+ property :renderer, accepts: ServerConfig::DevelopmentRenderer
19
+ property :entries, accepts: ServerConfig::DevelopmentEntries
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class DevelopmentEntries < Base
7
+ include SmartProperties
8
+
9
+ JAVASCRIPT = "javascript"
10
+ JAVASCRIPT_REACT = "javascript-react"
11
+ TYPESCRIPT = "typescript"
12
+ TYPESCRIPT_REACT = "typescript-react"
13
+
14
+ VALID_ENTRY_POINTS = [
15
+ "src/index.js",
16
+ "src/index.jsx",
17
+ "src/index.ts",
18
+ "src/index.tsx",
19
+ ]
20
+
21
+ property! :main, accepts: VALID_ENTRY_POINTS
22
+
23
+ def self.find(template)
24
+ case template
25
+ when JAVASCRIPT
26
+ new(main: "src/index.js")
27
+ when JAVASCRIPT_REACT
28
+ new(main: "src/index.jsx")
29
+ when TYPESCRIPT
30
+ new(main: "src/index.ts")
31
+ when TYPESCRIPT_REACT
32
+ new(main: "src/index.tsx")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class DevelopmentRenderer < Base
7
+ include SmartProperties
8
+
9
+ VALID_RENDERERS = [
10
+ "@shopify/admin-ui-extensions",
11
+ "@shopify/post-purchase-ui-extensions",
12
+ "@shopify/checkout-ui-extensions",
13
+ ]
14
+
15
+ property! :name, accepts: VALID_RENDERERS
16
+
17
+ def self.find(type)
18
+ case type.downcase
19
+ when "admin_ui_extension"
20
+ new(name: "@shopify/admin-ui-extensions")
21
+ when "checkout_ui_extension"
22
+ new(name: "@shopify/checkout-ui-extensions")
23
+ when "checkout_post_purchase"
24
+ new(name: "@shopify/post-purchase-ui-extensions")
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ require "securerandom"
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class Extension < Base
7
+ include SmartProperties
8
+ property! :uuid, accepts: String
9
+ property! :type, accepts: String
10
+ property! :user, accepts: ServerConfig::User
11
+ property! :development, accepts: ServerConfig::Development
12
+
13
+ def self.build(uuid: "", template:, type:, root_dir:)
14
+ renderer = ServerConfig::DevelopmentRenderer.find(type)
15
+ entry = ServerConfig::DevelopmentEntries.find(template)
16
+ new(
17
+ uuid: uuid.empty? ? generate_dev_uuid : uuid,
18
+ type: type.downcase,
19
+ user: ServerConfig::User.new,
20
+ development: ServerConfig::Development.new(
21
+ root_dir: root_dir,
22
+ template: template,
23
+ renderer: renderer,
24
+ entries: entry
25
+ )
26
+ )
27
+ end
28
+
29
+ def self.generate_dev_uuid
30
+ "dev-#{SecureRandom.uuid}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class Root < Base
7
+ include SmartProperties
8
+
9
+ property! :port, accepts: Integer, default: 39351
10
+ property! :extensions, accepts: Array, default: -> { [] }
11
+
12
+ def to_yaml
13
+ to_h.to_yaml.gsub("---\n", "")
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ module Extension
2
+ module Models
3
+ module ServerConfig
4
+ class User < Base
5
+ include SmartProperties
6
+ property! :metafields, accepts: Array, default: -> { [] }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -9,7 +9,7 @@ module Extension
9
9
 
10
10
  property! :from
11
11
  property! :to, default: -> { from + 10 }
12
- property! :host, default: "localhost"
12
+ property! :host, default: "127.0.0.1"
13
13
 
14
14
  def call
15
15
  available_port = port_range(from: from, to: to).find { |p| available?(host, p) }
@@ -0,0 +1,58 @@
1
+
2
+ # frozen_string_literal: true
3
+ require "shopify_cli"
4
+
5
+ module Extension
6
+ module Tasks
7
+ class RunExtensionCommand < ShopifyCli::Task
8
+ include SmartProperties
9
+
10
+ SUPPORTED_EXTENSION_TYPES = [
11
+ "checkout_ui_extension",
12
+ ]
13
+
14
+ SUPPORTED_COMMANDS = [
15
+ "create",
16
+ "build",
17
+ ]
18
+
19
+ property :root_dir, accepts: String
20
+ property :template, accepts: Models::ServerConfig::Development::VALID_TEMPLATES
21
+ property! :type, accepts: SUPPORTED_EXTENSION_TYPES
22
+ property! :command, accepts: SUPPORTED_COMMANDS
23
+
24
+ def call
25
+ ShopifyCli::Result
26
+ .call(&method(:build_extension))
27
+ .then(&method(:build_server_config))
28
+ .then(&method(:run_command))
29
+ .unwrap do |error|
30
+ raise error unless error.nil?
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def build_extension
37
+ Models::ServerConfig::Extension.build(
38
+ template: template,
39
+ type: type,
40
+ root_dir: root_dir,
41
+ )
42
+ end
43
+
44
+ def build_server_config(extension)
45
+ Models::ServerConfig::Root.new(extensions: [extension])
46
+ end
47
+
48
+ def run_command(server_config)
49
+ case command
50
+ when "create"
51
+ Models::DevelopmentServer.new.create(server_config)
52
+ when "build"
53
+ Models::DevelopmentServer.new.build(server_config)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -46,7 +46,7 @@ module Node
46
46
  scopes: "write_products,write_customers,write_draft_orders",
47
47
  ).write(@ctx)
48
48
 
49
- partners_url = ShopifyCli::PartnersAPI.partners_url_for(form.organization_id, api_client["id"], local_debug?)
49
+ partners_url = ShopifyCli::PartnersAPI.partners_url_for(form.organization_id, api_client["id"])
50
50
 
51
51
  @ctx.puts(@ctx.message("apps.create.info.created", form.title, partners_url))
52
52
  @ctx.puts(@ctx.message("apps.create.info.serve", form.name, ShopifyCli::TOOL_NAME, "node"))
@@ -120,10 +120,6 @@ module Node
120
120
  @ctx.debug(e)
121
121
  end
122
122
  end
123
-
124
- def local_debug?
125
- @ctx.getenv(ShopifyCli::PartnersAPI::LOCAL_DEBUG)
126
- end
127
123
  end
128
124
  end
129
125
  end
@@ -63,7 +63,7 @@ module Rails
63
63
  scopes: "write_products,write_customers,write_draft_orders",
64
64
  ).write(@ctx)
65
65
 
66
- partners_url = ShopifyCli::PartnersAPI.partners_url_for(form.organization_id, api_client["id"], local_debug?)
66
+ partners_url = ShopifyCli::PartnersAPI.partners_url_for(form.organization_id, api_client["id"])
67
67
 
68
68
  @ctx.puts(@ctx.message("apps.create.info.created", form.title, partners_url))
69
69
  @ctx.puts(@ctx.message("apps.create.info.serve", form.name, ShopifyCli::TOOL_NAME, "rails"))
@@ -178,10 +178,6 @@ module Rails
178
178
  def install_gem(name, version = nil)
179
179
  Gem.install(@ctx, name, version)
180
180
  end
181
-
182
- def local_debug?
183
- @ctx.getenv(ShopifyCli::PartnersAPI::LOCAL_DEBUG)
184
- end
185
181
  end
186
182
  end
187
183
  end
@@ -45,12 +45,14 @@ module Script
45
45
  end
46
46
 
47
47
  module Infrastructure
48
+ autoload :ApiClients, Project.project_filepath("layers/infrastructure/api_clients")
48
49
  autoload :Errors, Project.project_filepath("layers/infrastructure/errors")
49
50
  autoload :CommandRunner, Project.project_filepath("layers/infrastructure/command_runner")
50
51
  autoload :PushPackageRepository, Project.project_filepath("layers/infrastructure/push_package_repository")
51
52
  autoload :ExtensionPointRepository, Project.project_filepath("layers/infrastructure/extension_point_repository")
52
53
  autoload :ScriptProjectRepository, Project.project_filepath("layers/infrastructure/script_project_repository")
53
54
  autoload :ScriptService, Project.project_filepath("layers/infrastructure/script_service")
55
+ autoload :ScriptUploader, Project.project_filepath("layers/infrastructure/script_uploader")
54
56
 
55
57
  module Languages
56
58
  autoload :AssemblyScriptProjectCreator,
@@ -20,7 +20,16 @@ module Script
20
20
  compiled_type: task_runner.compiled_type,
21
21
  metadata: task_runner.metadata,
22
22
  )
23
- uuid = package.push(Infrastructure::ScriptService.new(ctx: p_ctx), script_project.api_key, force)
23
+ script_service = Infrastructure::ScriptService.new(ctx: p_ctx, api_key: script_project.api_key)
24
+ module_upload_url = Infrastructure::ScriptUploader.new(script_service).upload(package.script_content)
25
+ uuid = script_service.set_app_script(
26
+ uuid: package.uuid,
27
+ extension_point_type: package.extension_point_type,
28
+ force: force,
29
+ metadata: package.metadata,
30
+ script_json: package.script_json,
31
+ module_upload_url: module_upload_url,
32
+ )
24
33
  script_project_repo.update_env(uuid: uuid)
25
34
  spinner.update_title(p_ctx.message("script.application.pushed"))
26
35
  end
@@ -29,18 +29,6 @@ module Script
29
29
  @metadata = metadata
30
30
  @script_json = script_json
31
31
  end
32
-
33
- def push(script_service, api_key, force)
34
- script_service.push(
35
- uuid: @uuid,
36
- extension_point_type: @extension_point_type,
37
- script_content: @script_content,
38
- api_key: api_key,
39
- force: force,
40
- metadata: @metadata,
41
- script_json: @script_json,
42
- )
43
- end
44
32
  end
45
33
  end
46
34
  end
@@ -0,0 +1,89 @@
1
+ module Script
2
+ module Layers
3
+ module Infrastructure
4
+ class ApiClients
5
+ def self.default_client(ctx, api_key)
6
+ if ENV["BYPASS_PARTNERS_PROXY"]
7
+ ScriptServiceApiClient.new(ctx, api_key)
8
+ else
9
+ PartnersProxyApiClient.new(ctx, api_key)
10
+ end
11
+ end
12
+
13
+ class ScriptServiceApiClient
14
+ LOCAL_INSTANCE_URL = "https://script-service.myshopify.io"
15
+
16
+ def initialize(ctx, api_key)
17
+ instance_url = script_service_url
18
+ @api = ShopifyCli::API.new(
19
+ ctx: ctx,
20
+ url: "#{instance_url}/graphql",
21
+ token: { "APP_KEY" => api_key }.compact.to_json,
22
+ auth_header: "X-Shopify-Authenticated-Tokens"
23
+ )
24
+ end
25
+
26
+ def query(query_name, variables: {})
27
+ @api.query(query_name, variables: variables)
28
+ end
29
+
30
+ private
31
+
32
+ def script_service_url
33
+ if ::ShopifyCli::Environment.use_spin_partners_instance?
34
+ "https://script-service.#{::ShopifyCli::Environment.spin_url}"
35
+ else
36
+ LOCAL_INSTANCE_URL
37
+ end
38
+ end
39
+ end
40
+ private_constant(:ScriptServiceApiClient)
41
+
42
+ class PartnersProxyApiClient
43
+ def initialize(ctx, api_key)
44
+ @ctx = ctx
45
+ @api_key = api_key
46
+ end
47
+
48
+ def query(query_name, variables: {})
49
+ response = ShimAPI.query(@ctx, query_name, api_key: @api_key, variables: variables.to_json)
50
+ raise_if_graphql_failed(response)
51
+ JSON.parse(response["data"]["scriptServiceProxy"])
52
+ end
53
+
54
+ def raise_if_graphql_failed(response)
55
+ raise Errors::EmptyResponseError if response.nil?
56
+
57
+ return unless response.key?("errors")
58
+ case error_code(response["errors"])
59
+ when "forbidden"
60
+ raise Errors::ForbiddenError
61
+ when "forbidden_on_shop"
62
+ raise Errors::ShopAuthenticationError
63
+ when "app_not_installed_on_shop"
64
+ raise Errors::AppNotInstalledError
65
+ else
66
+ raise Errors::GraphqlError, response["errors"]
67
+ end
68
+ end
69
+
70
+ def error_code(errors)
71
+ errors.map do |e|
72
+ code = e.dig("extensions", "code")
73
+ return code if code
74
+ end
75
+ end
76
+
77
+ class ShimAPI < ShopifyCli::PartnersAPI
78
+ def query(query_name, variables: {})
79
+ variables[:query] = load_query(query_name)
80
+ super("script_service_proxy", variables: variables)
81
+ end
82
+ end
83
+ private_constant(:ShimAPI)
84
+ end
85
+ private_constant(:PartnersProxyApiClient)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -40,7 +40,7 @@ module Script
40
40
  def extension_point_version
41
41
  return extension_point.sdks.assemblyscript.version if extension_point.sdks.assemblyscript.versioned?
42
42
 
43
- out = command_runner.call("npm show #{extension_point.sdks.assemblyscript.package} version --json")
43
+ out = command_runner.call("npm -s show #{extension_point.sdks.assemblyscript.package} version --json")
44
44
  "^#{JSON.parse(out)}"
45
45
  end
46
46