shopify-cli 2.16.0 → 2.18.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 +33 -0
- data/Gemfile.lock +3 -3
- data/ext/shopify-extensions/version +1 -1
- data/lib/project_types/extension/cli.rb +2 -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/development_renderer.rb +2 -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 +8 -4
- 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 +20 -18
- 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/errors.rb +11 -0
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +12 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +9 -0
- data/lib/project_types/script/messages/messages.rb +3 -0
- data/lib/project_types/script/ui/error_handler.rb +8 -0
- data/lib/project_types/theme/commands/delete.rb +1 -0
- data/lib/project_types/theme/commands/open.rb +6 -1
- data/lib/project_types/theme/commands/publish.rb +1 -0
- data/lib/project_types/theme/commands/serve.rb +28 -0
- data/lib/project_types/theme/forms/select.rb +4 -1
- data/lib/project_types/theme/messages/messages.rb +33 -3
- data/lib/shopify_cli/admin_api.rb +1 -1
- data/lib/shopify_cli/commands/login.rb +2 -2
- data/lib/shopify_cli/commands/logout.rb +1 -1
- data/lib/shopify_cli/context.rb +7 -3
- data/lib/shopify_cli/core/monorail.rb +1 -1
- data/lib/shopify_cli/heroku.rb +5 -3
- data/lib/shopify_cli/partners_api/app_extensions.rb +1 -1
- data/lib/shopify_cli/release.rb +5 -2
- data/lib/shopify_cli/services/app/create/rails_service.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 +20 -3
- data/lib/shopify_cli/theme/development_theme.rb +11 -1
- data/lib/shopify_cli/theme/file.rb +9 -0
- data/lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb +2 -2
- data/lib/shopify_cli/theme/syncer/json_update_handler.rb +1 -1
- 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: 7dc113806552b27305be696850c04b292d7ba8feb0e5a60c0755bdb93b193535
|
|
4
|
+
data.tar.gz: 7fd46f5612eda607b0e2b2f01ea8662ce1d6d4803475b4e7d3bde98155ed06db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d1553e12053b6666755dde7c4381fce2018da1d73ab2f85cc456f6ad97fd58db89360a4fe02beb7b40d3a6d0010e2c8f15b68ff6246ff25426796f39f451aafc
|
|
7
|
+
data.tar.gz: 5a9f020586bfaf2b828aed9bb1ae4040bc0deab133e71181fe49c5710fd9a5a3b3cc71faf653f0311054038b76d749303947e0af6d902b7096cf84c2c610a3bf
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@ 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.18.0 - 2022-05-30
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
* [#2336](https://github.com/Shopify/shopify-cli/pull/2336): Add `--theme/-t` flag support to the `theme serve` command
|
|
9
|
+
* [#2325](https://github.com/Shopify/shopify-cli/pull/2325): Add `-e/--editor` flag to open theme editor in the `theme open` command
|
|
10
|
+
* [#2330](https://github.com/Shopify/shopify-cli/pull/2330): Add remote file deleted warning flow to `theme serve --theme-editor-sync`
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
* [#2352](https://github.com/Shopify/shopify-cli/pull/2352): Provide better DX when dealing with empty theme selection
|
|
14
|
+
* [#2347](https://github.com/Shopify/shopify-cli/pull/2347): Fix #2346 Heroku CLI installation for Apple silicon
|
|
15
|
+
|
|
16
|
+
## Version 2.17.0 - 2022-05-12
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
* [#2262](https://github.com/Shopify/shopify-cli/pull/2262): Add `capabilities` permissions to checkout extensions config
|
|
20
|
+
* [#2292](https://github.com/Shopify/shopify-cli/pull/2292): Add support for App Bridge create/details URLs for scripts
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
* [#2287](https://github.com/Shopify/shopify-cli/pull/2287): Fix `Encoding::UndefinedConversionError` on `theme serve` and `theme pull`
|
|
24
|
+
* [#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
|
|
25
|
+
* [#2297](https://github.com/Shopify/shopify-cli/pull/2297): Only show update message when the new version is higher
|
|
26
|
+
* [#2270](https://github.com/Shopify/shopify-cli/pull/2270): Use ignore filter regex in watcher class
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
* [#2299](https://github.com/Shopify/shopify-cli/pull/2299): Improve the unauthorized API errors when doing theme development
|
|
30
|
+
|
|
31
|
+
## Version 2.16.1 - 2022-04-26
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
* [#2279](https://github.com/Shopify/shopify-cli/pull/2279): Fix logout when there are theme permission issues
|
|
35
|
+
* [#2285](https://github.com/Shopify/shopify-cli/pull/2285): Fix extension loading for extension connect
|
|
36
|
+
* [#2284](https://github.com/Shopify/shopify-cli/pull/2284): Fix version check for Windows
|
|
37
|
+
|
|
5
38
|
## Version 2.16.0 - 2022-04-25
|
|
6
39
|
|
|
7
40
|
### Fixed
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
shopify-cli (2.
|
|
4
|
+
shopify-cli (2.18.0)
|
|
5
5
|
bugsnag (~> 6.22)
|
|
6
6
|
listen (~> 3.7.0)
|
|
7
7
|
theme-check (~> 1.10.1)
|
|
@@ -101,7 +101,7 @@ GEM
|
|
|
101
101
|
mocha (1.13.0)
|
|
102
102
|
multi_test (0.1.2)
|
|
103
103
|
multipart-post (2.1.1)
|
|
104
|
-
nokogiri (1.13.
|
|
104
|
+
nokogiri (1.13.6)
|
|
105
105
|
mini_portile2 (~> 2.8.0)
|
|
106
106
|
racc (~> 1.4)
|
|
107
107
|
octokit (4.22.0)
|
|
@@ -118,7 +118,7 @@ GEM
|
|
|
118
118
|
pry (~> 0.13.0)
|
|
119
119
|
public_suffix (4.0.6)
|
|
120
120
|
racc (1.6.0)
|
|
121
|
-
rack (2.2.3)
|
|
121
|
+
rack (2.2.3.1)
|
|
122
122
|
rainbow (3.1.1)
|
|
123
123
|
rake (13.0.6)
|
|
124
124
|
rb-fsevent (0.11.1)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
v0.
|
|
1
|
+
v0.12.0
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "pathname"
|
|
4
4
|
require "json"
|
|
5
|
+
require "yaml"
|
|
5
6
|
|
|
6
7
|
module Extension
|
|
7
8
|
class PackageResolutionFailed < RuntimeError; end
|
|
@@ -121,6 +122,7 @@ module Extension
|
|
|
121
122
|
module ServerConfig
|
|
122
123
|
autoload :Base, Project.project_filepath("models/server_config/base")
|
|
123
124
|
autoload :App, Project.project_filepath("models/server_config/app")
|
|
125
|
+
autoload :Capabilities, Project.project_filepath("models/server_config/capabilities")
|
|
124
126
|
autoload :Development, Project.project_filepath("models/server_config/development")
|
|
125
127
|
autoload :DevelopmentEntries, Project.project_filepath("models/server_config/development_entries")
|
|
126
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
|
|
@@ -26,6 +26,8 @@ module Extension
|
|
|
26
26
|
new(name: "@shopify/post-purchase-ui-extensions", version: "^0.13.2")
|
|
27
27
|
when "pos_ui_extension"
|
|
28
28
|
new(name: "@shopify/retail-ui-extensions", version: "^0.1.0")
|
|
29
|
+
when "beacon_extension"
|
|
30
|
+
nil
|
|
29
31
|
else
|
|
30
32
|
raise ArgumentError, "Unknown extension type: #{type}"
|
|
31
33
|
end
|
|
@@ -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,10 +28,9 @@ 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
|
-
type: type
|
|
33
|
+
type: type,
|
|
34
34
|
user: Models::ServerConfig::User.new,
|
|
35
35
|
development: Models::ServerConfig::Development.new(
|
|
36
36
|
build_dir: hash.dig("development", "build_dir") || DEFAULT_BUILD_DIR,
|
|
@@ -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
|
|
@@ -9,50 +9,52 @@ payment_methods:
|
|
|
9
9
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
10
10
|
rust:
|
|
11
11
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
12
|
-
|
|
12
|
+
payment_customization:
|
|
13
|
+
beta: true
|
|
13
14
|
domain: 'checkout'
|
|
14
15
|
libraries:
|
|
15
|
-
typescript:
|
|
16
|
-
beta: true
|
|
17
|
-
package: "@shopify/scripts-checkout-apis"
|
|
18
|
-
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
19
16
|
wasm:
|
|
20
17
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
rust:
|
|
19
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
20
|
+
shipping_methods:
|
|
21
|
+
domain: 'checkout'
|
|
24
22
|
libraries:
|
|
25
23
|
typescript:
|
|
26
24
|
beta: true
|
|
27
|
-
package: "@shopify/scripts-
|
|
25
|
+
package: "@shopify/scripts-checkout-apis"
|
|
28
26
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
29
27
|
wasm:
|
|
30
28
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
31
|
-
|
|
29
|
+
rust:
|
|
30
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
31
|
+
product_discounts:
|
|
32
32
|
beta: true
|
|
33
33
|
domain: 'discounts'
|
|
34
34
|
libraries:
|
|
35
|
-
typescript:
|
|
36
|
-
beta: true
|
|
37
|
-
package: "@shopify/scripts-discounts-apis"
|
|
38
|
-
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
39
35
|
wasm:
|
|
40
36
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
41
|
-
|
|
37
|
+
rust:
|
|
38
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
39
|
+
order_discounts:
|
|
42
40
|
beta: true
|
|
43
41
|
domain: 'discounts'
|
|
44
42
|
libraries:
|
|
45
43
|
wasm:
|
|
46
44
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
47
|
-
|
|
45
|
+
rust:
|
|
46
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
47
|
+
shipping_discounts:
|
|
48
48
|
beta: true
|
|
49
49
|
domain: 'discounts'
|
|
50
50
|
libraries:
|
|
51
51
|
wasm:
|
|
52
52
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
53
|
-
|
|
53
|
+
rust:
|
|
54
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
|
55
|
+
shipping_rates_consolidation:
|
|
54
56
|
beta: true
|
|
55
|
-
domain: '
|
|
57
|
+
domain: 'checkout'
|
|
56
58
|
libraries:
|
|
57
59
|
wasm:
|
|
58
60
|
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
|
|
@@ -194,6 +194,17 @@ module Script
|
|
|
194
194
|
messages.join("\n")
|
|
195
195
|
end
|
|
196
196
|
end
|
|
197
|
+
|
|
198
|
+
class InvalidAppBridgePathError < ScriptProjectError
|
|
199
|
+
def initialize(path_type)
|
|
200
|
+
@path_type = path_type
|
|
201
|
+
super()
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def path_key
|
|
205
|
+
"app_bridge_#{@path_type}_path"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
197
208
|
end
|
|
198
209
|
end
|
|
199
210
|
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
|
}
|
|
@@ -87,6 +92,10 @@ module Script
|
|
|
87
92
|
raise Errors::InvalidInputQueryErrors, errors.map { |err| err["message"] }
|
|
88
93
|
elsif user_errors.find { |err| %w(not_use_msgpack_error schema_version_argument_error).include?(err["tag"]) }
|
|
89
94
|
raise Domain::Errors::MetadataValidationError
|
|
95
|
+
elsif user_errors.find { |err| err["tag"] == "invalid_app_bridge_create_path" }
|
|
96
|
+
raise Errors::InvalidAppBridgePathError, "create"
|
|
97
|
+
elsif user_errors.find { |err| err["tag"] == "invalid_app_bridge_details_path" }
|
|
98
|
+
raise Errors::InvalidAppBridgePathError, "details"
|
|
90
99
|
else
|
|
91
100
|
raise Errors::GraphqlError, user_errors
|
|
92
101
|
end
|
|
@@ -164,6 +164,9 @@ module Script
|
|
|
164
164
|
missing_env_file_variables: "The following are missing in the .env file: %s. ",
|
|
165
165
|
missing_env_file_variables_solution: "To add it, connect your script with " \
|
|
166
166
|
"{{command:%1$s script connect}} ",
|
|
167
|
+
|
|
168
|
+
invalid_app_bridge_path_cause: "The script couldn't be pushed because the App Bridge path is incorrect in .shopify-cli.yml.",
|
|
169
|
+
invalid_app_bridge_path_help: "The %{path_key} needs to be set to a path that starts with {{command:/}}.",
|
|
167
170
|
},
|
|
168
171
|
|
|
169
172
|
create: {
|
|
@@ -316,6 +316,14 @@ module Script
|
|
|
316
316
|
),
|
|
317
317
|
help_suggestion: ShopifyCLI::Context.message("script.error.language_library_for_api_not_found_help"),
|
|
318
318
|
}
|
|
319
|
+
when Layers::Infrastructure::Errors::InvalidAppBridgePathError
|
|
320
|
+
{
|
|
321
|
+
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_app_bridge_path_cause"),
|
|
322
|
+
help_suggestion: ShopifyCLI::Context.message(
|
|
323
|
+
"script.error.invalid_app_bridge_path_help",
|
|
324
|
+
path_key: e.path_key,
|
|
325
|
+
),
|
|
326
|
+
}
|
|
319
327
|
end
|
|
320
328
|
end
|
|
321
329
|
end
|
|
@@ -12,13 +12,18 @@ module Theme
|
|
|
12
12
|
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
|
13
13
|
parser.on("-l", "--live") { flags[:live] = true }
|
|
14
14
|
parser.on("-d", "--development") { flags[:development] = true }
|
|
15
|
+
parser.on("-e", "--editor") { flags[:editor] = true }
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def call(_args, _name)
|
|
18
19
|
theme = find_theme(**options.flags)
|
|
19
20
|
|
|
20
21
|
@ctx.puts(@ctx.message("theme.open.details", theme.name, theme.preview_url, theme.editor_url))
|
|
21
|
-
|
|
22
|
+
if options.flags[:editor]
|
|
23
|
+
@ctx.open_browser_url!(theme.editor_url)
|
|
24
|
+
else
|
|
25
|
+
@ctx.open_browser_url!(theme.preview_url)
|
|
26
|
+
end
|
|
22
27
|
end
|
|
23
28
|
|
|
24
29
|
def self.help
|
|
@@ -17,12 +17,16 @@ module Theme
|
|
|
17
17
|
parser.on("--poll") { flags[:poll] = true }
|
|
18
18
|
parser.on("--live-reload=MODE") { |mode| flags[:mode] = as_reload_mode(mode) }
|
|
19
19
|
parser.on("--theme-editor-sync") { flags[:editor_sync] = true }
|
|
20
|
+
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def call(_args, name)
|
|
24
|
+
valid_authentication_method!
|
|
25
|
+
|
|
23
26
|
root = root_value(options, name)
|
|
24
27
|
flags = options.flags.dup
|
|
25
28
|
host = flags[:host] || DEFAULT_HTTP_HOST
|
|
29
|
+
|
|
26
30
|
ShopifyCLI::Theme::DevServer.start(@ctx, root, host: host, **flags) do |syncer|
|
|
27
31
|
UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delay_low_priority_files: true)
|
|
28
32
|
end
|
|
@@ -38,6 +42,30 @@ module Theme
|
|
|
38
42
|
def self.help
|
|
39
43
|
ShopifyCLI::Context.message("theme.serve.help", ShopifyCLI::TOOL_NAME)
|
|
40
44
|
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def valid_authentication_method!
|
|
49
|
+
if exchange_token && !storefront_renderer_token
|
|
50
|
+
ShopifyCLI::Context.abort(error_message, help_message)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def error_message
|
|
55
|
+
ShopifyCLI::Context.message("theme.serve.auth.error_message", ShopifyCLI::TOOL_NAME)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def help_message
|
|
59
|
+
ShopifyCLI::Context.message("theme.serve.auth.help_message", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def exchange_token
|
|
63
|
+
ShopifyCLI::DB.get(:shopify_exchange_token)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def storefront_renderer_token
|
|
67
|
+
ShopifyCLI::DB.get(:storefront_renderer_production_exchange_token)
|
|
68
|
+
end
|
|
41
69
|
end
|
|
42
70
|
end
|
|
43
71
|
end
|
|
@@ -6,7 +6,7 @@ module Theme
|
|
|
6
6
|
module Forms
|
|
7
7
|
class Select < ShopifyCLI::Form
|
|
8
8
|
attr_accessor :theme
|
|
9
|
-
flag_arguments :root, :title, :exclude_roles, :include_foreign_developments
|
|
9
|
+
flag_arguments :root, :title, :exclude_roles, :include_foreign_developments, :cmd
|
|
10
10
|
|
|
11
11
|
def ask
|
|
12
12
|
self.theme = CLI::UI::Prompt.ask(title, allow_empty: false) do |handler|
|
|
@@ -18,6 +18,9 @@ module Theme
|
|
|
18
18
|
|
|
19
19
|
handler.option(presenter.to_s(:short)) { theme }
|
|
20
20
|
end
|
|
21
|
+
if handler.options.empty? && cmd
|
|
22
|
+
@ctx.abort(@ctx.message("theme.#{cmd}.no_themes_error"), @ctx.message("theme.#{cmd}.no_themes_resolution"))
|
|
23
|
+
end
|
|
21
24
|
end
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -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
|
|
@@ -37,6 +42,8 @@ module Theme
|
|
|
37
42
|
HELP
|
|
38
43
|
done: "Your theme is now live at %s",
|
|
39
44
|
not_found: "Theme #%s does not exist",
|
|
45
|
+
no_themes_error: "You don't have any theme to be published.",
|
|
46
|
+
no_themes_resolution: "Try to create an unpublished theme with {{command:theme push -u -t <theme_name>}}.",
|
|
40
47
|
select: "Select theme to push to",
|
|
41
48
|
confirm: "Are you sure you want to make %s the new live theme on %s?",
|
|
42
49
|
},
|
|
@@ -96,6 +103,7 @@ module Theme
|
|
|
96
103
|
name: "Theme name",
|
|
97
104
|
},
|
|
98
105
|
serve: {
|
|
106
|
+
theme_not_found: "Theme \"%s\" doesn't exist",
|
|
99
107
|
help: <<~HELP,
|
|
100
108
|
Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time.
|
|
101
109
|
|
|
@@ -116,6 +124,14 @@ module Theme
|
|
|
116
124
|
viewing_theme: "Viewing theme…",
|
|
117
125
|
syncing_theme: "Syncing theme #%s on %s",
|
|
118
126
|
open_fail: "Couldn't open the theme",
|
|
127
|
+
auth: {
|
|
128
|
+
error_message: <<~ERROR_MESSAGE,
|
|
129
|
+
It looks like you are using credentials that do not work with {{command:%s theme serve}}.
|
|
130
|
+
ERROR_MESSAGE
|
|
131
|
+
help_message: <<~HELP_MESSAGE,
|
|
132
|
+
Run {{command:%s logout}} and {{command:%s login --password "" --store STORE}} to force the authentication thought your browser.
|
|
133
|
+
HELP_MESSAGE
|
|
134
|
+
},
|
|
119
135
|
operation: {
|
|
120
136
|
status: {
|
|
121
137
|
error: "ERROR",
|
|
@@ -126,14 +142,14 @@ module Theme
|
|
|
126
142
|
syncer: {
|
|
127
143
|
forms: {
|
|
128
144
|
apply_to_all: {
|
|
129
|
-
title: "Would like apply this to all the other %s files?",
|
|
145
|
+
title: "Would you like to apply this to all the other %s files?",
|
|
130
146
|
yes: "Yes",
|
|
131
147
|
no: "No",
|
|
132
148
|
},
|
|
133
149
|
update_strategy: {
|
|
134
150
|
title_context: <<~TITLE,
|
|
135
151
|
|
|
136
|
-
The local file {{command:%s}} is different from the remote version in the development theme.
|
|
152
|
+
The local file {{command:%s}} is different from the remote version in the development theme.
|
|
137
153
|
TITLE
|
|
138
154
|
title_question: "What would you like to do?",
|
|
139
155
|
keep_remote: "Keep the remote version",
|
|
@@ -141,10 +157,21 @@ module Theme
|
|
|
141
157
|
union_merge: "Merge files (it may break the local file)",
|
|
142
158
|
exit: "Exit",
|
|
143
159
|
},
|
|
160
|
+
update_remote_deleted_strategy: {
|
|
161
|
+
title_context: <<~TITLE,
|
|
162
|
+
|
|
163
|
+
The local file {{command:%s}} doesn’t exist in the remote version of the development theme.
|
|
164
|
+
TITLE
|
|
165
|
+
title_question: "What would you like to do?",
|
|
166
|
+
keep_remote: "Keep the remote version (and remove it locally)",
|
|
167
|
+
keep_local: "Keep the local version (and restore it remotely)",
|
|
168
|
+
union_merge: "Merge files (it may break the local file)",
|
|
169
|
+
exit: "Exit",
|
|
170
|
+
},
|
|
144
171
|
delete_strategy: {
|
|
145
172
|
title_context: <<~TITLE,
|
|
146
173
|
|
|
147
|
-
The local file {{command:%s}} has been recently removed, but it's present on your remote development theme.
|
|
174
|
+
The local file {{command:%s}} has been recently removed, but it's present on your remote development theme.
|
|
148
175
|
TITLE
|
|
149
176
|
title_question: "What would you like to do?",
|
|
150
177
|
delete: "Delete permanently",
|
|
@@ -209,6 +236,8 @@ module Theme
|
|
|
209
236
|
HELP
|
|
210
237
|
select: "Select theme to delete",
|
|
211
238
|
done: "%s theme(s) deleted",
|
|
239
|
+
no_themes_error: "You don't have any theme to be deleted.",
|
|
240
|
+
no_themes_resolution: "Try to create an unpublished theme with {{command:theme push -u -t <theme_name>}}.",
|
|
212
241
|
not_found: "{{x}} Theme #%s does not exist",
|
|
213
242
|
live: "{{x}} Theme #%s is your live theme. You can't delete it.",
|
|
214
243
|
confirm: "Are you sure you want to delete %s on %s?",
|
|
@@ -280,6 +309,7 @@ module Theme
|
|
|
280
309
|
{{command:-t, --theme=NAME_OR_ID}} Theme ID or name of your theme.
|
|
281
310
|
{{command:-l, --live}} Open your live theme.
|
|
282
311
|
{{command:-d, --development}} Open your development theme.
|
|
312
|
+
{{command:-e, --editor}} Open the editor to the specified/selected theme.
|
|
283
313
|
HELP
|
|
284
314
|
},
|
|
285
315
|
list: {
|
|
@@ -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)
|
|
@@ -31,7 +31,7 @@ module ShopifyCLI
|
|
|
31
31
|
return unless has_shop?
|
|
32
32
|
|
|
33
33
|
ShopifyCLI::Theme::DevelopmentTheme.delete(@ctx)
|
|
34
|
-
rescue ShopifyCLI::API::APIRequestError
|
|
34
|
+
rescue ShopifyCLI::API::APIRequestError, ShopifyCLI::Abort, ShopifyCLI::AbortSilent
|
|
35
35
|
# Ignore since we can't delete it
|
|
36
36
|
end
|
|
37
37
|
end
|
data/lib/shopify_cli/context.rb
CHANGED
|
@@ -621,12 +621,16 @@ module ShopifyCLI
|
|
|
621
621
|
#
|
|
622
622
|
def new_version
|
|
623
623
|
if (time_of_last_check + VERSION_CHECK_INTERVAL) < (Time.now.to_i)
|
|
624
|
-
|
|
625
|
-
|
|
624
|
+
# Fork is not supported in Windows
|
|
625
|
+
if Process.respond_to?(:fork)
|
|
626
|
+
fork { retrieve_latest_gem_version }
|
|
627
|
+
else
|
|
628
|
+
thread = Thread.new { retrieve_latest_gem_version }
|
|
629
|
+
at_exit { thread.join }
|
|
626
630
|
end
|
|
627
631
|
end
|
|
628
632
|
latest_version = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
|
|
629
|
-
latest_version
|
|
633
|
+
latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
|
|
630
634
|
end
|
|
631
635
|
|
|
632
636
|
# Returns file extension depending on OS
|
|
@@ -6,7 +6,7 @@ require "rbconfig"
|
|
|
6
6
|
module ShopifyCLI
|
|
7
7
|
module Core
|
|
8
8
|
module Monorail
|
|
9
|
-
ENDPOINT_URI = URI.parse("https://monorail-edge.
|
|
9
|
+
ENDPOINT_URI = URI.parse("https://monorail-edge.shopifysvc.com/v1/produce")
|
|
10
10
|
INVOCATIONS_SCHEMA = "app_cli_command/5.0"
|
|
11
11
|
|
|
12
12
|
# Extra hash of data that will be sent in the payload
|
data/lib/shopify_cli/heroku.rb
CHANGED
|
@@ -4,6 +4,7 @@ module ShopifyCLI
|
|
|
4
4
|
linux: "https://cli-assets.heroku.com/heroku-linux-x64.tar.gz",
|
|
5
5
|
mac: "https://cli-assets.heroku.com/heroku-darwin-x64.tar.gz",
|
|
6
6
|
windows: "https://cli-assets.heroku.com/heroku-x64.exe",
|
|
7
|
+
mac_m1: "https://cli-assets.heroku.com/heroku-darwin-x64.tar.gz",
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
def initialize(ctx)
|
|
@@ -97,15 +98,16 @@ module ShopifyCLI
|
|
|
97
98
|
if File.exist?(local_path)
|
|
98
99
|
local_path
|
|
99
100
|
elsif @ctx.windows?
|
|
100
|
-
# Check if Heroku exists in the Windows registry and run it from there
|
|
101
|
-
require "win32/registry"
|
|
102
101
|
begin
|
|
102
|
+
# Check if Heroku exists in the Windows registry and run it from there
|
|
103
|
+
require "win32/registry"
|
|
104
|
+
|
|
103
105
|
windows_path = Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\heroku') do |reg|
|
|
104
106
|
reg[""] # This reads the 'Default' registry key
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
File.join(windows_path, "bin", "heroku").to_s
|
|
108
|
-
rescue
|
|
110
|
+
rescue StandardError, LoadError
|
|
109
111
|
"heroku"
|
|
110
112
|
end
|
|
111
113
|
else
|
data/lib/shopify_cli/release.rb
CHANGED
|
@@ -8,7 +8,6 @@ module ShopifyCLI
|
|
|
8
8
|
class Release
|
|
9
9
|
def initialize(new_version, github_access_token)
|
|
10
10
|
@new_version = new_version
|
|
11
|
-
@changelog = ShopifyCLI::Changelog.new
|
|
12
11
|
@github = Octokit::Client.new(access_token: github_access_token)
|
|
13
12
|
end
|
|
14
13
|
|
|
@@ -32,7 +31,7 @@ module ShopifyCLI
|
|
|
32
31
|
|
|
33
32
|
private
|
|
34
33
|
|
|
35
|
-
attr_reader :new_version, :
|
|
34
|
+
attr_reader :new_version, :github
|
|
36
35
|
|
|
37
36
|
def ensure_updated_main
|
|
38
37
|
# We can't be sure what is the correct action to take if changes have been
|
|
@@ -190,5 +189,9 @@ module ShopifyCLI
|
|
|
190
189
|
def system_or_fail(command, action)
|
|
191
190
|
raise "Failed to #{action}!" unless system(command)
|
|
192
191
|
end
|
|
192
|
+
|
|
193
|
+
def changelog
|
|
194
|
+
@changelog ||= ShopifyCLI::Changelog.new
|
|
195
|
+
end
|
|
193
196
|
end
|
|
194
197
|
end
|
|
@@ -184,7 +184,7 @@ module ShopifyCLI
|
|
|
184
184
|
|
|
185
185
|
context.puts(context.message("core.app.create.rails.adding_shopify_gem"))
|
|
186
186
|
File.open(File.join(context.root, "Gemfile"), "a") do |f|
|
|
187
|
-
f.puts "\ngem 'shopify_app', '
|
|
187
|
+
f.puts "\ngem 'shopify_app', '~>19.0.1'"
|
|
188
188
|
end
|
|
189
189
|
CLI::UI::Frame.open(context.message("core.app.create.rails.running_bundle_install")) do
|
|
190
190
|
syscall(%w(bundle install))
|
|
@@ -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
|
|
@@ -27,12 +27,13 @@ module ShopifyCLI
|
|
|
27
27
|
class << self
|
|
28
28
|
attr_accessor :ctx
|
|
29
29
|
|
|
30
|
-
def start(ctx, root, host: "127.0.0.1", port: 9292, poll: false, editor_sync: false,
|
|
30
|
+
def start(ctx, root, host: "127.0.0.1", theme: nil, port: 9292, poll: false, editor_sync: false,
|
|
31
|
+
mode: ReloadMode.default)
|
|
31
32
|
@ctx = ctx
|
|
32
|
-
theme =
|
|
33
|
+
theme = find_theme(root, theme)
|
|
33
34
|
ignore_filter = IgnoreFilter.from_path(root)
|
|
34
35
|
@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)
|
|
36
|
+
watcher = Watcher.new(ctx, theme: theme, ignore_filter: ignore_filter, syncer: @syncer, poll: poll)
|
|
36
37
|
remote_watcher = RemoteWatcher.to(theme: theme, syncer: @syncer)
|
|
37
38
|
|
|
38
39
|
# Setup the middleware stack. Mimics Rack::Builder / config.ru, but in reverse order
|
|
@@ -108,6 +109,22 @@ module ShopifyCLI
|
|
|
108
109
|
@syncer.shutdown
|
|
109
110
|
WebServer.shutdown
|
|
110
111
|
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def find_theme(root, identifier)
|
|
116
|
+
return theme_by_identifier(root, identifier) if identifier
|
|
117
|
+
DevelopmentTheme.find_or_create!(@ctx, root: root)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def theme_by_identifier(root, identifier)
|
|
121
|
+
theme = ShopifyCLI::Theme::Theme.find_by_identifier(@ctx, root: root, identifier: identifier)
|
|
122
|
+
theme || not_found_error(identifier)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def not_found_error(identifier)
|
|
126
|
+
@ctx.abort(@ctx.message("theme.serve.theme_not_found", identifier))
|
|
127
|
+
end
|
|
111
128
|
end
|
|
112
129
|
end
|
|
113
130
|
end
|
|
@@ -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
|
|
@@ -7,7 +7,7 @@ module ShopifyCLI
|
|
|
7
7
|
class Syncer
|
|
8
8
|
module Forms
|
|
9
9
|
class SelectUpdateStrategy < BaseStrategyForm
|
|
10
|
-
flag_arguments :file
|
|
10
|
+
flag_arguments :file, :exists_remotely
|
|
11
11
|
|
|
12
12
|
def strategies
|
|
13
13
|
%i[
|
|
@@ -19,7 +19,7 @@ module ShopifyCLI
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def prefix
|
|
22
|
-
"theme.serve.syncer.forms
|
|
22
|
+
"theme.serve.syncer.forms.#{exists_remotely ? "update_strategy" : "update_remote_deleted_strategy"}"
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -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.18.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-30 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
|