Skip to content

Commit b7bab1d

Browse files
committed
Package manager detection
1 parent 8eca54b commit b7bab1d

File tree

3 files changed

+109
-28
lines changed

3 files changed

+109
-28
lines changed

lib/install/bootstrap/install.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
add_package_json_script("build:css:compile", "sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules")
3838
add_package_json_script("build:css:prefix", "postcss ./app/assets/builds/application.css --use=autoprefixer --output=./app/assets/builds/application.css")
3939
add_package_json_script("build:css", "#{bundler_run_cmd} build:css:compile && #{bundler_run_cmd} build:css:prefix")
40-
add_package_json_script("watch:css", "nodemon --watch ./app/assets/stylesheets/ --ext scss --exec \\\"#{bundler_run_cmd} build:css\\\"", false)
40+
add_package_json_script("watch:css", "nodemon --watch ./app/assets/stylesheets/ --ext scss --exec \\\"#{bundler_run_cmd} build:css\\\"", run_script: false)
4141

4242
gsub_file "Procfile.dev", "build:css --watch", "watch:css"
4343

lib/install/helpers.rb

+107-26
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,129 @@
1+
# frozen_string_literal: true
2+
13
require 'json'
24

35
module Helpers
6+
SUPPORTED_PACKAGE_MANAGERS = %i[yarn npm pnpm bun].freeze
7+
UNSUPPORTED_PACKAGE_MANAGER_ERROR_MESSAGE = "No supported package manager (#{SUPPORTED_PACKAGE_MANAGERS.join(', ')}) found. Please install one."
8+
9+
PM_COMMANDS = {
10+
yarn: { cmd: 'yarn', run: 'yarn', x: 'npx' },
11+
npm: { cmd: 'npm', run: 'npm run', x: 'npx' },
12+
pnpm: { cmd: 'pnpm', run: 'pnpm run', x: 'pnpx' },
13+
bun: { cmd: 'bun', run: 'bun run', x: 'bunx' }
14+
}.freeze
15+
16+
SCRIPT_STRATEGIES = {
17+
bun: lambda do |helper, name, script, run_script|
18+
package_json = JSON.parse(File.read("package.json"))
19+
package_json["scripts"] ||= {}
20+
package_json["scripts"][name] = script.gsub('\\"', '"')
21+
File.write("package.json", JSON.pretty_generate(package_json))
22+
helper.run %(#{helper.bundler_run_cmd} #{name}) if run_script
23+
end,
24+
25+
pnpm: lambda do |helper, name, script, run_script|
26+
helper.say "Add #{name} script"
27+
helper.run %(pnpm pkg set scripts.#{name}="#{script}")
28+
helper.run %(#{helper.bundler_run_cmd} #{name}) if run_script
29+
end,
30+
31+
npm: lambda do |helper, name, script, run_script|
32+
helper.say "Add #{name} script"
33+
npx_version = `npx -v`.to_f
34+
35+
if npx_version >= 7.1 && npx_version < 8.0
36+
helper.run %(npm set-script #{name} "#{script}")
37+
else
38+
helper.run %(npm pkg set scripts.#{name}="#{script}")
39+
end
40+
41+
helper.run %(#{helper.bundler_run_cmd} #{name}) if run_script
42+
end,
43+
44+
yarn: lambda do |helper, name, script, run_script|
45+
npx_version = `npx -v`.to_f
46+
47+
if npx_version >= 7.1 && npx_version < 8.0
48+
helper.say "Add #{name} script"
49+
helper.run %(npm set-script #{name} "#{script}")
50+
helper.run %(#{helper.bundler_run_cmd} #{name}) if run_script
51+
elsif npx_version >= 8.0
52+
helper.say "Add #{name} script"
53+
helper.run %(npm pkg set scripts.#{name}="#{script}")
54+
helper.run %(#{helper.bundler_run_cmd} #{name}) if run_script
55+
else
56+
helper.say %(Add "scripts": { "#{name}": "#{script}" } to your package.json), :green
57+
end
58+
end
59+
}.freeze
60+
461
def bundler_cmd
5-
using_bun? ? "bun" : "yarn"
62+
PM_COMMANDS.dig(package_manager, :cmd) || PM_COMMANDS.dig(:yarn, :cmd)
663
end
764

865
def bundler_run_cmd
9-
using_bun? ? "bun run" : "yarn"
66+
PM_COMMANDS.dig(package_manager, :run) || PM_COMMANDS.dig(yarn, :run)
1067
end
1168

1269
def bundler_x_cmd
13-
using_bun? ? "bunx" : "npx"
70+
PM_COMMANDS.dig(package_manager, :x) || PM_COMMANDS.dig(yarn, :x)
1471
end
1572

1673
def using_bun?
17-
tool_exists?('bun') && (File.exist?('bun.lockb') ||
18-
File.exist?('bun.lock') ||
19-
File.exist?('yarn.lock'))
74+
package_manager == :bun
75+
end
76+
77+
def package_manager
78+
@package_manager ||=
79+
tool_determined_by_package_json_package_manager ||
80+
tool_determined_by_config_file ||
81+
tool_determined_by_executable
2082
end
2183

84+
def add_package_json_script(name, script, run_script: true)
85+
strategy = SCRIPT_STRATEGIES[package_manager] || SCRIPT_STRATEGIES[:yarn]
86+
strategy.call(self, name, script, run_script)
87+
end
88+
89+
private
90+
2291
def tool_exists?(tool)
2392
system "command -v #{tool} > /dev/null"
2493
end
2594

26-
def add_package_json_script(name, script, run_script=true)
27-
if using_bun?
28-
package_json = JSON.parse(File.read("package.json"))
29-
package_json["scripts"] ||= {}
30-
package_json["scripts"][name] = script.gsub('\\"', '"')
31-
File.write("package.json", JSON.pretty_generate(package_json))
32-
run %(bun run #{name}) if run_script
33-
else
34-
case `npx -v`.to_f
35-
when 7.1...8.0
36-
say "Add #{name} script"
37-
run %(npm set-script #{name} "#{script}")
38-
run %(yarn #{name}) if run_script
39-
when (8.0..)
40-
say "Add #{name} script"
41-
run %(npm pkg set scripts.#{name}="#{script}")
42-
run %(yarn #{name}) if run_script
43-
else
44-
say %(Add "scripts": { "#{name}": "#{script}" } to your package.json), :green
45-
end
95+
def tool_determined_by_package_json_package_manager
96+
return nil unless File.exist?('package.json')
97+
98+
package_json = JSON.parse(File.read('package.json'))
99+
return nil unless package_json['packageManager']
100+
101+
pm_name = package_json['packageManager'].split('@').first.downcase.to_sym
102+
103+
unless SUPPORTED_PACKAGE_MANAGERS.include?(pm_name)
104+
raise UNSUPPORTED_PACKAGE_MANAGER_ERROR_MESSAGE
105+
end
106+
107+
unless tool_exists?(pm_name)
108+
raise "The package manager '#{pm_name}' specified in package.json is not installed. Please install it first."
109+
end
110+
111+
pm_name
112+
end
113+
114+
def tool_determined_by_config_file
115+
case
116+
when File.exist?("yarn.lock") then :yarn
117+
when File.exist?("bun.lockb") then :bun
118+
when File.exist?("bun.lock") then :bun
119+
when File.exist?("package-lock.json") then :npm
120+
when File.exist?("pnpm-lock.yaml") then :pnpm
121+
end
122+
end
123+
124+
def tool_determined_by_executable
125+
PM_COMMANDS.keys.each do |tool|
126+
return tool if tool_exists?(tool)
46127
end
47128
end
48129
end

lib/tasks/cssbundling/build.rake

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module Cssbundling
2222
extend self
2323

2424
LOCK_FILES = {
25-
bun: %w[bun.lockb bun.lock yarn.lock],
25+
bun: %w[bun.lockb bun.lock],
2626
yarn: %w[yarn.lock],
2727
pnpm: %w[pnpm-lock.yaml],
2828
npm: %w[package-lock.json]

0 commit comments

Comments
 (0)