lib/svelte_on_rails/lib/utils.rb
module SvelteOnRails module Lib class Utils def self.gem_app_dir File.expand_path('../../svelte_on_rails', __dir__) + '/' end def self.asset_path(filename) config = SvelteOnRails::Configuration.instance path = (config.frontend_folder + config.components_folder).join(filename) manifest = config.ssr_manifest manifest[path.to_s.sub(/\.svelte$/, '') + '.svelte']['file'] end def self.file_exist_case_sensitive?(containing_dir, filename) # Combine the directory path and filename full_path = File.join(containing_dir, filename) # Check if the file exists and the path matches case-sensitively File.exist?(full_path) && Dir[File.join(containing_dir, "**/*")].any? do |f| f == full_path end end def self.component_files(filename, base_path: SvelteOnRails::Configuration.instance.components_folder_full) fn = (filename.match(/\.svelte$/) ? filename[0..-8] : filename) svelte_file = (base_path + fn).to_s + '.svelte' svelte_filename = fn + '.svelte' cnf = SvelteOnRails::Configuration.instance cf = cnf.rails_root.join('public', 'vite-ssr', asset_path(filename).sub(/.js$/, '')) { svelte_file: svelte_file, svelte_filename: svelte_filename, compiled_file: cf.to_s } end def self.watch_changes_and_precompile config = SvelteOnRails::Configuration.instance return unless config.watch_changes? mtime = Dir[File.join(config.components_folder_full, '**/*.svelte')].map do |file| File.mtime(file).to_f end.max || 0.0 last = if Dir.exist?(config.ssr_dist_folder) mtime_path = config.ssr_dist_folder.join('last_mtime') (File.exist?(mtime_path) ? File.read(mtime_path).to_f : 0.0) end if !last || mtime > last precompile(mtime) end end def self.precompile(last_mtime = nil) config = SvelteOnRails::Configuration.instance # run build cmd = "#{config.rails_root.join('node_modules', '.bin', 'vite')} build --config vite-ssr.config.ts" stdout, stderr, status = Open3.capture3(cmd) warnings = stderr.to_s.split("\n") errors_matcher = Regexp.new('(Could not resolve|failed to resolve)') error_lines = warnings.select { |e| e.match(errors_matcher) } have_error = error_lines.present? || status.to_s.match(/exit 1/) # error handling if stderr.present? red_background = "\033[97;41m" light_blue_background = "\033[30;106m" clear_colors = "\033[0m" msg = " +++ #{have_error ? 'ERROR' : 'WARNING'} compiling Svelte components#{have_error ? ' failed' : ''} («#{cmd}») +++ " puts "#{have_error ? red_background : light_blue_background}#{msg}#{clear_colors}" warnings.each do |e| if e.match(errors_matcher) red_font = "\033[31m" puts "#{red_background} #{clear_colors}#{red_font} #{e}#{clear_colors}" else puts "#{light_blue_background} #{clear_colors}#{e}" end end if have_error puts "#{red_background} +++ End of error message +++ #{clear_colors}" else puts "#{light_blue_background} +++ End of compiling warnings +++ #{clear_colors}" end puts "#{have_error ? red_background : light_blue_background} +++ Run «npm run build:ssr» on the console to see the original error message +++ #{clear_colors}" if have_error cl_str = if error_lines.present? "#{error_lines.join("\n")}\n\n" end raise "Svelte components compilation failed\n\n#{cl_str}Full message:\n+++\n#{stderr}+++\n\nYou can run «npm run build:ssr» on the console to see the original error message\n" end end puts stdout unless Dir.exist?(config.ssr_dist_folder) raise "Could not find dist folder: #{config.ssr_dist_folder}" end if last_mtime mtime_path = config.ssr_dist_folder.join('last_mtime') File.write(mtime_path, last_mtime.to_s) end end # Defining methods to log errors and warnings using Rails logger def self.puts_error(text) # Using Rails logger to log error with custom formatting caller_info = caller[1] =~ /`([^']*)'/ ? $1 : "unknown" Rails.logger.error(" => [svelte-on-rails] #{caller_info} ERROR") text.split("\n").each do |line| Rails.logger.error(" => #{line}") end end # Defining method to log warnings using Rails logger def self.puts_warning(text) # Using Rails logger to log warning with custom formatting caller_info = caller[1] =~ /`([^']*)'/ ? $1 : "unknown" Rails.logger.warn(" => [svelte-on-rails] #{caller_info} WARNING \e[0m") text.split("\n").each do |line| Rails.logger.warn(" => #{line}") end end end end end