vite_ruby 3.9.2 → 4.0.0.alpha1

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.
@@ -9,7 +9,7 @@ class ViteRuby::Commands
9
9
 
10
10
  # Public: Defaults to production, and exits if the build fails.
11
11
  def build_from_task(*args)
12
- with_node_env(ENV.fetch("NODE_ENV", "production")) {
12
+ with_node_env(ENV.fetch('NODE_ENV', 'production')) {
13
13
  ensure_log_goes_to_stdout {
14
14
  build(*args) || exit!
15
15
  }
@@ -23,30 +23,52 @@ class ViteRuby::Commands
23
23
 
24
24
  # Public: Removes all build cache and previously compiled assets.
25
25
  def clobber
26
- dirs = [config.build_output_dir, config.ssr_output_dir, config.build_cache_dir, config.vite_cache_dir]
26
+ dirs = [config.build_output_dir, config.build_cache_dir, config.vite_cache_dir]
27
27
  dirs.each { |dir| dir.rmtree if dir.exist? }
28
- $stdout.puts "Removed vite cache and output dirs:\n\t#{dirs.join("\n\t")}"
28
+ $stdout.puts "Removed vite cache and output dirs:\n\t#{ dirs.join("\n\t") }"
29
29
  end
30
30
 
31
- # Internal: Installs the binstub for the CLI in the appropriate path.
32
- def install_binstubs
33
- `bundle binstub vite_ruby --path #{config.root.join("bin")}`
34
- `bundle config --delete bin`
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
+ }
35
36
  end
36
37
 
37
- # Internal: Checks if the npm version is 6 or lower.
38
- def legacy_npm_version?
39
- `npm --version`.to_i < 7 rescue false
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
40
61
  end
41
62
 
42
- # Internal: Checks if the yarn version is 1.x.
43
- def legacy_yarn_version?
44
- `yarn --version`.to_i < 2 rescue false
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
+ `bundle config --delete bin`
45
67
  end
46
68
 
47
69
  # Internal: Verifies if ViteRuby is properly installed.
48
70
  def verify_install
49
- unless File.exist?(config.root.join("bin/vite"))
71
+ unless File.exist?(config.root.join('bin/vite'))
50
72
  warn <<~WARN
51
73
 
52
74
  vite binstub not found.
@@ -59,7 +81,7 @@ class ViteRuby::Commands
59
81
  unless config_path.exist?
60
82
  warn <<~WARN
61
83
 
62
- Configuration #{config_path} file for vite-plugin-ruby not found.
84
+ Configuration #{ config_path } file for vite-plugin-ruby not found.
63
85
  Make sure `bundle exec vite install` has run successfully before running dependent tasks.
64
86
  WARN
65
87
  exit!
@@ -68,24 +90,24 @@ class ViteRuby::Commands
68
90
 
69
91
  # Internal: Prints information about ViteRuby's environment.
70
92
  def print_info
71
- config.within_root do
72
- $stdout.puts "bin/vite present?: #{File.exist? "bin/vite"}"
93
+ Dir.chdir(config.root) do
94
+ $stdout.puts "bin/vite present?: #{ File.exist? 'bin/vite' }"
73
95
 
74
- $stdout.puts "vite_ruby: #{ViteRuby::VERSION}"
96
+ $stdout.puts "vite_ruby: #{ ViteRuby::VERSION }"
75
97
  ViteRuby.framework_libraries.each do |framework, library|
76
- $stdout.puts "#{library.name}: #{library.version}"
77
- $stdout.puts "#{framework}: #{Gem.loaded_specs[framework]&.version}"
98
+ $stdout.puts "#{ library.name }: #{ library.version }"
99
+ $stdout.puts "#{ framework }: #{ Gem.loaded_specs[framework]&.version }"
78
100
  end
79
101
 
80
- $stdout.puts "ruby: #{`ruby --version`}"
81
- $stdout.puts "node: #{`node --version`}"
82
-
83
- pkg = config.package_manager
84
- $stdout.puts "#{pkg}: #{`#{pkg} --version` rescue nil}"
102
+ $stdout.puts "node: #{ `node --version` }"
103
+ $stdout.puts "npm: #{ `npm --version` }"
104
+ $stdout.puts "yarn: #{ `yarn --version` rescue nil }"
105
+ $stdout.puts "pnpm: #{ `pnpm --version` rescue nil }"
106
+ $stdout.puts "ruby: #{ `ruby --version` }"
85
107
 
86
108
  $stdout.puts "\n"
87
109
  packages = `npm ls vite vite-plugin-ruby`
88
- packages_msg = packages.include?("vite@") ? "installed packages:\n#{packages}" : "❌ Check that vite and vite-plugin-ruby have been added as development dependencies and installed."
110
+ packages_msg = packages.include?('vite@') ? "installed packages:\n#{ packages }" : '❌ Check that vite and vite-plugin-ruby have been added as development dependencies and installed.'
89
111
  $stdout.puts packages_msg
90
112
 
91
113
  ViteRuby::CompatibilityCheck.verify_plugin_version(config.root)
@@ -98,19 +120,42 @@ private
98
120
 
99
121
  def_delegators :@vite_ruby, :config, :builder, :manifest, :logger, :logger=
100
122
 
123
+ def may_clean?
124
+ config.build_output_dir.exist? && config.manifest_path.exist?
125
+ end
126
+
127
+ def clean_files(files)
128
+ files.select { |file| File.file?(file) }.each do |file|
129
+ File.delete(file)
130
+ logger.info("Removed #{ file }")
131
+ end
132
+ end
133
+
134
+ def versions
135
+ all_files = Dir.glob("#{ config.build_output_dir }/**/*")
136
+ entries = all_files - [config.manifest_path] - current_version_files
137
+ entries.reject { |file| File.directory?(file) }
138
+ .group_by { |file| File.mtime(file).utc.to_i }
139
+ .sort.reverse
140
+ end
141
+
142
+ def current_version_files
143
+ Dir.glob(manifest.refresh.values.map { |value| config.build_output_dir.join("#{ value['file'] }*") })
144
+ end
145
+
101
146
  def with_node_env(env)
102
- original = ENV["NODE_ENV"]
103
- ENV["NODE_ENV"] = env
147
+ original = ENV['NODE_ENV']
148
+ ENV['NODE_ENV'] = env
104
149
  yield
105
150
  ensure
106
- ENV["NODE_ENV"] = original
151
+ ENV['NODE_ENV'] = original
107
152
  end
108
153
 
109
154
  def ensure_log_goes_to_stdout
110
155
  old_logger, original_sync = logger, $stdout.sync
111
156
 
112
157
  $stdout.sync = true
113
- self.logger = Logger.new($stdout, formatter: proc { |_, _, progname, msg| (progname == "vite") ? msg : "#{msg}\n" })
158
+ self.logger = Logger.new($stdout, formatter: proc { |_, _, progname, msg| progname == 'vite' ? msg : "#{ msg }\n" })
114
159
  yield
115
160
  ensure
116
161
  self.logger, $stdout.sync = old_logger, original_sync
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
3
+ require 'json'
4
4
 
5
5
  # Internal: Verifies that the installed vite-plugin-ruby version is compatible
6
6
  # with the current version of vite_ruby.
@@ -11,9 +11,9 @@ module ViteRuby::CompatibilityCheck
11
11
  class << self
12
12
  # Public: Attempt to verify that the vite-plugin-ruby version is compatible.
13
13
  def verify_plugin_version(root)
14
- package = JSON.parse(root.join("package.json").read) rescue {}
15
- requirement = package.dig("devDependencies", "vite-plugin-ruby") ||
16
- package.dig("dependencies", "vite-plugin-ruby")
14
+ package = JSON.parse(root.join('package.json').read) rescue {}
15
+ requirement = package.dig('devDependencies', 'vite-plugin-ruby') ||
16
+ package.dig('dependencies', 'vite-plugin-ruby')
17
17
 
18
18
  raise_unless_satisfied(requirement, ViteRuby::DEFAULT_PLUGIN_VERSION)
19
19
  end
@@ -22,9 +22,9 @@ module ViteRuby::CompatibilityCheck
22
22
  def raise_unless_satisfied(npm_req, ruby_req)
23
23
  unless compatible_plugin?(npm_req, ruby_req)
24
24
  raise ArgumentError, <<~ERROR
25
- vite-plugin-ruby@#{npm_req} might not be compatible with vite_ruby-#{ViteRuby::VERSION}
25
+ vite-plugin-ruby@#{ npm_req } might not be compatible with vite_ruby-#{ ViteRuby::VERSION }
26
26
 
27
- You may disable this check if needed: https://vite-ruby.netlify.app/config/#skipcompatibilitycheck
27
+ You may disable this check if needed: https://vite-ruby.netlify.app/config/#skipCompatibilityCheck
28
28
 
29
29
  You may upgrade both by running:
30
30
 
@@ -37,12 +37,12 @@ module ViteRuby::CompatibilityCheck
37
37
  # requirement.
38
38
  def compatible_plugin?(npm_req, ruby_req)
39
39
  npm_req, ruby_req = [npm_req, ruby_req]
40
- .map { |req| Gem::Requirement.new(req.sub("^", "~>")) }
40
+ .map { |req| Gem::Requirement.new(req.sub('^', '~>')) }
41
41
 
42
42
  current_version = npm_req.requirements.first.second
43
43
 
44
44
  ruby_req.satisfied_by?(current_version)
45
- rescue
45
+ rescue StandardError
46
46
  true
47
47
  end
48
48
  end
@@ -1,36 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
3
+ require 'json'
4
4
 
5
5
  # Public: Allows to resolve configuration sourced from `config/vite.json` and
6
6
  # environment variables, combining them with the default options.
7
7
  class ViteRuby::Config
8
- def origin
9
- "#{protocol}://#{host_with_port}"
10
- end
11
-
12
8
  def protocol
13
- https ? "https" : "http"
9
+ https ? 'https' : 'http'
14
10
  end
15
11
 
16
12
  def host_with_port
17
- "#{host}:#{port}"
13
+ "#{ host }:#{ port }"
18
14
  end
19
15
 
20
- # Internal: Path to the manifest files generated by Vite and vite-plugin-ruby.
21
- def known_manifest_paths
22
- [
23
- # NOTE: Generated by Vite when `manifest: true`, which vite-plugin-ruby enables.
24
- build_output_dir.join(".vite/manifest.json"),
25
-
26
- # NOTE: Path where vite-plugin-ruby outputs the assets manifest file.
27
- build_output_dir.join(".vite/manifest-assets.json"),
28
- ]
16
+ # Internal: Path where Vite outputs the manifest file.
17
+ def manifest_path
18
+ build_output_dir.join('manifest.json')
29
19
  end
30
20
 
31
- # Internal: Path to the manifest files generated by Vite and vite-plugin-ruby.
32
- def manifest_paths
33
- known_manifest_paths.select(&:exist?)
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')
34
24
  end
35
25
 
36
26
  # Public: The directory where Vite will store the built assets.
@@ -45,7 +35,7 @@ class ViteRuby::Config
45
35
 
46
36
  # Internal: The directory where Vite stores its processing cache.
47
37
  def vite_cache_dir
48
- root.join("node_modules/.vite")
38
+ root.join('node_modules/.vite')
49
39
  end
50
40
 
51
41
  # Public: The directory that Vite uses as root.
@@ -55,63 +45,46 @@ class ViteRuby::Config
55
45
 
56
46
  # Public: Loads an optional config/vite.rb file that can modify ViteRuby.env
57
47
  def load_ruby_config
58
- rb_config_path = File.expand_path(config_path.sub(/.json$/, ".rb"), root)
48
+ rb_config_path = File.expand_path(config_path.sub(/.json$/, '.rb'), root)
59
49
  load rb_config_path if File.exist?(rb_config_path)
60
50
  end
61
51
 
62
52
  # Public: Sets additional environment variables for vite-plugin-ruby.
63
- def to_env(env_vars = ViteRuby.env)
53
+ def to_env
64
54
  CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env|
65
55
  unless (value = @config[option]).nil?
66
- env["#{ViteRuby::ENV_PREFIX}_#{option.upcase}"] = value.to_s
56
+ env["#{ ViteRuby::ENV_PREFIX }_#{ option.upcase }"] = value.to_s
67
57
  end
68
- end.merge(env_vars)
58
+ end.merge(ViteRuby.env)
69
59
  end
70
60
 
71
61
  # Internal: Files and directories that should be watched for changes.
72
62
  def watched_paths
73
63
  [
74
64
  *(watch_additional_paths + additional_entrypoints).reject { |dir|
75
- dir.start_with?("~/") || dir.start_with?(source_code_dir)
65
+ dir.start_with?('~/') || dir.start_with?(source_code_dir)
76
66
  },
77
- "#{source_code_dir}/**/*",
78
- config_path.sub(/.json$/, ".{rb,json}"),
67
+ "#{ source_code_dir }/**/*",
68
+ config_path.sub(/.json$/, '.{rb,json}'),
79
69
  *DEFAULT_WATCHED_PATHS,
80
70
  ].freeze
81
71
  end
82
72
 
83
- # Internal: Changes the current directory to the root dir.
84
- def within_root(&block)
85
- Dir.chdir(File.expand_path(root), &block)
86
- end
87
-
88
73
  private
89
74
 
90
75
  # Internal: Coerces all the configuration values, in case they were passed
91
76
  # as environment variables which are always strings.
92
77
  def coerce_values(config)
93
- config["mode"] = config["mode"].to_s
94
- config["port"] = config["port"].to_i
95
- config["root"] = root = Pathname.new(config["root"])
96
- config["build_cache_dir"] = root.join(config["build_cache_dir"])
97
- config["ssr_output_dir"] = root.join(config["ssr_output_dir"])
98
- coerce_booleans(config, "auto_build", "hide_build_console_output", "https", "skip_compatibility_check", "skip_proxy")
99
- config["package_manager"] ||= detect_package_manager(root)
78
+ config['mode'] = config['mode'].to_s
79
+ config['port'] = config['port'].to_i
80
+ config['root'] = Pathname.new(config['root'])
81
+ config['build_cache_dir'] = config['root'].join(config['build_cache_dir'])
82
+ coerce_booleans(config, 'auto_build', 'hide_build_console_output', 'https', 'skip_compatibility_check')
100
83
  end
101
84
 
102
85
  # Internal: Coerces configuration options to boolean.
103
86
  def coerce_booleans(config, *names)
104
- truthy = [true, "true"]
105
- names.each { |name| config[name] = truthy.include?(config[name]) }
106
- end
107
-
108
- def detect_package_manager(root)
109
- return "npm" if root.join("package-lock.json").exist?
110
- return "pnpm" if root.join("pnpm-lock.yaml").exist?
111
- return "bun" if root.join("bun.lockb").exist? || root.join("bun.lock").exist?
112
- return "yarn" if root.join("yarn.lock").exist?
113
-
114
- "npm"
87
+ names.each { |name| config[name] = [true, 'true'].include?(config[name]) }
115
88
  end
116
89
 
117
90
  def initialize(attrs)
@@ -125,8 +98,8 @@ private
125
98
  # Public: Returns the project configuration for Vite.
126
99
  def resolve_config(**attrs)
127
100
  config = config_defaults.merge(attrs.transform_keys(&:to_s))
128
- file_path = File.join(config["root"], config["config_path"])
129
- file_config = config_from_file(file_path, mode: config["mode"])
101
+ file_path = File.join(config['root'], config['config_path'])
102
+ file_config = config_from_file(file_path, mode: config['mode'])
130
103
  new DEFAULT_CONFIG.merge(file_config).merge(config_from_env).merge(config)
131
104
  end
132
105
 
@@ -134,21 +107,21 @@ private
134
107
 
135
108
  # Internal: Converts camelCase to snake_case.
136
109
  SNAKE_CASE = ->(camel_cased_word) {
137
- camel_cased_word.to_s.gsub("::", "/")
110
+ camel_cased_word.to_s.gsub(/::/, '/')
138
111
  .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
139
112
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
140
- .tr("-", "_")
113
+ .tr('-', '_')
141
114
  .downcase
142
115
  }
143
116
 
144
117
  # Internal: Default values for a Ruby application.
145
- def config_defaults(asset_host: nil, mode: ENV.fetch("RACK_ENV", "development"), root: Dir.pwd)
118
+ def config_defaults(asset_host: nil, mode: ENV.fetch('RACK_ENV', 'development'), root: Dir.pwd)
146
119
  {
147
- "asset_host" => option_from_env("asset_host") || asset_host,
148
- "config_path" => option_from_env("config_path") || DEFAULT_CONFIG.fetch("config_path"),
149
- "mode" => option_from_env("mode") || mode,
150
- "root" => option_from_env("root") || root,
151
- }.select { |_, value| value }
120
+ 'asset_host' => option_from_env('asset_host') || asset_host,
121
+ 'config_path' => option_from_env('config_path') || DEFAULT_CONFIG.fetch('config_path'),
122
+ 'mode' => option_from_env('mode') || mode,
123
+ 'root' => option_from_env('root') || root,
124
+ }
152
125
  end
153
126
 
154
127
  # Internal: Used to load a JSON file from the specified path.
@@ -162,7 +135,7 @@ private
162
135
 
163
136
  # Internal: Retrieves a configuration option from environment variables.
164
137
  def option_from_env(name)
165
- ViteRuby.env["#{ViteRuby::ENV_PREFIX}_#{name.upcase}"]
138
+ ViteRuby.env["#{ ViteRuby::ENV_PREFIX }_#{ name.upcase }"]
166
139
  end
167
140
 
168
141
  # Internal: Extracts the configuration options provided as env vars.
@@ -177,16 +150,16 @@ private
177
150
  # Internal: Loads the configuration options provided in a JSON file.
178
151
  def config_from_file(path, mode:)
179
152
  multi_env_config = load_json(path)
180
- multi_env_config.fetch("all", {})
153
+ multi_env_config.fetch('all', {})
181
154
  .merge(multi_env_config.fetch(mode, {}))
182
155
  rescue Errno::ENOENT => error
183
- $stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{error.message}\n\n"
156
+ $stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{ error.message }\n\n"
184
157
  {}
185
158
  end
186
159
  end
187
160
 
188
161
  # Internal: Shared configuration with the Vite plugin for Ruby.
189
- DEFAULT_CONFIG = load_json("#{__dir__}/../../default.vite.json").freeze
162
+ DEFAULT_CONFIG = load_json("#{ __dir__ }/../../default.vite.json").freeze
190
163
 
191
164
  # Internal: Configuration options that can not be provided as env vars.
192
165
  NOT_CONFIGURABLE_WITH_ENV = %w[additional_entrypoints watch_additional_paths].freeze
@@ -196,15 +169,12 @@ private
196
169
 
197
170
  # Internal: If any of these files is modified the build won't be skipped.
198
171
  DEFAULT_WATCHED_PATHS = %w[
199
- bun.lockb
200
172
  package-lock.json
201
173
  package.json
202
174
  pnpm-lock.yaml
203
175
  postcss.config.js
204
176
  tailwind.config.js
205
177
  vite.config.js
206
- vite.config.mjs
207
- vite.config.mts
208
178
  vite.config.ts
209
179
  windi.config.ts
210
180
  yarn.lock
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rack/proxy"
3
+ require 'rack/proxy'
4
4
 
5
5
  # Public: Allows to relay asset requests to the Vite development server.
6
6
  class ViteRuby::DevServerProxy < Rack::Proxy
7
7
  HOST_WITH_PORT_REGEX = %r{^(.+?)(:\d+)/}
8
- VITE_DEPENDENCY_PREFIX = "/@"
8
+ VITE_DEPENDENCY_PREFIX = '/@'
9
9
 
10
10
  def initialize(app = nil, options = {})
11
11
  @vite_ruby = options.delete(:vite_ruby) || ViteRuby.instance
12
- options[:streaming] = false if config.mode == "test" && !options.key?(:streaming)
12
+ options[:streaming] = false if config.mode == 'test' && !options.key?(:streaming)
13
13
  super
14
14
  end
15
15
 
@@ -17,7 +17,7 @@ class ViteRuby::DevServerProxy < Rack::Proxy
17
17
  def perform_request(env)
18
18
  if vite_should_handle?(env) && dev_server_running?
19
19
  forward_to_vite_dev_server(env)
20
- super
20
+ super(env)
21
21
  else
22
22
  @app.call(env)
23
23
  end
@@ -30,47 +30,41 @@ private
30
30
  def_delegators :@vite_ruby, :config, :dev_server_running?
31
31
 
32
32
  def rewrite_uri_for_vite(env)
33
- uri = env.fetch("REQUEST_URI") { [env["PATH_INFO"], env["QUERY_STRING"]].reject { |str| str.to_s.strip.empty? }.join("?") }
34
- env["PATH_INFO"], env["QUERY_STRING"] = (env["REQUEST_URI"] = normalize_uri(uri)).split("?")
33
+ uri = env.fetch('REQUEST_URI') { [env['PATH_INFO'], env['QUERY_STRING']].reject { |str| str.to_s.strip.empty? }.join('?') }
34
+ env['PATH_INFO'], env['QUERY_STRING'] = (env['REQUEST_URI'] = normalize_uri(uri)).split('?')
35
35
  end
36
36
 
37
37
  def normalize_uri(uri)
38
38
  uri
39
- .sub(HOST_WITH_PORT_REGEX, "/") # Hanami adds the host and port.
40
- .sub(".ts.js", ".ts") # Hanami's javascript helper always adds the extension.
41
- .sub(/\.(sass|scss|styl|stylus|less|pcss|postcss)\.css$/, '.\1') # Rails' stylesheet_link_tag always adds the extension.
39
+ .sub(HOST_WITH_PORT_REGEX, '/') # Hanami adds the host and port.
40
+ .sub('.ts.js', '.ts') # Hanami's javascript helper always adds the extension.
41
+ .sub(/(\.(?!min|module)\w+)\.css$/, '\1') # Rails' stylesheet_link_tag always adds the extension.
42
42
  end
43
43
 
44
44
  def forward_to_vite_dev_server(env)
45
45
  rewrite_uri_for_vite(env)
46
- env["QUERY_STRING"] ||= ""
47
- env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = config.host
48
- env["HTTP_X_FORWARDED_SERVER"] = config.host_with_port
49
- env["HTTP_PORT"] = env["HTTP_X_FORWARDED_PORT"] = config.port.to_s
50
- env["HTTP_X_FORWARDED_PROTO"] = env["HTTP_X_FORWARDED_SCHEME"] = config.protocol
51
- env["HTTPS"] = env["HTTP_X_FORWARDED_SSL"] = "off" unless config.https
52
- env["SCRIPT_NAME"] = ""
46
+ env['QUERY_STRING'] ||= ''
47
+ env['HTTP_HOST'] = env['HTTP_X_FORWARDED_HOST'] = config.host
48
+ env['HTTP_X_FORWARDED_SERVER'] = config.host_with_port
49
+ env['HTTP_PORT'] = env['HTTP_X_FORWARDED_PORT'] = config.port.to_s
50
+ env['HTTP_X_FORWARDED_PROTO'] = env['HTTP_X_FORWARDED_SCHEME'] = config.protocol
51
+ env['HTTPS'] = env['HTTP_X_FORWARDED_SSL'] = 'off' unless config.https
52
+ env['SCRIPT_NAME'] = ''
53
53
  end
54
54
 
55
55
  def vite_should_handle?(env)
56
- path = normalize_uri(env["PATH_INFO"])
57
- return true if path.start_with?(vite_url_prefix) # Vite asset
58
-
59
- true if file_in_vite_root?(path) # Fallback if Vite can serve the file
56
+ path = normalize_uri(env['PATH_INFO'])
57
+ return true if path.start_with?(vite_asset_url_prefix) # Vite asset
58
+ return true if path.start_with?(VITE_DEPENDENCY_PREFIX) # Packages and imports
59
+ return true if file_in_vite_root?(path) # Fallback if Vite can serve the file
60
60
  end
61
61
 
62
- # NOTE: When using an empty 'public_output_dir', we need to rely on a
63
- # filesystem check to check whether Vite should serve the request.
64
62
  def file_in_vite_root?(path)
65
- path.include?(".") && # Check for extension, avoid filesystem if possible.
66
- config.vite_root_dir.join(path.start_with?("/") ? path[1..] : path).file?
63
+ path.include?('.') && # Check for extension, avoid filesystem if possible.
64
+ config.vite_root_dir.join(path.start_with?('/') ? path[1..-1] : path).file?
67
65
  end
68
66
 
69
- # NOTE: Vite is configured to use 'public_output_dir' as the base, which can
70
- # be customized by the user in development to not match any of the routes.
71
- #
72
- # If the path starts with that prefix, it will be redirected to Vite.
73
- def vite_url_prefix
74
- @vite_url_prefix ||= config.public_output_dir.empty? ? VITE_DEPENDENCY_PREFIX : "/#{config.public_output_dir}/"
67
+ def vite_asset_url_prefix
68
+ @vite_asset_url_prefix ||= config.public_output_dir.empty? ? "\0" : "/#{ config.public_output_dir }/"
75
69
  end
76
70
  end
@@ -3,7 +3,7 @@
3
3
  # Internal: Provides common functionality for errors.
4
4
  class ViteRuby::Error < StandardError
5
5
  def message
6
- super.sub(":troubleshooting:", <<~MSG)
6
+ super.sub(':troubleshooting:', <<~MSG)
7
7
  Visit the Troubleshooting guide for more information:
8
8
  https://vite-ruby.netlify.app/guide/troubleshooting.html#troubleshooting
9
9
  MSG
data/lib/vite_ruby/io.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
3
+ require 'open3'
4
4
 
5
5
  # Public: Builds on top of Ruby I/O open3 providing a friendlier experience.
6
6
  module ViteRuby::IO
7
7
  class << self
8
8
  # Internal: A modified version of capture3 that can continuosly print stdout.
9
9
  # NOTE: Streaming output provides a better UX when running bin/vite build.
10
- def capture(*cmd, with_output: $stdout.method(:puts), stdin_data: "", **opts)
10
+ def capture(*cmd, with_output: $stdout.method(:puts), stdin_data: '', **opts)
11
11
  return Open3.capture3(*cmd, **opts) unless with_output
12
12
 
13
13
  Open3.popen3(*cmd, **opts) { |stdin, stdout, stderr, wait_threads|
@@ -15,13 +15,13 @@ module ViteRuby::IO
15
15
  stdin.close
16
16
  out = Thread.new { read_lines(stdout, &with_output) }
17
17
  err = Thread.new { stderr.read }
18
- [out.value, err.value.to_s, wait_threads.value]
18
+ [out.value, err.value, wait_threads.value]
19
19
  }
20
20
  end
21
21
 
22
22
  # Internal: Reads and yield every line in the stream. Returns the full content.
23
23
  def read_lines(io)
24
- buffer = +""
24
+ buffer = +''
25
25
  while line = io.gets
26
26
  buffer << line
27
27
  yield line