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.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/workflows/shopify.yml +106 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +23 -0
- data/Dockerfile +19 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +50 -13
- data/Rakefile +66 -0
- data/dev.yml +11 -1
- data/ext/shopify-extensions/extconf.rb +21 -0
- data/ext/shopify-extensions/shopify_extensions.rb +152 -0
- data/ext/shopify-extensions/version +1 -0
- data/lib/project_types/extension/cli.rb +14 -0
- data/lib/project_types/extension/commands/build.rb +30 -2
- data/lib/project_types/extension/commands/create.rb +25 -0
- data/lib/project_types/extension/forms/create.rb +4 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
- data/lib/project_types/extension/messages/messages.rb +3 -0
- data/lib/project_types/extension/models/development_server.rb +35 -0
- data/lib/project_types/extension/models/development_server_requirements.rb +17 -0
- data/lib/project_types/extension/models/server_config/base.rb +31 -0
- data/lib/project_types/extension/models/server_config/development.rb +23 -0
- data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
- data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
- data/lib/project_types/extension/models/server_config/extension.rb +35 -0
- data/lib/project_types/extension/models/server_config/root.rb +18 -0
- data/lib/project_types/extension/models/server_config/user.rb +10 -0
- data/lib/project_types/extension/tasks/choose_next_available_port.rb +1 -1
- data/lib/project_types/extension/tasks/run_extension_command.rb +58 -0
- data/lib/project_types/node/commands/create.rb +1 -5
- data/lib/project_types/rails/commands/create.rb +1 -5
- data/lib/project_types/script/cli.rb +2 -0
- data/lib/project_types/script/layers/application/push_script.rb +10 -1
- data/lib/project_types/script/layers/domain/push_package.rb +0 -12
- data/lib/project_types/script/layers/infrastructure/api_clients.rb +89 -0
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/script_service.rb +26 -141
- data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
- data/lib/project_types/script/tasks/ensure_env.rb +2 -2
- data/lib/project_types/script/ui/error_handler.rb +1 -1
- data/lib/shopify-cli/constants.rb +26 -0
- data/lib/shopify-cli/environment.rb +60 -0
- data/lib/shopify-cli/git.rb +2 -2
- data/lib/shopify-cli/identity_auth.rb +16 -23
- data/lib/shopify-cli/partners_api.rb +3 -27
- data/lib/shopify-cli/theme/dev_server/hot_reload.rb +4 -5
- data/lib/shopify-cli/theme/development_theme.rb +16 -2
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +4 -2
- data/shopify-cli.gemspec +3 -3
- metadata +29 -9
- 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,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"]
|
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"]
|
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
|
-
|
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
|
data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb
CHANGED
@@ -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
|
|