|  | 
|  | 1 | +# frozen_string_literal: true | 
|  | 2 | + | 
| 1 | 3 | require 'json' | 
| 2 | 4 | 
 | 
| 3 | 5 | 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 | + | 
| 4 | 61 |   def bundler_cmd | 
| 5 |  | -    using_bun? ? "bun" : "yarn" | 
|  | 62 | +    PM_COMMANDS.dig(package_manager, :cmd) || PM_COMMANDS.dig(:yarn, :cmd) | 
| 6 | 63 |   end | 
| 7 | 64 | 
 | 
| 8 | 65 |   def bundler_run_cmd | 
| 9 |  | -    using_bun? ? "bun run" : "yarn" | 
|  | 66 | +    PM_COMMANDS.dig(package_manager, :run) || PM_COMMANDS.dig(yarn, :run) | 
| 10 | 67 |   end | 
| 11 | 68 | 
 | 
| 12 | 69 |   def bundler_x_cmd | 
| 13 |  | -    using_bun? ? "bunx" : "npx" | 
|  | 70 | +    PM_COMMANDS.dig(package_manager, :x) || PM_COMMANDS.dig(yarn, :x) | 
| 14 | 71 |   end | 
| 15 | 72 | 
 | 
| 16 | 73 |   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 ||= tool_determined_by_config_file || tool_determined_by_executable | 
| 20 | 79 |   end | 
| 21 | 80 | 
 | 
|  | 81 | +  def add_package_json_script(name, script, run_script: true) | 
|  | 82 | +    strategy = SCRIPT_STRATEGIES[package_manager] || SCRIPT_STRATEGIES[:yarn] | 
|  | 83 | +    strategy.call(self, name, script, run_script) | 
|  | 84 | +  end | 
|  | 85 | + | 
|  | 86 | +  private | 
|  | 87 | + | 
| 22 | 88 |   def tool_exists?(tool) | 
| 23 | 89 |     system "command -v #{tool} > /dev/null" | 
| 24 | 90 |   end | 
| 25 | 91 | 
 | 
| 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 | 
|  | 92 | +  def tool_determined_by_config_file | 
|  | 93 | +    case | 
|  | 94 | +    when File.exist?("yarn.lock")         then :yarn | 
|  | 95 | +    when File.exist?("bun.lockb")         then :bun | 
|  | 96 | +    when File.exist?("bun.lock")          then :bun | 
|  | 97 | +    when File.exist?("package-lock.json") then :npm | 
|  | 98 | +    when File.exist?("pnpm-lock.yaml")    then :pnpm | 
|  | 99 | +    end | 
|  | 100 | +  end | 
|  | 101 | + | 
|  | 102 | +  def tool_determined_by_executable | 
|  | 103 | +    PM_COMMANDS.keys.each do |tool| | 
|  | 104 | +      return tool if tool_exists?(tool) | 
| 46 | 105 |     end | 
| 47 | 106 |   end | 
| 48 | 107 | end | 
0 commit comments