shopify-cli 2.15.6 → 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/.github/CODEOWNERS +4 -4
- data/.github/workflows/shopify.yml +0 -33
- data/CHANGELOG.md +35 -1
- data/Gemfile.lock +4 -4
- data/Tests.dockerfile +1 -1
- data/ext/shopify-extensions/version +1 -1
- data/lib/graphql/find_organization_with_apps.graphql +20 -0
- data/lib/project_types/extension/cli.rb +3 -0
- data/lib/project_types/extension/commands/build.rb +0 -2
- data/lib/project_types/extension/commands/create.rb +6 -0
- data/lib/project_types/extension/commands/serve.rb +8 -3
- data/lib/project_types/extension/features/argo.rb +0 -31
- data/lib/project_types/extension/features/argo_config.rb +0 -1
- data/lib/project_types/extension/features/argo_serve.rb +1 -1
- data/lib/project_types/extension/messages/messages.rb +23 -0
- data/lib/project_types/extension/models/development_server.rb +2 -1
- data/lib/project_types/extension/models/development_server_requirements.rb +24 -4
- data/lib/project_types/extension/models/npm_package.rb +15 -3
- data/lib/project_types/extension/models/server_config/capabilities.rb +11 -0
- data/lib/project_types/extension/models/server_config/development_renderer.rb +6 -1
- data/lib/project_types/extension/models/server_config/extension.rb +10 -3
- data/lib/project_types/extension/models/server_config/root.rb +0 -2
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
- data/lib/project_types/extension/tasks/configure_features.rb +4 -0
- data/lib/project_types/extension/tasks/convert_server_config.rb +8 -4
- data/lib/project_types/extension/tasks/execute_commands/base.rb +2 -0
- data/lib/project_types/extension/tasks/execute_commands/build.rb +2 -1
- data/lib/project_types/extension/tasks/execute_commands/create.rb +0 -3
- data/lib/project_types/extension/tasks/execute_commands/outdated_extension_detection.rb +53 -0
- data/lib/project_types/extension/tasks/execute_commands/serve.rb +2 -1
- data/lib/project_types/extension/tasks/get_apps.rb +6 -9
- data/lib/project_types/extension/tasks/get_extensions.rb +12 -11
- data/lib/project_types/extension/tasks/merge_server_config.rb +4 -3
- data/lib/project_types/script/cli.rb +1 -0
- data/lib/project_types/script/config/extension_points.yml +17 -3
- data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
- data/lib/project_types/script/layers/application/connect_app.rb +1 -1
- 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 +0 -3
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +3 -2
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +2 -2
- 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 +5 -2
- data/lib/shopify_cli/commands/login.rb +2 -2
- data/lib/shopify_cli/commands/logout.rb +1 -1
- data/lib/shopify_cli/constants.rb +2 -0
- data/lib/shopify_cli/context.rb +14 -9
- data/lib/shopify_cli/environment.rb +8 -0
- data/lib/shopify_cli/partners_api/app_extensions.rb +6 -6
- data/lib/shopify_cli/partners_api/organizations.rb +12 -4
- data/lib/shopify_cli/services/app/create/rails_service.rb +1 -1
- data/lib/shopify_cli/tasks/ensure_env.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb +5 -6
- data/lib/shopify_cli/theme/dev_server/local_assets.rb +1 -1
- 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.rb +4 -0
- data/lib/shopify_cli/theme/theme_admin_api.rb +3 -1
- data/lib/shopify_cli/version.rb +1 -1
- data/{shipit.yml → shipit.rubygems.yml} +0 -0
- data/shopify-cli.gemspec +1 -1
- metadata +9 -5
@@ -0,0 +1,53 @@
|
|
1
|
+
module Extension
|
2
|
+
module Tasks
|
3
|
+
module ExecuteCommands
|
4
|
+
module OutdatedExtensionDetection
|
5
|
+
class OutdatedCheck
|
6
|
+
include ShopifyCLI::MethodObject
|
7
|
+
|
8
|
+
property! :type, accepts: Models::DevelopmentServerRequirements.method(:type_supported?)
|
9
|
+
property! :context, accepts: ShopifyCLI::Context
|
10
|
+
property! :project, accepts: ShopifyCLI::Project, default: -> { ShopifyCLI::Project.current }
|
11
|
+
|
12
|
+
def call
|
13
|
+
return false if valid?(parse_package)
|
14
|
+
context.abort(upgrade_instructions)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def upgrade_instructions
|
20
|
+
case type
|
21
|
+
when "checkout_ui_extension"
|
22
|
+
context.message("errors.outdated_extensions.checkout_ui_extension")
|
23
|
+
else
|
24
|
+
context.message("errors.outdated_extensions.unknown")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_package
|
29
|
+
File.open(Pathname(project.directory).join("package.json")) do |file|
|
30
|
+
Models::NpmPackage.parse(file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid?(package)
|
35
|
+
case type
|
36
|
+
when "checkout_ui_extension"
|
37
|
+
package.dev_dependency?("@shopify/shopify-cli-extensions") &&
|
38
|
+
package.script?("build") &&
|
39
|
+
package.script?("develop")
|
40
|
+
else
|
41
|
+
true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def call(*)
|
47
|
+
return super unless Models::DevelopmentServerRequirements.supported?(type)
|
48
|
+
OutdatedCheck.call(type: type, context: context).then { super }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -5,7 +5,8 @@ module Extension
|
|
5
5
|
module Tasks
|
6
6
|
module ExecuteCommands
|
7
7
|
class Serve < Base
|
8
|
-
|
8
|
+
prepend OutdatedExtensionDetection
|
9
|
+
|
9
10
|
property! :config_file_path, accepts: String
|
10
11
|
property :port, accepts: Integer, default: ShopifyCLI::Constants::Extension::DEFAULT_PORT
|
11
12
|
property :resource_url, accepts: String
|
@@ -5,20 +5,17 @@ module Extension
|
|
5
5
|
module Tasks
|
6
6
|
class GetApps < ShopifyCLI::Task
|
7
7
|
def call(context:)
|
8
|
-
|
9
|
-
|
8
|
+
org_id = ShopifyCLI::DB.get(:organization_id)
|
9
|
+
return [] unless org_id
|
10
|
+
|
11
|
+
organization = ShopifyCLI::PartnersAPI::Organizations.fetch_with_apps(context, id: org_id)
|
12
|
+
apps_owned_by_organization(organization)
|
10
13
|
end
|
11
14
|
|
12
15
|
private
|
13
16
|
|
14
|
-
def apps_from_organizations(organizations)
|
15
|
-
organizations.flat_map do |organization|
|
16
|
-
apps_owned_by_organization(organization)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
17
|
def apps_owned_by_organization(organization)
|
21
|
-
return [] unless organization
|
18
|
+
return [] unless organization&.dig("apps")
|
22
19
|
|
23
20
|
organization["apps"].map do |app|
|
24
21
|
Converters::AppConverter.from_hash(app, organization)
|
@@ -5,28 +5,29 @@ module Extension
|
|
5
5
|
module Tasks
|
6
6
|
class GetExtensions < ShopifyCLI::Task
|
7
7
|
def call(context:, type:)
|
8
|
-
|
9
|
-
|
8
|
+
org_id = ShopifyCLI::DB.get(:organization_id)
|
9
|
+
return [] unless org_id
|
10
|
+
|
11
|
+
organization = ShopifyCLI::PartnersAPI::Organizations.fetch_with_extensions(context, type, id: org_id)
|
12
|
+
return [] unless organization_with_apps?(organization)
|
13
|
+
extensions_owned_by_organization(organization, context: context)
|
10
14
|
end
|
11
15
|
|
12
16
|
private
|
13
17
|
|
14
|
-
def extensions_from_organizations(organizations, context:)
|
15
|
-
organizations.flat_map do |organization|
|
16
|
-
extensions_owned_by_organization(organization, context: context)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
18
|
def extensions_owned_by_organization(organization, context:)
|
21
|
-
return [] unless organization.key?("apps") && organization["apps"].any?
|
22
|
-
|
23
19
|
organization["apps"].flat_map do |app|
|
24
|
-
app["extensionRegistrations"]
|
20
|
+
registrations = app["extensionRegistrations"] || []
|
21
|
+
registrations.map do |registration|
|
25
22
|
[Converters::AppConverter.from_hash(app, organization),
|
26
23
|
Converters::RegistrationConverter.from_hash(context, registration)]
|
27
24
|
end
|
28
25
|
end
|
29
26
|
end
|
27
|
+
|
28
|
+
def organization_with_apps?(organization)
|
29
|
+
organization&.key?("apps") && organization["apps"].any?
|
30
|
+
end
|
30
31
|
end
|
31
32
|
end
|
32
33
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "shopify_cli"
|
3
|
-
require "yaml"
|
4
3
|
require "pathname"
|
5
4
|
|
6
5
|
module Extension
|
@@ -10,7 +9,7 @@ module Extension
|
|
10
9
|
|
11
10
|
property! :context, accepts: ShopifyCLI::Context
|
12
11
|
property! :file_path, accepts: ->(path) { Pathname(path).yield_self(&:absolute?) }
|
13
|
-
property
|
12
|
+
property! :port, accepts: Integer, default: ShopifyCLI::Constants::Extension::DEFAULT_PORT
|
14
13
|
property :resource_url, accepts: String
|
15
14
|
property :tunnel_url, accepts: String
|
16
15
|
property! :type, accepts: Models::DevelopmentServerRequirements::SUPPORTED_EXTENSION_TYPES
|
@@ -33,7 +32,9 @@ module Extension
|
|
33
32
|
store: project.env.shop || "",
|
34
33
|
title: project.title,
|
35
34
|
tunnel_url: tunnel_url,
|
36
|
-
type: type
|
35
|
+
type: type,
|
36
|
+
port: port,
|
37
|
+
metafields: config["metafields"]
|
37
38
|
)
|
38
39
|
rescue Psych::SyntaxError => e
|
39
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
|
@@ -7,6 +7,8 @@ payment_methods:
|
|
7
7
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
8
8
|
wasm:
|
9
9
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
10
|
+
rust:
|
11
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
10
12
|
shipping_methods:
|
11
13
|
domain: 'checkout'
|
12
14
|
libraries:
|
@@ -36,21 +38,33 @@ delivery_discount_types:
|
|
36
38
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
37
39
|
wasm:
|
38
40
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
39
|
-
|
41
|
+
product_discounts:
|
40
42
|
beta: true
|
41
43
|
domain: 'discounts'
|
42
44
|
libraries:
|
43
45
|
wasm:
|
44
46
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
45
|
-
|
47
|
+
rust:
|
48
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
49
|
+
order_discounts:
|
46
50
|
beta: true
|
47
51
|
domain: 'discounts'
|
48
52
|
libraries:
|
49
53
|
wasm:
|
50
54
|
repo: "https://github.com/Shopify/scripts-apis-examples"
|
51
|
-
|
55
|
+
rust:
|
56
|
+
repo: "https://github.com/Shopify/scripts-apis-examples"
|
57
|
+
shipping_discounts:
|
52
58
|
beta: true
|
53
59
|
domain: 'discounts'
|
54
60
|
libraries:
|
55
61
|
wasm:
|
56
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
|
@@ -137,8 +137,6 @@ module Script
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
class ProjectCreatorNotFoundError < ScriptProjectError; end
|
141
|
-
|
142
140
|
class SystemCallFailureError < ScriptProjectError
|
143
141
|
attr_reader :out, :cmd
|
144
142
|
def initialize(out:, cmd:)
|
@@ -157,7 +155,6 @@ module Script
|
|
157
155
|
end
|
158
156
|
|
159
157
|
class ScriptProjectAlreadyExistsError < ScriptProjectError; end
|
160
|
-
class TaskRunnerNotFoundError < ScriptProjectError; end
|
161
158
|
class BuildScriptNotFoundError < ScriptProjectError; end
|
162
159
|
|
163
160
|
class WebAssemblyBinaryNotFoundError < ScriptProjectError
|
@@ -26,8 +26,9 @@ module Script
|
|
26
26
|
"wasm" => WasmProjectCreator,
|
27
27
|
}
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
project_creator = project_creators[language] || WasmProjectCreator
|
30
|
+
|
31
|
+
project_creator.new(
|
31
32
|
ctx: ctx,
|
32
33
|
type: type,
|
33
34
|
project_name: project_name,
|
@@ -13,8 +13,8 @@ module Script
|
|
13
13
|
"wasm" => WasmTaskRunner,
|
14
14
|
}
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
task_runner = task_runners[language] || WasmTaskRunner
|
17
|
+
task_runner.new(ctx)
|
18
18
|
end
|
19
19
|
|
20
20
|
def initialize(ctx)
|
@@ -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",
|
@@ -98,6 +98,8 @@ module ShopifyCLI
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def get_shop_or_abort(ctx)
|
101
|
+
env_store = Environment.store
|
102
|
+
return env_store unless env_store.nil?
|
101
103
|
ctx.abort(
|
102
104
|
ctx.message("core.populate.error.no_shop", ShopifyCLI::TOOL_NAME)
|
103
105
|
) unless ShopifyCLI::DB.exists?(:shop)
|
@@ -119,7 +121,8 @@ module ShopifyCLI
|
|
119
121
|
end
|
120
122
|
|
121
123
|
def access_token(ctx, shop)
|
122
|
-
|
124
|
+
env_token = Environment.admin_auth_token
|
125
|
+
env_token || ShopifyCLI::DB.get(:shopify_exchange_token) do
|
123
126
|
authenticate(ctx, shop)
|
124
127
|
ShopifyCLI::DB.get(:shopify_exchange_token)
|
125
128
|
end
|
@@ -153,7 +156,7 @@ module ShopifyCLI
|
|
153
156
|
def auth_headers(token)
|
154
157
|
{
|
155
158
|
Authorization: "Bearer #{token}",
|
156
|
-
"X-Shopify-Access-Token" => token,
|
159
|
+
"X-Shopify-Access-Token" => token,
|
157
160
|
}
|
158
161
|
end
|
159
162
|
end
|
@@ -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
|
@@ -53,9 +53,11 @@ module ShopifyCLI
|
|
53
53
|
|
54
54
|
# Authentication
|
55
55
|
AUTH_TOKEN = "SHOPIFY_CLI_AUTH_TOKEN"
|
56
|
+
ADMIN_AUTH_TOKEN = "SHOPIFY_CLI_ADMIN_AUTH_TOKEN"
|
56
57
|
|
57
58
|
# Monorail
|
58
59
|
MONORAIL_REAL_EVENTS = "MONORAIL_REAL_EVENTS"
|
60
|
+
STORE = "SHOPIFY_CLI_STORE"
|
59
61
|
end
|
60
62
|
|
61
63
|
module SupportedVersions
|
data/lib/shopify_cli/context.rb
CHANGED
@@ -17,6 +17,7 @@ module ShopifyCLI
|
|
17
17
|
GEM_LATEST_URI = URI.parse("https://rubygems.org/api/v1/versions/shopify-cli/latest.json")
|
18
18
|
VERSION_CHECK_SECTION = "versioncheck"
|
19
19
|
LAST_CHECKED_AT_FIELD = "last_checked_at"
|
20
|
+
LATEST_VERSION_FIELD = "latest_version"
|
20
21
|
VERSION_CHECK_INTERVAL = 86400
|
21
22
|
|
22
23
|
class << self
|
@@ -619,11 +620,17 @@ module ShopifyCLI
|
|
619
620
|
# : nil otherwise
|
620
621
|
#
|
621
622
|
def new_version
|
622
|
-
if (time_of_last_check + VERSION_CHECK_INTERVAL) < (
|
623
|
-
|
624
|
-
|
625
|
-
|
623
|
+
if (time_of_last_check + VERSION_CHECK_INTERVAL) < (Time.now.to_i)
|
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 }
|
630
|
+
end
|
626
631
|
end
|
632
|
+
latest_version = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
|
633
|
+
latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
|
627
634
|
end
|
628
635
|
|
629
636
|
# Returns file extension depending on OS
|
@@ -669,17 +676,15 @@ module ShopifyCLI
|
|
669
676
|
def retrieve_latest_gem_version
|
670
677
|
response = Net::HTTP.get_response(GEM_LATEST_URI)
|
671
678
|
latest = JSON.parse(response.body)
|
672
|
-
latest["version"]
|
679
|
+
ShopifyCLI::Config.set(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, latest["version"])
|
673
680
|
rescue
|
674
681
|
nil
|
682
|
+
ensure
|
683
|
+
ShopifyCLI::Config.set(VERSION_CHECK_SECTION, LAST_CHECKED_AT_FIELD, Time.now.to_i)
|
675
684
|
end
|
676
685
|
|
677
686
|
def time_of_last_check
|
678
687
|
(val = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LAST_CHECKED_AT_FIELD)) ? val.to_i : 0
|
679
688
|
end
|
680
|
-
|
681
|
-
def update_time_of_last_check(time)
|
682
|
-
ShopifyCLI::Config.set(VERSION_CHECK_SECTION, LAST_CHECKED_AT_FIELD, time)
|
683
|
-
end
|
684
689
|
end
|
685
690
|
end
|
@@ -166,6 +166,14 @@ module ShopifyCLI
|
|
166
166
|
env_variables[Constants::EnvironmentVariables::AUTH_TOKEN]
|
167
167
|
end
|
168
168
|
|
169
|
+
def self.admin_auth_token(env_variables: ENV)
|
170
|
+
env_variables[Constants::EnvironmentVariables::ADMIN_AUTH_TOKEN]
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.store(env_variables: ENV)
|
174
|
+
env_variables[Constants::EnvironmentVariables::STORE]
|
175
|
+
end
|
176
|
+
|
169
177
|
def self.env_variable_truthy?(variable_name, env_variables: ENV)
|
170
178
|
TRUTHY_ENV_VARIABLE_VALUES.include?(env_variables[variable_name.to_s])
|
171
179
|
end
|
@@ -8,23 +8,23 @@ module ShopifyCLI
|
|
8
8
|
class PartnersAPI
|
9
9
|
class AppExtensions
|
10
10
|
class << self
|
11
|
-
def fetch_apps_extensions(ctx,
|
12
|
-
jobs = apps(
|
11
|
+
def fetch_apps_extensions(ctx, org, type)
|
12
|
+
jobs = apps(org).map { |app| AppExtensions::Job.new(ctx, app, type) }
|
13
13
|
|
14
14
|
consume_jobs!(jobs)
|
15
15
|
patch_apps_with_extensions!(jobs)
|
16
16
|
|
17
|
-
|
17
|
+
org
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
-
def apps(
|
23
|
-
|
22
|
+
def apps(org)
|
23
|
+
(org && org["apps"]) || []
|
24
24
|
end
|
25
25
|
|
26
26
|
def consume_jobs!(jobs)
|
27
|
-
thread_pool = ShopifyCLI::ThreadPool.new
|
27
|
+
thread_pool = ShopifyCLI::ThreadPool.new(pool_size: 1)
|
28
28
|
jobs.each do |job|
|
29
29
|
thread_pool.schedule(job)
|
30
30
|
end
|
@@ -18,7 +18,7 @@ module ShopifyCLI
|
|
18
18
|
org
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def fetch_all_with_apps(ctx)
|
22
22
|
resp = PartnersAPI.query(ctx, "all_orgs_with_apps")
|
23
23
|
(resp&.dig("data", "organizations", "nodes") || []).map do |org|
|
24
24
|
org["stores"] = (org.dig("stores", "nodes") || [])
|
@@ -27,9 +27,17 @@ module ShopifyCLI
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
30
|
+
def fetch_with_apps(ctx, id:)
|
31
|
+
resp = PartnersAPI.query(ctx, "find_organization_with_apps", id: id)
|
32
|
+
organization = resp&.dig("data", "organizations", "nodes")&.first
|
33
|
+
return unless organization
|
34
|
+
|
35
|
+
organization.tap { organization["apps"] = (organization.dig("apps", "nodes") || []) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetch_with_extensions(ctx, type, id:)
|
39
|
+
organization = fetch_with_apps(ctx, id: id)
|
40
|
+
AppExtensions.fetch_apps_extensions(ctx, organization, type)
|
33
41
|
end
|
34
42
|
end
|
35
43
|
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))
|
@@ -25,7 +25,7 @@ module ShopifyCLI
|
|
25
25
|
if Shopifolk.check && wants_to_run_against_shopify_org?
|
26
26
|
Shopifolk.act_as_shopify_organization
|
27
27
|
end
|
28
|
-
orgs = PartnersAPI::Organizations.
|
28
|
+
orgs = PartnersAPI::Organizations.fetch_all_with_apps(@ctx)
|
29
29
|
org_id = if orgs.count == 1
|
30
30
|
orgs.first["id"]
|
31
31
|
else
|