lib/svelte_on_rails/renderer/renderer.rb



module SvelteOnRails
  class Renderer

    require 'open3'

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

      config = SvelteOnRails::Configuration.instance

      unless system("#{config.node_bin_path} --version > /dev/null 2>&1")
        raise "Node.js not found at '#{config.node_bin_path}'. Please configure SvelteOnRails.node_bin (e.g., to ~/.nvm/versions/node/vX.Y.Z/bin/node) or ensure 'node' is in the PATH. If using NVM, run `nvm which default` to find the path."
      end

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

    end

    # render

    def render(props = {})
      require 'base64'
      require 'json'
      utils = SvelteOnRails::Lib::Utils
      cnf = SvelteOnRails::Configuration.instance

      cmd = [
        cnf.node_bin_path,
        File.join(utils.gem_app_dir, 'renderer', 'render.js'),
        @component_files[:compiled_file] + '.js',
        cnf.rails_root
      ].join(' ')

      Dir.chdir(cnf.rails_root) do
        stdout, stderr, status = Open3.capture3(cmd, stdin_data: props.to_json)

        ary = stdout.split('[svelte-on-rails:successful-json-response]')

        unless ary.length == 2
          raise "[svelte-on-rails] render ERROR for component: #{@component_files[:svelte_filename]}\n\ncommand:\n+++\n#{cmd}\n+++\n\nstdout:\n+++\n#{stdout}+++\n\n\nstderr:\n+++\n#{stderr}+++"
        end


        begin


          res = JSON.parse(ary[1])
          css_file = @component_files[:compiled_file] + '.css'
          if File.exist?(css_file)
            res['css'] = File.read(css_file)
          end

          unless status.to_s.match(/^pid [0-9]+ exit 0$/)
            cmp = "#{@component_files[:svelte_filename]} was returned «#{status.to_s}»\n\n"
            msg = "#{cmp}output from render.js (stderr) =>\n+++\n" + stderr + "+++\n\nRender Svelte Server-side =>\n#{cmd}\n\n"
            utils.puts_warning(msg)
          end

          return res
        rescue JSON::ParserError => e

          raise "[svelte-on-rails] render ERROR Svelte Server-side for component: #{@component_files[:svelte_filename]}\n\nError message:\n+++\n#{e.message}\n+++\n\nstdout:\n+++\n#{stdout}+++\n\n\nstderr:\n+++\n#{stderr}+++"
        end
      end
    end

  end
end