lib/svelte_on_rails/compiler/compiler.rb



module SvelteOnRails

  class Compiler

    require 'open3'

    def initialize(filename, base_path: SvelteOnRails::Configuration.instance.components_folder_full)

      utils = SvelteOnRails::Lib::Utils
      @files = utils.component_files(filename, base_path: base_path)

    end

    # compiler
    def compile_if_changes

      # letzte Änderung innerhalb des ordners ermitteln

      watch_changes = SvelteOnRails::Configuration.instance.watch_changes?
      ts_file = SvelteOnRails::Configuration.instance.dist_folder.join('reset_timestamp')

      have_changes = if watch_changes && File.exist?(ts_file)

                       # compare last modification timestamp
                       last_modification = 100.years.ago.to_time
                       Dir.glob("#{SvelteOnRails::Configuration.instance.components_folder}**/*").each do |path|
                         if File.file?(path)
                           mtime = File.mtime(path)
                           if mtime > last_modification
                             last_modification = mtime
                           end
                         end
                       end
                       File.mtime(ts_file) < last_modification

                     elsif watch_changes
                       true
                     elsif !File.exist?(ts_file)
                       true
                     else
                       false
                     end

      if have_changes || !File.exist?(compiled_js_file) || !File.exist?(compiled_css_file)
        if have_changes || (!File.exist?(ts_file) && watch_changes)
          self.class.reset_dist
        end
        compile
      end
    end

    def compiled_js_file
      @files[:compiled_file] + '.js'
    end

    def compiled_css_file
      @files[:compiled_file] + '.css'
    end

    def compiled_file
      @files[:compiled_file]
    end

    def compile

      start_time = Time.now

      cnf = SvelteOnRails::Configuration.instance
      subs = @files[:svelte_filename].split('/')[0..-2].join('/')
      dist = cnf.dist_folder + cnf.components_folder + subs
      utils = SvelteOnRails::Lib::Utils

      cmd = [
        'node',
        utils.gem_app_dir + 'compiler/compile.js',
        @files[:svelte_file],
        dist,
        utils.gem_app_dir
      ].join(' ')

      Dir.chdir(cnf.rails_root) do
        env = { 'NODE_PATH' => File.join(cnf.rails_root, 'node_modules') }

        stdout, stderr, status = Open3.capture3(env, cmd, chdir: cnf.rails_root)

        unless status.to_s.match(/^pid [0-9]+ exit 0$/)
          raise "Compiling «#{@files[:svelte_filename]}» Server-side, script compile.js, executed within Rails.root:\n\n#{cmd}\n\n++++++\n\n#{stderr}\n\n++++++\n\n"
        end
      end

      time = Time.now - start_time
      Rails.logger.info "  Compiled #{@files[:svelte_filename]}.js: #{time.round(3)}ms" rescue nil
    end

    def self.reset_dist
      unless Dir.exist?(SvelteOnRails::Configuration.instance.dist_folder)
        FileUtils.mkdir_p(SvelteOnRails::Configuration.instance.dist_folder)
      end
      FileUtils.rm_rf Dir.glob("#{SvelteOnRails::Configuration.instance.dist_folder}/*")
      FileUtils.touch SvelteOnRails::Configuration.instance.dist_folder.join('reset_timestamp')
    end

    def self.reset_and_compile_all
      SvelteOnRails::RenderServerSide.reset_dist
      cnf = SvelteOnRails::Configuration.instance
      frontend_folder = cnf.frontend_folder_full
      sveltes = Dir.glob(cnf.frontend_folder_full.join('**/*.svelte'))
      sveltes.each_with_index do |file, ind|
        comp_name = file.to_s[(cnf.frontend_folder_full.to_s.length + 1)..-1]

        n = SvelteOnRails::RenderServerSide.new(comp_name, base_path: frontend_folder)
        n.compile

        puts "compiled #{ind + 1}/#{sveltes.length}: #{comp_name}"

      end
    end

  end
end