class VueCreate

Public Class Methods

new() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 4
def initialize
  @input = InputLoop.new
  @pwd = FileUtils.pwd
  @root = ::Rails.root
  @pack = @root.join('package.json')
  @src_dir = Pathname.new(__FILE__).dirname.join('..', '..', 'source')
end
run!() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 12
def self.run!
  new.start
end

Public Instance Methods

start() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 16
def start
  check_node!
  FileUtils.chdir(@root)
  @pending_install = false
  @pending_fixes = []
  begin
    package_manager?
    install_vue_cli
    run_vue_create?
    install_dev_deps
    @pm.install if @pending_install
    delete_vue_sample?
    copy_demo?
    copy_config
    generate_vue_yml
    ensure_entry_point!
    fix_jest_config!
    eslint_fix!
    puts 'vue:create finished!'
  ensure
    FileUtils.chdir(@pwd)
  end
end

Private Instance Methods

check_node!() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 42
def check_node!
  @pm = VueCli::Rails::NodeEnv.new
  abort('Cannot find node.js') unless @pm.node?
end
copy_config() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 197
def copy_config
  puts 'Copying configuration files...'
  FileUtils.cp(@src_dir.join('vue.rails.js'), "#{@root}/")

  src_cfg = @src_dir.join('vue.config.js')
  dst_cfg = @root.join('vue.config.js')
  config = src_cfg.read
  if dst_cfg.exist?
    if dst_cfg.size > 500
      puts 'Detected `vue.config.js`!'
      return if @input.gets('  Do you want to overwrite vue.config.js?', 'yN') == 'n'
    else
      old_cfg = %x`node -e "console.log(JSON.stringify(require('./vue.config.js'),null,2))"`
      config = config.sub('const oldConfig = {};', "const oldConfig = #{old_cfg};")
    end
  end

  dst_cfg.write(config)
  @pending_fixes << dst_cfg.to_s
end
copy_demo?() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 171
def copy_demo?
  return unless @input.gets('Do you want to copy demo code?', 'yN') == 'y'

  FileUtils.cp_r(@src_dir.join('app'), @root)
  routes = @root.join('config', 'routes.rb')
  return unless routes.exist?

  route_lines = routes.read.split("\n")
  foo = false
  bar = false
  route_lines.each do |line|
    foo ||= line.include?('vue_demo#foo')
    bar ||= line.include?('vue_demo#bar')
  end
  return if foo && bar

  end_line = route_lines.rindex { |ln| ln =~ /^\s*end\b/ }
  return if end_line.blank?

  route_lines.insert(end_line, "  get 'vue_demo/baz' => 'vue_demo#baz'") unless foo
  route_lines.insert(end_line, "  get 'vue_demo/bar' => 'vue_demo#bar'") unless bar
  route_lines.insert(end_line, "  get 'vue_demo/foo' => 'vue_demo#foo'") unless foo
  route_lines.insert(end_line, '  # Example of vue_cli-rails')
  routes.write(route_lines.join("\n"))
end
delete_vue_sample?() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 161
def delete_vue_sample?
  %w[src dist].each do |fn|
    file = @root.join(fn)
    next unless file.exist?

    puts "Detected `#{fn}` (should be generated by vue-cli)"
    FileUtils.rm_rf(file.to_s) if @input.gets("  Do you want to delete #{file}?") == 'y'
  end
end
ensure_entry_point!() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 230
def ensure_entry_point!
  %w[entry_points assets components utils views].each do |dir_name|
    dir = @root.join("app/assets/vue/#{dir_name}")
    FileUtils.mkdir_p(dir) unless dir.exist?
  end

  ep_dir = @root.join('app/assets/vue/entry_points')
  return if Dir[ep_dir.join('**/*.js')].any?
  ep_dir.join('entry_point_demo.js').write("console.log('This is a demo entry point')")
end
eslint_fix!() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 263
def eslint_fix!
  dev_deps = JSON.parse(@pack.read)['devDependencies']
  return unless dev_deps['eslint'].present?
  @pm.exec('eslint', @pending_fixes.map { |fn| "'#{fn}'" }.join(' '), '--fix')
rescue => e
  STDERR.puts e.message
end
fix_jest_config!() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 241
  def fix_jest_config!
    jest_file = @root.join('jest.config.js')
    return unless jest_file.exist?

    jest_config = %x`node -e "console.log(JSON.stringify(require('./jest.config.js')))"`
    jest_config = JSON.parse(jest_config)
    if jest_config['transformIgnorePatterns'] &&
       !jest_config['transformIgnorePatterns'].include?('<rootDir>/node_modules/')
      jest_config['transformIgnorePatterns'].unshift('<rootDir>/node_modules/')
    end
    jest_config.delete('moduleNameMapper')
    jest = <<~JS
      const { jestModuleNameMapper: moduleNameMapper } = require('./vue.rails');

      module.exports = #{JSON.pretty_generate(jest_config)}_MODULE_NAME_MAPPER_;
    JS
    jest_file.write(jest.sub(/\n?}_MODULE_NAME_MAPPER_/, ",\n  moduleNameMapper\n}"))
    @pending_fixes << jest_file.to_s
  rescue => e
    STDERR.puts e.message
  end
generate_vue_yml() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 218
def generate_vue_yml
  yml_dest = @root.join('config', 'vue.yml')
  if yml_dest.exist?
    puts 'Detected `config/vue.yml`!'
    return if @input.gets('  Do you want to overwrite config/vue.yml?') == 'n'
  end

  yml = @src_dir.join('vue.yml').read
  yml = yml.sub('${PACKAGE_MANAGER}', @pm.package_manager.to_s)
  yml_dest.write(yml)
end
install_dev_deps() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 149
def install_dev_deps
  package = JSON.parse(@pack.read)
  dev_deps = package['devDependencies']
  dd = %w[webpack-assets-manifest js-yaml].find_all do |dep|
    !dev_deps.key?(dep)
  end
  if dd.any?
    @pm.add("-D #{dd.join(' ')}")
    @pending_install = false
  end
end
install_vue_cli() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 65
def install_vue_cli
  return if @pm.vue?

  puts "@vue/cli haven't been installed"
  pm.global_add('@vue/cli')
end
package_manager?() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 47
def package_manager?
  yarn = @pm.yarn_version
  npm = @pm.npm_version
  abort('Cannot find npm or yarn') unless yarn || npm

  input = if yarn && npm
    @input.gets(
      'Which package manager to use?',
      @root.join('package-lock.json').exist? ? 'yN' : 'Yn',
      y: 'yarn', n: 'npm',
    )
  else
    npm ? 'n' : 'y'
  end
  @pm.use!(input == 'n' ? :npm : :yarn)
  puts "Using package manager: #{@pm.package_manager}"
end
run_vue_create?() click to toggle source
# File lib/helpers/scripts/vue_create.rb, line 72
def run_vue_create?
  pack_input = 'y'
  if @pack.exist?
    puts 'Detected `package.json`!'
    pack_input = @input.gets(
      '  Do you want vue-cli to overwrite your package.json',
      'yAks',
      a: 'Auto', k: 'Keep', s: 'Skip vue create',
    )
  end
  return if pack_input == 's'

  gi_input = 'y'
  gi = @root.join('.gitignore')
  if gi.exist?
    puts 'Detected `.gitignore`!'
    gi_input = @input.gets(
      '  Do you want vue-cli to overwrite your .gitignore',
      'yMk',
      m: 'Merge', k: 'Keep',
    )
  end

  # backups
  vue_config = @root.join('vue.config.js')
  backup_vue_config = vue_config.exist?
  src_json = JSON.parse(@pack.read) if pack_input != 'y'
  gi_lines = gi.read.split("\n") if gi_input != 'y'
  if backup_vue_config
    FileUtils.mv(vue_config, "#{vue_config}.backup")
    # will be recreated
    FileUtils.rm_f(@root.join('vue.rails.js'))
  end
  pub_dir = @root.join('public')
  FileUtils.mv(pub_dir, "#{pub_dir}.backup")
  reademe = @root.join('README.md')
  reademe = reademe.exist? && reademe
  FileUtils.mv(reademe, "#{reademe}.backup") if reademe

  begin
    @pm.exec('vue create', '', "-n -m #{@pm.package_manager} .")
  ensure
    # restore backups
    FileUtils.rm_rf(pub_dir) if pub_dir.exist?
    FileUtils.mv("#{pub_dir}.backup", pub_dir)
    FileUtils.mv("#{vue_config}.backup", vue_config) if backup_vue_config
    if reademe
      FileUtils.rm_f(reademe)
      FileUtils.mv("#{reademe}.backup", reademe)
    end
  end

  # merge gitignore
  if gi_input == 'm'
    old_gi = Set.new(gi_lines.map(&:strip))
    new_lines = gi.read.split("\n")

    new_lines.map(&:strip).find_all(&:present?).each do |ln|
      gi_lines << ln unless old_gi.include?(ln)
    end
    gi.write(gi_lines.map { |ln| "#{ln}\n" }.join('')) if gi_lines.size != new_lines.size
  elsif gi_input == 'k'
    gi.write(gi_lines.join(''))
  end

  # check packages.json
  return if pack_input == 'y'
  dst_json = JSON.parse(@pack.read)
  return if dst_json == src_json

  # merge packages.json
  src_json, dst_json = [dst_json, src_json] if pack_input == 'a'
  dst_json.deep_merge!(src_json)
  @pack.write(JSON.pretty_generate(dst_json))
  @pending_install = true
end