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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -418
- data/README.md +1 -1
- data/default.vite.json +2 -7
- data/exe/vite +3 -5
- data/lib/tasks/vite.rake +19 -56
- data/lib/vite_ruby/build.rb +17 -47
- data/lib/vite_ruby/builder.rb +34 -29
- data/lib/vite_ruby/cli/build.rb +4 -6
- data/lib/vite_ruby/cli/clobber.rb +4 -4
- data/lib/vite_ruby/cli/dev.rb +3 -3
- data/lib/vite_ruby/cli/file_utils.rb +8 -8
- data/lib/vite_ruby/cli/install.rb +38 -43
- data/lib/vite_ruby/cli/upgrade.rb +4 -4
- data/lib/vite_ruby/cli/upgrade_packages.rb +4 -3
- data/lib/vite_ruby/cli/version.rb +1 -1
- data/lib/vite_ruby/cli/vite.rb +9 -24
- data/lib/vite_ruby/cli.rb +8 -21
- data/lib/vite_ruby/commands.rb +75 -30
- data/lib/vite_ruby/compatibility_check.rb +8 -8
- data/lib/vite_ruby/config.rb +37 -67
- data/lib/vite_ruby/dev_server_proxy.rb +24 -30
- data/lib/vite_ruby/error.rb +1 -1
- data/lib/vite_ruby/io.rb +4 -4
- data/lib/vite_ruby/manifest.rb +32 -46
- data/lib/vite_ruby/missing_entrypoint_error.rb +14 -22
- data/lib/vite_ruby/missing_executable_error.rb +1 -1
- data/lib/vite_ruby/runner.rb +12 -20
- data/lib/vite_ruby/version.rb +3 -3
- data/lib/vite_ruby.rb +34 -49
- metadata +12 -48
- data/lib/vite_ruby/cli/ssr.rb +0 -27
data/lib/vite_ruby/commands.rb
CHANGED
@@ -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(
|
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.
|
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
|
-
#
|
32
|
-
def
|
33
|
-
|
34
|
-
|
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
|
-
#
|
38
|
-
|
39
|
-
|
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:
|
43
|
-
def
|
44
|
-
`
|
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(
|
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.
|
72
|
-
$stdout.puts "bin/vite present?: #{File.exist?
|
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 "
|
81
|
-
$stdout.puts "
|
82
|
-
|
83
|
-
|
84
|
-
$stdout.puts "
|
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?(
|
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[
|
103
|
-
ENV[
|
147
|
+
original = ENV['NODE_ENV']
|
148
|
+
ENV['NODE_ENV'] = env
|
104
149
|
yield
|
105
150
|
ensure
|
106
|
-
ENV[
|
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|
|
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
|
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(
|
15
|
-
requirement = package.dig(
|
16
|
-
|
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/#
|
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
|
data/lib/vite_ruby/config.rb
CHANGED
@@ -1,36 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
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 ?
|
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
|
21
|
-
def
|
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
|
32
|
-
def
|
33
|
-
|
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(
|
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$/,
|
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
|
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(
|
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?(
|
65
|
+
dir.start_with?('~/') || dir.start_with?(source_code_dir)
|
76
66
|
},
|
77
|
-
"#{source_code_dir}/**/*",
|
78
|
-
config_path.sub(/.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[
|
94
|
-
config[
|
95
|
-
config[
|
96
|
-
config[
|
97
|
-
config
|
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
|
-
|
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[
|
129
|
-
file_config = config_from_file(file_path, mode: config[
|
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(
|
118
|
+
def config_defaults(asset_host: nil, mode: ENV.fetch('RACK_ENV', 'development'), root: Dir.pwd)
|
146
119
|
{
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
}
|
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(
|
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
|
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 ==
|
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(
|
34
|
-
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('?')
|
35
35
|
end
|
36
36
|
|
37
37
|
def normalize_uri(uri)
|
38
38
|
uri
|
39
|
-
.sub(HOST_WITH_PORT_REGEX,
|
40
|
-
.sub(
|
41
|
-
.sub(
|
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[
|
47
|
-
env[
|
48
|
-
env[
|
49
|
-
env[
|
50
|
-
env[
|
51
|
-
env[
|
52
|
-
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'] = ''
|
53
53
|
end
|
54
54
|
|
55
55
|
def vite_should_handle?(env)
|
56
|
-
path = normalize_uri(env[
|
57
|
-
return true if path.start_with?(
|
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?(
|
66
|
-
config.vite_root_dir.join(path.start_with?(
|
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
|
-
|
70
|
-
|
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
|
data/lib/vite_ruby/error.rb
CHANGED
@@ -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(
|
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
|
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:
|
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
|
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
|