class ViteRuby::Builder

Experimental RBS support (using type sampling data from the type_fusion project).

# sig/vite_ruby/builder.rbs

class ViteRuby::Builder
  def last_build_metadata: (ssr: false) -> ViteRuby::Build
end

Public: Keeps track of watched files and triggers builds as needed.

def build(*args)

and triggers a Vite build if any files have changed.
Public: Checks if the watched files have changed since the last compilation,
def build(*args)
  last_build = last_build_metadata(ssr: args.include?('--ssr'))
  if args.delete('--force') || last_build.stale? || config.manifest_paths.empty?
    stdout, stderr, status = build_with_vite(*args)
    log_build_result(stdout, stderr, status)
    record_build_metadata(last_build, errors: stderr, success: status.success?)
    status.success?
  elsif last_build.success
    logger.debug "Skipping vite build. Watched files have not changed since the last build at #{ last_build.timestamp }"
    true
  else
    logger.error "Skipping vite build. Watched files have not changed since the build failed at #{ last_build.timestamp } ❌"
    false
  end
end

def build_with_vite(*args)

Public: Initiates a Vite build command to generate assets.
def build_with_vite(*args)
  logger.info 'Building with Vite ⚡️'
  run(['build', *args])
end

def initialize(vite_ruby)

def initialize(vite_ruby)
  @vite_ruby = vite_ruby
end

def last_build_metadata(ssr: false)

Experimental RBS support (using type sampling data from the type_fusion project).

def last_build_metadata: (ssr: false) -> ViteRuby::Build

This signature was generated using 1 sample from 1 application.

Internal: Reads the result of the last compilation from disk.
def last_build_metadata(ssr: false)
  ViteRuby::Build.from_previous(last_build_path(ssr: ssr), watched_files_digest)
end

def last_build_path(ssr:)

Internal: The file path where metadata of the last build is stored.
def last_build_path(ssr:)
  config.build_cache_dir.join("last#{ '-ssr' if ssr }-build-#{ config.mode }.json")
end

def log_build_result(_stdout, stderr, status)

NOTE: By default it also outputs the manifest entries.

Internal: Outputs the build results.
def log_build_result(_stdout, stderr, status)
  if status.success?
    logger.info "Build with Vite complete: #{ config.build_output_dir }"
    logger.error stderr unless stderr.empty?
  else
    logger.error stderr
    logger.error status
    logger.error 'Build with Vite failed! ❌'
    logger.error '❌ Check that vite and vite-plugin-ruby are in devDependencies and have been installed. ' if stderr.include?('ERR! canceled')
  end
end

def record_build_metadata(build, **attrs)

Internal: Writes a digest of the watched files to disk for future checks.
def record_build_metadata(build, **attrs)
  config.build_cache_dir.mkpath
  build.with_result(**attrs).write_to_cache
end

def watched_files_digest

changes, and skip Vite builds if no files have changed.
Internal: Returns a digest of all the watched files, allowing to detect
def watched_files_digest
  return @last_digest if @last_digest_at && Time.now - @last_digest_at < 1
  config.within_root do
    files = Dir[*config.watched_paths].reject { |f| File.directory?(f) }
    file_ids = files.sort.map { |f| "#{ File.basename(f) }/#{ Digest::SHA1.file(f).hexdigest }" }
    @last_digest_at = Time.now
    @last_digest = Digest::SHA1.hexdigest(file_ids.join('/'))
  end
end