shopify-cli 0.9.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 +7 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/CODE_OF_CONDUCT.md +73 -0
- data/.github/CONTRIBUTING.md +51 -0
- data/.github/DESIGN.md +153 -0
- data/.github/ISSUE_TEMPLATE.md +38 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
- data/.github/probots.yml +3 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +47 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +77 -0
- data/LICENSE.md +7 -0
- data/README.md +13 -0
- data/Rakefile +101 -0
- data/SECURITY.md +59 -0
- data/Vagrantfile +17 -0
- data/bin/load_shopify.rb +20 -0
- data/bin/shopify +32 -0
- data/dev.yml +17 -0
- data/docs/Gemfile +5 -0
- data/docs/Gemfile.lock +248 -0
- data/docs/_config.yml +16 -0
- data/docs/_data/nav.yml +26 -0
- data/docs/_includes/footer.html +15 -0
- data/docs/_includes/head.html +19 -0
- data/docs/_includes/sidebar_nav.html +22 -0
- data/docs/_includes/toc.html +112 -0
- data/docs/_layouts/default.html +79 -0
- data/docs/app/node/commands/index.md +82 -0
- data/docs/app/node/index.md +35 -0
- data/docs/app/rails/commands/index.md +80 -0
- data/docs/app/rails/index.md +36 -0
- data/docs/core/index.md +70 -0
- data/docs/css/docs.css +157 -0
- data/docs/getting-started/index.md +61 -0
- data/docs/help/start-app/index.md +6 -0
- data/docs/images/header.png +0 -0
- data/docs/index.md +27 -0
- data/docs/installing-ruby.md +28 -0
- data/ext/shopify-cli/extconf.rb +27 -0
- data/install.sh +7 -0
- data/lib/docgen/class_template.md.erb +81 -0
- data/lib/docgen/index_template.md.erb +5 -0
- data/lib/docgen/markdown.rb +101 -0
- data/lib/graphql/admin_introspection.graphql +87 -0
- data/lib/graphql/all_organizations.graphql +19 -0
- data/lib/graphql/all_orgs_with_apps.graphql +30 -0
- data/lib/graphql/api_versions.graphql +6 -0
- data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
- data/lib/graphql/create_app.graphql +20 -0
- data/lib/graphql/create_customer.graphql +9 -0
- data/lib/graphql/create_draft_order.graphql +8 -0
- data/lib/graphql/create_product.graphql +9 -0
- data/lib/graphql/extension_create.graphql +21 -0
- data/lib/graphql/extension_update_draft.graphql +18 -0
- data/lib/graphql/find_organization.graphql +17 -0
- data/lib/graphql/get_app_urls.graphql +6 -0
- data/lib/graphql/update_dashboard_urls.graphql +8 -0
- data/lib/project_types/extension/cli.rb +71 -0
- data/lib/project_types/extension/commands/build.rb +29 -0
- data/lib/project_types/extension/commands/create.rb +49 -0
- data/lib/project_types/extension/commands/extension_command.rb +22 -0
- data/lib/project_types/extension/commands/push.rb +69 -0
- data/lib/project_types/extension/commands/register.rb +78 -0
- data/lib/project_types/extension/commands/serve.rb +24 -0
- data/lib/project_types/extension/commands/tunnel.rb +69 -0
- data/lib/project_types/extension/extension_project.rb +85 -0
- data/lib/project_types/extension/extension_project_keys.rb +10 -0
- data/lib/project_types/extension/features/argo.rb +48 -0
- data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
- data/lib/project_types/extension/features/argo_setup.rb +54 -0
- data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
- data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
- data/lib/project_types/extension/features/tunnel_url.rb +20 -0
- data/lib/project_types/extension/forms/create.rb +52 -0
- data/lib/project_types/extension/forms/register.rb +48 -0
- data/lib/project_types/extension/messages/message_loading.rb +37 -0
- data/lib/project_types/extension/messages/messages.rb +126 -0
- data/lib/project_types/extension/models/app.rb +14 -0
- data/lib/project_types/extension/models/registration.rb +19 -0
- data/lib/project_types/extension/models/type.rb +76 -0
- data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
- data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
- data/lib/project_types/extension/models/validation_error.rb +17 -0
- data/lib/project_types/extension/models/version.rb +15 -0
- data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
- data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
- data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
- data/lib/project_types/extension/tasks/create_extension.rb +31 -0
- data/lib/project_types/extension/tasks/get_apps.rb +34 -0
- data/lib/project_types/extension/tasks/update_draft.rb +29 -0
- data/lib/project_types/extension/tasks/user_errors.rb +45 -0
- data/lib/project_types/node/cli.rb +37 -0
- data/lib/project_types/node/commands/create.rb +117 -0
- data/lib/project_types/node/commands/deploy.rb +22 -0
- data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
- data/lib/project_types/node/commands/generate.rb +51 -0
- data/lib/project_types/node/commands/generate/billing.rb +37 -0
- data/lib/project_types/node/commands/generate/page.rb +55 -0
- data/lib/project_types/node/commands/generate/webhook.rb +33 -0
- data/lib/project_types/node/commands/open.rb +16 -0
- data/lib/project_types/node/commands/populate.rb +23 -0
- data/lib/project_types/node/commands/populate/customer.rb +31 -0
- data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
- data/lib/project_types/node/commands/populate/product.rb +30 -0
- data/lib/project_types/node/commands/serve.rb +45 -0
- data/lib/project_types/node/commands/tunnel.rb +39 -0
- data/lib/project_types/node/forms/create.rb +87 -0
- data/lib/project_types/node/messages/messages.rb +260 -0
- data/lib/project_types/rails/cli.rb +41 -0
- data/lib/project_types/rails/commands/create.rb +126 -0
- data/lib/project_types/rails/commands/deploy.rb +22 -0
- data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
- data/lib/project_types/rails/commands/generate.rb +49 -0
- data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
- data/lib/project_types/rails/commands/open.rb +16 -0
- data/lib/project_types/rails/commands/populate.rb +23 -0
- data/lib/project_types/rails/commands/populate/customer.rb +31 -0
- data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
- data/lib/project_types/rails/commands/populate/product.rb +30 -0
- data/lib/project_types/rails/commands/serve.rb +47 -0
- data/lib/project_types/rails/commands/tunnel.rb +39 -0
- data/lib/project_types/rails/forms/create.rb +116 -0
- data/lib/project_types/rails/gem.rb +56 -0
- data/lib/project_types/rails/messages/messages.rb +283 -0
- data/lib/project_types/rails/ruby.rb +17 -0
- data/lib/project_types/script/cli.rb +76 -0
- data/lib/project_types/script/commands/create.rb +45 -0
- data/lib/project_types/script/commands/disable.rb +36 -0
- data/lib/project_types/script/commands/enable.rb +46 -0
- data/lib/project_types/script/commands/push.rb +39 -0
- data/lib/project_types/script/config/extension_points.yml +18 -0
- data/lib/project_types/script/errors.rb +16 -0
- data/lib/project_types/script/forms/create.rb +29 -0
- data/lib/project_types/script/forms/enable.rb +24 -0
- data/lib/project_types/script/forms/push.rb +19 -0
- data/lib/project_types/script/forms/script_form.rb +66 -0
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
- data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
- data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
- data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
- data/lib/project_types/script/layers/application/build_script.rb +43 -0
- data/lib/project_types/script/layers/application/create_script.rb +47 -0
- data/lib/project_types/script/layers/application/disable_script.rb +19 -0
- data/lib/project_types/script/layers/application/enable_script.rb +21 -0
- data/lib/project_types/script/layers/application/extension_points.rb +17 -0
- data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
- data/lib/project_types/script/layers/application/push_script.rb +30 -0
- data/lib/project_types/script/layers/domain/errors.rb +25 -0
- data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
- data/lib/project_types/script/layers/domain/push_package.rb +29 -0
- data/lib/project_types/script/layers/domain/script.rb +18 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
- data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
- data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
- data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
- data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
- data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
- data/lib/project_types/script/messages/messages.rb +204 -0
- data/lib/project_types/script/script_project.rb +37 -0
- data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
- data/lib/project_types/script/ui/error_handler.rb +136 -0
- data/lib/project_types/script/ui/strict_spinner.rb +22 -0
- data/lib/rubygems_plugin.rb +18 -0
- data/lib/shopify-cli/admin_api.rb +99 -0
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
- data/lib/shopify-cli/admin_api/schema.rb +32 -0
- data/lib/shopify-cli/api.rb +104 -0
- data/lib/shopify-cli/command.rb +67 -0
- data/lib/shopify-cli/commands.rb +28 -0
- data/lib/shopify-cli/commands/connect.rb +108 -0
- data/lib/shopify-cli/commands/create.rb +50 -0
- data/lib/shopify-cli/commands/help.rb +79 -0
- data/lib/shopify-cli/commands/logout.rb +23 -0
- data/lib/shopify-cli/commands/system.rb +135 -0
- data/lib/shopify-cli/commands/version.rb +15 -0
- data/lib/shopify-cli/context.rb +372 -0
- data/lib/shopify-cli/core.rb +9 -0
- data/lib/shopify-cli/core/entry_point.rb +40 -0
- data/lib/shopify-cli/core/executor.rb +21 -0
- data/lib/shopify-cli/core/help_resolver.rb +20 -0
- data/lib/shopify-cli/core/monorail.rb +118 -0
- data/lib/shopify-cli/db.rb +114 -0
- data/lib/shopify-cli/form.rb +40 -0
- data/lib/shopify-cli/git.rb +141 -0
- data/lib/shopify-cli/helpers.rb +5 -0
- data/lib/shopify-cli/helpers/haikunator.rb +92 -0
- data/lib/shopify-cli/heroku.rb +97 -0
- data/lib/shopify-cli/js_deps.rb +110 -0
- data/lib/shopify-cli/js_system.rb +98 -0
- data/lib/shopify-cli/messages/messages.rb +287 -0
- data/lib/shopify-cli/oauth.rb +192 -0
- data/lib/shopify-cli/oauth/servlet.rb +61 -0
- data/lib/shopify-cli/options.rb +40 -0
- data/lib/shopify-cli/packager.rb +116 -0
- data/lib/shopify-cli/partners_api.rb +114 -0
- data/lib/shopify-cli/partners_api/organizations.rb +32 -0
- data/lib/shopify-cli/process_supervision.rb +187 -0
- data/lib/shopify-cli/project.rb +191 -0
- data/lib/shopify-cli/project_type.rb +83 -0
- data/lib/shopify-cli/resources.rb +5 -0
- data/lib/shopify-cli/resources/env_file.rb +96 -0
- data/lib/shopify-cli/sub_command.rb +15 -0
- data/lib/shopify-cli/task.rb +10 -0
- data/lib/shopify-cli/tasks.rb +32 -0
- data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
- data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
- data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
- data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
- data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
- data/lib/shopify-cli/tunnel.rb +154 -0
- data/lib/shopify-cli/version.rb +3 -0
- data/lib/shopify_cli.rb +132 -0
- data/shopify-cli.gemspec +40 -0
- data/shopify.fish +12 -0
- data/shopify.sh +11 -0
- data/vendor/deps/cli-kit/REVISION +1 -0
- data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
- data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
- data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
- data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
- data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
- data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
- data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
- data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
- data/vendor/deps/cli-ui/REVISION +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
- data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
- data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
- data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
- data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
- data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
- data/vendor/deps/smart_properties/REVISION +1 -0
- data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
- data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
- data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
- data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
- data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
- data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
- data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
- data/vendor/lib/semantic/LICENSE +20 -0
- data/vendor/lib/semantic/semantic.rb +4 -0
- data/vendor/lib/semantic/version.rb +180 -0
- metadata +374 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
|
|
3
|
+
module ShopifyCli
|
|
4
|
+
module Commands
|
|
5
|
+
Registry = CLI::Kit::CommandRegistry.new(
|
|
6
|
+
default: 'help',
|
|
7
|
+
contextual_resolver: nil,
|
|
8
|
+
)
|
|
9
|
+
@core_commands = []
|
|
10
|
+
|
|
11
|
+
def self.register(const, cmd, path = nil, is_core = false)
|
|
12
|
+
autoload(const, path) if path
|
|
13
|
+
Registry.add(->() { const_get(const) }, cmd)
|
|
14
|
+
@core_commands.push(cmd) if is_core
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.core_command?(cmd)
|
|
18
|
+
@core_commands.include?(cmd)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
register :Connect, 'connect', 'shopify-cli/commands/connect', true
|
|
22
|
+
register :Create, 'create', 'shopify-cli/commands/create', true
|
|
23
|
+
register :Help, 'help', 'shopify-cli/commands/help', true
|
|
24
|
+
register :Logout, 'logout', 'shopify-cli/commands/logout', true
|
|
25
|
+
register :System, 'system', 'shopify-cli/commands/system', true
|
|
26
|
+
register :Version, 'version', 'shopify-cli/commands/version', true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
|
|
3
|
+
module ShopifyCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Connect < ShopifyCli::Command
|
|
6
|
+
def call(*)
|
|
7
|
+
project_type = ask_project_type unless Project.has_current?
|
|
8
|
+
|
|
9
|
+
if Project.has_current? && Project.current
|
|
10
|
+
@ctx.puts @ctx.message('core.connect.already_connected_warning')
|
|
11
|
+
prod_warning = @ctx.message('core.connect.production_warning')
|
|
12
|
+
@ctx.puts prod_warning if [:rails, :node].include?(Project.current_project_type)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
env_data = begin
|
|
16
|
+
Resources::EnvFile.parse_external_env
|
|
17
|
+
rescue Errno::ENOENT
|
|
18
|
+
{}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
org = fetch_org
|
|
22
|
+
id = org['id']
|
|
23
|
+
app = get_app(org['apps'])
|
|
24
|
+
shop = get_shop(org['stores'], id)
|
|
25
|
+
|
|
26
|
+
write_env(app, shop, env_data[:scopes], env_data[:extra])
|
|
27
|
+
write_cli_yml(project_type, id) unless Project.has_current?
|
|
28
|
+
|
|
29
|
+
@ctx.puts(@ctx.message('core.connect.connected', app.first['title']))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def ask_project_type
|
|
33
|
+
CLI::UI::Prompt.ask(@ctx.message('core.connect.project_type_select')) do |handler|
|
|
34
|
+
ShopifyCli::Commands::Create.all_visible_type.each do |type|
|
|
35
|
+
handler.option(type.project_name) { type.project_type }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def fetch_org
|
|
41
|
+
orgs = PartnersAPI::Organizations.fetch_with_app(@ctx)
|
|
42
|
+
org_id = if orgs.count == 1
|
|
43
|
+
orgs.first["id"]
|
|
44
|
+
else
|
|
45
|
+
CLI::UI::Prompt.ask(@ctx.message('core.connect.organization_select')) do |handler|
|
|
46
|
+
orgs.each do |org|
|
|
47
|
+
handler.option(
|
|
48
|
+
ctx.message('core.partners_api.org_name_and_id', org['businessName'], org['id'])
|
|
49
|
+
) { org["id"] }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
org = orgs.find { |o| o["id"] == org_id }
|
|
54
|
+
org
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def get_app(apps)
|
|
58
|
+
app_id = if apps.count == 1
|
|
59
|
+
apps.first["id"]
|
|
60
|
+
else
|
|
61
|
+
CLI::UI::Prompt.ask(@ctx.message('core.connect.app_select')) do |handler|
|
|
62
|
+
apps.each { |app| handler.option(app["title"]) { app["id"] } }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
apps.select { |app| app["id"] == app_id }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def get_shop(shops, id)
|
|
69
|
+
if shops.count == 1
|
|
70
|
+
shop = shops.first["shopDomain"]
|
|
71
|
+
elsif shops.count == 0
|
|
72
|
+
@ctx.puts(@ctx.message('core.connect.no_development_stores', id))
|
|
73
|
+
else
|
|
74
|
+
shop = CLI::UI::Prompt.ask(@ctx.message('core.connect.development_store_select')) do |handler|
|
|
75
|
+
shops.each { |s| handler.option(s["shopName"]) { s["shopDomain"] } }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
shop
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def write_env(app, shop, scopes, extra)
|
|
82
|
+
scopes = 'write_products,write_customers,write_draft_orders' if scopes.nil?
|
|
83
|
+
extra = {} if extra.nil?
|
|
84
|
+
|
|
85
|
+
Resources::EnvFile.new(
|
|
86
|
+
api_key: app.first["apiKey"],
|
|
87
|
+
secret: app.first["apiSecretKeys"].first["secret"],
|
|
88
|
+
shop: shop,
|
|
89
|
+
scopes: scopes,
|
|
90
|
+
extra: extra,
|
|
91
|
+
).write(@ctx)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def write_cli_yml(project_type, org_id)
|
|
95
|
+
ShopifyCli::Project.write(
|
|
96
|
+
@ctx,
|
|
97
|
+
project_type: project_type,
|
|
98
|
+
organization_id: org_id,
|
|
99
|
+
)
|
|
100
|
+
@ctx.done(@ctx.message('core.connect.cli_yml_saved'))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.help
|
|
104
|
+
ShopifyCli::Context.message('core.connect.help', ShopifyCli::TOOL_NAME)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
|
|
3
|
+
module ShopifyCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Create < ShopifyCli::Command
|
|
6
|
+
def self.call(args, command_name)
|
|
7
|
+
ProjectType.load_type(args[0]) unless args.empty?
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def call(args, command_name)
|
|
12
|
+
unless args.empty?
|
|
13
|
+
@ctx.puts(@ctx.message('core.create.error.invalid_app_type', args[0]))
|
|
14
|
+
return @ctx.puts(self.class.help)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
type_name = CLI::UI::Prompt.ask(@ctx.message('core.create.project_type_select')) do |handler|
|
|
18
|
+
self.class.all_visible_type.each do |type|
|
|
19
|
+
handler.option(type.project_name) { type.project_type }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
klass = ProjectType.load_type(type_name).create_command
|
|
24
|
+
klass.ctx = @ctx
|
|
25
|
+
klass.call(args, command_name, 'create')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.all_visible_type
|
|
29
|
+
ProjectType
|
|
30
|
+
.load_all
|
|
31
|
+
.select { |type| !type.hidden }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.help
|
|
35
|
+
project_types = all_visible_type.map(&:project_type).join(" | ")
|
|
36
|
+
ShopifyCli::Context.message('core.create.help', ShopifyCli::TOOL_NAME, project_types)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.extended_help
|
|
40
|
+
<<~HELP
|
|
41
|
+
#{
|
|
42
|
+
all_visible_type.map do |type|
|
|
43
|
+
type.create_command.help
|
|
44
|
+
end.join("\n")
|
|
45
|
+
}
|
|
46
|
+
HELP
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
|
|
3
|
+
module ShopifyCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Help < ShopifyCli::Command
|
|
6
|
+
def call(args, _name)
|
|
7
|
+
command = args.shift
|
|
8
|
+
if command && command != 'help'
|
|
9
|
+
if Registry.exist?(command)
|
|
10
|
+
cmd, _ = Registry.lookup_command(command)
|
|
11
|
+
subcmd, _ = cmd.subcommand_registry.lookup_command(args.first)
|
|
12
|
+
if subcmd
|
|
13
|
+
display_help(subcmd)
|
|
14
|
+
else
|
|
15
|
+
display_help(cmd)
|
|
16
|
+
end
|
|
17
|
+
return
|
|
18
|
+
else
|
|
19
|
+
@ctx.puts(@ctx.message('core.help.error.command_not_found', command))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
preamble = @ctx.message('core.help.preamble', ShopifyCli::TOOL_NAME)
|
|
24
|
+
@ctx.puts(preamble)
|
|
25
|
+
|
|
26
|
+
core_commands.each do |name, klass|
|
|
27
|
+
next if name == 'help'
|
|
28
|
+
@ctx.puts("{{command:#{name}}}: #{klass.help}\n")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
return unless inside_supported_project?
|
|
32
|
+
|
|
33
|
+
@ctx.puts("{{bold:Project: #{Project.project_name} (#{project_type_name})}}")
|
|
34
|
+
@ctx.puts("{{bold:Available commands for #{project_type_name} projects:}}\n\n")
|
|
35
|
+
|
|
36
|
+
local_commands.each do |name, klass|
|
|
37
|
+
next if name == 'help'
|
|
38
|
+
@ctx.puts("{{command:#{name}}}: #{klass.help}\n")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def project_type_name
|
|
45
|
+
ProjectType.load_type(Project.current_project_type).project_name
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def core_commands
|
|
49
|
+
resolved_commands
|
|
50
|
+
.select { |_name, c| !c.hidden }
|
|
51
|
+
.select { |name, _c| Commands.core_command?(name) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def local_commands
|
|
55
|
+
resolved_commands
|
|
56
|
+
.reject { |name, _c| Commands.core_command?(name) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def display_help(klass)
|
|
60
|
+
output = klass.help
|
|
61
|
+
if klass.respond_to?(:extended_help)
|
|
62
|
+
output += "\n"
|
|
63
|
+
output += klass.extended_help
|
|
64
|
+
end
|
|
65
|
+
@ctx.puts(output)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def resolved_commands
|
|
69
|
+
ShopifyCli::Commands::Registry
|
|
70
|
+
.resolved_commands
|
|
71
|
+
.sort
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def inside_supported_project?
|
|
75
|
+
Project.current_project_type && ProjectType.load_type(Project.current_project_type)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
|
|
3
|
+
module ShopifyCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Logout < ShopifyCli::Command
|
|
6
|
+
LOGIN_TOKENS = [
|
|
7
|
+
:identity_access_token, :identity_refresh_token, :identity_exchange_token,
|
|
8
|
+
:admin_access_token, :admin_refresh_token, :admin_exchange_token
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
def call(*)
|
|
12
|
+
LOGIN_TOKENS.each do |token|
|
|
13
|
+
ShopifyCli::DB.del(token) if ShopifyCli::DB.exists?(token)
|
|
14
|
+
end
|
|
15
|
+
@ctx.puts(@ctx.message('core.logout.success'))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.help
|
|
19
|
+
ShopifyCli::Context.message('core.logout.help', ShopifyCli::TOOL_NAME)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
require 'rbconfig'
|
|
3
|
+
|
|
4
|
+
module ShopifyCli
|
|
5
|
+
module Commands
|
|
6
|
+
class System < ShopifyCli::Command
|
|
7
|
+
hidden_command
|
|
8
|
+
|
|
9
|
+
def call(args, _name)
|
|
10
|
+
show_all_details = false
|
|
11
|
+
flag = args.shift
|
|
12
|
+
if flag && flag != 'all'
|
|
13
|
+
@ctx.puts(@ctx.message('core.system.error.unknown_option', flag))
|
|
14
|
+
@ctx.puts("\n" + self.class.help)
|
|
15
|
+
return
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
show_all_details = true if flag == 'all'
|
|
19
|
+
|
|
20
|
+
display_environment if show_all_details
|
|
21
|
+
|
|
22
|
+
display_cli_constants(show_all_details)
|
|
23
|
+
display_cli_ruby(show_all_details)
|
|
24
|
+
display_utility_commands(show_all_details)
|
|
25
|
+
display_project_commands(show_all_details)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.help
|
|
29
|
+
ShopifyCli::Context.message('core.system.help', ShopifyCli::TOOL_NAME)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def display_cli_constants(show_all_details)
|
|
35
|
+
cli_constants = %w(ROOT)
|
|
36
|
+
cli_constants_extra = %w(
|
|
37
|
+
PROJECT_TYPES_DIR
|
|
38
|
+
TEMP_DIR
|
|
39
|
+
CACHE_DIR
|
|
40
|
+
TOOL_CONFIG_PATH
|
|
41
|
+
LOG_FILE
|
|
42
|
+
DEBUG_LOG_FILE
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
cli_constants += cli_constants_extra if show_all_details
|
|
46
|
+
|
|
47
|
+
@ctx.puts(@ctx.message('core.system.header'))
|
|
48
|
+
cli_constants.each do |s|
|
|
49
|
+
@ctx.puts(" " + @ctx.message('core.system.const', s, ShopifyCli.const_get(s.to_sym)) + "\n")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def display_cli_ruby(_show_all_details)
|
|
54
|
+
rbconfig_constants = %w(host RUBY_VERSION_NAME)
|
|
55
|
+
|
|
56
|
+
@ctx.puts("\n" + @ctx.message('core.system.ruby_header', RbConfig.ruby))
|
|
57
|
+
rbconfig_constants.each do |s|
|
|
58
|
+
@ctx.puts(" " + @ctx.message('core.system.rb_config', RbConfig::CONFIG[s], s))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def display_utility_commands(_show_all_details)
|
|
63
|
+
commands = %w(git curl tar unzip)
|
|
64
|
+
|
|
65
|
+
@ctx.puts("\n" + @ctx.message('core.system.command_header'))
|
|
66
|
+
commands.each do |s|
|
|
67
|
+
output, status = @ctx.capture2e('which', s)
|
|
68
|
+
if status.success?
|
|
69
|
+
@ctx.puts(" " + @ctx.message('core.system.command_with_path', s, output))
|
|
70
|
+
else
|
|
71
|
+
@ctx.puts(" " + @ctx.message('core.system.command_not_found', s))
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def display_ngrok
|
|
77
|
+
ngrok_location = File.join(ShopifyCli::CACHE_DIR, 'ngrok')
|
|
78
|
+
if File.exist?(ngrok_location)
|
|
79
|
+
@ctx.puts(" " + @ctx.message('core.system.ngrok_available', ngrok_location))
|
|
80
|
+
else
|
|
81
|
+
@ctx.puts(" " + @ctx.message('core.system.ngrok_not_available'))
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def display_project_commands(_show_all_details)
|
|
86
|
+
case Project.current_project_type
|
|
87
|
+
when :node
|
|
88
|
+
display_project('Node.js', %w(npm node yarn))
|
|
89
|
+
when :rails
|
|
90
|
+
display_project('Rails', %w(gem rails rake ruby))
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def display_project(project_type, commands)
|
|
95
|
+
@ctx.puts("\n" + @ctx.message('core.system.project.header', project_type))
|
|
96
|
+
commands.each do |s|
|
|
97
|
+
output, status = @ctx.capture2e('which', s)
|
|
98
|
+
if status.success?
|
|
99
|
+
version_output, _ = @ctx.capture2e(s, '--version')
|
|
100
|
+
version = version_output.match(/(\d+\.[^\s]+)/)[0]
|
|
101
|
+
@ctx.puts(" " + @ctx.message('core.system.project.command_with_path', s, output.strip, version.strip))
|
|
102
|
+
else
|
|
103
|
+
@ctx.puts(" " + @ctx.message('core.system.project.command_not_found', s))
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
display_ngrok
|
|
107
|
+
display_project_environment
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def display_project_environment
|
|
111
|
+
@ctx.puts("\n " + @ctx.message('core.system.project.env_header'))
|
|
112
|
+
if File.exist?('./.env')
|
|
113
|
+
Project.current.env.to_h.each do |k, v|
|
|
114
|
+
display_value = if v.nil? || v.strip == ''
|
|
115
|
+
@ctx.message('core.system.project.env_not_set')
|
|
116
|
+
else
|
|
117
|
+
k.match(/^SHOPIFY_API/) ? "********" : v
|
|
118
|
+
end
|
|
119
|
+
@ctx.puts(" " + @ctx.message('core.system.project.env', k, display_value))
|
|
120
|
+
end
|
|
121
|
+
else
|
|
122
|
+
@ctx.puts(" " + @ctx.message('core.system.project.no_env'))
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def display_environment
|
|
127
|
+
@ctx.puts(@ctx.message('core.system.environment_header'))
|
|
128
|
+
%w(TERM SHELL PATH USING_SHOPIFY_CLI LANG).each do |k|
|
|
129
|
+
@ctx.puts(" " + @ctx.message('core.system.env', k, ENV[k])) unless ENV[k].nil?
|
|
130
|
+
end
|
|
131
|
+
@ctx.puts("")
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'shopify_cli'
|
|
2
|
+
|
|
3
|
+
module ShopifyCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Version < ShopifyCli::Command
|
|
6
|
+
def self.help
|
|
7
|
+
ShopifyCli::Context.message('core.version.help', ShopifyCli::TOOL_NAME)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(_args, _name)
|
|
11
|
+
@ctx.puts(ShopifyCli::VERSION.to_s)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'shopify_cli'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'rbconfig'
|
|
5
|
+
|
|
6
|
+
module ShopifyCli
|
|
7
|
+
##
|
|
8
|
+
# Context captures a lot about the current running command. It captures the
|
|
9
|
+
# environment, output, system and file operations. It is useful to have the
|
|
10
|
+
# context especially in tests so that you have a single access point to these
|
|
11
|
+
# resoures.
|
|
12
|
+
#
|
|
13
|
+
class Context
|
|
14
|
+
class << self
|
|
15
|
+
attr_reader :messages
|
|
16
|
+
|
|
17
|
+
# adds a new set of messages to be used by the CLI. The messages are expected to be a hash of symbols, and
|
|
18
|
+
# multiple levels are allowed. When fetching messages a dot notation is used to separate different levels. See
|
|
19
|
+
# Context::message for more information.
|
|
20
|
+
#
|
|
21
|
+
# #### Parameters
|
|
22
|
+
# * `messages` - Hash containing the new keys to register
|
|
23
|
+
def load_messages(messages)
|
|
24
|
+
@messages ||= {}
|
|
25
|
+
@messages = @messages.merge(messages) do |key|
|
|
26
|
+
Context.new.abort("Message key '#{key}' already exists and cannot be registered") if @messages.key?(key)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# returns the user-facing messages for the given key. Returns the key if no message is available.
|
|
31
|
+
#
|
|
32
|
+
# #### Parameters
|
|
33
|
+
# * `key` - a symbol representing the message
|
|
34
|
+
# * `params` - the parameters to format the string with
|
|
35
|
+
def message(key, *params)
|
|
36
|
+
key_parts = key.split('.').map(&:to_sym)
|
|
37
|
+
str = Context.messages.dig(*key_parts)
|
|
38
|
+
str ? str % params : key
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# is the directory root that the current command is running in. If you want to
|
|
43
|
+
# simulate a `cd` for the file operations, you can change this variable.
|
|
44
|
+
attr_accessor :root
|
|
45
|
+
# is an accessor for environment variables. These variables are also added to
|
|
46
|
+
# any command run by the context.
|
|
47
|
+
attr_accessor :env
|
|
48
|
+
|
|
49
|
+
def initialize(root: Dir.pwd, env: ($original_env || ENV).clone) # :nodoc:
|
|
50
|
+
self.root = root
|
|
51
|
+
self.env = env
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# will return which operating system that the cli is running on [:mac, :linux]
|
|
55
|
+
def os
|
|
56
|
+
host = uname
|
|
57
|
+
return :mac if /darwin/.match(host)
|
|
58
|
+
return :linux if /linux/.match(host)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# will return true if the cli is running on an apple computer.
|
|
62
|
+
def mac?
|
|
63
|
+
os == :mac
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# will return true if the cli is running on a linux distro
|
|
67
|
+
def linux?
|
|
68
|
+
os == :linux
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# will return true if the cli is being run from an installation, and not a
|
|
72
|
+
# development instance. The gem installation will not have a 'test' directory.
|
|
73
|
+
# See `#development?` for checking for development environment.
|
|
74
|
+
#
|
|
75
|
+
def system?
|
|
76
|
+
!Dir.exist?(File.join(ShopifyCli::ROOT, 'test'))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# will return true if the cli is running on your development instance.
|
|
80
|
+
#
|
|
81
|
+
def development?
|
|
82
|
+
!system? && !testing?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# will return true while tests are running, either locally or on CI
|
|
86
|
+
def testing?
|
|
87
|
+
ci? || ENV['TEST']
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# will return true if the cli is being tested on CI
|
|
92
|
+
def ci?
|
|
93
|
+
ENV['CI']
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# get a environment variable value by name.
|
|
97
|
+
#
|
|
98
|
+
# #### Parameters
|
|
99
|
+
# * `name` - the name of the environment variable that you want to fetch
|
|
100
|
+
#
|
|
101
|
+
# #### Returns
|
|
102
|
+
# * `value` - will return the value, or nil if the variable does not exist
|
|
103
|
+
#
|
|
104
|
+
def getenv(name)
|
|
105
|
+
v = @env[name]
|
|
106
|
+
v == '' ? nil : v
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# set a environment variable value by name.
|
|
110
|
+
#
|
|
111
|
+
# #### Parameters
|
|
112
|
+
# * `key` - the name of the environment variable that you want to set
|
|
113
|
+
# * `value` - the value of the variable
|
|
114
|
+
#
|
|
115
|
+
def setenv(key, value)
|
|
116
|
+
@env[key] = value
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# will write/overwrite a file with the provided contents, relative to the context root
|
|
120
|
+
# unless the file path is absolute.
|
|
121
|
+
#
|
|
122
|
+
# #### Parameters
|
|
123
|
+
# * `fname` - filename of the file that you are writing, relative to root unless it is absolute.
|
|
124
|
+
# * `content` - the body contents of the file that you are writing
|
|
125
|
+
#
|
|
126
|
+
# #### Example
|
|
127
|
+
#
|
|
128
|
+
# @ctx.write('new.txt', 'hello world')
|
|
129
|
+
#
|
|
130
|
+
def write(fname, content)
|
|
131
|
+
File.write(ctx_path(fname), content)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# will rename a file from one place to another, relative to the command root
|
|
135
|
+
# unless the path is absolute.
|
|
136
|
+
#
|
|
137
|
+
# #### Parameters
|
|
138
|
+
# * `from` - the path of the original file
|
|
139
|
+
# * `to` - the destination path
|
|
140
|
+
#
|
|
141
|
+
def rename(from, to)
|
|
142
|
+
File.rename(ctx_path(from), ctx_path(to))
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# will remove a plain file from the FS, the filepath is relative to the command
|
|
146
|
+
# root unless absolute.
|
|
147
|
+
#
|
|
148
|
+
# #### Parameters
|
|
149
|
+
# * `fname` - the file path relative to the context root to remove from the FS
|
|
150
|
+
#
|
|
151
|
+
def rm(fname)
|
|
152
|
+
FileUtils.rm(ctx_path(fname))
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# will remove a directory from the FS, the filepath is relative to the command
|
|
156
|
+
# root unless absolute
|
|
157
|
+
#
|
|
158
|
+
# #### Parameters
|
|
159
|
+
# * `fname` - the file path to a directory, relative to the context root to remove from the FS
|
|
160
|
+
#
|
|
161
|
+
def rm_r(fname)
|
|
162
|
+
FileUtils.rm_r(ctx_path(fname))
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# will create a directory, recursively if it does not exist. So if you create
|
|
166
|
+
# a directory `foo/bar/dun`, this will also create the directories `foo` and
|
|
167
|
+
# `foo/bar` if they do not exist. The path will be made relative to the command
|
|
168
|
+
# root unless absolute
|
|
169
|
+
#
|
|
170
|
+
# #### Parameters
|
|
171
|
+
# * `path` - file path of the directory that you want to create
|
|
172
|
+
#
|
|
173
|
+
def mkdir_p(path)
|
|
174
|
+
FileUtils.mkdir_p(path)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# will output to the console a link for the user to either copy/paste
|
|
178
|
+
# or click on.
|
|
179
|
+
#
|
|
180
|
+
# #### Parameters
|
|
181
|
+
# * `uri` - a http URI to open in a browser
|
|
182
|
+
#
|
|
183
|
+
def open_url!(uri)
|
|
184
|
+
help = message('core.context.open_url', uri)
|
|
185
|
+
puts(help)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# will output a message, prefixed by a yellow star, indicating that task
|
|
189
|
+
# started.
|
|
190
|
+
#
|
|
191
|
+
# #### Parameters
|
|
192
|
+
# * `text` - a string message to output
|
|
193
|
+
#
|
|
194
|
+
def print_task(text)
|
|
195
|
+
puts "{{yellow:*}} #{text}"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# a wrapper around Kernel.puts to allow for easy formatting
|
|
199
|
+
#
|
|
200
|
+
# #### Parameters
|
|
201
|
+
# * `text` - a string message to output
|
|
202
|
+
#
|
|
203
|
+
def puts(*args)
|
|
204
|
+
Kernel.puts(CLI::UI.fmt(*args))
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# outputs a message, prefixed by a checkmark indicating that something completed
|
|
208
|
+
#
|
|
209
|
+
# #### Parameters
|
|
210
|
+
# * `text` - a string message to output
|
|
211
|
+
#
|
|
212
|
+
def done(text)
|
|
213
|
+
puts("{{v}} #{text}")
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# aborts the current running command and outputs an error message, prefixed
|
|
217
|
+
# by a red x
|
|
218
|
+
#
|
|
219
|
+
# #### Parameters
|
|
220
|
+
# * `text` - a string message to output
|
|
221
|
+
#
|
|
222
|
+
def abort(text)
|
|
223
|
+
raise ShopifyCli::Abort, "{{x}} #{text}"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# outputs a message, prefixed by a red `DEBUG` tag. This will only output to
|
|
227
|
+
# the console if you have `DEBUG=1` set in your shell environment.
|
|
228
|
+
#
|
|
229
|
+
# #### Parameters
|
|
230
|
+
# * `text` - a string message to output
|
|
231
|
+
#
|
|
232
|
+
def debug(text)
|
|
233
|
+
puts("{{red:DEBUG}} #{text}") if getenv('DEBUG')
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# proxy call to Context.message.
|
|
237
|
+
#
|
|
238
|
+
# #### Parameters
|
|
239
|
+
# * `key` - a symbol representing the message
|
|
240
|
+
# * `params` - the parameters to format the string with
|
|
241
|
+
def message(key, *params)
|
|
242
|
+
Context.message(key, *params)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# will grab the host info of the computer running the cli. This indicates the
|
|
246
|
+
# computer architecture and operating system
|
|
247
|
+
def uname
|
|
248
|
+
@uname ||= RbConfig::CONFIG["host"]
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Execute a command in the user's environment
|
|
252
|
+
# Outputs result of the command without capturing it
|
|
253
|
+
#
|
|
254
|
+
# #### Parameters
|
|
255
|
+
# - `*args`: A splat of arguments evaluated as a command. (e.g. `'rm', folder` is equivalent to `rm #{folder}`)
|
|
256
|
+
# - `**kwargs`: additional keyword arguments to pass to Process.spawn
|
|
257
|
+
#
|
|
258
|
+
# #### Returns
|
|
259
|
+
# - `status`: boolean success status of the command execution
|
|
260
|
+
#
|
|
261
|
+
# #### Usage
|
|
262
|
+
#
|
|
263
|
+
# stat = @ctx.system('ls', 'a_folder')
|
|
264
|
+
#
|
|
265
|
+
def system(*args, **kwargs)
|
|
266
|
+
CLI::Kit::System.system(*args, env: @env, **kwargs)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Execute a command in the user's environment
|
|
270
|
+
# This is meant to be largely equivalent to backticks, only with the env passed in.
|
|
271
|
+
# Captures the results of the command without output to the console
|
|
272
|
+
#
|
|
273
|
+
# #### Parameters
|
|
274
|
+
# - `*args`: A splat of arguments evaluated as a command. (e.g. `'rm', folder` is equivalent to `rm #{folder}`)
|
|
275
|
+
# - `**kwargs`: additional arguments to pass to Open3.capture2
|
|
276
|
+
#
|
|
277
|
+
# #### Returns
|
|
278
|
+
# - `output`: output (STDOUT) of the command execution
|
|
279
|
+
# - `status`: boolean success status of the command execution
|
|
280
|
+
#
|
|
281
|
+
# #### Usage
|
|
282
|
+
#
|
|
283
|
+
# out, stat = @ctx.capture2('ls', 'a_folder')
|
|
284
|
+
#
|
|
285
|
+
def capture2(*args, **kwargs)
|
|
286
|
+
CLI::Kit::System.capture2(*args, env: @env, **kwargs)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Execute a command in the user's environment
|
|
290
|
+
# This is meant to be largely equivalent to backticks, only with the env passed in.
|
|
291
|
+
# Captures the results of the command without output to the console
|
|
292
|
+
#
|
|
293
|
+
# #### Parameters
|
|
294
|
+
# - `*args`: A splat of arguments evaluated as a command. (e.g. `'rm', folder` is equivalent to `rm #{folder}`)
|
|
295
|
+
# - `**kwargs`: additional arguments to pass to Open3.capture2e
|
|
296
|
+
#
|
|
297
|
+
# #### Returns
|
|
298
|
+
# - `output`: output (STDOUT merged with STDERR) of the command execution
|
|
299
|
+
# - `status`: boolean success status of the command execution
|
|
300
|
+
#
|
|
301
|
+
# #### Usage
|
|
302
|
+
#
|
|
303
|
+
# out_and_err, stat = @ctx.capture2e('ls', 'a_folder')
|
|
304
|
+
#
|
|
305
|
+
def capture2e(*args, **kwargs)
|
|
306
|
+
CLI::Kit::System.capture2e(*args, env: @env, **kwargs)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Execute a command in the user's environment
|
|
310
|
+
# This is meant to be largely equivalent to backticks, only with the env passed in.
|
|
311
|
+
# Captures the results of the command without output to the console
|
|
312
|
+
#
|
|
313
|
+
# #### Parameters
|
|
314
|
+
# - `*args`: A splat of arguments evaluated as a command. (e.g. `'rm', folder` is equivalent to `rm #{folder}`)
|
|
315
|
+
# - `**kwargs`: additional arguments to pass to Open3.capture3
|
|
316
|
+
#
|
|
317
|
+
# #### Returns
|
|
318
|
+
# - `output`: STDOUT of the command execution
|
|
319
|
+
# - `error`: STDERR of the command execution
|
|
320
|
+
# - `status`: boolean success status of the command execution
|
|
321
|
+
#
|
|
322
|
+
# #### Usage
|
|
323
|
+
#
|
|
324
|
+
# out, err, stat = @ctx.capture3('ls', 'a_folder')
|
|
325
|
+
#
|
|
326
|
+
def capture3(*args, **kwargs)
|
|
327
|
+
CLI::Kit::System.capture3(*args, env: @env, **kwargs)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# captures the info signal (ctrl-T) and provide a handler to it.
|
|
331
|
+
#
|
|
332
|
+
# #### Example
|
|
333
|
+
#
|
|
334
|
+
# @ctx.on_siginfo do
|
|
335
|
+
# @ctx.open_url!("http://google.com")
|
|
336
|
+
# end
|
|
337
|
+
#
|
|
338
|
+
def on_siginfo
|
|
339
|
+
# Reset any previous SIGINFO handling we had so the only action we take is the given block
|
|
340
|
+
trap('INFO', 'DEFAULT')
|
|
341
|
+
|
|
342
|
+
fork do
|
|
343
|
+
begin
|
|
344
|
+
r, w = IO.pipe
|
|
345
|
+
@signal = false
|
|
346
|
+
trap('SIGINFO') do
|
|
347
|
+
@signal = true
|
|
348
|
+
w.write(0)
|
|
349
|
+
end
|
|
350
|
+
while r.read(1)
|
|
351
|
+
next unless @signal
|
|
352
|
+
@signal = false
|
|
353
|
+
yield
|
|
354
|
+
end
|
|
355
|
+
rescue Interrupt
|
|
356
|
+
exit(0)
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
private
|
|
362
|
+
|
|
363
|
+
def ctx_path(fname)
|
|
364
|
+
require 'pathname'
|
|
365
|
+
if Pathname.new(fname).absolute?
|
|
366
|
+
fname
|
|
367
|
+
else
|
|
368
|
+
File.join(root, fname)
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
end
|