shopify-cli 0.9.3 → 1.0.4

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -4
  3. data/docs/getting-started/install/index.md +37 -1
  4. data/docs/getting-started/migrate/index.md +34 -1
  5. data/lib/project_types/extension/cli.rb +1 -1
  6. data/lib/project_types/extension/commands/build.rb +1 -1
  7. data/lib/project_types/node/forms/create.rb +3 -54
  8. data/lib/project_types/node/messages/messages.rb +3 -14
  9. data/lib/project_types/rails/cli.rb +0 -1
  10. data/lib/project_types/rails/forms/create.rb +3 -52
  11. data/lib/project_types/rails/messages/messages.rb +2 -13
  12. data/lib/project_types/script/cli.rb +2 -3
  13. data/lib/project_types/script/commands/create.rb +4 -4
  14. data/lib/project_types/script/commands/disable.rb +4 -14
  15. data/lib/project_types/script/commands/enable.rb +35 -11
  16. data/lib/project_types/script/commands/push.rb +9 -9
  17. data/lib/project_types/script/config/extension_points.yml +9 -3
  18. data/lib/project_types/script/forms/script_form.rb +5 -2
  19. data/lib/project_types/script/layers/application/create_script.rb +7 -6
  20. data/lib/project_types/script/layers/application/disable_script.rb +9 -7
  21. data/lib/project_types/script/layers/application/enable_script.rb +11 -9
  22. data/lib/project_types/script/layers/application/push_script.rb +6 -4
  23. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +2 -2
  24. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +2 -2
  25. data/lib/project_types/script/layers/infrastructure/errors.rb +1 -0
  26. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
  27. data/lib/project_types/script/layers/infrastructure/script_repository.rb +1 -1
  28. data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -0
  29. data/lib/project_types/script/messages/messages.rb +16 -19
  30. data/lib/project_types/script/script_project.rb +8 -4
  31. data/lib/project_types/script/templates/ts/as-pect.config.js +6 -0
  32. data/lib/project_types/script/ui/error_handler.rb +4 -0
  33. data/lib/project_types/script/ui/printing_spinner.rb +75 -0
  34. data/lib/shopify-cli/admin_api.rb +1 -2
  35. data/lib/shopify-cli/admin_api/populate_resource_command.rb +10 -1
  36. data/lib/shopify-cli/admin_api/schema.rb +20 -8
  37. data/lib/shopify-cli/command.rb +2 -5
  38. data/lib/shopify-cli/commands.rb +1 -0
  39. data/lib/shopify-cli/commands/config.rb +44 -0
  40. data/lib/shopify-cli/commands/connect.rb +18 -11
  41. data/lib/shopify-cli/commands/create.rb +1 -1
  42. data/lib/shopify-cli/commands/help.rb +1 -1
  43. data/lib/shopify-cli/commands/system.rb +1 -1
  44. data/lib/shopify-cli/context.rb +10 -1
  45. data/lib/shopify-cli/core.rb +0 -1
  46. data/lib/shopify-cli/core/entry_point.rb +6 -0
  47. data/lib/shopify-cli/core/finalize.rb +13 -0
  48. data/lib/shopify-cli/feature.rb +97 -0
  49. data/lib/shopify-cli/messages/messages.rb +45 -2
  50. data/lib/shopify-cli/partners_api/organizations.rb +7 -7
  51. data/lib/shopify-cli/project_type.rb +2 -5
  52. data/lib/shopify-cli/tasks.rb +1 -0
  53. data/lib/shopify-cli/tasks/ensure_env.rb +0 -1
  54. data/lib/shopify-cli/tasks/select_org_and_shop.rb +77 -0
  55. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +4 -3
  56. data/lib/shopify-cli/tunnel.rb +33 -9
  57. data/lib/shopify-cli/version.rb +1 -1
  58. data/lib/shopify_cli.rb +1 -0
  59. metadata +7 -4
  60. data/lib/project_types/script/forms/enable.rb +0 -24
  61. data/lib/project_types/script/forms/push.rb +0 -19
@@ -3,29 +3,31 @@
3
3
  module Script
4
4
  module Commands
5
5
  class Enable < ShopifyCli::Command
6
+ prerequisite_task :ensure_env
6
7
  options do |parser, flags|
7
- parser.on('--api_key=APIKEY') { |t| flags[:api_key] = t }
8
- parser.on('--shop_domain=MYSHOPIFYDOMAIN') { |t| flags[:shop_domain] = t }
8
+ parser.on('--config_props=KEYVALUEPAIRS', Array) do |t|
9
+ flags[:config_props] = Hash[t.map { |s| s.split(':') }]
10
+ end
11
+ parser.on('--config_file=CONFIGFILEPATH') { |t| flags[:config_file] = t }
9
12
  end
10
13
 
11
- def call(args, _name)
12
- form = Forms::Enable.ask(@ctx, args, options.flags)
13
- return @ctx.puts(self.class.help) unless form
14
-
14
+ def call(_args, _name)
15
15
  project = ScriptProject.current
16
+ api_key = project.env[:api_key]
17
+ shop_domain = project.env[:shop]
16
18
 
17
19
  Layers::Application::EnableScript.call(
18
20
  ctx: @ctx,
19
- api_key: form.api_key,
20
- shop_domain: form.shop_domain,
21
- configuration: { entries: [] },
21
+ api_key: api_key,
22
+ shop_domain: shop_domain,
23
+ configuration: acquire_configuration(**slice(options.flags, :config_file, :config_props)),
22
24
  extension_point_type: project.extension_point_type,
23
25
  title: project.script_name
24
26
  )
25
27
  @ctx.puts(@ctx.message(
26
28
  'script.enable.script_enabled',
27
- api_key: form.api_key,
28
- shop_domain: form.shop_domain,
29
+ api_key: api_key,
30
+ shop_domain: shop_domain,
29
31
  type: project.extension_point_type.capitalize,
30
32
  title: project.script_name
31
33
  ))
@@ -41,6 +43,28 @@ module Script
41
43
  def self.extended_help
42
44
  ShopifyCli::Context.message('script.enable.extended_help', ShopifyCli::TOOL_NAME)
43
45
  end
46
+
47
+ private
48
+
49
+ def acquire_configuration(config_file: nil, config_props: nil)
50
+ properties = {}
51
+ properties = YAML.load(File.read(config_file)) unless config_file.nil?
52
+ properties = properties.merge(config_props) unless config_props.nil?
53
+
54
+ configuration = { entries: [] }
55
+ properties.each do |key, value|
56
+ configuration[:entries].push({
57
+ key: key,
58
+ value: value,
59
+ })
60
+ end
61
+ configuration
62
+ end
63
+
64
+ # No slice pre Ruby 2.5 so roll our own
65
+ def slice(hash, *keys)
66
+ Hash[hash.to_a - hash.select { |key, _value| !keys.include?(key) }.to_a]
67
+ end
44
68
  end
45
69
  end
46
70
  end
@@ -3,27 +3,27 @@
3
3
  module Script
4
4
  module Commands
5
5
  class Push < ShopifyCli::Command
6
+ prerequisite_task :ensure_env
7
+
6
8
  options do |parser, flags|
7
- parser.on('--api_key=APIKEY') { |t| flags[:api_key] = t }
8
9
  parser.on('--force') { |t| flags[:force] = t }
9
10
  end
10
11
 
11
- def call(args, _name)
12
- form = Forms::Push.ask(@ctx, args, options.flags)
12
+ def call(_args, _name)
13
13
  project = ScriptProject.current
14
-
15
- return @ctx.puts(self.class.help) unless form && ScriptProject::SUPPORTED_LANGUAGES.include?(project.language)
16
-
14
+ api_key = project.env[:api_key]
15
+ return @ctx.puts(self.class.help) unless api_key &&
16
+ ScriptProject::SUPPORTED_LANGUAGES.include?(project.language)
17
17
  Layers::Application::PushScript.call(
18
18
  ctx: @ctx,
19
19
  language: project.language,
20
20
  extension_point_type: project.extension_point_type,
21
21
  script_name: project.script_name,
22
22
  source_file: project.source_file,
23
- api_key: form.api_key,
24
- force: form.force
23
+ api_key: api_key,
24
+ force: options.flags.key?(:force)
25
25
  )
26
- @ctx.puts(@ctx.message('script.push.script_pushed', api_key: form.api_key))
26
+ @ctx.puts(@ctx.message('script.push.script_pushed', api_key: api_key))
27
27
  rescue StandardError => e
28
28
  UI::ErrorHandler.pretty_print_and_raise(e, failed_op: @ctx.message('script.push.error.operation_failed'))
29
29
  end
@@ -1,18 +1,24 @@
1
1
  discount:
2
2
  assemblyscript:
3
3
  package: "@shopify/extension-point-as-discount"
4
- version: "^0.2.2"
4
+ version: "^0.2.4"
5
5
  sdk-version: "^6.0.0"
6
6
  toolchain-version: "^1.1.0"
7
7
  unit_limit_per_order:
8
8
  assemblyscript:
9
9
  package: "@shopify/extension-point-as-unit-limit-per-order"
10
- version: "^0.1.2"
10
+ version: "^0.1.6"
11
11
  sdk-version: "^6.0.0"
12
12
  toolchain-version: "^1.1.0"
13
13
  payment_filter:
14
14
  assemblyscript:
15
15
  package: "@shopify/extension-point-as-payment-filter"
16
- version: "^0.1.2"
16
+ version: "^0.2.2"
17
+ sdk-version: "^6.0.0"
18
+ toolchain-version: "^1.1.0"
19
+ shipping_filter:
20
+ assemblyscript:
21
+ package: "@shopify/extension-point-as-shipping-filter"
22
+ version: "^0.2.4"
17
23
  sdk-version: "^6.0.0"
18
24
  toolchain-version: "^1.1.0"
@@ -11,8 +11,11 @@ module Script
11
11
 
12
12
  def organizations
13
13
  return @organizations if defined?(@organizations)
14
- ctx.puts(ctx.message('script.forms.script_form.fetching_organizations'))
15
- @organizations = ShopifyCli::PartnersAPI::Organizations.fetch_with_app(ctx)
14
+ UI::PrintingSpinner.spin(ctx, ctx.message('script.forms.script_form.fetching_organizations')) do |ctx, spinner|
15
+ @organizations = ShopifyCli::PartnersAPI::Organizations.fetch_with_app(ctx)
16
+ spinner.update_title(ctx.message('script.forms.script_form.fetched_organizations'))
17
+ end
18
+ @organizations
16
19
  end
17
20
 
18
21
  def ask_app_api_key(apps, message: ctx.message('script.forms.script_form.ask_app_api_key_default'))
@@ -12,8 +12,9 @@ module Script
12
12
  project = setup_project(ctx, script_name, extension_point)
13
13
  project_creator = Infrastructure::ProjectCreator
14
14
  .for(ctx, language, extension_point, script_name, project.directory)
15
- install_dependencies(ctx, language, script_name, project, project_creator)
16
- bootstrap(ctx, project_creator)
15
+ install_dependencies(ctx, language, script_name, project.source_file, project_creator)
16
+ bootstrap(ctx, project.source_path, project_creator)
17
+ project
17
18
  end
18
19
 
19
20
  private
@@ -30,16 +31,16 @@ module Script
30
31
  ScriptProject.current
31
32
  end
32
33
 
33
- def install_dependencies(ctx, language, script_name, project, project_creator)
34
- task_runner = Infrastructure::TaskRunner.for(ctx, language, script_name, project.source_file)
34
+ def install_dependencies(ctx, language, script_name, source_file, project_creator)
35
+ task_runner = Infrastructure::TaskRunner.for(ctx, language, script_name, source_file)
35
36
  project_creator.setup_dependencies
36
37
  ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
37
38
  end
38
39
 
39
- def bootstrap(ctx, project_creator)
40
+ def bootstrap(ctx, source_path, project_creator)
40
41
  UI::StrictSpinner.spin(ctx.message('script.create.creating')) do |spinner|
41
42
  project_creator.bootstrap
42
- spinner.update_title(ctx.message('script.create.created'))
43
+ spinner.update_title(ctx.message('script.create.created', source_path))
43
44
  end
44
45
  end
45
46
  end
@@ -5,13 +5,15 @@ module Script
5
5
  module Application
6
6
  class DisableScript
7
7
  def self.call(ctx:, api_key:, shop_domain:, extension_point_type:)
8
- script_service = Infrastructure::ScriptService.new(ctx: ctx)
9
- script_service.disable(
10
- api_key: api_key,
11
- shop_domain: shop_domain,
12
- extension_point_type: extension_point_type,
13
- )
14
- ctx.puts(ctx.message('script.application.disabled'))
8
+ UI::PrintingSpinner.spin(ctx, ctx.message('script.application.disabling')) do |p_ctx, spinner|
9
+ script_service = Infrastructure::ScriptService.new(ctx: p_ctx)
10
+ script_service.disable(
11
+ api_key: api_key,
12
+ shop_domain: shop_domain,
13
+ extension_point_type: extension_point_type,
14
+ )
15
+ spinner.update_title(p_ctx.message('script.application.disabled'))
16
+ end
15
17
  end
16
18
  end
17
19
  end
@@ -5,15 +5,17 @@ module Script
5
5
  module Application
6
6
  class EnableScript
7
7
  def self.call(ctx:, api_key:, shop_domain:, configuration:, extension_point_type:, title:)
8
- script_service = Infrastructure::ScriptService.new(ctx: ctx)
9
- script_service.enable(
10
- api_key: api_key,
11
- shop_domain: shop_domain,
12
- configuration: configuration,
13
- extension_point_type: extension_point_type,
14
- title: title
15
- )
16
- ctx.puts(ctx.message('script.application.enabled'))
8
+ UI::PrintingSpinner.spin(ctx, ctx.message('script.application.enabling')) do |p_ctx, spinner|
9
+ script_service = Infrastructure::ScriptService.new(ctx: p_ctx)
10
+ script_service.enable(
11
+ api_key: api_key,
12
+ shop_domain: shop_domain,
13
+ configuration: configuration,
14
+ extension_point_type: extension_point_type,
15
+ title: title
16
+ )
17
+ spinner.update_title(p_ctx.message('script.application.enabled'))
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -20,10 +20,12 @@ module Script
20
20
  private
21
21
 
22
22
  def push_script(ctx, task_runner, script, api_key, force)
23
- Infrastructure::PushPackageRepository.new(ctx: ctx)
24
- .get_push_package(script, task_runner.compiled_type)
25
- .push(Infrastructure::ScriptService.new(ctx: ctx), api_key, force)
26
- ctx.puts(ctx.message('script.application.pushed'))
23
+ UI::PrintingSpinner.spin(ctx, ctx.message('script.application.pushing')) do |p_ctx, spinner|
24
+ Infrastructure::PushPackageRepository.new(ctx: p_ctx)
25
+ .get_push_package(script, task_runner.compiled_type)
26
+ .push(Infrastructure::ScriptService.new(ctx: p_ctx), api_key, force)
27
+ spinner.update_title(p_ctx.message('script.application.pushed'))
28
+ end
27
29
  end
28
30
  end
29
31
  end
@@ -86,14 +86,14 @@ module Script
86
86
  "@shopify/scripts-toolchain-as": "#{extension_point.sdks[:ts].toolchain_version}",
87
87
  "#{extension_point.sdks[:ts].package}": "#{extension_point.sdks[:ts].version}",
88
88
  "@as-pect/cli": "4.0.0",
89
- "as-wasi": "^0.0.1",
89
+ "as-wasi": "^0.2.0",
90
90
  "assemblyscript": "^0.12.0"
91
91
  },
92
92
  "scripts": {
93
93
  "test": "asp --config test/as-pect.config.js --summary --verbose"
94
94
  },
95
95
  "engines": {
96
- "node": ">=12.16"
96
+ "node": ">=14.5"
97
97
  }
98
98
  }
99
99
  HERE
@@ -6,7 +6,7 @@ module Script
6
6
  class AssemblyScriptTaskRunner
7
7
  BYTECODE_FILE = "%{name}.wasm"
8
8
  SCRIPT_SDK_BUILD = "npx --no-install shopify-scripts-build --src=../%{source} --binary=#{BYTECODE_FILE} "\
9
- "-- --lib=../node_modules --validate --optimize"
9
+ "-- --lib=../node_modules --optimize --use Date="
10
10
 
11
11
  attr_reader :ctx, :script_name, :script_source_file
12
12
 
@@ -34,7 +34,7 @@ module Script
34
34
 
35
35
  def dependencies_installed?
36
36
  # Assuming if node_modules folder exist at root of script folder, all deps are installed
37
- ctx.exist?("node_modules")
37
+ ctx.dir_exist?("node_modules")
38
38
  end
39
39
 
40
40
  private
@@ -5,6 +5,7 @@ module Script
5
5
  module Infrastructure
6
6
  module Errors
7
7
  class AppNotInstalledError < ScriptProjectError; end
8
+ class AppScriptNotPushedError < ScriptProjectError; end
8
9
  class AppScriptUndefinedError < ScriptProjectError; end
9
10
  class BuildError < ScriptProjectError; end
10
11
  class DependencyInstallError < ScriptProjectError; end
@@ -22,7 +22,7 @@ module Script
22
22
  def get_push_package(script, compiled_type)
23
23
  build_file_path = file_path(script.name, compiled_type)
24
24
 
25
- raise Domain::PushPackageNotFoundError unless File.exist?(build_file_path)
25
+ raise Domain::PushPackageNotFoundError unless ctx.file_exist?(build_file_path)
26
26
 
27
27
  script_content = File.read(build_file_path)
28
28
 
@@ -9,7 +9,7 @@ module Script
9
9
 
10
10
  def get_script(language, extension_point_type, script_name)
11
11
  source_file_path = src_code_file(language)
12
- unless File.exist?(source_file_path)
12
+ unless ctx.file_exist?(source_file_path)
13
13
  raise Domain::Errors::ScriptNotFoundError.new(extension_point_type, source_file_path)
14
14
  end
15
15
 
@@ -60,6 +60,8 @@ module Script
60
60
  raise Errors::AppScriptUndefinedError, api_key
61
61
  elsif user_errors.any? { |e| e['tag'] == 'shop_script_conflict' }
62
62
  raise Errors::ShopScriptConflictError
63
+ elsif user_errors.any? { |e| e['tag'] == 'app_script_not_pushed' }
64
+ raise Errors::AppScriptNotPushedError
63
65
  else
64
66
  raise Errors::ScriptServiceUserError.new(query_name, user_errors.to_s)
65
67
  end
@@ -42,6 +42,8 @@ module Script
42
42
 
43
43
  app_not_installed_cause: "App not installed on development store.",
44
44
 
45
+ app_script_not_pushed_help: "Push the script and then try this command again.",
46
+
45
47
  app_script_undefined_help: "Push script to app.",
46
48
 
47
49
  build_error_cause: "Something went wrong while building the script.",
@@ -83,10 +85,9 @@ module Script
83
85
  operation_failed: "Script not created.",
84
86
  },
85
87
 
86
- script_path: "{{v}} Project directory: {{green:%{folder}}}",
87
- script_created: "{{v}} Script created: {{green:%{script_id}}}",
88
+ change_directory_notice: "{{*}} Change directories to {{green:%s}} to run script commands",
88
89
  creating: "Creating script",
89
- created: "Created script",
90
+ created: "Created script: {{green:%s}}",
90
91
  },
91
92
 
92
93
  push: {
@@ -96,7 +97,6 @@ module Script
96
97
  HELP
97
98
  extended_help: <<~HELP,
98
99
  \s\sOptions:
99
- \s\s{{command:--API_key=<API_key>}} API key. Must be a valid API key, otherwise store access fails.
100
100
  \s\s{{command:[--force]}} Forces the script to be overwritten if an instance of it already exists.
101
101
  HELP
102
102
 
@@ -112,14 +112,10 @@ module Script
112
112
  Turn off script in development store.
113
113
  Usage: {{command:%s disable}}
114
114
  HELP
115
- extended_help: <<~HELP,
116
- \s\sOptions:
117
- \s\s{{command:--API_key=<API_key>}} API key. Must be a valid API key, otherwise store access fails.
118
- \s\s{{command:--shop_domain=<my_store.myshopify.com>}} Test store URL. Must be an existing test store.
119
- HELP
120
115
 
121
116
  error: {
122
117
  operation_failed: "Can't disable script.",
118
+ not_pushed_to_app: "Can't disable the script because it hasn't been pushed to the app.",
123
119
  },
124
120
 
125
121
  script_disabled: "{{v}} Script disabled. Script is turned off in development store.",
@@ -132,8 +128,8 @@ module Script
132
128
  HELP
133
129
  extended_help: <<~HELP,
134
130
  \s\sOptions:
135
- \s\s{{command:--API_key=<API_key>}} API key. Must be a valid API key, otherwise store access fails.
136
- \s\s{{command:--shop_domain=<my_store.myshopify.com>}} Test store URL. Must be an existing test store.
131
+ \s\s{{command:--config_props='name1:value1, name2:value2'}} Optional. Define the configuration of your script by passing individual name and value pairs. If used with --config_file, then matching values in --config_props will override those set in the file.
132
+ \s\s{{command:--config_file=<path/to/YAMLFilename>}} Optional. Define the configuration of your script using a YAML formatted file. --config_props values override properties in this file.
137
133
  HELP
138
134
 
139
135
  info: "{{*}} A script always remains enabled until you disable it - even after pushing "\
@@ -142,6 +138,7 @@ module Script
142
138
 
143
139
  error: {
144
140
  operation_failed: "Can't enable script.",
141
+ not_pushed_to_app: "Can't enable the script because it hasn't been pushed to the app.",
145
142
  },
146
143
 
147
144
  script_enabled: "{{v}} Script enabled. %{type} script %{title} in app (API key: %{api_key}) "\
@@ -177,25 +174,25 @@ module Script
177
174
  script_form: {
178
175
  ask_app_api_key_default: "Which app do you want this script to belong to?",
179
176
  ask_shop_domain_default: "Select a development store",
180
- fetching_organizations: "{{i}} Fetching partner organizations",
177
+ fetching_organizations: "Fetching partner organizations",
178
+ fetched_organizations: "Fetched partner organizations",
181
179
  select_organization: "Select partner organization.",
182
180
  using_app: "Using app {{green:%{title} (%{api_key})}}.",
183
181
  using_development_store: "Using development store {{green:%{domain}}}",
184
182
  using_organization: "Partner organization {{green:%s}}.",
185
183
  },
186
- enable: {
187
- ask_app_api_key: "Which app is the script pushed to?",
188
- ask_shop_domain: "Which development store is the app installed on?",
189
- },
190
184
  },
191
185
 
192
186
  application: {
193
187
  building: "Building",
194
188
  building_script: "Building script",
195
189
  built: "Built",
196
- pushed: "{{v}} Pushed",
197
- disabled: "{{v}} Disabled",
198
- enabled: "{{v}} Enabled",
190
+ pushing: "Pushing",
191
+ pushed: "Pushed",
192
+ disabling: "Disabling",
193
+ disabled: "Disabled",
194
+ enabling: "Enabling",
195
+ enabled: "Enabled",
199
196
  },
200
197
  },
201
198
  }.freeze
@@ -19,12 +19,16 @@ module Script
19
19
  }
20
20
  end
21
21
 
22
+ def file_name
23
+ "script.#{language}"
24
+ end
25
+
22
26
  def source_file
23
27
  "#{SOURCE_DIR}/#{file_name}"
24
28
  end
25
29
 
26
- def file_name
27
- "script.#{language}"
30
+ def source_path
31
+ "#{script_name}/#{source_file}"
28
32
  end
29
33
 
30
34
  private
@@ -36,14 +40,14 @@ module Script
36
40
 
37
41
  class << self
38
42
  def create(ctx, dir)
39
- raise Errors::ScriptProjectAlreadyExistsError, dir if ctx.exist?(dir)
43
+ raise Errors::ScriptProjectAlreadyExistsError, dir if ctx.dir_exist?(dir)
40
44
  ctx.mkdir_p(dir)
41
45
  ctx.chdir(dir)
42
46
  end
43
47
 
44
48
  def cleanup(ctx:, script_name:, root_dir:)
45
49
  ctx.chdir(root_dir)
46
- ctx.rm_r("#{root_dir}/#{script_name}") if ctx.exist?("#{root_dir}/#{script_name}")
50
+ ctx.rm_r("#{root_dir}/#{script_name}") if ctx.dir_exist?("#{root_dir}/#{script_name}")
47
51
  end
48
52
  end
49
53
  end