shopify-cli 1.7.1 → 1.11.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/PULL_REQUEST_TEMPLATE.md +1 -0
- data/.github/workflows/build.yml +28 -0
- data/.rubocop_todo.yml +15 -2
- data/CHANGELOG.md +25 -0
- data/Gemfile.lock +15 -15
- data/README.md +2 -1
- data/dev.yml +3 -0
- data/lib/docgen/markdown.rb +1 -1
- data/lib/graphql/extension_create.graphql +17 -2
- data/lib/graphql/fetch_specifications.graphql +14 -0
- data/lib/project_types/extension/cli.rb +8 -10
- data/lib/project_types/extension/commands/create.rb +2 -2
- data/lib/project_types/extension/commands/extension_command.rb +10 -6
- data/lib/project_types/extension/commands/push.rb +2 -2
- data/lib/project_types/extension/commands/register.rb +6 -5
- data/lib/project_types/extension/commands/serve.rb +64 -22
- data/lib/project_types/extension/commands/tunnel.rb +3 -1
- data/lib/project_types/extension/extension_project.rb +20 -4
- data/lib/project_types/extension/extension_project_keys.rb +2 -1
- data/lib/project_types/extension/features/argo.rb +19 -44
- data/lib/project_types/extension/features/argo_runtime.rb +63 -0
- data/lib/project_types/extension/features/argo_serve.rb +79 -0
- data/lib/project_types/extension/features/argo_serve_options.rb +40 -0
- data/lib/project_types/extension/features/argo_setup.rb +1 -1
- data/lib/project_types/extension/forms/questions/ask_type.rb +16 -5
- data/lib/project_types/extension/messages/message_loading.rb +3 -1
- data/lib/project_types/extension/messages/messages.rb +9 -6
- data/lib/project_types/extension/models/npm_package.rb +14 -0
- data/lib/project_types/extension/models/registration.rb +1 -0
- data/lib/project_types/extension/models/specification.rb +7 -2
- data/lib/project_types/extension/models/specification_handlers/checkout_argo_extension.rb +18 -0
- data/lib/project_types/extension/models/specification_handlers/default.rb +35 -2
- data/lib/project_types/extension/models/specifications.rb +12 -1
- data/lib/project_types/extension/models/version.rb +1 -1
- data/lib/project_types/extension/tasks/choose_next_available_port.rb +36 -0
- data/lib/project_types/extension/tasks/configure_features.rb +5 -1
- data/lib/project_types/extension/tasks/converters/registration_converter.rb +2 -0
- data/lib/project_types/extension/tasks/fetch_specifications.rb +8 -28
- data/lib/project_types/extension/tasks/find_npm_packages.rb +106 -0
- data/lib/project_types/node/commands/generate.rb +0 -22
- data/lib/project_types/node/forms/create.rb +10 -1
- data/lib/project_types/node/messages/messages.rb +5 -4
- data/lib/project_types/rails/forms/create.rb +11 -1
- data/lib/project_types/rails/messages/messages.rb +5 -4
- data/lib/project_types/script/cli.rb +7 -8
- data/lib/project_types/script/commands/create.rb +0 -7
- data/lib/project_types/script/commands/push.rb +3 -3
- data/lib/project_types/script/config/extension_points.yml +17 -0
- data/lib/project_types/script/errors.rb +0 -19
- data/lib/project_types/script/forms/create.rb +3 -14
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +5 -5
- data/lib/project_types/script/graphql/get_app_scripts.graphql +6 -0
- data/lib/project_types/script/graphql/script_service_proxy.graphql +1 -2
- data/lib/project_types/script/layers/application/build_script.rb +1 -2
- data/lib/project_types/script/layers/application/create_script.rb +32 -49
- data/lib/project_types/script/layers/application/extension_points.rb +3 -2
- data/lib/project_types/script/layers/application/push_script.rb +5 -5
- data/lib/project_types/script/layers/domain/errors.rb +0 -2
- data/lib/project_types/script/layers/domain/extension_point.rb +60 -45
- data/lib/project_types/script/layers/domain/metadata.rb +18 -25
- data/lib/project_types/script/layers/domain/push_package.rb +4 -4
- data/lib/project_types/script/layers/domain/script_project.rb +54 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +39 -14
- data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +14 -43
- data/lib/project_types/script/layers/infrastructure/command_runner.rb +19 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +40 -20
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +12 -13
- data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +9 -10
- data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +6 -7
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +172 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +25 -76
- data/lib/project_types/script/messages/messages.rb +20 -53
- data/lib/project_types/script/tasks/ensure_env.rb +85 -0
- data/lib/project_types/script/ui/error_handler.rb +32 -41
- data/lib/shopify-cli/context.rb +28 -0
- data/lib/shopify-cli/js_system.rb +2 -2
- data/lib/shopify-cli/messages/messages.rb +50 -45
- data/lib/shopify-cli/method_object.rb +4 -4
- data/lib/shopify-cli/oauth.rb +9 -3
- data/lib/shopify-cli/packager.rb +1 -1
- data/lib/shopify-cli/partners_api/organizations.rb +3 -3
- data/lib/shopify-cli/resolve_constant.rb +1 -1
- data/lib/shopify-cli/resources/env_file.rb +1 -1
- data/lib/shopify-cli/tasks/ensure_dev_store.rb +1 -1
- data/lib/shopify-cli/tasks/select_org_and_shop.rb +6 -4
- data/lib/shopify-cli/transform_data_structure.rb +2 -2
- data/lib/shopify-cli/tunnel.rb +22 -1
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +0 -1
- data/vendor/deps/smart_properties/REVISION +1 -1
- data/vendor/deps/smart_properties/lib/smart_properties/property.rb +7 -1
- data/vendor/deps/smart_properties/lib/smart_properties/version.rb +1 -1
- metadata +17 -12
- data/.travis.yml +0 -14
- data/lib/project_types/script/commands/disable.rb +0 -25
- data/lib/project_types/script/commands/enable.rb +0 -80
- data/lib/project_types/script/graphql/shop_script_delete.graphql +0 -14
- data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +0 -28
- data/lib/project_types/script/layers/application/disable_script.rb +0 -21
- data/lib/project_types/script/layers/application/enable_script.rb +0 -23
- data/lib/project_types/script/layers/infrastructure/config_ui_repository.rb +0 -46
- data/lib/project_types/script/script_project.rb +0 -64
|
@@ -33,9 +33,7 @@ module Script
|
|
|
33
33
|
|
|
34
34
|
def dependencies_installed?
|
|
35
35
|
# Assuming if node_modules folder exist at root of script folder, all deps are installed
|
|
36
|
-
|
|
37
|
-
check_if_ep_dependencies_up_to_date!
|
|
38
|
-
true
|
|
36
|
+
ctx.dir_exist?("node_modules")
|
|
39
37
|
end
|
|
40
38
|
|
|
41
39
|
def metadata
|
|
@@ -65,9 +63,7 @@ module Script
|
|
|
65
63
|
|
|
66
64
|
def compile
|
|
67
65
|
check_compilation_dependencies!
|
|
68
|
-
|
|
69
|
-
out, status = ctx.capture2e(SCRIPT_SDK_BUILD)
|
|
70
|
-
raise Domain::Errors::ServiceFailureError, out unless status.success?
|
|
66
|
+
CommandRunner.new(ctx: ctx).call(SCRIPT_SDK_BUILD)
|
|
71
67
|
end
|
|
72
68
|
|
|
73
69
|
def check_compilation_dependencies!
|
|
@@ -83,47 +79,22 @@ module Script
|
|
|
83
79
|
end
|
|
84
80
|
|
|
85
81
|
def bytecode
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
legacy_filename = format(BYTECODE_FILE, name: script_name)
|
|
83
|
+
filename = format(BYTECODE_FILE, name: "script")
|
|
84
|
+
|
|
85
|
+
bytecode_file = if ctx.file_exist?(filename)
|
|
86
|
+
filename
|
|
87
|
+
elsif ctx.file_exist?(legacy_filename)
|
|
88
|
+
legacy_filename
|
|
89
|
+
else
|
|
90
|
+
raise Errors::WebAssemblyBinaryNotFoundError
|
|
91
|
+
end
|
|
88
92
|
|
|
89
|
-
contents =
|
|
90
|
-
|
|
93
|
+
contents = ctx.binread(bytecode_file)
|
|
94
|
+
ctx.rm(bytecode_file)
|
|
91
95
|
|
|
92
96
|
contents
|
|
93
97
|
end
|
|
94
|
-
|
|
95
|
-
def check_if_ep_dependencies_up_to_date!
|
|
96
|
-
return true if ENV["SHOPIFY_CLI_SCRIPTS_IGNORE_OUTDATED"]
|
|
97
|
-
|
|
98
|
-
# ignore exit code since it will not be 0 unless every package is up to date which they probably won't be
|
|
99
|
-
out, _ = ctx.capture2e("npm", "outdated", "--json", "--depth", "0")
|
|
100
|
-
parsed_outdated_check = JSON.parse(out)
|
|
101
|
-
outdated_ep_packages = parsed_outdated_check
|
|
102
|
-
.select { |package_name, _| package_name.start_with?("@shopify/extension-point-as-") }
|
|
103
|
-
.select { |_, version_info| !package_is_up_to_date?(version_info) }
|
|
104
|
-
.keys
|
|
105
|
-
raise Errors::PackagesOutdatedError.new(outdated_ep_packages),
|
|
106
|
-
"NPM packages out of date: #{outdated_ep_packages.join(", ")}" unless outdated_ep_packages.empty?
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def package_is_up_to_date?(version_info)
|
|
110
|
-
require "semantic/semantic"
|
|
111
|
-
current_version = version_info["current"]
|
|
112
|
-
latest_version = version_info["latest"]
|
|
113
|
-
|
|
114
|
-
# making an assumption that the script developer knows what they're doing if they're not referencing a
|
|
115
|
-
# semver version
|
|
116
|
-
begin
|
|
117
|
-
current_version = ::Semantic::Version.new(current_version)
|
|
118
|
-
latest_version = ::Semantic::Version.new(latest_version)
|
|
119
|
-
rescue ArgumentError
|
|
120
|
-
return true
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
return false if current_version.major < latest_version.major
|
|
124
|
-
return false if latest_version.major == 0 && current_version.minor < latest_version.minor
|
|
125
|
-
true
|
|
126
|
-
end
|
|
127
98
|
end
|
|
128
99
|
end
|
|
129
100
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Script
|
|
4
|
+
module Layers
|
|
5
|
+
module Infrastructure
|
|
6
|
+
class CommandRunner
|
|
7
|
+
include SmartProperties
|
|
8
|
+
|
|
9
|
+
property! :ctx, accepts: ShopifyCli::Context
|
|
10
|
+
|
|
11
|
+
def call(cmd)
|
|
12
|
+
out, status = ctx.capture2e(cmd)
|
|
13
|
+
raise Errors::SystemCallFailureError.new(out: out.chomp, cmd: cmd) unless status.success?
|
|
14
|
+
out
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -5,8 +5,6 @@ module Script
|
|
|
5
5
|
module Infrastructure
|
|
6
6
|
module Errors
|
|
7
7
|
class AppNotInstalledError < ScriptProjectError; end
|
|
8
|
-
class AppScriptNotPushedError < ScriptProjectError; end
|
|
9
|
-
class AppScriptUndefinedError < ScriptProjectError; end
|
|
10
8
|
class BuildError < ScriptProjectError; end
|
|
11
9
|
class ConfigUiSyntaxError < ScriptProjectError; end
|
|
12
10
|
|
|
@@ -19,6 +17,15 @@ module Script
|
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
19
|
|
|
20
|
+
class ConfigUiInvalidInputModeError < ScriptProjectError
|
|
21
|
+
attr_reader :filename, :valid_input_modes
|
|
22
|
+
def initialize(filename, valid_input_modes)
|
|
23
|
+
super()
|
|
24
|
+
@filename = filename
|
|
25
|
+
@valid_input_modes = valid_input_modes
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
22
29
|
class ConfigUiFieldsMissingKeysError < ScriptProjectError
|
|
23
30
|
attr_reader :filename, :missing_keys
|
|
24
31
|
def initialize(filename, missing_keys)
|
|
@@ -28,9 +35,29 @@ module Script
|
|
|
28
35
|
end
|
|
29
36
|
end
|
|
30
37
|
|
|
38
|
+
class ConfigUiFieldsInvalidTypeError < ScriptProjectError
|
|
39
|
+
attr_reader :filename, :valid_types
|
|
40
|
+
def initialize(filename, valid_types)
|
|
41
|
+
super()
|
|
42
|
+
@filename = filename
|
|
43
|
+
@valid_types = valid_types
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
31
47
|
class DependencyInstallError < ScriptProjectError; end
|
|
48
|
+
class DeprecatedEPError < ScriptProjectError; end
|
|
32
49
|
class EmptyResponseError < ScriptProjectError; end
|
|
33
50
|
class ForbiddenError < ScriptProjectError; end
|
|
51
|
+
class InvalidContextError < ScriptProjectError; end
|
|
52
|
+
|
|
53
|
+
class InvalidLanguageError < ScriptProjectError
|
|
54
|
+
attr_reader :language, :extension_point_type
|
|
55
|
+
def initialize(language, extension_point_type)
|
|
56
|
+
super()
|
|
57
|
+
@language = language
|
|
58
|
+
@extension_point_type = extension_point_type
|
|
59
|
+
end
|
|
60
|
+
end
|
|
34
61
|
|
|
35
62
|
class GraphqlError < ScriptProjectError
|
|
36
63
|
attr_reader :errors
|
|
@@ -42,33 +69,26 @@ module Script
|
|
|
42
69
|
|
|
43
70
|
class ProjectCreatorNotFoundError < ScriptProjectError; end
|
|
44
71
|
|
|
45
|
-
class
|
|
46
|
-
attr_reader :
|
|
47
|
-
def initialize(
|
|
72
|
+
class SystemCallFailureError < ScriptProjectError
|
|
73
|
+
attr_reader :out, :cmd
|
|
74
|
+
def initialize(out:, cmd:)
|
|
48
75
|
super()
|
|
49
|
-
@
|
|
76
|
+
@out = out
|
|
77
|
+
@cmd = cmd
|
|
50
78
|
end
|
|
51
79
|
end
|
|
52
80
|
|
|
53
|
-
class
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
class ScriptRepushError < ScriptProjectError
|
|
82
|
+
attr_reader :uuid
|
|
83
|
+
def initialize(uuid)
|
|
84
|
+
super()
|
|
85
|
+
@uuid = uuid
|
|
56
86
|
end
|
|
57
87
|
end
|
|
58
88
|
|
|
89
|
+
class ScriptProjectAlreadyExistsError < ScriptProjectError; end
|
|
59
90
|
class ShopAuthenticationError < ScriptProjectError; end
|
|
60
|
-
class ShopScriptConflictError < ScriptProjectError; end
|
|
61
|
-
class ShopScriptUndefinedError < ScriptProjectError; end
|
|
62
91
|
class TaskRunnerNotFoundError < ScriptProjectError; end
|
|
63
|
-
|
|
64
|
-
class PackagesOutdatedError < ScriptProjectError
|
|
65
|
-
attr_reader :outdated_packages
|
|
66
|
-
def initialize(outdated_packages)
|
|
67
|
-
super("EP packages are outdated and need to be updated: #{outdated_packages.join(", ")}")
|
|
68
|
-
@outdated_packages = outdated_packages
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
92
|
class BuildScriptNotFoundError < ScriptProjectError; end
|
|
73
93
|
class InvalidBuildScriptError < ScriptProjectError; end
|
|
74
94
|
|
|
@@ -7,37 +7,36 @@ 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
|
|
11
|
-
build_file_path = file_path(script_project.
|
|
10
|
+
def create_push_package(script_project:, script_content:, compiled_type:, metadata:)
|
|
11
|
+
build_file_path = file_path(script_project.id, compiled_type)
|
|
12
12
|
write_to_path(build_file_path, script_content)
|
|
13
13
|
|
|
14
14
|
Domain::PushPackage.new(
|
|
15
15
|
id: build_file_path,
|
|
16
|
+
uuid: script_project.uuid,
|
|
16
17
|
extension_point_type: script_project.extension_point_type,
|
|
17
18
|
script_name: script_project.script_name,
|
|
18
|
-
description: script_project.description,
|
|
19
19
|
script_content: script_content,
|
|
20
20
|
compiled_type: compiled_type,
|
|
21
21
|
metadata: metadata,
|
|
22
|
-
config_ui: config_ui,
|
|
22
|
+
config_ui: script_project.config_ui,
|
|
23
23
|
)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def get_push_package(script_project:, compiled_type:, metadata
|
|
27
|
-
build_file_path = file_path(script_project.
|
|
26
|
+
def get_push_package(script_project:, compiled_type:, metadata:)
|
|
27
|
+
build_file_path = file_path(script_project.id, compiled_type)
|
|
28
28
|
raise Domain::PushPackageNotFoundError unless ctx.file_exist?(build_file_path)
|
|
29
29
|
|
|
30
|
-
script_content =
|
|
31
|
-
|
|
30
|
+
script_content = ctx.binread(build_file_path)
|
|
32
31
|
Domain::PushPackage.new(
|
|
33
32
|
id: build_file_path,
|
|
33
|
+
uuid: script_project.uuid,
|
|
34
34
|
extension_point_type: script_project.extension_point_type,
|
|
35
35
|
script_name: script_project.script_name,
|
|
36
|
-
description: script_project.description,
|
|
37
36
|
script_content: script_content,
|
|
38
37
|
compiled_type: compiled_type,
|
|
39
38
|
metadata: metadata,
|
|
40
|
-
config_ui: config_ui,
|
|
39
|
+
config_ui: script_project.config_ui,
|
|
41
40
|
)
|
|
42
41
|
end
|
|
43
42
|
|
|
@@ -45,11 +44,11 @@ module Script
|
|
|
45
44
|
|
|
46
45
|
def write_to_path(path, content)
|
|
47
46
|
ctx.mkdir_p(File.dirname(path))
|
|
48
|
-
ctx.
|
|
47
|
+
ctx.binwrite(path, content)
|
|
49
48
|
end
|
|
50
49
|
|
|
51
|
-
def file_path(
|
|
52
|
-
"#{
|
|
50
|
+
def file_path(path_to_script, compiled_type)
|
|
51
|
+
"#{path_to_script}/build/script.#{compiled_type}"
|
|
53
52
|
end
|
|
54
53
|
end
|
|
55
54
|
end
|
|
@@ -27,28 +27,27 @@ module Script
|
|
|
27
27
|
|
|
28
28
|
private
|
|
29
29
|
|
|
30
|
+
def command_runner
|
|
31
|
+
@command_runner ||= CommandRunner.new(ctx: ctx)
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
def git_init
|
|
31
|
-
|
|
32
|
-
raise Domain::Errors::ServiceFailureError, out unless status.success?
|
|
35
|
+
command_runner.call("git init")
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def setup_remote
|
|
36
39
|
repo = extension_point.sdks.rust.package
|
|
37
|
-
|
|
38
|
-
raise Domain::Errors::ServiceFailureError, out unless status.success?
|
|
40
|
+
command_runner.call("git remote add -f origin #{repo}")
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def setup_sparse_checkout
|
|
42
44
|
type = extension_point.type
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
out, status = ctx.capture2e("echo #{type}/#{SAMPLE_PATH} >> .git/info/sparse-checkout")
|
|
46
|
-
raise Domain::Errors::ServiceFailureError, out unless status.success?
|
|
45
|
+
command_runner.call("git config core.sparsecheckout true")
|
|
46
|
+
command_runner.call("echo #{type}/#{SAMPLE_PATH} >> .git/info/sparse-checkout")
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def pull
|
|
50
|
-
|
|
51
|
-
raise Domain::Errors::ServiceFailureError, out unless status.success?
|
|
50
|
+
command_runner.call("git pull origin #{ORIGIN_BRANCH}")
|
|
52
51
|
end
|
|
53
52
|
|
|
54
53
|
def clean
|
|
@@ -3,14 +3,14 @@ module Script
|
|
|
3
3
|
module Layers
|
|
4
4
|
module Infrastructure
|
|
5
5
|
class RustTaskRunner
|
|
6
|
-
attr_reader :ctx
|
|
6
|
+
attr_reader :ctx
|
|
7
7
|
|
|
8
8
|
BUILD_TARGET = "wasm32-unknown-unknown"
|
|
9
9
|
METADATA_FILE = "build/metadata.json"
|
|
10
|
+
CARGO_BUILD_CMD = "cargo build --target=#{BUILD_TARGET} --release"
|
|
10
11
|
|
|
11
|
-
def initialize(ctx,
|
|
12
|
+
def initialize(ctx, _)
|
|
12
13
|
@ctx = ctx
|
|
13
|
-
@script_name = script_name
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def dependencies_installed?
|
|
@@ -42,16 +42,15 @@ module Script
|
|
|
42
42
|
private
|
|
43
43
|
|
|
44
44
|
def compile
|
|
45
|
-
|
|
46
|
-
raise Domain::Errors::ServiceFailureError, out unless status.success?
|
|
45
|
+
CommandRunner.new(ctx: ctx).call(CARGO_BUILD_CMD)
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
def bytecode
|
|
50
|
-
binary_name = "
|
|
49
|
+
binary_name = "script.wasm"
|
|
51
50
|
binary_path = "target/#{BUILD_TARGET}/release/#{binary_name}"
|
|
52
51
|
raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(binary_path)
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
ctx.binread(binary_path)
|
|
55
54
|
end
|
|
56
55
|
end
|
|
57
56
|
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Script
|
|
4
|
+
module Layers
|
|
5
|
+
module Infrastructure
|
|
6
|
+
class ScriptProjectRepository
|
|
7
|
+
include SmartProperties
|
|
8
|
+
property! :ctx, accepts: ShopifyCli::Context
|
|
9
|
+
|
|
10
|
+
DEFAULT_CONFIG_UI_FILENAME = "config-ui.yml"
|
|
11
|
+
MUTABLE_ENV_VALUES = %i(uuid)
|
|
12
|
+
|
|
13
|
+
def create(script_name:, extension_point_type:, language:, no_config_ui:)
|
|
14
|
+
validate_metadata!(extension_point_type, language)
|
|
15
|
+
|
|
16
|
+
config_ui_file = nil
|
|
17
|
+
optional_identifiers = {}
|
|
18
|
+
optional_identifiers.merge!(config_ui_file: DEFAULT_CONFIG_UI_FILENAME) unless no_config_ui
|
|
19
|
+
|
|
20
|
+
ShopifyCli::Project.write(
|
|
21
|
+
ctx,
|
|
22
|
+
project_type: :script,
|
|
23
|
+
organization_id: nil,
|
|
24
|
+
extension_point_type: extension_point_type,
|
|
25
|
+
script_name: script_name,
|
|
26
|
+
language: language,
|
|
27
|
+
**optional_identifiers
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
Domain::ScriptProject.new(
|
|
31
|
+
id: ctx.root,
|
|
32
|
+
env: project.env,
|
|
33
|
+
script_name: script_name,
|
|
34
|
+
extension_point_type: extension_point_type,
|
|
35
|
+
language: language,
|
|
36
|
+
config_ui: config_ui_file
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get
|
|
41
|
+
validate_metadata!(extension_point_type, language)
|
|
42
|
+
|
|
43
|
+
config_ui = ConfigUiRepository.new(ctx: ctx).get(config_ui_file)
|
|
44
|
+
|
|
45
|
+
Domain::ScriptProject.new(
|
|
46
|
+
id: project.directory,
|
|
47
|
+
env: project.env,
|
|
48
|
+
script_name: script_name,
|
|
49
|
+
extension_point_type: extension_point_type,
|
|
50
|
+
language: language,
|
|
51
|
+
config_ui: config_ui
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def update_env(**args)
|
|
56
|
+
capture_io do
|
|
57
|
+
args.slice(*MUTABLE_ENV_VALUES).each do |key, value|
|
|
58
|
+
project.env.extra[key.to_s.upcase] = value
|
|
59
|
+
project.env.update(ctx, :extra, project.env.extra)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Domain::ScriptProject.new(
|
|
64
|
+
id: ctx.root,
|
|
65
|
+
env: project.env,
|
|
66
|
+
script_name: script_name,
|
|
67
|
+
extension_point_type: extension_point_type,
|
|
68
|
+
language: language,
|
|
69
|
+
config_ui: ConfigUiRepository.new(ctx: ctx).get(config_ui_file),
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def create_env(api_key:, secret:, uuid:)
|
|
74
|
+
ShopifyCli::Resources::EnvFile.new(
|
|
75
|
+
api_key: api_key,
|
|
76
|
+
secret: secret,
|
|
77
|
+
extra: {
|
|
78
|
+
Domain::ScriptProject::UUID_ENV_KEY => uuid,
|
|
79
|
+
}
|
|
80
|
+
).write(ctx)
|
|
81
|
+
|
|
82
|
+
Domain::ScriptProject.new(
|
|
83
|
+
id: ctx.root,
|
|
84
|
+
env: project.env,
|
|
85
|
+
script_name: script_name,
|
|
86
|
+
extension_point_type: extension_point_type,
|
|
87
|
+
language: language,
|
|
88
|
+
config_ui: ConfigUiRepository.new(ctx: ctx).get(config_ui_file),
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def capture_io(&block)
|
|
95
|
+
CLI::UI::StdoutRouter::Capture.new(&block).run
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def extension_point_type
|
|
99
|
+
project_config_value!("extension_point_type")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def script_name
|
|
103
|
+
project_config_value!("script_name")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def config_ui_file
|
|
107
|
+
project_config_value("config_ui_file")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def language
|
|
111
|
+
project_config_value("language")&.downcase || default_language
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def project_config_value(key)
|
|
115
|
+
return nil unless project.config.key?(key)
|
|
116
|
+
project.config[key]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def project_config_value!(key)
|
|
120
|
+
raise Errors::InvalidContextError, key unless project.config.key?(key)
|
|
121
|
+
project.config[key]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def project
|
|
125
|
+
@project ||= ShopifyCli::Project.current(force_reload: true)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def default_language
|
|
129
|
+
Domain::ExtensionPoint::ExtensionPointAssemblyScriptSDK.language
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def validate_metadata!(extension_point_type, language)
|
|
133
|
+
if Application::ExtensionPoints.deprecated_types.include?(extension_point_type)
|
|
134
|
+
raise Errors::DeprecatedEPError, extension_point_type
|
|
135
|
+
elsif !Application::ExtensionPoints.supported_language?(type: extension_point_type, language: language)
|
|
136
|
+
raise Errors::InvalidLanguageError.new(language, extension_point_type)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
class ConfigUiRepository
|
|
141
|
+
include SmartProperties
|
|
142
|
+
property! :ctx, accepts: ShopifyCli::Context
|
|
143
|
+
|
|
144
|
+
def get(filename)
|
|
145
|
+
return nil unless filename
|
|
146
|
+
|
|
147
|
+
path = File.join(ctx.root, filename)
|
|
148
|
+
raise Domain::Errors::MissingSpecifiedConfigUiDefinitionError, filename unless File.exist?(path)
|
|
149
|
+
|
|
150
|
+
content = File.read(path)
|
|
151
|
+
raise Domain::Errors::InvalidConfigUiDefinitionError, filename unless valid_config_ui?(content)
|
|
152
|
+
|
|
153
|
+
Domain::ConfigUi.new(
|
|
154
|
+
filename: filename,
|
|
155
|
+
content: content,
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
def valid_config_ui?(raw_yaml)
|
|
162
|
+
require "yaml" # takes 20ms, so deferred as late as possible.
|
|
163
|
+
YAML.safe_load(raw_yaml)
|
|
164
|
+
true
|
|
165
|
+
rescue Psych::SyntaxError
|
|
166
|
+
false
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|