shopify-cli 1.0.2 → 1.1.1
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/.travis.yml +3 -2
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -13
- data/bin/load_shopify.rb +3 -1
- data/bin/shopify +2 -0
- data/docs/Gemfile.lock +23 -13
- data/docs/getting-started/index.md +3 -2
- data/docs/getting-started/install/index.md +55 -9
- data/docs/getting-started/uninstall/index.md +1 -1
- data/docs/getting-started/upgrade/index.md +8 -4
- data/ext/shopify-cli/extconf.rb +40 -20
- data/lib/project_types/extension/cli.rb +1 -1
- data/lib/project_types/extension/commands/build.rb +1 -1
- data/lib/project_types/extension/models/type.rb +1 -0
- data/lib/project_types/extension/tasks/create_extension.rb +1 -1
- data/lib/project_types/extension/tasks/get_app.rb +1 -1
- data/lib/project_types/extension/tasks/update_draft.rb +1 -1
- data/lib/project_types/node/commands/create.rb +4 -4
- data/lib/project_types/node/commands/deploy/heroku.rb +6 -1
- data/lib/project_types/node/commands/generate/billing.rb +7 -5
- data/lib/project_types/node/commands/generate/page.rb +9 -5
- data/lib/project_types/node/commands/generate/webhook.rb +5 -1
- data/lib/project_types/node/messages/messages.rb +1 -0
- data/lib/project_types/rails/cli.rb +0 -1
- data/lib/project_types/rails/commands/create.rb +52 -4
- data/lib/project_types/rails/commands/generate.rb +1 -0
- data/lib/project_types/rails/commands/generate/webhook.rb +3 -2
- data/lib/project_types/rails/commands/serve.rb +6 -2
- data/lib/project_types/rails/gem.rb +61 -6
- data/lib/project_types/rails/messages/messages.rb +27 -11
- data/lib/project_types/script/cli.rb +2 -3
- data/lib/project_types/script/commands/create.rb +5 -9
- data/lib/project_types/script/commands/disable.rb +4 -15
- data/lib/project_types/script/commands/enable.rb +37 -13
- data/lib/project_types/script/commands/push.rb +8 -13
- data/lib/project_types/script/config/extension_points.yml +9 -3
- data/lib/project_types/script/errors.rb +8 -0
- data/lib/project_types/script/forms/create.rb +1 -1
- data/lib/project_types/script/layers/application/create_script.rb +7 -6
- data/lib/project_types/script/layers/application/disable_script.rb +9 -7
- data/lib/project_types/script/layers/application/enable_script.rb +11 -9
- data/lib/project_types/script/layers/application/push_script.rb +6 -4
- data/lib/project_types/script/layers/domain/errors.rb +2 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +2 -2
- data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/errors.rb +2 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +8 -2
- data/lib/project_types/script/messages/messages.rb +25 -31
- data/lib/project_types/script/script_project.rb +6 -2
- data/lib/project_types/script/templates/ts/as-pect.config.js +6 -0
- data/lib/project_types/script/ui/error_handler.rb +8 -0
- data/lib/project_types/script/ui/printing_spinner.rb +75 -0
- data/lib/rubygems_plugin.rb +18 -10
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +1 -1
- data/lib/shopify-cli/admin_api/schema.rb +20 -18
- data/lib/shopify-cli/command.rb +14 -11
- data/lib/shopify-cli/commands.rb +1 -0
- data/lib/shopify-cli/commands/config.rb +44 -0
- data/lib/shopify-cli/commands/connect.rb +8 -69
- data/lib/shopify-cli/commands/create.rb +2 -2
- data/lib/shopify-cli/commands/help.rb +1 -1
- data/lib/shopify-cli/commands/system.rb +22 -13
- data/lib/shopify-cli/context.rb +28 -0
- data/lib/shopify-cli/core.rb +0 -1
- data/lib/shopify-cli/core/entry_point.rb +1 -1
- data/lib/shopify-cli/core/executor.rb +3 -5
- data/lib/shopify-cli/core/monorail.rb +1 -1
- data/lib/shopify-cli/db.rb +1 -1
- data/lib/shopify-cli/feature.rb +97 -0
- data/lib/shopify-cli/heroku.rb +21 -5
- data/lib/shopify-cli/js_deps.rb +2 -2
- data/lib/shopify-cli/js_system.rb +2 -2
- data/lib/shopify-cli/messages/messages.rb +40 -12
- data/lib/shopify-cli/partners_api/organizations.rb +7 -7
- data/lib/shopify-cli/process_supervision.rb +60 -21
- data/lib/shopify-cli/project.rb +14 -6
- data/lib/shopify-cli/project_type.rb +5 -7
- data/lib/shopify-cli/sub_command.rb +1 -0
- data/lib/shopify-cli/task.rb +2 -2
- data/lib/shopify-cli/tasks.rb +11 -4
- data/lib/shopify-cli/tasks/ensure_env.rb +72 -16
- data/lib/shopify-cli/tasks/update_dashboard_urls.rb +4 -3
- data/lib/shopify-cli/tunnel.rb +53 -14
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +36 -9
- data/shopify-cli.gemspec +4 -1
- data/vendor/deps/cli-kit/REVISION +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit.rb +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +2 -2
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +12 -6
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +9 -11
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +8 -2
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +7 -7
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +48 -17
- data/vendor/deps/cli-ui/REVISION +1 -1
- data/vendor/deps/cli-ui/lib/cli/ui.rb +5 -4
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +9 -3
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -2
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +13 -5
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +29 -2
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +21 -10
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +63 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +11 -2
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -3
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +6 -8
- data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +2 -0
- data/vendor/gen/lib/gen.rb +39 -0
- data/vendor/gen/lib/gen/commands.rb +18 -0
- data/vendor/gen/lib/gen/commands/help.rb +20 -0
- data/vendor/gen/lib/gen/commands/new.rb +21 -0
- data/vendor/gen/lib/gen/entry_point.rb +10 -0
- data/vendor/gen/lib/gen/generator.rb +165 -0
- data/vendor/gen/template/.gitignore +2 -0
- data/vendor/gen/template/Gemfile +10 -0
- data/vendor/gen/template/README.md +1 -0
- data/vendor/gen/template/bin/testunit +23 -0
- data/vendor/gen/template/bin/update-deps +97 -0
- data/vendor/gen/template/dev-gems.yml +3 -0
- data/vendor/gen/template/dev-vendor.yml +4 -0
- data/vendor/gen/template/exe/__app__-gems +17 -0
- data/vendor/gen/template/exe/__app__-vendor +18 -0
- data/vendor/gen/template/lib/__app__.rb +33 -0
- data/vendor/gen/template/lib/__app__/commands.rb +18 -0
- data/vendor/gen/template/lib/__app__/commands/example.rb +19 -0
- data/vendor/gen/template/lib/__app__/commands/help.rb +21 -0
- data/vendor/gen/template/lib/__app__/entry_point.rb +10 -0
- data/vendor/gen/template/test/example_test.rb +17 -0
- data/vendor/gen/template/test/test_helper.rb +22 -0
- metadata +28 -6
- data/Vagrantfile +0 -17
- data/lib/project_types/script/forms/enable.rb +0 -24
- data/lib/project_types/script/forms/push.rb +0 -19
- data/lib/project_types/script/forms/script_form.rb +0 -66
data/lib/shopify-cli/js_deps.rb
CHANGED
|
@@ -69,7 +69,7 @@ module ShopifyCli
|
|
|
69
69
|
deps = parse_dependencies
|
|
70
70
|
errors = nil
|
|
71
71
|
|
|
72
|
-
spinner_title = ctx.message('core.js_deps.
|
|
72
|
+
spinner_title = ctx.message('core.js_deps.installing', @system.package_manager)
|
|
73
73
|
success = CLI::UI::Spinner.spin(spinner_title, auto_debrief: false) do |spinner|
|
|
74
74
|
_, errors, status = CLI::Kit::System.capture3(*cmd, env: @ctx.env, chdir: ctx.root)
|
|
75
75
|
update_spinner_title_and_status(spinner, status, deps)
|
|
@@ -81,7 +81,7 @@ module ShopifyCli
|
|
|
81
81
|
|
|
82
82
|
def update_spinner_title_and_status(spinner, status, deps)
|
|
83
83
|
if status.success?
|
|
84
|
-
spinner.update_title(ctx.message('core.js_deps.
|
|
84
|
+
spinner.update_title(ctx.message('core.js_deps.installed', deps.size))
|
|
85
85
|
else
|
|
86
86
|
spinner.update_title(ctx.message('core.js_deps.error.install_spinner_error', deps.size))
|
|
87
87
|
CLI::UI::Spinner::TASK_FAILED
|
|
@@ -64,8 +64,8 @@ module ShopifyCli
|
|
|
64
64
|
#
|
|
65
65
|
def yarn?
|
|
66
66
|
@has_yarn ||= begin
|
|
67
|
-
|
|
68
|
-
File.exist?(File.join(ctx.root, 'yarn.lock')) &&
|
|
67
|
+
cmd_path = @ctx.which('yarn')
|
|
68
|
+
File.exist?(File.join(ctx.root, 'yarn.lock')) && !cmd_path.nil?
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
|
|
@@ -16,13 +16,6 @@ module ShopifyCli
|
|
|
16
16
|
already_connected_warning: "{{yellow:! This app appears to be already connected}}",
|
|
17
17
|
connected: "{{v}} Project now connected to {{green:%s}}",
|
|
18
18
|
project_type_select: "What type of project would you like to connect?",
|
|
19
|
-
organization_select: "To which partner organization does this project belong?",
|
|
20
|
-
app_select: "To which app does this project belong?",
|
|
21
|
-
no_development_stores: <<~MESSAGE,
|
|
22
|
-
No development stores available.
|
|
23
|
-
Visit {{underline:https://partners.shopify.com/%d/stores}} to create one
|
|
24
|
-
MESSAGE
|
|
25
|
-
development_store_select: "Which development store would you like to use?",
|
|
26
19
|
cli_yml_saved: ".shopify-cli.yml saved to project root",
|
|
27
20
|
},
|
|
28
21
|
|
|
@@ -52,6 +45,19 @@ module ShopifyCli
|
|
|
52
45
|
saved: "%s saved to project root",
|
|
53
46
|
},
|
|
54
47
|
|
|
48
|
+
config: {
|
|
49
|
+
help: <<~HELP,
|
|
50
|
+
Change configuration of how the CLI operates
|
|
51
|
+
Usage: {{command:%s config [ feature ] [ feature_name ] }}
|
|
52
|
+
HELP
|
|
53
|
+
feature: {
|
|
54
|
+
enabled: "{{v}} feature {{green:%s}} was enabled",
|
|
55
|
+
disabled: "{{v}} feature {{green:%s}} was disabled",
|
|
56
|
+
is_enabled: "{{v}} feature {{green:%s}} is enabled",
|
|
57
|
+
is_disabled: "{{v}} feature {{green:%s}} is disabled",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
|
|
55
61
|
git: {
|
|
56
62
|
error: {
|
|
57
63
|
directory_exists: "Project directory already exists. Please create a project with a new name.",
|
|
@@ -232,9 +238,21 @@ module ShopifyCli
|
|
|
232
238
|
|
|
233
239
|
tasks: {
|
|
234
240
|
ensure_env: {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
organization_select: "To which partner organization does this project belong?",
|
|
242
|
+
no_development_stores: <<~MESSAGE,
|
|
243
|
+
No development stores available.
|
|
244
|
+
Visit {{underline:https://partners.shopify.com/%d/stores}} to create one
|
|
245
|
+
MESSAGE
|
|
246
|
+
development_store_select: "Which development store would you like to use?",
|
|
247
|
+
app_select: "To which app does this project belong?",
|
|
248
|
+
no_apps: 'You have no apps to connect to, creating a new app.',
|
|
249
|
+
app_name: "App name",
|
|
250
|
+
app_type: {
|
|
251
|
+
select: "What type of app are you building?",
|
|
252
|
+
select_public: "Public: An app built for a wide merchant audience.",
|
|
253
|
+
select_custom: "Custom: An app custom built for a single client.",
|
|
254
|
+
selected: "App type {{green:%s}}",
|
|
255
|
+
},
|
|
238
256
|
},
|
|
239
257
|
ensure_dev_store: {
|
|
240
258
|
could_not_verify_store: "Couldn't verify your store %s",
|
|
@@ -271,12 +289,22 @@ module ShopifyCli
|
|
|
271
289
|
error: {
|
|
272
290
|
stop: "ngrok tunnel could not be stopped. Try running {{command:killall -9 ngrok}}",
|
|
273
291
|
url_fetch_failure: "Unable to fetch external url",
|
|
292
|
+
prereq_command_required: "%1$s is required for installing ngrok. Please install %1$s using the appropriate"\
|
|
293
|
+
" package manager for your system.",
|
|
274
294
|
},
|
|
275
295
|
|
|
276
|
-
stopped: "{{green:x}} ngrok tunnel stopped",
|
|
277
296
|
not_running: "{{green:x}} ngrok tunnel not running",
|
|
278
|
-
|
|
297
|
+
signup_suggestion: <<~MESSAGE,
|
|
298
|
+
{{*}} To avoid tunnels that timeout, it is recommended to signup for a free ngrok
|
|
299
|
+
account at {{underline:https://ngrok.com/signup}}. After you signup, install your
|
|
300
|
+
personalized authorization token using {{command:%s tunnel auth <token>}}.
|
|
301
|
+
MESSAGE
|
|
279
302
|
start: "{{v}} ngrok tunnel running at {{underline:%s}}",
|
|
303
|
+
start_with_account: "{{v}} ngrok tunnel running at {{underline:%s}}, with account %s",
|
|
304
|
+
stopped: "{{green:x}} ngrok tunnel stopped",
|
|
305
|
+
timed_out: "{{x}} ngrok tunnel has timed out, restarting ...",
|
|
306
|
+
will_timeout: "{{*}} This tunnel will timeout in {{red:%s}}",
|
|
307
|
+
prereq_command_location: "%s @ %s",
|
|
280
308
|
},
|
|
281
309
|
|
|
282
310
|
version: {
|
|
@@ -4,25 +4,25 @@ module ShopifyCli
|
|
|
4
4
|
class << self
|
|
5
5
|
def fetch_all(ctx)
|
|
6
6
|
resp = PartnersAPI.query(ctx, 'all_organizations')
|
|
7
|
-
resp
|
|
8
|
-
org['stores'] = org
|
|
7
|
+
(resp.dig('data', 'organizations', 'nodes') || []).map do |org|
|
|
8
|
+
org['stores'] = (org.dig('stores', 'nodes') || [])
|
|
9
9
|
org
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def fetch(ctx, id:)
|
|
14
14
|
resp = PartnersAPI.query(ctx, 'find_organization', id: id)
|
|
15
|
-
org = resp
|
|
15
|
+
org = resp.dig('data', 'organizations', 'nodes').first
|
|
16
16
|
return nil if org.nil?
|
|
17
|
-
org['stores'] = org
|
|
17
|
+
org['stores'] = (org.dig('stores', 'nodes') || [])
|
|
18
18
|
org
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def fetch_with_app(ctx)
|
|
22
22
|
resp = PartnersAPI.query(ctx, 'all_orgs_with_apps')
|
|
23
|
-
resp
|
|
24
|
-
org['stores'] = org
|
|
25
|
-
org['apps'] = org
|
|
23
|
+
(resp.dig('data', 'organizations', 'nodes') || []).map do |org|
|
|
24
|
+
org['stores'] = (org.dig('stores', 'nodes') || [])
|
|
25
|
+
org['apps'] = (org.dig('apps', 'nodes') || [])
|
|
26
26
|
org
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -5,13 +5,10 @@ module ShopifyCli
|
|
|
5
5
|
# ProcessSupervision wraps a running process spawned by `exec` and keeps track
|
|
6
6
|
# if its `pid` and keeps a log file for it as well
|
|
7
7
|
class ProcessSupervision
|
|
8
|
-
# is the directory where the pid and logfile are kept
|
|
9
|
-
RUN_DIR = File.join(ShopifyCli::CACHE_DIR, 'sv')
|
|
10
|
-
|
|
11
8
|
# a string or a symbol to identify this process by
|
|
12
9
|
attr_reader :identifier
|
|
13
10
|
# process ID for the running process
|
|
14
|
-
|
|
11
|
+
attr_accessor :pid
|
|
15
12
|
# starttime of the process
|
|
16
13
|
attr_reader :time
|
|
17
14
|
# filepath to the pidfile for this process
|
|
@@ -20,6 +17,11 @@ module ShopifyCli
|
|
|
20
17
|
attr_reader :log_path
|
|
21
18
|
|
|
22
19
|
class << self
|
|
20
|
+
def run_dir
|
|
21
|
+
# is the directory where the pid and logfile are kept
|
|
22
|
+
File.join(ShopifyCli.cache_dir, 'sv')
|
|
23
|
+
end
|
|
24
|
+
|
|
23
25
|
##
|
|
24
26
|
# Will find and create a new instance of ProcessSupervision for a running process
|
|
25
27
|
# if it is currently running. It will return nil if the process is not running.
|
|
@@ -34,7 +36,7 @@ module ShopifyCli
|
|
|
34
36
|
# will be nil if the process is not running.
|
|
35
37
|
#
|
|
36
38
|
def for_ident(identifier)
|
|
37
|
-
pid, time = File.read(File.join(
|
|
39
|
+
pid, time = File.read(File.join(ShopifyCli::ProcessSupervision.run_dir, "#{identifier}.pid")).split(':')
|
|
38
40
|
new(identifier, pid: Integer(pid), time: time)
|
|
39
41
|
rescue Errno::ENOENT
|
|
40
42
|
nil
|
|
@@ -56,15 +58,37 @@ module ShopifyCli
|
|
|
56
58
|
#
|
|
57
59
|
def start(identifier, args)
|
|
58
60
|
return for_ident(identifier) if running?(identifier)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
|
|
62
|
+
# Windows doesn't support forking process without extra gems, so we resort to spawning a new child process -
|
|
63
|
+
# that means that it dies along with the original process if it is interrupted. On UNIX, we fork the process so
|
|
64
|
+
# that it doesn't have to be restarted on every run.
|
|
65
|
+
if Context.new.windows?
|
|
66
|
+
pid_file = new(identifier)
|
|
67
|
+
|
|
68
|
+
# Make sure the file exists and is empty, otherwise Windows fails
|
|
69
|
+
File.open(pid_file.log_path, 'w') {}
|
|
70
|
+
pid = Process.spawn(
|
|
71
|
+
*args,
|
|
72
|
+
out: pid_file.log_path,
|
|
73
|
+
err: pid_file.log_path,
|
|
74
|
+
in: Context.new.windows? ? "nul" : "/dev/null",
|
|
75
|
+
)
|
|
76
|
+
pid_file.pid = pid
|
|
61
77
|
pid_file.write
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
|
|
79
|
+
Process.detach(pid)
|
|
80
|
+
else
|
|
81
|
+
fork do
|
|
82
|
+
pid_file = new(identifier, pid: Process.pid)
|
|
83
|
+
pid_file.write
|
|
84
|
+
STDOUT.reopen(pid_file.log_path, "w")
|
|
85
|
+
STDERR.reopen(pid_file.log_path, "w")
|
|
86
|
+
STDIN.reopen("/dev/null", "r")
|
|
87
|
+
Process.setsid
|
|
88
|
+
exec(*args)
|
|
89
|
+
end
|
|
67
90
|
end
|
|
91
|
+
|
|
68
92
|
sleep(0.1)
|
|
69
93
|
for_ident(identifier)
|
|
70
94
|
end
|
|
@@ -104,24 +128,29 @@ module ShopifyCli
|
|
|
104
128
|
end
|
|
105
129
|
end
|
|
106
130
|
|
|
107
|
-
def initialize(identifier, pid
|
|
131
|
+
def initialize(identifier, pid: nil, time: Time.now.strftime('%s')) # :nodoc:
|
|
108
132
|
@identifier = identifier
|
|
109
133
|
@pid = pid
|
|
110
134
|
@time = time
|
|
111
|
-
|
|
112
|
-
@
|
|
135
|
+
FileUtils.mkdir_p(ShopifyCli::ProcessSupervision.run_dir)
|
|
136
|
+
@pid_path = File.join(ShopifyCli::ProcessSupervision.run_dir, "#{identifier}.pid")
|
|
137
|
+
@log_path = File.join(ShopifyCli::ProcessSupervision.run_dir, "#{identifier}.log")
|
|
113
138
|
end
|
|
114
139
|
|
|
115
140
|
##
|
|
116
141
|
# will attempt to shutdown a running process
|
|
117
142
|
#
|
|
143
|
+
# #### Parameters
|
|
144
|
+
#
|
|
145
|
+
# * `ctx` - the context of this command
|
|
146
|
+
#
|
|
118
147
|
# #### Returns
|
|
119
148
|
#
|
|
120
149
|
# * `stopped` - [true, false]
|
|
121
150
|
#
|
|
122
151
|
def stop
|
|
123
|
-
unlink
|
|
124
152
|
kill_proc
|
|
153
|
+
unlink
|
|
125
154
|
true
|
|
126
155
|
rescue
|
|
127
156
|
false
|
|
@@ -157,7 +186,11 @@ module ShopifyCli
|
|
|
157
186
|
end
|
|
158
187
|
|
|
159
188
|
def kill_proc
|
|
160
|
-
|
|
189
|
+
if Context.new.windows?
|
|
190
|
+
kill(pid)
|
|
191
|
+
else
|
|
192
|
+
kill(-pid) # process group
|
|
193
|
+
end
|
|
161
194
|
rescue Errno::ESRCH
|
|
162
195
|
begin
|
|
163
196
|
kill(pid)
|
|
@@ -167,12 +200,18 @@ module ShopifyCli
|
|
|
167
200
|
end
|
|
168
201
|
|
|
169
202
|
def kill(id)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
203
|
+
ctx = Context.new
|
|
204
|
+
|
|
205
|
+
# Windows does not handle SIGTERM, go straight to SIGKILL
|
|
206
|
+
unless ctx.windows?
|
|
207
|
+
Process.kill('TERM', id)
|
|
208
|
+
50.times do
|
|
209
|
+
sleep 0.1
|
|
210
|
+
break unless stat(id)
|
|
211
|
+
end
|
|
174
212
|
end
|
|
175
213
|
Process.kill('KILL', id) if stat(id)
|
|
214
|
+
sleep(0.1) if ctx.windows? # Give Windows a second to actually close the process
|
|
176
215
|
end
|
|
177
216
|
|
|
178
217
|
def stat(id)
|
data/lib/shopify-cli/project.rb
CHANGED
|
@@ -15,6 +15,10 @@ module ShopifyCli
|
|
|
15
15
|
# will get an instance of the project that the user is currently operating
|
|
16
16
|
# on. This is used for access to project resources.
|
|
17
17
|
#
|
|
18
|
+
# #### Parameters
|
|
19
|
+
#
|
|
20
|
+
# * `force_reload` - whether to force a reload of the project files
|
|
21
|
+
#
|
|
18
22
|
# #### Returns
|
|
19
23
|
#
|
|
20
24
|
# * `project` - a Project instance if the user is currently in the project.
|
|
@@ -29,8 +33,8 @@ module ShopifyCli
|
|
|
29
33
|
#
|
|
30
34
|
# project = ShopifyCli::Project.current
|
|
31
35
|
#
|
|
32
|
-
def current
|
|
33
|
-
at(Dir.pwd)
|
|
36
|
+
def current(force_reload: false)
|
|
37
|
+
at(Dir.pwd, force_reload: force_reload)
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
##
|
|
@@ -93,13 +97,17 @@ module ShopifyCli
|
|
|
93
97
|
|
|
94
98
|
private
|
|
95
99
|
|
|
96
|
-
def directory(dir)
|
|
100
|
+
def directory(dir, force_reload: false)
|
|
101
|
+
@dir = nil if force_reload
|
|
102
|
+
|
|
97
103
|
@dir ||= Hash.new { |h, k| h[k] = __directory(k) }
|
|
98
104
|
@dir[dir]
|
|
99
105
|
end
|
|
100
106
|
|
|
101
|
-
def at(dir)
|
|
102
|
-
|
|
107
|
+
def at(dir, force_reload: false)
|
|
108
|
+
@at = nil if force_reload
|
|
109
|
+
|
|
110
|
+
proj_dir = directory(dir, force_reload: force_reload)
|
|
103
111
|
unless proj_dir
|
|
104
112
|
raise(ShopifyCli::Abort, Context.message('core.project.error.not_in_project'))
|
|
105
113
|
end
|
|
@@ -109,7 +117,7 @@ module ShopifyCli
|
|
|
109
117
|
|
|
110
118
|
def __directory(curr)
|
|
111
119
|
loop do
|
|
112
|
-
return nil if curr == '/'
|
|
120
|
+
return nil if curr == '/' || /^[A-Z]:\/$/.match?(curr)
|
|
113
121
|
file = File.join(curr, '.shopify-cli.yml')
|
|
114
122
|
return curr if File.exist?(file)
|
|
115
123
|
curr = File.dirname(curr)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module ShopifyCli
|
|
2
2
|
class ProjectType
|
|
3
|
+
extend Feature::Set
|
|
4
|
+
|
|
3
5
|
class << self
|
|
4
6
|
attr_accessor :project_type,
|
|
5
7
|
:project_name,
|
|
6
8
|
:project_creator_command_class,
|
|
7
9
|
:project_load_shallow
|
|
8
|
-
attr_reader :hidden
|
|
9
10
|
|
|
10
11
|
def repository
|
|
11
12
|
@repository ||= []
|
|
@@ -13,6 +14,7 @@ module ShopifyCli
|
|
|
13
14
|
alias_method :all_loaded, :repository
|
|
14
15
|
|
|
15
16
|
def inherited(klass)
|
|
17
|
+
super
|
|
16
18
|
repository << klass
|
|
17
19
|
klass.project_type = @current_type
|
|
18
20
|
klass.project_load_shallow = @shallow_load
|
|
@@ -31,7 +33,7 @@ module ShopifyCli
|
|
|
31
33
|
|
|
32
34
|
def load_all
|
|
33
35
|
Dir.glob(File.join(ShopifyCli::ROOT, 'lib', 'project_types', '*', 'cli.rb')).map do |filepath|
|
|
34
|
-
load_type(filepath.split(File::Separator)[-2], true)
|
|
36
|
+
load_type(filepath.split(File::Separator)[-2].to_sym, true)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
|
|
@@ -53,10 +55,6 @@ module ShopifyCli
|
|
|
53
55
|
const_get(@project_creator_command_class)
|
|
54
56
|
end
|
|
55
57
|
|
|
56
|
-
def hidden_project_type
|
|
57
|
-
@hidden = true
|
|
58
|
-
end
|
|
59
|
-
|
|
60
58
|
def register_command(const, cmd)
|
|
61
59
|
return if project_load_shallow
|
|
62
60
|
Context.new.abort(
|
|
@@ -67,7 +65,7 @@ module ShopifyCli
|
|
|
67
65
|
|
|
68
66
|
def register_task(task, name)
|
|
69
67
|
return if project_load_shallow
|
|
70
|
-
Task
|
|
68
|
+
ShopifyCli::Task.register(task, name)
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
def register_messages(messages)
|
data/lib/shopify-cli/task.rb
CHANGED
data/lib/shopify-cli/tasks.rb
CHANGED
|
@@ -12,15 +12,22 @@ module ShopifyCli
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def [](name)
|
|
15
|
-
@tasks[name]
|
|
15
|
+
class_or_proc = @tasks[name]
|
|
16
|
+
if class_or_proc.is_a?(Class)
|
|
17
|
+
class_or_proc
|
|
18
|
+
elsif class_or_proc.respond_to?(:call)
|
|
19
|
+
class_or_proc.call
|
|
20
|
+
else
|
|
21
|
+
class_or_proc
|
|
22
|
+
end
|
|
16
23
|
end
|
|
17
24
|
end
|
|
18
25
|
|
|
19
26
|
Registry = TaskRegistry.new
|
|
20
27
|
|
|
21
|
-
def self.register(task, name, path)
|
|
22
|
-
autoload(task, path)
|
|
23
|
-
Registry.add(const_get(task), name)
|
|
28
|
+
def self.register(task, name, path = nil)
|
|
29
|
+
autoload(task, path) if path
|
|
30
|
+
Registry.add(-> () { const_get(task) }, name)
|
|
24
31
|
end
|
|
25
32
|
|
|
26
33
|
register :CreateApiClient, :create_api_client, 'shopify-cli/tasks/create_api_client'
|
|
@@ -3,28 +3,84 @@ require 'shopify_cli'
|
|
|
3
3
|
module ShopifyCli
|
|
4
4
|
module Tasks
|
|
5
5
|
class EnsureEnv < ShopifyCli::Task
|
|
6
|
-
def call(ctx)
|
|
6
|
+
def call(ctx, regenerate: false, required: [:api_key, :secret])
|
|
7
7
|
@ctx = ctx
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
env_data =
|
|
9
|
+
begin
|
|
10
|
+
Resources::EnvFile.parse_external_env
|
|
11
|
+
rescue Errno::ENOENT
|
|
12
|
+
{}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
return {} if !regenerate && required.all? { |property| env_data[property] }
|
|
16
|
+
|
|
17
|
+
org = fetch_org
|
|
18
|
+
write_env(env_data, org)
|
|
19
|
+
org
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def fetch_org
|
|
25
|
+
orgs = PartnersAPI::Organizations.fetch_with_app(@ctx)
|
|
26
|
+
org_id = if orgs.count == 1
|
|
27
|
+
orgs.first["id"]
|
|
28
|
+
else
|
|
29
|
+
CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.organization_select')) do |handler|
|
|
30
|
+
orgs.each do |org|
|
|
31
|
+
handler.option(
|
|
32
|
+
@ctx.message('core.partners_api.org_name_and_id', org['businessName'], org['id'])
|
|
33
|
+
) { org["id"] }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
orgs.find { |o| o["id"] == org_id }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_app(org_id, apps)
|
|
41
|
+
if apps.count == 1
|
|
42
|
+
apps.first
|
|
43
|
+
elsif apps.count == 0
|
|
44
|
+
@ctx.puts(@ctx.message('core.tasks.ensure_env.no_apps'))
|
|
45
|
+
title = CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.app_name'))
|
|
46
|
+
type = CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.app_type.select')) do |handler|
|
|
47
|
+
handler.option(@ctx.message('core.tasks.ensure_env.app_type.select_public')) { 'public' }
|
|
48
|
+
handler.option(@ctx.message('core.tasks.ensure_env.app_type.select_custom')) { 'custom' }
|
|
49
|
+
end
|
|
50
|
+
ShopifyCli::Tasks::CreateApiClient.call(@ctx, org_id: org_id, title: title, type: type)
|
|
51
|
+
else
|
|
52
|
+
CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.app_select')) do |handler|
|
|
53
|
+
apps.each { |app| handler.option(app["title"]) { app } }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_shop(shops, id)
|
|
59
|
+
if shops.count == 1
|
|
60
|
+
shop = shops.first["shopDomain"]
|
|
61
|
+
elsif shops.count == 0
|
|
62
|
+
@ctx.puts(@ctx.message('core.tasks.ensure_env.no_development_stores', id))
|
|
63
|
+
else
|
|
64
|
+
shop = CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.development_store_select')) do |handler|
|
|
65
|
+
shops.each { |s| handler.option(s["shopName"]) { s["shopDomain"] } }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
shop
|
|
11
69
|
end
|
|
12
70
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
shop = CLI::UI.ask(@ctx.message('core.tasks.ensure_env.development_store_question'))
|
|
71
|
+
def write_env(env_data, org)
|
|
72
|
+
id = org['id']
|
|
73
|
+
app = get_app(id, org['apps'])
|
|
17
74
|
|
|
18
|
-
shop
|
|
75
|
+
env_data[:shop] = get_shop(org['stores'], id)
|
|
76
|
+
env_data[:api_key] = app["apiKey"]
|
|
77
|
+
env_data[:secret] = app["apiSecretKeys"].first["secret"]
|
|
78
|
+
env_data[:scopes] = 'write_products,write_customers,write_draft_orders' if env_data[:scopes].nil?
|
|
79
|
+
env_data[:extra] = {} if env_data[:extra].nil?
|
|
19
80
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
secret: api_secret,
|
|
23
|
-
shop: shop,
|
|
24
|
-
host: ShopifyCli::Tunnel.start(@ctx),
|
|
25
|
-
scopes: 'write_products,write_customers,write_draft_orders',
|
|
81
|
+
Resources::EnvFile.new(
|
|
82
|
+
env_data
|
|
26
83
|
).write(@ctx)
|
|
27
|
-
env
|
|
28
84
|
end
|
|
29
85
|
end
|
|
30
86
|
end
|