shopify-cli 2.16.1 → 2.17.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/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/lib/project_types/extension/cli.rb +1 -0
- data/lib/project_types/extension/commands/build.rb +0 -2
- data/lib/project_types/extension/commands/serve.rb +8 -3
- data/lib/project_types/extension/features/argo_serve.rb +1 -1
- data/lib/project_types/extension/models/server_config/capabilities.rb +11 -0
- data/lib/project_types/extension/models/server_config/extension.rb +10 -3
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
- data/lib/project_types/extension/tasks/convert_server_config.rb +7 -3
- data/lib/project_types/extension/tasks/merge_server_config.rb +4 -2
- data/lib/project_types/script/cli.rb +1 -0
- data/lib/project_types/script/config/extension_points.yml +15 -3
- data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
- data/lib/project_types/script/layers/application/push_script.rb +1 -0
- data/lib/project_types/script/layers/domain/app_bridge.rb +16 -0
- data/lib/project_types/script/layers/domain/script_project.rb +1 -0
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +12 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +5 -0
- data/lib/project_types/theme/commands/serve.rb +27 -0
- data/lib/project_types/theme/messages/messages.rb +13 -0
- data/lib/shopify_cli/admin_api.rb +1 -1
- data/lib/shopify_cli/commands/login.rb +2 -2
- data/lib/shopify_cli/context.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb +5 -6
- data/lib/shopify_cli/theme/dev_server/watcher.rb +2 -1
- data/lib/shopify_cli/theme/dev_server.rb +1 -1
- data/lib/shopify_cli/theme/development_theme.rb +11 -1
- data/lib/shopify_cli/theme/file.rb +9 -0
- data/lib/shopify_cli/theme/theme_admin_api.rb +3 -1
- data/lib/shopify_cli/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3acc31975c1b9d6478fe3f5d39ebf4ca0550b5956dc22dd4710103ae77bb0b4
|
4
|
+
data.tar.gz: 2cbf01bd46b9d3d175b6b4f534f28b52ce69972125169a243788d922a68bf19a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7999265576034095a1114c3a29a2ab9bbaee62bac8c29b26b79d2c724b8be1dbc045e0da7c94a1863e465545bd7be32851f2f36ae1b020a269346d4417c0008c
|
7
|
+
data.tar.gz: e5affc3532841d156305192ad2aa775065a9571a7bbf8ee6ab7b56d7f5d62c7a30407cf25e658bb99283d8429eb1b009ff406651fa7915c9e2a07508923be993
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,21 @@ From version 2.6.0, the sections in this file adhere to the [keep a changelog](h
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## Version 2.17.0 - 2022-05-12
|
6
|
+
|
7
|
+
### Added
|
8
|
+
* [#2262](https://github.com/Shopify/shopify-cli/pull/2262): Add `capabilities` permissions to checkout extensions config
|
9
|
+
* [#2292](https://github.com/Shopify/shopify-cli/pull/2292): Add support for App Bridge create/details URLs for scripts
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
* [#2287](https://github.com/Shopify/shopify-cli/pull/2287): Fix `Encoding::UndefinedConversionError` on `theme serve` and `theme pull`
|
13
|
+
* [#2310](https://github.com/Shopify/shopify-cli/pull/2310): Fix live-reload to be resilient and no longer raise an error when a locale file is invalid
|
14
|
+
* [#2297](https://github.com/Shopify/shopify-cli/pull/2297): Only show update message when the new version is higher
|
15
|
+
* [#2270](https://github.com/Shopify/shopify-cli/pull/2270): Use ignore filter regex in watcher class
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
* [#2299](https://github.com/Shopify/shopify-cli/pull/2299): Improve the unauthorized API errors when doing theme development
|
19
|
+
|
5
20
|
## Version 2.16.1 - 2022-04-26
|
6
21
|
|
7
22
|
### Fixed
|
data/Gemfile.lock
CHANGED
@@ -122,6 +122,7 @@ module Extension
|
|
122
122
|
module ServerConfig
|
123
123
|
autoload :Base, Project.project_filepath("models/server_config/base")
|
124
124
|
autoload :App, Project.project_filepath("models/server_config/app")
|
125
|
+
autoload :Capabilities, Project.project_filepath("models/server_config/capabilities")
|
125
126
|
autoload :Development, Project.project_filepath("models/server_config/development")
|
126
127
|
autoload :DevelopmentEntries, Project.project_filepath("models/server_config/development_entries")
|
127
128
|
autoload :DevelopmentRenderer, Project.project_filepath("models/server_config/development_renderer")
|
@@ -14,6 +14,9 @@ module Extension
|
|
14
14
|
parser.on("--resourceUrl=RESOURCE_URL", "Provide a resource URL") do |resource_url|
|
15
15
|
flags[:resource_url] = resource_url
|
16
16
|
end
|
17
|
+
parser.on("-p", "--port=PORT", "Specify the port to use") do |port|
|
18
|
+
flags[:port] = port.to_i
|
19
|
+
end
|
17
20
|
end
|
18
21
|
|
19
22
|
class RuntimeConfiguration
|
@@ -22,13 +25,14 @@ module Extension
|
|
22
25
|
property :tunnel_url, accepts: String, default: nil
|
23
26
|
property :resource_url, accepts: String, default: nil
|
24
27
|
property! :tunnel_requested, accepts: [true, false], reader: :tunnel_requested?, default: true
|
25
|
-
property
|
28
|
+
property :port, accepts: (1...(2**16))
|
26
29
|
end
|
27
30
|
|
28
31
|
def call(_args, _command_name)
|
29
32
|
config = RuntimeConfiguration.new(
|
30
33
|
tunnel_requested: tunnel_requested?,
|
31
|
-
resource_url: options.flags[:resource_url]
|
34
|
+
resource_url: options.flags[:resource_url],
|
35
|
+
port: options.flags[:port]
|
32
36
|
)
|
33
37
|
|
34
38
|
ShopifyCLI::Result
|
@@ -51,10 +55,11 @@ module Extension
|
|
51
55
|
end
|
52
56
|
|
53
57
|
def find_available_port(runtime_configuration)
|
58
|
+
return runtime_configuration unless runtime_configuration.port.nil?
|
54
59
|
return runtime_configuration unless specification_handler.choose_port?(@ctx)
|
55
60
|
|
56
61
|
chosen_port = Tasks::ChooseNextAvailablePort
|
57
|
-
.call(from:
|
62
|
+
.call(from: DEFAULT_PORT)
|
58
63
|
.unwrap { |_error| @ctx.abort(@ctx.message("serve.no_available_ports_found")) }
|
59
64
|
runtime_configuration.tap { |c| c.port = chosen_port }
|
60
65
|
end
|
@@ -9,7 +9,7 @@ module Extension
|
|
9
9
|
property! :specification_handler, accepts: Extension::Models::SpecificationHandlers::Default
|
10
10
|
property :argo_runtime, accepts: -> (runtime) { runtime.class < Features::Runtimes::Base }
|
11
11
|
property! :context, accepts: ShopifyCLI::Context
|
12
|
-
property! :port, accepts: Integer
|
12
|
+
property! :port, accepts: Integer
|
13
13
|
property :tunnel_url, accepts: String, default: nil
|
14
14
|
property! :js_system, accepts: ->(jss) { jss.respond_to?(:call) }, default: ShopifyCLI::JsSystem
|
15
15
|
property :resource_url, accepts: String, default: nil
|
@@ -10,11 +10,14 @@ module Extension
|
|
10
10
|
property! :type, accepts: String
|
11
11
|
property! :user, accepts: ServerConfig::User
|
12
12
|
property! :development, accepts: ServerConfig::Development
|
13
|
+
property :capabilities, accepts: ServerConfig::Capabilities
|
13
14
|
property :extension_points, accepts: Array
|
14
|
-
property :version, accepts: String
|
15
15
|
property :title, accepts: String
|
16
|
+
property :description, accepts: String
|
17
|
+
property :version, accepts: String
|
18
|
+
property :metafields, accepts: Array
|
16
19
|
|
17
|
-
def self.build(uuid: "", template:, type:, root_dir
|
20
|
+
def self.build(uuid: "", template:, type:, root_dir:, **args)
|
18
21
|
renderer = ServerConfig::DevelopmentRenderer.find(type)
|
19
22
|
entry = ServerConfig::DevelopmentEntries.find(template)
|
20
23
|
new(
|
@@ -26,7 +29,11 @@ module Extension
|
|
26
29
|
template: template,
|
27
30
|
renderer: renderer,
|
28
31
|
entries: entry
|
29
|
-
)
|
32
|
+
),
|
33
|
+
capabilities: ServerConfig::Capabilities.new(
|
34
|
+
network_access: false
|
35
|
+
),
|
36
|
+
metafields: args.delete(:metafields)
|
30
37
|
)
|
31
38
|
end
|
32
39
|
|
@@ -15,7 +15,7 @@ module Extension
|
|
15
15
|
(?<region>[a-zA-Z]{2}) # Optional region subtag
|
16
16
|
)?
|
17
17
|
\z}x
|
18
|
-
PERMITTED_CONFIG_KEYS = [:extension_points, :metafields, :name]
|
18
|
+
PERMITTED_CONFIG_KEYS = [:extension_points, :metafields, :name, :capabilities]
|
19
19
|
|
20
20
|
def config(context)
|
21
21
|
{
|
@@ -9,13 +9,14 @@ module Extension
|
|
9
9
|
property! :api_key, accepts: String
|
10
10
|
property! :context, accepts: ShopifyCLI::Context
|
11
11
|
property! :hash, accepts: Hash
|
12
|
-
property
|
12
|
+
property! :port, accepts: Integer
|
13
13
|
property! :registration_uuid, accepts: String
|
14
14
|
property :resource_url, accepts: String
|
15
15
|
property! :store, accepts: String
|
16
16
|
property! :title, accepts: String
|
17
17
|
property :tunnel_url, accepts: String
|
18
18
|
property! :type, accepts: String
|
19
|
+
property :metafields, accepts: Array
|
19
20
|
|
20
21
|
DEFAULT_BUILD_DIR = "build"
|
21
22
|
|
@@ -27,7 +28,6 @@ module Extension
|
|
27
28
|
context.abort(context.message("tasks.errors.parse_error")) if hash.nil?
|
28
29
|
|
29
30
|
renderer = Models::ServerConfig::DevelopmentRenderer.find(type)
|
30
|
-
|
31
31
|
extension = Models::ServerConfig::Extension.new(
|
32
32
|
uuid: registration_uuid,
|
33
33
|
type: type.upcase,
|
@@ -40,8 +40,12 @@ module Extension
|
|
40
40
|
)
|
41
41
|
),
|
42
42
|
extension_points: hash.dig("extension_points"),
|
43
|
+
capabilities: Models::ServerConfig::Capabilities.new(
|
44
|
+
network_access: hash.dig("capabilities", "network_access") || false
|
45
|
+
),
|
43
46
|
version: renderer ? version(renderer.name, context) : nil,
|
44
|
-
title: title
|
47
|
+
title: title,
|
48
|
+
metafields: metafields
|
45
49
|
)
|
46
50
|
|
47
51
|
unless resource_url.nil?
|
@@ -9,7 +9,7 @@ module Extension
|
|
9
9
|
|
10
10
|
property! :context, accepts: ShopifyCLI::Context
|
11
11
|
property! :file_path, accepts: ->(path) { Pathname(path).yield_self(&:absolute?) }
|
12
|
-
property
|
12
|
+
property! :port, accepts: Integer, default: ShopifyCLI::Constants::Extension::DEFAULT_PORT
|
13
13
|
property :resource_url, accepts: String
|
14
14
|
property :tunnel_url, accepts: String
|
15
15
|
property! :type, accepts: Models::DevelopmentServerRequirements::SUPPORTED_EXTENSION_TYPES
|
@@ -32,7 +32,9 @@ module Extension
|
|
32
32
|
store: project.env.shop || "",
|
33
33
|
title: project.title,
|
34
34
|
tunnel_url: tunnel_url,
|
35
|
-
type: type
|
35
|
+
type: type,
|
36
|
+
port: port,
|
37
|
+
metafields: config["metafields"]
|
36
38
|
)
|
37
39
|
rescue Psych::SyntaxError => e
|
38
40
|
raise(
|
@@ -50,6 +50,7 @@ module Script
|
|
50
50
|
autoload :ExtensionPoint, Project.project_filepath("layers/domain/extension_point")
|
51
51
|
autoload :ScriptConfig, Project.project_filepath("layers/domain/script_config")
|
52
52
|
autoload :ScriptProject, Project.project_filepath("layers/domain/script_project")
|
53
|
+
autoload :AppBridge, Project.project_filepath("layers/domain/app_bridge")
|
53
54
|
end
|
54
55
|
|
55
56
|
module Infrastructure
|
@@ -38,21 +38,33 @@ delivery_discount_types:
|
|
38
38
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
39
39
|
wasm:
|
40
40
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
41
|
-
|
41
|
+
product_discounts:
|
42
42
|
beta: true
|
43
43
|
domain: 'discounts'
|
44
44
|
libraries:
|
45
45
|
wasm:
|
46
46
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
47
|
-
|
47
|
+
rust:
|
48
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
49
|
+
order_discounts:
|
48
50
|
beta: true
|
49
51
|
domain: 'discounts'
|
50
52
|
libraries:
|
51
53
|
wasm:
|
52
54
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
53
|
-
|
55
|
+
rust:
|
56
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
57
|
+
shipping_discounts:
|
54
58
|
beta: true
|
55
59
|
domain: 'discounts'
|
56
60
|
libraries:
|
57
61
|
wasm:
|
58
62
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
63
|
+
rust:
|
64
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
65
|
+
shipping_rates_consolidation:
|
66
|
+
beta: true
|
67
|
+
domain: 'checkout'
|
68
|
+
libraries:
|
69
|
+
wasm:
|
70
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
@@ -12,6 +12,7 @@ mutation AppScriptSet(
|
|
12
12
|
$moduleUploadUrl: String!,
|
13
13
|
$library: LibraryInput,
|
14
14
|
$inputQuery: String,
|
15
|
+
$appBridge: AppBridgeInput!,
|
15
16
|
) {
|
16
17
|
appScriptSet(
|
17
18
|
uuid: $uuid
|
@@ -27,6 +28,7 @@ mutation AppScriptSet(
|
|
27
28
|
moduleUploadUrl: $moduleUploadUrl,
|
28
29
|
library: $library,
|
29
30
|
inputQuery: $inputQuery,
|
31
|
+
appBridge: $appBridge
|
30
32
|
) {
|
31
33
|
userErrors {
|
32
34
|
field
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Script
|
4
|
+
module Layers
|
5
|
+
module Domain
|
6
|
+
class AppBridge
|
7
|
+
attr_reader :create_path, :details_path
|
8
|
+
|
9
|
+
def initialize(create_path:, details_path:)
|
10
|
+
@create_path = create_path
|
11
|
+
@details_path = details_path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -54,6 +54,7 @@ module Script
|
|
54
54
|
extension_point_type: extension_point_type,
|
55
55
|
language: language,
|
56
56
|
script_config: script_config_repository.get!,
|
57
|
+
app_bridge: app_bridge,
|
57
58
|
input_query: read_input_query,
|
58
59
|
)
|
59
60
|
end
|
@@ -94,6 +95,7 @@ module Script
|
|
94
95
|
extension_point_type: extension_point_type,
|
95
96
|
language: language,
|
96
97
|
script_config: script_config,
|
98
|
+
app_bridge: app_bridge,
|
97
99
|
)
|
98
100
|
end
|
99
101
|
|
@@ -121,6 +123,16 @@ module Script
|
|
121
123
|
project_config_value("language")&.downcase || default_language
|
122
124
|
end
|
123
125
|
|
126
|
+
def app_bridge
|
127
|
+
create_path = project_config_value("app_bridge_create_path") || "/"
|
128
|
+
details_path = project_config_value("app_bridge_details_path") || "/"
|
129
|
+
|
130
|
+
Domain::AppBridge.new(
|
131
|
+
create_path: create_path,
|
132
|
+
details_path: details_path,
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
124
136
|
def project_config_value(key)
|
125
137
|
return nil unless project.config.key?(key)
|
126
138
|
project.config[key]
|
@@ -20,6 +20,7 @@ module Script
|
|
20
20
|
force: false,
|
21
21
|
metadata:,
|
22
22
|
script_config:,
|
23
|
+
app_bridge:,
|
23
24
|
module_upload_url:,
|
24
25
|
library:,
|
25
26
|
input_query: nil
|
@@ -36,6 +37,10 @@ module Script
|
|
36
37
|
scriptConfigVersion: script_config.version,
|
37
38
|
configurationUi: script_config.configuration_ui,
|
38
39
|
configurationDefinition: script_config.configuration&.to_json,
|
40
|
+
appBridge: {
|
41
|
+
createPath: app_bridge.create_path,
|
42
|
+
detailsPath: app_bridge.details_path,
|
43
|
+
},
|
39
44
|
moduleUploadUrl: module_upload_url,
|
40
45
|
inputQuery: input_query,
|
41
46
|
}
|
@@ -20,9 +20,12 @@ module Theme
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def call(_args, name)
|
23
|
+
valid_authentication_method!
|
24
|
+
|
23
25
|
root = root_value(options, name)
|
24
26
|
flags = options.flags.dup
|
25
27
|
host = flags[:host] || DEFAULT_HTTP_HOST
|
28
|
+
|
26
29
|
ShopifyCLI::Theme::DevServer.start(@ctx, root, host: host, **flags) do |syncer|
|
27
30
|
UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delay_low_priority_files: true)
|
28
31
|
end
|
@@ -38,6 +41,30 @@ module Theme
|
|
38
41
|
def self.help
|
39
42
|
ShopifyCLI::Context.message("theme.serve.help", ShopifyCLI::TOOL_NAME)
|
40
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def valid_authentication_method!
|
48
|
+
if exchange_token && !storefront_renderer_token
|
49
|
+
ShopifyCLI::Context.abort(error_message, help_message)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def error_message
|
54
|
+
ShopifyCLI::Context.message("theme.serve.auth.error_message", ShopifyCLI::TOOL_NAME)
|
55
|
+
end
|
56
|
+
|
57
|
+
def help_message
|
58
|
+
ShopifyCLI::Context.message("theme.serve.auth.help_message", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
|
59
|
+
end
|
60
|
+
|
61
|
+
def exchange_token
|
62
|
+
ShopifyCLI::DB.get(:shopify_exchange_token)
|
63
|
+
end
|
64
|
+
|
65
|
+
def storefront_renderer_token
|
66
|
+
ShopifyCLI::DB.get(:storefront_renderer_production_exchange_token)
|
67
|
+
end
|
41
68
|
end
|
42
69
|
end
|
43
70
|
end
|
@@ -8,6 +8,11 @@ module Theme
|
|
8
8
|
Usage: {{command:%1$s theme [ %2$s ]}}
|
9
9
|
HELP
|
10
10
|
ensure_user_error: "You are not authorized to edit themes on %s.",
|
11
|
+
unauthorized_error: <<~EOD,
|
12
|
+
You can't use Shopify CLI with development stores if you only have Partner staff member access. If you want to use Shopify CLI to work on a development store, then you should be the store owner or create a staff account on the store.
|
13
|
+
|
14
|
+
If you're the store owner, then you need to log in to the store directly using the store URL at least once (for example, using %s.myshopify.com/admin) before you log in using Shopify CLI. Logging in to the Shopify admin directly connects the development store with your Shopify login.
|
15
|
+
EOD
|
11
16
|
ensure_user_try_this: <<~ENSURE_USER,
|
12
17
|
Check if your user is activated, has permission to edit themes at the store, and try to re-login.
|
13
18
|
ENSURE_USER
|
@@ -116,6 +121,14 @@ module Theme
|
|
116
121
|
viewing_theme: "Viewing theme…",
|
117
122
|
syncing_theme: "Syncing theme #%s on %s",
|
118
123
|
open_fail: "Couldn't open the theme",
|
124
|
+
auth: {
|
125
|
+
error_message: <<~ERROR_MESSAGE,
|
126
|
+
It looks like you are using credentials that do not work with {{command:%s theme serve}}.
|
127
|
+
ERROR_MESSAGE
|
128
|
+
help_message: <<~HELP_MESSAGE,
|
129
|
+
Run {{command:%s logout}} and {{command:%s login --password "" --store STORE}} to force the authentication thought your browser.
|
130
|
+
HELP_MESSAGE
|
131
|
+
},
|
119
132
|
operation: {
|
120
133
|
status: {
|
121
134
|
error: "ERROR",
|
@@ -26,8 +26,8 @@ module ShopifyCLI
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
if
|
29
|
+
password = options.flags[:password] || @ctx.getenv("SHOPIFY_PASSWORD")
|
30
|
+
if !password.nil? && !password.empty?
|
31
31
|
ShopifyCLI::DB.set(shopify_exchange_token: password)
|
32
32
|
else
|
33
33
|
IdentityAuth.new(ctx: @ctx).authenticate(spinner: true)
|
data/lib/shopify_cli/context.rb
CHANGED
@@ -630,7 +630,7 @@ module ShopifyCLI
|
|
630
630
|
end
|
631
631
|
end
|
632
632
|
latest_version = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
|
633
|
-
latest_version
|
633
|
+
latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
|
634
634
|
end
|
635
635
|
|
636
636
|
# Returns file extension depending on OS
|
@@ -14,13 +14,12 @@ module ShopifyCLI
|
|
14
14
|
|
15
15
|
files.each do |file|
|
16
16
|
section_hash(file).each do |key, value|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
next if !name || !type
|
17
|
+
next unless key
|
18
|
+
next unless value.is_a?(Hash)
|
19
|
+
next unless (type = value&.dig("type"))
|
21
20
|
|
22
21
|
index[type] = [] unless index[type]
|
23
|
-
index[type] <<
|
22
|
+
index[type] << key
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
@@ -42,7 +41,7 @@ module ShopifyCLI
|
|
42
41
|
end
|
43
42
|
|
44
43
|
def files
|
45
|
-
@theme.json_files
|
44
|
+
@theme.json_files.filter(&:template?)
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
@@ -14,7 +14,8 @@ module ShopifyCLI
|
|
14
14
|
@theme = theme
|
15
15
|
@syncer = syncer
|
16
16
|
@ignore_filter = ignore_filter
|
17
|
-
@listener = Listen.to(@theme.root, force_polling: poll
|
17
|
+
@listener = Listen.to(@theme.root, force_polling: poll,
|
18
|
+
ignore: @ignore_filter&.regexes) do |modified, added, removed|
|
18
19
|
changed
|
19
20
|
notify_observers(modified, added, removed)
|
20
21
|
end
|
@@ -32,7 +32,7 @@ module ShopifyCLI
|
|
32
32
|
theme = DevelopmentTheme.find_or_create!(ctx, root: root)
|
33
33
|
ignore_filter = IgnoreFilter.from_path(root)
|
34
34
|
@syncer = Syncer.new(ctx, theme: theme, ignore_filter: ignore_filter, overwrite_json: !editor_sync)
|
35
|
-
watcher = Watcher.new(ctx, theme: theme, syncer: @syncer, poll: poll)
|
35
|
+
watcher = Watcher.new(ctx, theme: theme, ignore_filter: ignore_filter, syncer: @syncer, poll: poll)
|
36
36
|
remote_watcher = RemoteWatcher.to(theme: theme, syncer: @syncer)
|
37
37
|
|
38
38
|
# Setup the middleware stack. Mimics Rack::Builder / config.ru, but in reverse order
|
@@ -79,13 +79,23 @@ module ShopifyCLI
|
|
79
79
|
|
80
80
|
theme_name = "Development ()"
|
81
81
|
hostname_character_limit = API_NAME_LIMIT - theme_name.length - hash.length - 1
|
82
|
-
identifier = "#{hash}-#{hostname[0, hostname_character_limit]}"
|
82
|
+
identifier = encode_identifier("#{hash}-#{hostname[0, hostname_character_limit]}")
|
83
83
|
theme_name = "Development (#{identifier})"
|
84
84
|
|
85
85
|
ShopifyCLI::DB.set(development_theme_name: theme_name)
|
86
86
|
|
87
87
|
theme_name
|
88
88
|
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# In some cases, the identifier string encoding may be obfuscated by the hostname,
|
92
|
+
# which may be an ASCII string.
|
93
|
+
#
|
94
|
+
# This method ensures the result identifier is a UTF-8 valid string.
|
95
|
+
#
|
96
|
+
def encode_identifier(identifier)
|
97
|
+
identifier.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "-")
|
98
|
+
end
|
89
99
|
end
|
90
100
|
end
|
91
101
|
end
|
@@ -30,6 +30,15 @@ module ShopifyCLI
|
|
30
30
|
else
|
31
31
|
path.write(content, 0, mode: "wb")
|
32
32
|
end
|
33
|
+
rescue Encoding::UndefinedConversionError
|
34
|
+
##
|
35
|
+
# The CLI tries to write the file and normalize EOL characters to avoid
|
36
|
+
# errors on Windows when files are shared across different operational systems.
|
37
|
+
#
|
38
|
+
# The CLI fallbacks any error during the conversion by writing the file
|
39
|
+
# in binary mode when the normalization fails (e.g., ASCII files), so no data is lost.
|
40
|
+
#
|
41
|
+
path.write(content, 0, mode: "wb")
|
33
42
|
end
|
34
43
|
|
35
44
|
def delete
|
@@ -53,8 +53,10 @@ module ShopifyCLI
|
|
53
53
|
# * when an asset operation cannot be performed:
|
54
54
|
# - <APIRequestForbiddenError: 403 {"message":"templates/gift_card.liquid could not be deleted"}>
|
55
55
|
#
|
56
|
-
if empty_response?(error)
|
56
|
+
if empty_response?(error)
|
57
57
|
return permission_error
|
58
|
+
elsif unauthorized_response?(error)
|
59
|
+
raise ShopifyCLI::Abort, @ctx.message("theme.unauthorized_error", @shop)
|
58
60
|
end
|
59
61
|
|
60
62
|
raise error
|
data/lib/shopify_cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -244,6 +244,7 @@ files:
|
|
244
244
|
- lib/project_types/extension/models/registration.rb
|
245
245
|
- lib/project_types/extension/models/server_config/app.rb
|
246
246
|
- lib/project_types/extension/models/server_config/base.rb
|
247
|
+
- lib/project_types/extension/models/server_config/capabilities.rb
|
247
248
|
- lib/project_types/extension/models/server_config/development.rb
|
248
249
|
- lib/project_types/extension/models/server_config/development_entries.rb
|
249
250
|
- lib/project_types/extension/models/server_config/development_renderer.rb
|
@@ -320,6 +321,7 @@ files:
|
|
320
321
|
- lib/project_types/script/layers/application/extension_points.rb
|
321
322
|
- lib/project_types/script/layers/application/project_dependencies.rb
|
322
323
|
- lib/project_types/script/layers/application/push_script.rb
|
324
|
+
- lib/project_types/script/layers/domain/app_bridge.rb
|
323
325
|
- lib/project_types/script/layers/domain/errors.rb
|
324
326
|
- lib/project_types/script/layers/domain/extension_point.rb
|
325
327
|
- lib/project_types/script/layers/domain/metadata.rb
|