shopify-cli 2.3.0 → 2.4.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 (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