shopify-cli 2.7.3 → 2.10.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +44 -0
- data/Gemfile.lock +1 -1
- data/RELEASING.md +4 -3
- data/dev.yml +2 -2
- data/ext/javy/javy.rb +8 -9
- data/lib/graphql/get_extension_registrations.graphql +27 -0
- data/lib/project_types/extension/cli.rb +27 -2
- data/lib/project_types/extension/commands/build.rb +10 -10
- data/lib/project_types/extension/commands/create.rb +2 -3
- data/lib/project_types/extension/commands/push.rb +36 -8
- data/lib/project_types/extension/extension_project.rb +1 -1
- data/lib/project_types/extension/features/argo_serve.rb +6 -5
- data/lib/project_types/extension/forms/questions/ask_registration.rb +6 -2
- data/lib/project_types/extension/loaders/project.rb +29 -0
- data/lib/project_types/extension/loaders/specification_handler.rb +22 -0
- data/lib/project_types/extension/messages/messages.rb +4 -0
- data/lib/project_types/extension/models/app.rb +1 -1
- data/lib/project_types/extension/models/development_server.rb +2 -4
- data/lib/project_types/extension/models/specification_handlers/default.rb +4 -0
- data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
- data/lib/project_types/extension/tasks/execute_commands/base.rb +13 -0
- data/lib/project_types/extension/tasks/execute_commands/build.rb +29 -0
- data/lib/project_types/extension/tasks/execute_commands/create.rb +33 -0
- data/lib/project_types/extension/tasks/execute_commands/serve.rb +35 -0
- data/lib/project_types/extension/tasks/merge_server_config.rb +33 -22
- data/lib/project_types/rails/gem.rb +1 -2
- data/lib/project_types/script/cli.rb +7 -0
- data/lib/project_types/script/commands/connect.rb +19 -0
- data/lib/project_types/script/commands/create.rb +8 -2
- data/lib/project_types/script/commands/push.rb +35 -12
- data/lib/project_types/script/layers/application/connect_app.rb +15 -3
- data/lib/project_types/script/layers/application/create_script.rb +16 -16
- data/lib/project_types/script/layers/application/extension_points.rb +50 -26
- data/lib/project_types/script/layers/application/push_script.rb +5 -2
- data/lib/project_types/script/layers/domain/errors.rb +3 -2
- data/lib/project_types/script/layers/domain/extension_point.rb +14 -0
- data/lib/project_types/script/layers/domain/script_config.rb +6 -4
- data/lib/project_types/script/layers/infrastructure/errors.rb +38 -23
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +49 -28
- data/lib/project_types/script/layers/infrastructure/script_service.rb +22 -5
- data/lib/project_types/script/loaders/project.rb +44 -0
- data/lib/project_types/script/loaders/specification_handler.rb +22 -0
- data/lib/project_types/script/messages/messages.rb +39 -16
- data/lib/project_types/script/ui/error_handler.rb +46 -29
- data/lib/project_types/theme/commands/pull.rb +45 -17
- data/lib/project_types/theme/commands/push.rb +65 -28
- data/lib/project_types/theme/commands/serve.rb +5 -0
- data/lib/project_types/theme/messages/messages.rb +34 -18
- data/lib/shopify_cli/command.rb +6 -0
- data/lib/shopify_cli/commands/login.rb +1 -1
- data/lib/shopify_cli/commands/switch.rb +1 -1
- data/lib/shopify_cli/constants.rb +11 -2
- data/lib/shopify_cli/context.rb +66 -12
- data/lib/shopify_cli/core/executor.rb +4 -4
- data/lib/shopify_cli/environment.rb +50 -20
- data/lib/shopify_cli/form.rb +2 -0
- data/lib/shopify_cli/identity_auth.rb +4 -3
- data/lib/shopify_cli/messages/messages.rb +9 -1
- data/lib/shopify_cli/method_object.rb +21 -9
- data/lib/shopify_cli/partners_api/app_extensions/job.rb +36 -0
- data/lib/shopify_cli/partners_api/app_extensions.rb +46 -0
- data/lib/shopify_cli/partners_api/organizations.rb +2 -5
- data/lib/shopify_cli/partners_api.rb +1 -0
- data/lib/shopify_cli/project.rb +8 -7
- data/lib/shopify_cli/resources/env_file.rb +18 -6
- data/lib/shopify_cli/result.rb +61 -59
- data/lib/shopify_cli/task.rb +5 -3
- data/lib/shopify_cli/theme/dev_server/cdn/cdn_helper.rb +49 -0
- data/lib/shopify_cli/theme/dev_server/cdn_assets.rb +69 -0
- data/lib/shopify_cli/theme/dev_server/cdn_fonts.rb +8 -28
- data/lib/shopify_cli/theme/dev_server/hot-reload.js +34 -3
- data/lib/shopify_cli/theme/dev_server/hot_reload.rb +18 -2
- data/lib/shopify_cli/theme/dev_server/local_assets.rb +4 -0
- data/lib/shopify_cli/theme/dev_server/proxy/template_param_builder.rb +84 -0
- data/lib/shopify_cli/theme/dev_server/proxy.rb +10 -15
- data/lib/shopify_cli/theme/dev_server/reload_mode.rb +34 -0
- data/lib/shopify_cli/theme/dev_server.rb +8 -21
- data/lib/shopify_cli/theme/file.rb +2 -2
- data/lib/shopify_cli/theme/filter/path_matcher.rb +38 -0
- data/lib/shopify_cli/theme/ignore_filter.rb +14 -18
- data/lib/shopify_cli/theme/include_filter.rb +43 -0
- data/lib/shopify_cli/theme/syncer.rb +17 -2
- data/lib/shopify_cli/theme/theme.rb +26 -4
- data/lib/shopify_cli/thread_pool/job.rb +27 -0
- data/lib/shopify_cli/thread_pool.rb +37 -0
- data/lib/shopify_cli/version.rb +1 -1
- data/lib/shopify_cli.rb +6 -1
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +3 -1
- data/vendor/deps/ruby2_keywords/LICENSE +22 -0
- data/vendor/deps/ruby2_keywords/README.md +67 -0
- data/vendor/deps/ruby2_keywords/Rakefile +54 -0
- data/vendor/deps/ruby2_keywords/lib/ruby2_keywords.rb +57 -0
- data/vendor/deps/ruby2_keywords/ruby2_keywords.gemspec +18 -0
- data/vendor/deps/ruby2_keywords/test/test_keyword.rb +41 -0
- metadata +28 -4
- data/lib/graphql/all_orgs_with_extensions.graphql +0 -37
- data/lib/project_types/extension/tasks/run_extension_command.rb +0 -82
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cgi"
|
|
4
|
+
|
|
5
|
+
module ShopifyCLI
|
|
6
|
+
module Theme
|
|
7
|
+
module DevServer
|
|
8
|
+
class Proxy
|
|
9
|
+
class TemplateParamBuilder
|
|
10
|
+
def build
|
|
11
|
+
# Core doesn't support replace_templates
|
|
12
|
+
return {} if core?(current_path)
|
|
13
|
+
|
|
14
|
+
(syncer_templates + request_templates)
|
|
15
|
+
.select { |file| file.liquid? || file.json? }
|
|
16
|
+
.uniq(&:relative_path)
|
|
17
|
+
.map { |file| as_param(file) }
|
|
18
|
+
.to_h
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def with_core_endpoints(core_endpoints)
|
|
22
|
+
@core_endpoints = core_endpoints
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def with_syncer(syncer)
|
|
27
|
+
@syncer = syncer
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def with_rack_env(rack_env)
|
|
32
|
+
@rack_env = rack_env
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def with_theme(theme)
|
|
37
|
+
@theme = theme
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def as_param(file)
|
|
44
|
+
["replace_templates[#{file.relative_path}]", file.read]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def syncer_templates
|
|
48
|
+
@syncer&.pending_updates || []
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def request_templates
|
|
52
|
+
cookie_sections
|
|
53
|
+
.map { |section| @theme[section] unless @theme.nil? }
|
|
54
|
+
.compact
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def cookie_sections
|
|
58
|
+
CGI::Cookie.parse(cookie)["hot_reload_sections"].join.split(",") || []
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def core?(path)
|
|
62
|
+
core_endpoints.include?(path)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def current_path
|
|
66
|
+
rack_env["PATH_INFO"]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def cookie
|
|
70
|
+
rack_env["HTTP_COOKIE"]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def core_endpoints
|
|
74
|
+
@core_endpoints || []
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def rack_env
|
|
78
|
+
@rack_env || {}
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
require "net/http"
|
|
3
3
|
require "stringio"
|
|
4
4
|
require "time"
|
|
5
|
+
require "cgi"
|
|
6
|
+
|
|
7
|
+
require_relative "proxy/template_param_builder"
|
|
5
8
|
|
|
6
9
|
module ShopifyCLI
|
|
7
10
|
module Theme
|
|
@@ -15,6 +18,7 @@ module ShopifyCLI
|
|
|
15
18
|
"trailer",
|
|
16
19
|
"transfer-encoding",
|
|
17
20
|
"upgrade",
|
|
21
|
+
"content-security-policy",
|
|
18
22
|
]
|
|
19
23
|
|
|
20
24
|
class Proxy
|
|
@@ -112,21 +116,12 @@ module ShopifyCLI
|
|
|
112
116
|
end
|
|
113
117
|
|
|
114
118
|
def build_replace_templates_param(env)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
# Only replace Liquid or JSON files
|
|
122
|
-
file.liquid? || file.json?
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
pending_templates.each do |path|
|
|
126
|
-
params["replace_templates[#{path.relative_path}]"] = path.read
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
params
|
|
119
|
+
TemplateParamBuilder.new
|
|
120
|
+
.with_core_endpoints(@core_endpoints)
|
|
121
|
+
.with_syncer(@syncer)
|
|
122
|
+
.with_theme(@theme)
|
|
123
|
+
.with_rack_env(env)
|
|
124
|
+
.build
|
|
130
125
|
end
|
|
131
126
|
|
|
132
127
|
def add_session_cookie(cookie_header)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyCLI
|
|
4
|
+
module Theme
|
|
5
|
+
module DevServer
|
|
6
|
+
class ReloadMode
|
|
7
|
+
MODES = [:"hot-reload", :"full-page", :off]
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def default
|
|
11
|
+
:"hot-reload"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get!(mode)
|
|
15
|
+
MODES.find { |m| m == mode.to_sym } || raise_error(mode)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def raise_error(invalid_mode)
|
|
21
|
+
error_message = ShopifyCLI::Context.message("theme.serve.reload_mode_is_not_valid", invalid_mode)
|
|
22
|
+
help_message = ShopifyCLI::Context.message("theme.serve.try_a_valid_reload_mode", valid_modes)
|
|
23
|
+
|
|
24
|
+
ShopifyCLI::Context.abort(error_message, help_message)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def valid_modes
|
|
28
|
+
MODES.map { |v| "`#{v}`" }.join(", ")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -3,9 +3,11 @@ require_relative "development_theme"
|
|
|
3
3
|
require_relative "ignore_filter"
|
|
4
4
|
require_relative "syncer"
|
|
5
5
|
|
|
6
|
+
require_relative "dev_server/cdn_assets"
|
|
6
7
|
require_relative "dev_server/cdn_fonts"
|
|
7
8
|
require_relative "dev_server/hot_reload"
|
|
8
9
|
require_relative "dev_server/header_hash"
|
|
10
|
+
require_relative "dev_server/reload_mode"
|
|
9
11
|
require_relative "dev_server/local_assets"
|
|
10
12
|
require_relative "dev_server/proxy"
|
|
11
13
|
require_relative "dev_server/sse"
|
|
@@ -25,7 +27,7 @@ module ShopifyCLI
|
|
|
25
27
|
class << self
|
|
26
28
|
attr_accessor :ctx
|
|
27
29
|
|
|
28
|
-
def start(ctx, root, host: "127.0.0.1", port: 9292, poll: false)
|
|
30
|
+
def start(ctx, root, host: "127.0.0.1", port: 9292, poll: false, mode: ReloadMode.default)
|
|
29
31
|
@ctx = ctx
|
|
30
32
|
theme = DevelopmentTheme.new(ctx, root: root)
|
|
31
33
|
ignore_filter = IgnoreFilter.from_path(root)
|
|
@@ -36,7 +38,8 @@ module ShopifyCLI
|
|
|
36
38
|
@app = Proxy.new(ctx, theme: theme, syncer: @syncer)
|
|
37
39
|
@app = CdnFonts.new(@app, theme: theme)
|
|
38
40
|
@app = LocalAssets.new(ctx, @app, theme: theme)
|
|
39
|
-
@app =
|
|
41
|
+
@app = CdnAssets.new(@app, theme: theme)
|
|
42
|
+
@app = HotReload.new(ctx, @app, theme: theme, watcher: watcher, mode: mode, ignore_filter: ignore_filter)
|
|
40
43
|
stopped = false
|
|
41
44
|
address = "http://#{host}:#{port}"
|
|
42
45
|
|
|
@@ -83,7 +86,9 @@ module ShopifyCLI
|
|
|
83
86
|
ShopifyCLI::API::APIRequestUnauthorizedError
|
|
84
87
|
raise ShopifyCLI::Abort, @ctx.message("theme.serve.ensure_user", theme.shop)
|
|
85
88
|
rescue Errno::EADDRINUSE
|
|
86
|
-
|
|
89
|
+
error_message = @ctx.message("theme.serve.address_already_in_use", address)
|
|
90
|
+
help_message = @ctx.message("theme.serve.try_port_option")
|
|
91
|
+
@ctx.abort(error_message, help_message)
|
|
87
92
|
rescue Errno::EADDRNOTAVAIL
|
|
88
93
|
raise AddressBindingError, "Error binding to the address #{host}."
|
|
89
94
|
end
|
|
@@ -94,24 +99,6 @@ module ShopifyCLI
|
|
|
94
99
|
@syncer.shutdown
|
|
95
100
|
WebServer.shutdown
|
|
96
101
|
end
|
|
97
|
-
|
|
98
|
-
private
|
|
99
|
-
|
|
100
|
-
def abort_address_already_in_use(address)
|
|
101
|
-
open_frame(@ctx.message("theme.serve.already_in_use_error"), color: :red) do
|
|
102
|
-
@ctx.puts(@ctx.message("theme.serve.address_already_in_use", address))
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
open_frame(@ctx.message("theme.serve.try_this"), color: :green) do
|
|
106
|
-
@ctx.puts(@ctx.message("theme.serve.try_port_option"))
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
raise ShopifyCLI::AbortSilent
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def open_frame(title, color:, &block)
|
|
113
|
-
CLI::UI::Frame.open(title, color: CLI::UI.resolve_color(color), timing: false, &block)
|
|
114
|
-
end
|
|
115
102
|
end
|
|
116
103
|
end
|
|
117
104
|
end
|
|
@@ -18,7 +18,7 @@ module ShopifyCLI
|
|
|
18
18
|
|
|
19
19
|
def read
|
|
20
20
|
if text?
|
|
21
|
-
path.read
|
|
21
|
+
path.read(universal_newline: true)
|
|
22
22
|
else
|
|
23
23
|
path.read(mode: "rb")
|
|
24
24
|
end
|
|
@@ -27,7 +27,7 @@ module ShopifyCLI
|
|
|
27
27
|
def write(content)
|
|
28
28
|
path.parent.mkpath unless path.parent.directory?
|
|
29
29
|
if text?
|
|
30
|
-
path.write(content)
|
|
30
|
+
path.write(content, universal_newline: true)
|
|
31
31
|
else
|
|
32
32
|
path.write(content, 0, mode: "wb")
|
|
33
33
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyCLI
|
|
4
|
+
module Theme
|
|
5
|
+
module Filter
|
|
6
|
+
module PathMatcher
|
|
7
|
+
def regex_match?(regex, path)
|
|
8
|
+
regex.match?(path)
|
|
9
|
+
rescue StandardError
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def glob_match?(glob, path)
|
|
14
|
+
!!::File.fnmatch?(glob, path)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def regex?(pattern)
|
|
18
|
+
pattern.start_with?("/") && pattern.end_with?("/")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def as_regex(pattern)
|
|
22
|
+
Regexp.new(pattern.gsub(%r{^\/|\/$}, ""))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def as_glob(pattern)
|
|
26
|
+
# if specifying a directory, match everything below it
|
|
27
|
+
pattern += "*" if pattern.end_with?("/")
|
|
28
|
+
|
|
29
|
+
# The pattern will be scoped to root directory, so it should match anything
|
|
30
|
+
# within that space
|
|
31
|
+
pattern.prepend("*") unless pattern.start_with?("*")
|
|
32
|
+
|
|
33
|
+
pattern
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "filter/path_matcher"
|
|
4
|
+
|
|
3
5
|
module ShopifyCLI
|
|
4
6
|
module Theme
|
|
5
7
|
class IgnoreFilter
|
|
8
|
+
include Filter::PathMatcher
|
|
9
|
+
|
|
6
10
|
FILE = ".shopifyignore"
|
|
7
11
|
|
|
8
12
|
DEFAULT_REGEXES = [
|
|
@@ -72,11 +76,11 @@ module ShopifyCLI
|
|
|
72
76
|
return true if path.empty?
|
|
73
77
|
|
|
74
78
|
regexes.each do |regex|
|
|
75
|
-
return true if regex
|
|
79
|
+
return true if regex_match?(regex, path)
|
|
76
80
|
end
|
|
77
81
|
|
|
78
82
|
globs.each do |glob|
|
|
79
|
-
return true if
|
|
83
|
+
return true if glob_match?(glob, path)
|
|
80
84
|
end
|
|
81
85
|
|
|
82
86
|
false
|
|
@@ -91,24 +95,16 @@ module ShopifyCLI
|
|
|
91
95
|
new_regexes = DEFAULT_REGEXES.dup
|
|
92
96
|
new_globs = DEFAULT_GLOBS.dup
|
|
93
97
|
|
|
94
|
-
patterns
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
patterns
|
|
99
|
+
.map(&:strip)
|
|
100
|
+
.each do |pattern|
|
|
101
|
+
if regex?(pattern)
|
|
102
|
+
new_regexes << as_regex(pattern)
|
|
103
|
+
else
|
|
104
|
+
new_globs << as_glob(pattern)
|
|
105
|
+
end
|
|
100
106
|
end
|
|
101
107
|
|
|
102
|
-
# if specifying a directory, match everything below it
|
|
103
|
-
pattern += "*" if pattern.end_with?("/")
|
|
104
|
-
|
|
105
|
-
# The pattern will be scoped to root directory, so it should match anything
|
|
106
|
-
# within that space
|
|
107
|
-
pattern.prepend("*") unless pattern.start_with?("*")
|
|
108
|
-
|
|
109
|
-
new_globs << pattern
|
|
110
|
-
end
|
|
111
|
-
|
|
112
108
|
[new_regexes, new_globs]
|
|
113
109
|
end
|
|
114
110
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "filter/path_matcher"
|
|
4
|
+
|
|
5
|
+
module ShopifyCLI
|
|
6
|
+
module Theme
|
|
7
|
+
class IncludeFilter
|
|
8
|
+
include Filter::PathMatcher
|
|
9
|
+
|
|
10
|
+
def initialize(pattern = nil)
|
|
11
|
+
@pattern = pattern
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def match?(path)
|
|
15
|
+
return true unless present?(@pattern)
|
|
16
|
+
|
|
17
|
+
if regex_pattern?
|
|
18
|
+
regex_match?(regex_pattern, path)
|
|
19
|
+
else
|
|
20
|
+
glob_match?(glob_pattern, path)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def present?(pattern)
|
|
27
|
+
!pattern.nil? && !pattern.empty?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def regex_pattern?
|
|
31
|
+
@is_regex_pattern ||= regex?(@pattern)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def regex_pattern
|
|
35
|
+
@regex_pattern ||= as_regex(@pattern)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def glob_pattern
|
|
39
|
+
@glob_pattern ||= as_glob(@pattern)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -16,13 +16,15 @@ module ShopifyCLI
|
|
|
16
16
|
API_VERSION = "unstable"
|
|
17
17
|
|
|
18
18
|
attr_reader :checksums
|
|
19
|
+
attr_accessor :include_filter
|
|
19
20
|
attr_accessor :ignore_filter
|
|
20
21
|
|
|
21
22
|
def_delegators :@error_reporter, :has_any_error?
|
|
22
23
|
|
|
23
|
-
def initialize(ctx, theme:, ignore_filter: nil)
|
|
24
|
+
def initialize(ctx, theme:, include_filter: nil, ignore_filter: nil)
|
|
24
25
|
@ctx = ctx
|
|
25
26
|
@theme = theme
|
|
27
|
+
@include_filter = include_filter
|
|
26
28
|
@ignore_filter = ignore_filter
|
|
27
29
|
@error_reporter = ErrorReporter.new(ctx)
|
|
28
30
|
@standard_reporter = StandardReporter.new(ctx)
|
|
@@ -193,7 +195,7 @@ module ShopifyCLI
|
|
|
193
195
|
# Already enqueued
|
|
194
196
|
return if @pending.include?(operation)
|
|
195
197
|
|
|
196
|
-
if
|
|
198
|
+
if ignore?(operation)
|
|
197
199
|
@ctx.debug("ignore #{operation.file_path}")
|
|
198
200
|
return
|
|
199
201
|
end
|
|
@@ -251,6 +253,19 @@ module ShopifyCLI
|
|
|
251
253
|
response
|
|
252
254
|
end
|
|
253
255
|
|
|
256
|
+
def ignore?(operation)
|
|
257
|
+
path = operation.file_path
|
|
258
|
+
ignored_by_ignore_filter?(path) || ignored_by_include_filter?(path)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def ignored_by_ignore_filter?(path)
|
|
262
|
+
ignore_filter&.ignore?(path)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def ignored_by_include_filter?(path)
|
|
266
|
+
include_filter && !include_filter.match?(path)
|
|
267
|
+
end
|
|
268
|
+
|
|
254
269
|
def get(file)
|
|
255
270
|
_status, body, response = ShopifyCLI::AdminAPI.rest_request(
|
|
256
271
|
@ctx,
|
|
@@ -173,15 +173,37 @@ module ShopifyCLI
|
|
|
173
173
|
end
|
|
174
174
|
|
|
175
175
|
def live(ctx, root: nil)
|
|
176
|
-
|
|
176
|
+
find(ctx, root) { |attrs| attrs["role"] == "main" }
|
|
177
|
+
end
|
|
177
178
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
def development(ctx, root: nil)
|
|
180
|
+
find(ctx, root) { |attrs| attrs["role"] == "development" }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Finds a Theme by its identifier
|
|
184
|
+
#
|
|
185
|
+
# #### Parameters
|
|
186
|
+
# * `ctx` - current running context of your command
|
|
187
|
+
# * `root` - theme root
|
|
188
|
+
# * `identifier` - theme ID or theme name
|
|
189
|
+
def find_by_identifier(ctx, root: nil, identifier:)
|
|
190
|
+
find(ctx, root) do |attrs|
|
|
191
|
+
attrs.slice("name", "id").values.map(&:to_s).include?(identifier)
|
|
192
|
+
end
|
|
181
193
|
end
|
|
182
194
|
|
|
183
195
|
private
|
|
184
196
|
|
|
197
|
+
def find(ctx, root, &block)
|
|
198
|
+
_status, body = fetch_themes(ctx)
|
|
199
|
+
|
|
200
|
+
body["themes"]
|
|
201
|
+
.find(&block)
|
|
202
|
+
.tap do |attrs|
|
|
203
|
+
break new(ctx, root: root, **allowed_attrs(attrs)) if attrs
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
185
207
|
def allowed_attrs(attrs)
|
|
186
208
|
attrs.slice("id", "name", "role").transform_keys(&:to_sym)
|
|
187
209
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyCLI
|
|
4
|
+
class ThreadPool
|
|
5
|
+
class Job
|
|
6
|
+
attr_reader :error
|
|
7
|
+
|
|
8
|
+
def perform!
|
|
9
|
+
raise "`#{self.class.name}#perform!` must be defined"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
perform!
|
|
14
|
+
rescue StandardError => error
|
|
15
|
+
@error = error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def success?
|
|
19
|
+
!@error
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def error?
|
|
23
|
+
!!@error
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyCLI
|
|
4
|
+
class ThreadPool
|
|
5
|
+
attr_reader :errors
|
|
6
|
+
|
|
7
|
+
def initialize(pool_size: 10)
|
|
8
|
+
@jobs = Queue.new
|
|
9
|
+
@pool = Array.new(pool_size) { spawn_thread }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def schedule(job)
|
|
13
|
+
@jobs << job
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def shutdown
|
|
17
|
+
@pool.size.times do
|
|
18
|
+
schedule(-> { throw(:stop_thread) })
|
|
19
|
+
end
|
|
20
|
+
@pool.map(&:join)
|
|
21
|
+
ensure
|
|
22
|
+
@jobs.close
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def spawn_thread
|
|
28
|
+
Thread.new do
|
|
29
|
+
catch(:stop_thread) do
|
|
30
|
+
loop do
|
|
31
|
+
@jobs.pop.call
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/shopify_cli/version.rb
CHANGED
data/lib/shopify_cli.rb
CHANGED
|
@@ -15,12 +15,13 @@ ENV["PATH"] = ENV["PATH"].split(":").select { |p| p.start_with?("/", "~") }.join
|
|
|
15
15
|
vendor_path = File.expand_path("../../vendor/lib", __FILE__)
|
|
16
16
|
$LOAD_PATH.unshift(vendor_path) unless $LOAD_PATH.include?(vendor_path)
|
|
17
17
|
|
|
18
|
-
deps = %w(cli-ui cli-kit smart_properties webrick)
|
|
18
|
+
deps = %w(cli-ui cli-kit smart_properties ruby2_keywords webrick)
|
|
19
19
|
deps.each do |dep|
|
|
20
20
|
vendor_path = File.expand_path("../../vendor/deps/#{dep}/lib", __FILE__)
|
|
21
21
|
$LOAD_PATH.unshift(vendor_path) unless $LOAD_PATH.include?(vendor_path)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
require "ruby2_keywords"
|
|
24
25
|
require "cli/ui"
|
|
25
26
|
require "cli/kit"
|
|
26
27
|
require "smart_properties"
|
|
@@ -139,6 +140,10 @@ module ShopifyCLI
|
|
|
139
140
|
require "shopify_cli/messages/messages"
|
|
140
141
|
Context.load_messages(ShopifyCLI::Messages::MESSAGES)
|
|
141
142
|
|
|
143
|
+
# cli-ui utilities for capturing the output close the stream while capturing.
|
|
144
|
+
# By setting the value here we persist the tty value for the whole lifetime of the process.
|
|
145
|
+
Environment.interactive = $stdin.tty?
|
|
146
|
+
|
|
142
147
|
def self.cache_dir
|
|
143
148
|
cache_dir = if Environment.test?
|
|
144
149
|
TEMP_DIR
|
|
@@ -114,7 +114,9 @@ module CLI
|
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
def print_error_message(e)
|
|
117
|
-
|
|
117
|
+
CLI::UI::Frame.open("Error", color: :red, timing: false) do
|
|
118
|
+
$stderr.puts(format_error_message(e.message))
|
|
119
|
+
end
|
|
118
120
|
end
|
|
119
121
|
end
|
|
120
122
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright 2019-2020 Nobuyoshi Nakada, Yusuke Endoh
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
7
|
+
list of conditions and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
|
11
|
+
and/or other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
17
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
18
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
19
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
20
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
21
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
22
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# ruby2_keywords
|
|
2
|
+
|
|
3
|
+
Provides empty `Module#ruby2_keywords` method, for the forward
|
|
4
|
+
source-level compatibility against ruby2.7 and ruby3.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Add this line to your application's Gemfile:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'ruby2_keywords'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And then execute:
|
|
15
|
+
|
|
16
|
+
$ bundle
|
|
17
|
+
|
|
18
|
+
Or install it yourself as:
|
|
19
|
+
|
|
20
|
+
$ gem install ruby2_keywords
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
For class/module instance methods:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
require 'ruby2_keywords'
|
|
28
|
+
|
|
29
|
+
module YourModule
|
|
30
|
+
ruby2_keywords def delegating_method(*args)
|
|
31
|
+
other_method(*args)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For global methods:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
require 'ruby2_keywords'
|
|
40
|
+
|
|
41
|
+
ruby2_keywords def oldstyle_keywords(options = {})
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
You can do the same for a method defined by `Module#define_method`:
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
define_method :delegating_method do |*args, &block|
|
|
49
|
+
other_method(*args, &block)
|
|
50
|
+
end
|
|
51
|
+
ruby2_keywords :delegating_method
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Contributing
|
|
55
|
+
|
|
56
|
+
Bug reports and pull requests are welcome on [GitHub] or
|
|
57
|
+
[Ruby Issue Tracking System].
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
The gem is available as open source under the terms of the
|
|
62
|
+
[Ruby License] or the [2-Clause BSD License].
|
|
63
|
+
|
|
64
|
+
[GitHub]: https://github.com/ruby/ruby2_keywords/
|
|
65
|
+
[Ruby Issue Tracking System]: https://bugs.ruby-lang.org
|
|
66
|
+
[Ruby License]: https://www.ruby-lang.org/en/about/license.txt
|
|
67
|
+
[2-Clause BSD License]: https://opensource.org/licenses/BSD-2-Clause
|