vite_ruby 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/CHANGELOG.md +3 -0
 - data/CONTRIBUTING.md +33 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +82 -0
 - data/default.vite.json +17 -0
 - data/exe/vite +10 -0
 - data/lib/tasks/vite.rake +51 -0
 - data/lib/vite_ruby.rb +125 -0
 - data/lib/vite_ruby/builder.rb +103 -0
 - data/lib/vite_ruby/cli.rb +14 -0
 - data/lib/vite_ruby/cli/build.rb +18 -0
 - data/lib/vite_ruby/cli/dev.rb +12 -0
 - data/lib/vite_ruby/cli/install.rb +122 -0
 - data/lib/vite_ruby/cli/version.rb +9 -0
 - data/lib/vite_ruby/commands.rb +153 -0
 - data/lib/vite_ruby/config.rb +152 -0
 - data/lib/vite_ruby/dev_server_proxy.rb +62 -0
 - data/lib/vite_ruby/manifest.rb +168 -0
 - data/lib/vite_ruby/runner.rb +57 -0
 - data/lib/vite_ruby/version.rb +5 -0
 - data/templates/config/vite.config.ts +8 -0
 - data/templates/config/vite.json +15 -0
 - data/templates/entrypoints/application.js +8 -0
 - metadata +153 -0
 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'dry/cli'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # Public: Command line interface that allows to install the library, and run
         
     | 
| 
      
 6 
     | 
    
         
            +
            # simple commands.
         
     | 
| 
      
 7 
     | 
    
         
            +
            class ViteRuby::CLI
         
     | 
| 
      
 8 
     | 
    
         
            +
              extend Dry::CLI::Registry
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              register 'build', Build, aliases: ['b']
         
     | 
| 
      
 11 
     | 
    
         
            +
              register 'dev', Dev, aliases: %w[d serve]
         
     | 
| 
      
 12 
     | 
    
         
            +
              register 'install', Install, aliases: %w[setup init]
         
     | 
| 
      
 13 
     | 
    
         
            +
              register 'version', Version, aliases: ['v', '-v', '--version', 'info']
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class ViteRuby::CLI::Build < Dry::CLI::Command
         
     | 
| 
      
 4 
     | 
    
         
            +
              CURRENT_ENV = ENV['RACK_ENV'] || ENV['RAILS_ENV']
         
     | 
| 
      
 5 
     | 
    
         
            +
              DEFAULT_ENV = CURRENT_ENV || 'production'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              def self.shared_options
         
     | 
| 
      
 8 
     | 
    
         
            +
                option(:mode, default: self::DEFAULT_ENV, values: %w[development production], aliases: ['m'], desc: 'The build mode for Vite.')
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              desc 'Bundle all entrypoints using Vite.'
         
     | 
| 
      
 12 
     | 
    
         
            +
              shared_options
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def call(mode:)
         
     | 
| 
      
 15 
     | 
    
         
            +
                ViteRuby.env['VITE_RUBY_MODE'] = mode
         
     | 
| 
      
 16 
     | 
    
         
            +
                block_given? ? yield(mode) : ViteRuby.commands.build_from_task
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class ViteRuby::CLI::Dev < ViteRuby::CLI::Build
         
     | 
| 
      
 4 
     | 
    
         
            +
              DEFAULT_ENV = CURRENT_ENV || 'development'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              desc 'Start the Vite development server.'
         
     | 
| 
      
 7 
     | 
    
         
            +
              shared_options
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def call(mode:, args: [])
         
     | 
| 
      
 10 
     | 
    
         
            +
                super(mode: mode) { ViteRuby.run(args) }
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,122 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'dry/cli/utils/files'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'stringio'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'open3'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            class ViteRuby::CLI::Install < Dry::CLI::Command
         
     | 
| 
      
 8 
     | 
    
         
            +
              desc 'Performs the initial configuration setup to get started with Vite Ruby.'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def call(**)
         
     | 
| 
      
 11 
     | 
    
         
            +
                $stdout.sync = true
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                say 'Creating binstub'
         
     | 
| 
      
 14 
     | 
    
         
            +
                ViteRuby.commands.install_binstubs
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                say 'Creating configuration files'
         
     | 
| 
      
 17 
     | 
    
         
            +
                create_configuration_files
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                say 'Installing sample files'
         
     | 
| 
      
 20 
     | 
    
         
            +
                install_sample_files
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                say 'Installing js dependencies'
         
     | 
| 
      
 23 
     | 
    
         
            +
                install_js_dependencies
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                say 'Adding files to .gitignore'
         
     | 
| 
      
 26 
     | 
    
         
            +
                install_gitignore
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                say "\nVite ⚡️ Ruby successfully installed! 🎉"
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            protected
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              # Internal: Setup for a plain Rack application.
         
     | 
| 
      
 34 
     | 
    
         
            +
              def setup_app_files
         
     | 
| 
      
 35 
     | 
    
         
            +
                copy_template 'config/vite.json', to: config.config_path
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                if (rackup_file = root.join('config.ru')).exist?
         
     | 
| 
      
 38 
     | 
    
         
            +
                  inject_line_after_last rackup_file, 'require', 'use(ViteRuby::DevServerProxy, ssl_verify_none: true) if ViteRuby.run_proxy?'
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              # Internal: Create a sample JS file and attempt to inject it in an HTML template.
         
     | 
| 
      
 43 
     | 
    
         
            +
              def install_sample_files
         
     | 
| 
      
 44 
     | 
    
         
            +
                copy_template 'entrypoints/application.js', to: config.resolved_entrypoints_dir.join('application.js')
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            private
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              extend Forwardable
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              def_delegators 'ViteRuby', :config
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              %i[append cp inject_line_after inject_line_after_last inject_line_before write].each do |util|
         
     | 
| 
      
 54 
     | 
    
         
            +
                define_method(util) { |*args, **opts, &block|
         
     | 
| 
      
 55 
     | 
    
         
            +
                  Dry::CLI::Utils::Files.send(util, *args, **opts, &block) rescue nil
         
     | 
| 
      
 56 
     | 
    
         
            +
                }
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              TEMPLATES_PATH = Pathname.new(File.expand_path('../../../templates', __dir__))
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              def copy_template(path, to:)
         
     | 
| 
      
 62 
     | 
    
         
            +
                cp TEMPLATES_PATH.join(path), to
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              # Internal: Creates the Vite and vite-plugin-ruby configuration files.
         
     | 
| 
      
 66 
     | 
    
         
            +
              def create_configuration_files
         
     | 
| 
      
 67 
     | 
    
         
            +
                copy_template 'config/vite.config.ts', to: root.join('vite.config.ts')
         
     | 
| 
      
 68 
     | 
    
         
            +
                setup_app_files
         
     | 
| 
      
 69 
     | 
    
         
            +
                ViteRuby.reload_with('VITE_RUBY_CONFIG_PATH' => config.config_path)
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              # Internal: Installs vite and vite-plugin-ruby at the project level.
         
     | 
| 
      
 73 
     | 
    
         
            +
              def install_js_dependencies
         
     | 
| 
      
 74 
     | 
    
         
            +
                package_json = root.join('package.json')
         
     | 
| 
      
 75 
     | 
    
         
            +
                write(package_json, '{}') unless package_json.exist?
         
     | 
| 
      
 76 
     | 
    
         
            +
                Dir.chdir(root) do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  deps = "vite@#{ ViteRuby::DEFAULT_VITE_VERSION } vite-plugin-ruby@#{ ViteRuby::DEFAULT_PLUGIN_VERSION }"
         
     | 
| 
      
 78 
     | 
    
         
            +
                  stdout, stderr, status = Open3.capture3({ 'CI' => 'true' }, "npx ni -D #{ deps }")
         
     | 
| 
      
 79 
     | 
    
         
            +
                  stdout, stderr, = Open3.capture3({}, "yarn add -D #{ deps }") unless status.success?
         
     | 
| 
      
 80 
     | 
    
         
            +
                  say(stdout, "\n", stderr)
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              # Internal: Adds compilation output dirs to git ignore.
         
     | 
| 
      
 85 
     | 
    
         
            +
              def install_gitignore
         
     | 
| 
      
 86 
     | 
    
         
            +
                return unless (gitignore_file = root.join('.gitignore')).exist?
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                append(gitignore_file, <<~GITIGNORE)
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  # Vite Ruby
         
     | 
| 
      
 91 
     | 
    
         
            +
                  /public/vite
         
     | 
| 
      
 92 
     | 
    
         
            +
                  /public/vite-dev
         
     | 
| 
      
 93 
     | 
    
         
            +
                  /public/vite-test
         
     | 
| 
      
 94 
     | 
    
         
            +
                  node_modules
         
     | 
| 
      
 95 
     | 
    
         
            +
                  *.local
         
     | 
| 
      
 96 
     | 
    
         
            +
                  .DS_Store
         
     | 
| 
      
 97 
     | 
    
         
            +
                GITIGNORE
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              # Internal: The root path for the Ruby application.
         
     | 
| 
      
 101 
     | 
    
         
            +
              def root
         
     | 
| 
      
 102 
     | 
    
         
            +
                @root ||= silent_warnings { config.root }
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              def say(*args)
         
     | 
| 
      
 106 
     | 
    
         
            +
                $stdout.puts(*args)
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              # Internal: Avoid printing warning about missing vite.json, we will create one.
         
     | 
| 
      
 110 
     | 
    
         
            +
              def silent_warnings
         
     | 
| 
      
 111 
     | 
    
         
            +
                old_stderr = $stderr
         
     | 
| 
      
 112 
     | 
    
         
            +
                $stderr = StringIO.new
         
     | 
| 
      
 113 
     | 
    
         
            +
                yield
         
     | 
| 
      
 114 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 115 
     | 
    
         
            +
                $stderr = old_stderr
         
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
      
 117 
     | 
    
         
            +
            end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            # NOTE: This allows framework-specific variants to extend the installation.
         
     | 
| 
      
 120 
     | 
    
         
            +
            ViteRuby.framework_libraries.each do |_framework, library|
         
     | 
| 
      
 121 
     | 
    
         
            +
              require "#{ library.name }/installation"
         
     | 
| 
      
 122 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,153 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Public: Encapsulates common tasks, available both programatically and from the
         
     | 
| 
      
 4 
     | 
    
         
            +
            # CLI and Rake tasks.
         
     | 
| 
      
 5 
     | 
    
         
            +
            class ViteRuby::Commands
         
     | 
| 
      
 6 
     | 
    
         
            +
              def initialize(vite_ruby)
         
     | 
| 
      
 7 
     | 
    
         
            +
                @vite_ruby = vite_ruby
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # Public: Defaults to production, and exits if the build fails.
         
     | 
| 
      
 11 
     | 
    
         
            +
              def build_from_task
         
     | 
| 
      
 12 
     | 
    
         
            +
                with_node_env(ENV.fetch('NODE_ENV', 'production')) {
         
     | 
| 
      
 13 
     | 
    
         
            +
                  ensure_log_goes_to_stdout {
         
     | 
| 
      
 14 
     | 
    
         
            +
                    build || exit!
         
     | 
| 
      
 15 
     | 
    
         
            +
                  }
         
     | 
| 
      
 16 
     | 
    
         
            +
                }
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # Public: Builds all assets that are managed by Vite, from the entrypoints.
         
     | 
| 
      
 20 
     | 
    
         
            +
              def build
         
     | 
| 
      
 21 
     | 
    
         
            +
                builder.build.tap { manifest.refresh }
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              # Public: Removes all build cache and previously compiled assets.
         
     | 
| 
      
 25 
     | 
    
         
            +
              def clobber
         
     | 
| 
      
 26 
     | 
    
         
            +
                config.build_output_dir.rmtree if config.build_output_dir.exist?
         
     | 
| 
      
 27 
     | 
    
         
            +
                config.build_cache_dir.rmtree if config.build_cache_dir.exist?
         
     | 
| 
      
 28 
     | 
    
         
            +
                config.vite_cache_dir.rmtree if config.vite_cache_dir.exist?
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Public: Receives arguments from a rake task.
         
     | 
| 
      
 32 
     | 
    
         
            +
              def clean_from_task(args)
         
     | 
| 
      
 33 
     | 
    
         
            +
                ensure_log_goes_to_stdout {
         
     | 
| 
      
 34 
     | 
    
         
            +
                  clean(keep_up_to: Integer(args.keep || 2), age_in_seconds: Integer(args.age || 3600))
         
     | 
| 
      
 35 
     | 
    
         
            +
                }
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              # Public: Cleanup old assets in the output directory.
         
     | 
| 
      
 39 
     | 
    
         
            +
              #
         
     | 
| 
      
 40 
     | 
    
         
            +
              # keep_up_to - Max amount of backups to preserve.
         
     | 
| 
      
 41 
     | 
    
         
            +
              # age_in_seconds - Amount of time to look back in order to preserve them.
         
     | 
| 
      
 42 
     | 
    
         
            +
              #
         
     | 
| 
      
 43 
     | 
    
         
            +
              # NOTE: By default keeps the last version, or 2 if created in the past hour.
         
     | 
| 
      
 44 
     | 
    
         
            +
              #
         
     | 
| 
      
 45 
     | 
    
         
            +
              # Examples:
         
     | 
| 
      
 46 
     | 
    
         
            +
              #   To force only 1 backup to be kept: clean(1, 0)
         
     | 
| 
      
 47 
     | 
    
         
            +
              #   To only keep files created within the last 10 minutes: clean(0, 600)
         
     | 
| 
      
 48 
     | 
    
         
            +
              def clean(keep_up_to: 2, age_in_seconds: 3600)
         
     | 
| 
      
 49 
     | 
    
         
            +
                return false unless may_clean?
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                versions
         
     | 
| 
      
 52 
     | 
    
         
            +
                  .each_with_index
         
     | 
| 
      
 53 
     | 
    
         
            +
                  .drop_while { |(mtime, _), index|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    max_age = [0, Time.now - Time.at(mtime)].max
         
     | 
| 
      
 55 
     | 
    
         
            +
                    max_age < age_in_seconds || index < keep_up_to
         
     | 
| 
      
 56 
     | 
    
         
            +
                  }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  .each do |(_, files), _|
         
     | 
| 
      
 58 
     | 
    
         
            +
                    clean_files(files)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                true
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              # Internal: Installs the binstub for the CLI in the appropriate path.
         
     | 
| 
      
 64 
     | 
    
         
            +
              def install_binstubs
         
     | 
| 
      
 65 
     | 
    
         
            +
                `bundle binstub vite_ruby --path #{ config.root.join('bin') }`
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              # Internal: Verifies if ViteRuby is properly installed.
         
     | 
| 
      
 69 
     | 
    
         
            +
              def verify_install
         
     | 
| 
      
 70 
     | 
    
         
            +
                unless File.exist?(config.root.join('bin/vite'))
         
     | 
| 
      
 71 
     | 
    
         
            +
                  warn <<~WARN
         
     | 
| 
      
 72 
     | 
    
         
            +
                    vite binstub not found.
         
     | 
| 
      
 73 
     | 
    
         
            +
                    Have you run `bundle binstub vite`?
         
     | 
| 
      
 74 
     | 
    
         
            +
                    Make sure the bin directory and bin/vite are not included in .gitignore
         
     | 
| 
      
 75 
     | 
    
         
            +
                  WARN
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                config_path = config.root.join(config.config_path)
         
     | 
| 
      
 79 
     | 
    
         
            +
                unless config_path.exist?
         
     | 
| 
      
 80 
     | 
    
         
            +
                  warn <<~WARN
         
     | 
| 
      
 81 
     | 
    
         
            +
                    Configuration #{ config_path } file for vite-plugin-ruby not found.
         
     | 
| 
      
 82 
     | 
    
         
            +
                    Make sure `bundle exec vite install` has run successfully before running dependent tasks.
         
     | 
| 
      
 83 
     | 
    
         
            +
                  WARN
         
     | 
| 
      
 84 
     | 
    
         
            +
                  exit!
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              # Internal: Prints information about ViteRuby's environment.
         
     | 
| 
      
 89 
     | 
    
         
            +
              def print_info
         
     | 
| 
      
 90 
     | 
    
         
            +
                Dir.chdir(config.root) do
         
     | 
| 
      
 91 
     | 
    
         
            +
                  $stdout.puts "Is bin/vite present?: #{ File.exist? 'bin/vite' }"
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  $stdout.puts "vite_ruby: #{ ViteRuby::VERSION }"
         
     | 
| 
      
 94 
     | 
    
         
            +
                  ViteRuby.framework_libraries.each do |framework, library|
         
     | 
| 
      
 95 
     | 
    
         
            +
                    $stdout.puts "#{ library.name }: #{ library.version }"
         
     | 
| 
      
 96 
     | 
    
         
            +
                    $stdout.puts "#{ framework }: #{ Gem.loaded_specs[framework]&.version }"
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  $stdout.puts "node: #{ `node --version` }"
         
     | 
| 
      
 100 
     | 
    
         
            +
                  $stdout.puts "npm: #{ `npm --version` }"
         
     | 
| 
      
 101 
     | 
    
         
            +
                  $stdout.puts "yarn: #{ `yarn --version` }"
         
     | 
| 
      
 102 
     | 
    
         
            +
                  $stdout.puts "ruby: #{ `ruby --version` }"
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  $stdout.puts "\n"
         
     | 
| 
      
 105 
     | 
    
         
            +
                  $stdout.puts "vite-plugin-ruby: \n#{ `npm list vite-plugin-ruby version` }"
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            private
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
              extend Forwardable
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              def_delegators :@vite_ruby, :config, :builder, :manifest, :logger, :logger=
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              def may_clean?
         
     | 
| 
      
 116 
     | 
    
         
            +
                config.build_output_dir.exist? && config.manifest_path.exist?
         
     | 
| 
      
 117 
     | 
    
         
            +
              end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
              def clean_files(files)
         
     | 
| 
      
 120 
     | 
    
         
            +
                files.select { |file| File.file?(file) }.each do |file|
         
     | 
| 
      
 121 
     | 
    
         
            +
                  File.delete(file)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  logger.info("Removed #{ file }")
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              def versions
         
     | 
| 
      
 127 
     | 
    
         
            +
                all_files = Dir.glob("#{ config.build_output_dir }/**/*")
         
     | 
| 
      
 128 
     | 
    
         
            +
                entries = all_files - [config.manifest_path] - current_version_files
         
     | 
| 
      
 129 
     | 
    
         
            +
                entries.reject { |file| File.directory?(file) }
         
     | 
| 
      
 130 
     | 
    
         
            +
                  .group_by { |file| File.mtime(file).utc.to_i }
         
     | 
| 
      
 131 
     | 
    
         
            +
                  .sort.reverse
         
     | 
| 
      
 132 
     | 
    
         
            +
              end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
              def current_version_files
         
     | 
| 
      
 135 
     | 
    
         
            +
                Dir.glob(manifest.refresh.values.map { |value| config.build_output_dir.join("#{ value['file'] }*") })
         
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
              def with_node_env(env)
         
     | 
| 
      
 139 
     | 
    
         
            +
                original = ENV['NODE_ENV']
         
     | 
| 
      
 140 
     | 
    
         
            +
                ENV['NODE_ENV'] = env
         
     | 
| 
      
 141 
     | 
    
         
            +
                yield
         
     | 
| 
      
 142 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 143 
     | 
    
         
            +
                ENV['NODE_ENV'] = original
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
              def ensure_log_goes_to_stdout
         
     | 
| 
      
 147 
     | 
    
         
            +
                old_logger = logger
         
     | 
| 
      
 148 
     | 
    
         
            +
                self.logger = Logger.new($stdout)
         
     | 
| 
      
 149 
     | 
    
         
            +
                yield
         
     | 
| 
      
 150 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 151 
     | 
    
         
            +
                self.logger = old_logger
         
     | 
| 
      
 152 
     | 
    
         
            +
              end
         
     | 
| 
      
 153 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,152 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # Public: Allows to resolve configuration sourced from `config/vite.json` and
         
     | 
| 
      
 6 
     | 
    
         
            +
            # environment variables, combining them with the default options.
         
     | 
| 
      
 7 
     | 
    
         
            +
            class ViteRuby::Config
         
     | 
| 
      
 8 
     | 
    
         
            +
              def protocol
         
     | 
| 
      
 9 
     | 
    
         
            +
                https ? 'https' : 'http'
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def host_with_port
         
     | 
| 
      
 13 
     | 
    
         
            +
                "#{ host }:#{ port }"
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              # Internal: Path where Vite outputs the manifest file.
         
     | 
| 
      
 17 
     | 
    
         
            +
              def manifest_path
         
     | 
| 
      
 18 
     | 
    
         
            +
                build_output_dir.join('manifest.json')
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              # Internal: Path where vite-plugin-ruby outputs the assets manifest file.
         
     | 
| 
      
 22 
     | 
    
         
            +
              def assets_manifest_path
         
     | 
| 
      
 23 
     | 
    
         
            +
                build_output_dir.join('manifest-assets.json')
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # Public: The directory where Vite will store the built assets.
         
     | 
| 
      
 27 
     | 
    
         
            +
              def build_output_dir
         
     | 
| 
      
 28 
     | 
    
         
            +
                root.join(public_dir, public_output_dir)
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Public: The directory where the entries are located.
         
     | 
| 
      
 32 
     | 
    
         
            +
              def resolved_entrypoints_dir
         
     | 
| 
      
 33 
     | 
    
         
            +
                root.join(source_code_dir, entrypoints_dir)
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              # Internal: The directory where Vite stores its processing cache.
         
     | 
| 
      
 37 
     | 
    
         
            +
              def vite_cache_dir
         
     | 
| 
      
 38 
     | 
    
         
            +
                root.join('node_modules/.vite')
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              # Public: Sets additional environment variables for vite-plugin-ruby.
         
     | 
| 
      
 42 
     | 
    
         
            +
              def to_env
         
     | 
| 
      
 43 
     | 
    
         
            +
                CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env|
         
     | 
| 
      
 44 
     | 
    
         
            +
                  unless (value = @config[option]).nil?
         
     | 
| 
      
 45 
     | 
    
         
            +
                    env["#{ ViteRuby::ENV_PREFIX }_#{ option.upcase }"] = value.to_s
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end.merge(ViteRuby.env)
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            private
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              # Internal: Coerces all the configuration values, in case they were passed
         
     | 
| 
      
 53 
     | 
    
         
            +
              # as environment variables which are always strings.
         
     | 
| 
      
 54 
     | 
    
         
            +
              def coerce_values(config)
         
     | 
| 
      
 55 
     | 
    
         
            +
                config['mode'] = config['mode'].to_s
         
     | 
| 
      
 56 
     | 
    
         
            +
                config['port'] = config['port'].to_i
         
     | 
| 
      
 57 
     | 
    
         
            +
                config['root'] = Pathname.new(config['root'])
         
     | 
| 
      
 58 
     | 
    
         
            +
                config['build_cache_dir'] = config['root'].join(config['build_cache_dir'])
         
     | 
| 
      
 59 
     | 
    
         
            +
                coerce_booleans(config, 'auto_build', 'hide_build_console_output', 'https')
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              # Internal: Coerces configuration options to boolean.
         
     | 
| 
      
 63 
     | 
    
         
            +
              def coerce_booleans(config, *names)
         
     | 
| 
      
 64 
     | 
    
         
            +
                names.each { |name| config[name] = [true, 'true'].include?(config[name]) }
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              def initialize(attrs)
         
     | 
| 
      
 68 
     | 
    
         
            +
                @config = attrs.tap { |config| coerce_values(config) }.freeze
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 72 
     | 
    
         
            +
                private :new
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                # Public: Returns the project configuration for Vite.
         
     | 
| 
      
 75 
     | 
    
         
            +
                def resolve_config(**attrs)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  config = config_defaults.merge(attrs.transform_keys(&:to_s))
         
     | 
| 
      
 77 
     | 
    
         
            +
                  file_path = File.join(config['root'], config['config_path'])
         
     | 
| 
      
 78 
     | 
    
         
            +
                  file_config = config_from_file(file_path, mode: config['mode'])
         
     | 
| 
      
 79 
     | 
    
         
            +
                  new DEFAULT_CONFIG.merge(file_config).merge(config_from_env).merge(config)
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              private
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                # Internal: Converts camelCase to snake_case.
         
     | 
| 
      
 85 
     | 
    
         
            +
                SNAKE_CASE = ->(camel_cased_word) {
         
     | 
| 
      
 86 
     | 
    
         
            +
                  camel_cased_word.to_s.gsub(/::/, '/')
         
     | 
| 
      
 87 
     | 
    
         
            +
                    .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
         
     | 
| 
      
 88 
     | 
    
         
            +
                    .gsub(/([a-z\d])([A-Z])/, '\1_\2')
         
     | 
| 
      
 89 
     | 
    
         
            +
                    .tr('-', '_')
         
     | 
| 
      
 90 
     | 
    
         
            +
                    .downcase
         
     | 
| 
      
 91 
     | 
    
         
            +
                }
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                # Internal: Default values for a Ruby application.
         
     | 
| 
      
 94 
     | 
    
         
            +
                def config_defaults(asset_host: nil, mode: ENV.fetch('RACK_ENV', 'production'), root: Dir.pwd)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  {
         
     | 
| 
      
 96 
     | 
    
         
            +
                    'asset_host' => option_from_env('asset_host') || asset_host,
         
     | 
| 
      
 97 
     | 
    
         
            +
                    'config_path' => option_from_env('config_path') || DEFAULT_CONFIG.fetch('config_path'),
         
     | 
| 
      
 98 
     | 
    
         
            +
                    'mode' => option_from_env('mode') || mode,
         
     | 
| 
      
 99 
     | 
    
         
            +
                    'root' => option_from_env('root') || root,
         
     | 
| 
      
 100 
     | 
    
         
            +
                  }
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                # Internal: Used to load a JSON file from the specified path.
         
     | 
| 
      
 104 
     | 
    
         
            +
                def load_json(path)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  JSON.parse(File.read(File.expand_path(path))).each do |_env, config|
         
     | 
| 
      
 106 
     | 
    
         
            +
                    config.transform_keys!(&SNAKE_CASE) if config.is_a?(Hash)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end.tap do |config|
         
     | 
| 
      
 108 
     | 
    
         
            +
                    config.transform_keys!(&SNAKE_CASE)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                # Internal: Retrieves a configuration option from environment variables.
         
     | 
| 
      
 113 
     | 
    
         
            +
                def option_from_env(name)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  ViteRuby.env["#{ ViteRuby::ENV_PREFIX }_#{ name.upcase }"]
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                # Internal: Extracts the configuration options provided as env vars.
         
     | 
| 
      
 118 
     | 
    
         
            +
                def config_from_env
         
     | 
| 
      
 119 
     | 
    
         
            +
                  CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env_vars|
         
     | 
| 
      
 120 
     | 
    
         
            +
                    if value = option_from_env(option)
         
     | 
| 
      
 121 
     | 
    
         
            +
                      env_vars[option] = value
         
     | 
| 
      
 122 
     | 
    
         
            +
                    end
         
     | 
| 
      
 123 
     | 
    
         
            +
                  end
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                # Internal: Loads the configuration options provided in a JSON file.
         
     | 
| 
      
 127 
     | 
    
         
            +
                def config_from_file(path, mode:)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  multi_env_config = load_json(path)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  multi_env_config.fetch('all', {})
         
     | 
| 
      
 130 
     | 
    
         
            +
                    .merge(multi_env_config.fetch(mode, {}))
         
     | 
| 
      
 131 
     | 
    
         
            +
                rescue Errno::ENOENT => error
         
     | 
| 
      
 132 
     | 
    
         
            +
                  warn "Check that your vite.json configuration file is available in the load path:\n\n\t#{ error.message }\n\n"
         
     | 
| 
      
 133 
     | 
    
         
            +
                  {}
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
              # Internal: Shared configuration with the Vite plugin for Ruby.
         
     | 
| 
      
 138 
     | 
    
         
            +
              DEFAULT_CONFIG = load_json("#{ __dir__ }/../../default.vite.json").freeze
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
              # Internal: Configuration options that can not be provided as env vars.
         
     | 
| 
      
 141 
     | 
    
         
            +
              NOT_CONFIGURABLE_WITH_ENV = %w[watch_additional_paths].freeze
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
              # Internal: Configuration options that can be provided as env vars.
         
     | 
| 
      
 144 
     | 
    
         
            +
              CONFIGURABLE_WITH_ENV = (DEFAULT_CONFIG.keys + %w[mode root] - NOT_CONFIGURABLE_WITH_ENV).freeze
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            public
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
              # Define getters for the configuration options.
         
     | 
| 
      
 149 
     | 
    
         
            +
              (CONFIGURABLE_WITH_ENV + NOT_CONFIGURABLE_WITH_ENV).each do |option|
         
     | 
| 
      
 150 
     | 
    
         
            +
                define_method(option) { @config[option] }
         
     | 
| 
      
 151 
     | 
    
         
            +
              end
         
     | 
| 
      
 152 
     | 
    
         
            +
            end
         
     |