shopify-cli 2.6.2 → 2.6.6
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/PULL_REQUEST_TEMPLATE.md +15 -4
- data/.github/workflows/shopify.yml +3 -6
- data/CHANGELOG.md +89 -99
- data/CONTRIBUTING.md +9 -1
- data/Dockerfile +22 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +7 -3
- data/RELEASING.md +17 -30
- data/Rakefile +0 -5
- data/lib/project_types/extension/cli.rb +1 -0
- data/lib/project_types/extension/commands/create.rb +1 -0
- data/lib/project_types/extension/features/argo.rb +9 -10
- data/lib/project_types/extension/features/argo_serve.rb +1 -1
- data/lib/project_types/extension/forms/create.rb +1 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +2 -1
- data/lib/project_types/extension/messages/messages.rb +1 -0
- data/lib/project_types/extension/models/server_config/extension.rb +2 -0
- data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +1 -1
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
- data/lib/project_types/extension/tasks/converters/server_config_converter.rb +4 -5
- data/lib/project_types/extension/tasks/find_package_from_json.rb +37 -0
- data/lib/project_types/extension/tasks/load_server_config.rb +6 -1
- data/lib/project_types/node/commands/serve.rb +7 -16
- data/lib/project_types/node/messages/messages.rb +0 -5
- data/lib/project_types/php/commands/serve.rb +6 -9
- data/lib/project_types/php/messages/messages.rb +1 -4
- data/lib/project_types/rails/commands/create.rb +45 -16
- data/lib/project_types/rails/commands/serve.rb +7 -8
- data/lib/project_types/rails/forms/create.rb +0 -1
- data/lib/project_types/rails/messages/messages.rb +1 -4
- data/lib/project_types/script/commands/create.rb +4 -5
- data/lib/project_types/script/config/extension_points.yml +10 -0
- data/lib/project_types/script/errors.rb +0 -18
- data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
- data/lib/project_types/script/layers/application/build_script.rb +2 -1
- data/lib/project_types/script/layers/application/create_script.rb +2 -2
- data/lib/project_types/script/layers/application/push_script.rb +15 -1
- data/lib/project_types/script/layers/domain/push_package.rb +5 -2
- data/lib/project_types/script/layers/domain/script_json.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +0 -4
- data/lib/project_types/script/layers/infrastructure/errors.rb +17 -2
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +29 -13
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +29 -13
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +4 -2
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +3 -4
- data/lib/project_types/script/layers/infrastructure/script_service.rb +7 -2
- data/lib/project_types/script/messages/messages.rb +9 -22
- data/lib/project_types/script/ui/error_handler.rb +16 -26
- data/lib/project_types/theme/commands/serve.rb +2 -0
- data/lib/project_types/theme/messages/messages.rb +6 -0
- data/lib/shopify_cli/app_type_detector.rb +32 -0
- data/lib/shopify_cli/command.rb +6 -1
- data/lib/shopify_cli/command_options/command_serve_options.rb +43 -0
- data/lib/shopify_cli/command_options.rb +7 -0
- data/lib/shopify_cli/commands/login.rb +3 -3
- data/lib/shopify_cli/commands/reporting.rb +38 -0
- data/lib/shopify_cli/commands/switch.rb +1 -1
- data/lib/shopify_cli/commands.rb +1 -0
- data/lib/shopify_cli/constants.rb +7 -3
- data/lib/shopify_cli/core/monorail.rb +9 -20
- data/lib/shopify_cli/environment.rb +15 -1
- data/lib/shopify_cli/exception_reporter.rb +29 -15
- data/lib/shopify_cli/messages/messages.rb +48 -19
- data/lib/shopify_cli/migrator/migration.rb +1 -1
- data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +1 -1
- data/lib/shopify_cli/migrator/migrations/1633691650_merge_reporting_configuration.rb +41 -0
- data/lib/shopify_cli/migrator.rb +9 -11
- data/lib/shopify_cli/reporting_configuration_controller.rb +64 -0
- data/lib/shopify_cli/services/base_service.rb +13 -0
- data/lib/shopify_cli/services/reporting_service.rb +16 -0
- data/lib/shopify_cli/services.rb +6 -0
- data/lib/shopify_cli/theme/dev_server/watcher.rb +2 -2
- data/lib/shopify_cli/theme/dev_server.rb +3 -2
- data/lib/shopify_cli/version.rb +1 -1
- data/lib/shopify_cli.rb +4 -0
- data/shopify-cli.gemspec +2 -13
- data/utilities/docker/container.rb +97 -0
- data/utilities/docker.rb +45 -3
- metadata +18 -10
- data/ext/shopify-cli/extconf.rb +0 -60
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +0 -0
- data/lib/shopify_cli/exception_reporter/permission_controller.rb +0 -54
@@ -4,7 +4,6 @@ module Script
|
|
4
4
|
module Layers
|
5
5
|
module Infrastructure
|
6
6
|
module Errors
|
7
|
-
class AppNotInstalledError < ScriptProjectError; end
|
8
7
|
class BuildError < ScriptProjectError; end
|
9
8
|
class ScriptJsonSyntaxError < ScriptProjectError; end
|
10
9
|
|
@@ -40,6 +39,23 @@ module Script
|
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
42
|
+
class APILibraryNotFoundError < ScriptProjectError
|
43
|
+
attr_reader :library_name
|
44
|
+
def initialize(library_name)
|
45
|
+
super()
|
46
|
+
@library_name = library_name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class LanguageLibraryForAPINotFoundError < ScriptProjectError
|
51
|
+
attr_reader :language, :api
|
52
|
+
def initialize(language:, api:)
|
53
|
+
super()
|
54
|
+
@language = language
|
55
|
+
@api = api
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
43
59
|
class DependencyInstallError < ScriptProjectError; end
|
44
60
|
class DeprecatedEPError < ScriptProjectError; end
|
45
61
|
class EmptyResponseError < ScriptProjectError; end
|
@@ -84,7 +100,6 @@ module Script
|
|
84
100
|
end
|
85
101
|
|
86
102
|
class ScriptProjectAlreadyExistsError < ScriptProjectError; end
|
87
|
-
class ShopAuthenticationError < ScriptProjectError; end
|
88
103
|
class TaskRunnerNotFoundError < ScriptProjectError; end
|
89
104
|
class BuildScriptNotFoundError < ScriptProjectError; end
|
90
105
|
class InvalidBuildScriptError < ScriptProjectError; end
|
@@ -5,7 +5,7 @@ module Script
|
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
7
|
class AssemblyScriptTaskRunner
|
8
|
-
BYTECODE_FILE = "build
|
8
|
+
BYTECODE_FILE = "build/script.wasm"
|
9
9
|
METADATA_FILE = "build/metadata.json"
|
10
10
|
SCRIPT_SDK_BUILD = "npm run build"
|
11
11
|
|
@@ -47,8 +47,33 @@ module Script
|
|
47
47
|
Domain::Metadata.create_from_json(@ctx, raw_contents)
|
48
48
|
end
|
49
49
|
|
50
|
+
def library_version(library_name)
|
51
|
+
output = JSON.parse(CommandRunner.new(ctx: ctx).call("npm -s list --json"))
|
52
|
+
library_version_from_npm_list(output, library_name)
|
53
|
+
rescue Errors::SystemCallFailureError => error
|
54
|
+
library_version_from_npm_list_error_output(error, library_name)
|
55
|
+
end
|
56
|
+
|
50
57
|
private
|
51
58
|
|
59
|
+
def library_version_from_npm_list_error_output(error, library_name)
|
60
|
+
# npm list can return a failure status code, even when returning the correct data.
|
61
|
+
# This causes the CommandRunner to throw a SystemCallFailure error that contains the data.
|
62
|
+
# In here, we check that the output contains `npm list`'s structure and extract the version.
|
63
|
+
output = JSON.parse(error.out)
|
64
|
+
raise error unless output.key?("dependencies")
|
65
|
+
|
66
|
+
library_version_from_npm_list(output, library_name)
|
67
|
+
rescue JSON::ParserError
|
68
|
+
raise error
|
69
|
+
end
|
70
|
+
|
71
|
+
def library_version_from_npm_list(output, library_name)
|
72
|
+
output.dig("dependencies", library_name, "version").tap do |version|
|
73
|
+
raise Errors::APILibraryNotFoundError, library_name unless version
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
52
77
|
def check_node_version!
|
53
78
|
output, status = @ctx.capture2e("node", "--version")
|
54
79
|
raise Errors::DependencyInstallError, output unless status.success?
|
@@ -80,19 +105,10 @@ module Script
|
|
80
105
|
end
|
81
106
|
|
82
107
|
def bytecode
|
83
|
-
|
84
|
-
filename = format(BYTECODE_FILE, name: "script")
|
85
|
-
|
86
|
-
bytecode_file = if ctx.file_exist?(filename)
|
87
|
-
filename
|
88
|
-
elsif ctx.file_exist?(legacy_filename)
|
89
|
-
legacy_filename
|
90
|
-
else
|
91
|
-
raise Errors::WebAssemblyBinaryNotFoundError
|
92
|
-
end
|
108
|
+
raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(BYTECODE_FILE)
|
93
109
|
|
94
|
-
contents = ctx.binread(
|
95
|
-
ctx.rm(
|
110
|
+
contents = ctx.binread(BYTECODE_FILE)
|
111
|
+
ctx.rm(BYTECODE_FILE)
|
96
112
|
|
97
113
|
contents
|
98
114
|
end
|
@@ -5,7 +5,7 @@ module Script
|
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
7
|
class TypeScriptTaskRunner
|
8
|
-
BYTECODE_FILE = "build
|
8
|
+
BYTECODE_FILE = "build/index.wasm"
|
9
9
|
METADATA_FILE = "build/metadata.json"
|
10
10
|
SCRIPT_SDK_BUILD = "npm run build"
|
11
11
|
GEN_METADATA = "npm run gen-metadata"
|
@@ -48,8 +48,33 @@ module Script
|
|
48
48
|
Domain::Metadata.create_from_json(@ctx, raw_contents)
|
49
49
|
end
|
50
50
|
|
51
|
+
def library_version(library_name)
|
52
|
+
output = JSON.parse(CommandRunner.new(ctx: ctx).call("npm -s list --json"))
|
53
|
+
library_version_from_npm_list(output, library_name)
|
54
|
+
rescue Errors::SystemCallFailureError => error
|
55
|
+
library_version_from_npm_list_error_output(error, library_name)
|
56
|
+
end
|
57
|
+
|
51
58
|
private
|
52
59
|
|
60
|
+
def library_version_from_npm_list_error_output(error, library_name)
|
61
|
+
# npm list can return a failure status code, even when returning the correct data.
|
62
|
+
# This causes the CommandRunner to throw a SystemCallFailure error that contains the data.
|
63
|
+
# In here, we check that the output contains `npm list`'s structure and extract the version.
|
64
|
+
output = JSON.parse(error.out)
|
65
|
+
raise error unless output.key?("dependencies")
|
66
|
+
|
67
|
+
library_version_from_npm_list(output, library_name)
|
68
|
+
rescue JSON::ParserError
|
69
|
+
raise error
|
70
|
+
end
|
71
|
+
|
72
|
+
def library_version_from_npm_list(output, library_name)
|
73
|
+
output.dig("dependencies", library_name, "version").tap do |version|
|
74
|
+
raise Errors::APILibraryNotFoundError, library_name unless version
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
53
78
|
def check_node_version!
|
54
79
|
output, status = @ctx.capture2e("node", "--version")
|
55
80
|
raise Errors::DependencyInstallError, output unless status.success?
|
@@ -82,19 +107,10 @@ module Script
|
|
82
107
|
end
|
83
108
|
|
84
109
|
def bytecode
|
85
|
-
|
86
|
-
filename = format(BYTECODE_FILE, name: "index")
|
87
|
-
|
88
|
-
bytecode_file = if ctx.file_exist?(filename)
|
89
|
-
filename
|
90
|
-
elsif ctx.file_exist?(legacy_filename)
|
91
|
-
legacy_filename
|
92
|
-
else
|
93
|
-
raise Errors::WebAssemblyBinaryNotFoundError
|
94
|
-
end
|
110
|
+
raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(BYTECODE_FILE)
|
95
111
|
|
96
|
-
contents = ctx.binread(
|
97
|
-
ctx.rm(
|
112
|
+
contents = ctx.binread(BYTECODE_FILE)
|
113
|
+
ctx.rm(BYTECODE_FILE)
|
98
114
|
|
99
115
|
contents
|
100
116
|
end
|
@@ -7,7 +7,7 @@ module Script
|
|
7
7
|
include SmartProperties
|
8
8
|
property! :ctx, accepts: ShopifyCLI::Context
|
9
9
|
|
10
|
-
def create_push_package(script_project:, script_content:, compiled_type:, metadata:)
|
10
|
+
def create_push_package(script_project:, script_content:, compiled_type:, metadata:, library:)
|
11
11
|
build_file_path = file_path(script_project.id, compiled_type)
|
12
12
|
write_to_path(build_file_path, script_content)
|
13
13
|
|
@@ -19,10 +19,11 @@ module Script
|
|
19
19
|
compiled_type: compiled_type,
|
20
20
|
metadata: metadata,
|
21
21
|
script_json: script_project.script_json,
|
22
|
+
library: library
|
22
23
|
)
|
23
24
|
end
|
24
25
|
|
25
|
-
def get_push_package(script_project:, compiled_type:, metadata:)
|
26
|
+
def get_push_package(script_project:, compiled_type:, metadata:, library:)
|
26
27
|
build_file_path = file_path(script_project.id, compiled_type)
|
27
28
|
raise Domain::PushPackageNotFoundError unless ctx.file_exist?(build_file_path)
|
28
29
|
|
@@ -34,6 +35,7 @@ module Script
|
|
34
35
|
script_content: script_content,
|
35
36
|
metadata: metadata,
|
36
37
|
script_json: script_project.script_json,
|
38
|
+
library: library
|
37
39
|
)
|
38
40
|
end
|
39
41
|
|
@@ -81,10 +81,10 @@ module Script
|
|
81
81
|
)
|
82
82
|
end
|
83
83
|
|
84
|
-
def update_or_create_script_json(title
|
84
|
+
def update_or_create_script_json(title:)
|
85
85
|
script_json = ScriptJsonRepository
|
86
86
|
.new(ctx: ctx)
|
87
|
-
.update_or_create(title: title
|
87
|
+
.update_or_create(title: title)
|
88
88
|
|
89
89
|
Domain::ScriptProject.new(
|
90
90
|
id: ctx.root,
|
@@ -148,11 +148,10 @@ module Script
|
|
148
148
|
current_script_json || raise(Domain::Errors::NoScriptJsonFile)
|
149
149
|
end
|
150
150
|
|
151
|
-
def update_or_create(title
|
151
|
+
def update_or_create(title:)
|
152
152
|
json = current_script_json&.content || {}
|
153
153
|
json["version"] ||= "1"
|
154
154
|
json["title"] = title
|
155
|
-
json["configurationUi"] = !!configuration_ui
|
156
155
|
|
157
156
|
ctx.write(SCRIPT_JSON_FILENAME, JSON.pretty_generate(json))
|
158
157
|
|
@@ -18,7 +18,8 @@ module Script
|
|
18
18
|
force: false,
|
19
19
|
metadata:,
|
20
20
|
script_json:,
|
21
|
-
module_upload_url
|
21
|
+
module_upload_url:,
|
22
|
+
library:
|
22
23
|
)
|
23
24
|
query_name = "app_script_set"
|
24
25
|
variables = {
|
@@ -33,6 +34,10 @@ module Script
|
|
33
34
|
configurationUi: script_json.configuration_ui,
|
34
35
|
configurationDefinition: script_json.configuration&.to_json,
|
35
36
|
moduleUploadUrl: module_upload_url,
|
37
|
+
library: {
|
38
|
+
language: library[:language],
|
39
|
+
version: library[:version],
|
40
|
+
},
|
36
41
|
}
|
37
42
|
resp_hash = make_request(query_name: query_name, variables: variables)
|
38
43
|
user_errors = resp_hash["data"]["appScriptSet"]["userErrors"]
|
@@ -41,7 +46,7 @@ module Script
|
|
41
46
|
|
42
47
|
if user_errors.any? { |e| e["tag"] == "already_exists_error" }
|
43
48
|
raise Errors::ScriptRepushError, uuid
|
44
|
-
elsif (e = user_errors.any? { |err| err["tag"] == "
|
49
|
+
elsif (e = user_errors.any? { |err| err["tag"] == "configuration_definition_syntax_error" })
|
45
50
|
raise Errors::ScriptJsonSyntaxError
|
46
51
|
elsif (e = user_errors.find { |err| err["tag"] == "configuration_definition_missing_keys_error" })
|
47
52
|
raise Errors::ScriptJsonMissingKeysError, e["message"]
|
@@ -27,10 +27,6 @@ module Script
|
|
27
27
|
"extension_point_type or script_name.",
|
28
28
|
invalid_context_help: "Add these values and try again.",
|
29
29
|
|
30
|
-
invalid_config_props_cause: "{{command:--config-props}} is formatted incorrectly.",
|
31
|
-
invalid_config_props_help: "Try again using this format: "\
|
32
|
-
"{{cyan:--config-props='name1:value1, name2:value2'}}",
|
33
|
-
|
34
30
|
invalid_script_name_cause: "Invalid script name.",
|
35
31
|
invalid_script_name_help: "Replace or remove unsupported characters. Valid characters "\
|
36
32
|
"are numbers, letters, hyphens, or underscores.",
|
@@ -42,9 +38,6 @@ module Script
|
|
42
38
|
no_existing_orgs_cause: "You don't have any partner organizations.",
|
43
39
|
no_existing_orgs_help: "Visit https://partners.shopify.com/ to create a partners account.",
|
44
40
|
|
45
|
-
no_existing_stores_cause: "You don't have any stores in your Partner Dashboard.",
|
46
|
-
no_existing_stores_help: "Visit https://partners.shopify.com/%{organization_id}/stores/ to create one.",
|
47
|
-
|
48
41
|
project_exists_cause: "A directory with this same name already exists.",
|
49
42
|
project_exists_help: "Try again and enter a different name for the script.",
|
50
43
|
|
@@ -54,9 +47,6 @@ module Script
|
|
54
47
|
invalid_language_cause: "Invalid language %s.",
|
55
48
|
invalid_language_help: "Allowed values: %s.",
|
56
49
|
|
57
|
-
invalid_config: "Can't change the configuration values because %1$s is missing or "\
|
58
|
-
"it isn't formatted properly.",
|
59
|
-
|
60
50
|
missing_script_json_field_cause: "The script.json file is missing the required %s field.",
|
61
51
|
missing_script_json_field_help: "Add the field and try again.",
|
62
52
|
|
@@ -91,8 +81,8 @@ module Script
|
|
91
81
|
system_call_failure_cause: "An error was returned while running {{command:%{cmd}}}.",
|
92
82
|
system_call_failure_help: "Review the following error and try again.\n{{red:%{out}}}",
|
93
83
|
|
94
|
-
metadata_validation_cause: "
|
95
|
-
metadata_validation_help: "
|
84
|
+
metadata_validation_cause: "The Script API metadata is incorrect.",
|
85
|
+
metadata_validation_help: "The 'schemaVersions.major' field contains an unsupported version.",
|
96
86
|
|
97
87
|
metadata_schema_versions_missing: "Invalid Script metadata:" \
|
98
88
|
" 'schemaVersions' field is missing",
|
@@ -107,7 +97,6 @@ module Script
|
|
107
97
|
metadata_not_found_help: "Ensure the 'shopify/scripts-toolchain-as' package is up to date and " \
|
108
98
|
"'package.json' contains a 'scripts/build' entry with a " \
|
109
99
|
"'--metadata build/metadata.json' argument",
|
110
|
-
app_not_installed_cause: "App not installed on store.",
|
111
100
|
|
112
101
|
build_error_cause: "Something went wrong while building the script.",
|
113
102
|
build_error_help: "Correct the errors and try again.",
|
@@ -126,9 +115,6 @@ module Script
|
|
126
115
|
script_repush_cause: "A version of this script already exists on the app.",
|
127
116
|
script_repush_help: "Use {{cyan:--force}} to replace the existing script.",
|
128
117
|
|
129
|
-
shop_auth_cause: "Unable to authenticate with the store.",
|
130
|
-
shop_auth_help: "Try again.",
|
131
|
-
|
132
118
|
invalid_build_script: "The root package.json contains an invalid build command that " \
|
133
119
|
"is needed to compile your script to WebAssembly.",
|
134
120
|
build_script_not_found: "The root package.json is missing the build command that " \
|
@@ -148,6 +134,12 @@ module Script
|
|
148
134
|
|
149
135
|
script_upload_cause: "Fail to upload script.",
|
150
136
|
script_upload_help: "Try again.",
|
137
|
+
|
138
|
+
api_library_not_found_cause: "Script can't be created because API library %{library_name} is missing from the dependencies",
|
139
|
+
api_library_not_found_help: "This error can occur because the API library was removed from your system or there is a problem with dependencies in the repository.",
|
140
|
+
|
141
|
+
language_library_for_api_not_found_cause: "Script can’t be pushed because the %{language} library for API %{api} is missing.",
|
142
|
+
language_library_for_api_not_found_help: "Make sure extension_point.yml contains the correct API library.",
|
151
143
|
},
|
152
144
|
|
153
145
|
create: {
|
@@ -156,8 +148,7 @@ module Script
|
|
156
148
|
Usage: {{command:%1$s script create}}
|
157
149
|
Options:
|
158
150
|
{{command:--name=NAME}} Script project name. Use any string.
|
159
|
-
{{command:--
|
160
|
-
{{command:--no-config-ui}} Specify this option when you don’t want your script to render an interface in Shopify admin.
|
151
|
+
{{command:--api=TYPE}} Script API name. Allowed values: %2$s.
|
161
152
|
HELP
|
162
153
|
|
163
154
|
error: {
|
@@ -206,10 +197,6 @@ module Script
|
|
206
197
|
built: "Built",
|
207
198
|
pushing: "Pushing",
|
208
199
|
pushed: "Pushed",
|
209
|
-
disabling: "Disabling",
|
210
|
-
disabled: "Disabled",
|
211
|
-
enabling: "Enabling",
|
212
|
-
enabled: "Enabled",
|
213
200
|
ensure_env: {
|
214
201
|
organization: "Partner organization {{green:%s (%s)}}.",
|
215
202
|
organization_select: "Which partner organization do you want to use?",
|
@@ -44,15 +44,6 @@ module Script
|
|
44
44
|
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_context_cause"),
|
45
45
|
help_suggestion: ShopifyCLI::Context.message("script.error.invalid_context_help"),
|
46
46
|
}
|
47
|
-
when Errors::InvalidConfigProps
|
48
|
-
{
|
49
|
-
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_config_props_cause"),
|
50
|
-
help_suggestion: ShopifyCLI::Context.message("script.error.invalid_config_props_help"),
|
51
|
-
}
|
52
|
-
when Errors::InvalidConfigYAMLError
|
53
|
-
{
|
54
|
-
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_config", e.config_file),
|
55
|
-
}
|
56
47
|
when Layers::Infrastructure::Errors::InvalidLanguageError
|
57
48
|
{
|
58
49
|
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_language_cause", e.language),
|
@@ -76,14 +67,6 @@ module Script
|
|
76
67
|
cause_of_error: ShopifyCLI::Context.message("script.error.no_existing_orgs_cause"),
|
77
68
|
help_suggestion: ShopifyCLI::Context.message("script.error.no_existing_orgs_help"),
|
78
69
|
}
|
79
|
-
when Errors::NoExistingStoresError
|
80
|
-
{
|
81
|
-
cause_of_error: ShopifyCLI::Context.message("script.error.no_existing_stores_cause"),
|
82
|
-
help_suggestion: ShopifyCLI::Context.message(
|
83
|
-
"script.error.no_existing_stores_help",
|
84
|
-
organization_id: e.organization_id
|
85
|
-
),
|
86
|
-
}
|
87
70
|
when Layers::Infrastructure::Errors::ScriptProjectAlreadyExistsError
|
88
71
|
{
|
89
72
|
cause_of_error: ShopifyCLI::Context.message("script.error.project_exists_cause"),
|
@@ -135,10 +118,6 @@ module Script
|
|
135
118
|
cause_of_error: ShopifyCLI::Context.message("script.error.no_script_json_file_cause"),
|
136
119
|
help_suggestion: ShopifyCLI::Context.message("script.error.no_script_json_file_help"),
|
137
120
|
}
|
138
|
-
when Layers::Infrastructure::Errors::AppNotInstalledError
|
139
|
-
{
|
140
|
-
cause_of_error: ShopifyCLI::Context.message("script.error.app_not_installed_cause"),
|
141
|
-
}
|
142
121
|
when Layers::Infrastructure::Errors::BuildError
|
143
122
|
{
|
144
123
|
cause_of_error: ShopifyCLI::Context.message("script.error.build_error_cause"),
|
@@ -217,11 +196,6 @@ module Script
|
|
217
196
|
cause_of_error: ShopifyCLI::Context.message("script.error.script_repush_cause"),
|
218
197
|
help_suggestion: ShopifyCLI::Context.message("script.error.script_repush_help"),
|
219
198
|
}
|
220
|
-
when Layers::Infrastructure::Errors::ShopAuthenticationError
|
221
|
-
{
|
222
|
-
cause_of_error: ShopifyCLI::Context.message("script.error.shop_auth_cause"),
|
223
|
-
help_suggestion: ShopifyCLI::Context.message("script.error.shop_auth_help"),
|
224
|
-
}
|
225
199
|
when Layers::Infrastructure::Errors::BuildScriptNotFoundError
|
226
200
|
{
|
227
201
|
cause_of_error: ShopifyCLI::Context.message("script.error.build_script_not_found"),
|
@@ -250,6 +224,22 @@ module Script
|
|
250
224
|
cause_of_error: ShopifyCLI::Context.message("script.error.script_upload_cause"),
|
251
225
|
help_suggestion: ShopifyCLI::Context.message("script.error.script_upload_help"),
|
252
226
|
}
|
227
|
+
when Layers::Infrastructure::Errors::APILibraryNotFoundError
|
228
|
+
{
|
229
|
+
cause_of_error: ShopifyCLI::Context
|
230
|
+
.message("script.error.api_library_not_found_cause", library_name: e.library_name),
|
231
|
+
help_suggestion: ShopifyCLI::Context.message("script.error.api_library_not_found_help"),
|
232
|
+
}
|
233
|
+
when Layers::Infrastructure::Errors::LanguageLibraryForAPINotFoundError
|
234
|
+
{
|
235
|
+
cause_of_error: ShopifyCLI::Context
|
236
|
+
.message(
|
237
|
+
"script.error.language_library_for_api_not_found_cause",
|
238
|
+
language: e.language,
|
239
|
+
api: e.api
|
240
|
+
),
|
241
|
+
help_suggestion: ShopifyCLI::Context.message("script.error.language_library_for_api_not_found_help"),
|
242
|
+
}
|
253
243
|
end
|
254
244
|
end
|
255
245
|
end
|
@@ -5,7 +5,9 @@ module Theme
|
|
5
5
|
class Command
|
6
6
|
class Serve < ShopifyCLI::SubCommand
|
7
7
|
options do |parser, flags|
|
8
|
+
parser.on("--bind=HOST") { |bind| flags[:bind] = bind.to_s }
|
8
9
|
parser.on("--port=PORT") { |port| flags[:port] = port.to_i }
|
10
|
+
parser.on("--poll") { flags[:poll] = true }
|
9
11
|
end
|
10
12
|
|
11
13
|
def call(*)
|
@@ -88,7 +88,13 @@ module Theme
|
|
88
88
|
serve: {
|
89
89
|
help: <<~HELP,
|
90
90
|
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.
|
91
|
+
|
91
92
|
Usage: {{command:%s theme serve}}
|
93
|
+
|
94
|
+
Options:
|
95
|
+
{{command:--port=PORT}} Local port to serve theme preview from
|
96
|
+
{{command:--poll}} Force polling to detect file changes
|
97
|
+
{{command:--bind=HOST}} Set which network interface the web server listens on
|
92
98
|
HELP
|
93
99
|
serve: "Viewing theme…",
|
94
100
|
open_fail: "Couldn't open the theme",
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
class AppTypeDetector
|
5
|
+
Error = Class.new(StandardError)
|
6
|
+
TypeNotFoundError = Class.new(Error)
|
7
|
+
|
8
|
+
def self.detect(project_directory:)
|
9
|
+
return :node if node?(project_directory: project_directory)
|
10
|
+
return :rails if rails?(project_directory: project_directory)
|
11
|
+
return :php if php?(project_directory: project_directory)
|
12
|
+
raise TypeNotFoundError, "Couldn't detect the project type in directory: #{project_directory}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.node?(project_directory:)
|
16
|
+
package_json_path = File.join(project_directory, "package.json")
|
17
|
+
return false unless File.exist?(package_json_path)
|
18
|
+
package_json = JSON.parse(File.read(package_json_path))
|
19
|
+
!package_json.dig("scripts", "dev").nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.rails?(project_directory:)
|
23
|
+
rails_binstub_path = File.join(project_directory, "bin/rails")
|
24
|
+
File.exist?(rails_binstub_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.php?(project_directory:)
|
28
|
+
bootstrap_app_path = File.join(project_directory, "bootstrap/app.php")
|
29
|
+
File.exist?(bootstrap_app_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/shopify_cli/command.rb
CHANGED
@@ -27,7 +27,12 @@ module ShopifyCLI
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def options(&block)
|
30
|
-
|
30
|
+
existing_options = @_options
|
31
|
+
# We prevent new options calls to override existing blocks by nesting them.
|
32
|
+
@_options = ->(parser, flags) {
|
33
|
+
existing_options&.call(parser, flags)
|
34
|
+
block.call(parser, flags)
|
35
|
+
}
|
31
36
|
end
|
32
37
|
|
33
38
|
def subcommand(const, cmd, path = nil)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "shopify_cli"
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
module CommandOptions
|
5
|
+
module CommandServeOptions
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
base.class_eval do
|
9
|
+
def port
|
10
|
+
return ShopifyCLI::Tunnel::PORT.to_s unless options.flags.key?(:port)
|
11
|
+
port = options.flags[:port].to_i
|
12
|
+
@ctx.abort(@ctx.message("core.app.serve.error.invalid_port", options.flags[:port])) unless port > 0
|
13
|
+
port
|
14
|
+
end
|
15
|
+
|
16
|
+
def host
|
17
|
+
host = options.flags[:host]
|
18
|
+
unless host.nil?
|
19
|
+
@ctx.abort(@ctx.message("core.app.serve.error.host_must_be_https")) if host.match(/^https/i).nil?
|
20
|
+
end
|
21
|
+
host
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def parse_host_option
|
28
|
+
options do |parser, flags|
|
29
|
+
parser.on("--host=HOST") do |h|
|
30
|
+
flags[:host] = h.gsub('"', "")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_port_option
|
36
|
+
options do |parser, flags|
|
37
|
+
parser.on("--port=PORT") { |port| flags[:port] = port }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -15,7 +15,7 @@ module ShopifyCLI
|
|
15
15
|
|
16
16
|
def call(*)
|
17
17
|
shop = (options.flags[:shop] || @ctx.getenv("SHOPIFY_SHOP" || nil))
|
18
|
-
ShopifyCLI::DB.set(shop: self.class.validate_shop(shop)) unless shop.nil?
|
18
|
+
ShopifyCLI::DB.set(shop: self.class.validate_shop(shop, context: @ctx)) unless shop.nil?
|
19
19
|
|
20
20
|
if shop.nil? && Shopifolk.check
|
21
21
|
Shopifolk.reset
|
@@ -41,9 +41,9 @@ module ShopifyCLI
|
|
41
41
|
ShopifyCLI::Context.message("core.login.help", ShopifyCLI::TOOL_NAME)
|
42
42
|
end
|
43
43
|
|
44
|
-
def self.validate_shop(shop)
|
44
|
+
def self.validate_shop(shop, context:)
|
45
45
|
permanent_domain = shop_to_permanent_domain(shop)
|
46
|
-
|
46
|
+
context.abort(context.message("core.login.invalid_shop", shop)) unless permanent_domain
|
47
47
|
permanent_domain
|
48
48
|
end
|
49
49
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "shopify_cli"
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
module Commands
|
5
|
+
class Reporting < ShopifyCLI::Command
|
6
|
+
def call(args, _name)
|
7
|
+
enable_reporting = reporting_enabled?(args)
|
8
|
+
Services::ReportingService.call(enable: enable_reporting)
|
9
|
+
|
10
|
+
message = if enable_reporting
|
11
|
+
@ctx.message("core.reporting.turned_on_message")
|
12
|
+
else
|
13
|
+
@ctx.message("core.reporting.turned_off_message", ShopifyCLI::TOOL_NAME)
|
14
|
+
end
|
15
|
+
@ctx.puts(message)
|
16
|
+
end
|
17
|
+
|
18
|
+
def reporting_enabled?(args)
|
19
|
+
case args.first
|
20
|
+
when nil
|
21
|
+
@ctx.abort(@ctx.message("core.reporting.missing_argument", ShopifyCLI::TOOL_NAME))
|
22
|
+
when "on"
|
23
|
+
true
|
24
|
+
when "off"
|
25
|
+
false
|
26
|
+
else
|
27
|
+
@ctx.abort(
|
28
|
+
@ctx.message("core.reporting.invalid_argument", ShopifyCLI::TOOL_NAME, args.first)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.help
|
34
|
+
ShopifyCLI::Context.message("core.reporting.help", ShopifyCLI::TOOL_NAME)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -16,7 +16,7 @@ module ShopifyCLI
|
|
16
16
|
end
|
17
17
|
|
18
18
|
shop = if options.flags[:shop]
|
19
|
-
Login.validate_shop(options.flags[:shop])
|
19
|
+
Login.validate_shop(options.flags[:shop], context: @ctx)
|
20
20
|
elsif (org_id = DB.get(:organization_id))
|
21
21
|
res = ShopifyCLI::Tasks::SelectOrgAndShop.call(@ctx, organization_id: org_id)
|
22
22
|
res[:shop_domain]
|
data/lib/shopify_cli/commands.rb
CHANGED
@@ -23,6 +23,7 @@ module ShopifyCLI
|
|
23
23
|
register :Login, "login", "shopify_cli/commands/login", true
|
24
24
|
register :Logout, "logout", "shopify_cli/commands/logout", true
|
25
25
|
register :Populate, "populate", "shopify_cli/commands/populate", true
|
26
|
+
register :Reporting, "reporting", "shopify_cli/commands/reporting", true
|
26
27
|
register :Store, "store", "shopify_cli/commands/store", true
|
27
28
|
register :Switch, "switch", "shopify_cli/commands/switch", true
|
28
29
|
register :System, "system", "shopify_cli/commands/system", true
|
@@ -15,10 +15,10 @@ module ShopifyCLI
|
|
15
15
|
|
16
16
|
module Config
|
17
17
|
module Sections
|
18
|
-
module
|
19
|
-
NAME = "
|
18
|
+
module Analytics
|
19
|
+
NAME = "analytics"
|
20
20
|
module Fields
|
21
|
-
|
21
|
+
ENABLED = "enabled"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -39,7 +39,11 @@ module ShopifyCLI
|
|
39
39
|
|
40
40
|
# Environments
|
41
41
|
TEST = "SHOPIFY_CLI_TEST"
|
42
|
+
ACCEPTANCE_TEST = "SHOPIFY_CLI_ACCEPTANCE_TEST"
|
42
43
|
DEVELOPMENT = "SHOPIFY_CLI_DEVELOPMENT"
|
44
|
+
|
45
|
+
# Monorail
|
46
|
+
MONORAIL_REAL_EVENTS = "MONORAIL_REAL_EVENTS"
|
43
47
|
end
|
44
48
|
|
45
49
|
module Identity
|