shopify-cli 2.4.0 → 2.6.2
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/workflows/shopify.yml +0 -2
- data/.gitignore +1 -0
- data/.rubocop.yml +14 -14
- data/.rubocop_todo.yml +3 -3
- data/CHANGELOG.md +25 -0
- data/Dockerfile +1 -3
- data/Gemfile.lock +22 -16
- data/README.md +1 -1
- data/RELEASING.md +1 -1
- data/Rakefile +25 -34
- data/bin/console +11 -0
- data/bin/shopify +17 -4
- data/dev.yml +3 -0
- data/ext/shopify-cli/extconf.rb +1 -0
- data/lib/project_types/extension/cli.rb +5 -3
- data/lib/project_types/extension/commands/build.rb +4 -3
- data/lib/project_types/extension/commands/check.rb +2 -2
- data/lib/project_types/extension/commands/connect.rb +1 -1
- data/lib/project_types/extension/commands/create.rb +41 -23
- data/lib/project_types/extension/commands/extension_command.rb +1 -1
- data/lib/project_types/extension/commands/info.rb +1 -1
- data/lib/project_types/extension/commands/push.rb +1 -1
- data/lib/project_types/extension/commands/register.rb +2 -2
- data/lib/project_types/extension/commands/serve.rb +5 -5
- data/lib/project_types/extension/commands/tunnel.rb +6 -6
- data/lib/project_types/extension/extension_project.rb +4 -4
- data/lib/project_types/extension/features/argo.rb +3 -3
- data/lib/project_types/extension/features/argo_config.rb +5 -5
- data/lib/project_types/extension/features/argo_serve.rb +21 -6
- data/lib/project_types/extension/features/argo_setup.rb +1 -1
- data/lib/project_types/extension/features/argo_setup_step.rb +1 -1
- data/lib/project_types/extension/features/argo_setup_steps.rb +2 -2
- data/lib/project_types/extension/forms/connect.rb +2 -2
- data/lib/project_types/extension/forms/create.rb +2 -2
- data/lib/project_types/extension/forms/questions/ask_app.rb +2 -2
- data/lib/project_types/extension/forms/questions/ask_name.rb +1 -1
- data/lib/project_types/extension/forms/questions/ask_registration.rb +2 -2
- data/lib/project_types/extension/forms/questions/ask_template.rb +2 -2
- data/lib/project_types/extension/forms/questions/ask_type.rb +2 -2
- data/lib/project_types/extension/messages/message_loading.rb +2 -2
- data/lib/project_types/extension/models/development_server.rb +49 -6
- data/lib/project_types/extension/models/development_server_requirements.rb +21 -3
- data/lib/project_types/extension/models/lazy_specification_handler.rb +1 -1
- data/lib/project_types/extension/models/specification.rb +1 -1
- data/lib/project_types/extension/models/specification_handlers/default.rb +14 -2
- data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +1 -1
- data/lib/project_types/extension/models/specifications.rb +4 -4
- data/lib/project_types/extension/tasks/choose_next_available_port.rb +1 -1
- data/lib/project_types/extension/tasks/configure_features.rb +1 -1
- data/lib/project_types/extension/tasks/configure_options.rb +1 -1
- data/lib/project_types/extension/tasks/converters/product_converter.rb +1 -1
- data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
- data/lib/project_types/extension/tasks/create_extension.rb +2 -2
- data/lib/project_types/extension/tasks/fetch_specifications.rb +2 -2
- data/lib/project_types/extension/tasks/find_npm_packages.rb +5 -5
- data/lib/project_types/extension/tasks/get_app.rb +2 -2
- data/lib/project_types/extension/tasks/get_apps.rb +2 -2
- data/lib/project_types/extension/tasks/get_extensions.rb +2 -2
- data/lib/project_types/extension/tasks/get_product.rb +2 -2
- data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
- data/lib/project_types/extension/tasks/run_extension_command.rb +34 -11
- data/lib/project_types/extension/tasks/update_draft.rb +2 -2
- data/lib/project_types/node/cli.rb +3 -3
- data/lib/project_types/node/commands/connect.rb +4 -4
- data/lib/project_types/node/commands/create.rb +10 -10
- data/lib/project_types/node/commands/deploy/heroku.rb +4 -4
- data/lib/project_types/node/commands/deploy.rb +3 -3
- data/lib/project_types/node/commands/generate.rb +2 -2
- data/lib/project_types/node/commands/open.rb +3 -3
- data/lib/project_types/node/commands/serve.rb +15 -7
- data/lib/project_types/node/commands/tunnel.rb +6 -6
- data/lib/project_types/node/forms/create.rb +3 -3
- data/lib/project_types/node/messages/messages.rb +3 -0
- data/lib/project_types/php/cli.rb +27 -0
- data/lib/project_types/php/commands/connect.rb +19 -0
- data/lib/project_types/php/commands/create.rb +143 -0
- data/lib/project_types/php/commands/deploy/heroku.rb +129 -0
- data/lib/project_types/php/commands/deploy.rb +32 -0
- data/lib/project_types/php/commands/open.rb +16 -0
- data/lib/project_types/php/commands/serve.rb +51 -0
- data/lib/project_types/php/commands/tunnel.rb +37 -0
- data/lib/project_types/php/forms/create.rb +45 -0
- data/lib/project_types/php/messages/messages.rb +191 -0
- data/lib/project_types/rails/cli.rb +3 -3
- data/lib/project_types/rails/commands/connect.rb +4 -4
- data/lib/project_types/rails/commands/create.rb +12 -12
- data/lib/project_types/rails/commands/deploy/heroku.rb +4 -4
- data/lib/project_types/rails/commands/deploy.rb +3 -3
- data/lib/project_types/rails/commands/generate/webhook.rb +3 -3
- data/lib/project_types/rails/commands/generate.rb +3 -3
- data/lib/project_types/rails/commands/open.rb +3 -3
- data/lib/project_types/rails/commands/serve.rb +8 -8
- data/lib/project_types/rails/commands/tunnel.rb +6 -6
- data/lib/project_types/rails/forms/create.rb +3 -3
- data/lib/project_types/rails/gem.rb +1 -1
- data/lib/project_types/rails/ruby.rb +1 -1
- data/lib/project_types/script/cli.rb +15 -7
- data/lib/project_types/script/commands/create.rb +4 -2
- data/lib/project_types/script/commands/push.rb +2 -2
- data/lib/project_types/script/config/extension_points.yml +30 -29
- data/lib/project_types/script/forms/create.rb +1 -1
- data/lib/project_types/script/layers/application/create_script.rb +32 -12
- data/lib/project_types/script/layers/application/extension_points.rb +4 -4
- data/lib/project_types/script/layers/application/push_script.rb +4 -1
- data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
- data/lib/project_types/script/layers/domain/script_project.rb +2 -2
- data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +57 -0
- data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +35 -0
- data/lib/project_types/script/layers/infrastructure/command_runner.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +6 -6
- data/lib/project_types/script/layers/infrastructure/script_service.rb +4 -8
- data/lib/project_types/script/layers/infrastructure/service_locator.rb +20 -0
- data/lib/project_types/script/messages/messages.rb +4 -0
- data/lib/project_types/script/tasks/ensure_env.rb +6 -6
- data/lib/project_types/script/ui/error_handler.rb +83 -75
- data/lib/project_types/script/ui/printing_spinner.rb +1 -1
- data/lib/project_types/theme/cli.rb +3 -3
- data/lib/project_types/theme/commands/check.rb +3 -3
- data/lib/project_types/theme/commands/delete.rb +7 -7
- data/lib/project_types/theme/commands/init.rb +3 -3
- data/lib/project_types/theme/commands/language_server.rb +2 -2
- data/lib/project_types/theme/commands/package.rb +2 -2
- data/lib/project_types/theme/commands/publish.rb +5 -5
- data/lib/project_types/theme/commands/pull.rb +9 -9
- data/lib/project_types/theme/commands/push.rb +12 -12
- data/lib/project_types/theme/commands/serve.rb +4 -4
- data/lib/project_types/theme/forms/confirm_store.rb +1 -1
- data/lib/project_types/theme/forms/select.rb +2 -2
- data/lib/{shopify-cli → shopify_cli}/admin_api/populate_resource_command.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/admin_api/schema.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/admin_api.rb +27 -27
- data/lib/{shopify-cli → shopify_cli}/api.rb +12 -8
- data/lib/shopify_cli/command/app_sub_command.rb +16 -0
- data/lib/{shopify-cli → shopify_cli}/command.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/commands/config.rb +14 -14
- data/lib/{shopify-cli → shopify_cli}/commands/help.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/commands/login.rb +7 -7
- data/lib/shopify_cli/commands/logout.rb +39 -0
- data/lib/{shopify-cli → shopify_cli}/commands/populate/customer.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/commands/populate/draft_order.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/commands/populate/product.rb +4 -4
- data/lib/shopify_cli/commands/populate.rb +23 -0
- data/lib/shopify_cli/commands/store.rb +15 -0
- data/lib/{shopify-cli → shopify_cli}/commands/switch.rb +5 -5
- data/lib/{shopify-cli → shopify_cli}/commands/system.rb +10 -10
- data/lib/shopify_cli/commands/version.rb +15 -0
- data/lib/{shopify-cli → shopify_cli}/commands/whoami.rb +7 -7
- data/lib/shopify_cli/commands.rb +34 -0
- data/lib/{shopify-cli → shopify_cli}/connect.rb +3 -3
- data/lib/shopify_cli/constants.rb +54 -0
- data/lib/{shopify-cli → shopify_cli}/context.rb +6 -6
- data/lib/{shopify-cli → shopify_cli}/core/entry_point.rb +7 -7
- data/lib/{shopify-cli → shopify_cli}/core/executor.rb +8 -4
- data/lib/{shopify-cli → shopify_cli}/core/finalize.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/core/help_resolver.rb +2 -2
- data/lib/{shopify-cli → shopify_cli}/core/monorail.rb +8 -8
- data/lib/shopify_cli/core.rb +8 -0
- data/lib/{shopify-cli → shopify_cli}/db.rb +8 -8
- data/lib/{shopify-cli → shopify_cli}/environment.rb +36 -5
- data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
- data/lib/shopify_cli/exception_reporter.rb +55 -0
- data/lib/{shopify-cli → shopify_cli}/feature.rb +8 -8
- data/lib/{shopify-cli → shopify_cli}/form.rb +2 -2
- data/lib/{shopify-cli → shopify_cli}/git.rb +36 -6
- data/lib/{shopify-cli → shopify_cli}/helpers/haikunator.rb +1 -1
- data/lib/shopify_cli/helpers.rb +5 -0
- data/lib/{shopify-cli → shopify_cli}/heroku.rb +38 -13
- data/lib/{shopify-cli → shopify_cli}/http_request.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/identity_auth/servlet.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/identity_auth.rb +8 -8
- data/lib/{shopify-cli → shopify_cli}/js_deps.rb +7 -7
- data/lib/{shopify-cli → shopify_cli}/js_system.rb +10 -10
- data/lib/{shopify-cli → shopify_cli}/lazy_delegator.rb +2 -2
- data/lib/{shopify-cli → shopify_cli}/messages/messages.rb +44 -2
- data/lib/{shopify-cli → shopify_cli}/method_object.rb +15 -8
- data/lib/shopify_cli/migrator/migration.rb +27 -0
- data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
- data/lib/shopify_cli/migrator.rb +48 -0
- data/lib/{shopify-cli → shopify_cli}/options.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/packager.rb +8 -8
- data/lib/{shopify-cli → shopify_cli}/partners_api/organizations.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/partners_api.rb +13 -13
- data/lib/shopify_cli/php_deps.rb +102 -0
- data/lib/{shopify-cli → shopify_cli}/process_supervision.rb +10 -8
- data/lib/{shopify-cli → shopify_cli}/project.rb +15 -15
- data/lib/{shopify-cli → shopify_cli}/project_commands.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/project_type.rb +5 -5
- data/lib/{shopify-cli → shopify_cli}/resolve_constant.rb +5 -5
- data/lib/{shopify-cli → shopify_cli}/resources/env_file.rb +1 -1
- data/lib/shopify_cli/resources.rb +5 -0
- data/lib/{shopify-cli → shopify_cli}/result.rb +11 -11
- data/lib/{shopify-cli → shopify_cli}/shopifolk.rb +6 -6
- data/lib/{shopify-cli → shopify_cli}/sub_command.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/task.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/tasks/confirm_store.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/tasks/create_api_client.rb +4 -4
- data/lib/shopify_cli/tasks/ensure_authenticated.rb +13 -0
- data/lib/{shopify-cli → shopify_cli}/tasks/ensure_dev_store.rb +5 -5
- data/lib/{shopify-cli → shopify_cli}/tasks/ensure_env.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/tasks/ensure_loopback_url.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/tasks/ensure_project_type.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/tasks/select_org_and_shop.rb +8 -8
- data/lib/{shopify-cli → shopify_cli}/tasks/update_dashboard_urls.rb +6 -6
- data/lib/{shopify-cli → shopify_cli}/tasks.rb +10 -10
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/certificate_manager.rb +5 -5
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/header_hash.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot-reload.js +0 -0
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot_reload.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/local_assets.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/proxy.rb +2 -2
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/sse.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/watcher.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server/web_server.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/dev_server.rb +3 -3
- data/lib/{shopify-cli → shopify_cli}/theme/development_theme.rb +9 -9
- data/lib/{shopify-cli → shopify_cli}/theme/file.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/ignore_filter.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/mime_type.rb +1 -1
- data/lib/{shopify-cli → shopify_cli}/theme/syncer.rb +6 -6
- data/lib/{shopify-cli → shopify_cli}/theme/theme.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/transform_data_structure.rb +4 -4
- data/lib/{shopify-cli → shopify_cli}/tunnel.rb +14 -14
- data/lib/shopify_cli/version.rb +3 -0
- data/lib/shopify_cli.rb +61 -52
- data/shopify-cli.gemspec +11 -3
- data/utilities/docker.rb +47 -0
- data/utilities/utilities.rb +5 -0
- metadata +133 -95
- data/lib/project_types/script/layers/infrastructure/api_clients.rb +0 -89
- data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
- data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +0 -60
- data/lib/shopify-cli/commands/logout.rb +0 -39
- data/lib/shopify-cli/commands/populate.rb +0 -23
- data/lib/shopify-cli/commands/store.rb +0 -15
- data/lib/shopify-cli/commands/version.rb +0 -15
- data/lib/shopify-cli/commands.rb +0 -34
- data/lib/shopify-cli/constants.rb +0 -26
- data/lib/shopify-cli/core.rb +0 -8
- data/lib/shopify-cli/helpers.rb +0 -5
- data/lib/shopify-cli/resources.rb +0 -5
- data/lib/shopify-cli/tasks/ensure_authenticated.rb +0 -13
- data/lib/shopify-cli/version.rb +0 -3
|
@@ -20,7 +20,7 @@ module Extension
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def self.help
|
|
23
|
-
|
|
23
|
+
ShopifyCLI::Context.new.message("register.help", ShopifyCLI::TOOL_NAME)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
private
|
|
@@ -60,7 +60,7 @@ module Extension
|
|
|
60
60
|
|
|
61
61
|
def abort_not_registered
|
|
62
62
|
@ctx.puts(@ctx.message("register.confirm_abort"))
|
|
63
|
-
raise
|
|
63
|
+
raise ShopifyCLI::AbortSilent
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
end
|
|
@@ -29,7 +29,7 @@ module Extension
|
|
|
29
29
|
resource_url: options.flags[:resource_url]
|
|
30
30
|
)
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
ShopifyCLI::Result
|
|
33
33
|
.success(config)
|
|
34
34
|
.then(&method(:find_available_port))
|
|
35
35
|
.then(&method(:start_tunnel_if_required))
|
|
@@ -38,7 +38,7 @@ module Extension
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def self.help
|
|
41
|
-
|
|
41
|
+
ShopifyCLI::Context.new.message("serve.help", ShopifyCLI::TOOL_NAME)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
private
|
|
@@ -66,12 +66,12 @@ module Extension
|
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def can_start_tunnel?(runtime_configuration)
|
|
69
|
-
return true if
|
|
70
|
-
|
|
69
|
+
return true if ShopifyCLI::Tunnel.urls.empty?
|
|
70
|
+
ShopifyCLI::Tunnel.running_on?(runtime_configuration.port)
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def start_tunnel(runtime_configuration)
|
|
74
|
-
tunnel_url =
|
|
74
|
+
tunnel_url = ShopifyCLI::Tunnel.start(@ctx, port: runtime_configuration.port)
|
|
75
75
|
runtime_configuration.tap { |c| c.tunnel_url = tunnel_url }
|
|
76
76
|
end
|
|
77
77
|
|
|
@@ -21,25 +21,25 @@ module Extension
|
|
|
21
21
|
|
|
22
22
|
case subcommand
|
|
23
23
|
when AUTH_SUBCOMMAND then authorize(args)
|
|
24
|
-
when START_SUBCOMMAND then
|
|
25
|
-
when STOP_SUBCOMMAND then
|
|
24
|
+
when START_SUBCOMMAND then ShopifyCLI::Tunnel.start(@ctx, port: port)
|
|
25
|
+
when STOP_SUBCOMMAND then ShopifyCLI::Tunnel.stop(@ctx)
|
|
26
26
|
when STATUS_SUBCOMMAND then status
|
|
27
27
|
else @ctx.puts(self.class.help)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def self.help
|
|
32
|
-
|
|
32
|
+
ShopifyCLI::Context.message("tunnel.help", ShopifyCLI::TOOL_NAME)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def self.extended_help
|
|
36
|
-
|
|
36
|
+
ShopifyCLI::Context.message("tunnel.extended_help", ShopifyCLI::TOOL_NAME, DEFAULT_PORT)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
private
|
|
40
40
|
|
|
41
41
|
def status
|
|
42
|
-
tunnel_urls =
|
|
42
|
+
tunnel_urls = ShopifyCLI::Tunnel.urls
|
|
43
43
|
tunnel_url = tunnel_urls.find { |url| url.start_with?("https://") }
|
|
44
44
|
tunnel_url = tunnel_urls.first if tunnel_url.nil?
|
|
45
45
|
|
|
@@ -65,7 +65,7 @@ module Extension
|
|
|
65
65
|
@ctx.puts(@ctx.message("tunnel.missing_token"))
|
|
66
66
|
@ctx.puts("#{self.class.help}\n#{self.class.extended_help}")
|
|
67
67
|
else
|
|
68
|
-
|
|
68
|
+
ShopifyCLI::Tunnel.auth(@ctx, token)
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
end
|
|
@@ -3,10 +3,10 @@ require "shopify_cli"
|
|
|
3
3
|
require "securerandom"
|
|
4
4
|
|
|
5
5
|
module Extension
|
|
6
|
-
class ExtensionProject <
|
|
6
|
+
class ExtensionProject < ShopifyCLI::Project
|
|
7
7
|
class << self
|
|
8
8
|
def write_cli_file(context:, type:)
|
|
9
|
-
|
|
9
|
+
ShopifyCLI::Project.write(
|
|
10
10
|
context,
|
|
11
11
|
project_type: :extension,
|
|
12
12
|
organization_id: nil,
|
|
@@ -42,7 +42,7 @@ module Extension
|
|
|
42
42
|
resource_url: nil,
|
|
43
43
|
shop: nil
|
|
44
44
|
)
|
|
45
|
-
|
|
45
|
+
ShopifyCLI::Resources::EnvFile.new(
|
|
46
46
|
api_key: api_key,
|
|
47
47
|
secret: api_secret,
|
|
48
48
|
shop: shop,
|
|
@@ -134,7 +134,7 @@ module Extension
|
|
|
134
134
|
|
|
135
135
|
def validate_env_present
|
|
136
136
|
return if env
|
|
137
|
-
raise
|
|
137
|
+
raise ShopifyCLI::Abort, "Missing .env file. Run `shopify extension connect` to generate an .env file."
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
def integer?(value)
|
|
@@ -24,7 +24,7 @@ module Extension
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def config(context)
|
|
27
|
-
js_system =
|
|
27
|
+
js_system = ShopifyCLI::JsSystem.new(ctx: context)
|
|
28
28
|
if js_system.package_manager == "yarn"
|
|
29
29
|
run_yarn_install(context, js_system)
|
|
30
30
|
run_yarn_run_script(context, js_system)
|
|
@@ -42,9 +42,9 @@ module Extension
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def renderer_package(context)
|
|
45
|
-
js_system =
|
|
45
|
+
js_system = ShopifyCLI::JsSystem.new(ctx: context)
|
|
46
46
|
Tasks::FindNpmPackages
|
|
47
|
-
.exactly_one_of(renderer_package_name, js_system: js_system)
|
|
47
|
+
.exactly_one_of(renderer_package_name, js_system: js_system, production_only: true)
|
|
48
48
|
.unwrap { |err| raise err }
|
|
49
49
|
rescue Extension::PackageResolutionFailed
|
|
50
50
|
context.abort(
|
|
@@ -21,7 +21,7 @@ module Extension
|
|
|
21
21
|
return {} if config.nil?
|
|
22
22
|
|
|
23
23
|
unless config.is_a?(Hash)
|
|
24
|
-
raise
|
|
24
|
+
raise ShopifyCLI::Abort, ShopifyCLI::Context.message("core.yaml.error.not_hash", CONFIG_FILE_NAME)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
config.transform_keys!(&:to_sym)
|
|
@@ -30,8 +30,8 @@ module Extension
|
|
|
30
30
|
config
|
|
31
31
|
rescue Psych::SyntaxError => e
|
|
32
32
|
raise(
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
ShopifyCLI::Abort,
|
|
34
|
+
ShopifyCLI::Context.message("core.yaml.error.invalid", CONFIG_FILE_NAME, e.message)
|
|
35
35
|
)
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -45,8 +45,8 @@ module Extension
|
|
|
45
45
|
|
|
46
46
|
unless unpermitted_keys.empty?
|
|
47
47
|
raise(
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
ShopifyCLI::Abort,
|
|
49
|
+
ShopifyCLI::Context.message(
|
|
50
50
|
"features.argo.config.unpermitted_keys",
|
|
51
51
|
CONFIG_FILE_NAME,
|
|
52
52
|
unpermitted_keys.map { |k| "\n- #{k}" }.join
|
|
@@ -7,11 +7,11 @@ module Extension
|
|
|
7
7
|
NPM_SERVE_COMMAND = %w(run-script server)
|
|
8
8
|
|
|
9
9
|
property! :specification_handler, accepts: Extension::Models::SpecificationHandlers::Default
|
|
10
|
-
property
|
|
11
|
-
property! :context, accepts:
|
|
10
|
+
property :argo_runtime, accepts: -> (runtime) { runtime.class < Features::Runtimes::Base }
|
|
11
|
+
property! :context, accepts: ShopifyCLI::Context
|
|
12
12
|
property! :port, accepts: Integer, default: 39351
|
|
13
13
|
property :tunnel_url, accepts: String, default: nil
|
|
14
|
-
property! :js_system, accepts: ->(jss) { jss.respond_to?(:call) }, default:
|
|
14
|
+
property! :js_system, accepts: ->(jss) { jss.respond_to?(:call) }, default: ShopifyCLI::JsSystem
|
|
15
15
|
property :resource_url, accepts: String, default: nil
|
|
16
16
|
|
|
17
17
|
def call
|
|
@@ -30,6 +30,7 @@ module Extension
|
|
|
30
30
|
private
|
|
31
31
|
|
|
32
32
|
def start_server
|
|
33
|
+
return new_serve_flow if supports_development_server?
|
|
33
34
|
js_system.call(context, yarn: yarn_serve_command, npm: npm_serve_command)
|
|
34
35
|
end
|
|
35
36
|
|
|
@@ -58,8 +59,8 @@ module Extension
|
|
|
58
59
|
|
|
59
60
|
return if required_fields.none?
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
ShopifyCLI::Tasks::EnsureEnv.call(context, required: required_fields)
|
|
63
|
+
ShopifyCLI::Tasks::EnsureDevStore.call(context) if required_fields.include?(:shop)
|
|
63
64
|
|
|
64
65
|
project = ExtensionProject.current
|
|
65
66
|
ensure_resource_resource_url! if specification_handler.supplies_resource_url?
|
|
@@ -90,7 +91,7 @@ module Extension
|
|
|
90
91
|
def ensure_resource_resource_url!
|
|
91
92
|
project = ExtensionProject.current(force_reload: true)
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
ShopifyCLI::Result
|
|
94
95
|
.wrap(project.resource_url)
|
|
95
96
|
.rescue { specification_handler.build_resource_url(shop: project.env.shop, context: context) }
|
|
96
97
|
.then(&method(:persist_resource_url))
|
|
@@ -108,6 +109,20 @@ module Extension
|
|
|
108
109
|
ExtensionProject.update_env_file(context: context, resource_url: resource_url)
|
|
109
110
|
resource_url
|
|
110
111
|
end
|
|
112
|
+
|
|
113
|
+
def new_serve_flow
|
|
114
|
+
Tasks::RunExtensionCommand.new(
|
|
115
|
+
type: specification_handler.specification.identifier,
|
|
116
|
+
command: "serve",
|
|
117
|
+
context: context,
|
|
118
|
+
port: port,
|
|
119
|
+
config_file_name: specification_handler.server_config_file,
|
|
120
|
+
).call
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def supports_development_server?
|
|
124
|
+
Models::DevelopmentServerRequirements.supported?(specification_handler.specification.identifier)
|
|
125
|
+
end
|
|
111
126
|
end
|
|
112
127
|
end
|
|
113
128
|
end
|
|
@@ -26,7 +26,7 @@ module Extension
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def run_install_steps(context, steps, identifier, directory_name)
|
|
29
|
-
system =
|
|
29
|
+
system = ShopifyCLI::JsSystem.new(ctx: context)
|
|
30
30
|
|
|
31
31
|
steps.inject(true) do |success, setup_step|
|
|
32
32
|
success && setup_step.call(context, identifier, directory_name, system)
|
|
@@ -11,7 +11,7 @@ module Extension
|
|
|
11
11
|
def call(context, identifier, directory_name, js_system)
|
|
12
12
|
step_result = step.call(context, identifier, directory_name, js_system)
|
|
13
13
|
can_fail? ? step_result : true
|
|
14
|
-
rescue
|
|
14
|
+
rescue ShopifyCLI::Abort => e
|
|
15
15
|
context.puts(e.message)
|
|
16
16
|
false
|
|
17
17
|
rescue StandardError => e
|
|
@@ -18,7 +18,7 @@ module Extension
|
|
|
18
18
|
def self.clone_template(git_template)
|
|
19
19
|
ArgoSetupStep.default do |context, _identifier, directory_name, _js_system|
|
|
20
20
|
begin
|
|
21
|
-
|
|
21
|
+
ShopifyCLI::Git.clone(git_template, directory_name, ctx: context)
|
|
22
22
|
context.root = File.join(context.root, directory_name)
|
|
23
23
|
rescue StandardError
|
|
24
24
|
context.puts("{{x}} Unable to clone the repository.")
|
|
@@ -28,7 +28,7 @@ module Extension
|
|
|
28
28
|
|
|
29
29
|
def self.install_dependencies
|
|
30
30
|
ArgoSetupStep.default do |context, _identifier, _directory_name, js_system|
|
|
31
|
-
|
|
31
|
+
ShopifyCLI::JsDeps.new(ctx: context, system: js_system).install
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Extension
|
|
4
4
|
module Forms
|
|
5
|
-
class Connect <
|
|
5
|
+
class Connect < ShopifyCLI::Form
|
|
6
6
|
attr_reader :registration, :app
|
|
7
7
|
|
|
8
8
|
flag_arguments :type
|
|
@@ -19,7 +19,7 @@ module Extension
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def ask
|
|
22
|
-
|
|
22
|
+
ShopifyCLI::Result.wrap(ExtensionProjectDetails.new)
|
|
23
23
|
.then(&Questions::AskRegistration.new(ctx: ctx, type: type))
|
|
24
24
|
.unwrap { |e| raise e }
|
|
25
25
|
.tap do |project_details|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Extension
|
|
4
4
|
module Forms
|
|
5
|
-
class Create <
|
|
5
|
+
class Create < ShopifyCLI::Form
|
|
6
6
|
flag_arguments :name, :type, :api_key, :template
|
|
7
7
|
|
|
8
8
|
attr_reader :app
|
|
@@ -21,7 +21,7 @@ module Extension
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def ask
|
|
24
|
-
|
|
24
|
+
ShopifyCLI::Result.wrap(ExtensionProjectDetails.new)
|
|
25
25
|
.then(&Questions::AskApp.new(ctx: ctx, api_key: api_key))
|
|
26
26
|
.then(&Questions::AskType.new(ctx: ctx, type: type))
|
|
27
27
|
.then(&Questions::AskTemplate.new(ctx: ctx))
|
|
@@ -2,7 +2,7 @@ module Extension
|
|
|
2
2
|
module Forms
|
|
3
3
|
module Questions
|
|
4
4
|
class AskApp
|
|
5
|
-
include
|
|
5
|
+
include ShopifyCLI::MethodObject
|
|
6
6
|
|
|
7
7
|
property! :ctx
|
|
8
8
|
property :api_key
|
|
@@ -45,7 +45,7 @@ module Extension
|
|
|
45
45
|
def abort_no_apps
|
|
46
46
|
ctx.puts(@ctx.message("create.no_apps"))
|
|
47
47
|
ctx.puts(@ctx.message("create.learn_about_apps"))
|
|
48
|
-
raise
|
|
48
|
+
raise ShopifyCLI::AbortSilent
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
end
|
|
@@ -4,7 +4,7 @@ module Extension
|
|
|
4
4
|
module Forms
|
|
5
5
|
module Questions
|
|
6
6
|
class AskRegistration
|
|
7
|
-
include
|
|
7
|
+
include ShopifyCLI::MethodObject
|
|
8
8
|
|
|
9
9
|
property! :ctx
|
|
10
10
|
property! :type
|
|
@@ -43,7 +43,7 @@ module Extension
|
|
|
43
43
|
def abort_no_registrations
|
|
44
44
|
ctx.puts(@ctx.message("connect.no_extensions", type))
|
|
45
45
|
ctx.puts(@ctx.message("connect.learn_about_extensions"))
|
|
46
|
-
raise
|
|
46
|
+
raise ShopifyCLI::AbortSilent
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
@@ -2,7 +2,7 @@ module Extension
|
|
|
2
2
|
module Forms
|
|
3
3
|
module Questions
|
|
4
4
|
class AskTemplate
|
|
5
|
-
include
|
|
5
|
+
include ShopifyCLI::MethodObject
|
|
6
6
|
|
|
7
7
|
TEMPLATE_REQUIRED_TYPES = [
|
|
8
8
|
"checkout_ui_extension",
|
|
@@ -28,7 +28,7 @@ module Extension
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def extension_server_beta?
|
|
31
|
-
|
|
31
|
+
ShopifyCLI::Shopifolk.check && ShopifyCLI::Feature.enabled?(:extension_server_beta)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def choose_interactively
|
|
@@ -2,7 +2,7 @@ module Extension
|
|
|
2
2
|
module Forms
|
|
3
3
|
module Questions
|
|
4
4
|
class AskType
|
|
5
|
-
include
|
|
5
|
+
include ShopifyCLI::MethodObject
|
|
6
6
|
|
|
7
7
|
property! :ctx
|
|
8
8
|
property :type
|
|
@@ -39,7 +39,7 @@ module Extension
|
|
|
39
39
|
|
|
40
40
|
def abort_due_to_missing_specifications
|
|
41
41
|
ctx.puts(@ctx.message("create.no_available_extensions"))
|
|
42
|
-
raise
|
|
42
|
+
raise ShopifyCLI::AbortSilent
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
end
|
|
@@ -15,9 +15,9 @@ module Extension
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def self.load_current_type_messages
|
|
18
|
-
return unless
|
|
18
|
+
return unless ShopifyCLI::Project.has_current?
|
|
19
19
|
messages_for_type(
|
|
20
|
-
|
|
20
|
+
ShopifyCLI::Project.current.config[Extension::ExtensionProjectKeys::SPECIFICATION_IDENTIFIER_KEY]
|
|
21
21
|
)
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -7,9 +7,24 @@ module Extension
|
|
|
7
7
|
|
|
8
8
|
include SmartProperties
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
EXECUTABLE_DIRECTORY = File.join(ShopifyCLI::ROOT, "ext", "shopify-extensions")
|
|
11
11
|
|
|
12
|
-
property
|
|
12
|
+
property :executable, converts: :to_s
|
|
13
|
+
|
|
14
|
+
def executable
|
|
15
|
+
super || begin
|
|
16
|
+
case RbConfig::CONFIG.fetch("host_os")
|
|
17
|
+
when /(linux)|(darwin)/
|
|
18
|
+
File.join(EXECUTABLE_DIRECTORY, "shopify-extensions")
|
|
19
|
+
else
|
|
20
|
+
File.join(EXECUTABLE_DIRECTORY, "shopify-extensions.exe")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def executable_installed?
|
|
26
|
+
File.exist?(executable)
|
|
27
|
+
end
|
|
13
28
|
|
|
14
29
|
def create(server_config)
|
|
15
30
|
CLI::Kit::System.capture3(executable, "create", "-", stdin_data: server_config.to_yaml)
|
|
@@ -18,18 +33,46 @@ module Extension
|
|
|
18
33
|
end
|
|
19
34
|
|
|
20
35
|
def build(server_config)
|
|
21
|
-
_, error,
|
|
22
|
-
return if
|
|
36
|
+
_, error, status = CLI::Kit::System.capture3(executable, "build", "-", stdin_data: server_config.to_yaml)
|
|
37
|
+
return if status.success?
|
|
23
38
|
raise DevelopmentServerError, error
|
|
24
39
|
end
|
|
25
40
|
|
|
26
|
-
def serve
|
|
27
|
-
|
|
41
|
+
def serve(context, server_config)
|
|
42
|
+
CLI::Kit::System.popen3(executable, "serve", "-") do |input, out, err, status|
|
|
43
|
+
context.puts("Sending configuration data …")
|
|
44
|
+
input << server_config.to_yaml
|
|
45
|
+
input.close
|
|
46
|
+
|
|
47
|
+
forward_output_to_user(out, err, context)
|
|
48
|
+
|
|
49
|
+
status.value
|
|
50
|
+
end
|
|
28
51
|
end
|
|
29
52
|
|
|
30
53
|
def version
|
|
31
54
|
raise NotImplementedError
|
|
32
55
|
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def forward_output_to_user(out, err, ctx)
|
|
60
|
+
ctx.puts("Starting monitoring threads …")
|
|
61
|
+
|
|
62
|
+
Thread.new do
|
|
63
|
+
ctx.puts("Ready to process standard output")
|
|
64
|
+
while (line = out.gets)
|
|
65
|
+
ctx.puts(line)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
Thread.new do
|
|
70
|
+
ctx.puts("Ready to process standard error")
|
|
71
|
+
while (error = err.gets)
|
|
72
|
+
ctx.puts(error)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
33
76
|
end
|
|
34
77
|
end
|
|
35
78
|
end
|
|
@@ -8,9 +8,27 @@ module Extension
|
|
|
8
8
|
"checkout_ui_extension",
|
|
9
9
|
]
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
UNIX_NAME = "shopify-extensions"
|
|
12
|
+
WINDOWS_NAME = "shopify-extensions.exe"
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def supported?(type)
|
|
16
|
+
binary_installed? && type_supported?(type) && beta_enabled?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def binary_installed?
|
|
22
|
+
Models::DevelopmentServer.new.executable_installed?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def type_supported?(type)
|
|
26
|
+
SUPPORTED_EXTENSION_TYPES.include?(type.downcase)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def beta_enabled?
|
|
30
|
+
ShopifyCLI::Shopifolk.check && ShopifyCLI::Feature.enabled?(:extension_server_beta)
|
|
31
|
+
end
|
|
14
32
|
end
|
|
15
33
|
end
|
|
16
34
|
end
|
|
@@ -18,7 +18,7 @@ module Extension
|
|
|
18
18
|
def self.build(feature_set_attributes)
|
|
19
19
|
feature_set_attributes.each_with_object(OpenStruct.new) do |(identifier, feature_attributes), feature_set|
|
|
20
20
|
next if feature_attributes.nil?
|
|
21
|
-
feature_set[identifier] =
|
|
21
|
+
feature_set[identifier] = ShopifyCLI::ResolveConstant
|
|
22
22
|
.call(identifier, namespace: Features)
|
|
23
23
|
.rescue { OpenStruct }
|
|
24
24
|
.then { |c| c.new(**feature_attributes) }
|
|
@@ -43,10 +43,12 @@ module Extension
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def choose_port?(context)
|
|
46
|
+
return true if supports_development_server?
|
|
46
47
|
argo_runtime(context).supports?(:port)
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
def establish_tunnel?(context)
|
|
51
|
+
return true if supports_development_server?
|
|
50
52
|
argo_runtime(context).supports?(:public_url)
|
|
51
53
|
end
|
|
52
54
|
|
|
@@ -66,6 +68,8 @@ module Extension
|
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
def argo_runtime(context)
|
|
71
|
+
return if supports_development_server?
|
|
72
|
+
|
|
69
73
|
@argo_runtime ||= Features::ArgoRuntime.find(
|
|
70
74
|
cli_package: cli_package(context),
|
|
71
75
|
identifier: identifier
|
|
@@ -76,7 +80,7 @@ module Extension
|
|
|
76
80
|
cli_package_name = specification.features.argo&.cli_package_name
|
|
77
81
|
return unless cli_package_name
|
|
78
82
|
|
|
79
|
-
js_system =
|
|
83
|
+
js_system = ShopifyCLI::JsSystem.new(ctx: context)
|
|
80
84
|
Tasks::FindNpmPackages.exactly_one_of(cli_package_name, js_system: js_system)
|
|
81
85
|
.unwrap { |_e| context.abort(context.message("errors.package_not_found", cli_package_name)) }
|
|
82
86
|
end
|
|
@@ -87,7 +91,7 @@ module Extension
|
|
|
87
91
|
if (str = messages.dig(*key_parts))
|
|
88
92
|
str % params
|
|
89
93
|
else
|
|
90
|
-
|
|
94
|
+
ShopifyCLI::Context.message(key, *params)
|
|
91
95
|
end
|
|
92
96
|
end
|
|
93
97
|
|
|
@@ -99,6 +103,10 @@ module Extension
|
|
|
99
103
|
raise NotImplementedError
|
|
100
104
|
end
|
|
101
105
|
|
|
106
|
+
def server_config_file
|
|
107
|
+
"shopifile.yml"
|
|
108
|
+
end
|
|
109
|
+
|
|
102
110
|
protected
|
|
103
111
|
|
|
104
112
|
def argo
|
|
@@ -118,6 +126,10 @@ module Extension
|
|
|
118
126
|
def messages
|
|
119
127
|
@messages ||= Messages::TYPES[identifier.downcase.to_sym] || {}
|
|
120
128
|
end
|
|
129
|
+
|
|
130
|
+
def supports_development_server?
|
|
131
|
+
Models::DevelopmentServerRequirements.supported?(identifier)
|
|
132
|
+
end
|
|
121
133
|
end
|
|
122
134
|
end
|
|
123
135
|
end
|
|
@@ -15,7 +15,7 @@ module Extension
|
|
|
15
15
|
context.root = File.join(context.root, directory_name)
|
|
16
16
|
|
|
17
17
|
if getting_started
|
|
18
|
-
|
|
18
|
+
ShopifyCLI::Git.clone("https://github.com/Shopify/theme-extension-getting-started", context.root)
|
|
19
19
|
context.rm_r(".git")
|
|
20
20
|
else
|
|
21
21
|
FileUtils.makedirs(SUPPORTED_BUCKETS.map { |b| File.join(context.root, b) })
|
|
@@ -5,7 +5,7 @@ module Extension
|
|
|
5
5
|
|
|
6
6
|
property! :custom_handler_root,
|
|
7
7
|
accepts: ->(d) { File.directory?(d) },
|
|
8
|
-
default: -> { File.expand_path("lib/project_types/extension/models/specification_handlers",
|
|
8
|
+
default: -> { File.expand_path("lib/project_types/extension/models/specification_handlers", ShopifyCLI::ROOT) }
|
|
9
9
|
|
|
10
10
|
property! :custom_handler_namespace,
|
|
11
11
|
accepts: ->(m) { m.respond_to?(:const_get) },
|
|
@@ -39,9 +39,9 @@ module Extension
|
|
|
39
39
|
private
|
|
40
40
|
|
|
41
41
|
def fetch_specifications_and_build_handlers
|
|
42
|
-
|
|
42
|
+
ShopifyCLI::Result
|
|
43
43
|
.call(&fetch_specifications)
|
|
44
|
-
.map(&
|
|
44
|
+
.map(&ShopifyCLI::TransformDataStructure.new(symbolize_keys: true, underscore_keys: true))
|
|
45
45
|
.then(&method(:select_cli_extensions))
|
|
46
46
|
.then(&Tasks::ConfigureFeatures)
|
|
47
47
|
.then(&Tasks::ConfigureOptions)
|
|
@@ -61,7 +61,7 @@ module Extension
|
|
|
61
61
|
|
|
62
62
|
def instantiate_specification_handlers(specifications)
|
|
63
63
|
specifications.each_with_object({}) do |specification, handlers|
|
|
64
|
-
|
|
64
|
+
ShopifyCLI::ResolveConstant.call(specification.identifier, namespace: custom_handler_namespace)
|
|
65
65
|
.rescue { |error| error.is_a?(NameError) ? SpecificationHandlers::Default : raise(error) }
|
|
66
66
|
.then { |handler_class| handler_class.new(specification) }
|
|
67
67
|
.unwrap { |error| raise error }
|