vite_ruby-roda 3.9.2.1

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.
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/proxy"
4
+
5
+ # Public: Allows to relay asset requests to the Vite development server.
6
+ class ViteRuby::DevServerProxy < Rack::Proxy
7
+ HOST_WITH_PORT_REGEX = %r{^(.+?)(:\d+)/}
8
+ VITE_DEPENDENCY_PREFIX = "/@"
9
+
10
+ def initialize(app = nil, options = {})
11
+ @vite_ruby = options.delete(:vite_ruby) || ViteRuby.instance
12
+ options[:streaming] = false if config.mode == "test" && !options.key?(:streaming)
13
+ super
14
+ end
15
+
16
+ # Rack: Intercept asset requests and send them to the Vite server.
17
+ def perform_request(env)
18
+ if vite_should_handle?(env) && dev_server_running?
19
+ forward_to_vite_dev_server(env)
20
+ super
21
+ else
22
+ @app.call(env)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ extend Forwardable
29
+
30
+ def_delegators :@vite_ruby, :config, :dev_server_running?
31
+
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("?")
35
+ end
36
+
37
+ def normalize_uri(uri)
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.
42
+ end
43
+
44
+ def forward_to_vite_dev_server(env)
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"] = ""
53
+ end
54
+
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
60
+ end
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
+ 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?
67
+ end
68
+
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}/"
75
+ end
76
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Internal: Provides common functionality for errors.
4
+ class ViteRuby::Error < StandardError
5
+ def message
6
+ super.sub(":troubleshooting:", <<~MSG)
7
+ Visit the Troubleshooting guide for more information:
8
+ https://vite-ruby.netlify.app/guide/troubleshooting.html#troubleshooting
9
+ MSG
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ # Public: Builds on top of Ruby I/O open3 providing a friendlier experience.
6
+ module ViteRuby::IO
7
+ class << self
8
+ # Internal: A modified version of capture3 that can continuosly print stdout.
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)
11
+ return Open3.capture3(*cmd, **opts) unless with_output
12
+
13
+ Open3.popen3(*cmd, **opts) { |stdin, stdout, stderr, wait_threads|
14
+ stdin << stdin_data
15
+ stdin.close
16
+ out = Thread.new { read_lines(stdout, &with_output) }
17
+ err = Thread.new { stderr.read }
18
+ [out.value, err.value.to_s, wait_threads.value]
19
+ }
20
+ end
21
+
22
+ # Internal: Reads and yield every line in the stream. Returns the full content.
23
+ def read_lines(io)
24
+ buffer = +""
25
+ while line = io.gets
26
+ buffer << line
27
+ yield line
28
+ end
29
+ buffer
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Public: Registry for accessing resources managed by Vite, using a generated
4
+ # manifest file which maps entrypoint names to file paths.
5
+ #
6
+ # Example:
7
+ # lookup_entrypoint('calendar', type: :javascript)
8
+ # => { "file" => "/vite/assets/calendar-1016838bab065ae1e314.js", "imports" => [] }
9
+ #
10
+ # NOTE: Using `"autoBuild": true` in `config/vite.json` file will trigger a build
11
+ # on demand as needed, before performing any lookup.
12
+ class ViteRuby::Manifest
13
+ def initialize(vite_ruby)
14
+ @vite_ruby = vite_ruby
15
+ @build_mutex = Mutex.new if config.auto_build
16
+ end
17
+
18
+ # Public: Returns the path for the specified Vite entrypoint file.
19
+ #
20
+ # Raises an error if the resource could not be found in the manifest.
21
+ def path_for(name, **options)
22
+ lookup!(name, **options).fetch("file")
23
+ end
24
+
25
+ # Public: Returns scripts, imported modules, and stylesheets for the specified
26
+ # entrypoint files.
27
+ def resolve_entries(*names, **options)
28
+ entries = names.map { |name| lookup!(name, **options) }
29
+ script_paths = entries.map { |entry| entry.fetch("file") }
30
+
31
+ imports = dev_server_running? ? [] : entries.flat_map { |entry| entry["imports"] }.compact
32
+ {
33
+ scripts: script_paths,
34
+ imports: imports.filter_map { |entry| entry.fetch("file") }.uniq,
35
+ stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry["css"] }.compact.uniq,
36
+ }
37
+ end
38
+
39
+ # Public: Refreshes the cached mappings by reading the updated manifest files.
40
+ def refresh
41
+ @manifest = load_manifest
42
+ end
43
+
44
+ # Public: The path from where the browser can download the Vite HMR client.
45
+ def vite_client_src
46
+ prefix_asset_with_host("@vite/client") if dev_server_running?
47
+ end
48
+
49
+ # Public: The content of the preamble needed by the React Refresh plugin.
50
+ def react_refresh_preamble
51
+ if dev_server_running?
52
+ <<~REACT_REFRESH
53
+ <script type="module">
54
+ #{react_preamble_code}
55
+ </script>
56
+ REACT_REFRESH
57
+ end
58
+ end
59
+
60
+ # Public: Source script for the React Refresh plugin.
61
+ def react_preamble_code
62
+ if dev_server_running?
63
+ <<~REACT_PREAMBLE_CODE
64
+ import RefreshRuntime from '#{prefix_asset_with_host("@react-refresh")}'
65
+ RefreshRuntime.injectIntoGlobalHook(window)
66
+ window.$RefreshReg$ = () => {}
67
+ window.$RefreshSig$ = () => (type) => type
68
+ window.__vite_plugin_react_preamble_installed__ = true
69
+ REACT_PREAMBLE_CODE
70
+ end
71
+ end
72
+
73
+ protected
74
+
75
+ # Internal: Strict version of lookup.
76
+ #
77
+ # Returns a relative path for the asset, or raises an error if not found.
78
+ def lookup!(name, **options)
79
+ lookup(name, **options) || missing_entry_error(name, **options)
80
+ end
81
+
82
+ # Internal: Computes the path for a given Vite asset using manifest.json.
83
+ #
84
+ # Returns a relative path, or nil if the asset is not found.
85
+ #
86
+ # Example:
87
+ # manifest.lookup('calendar.js')
88
+ # => { "file" => "/vite/assets/calendar-1016838bab065ae1e122.js", "imports" => [] }
89
+ def lookup(name, **options)
90
+ @build_mutex.synchronize { builder.build || (return nil) } if should_build?
91
+
92
+ find_manifest_entry resolve_entry_name(name, **options)
93
+ end
94
+
95
+ private
96
+
97
+ # Internal: The prefix used by Vite.js to request files with an absolute path.
98
+ FS_PREFIX = "/@fs/"
99
+
100
+ extend Forwardable
101
+
102
+ def_delegators :@vite_ruby, :config, :builder, :dev_server_running?
103
+
104
+ # NOTE: Auto compilation is convenient when running tests, when the developer
105
+ # won't focus on the frontend, or when running the Vite server is not desired.
106
+ def should_build?
107
+ config.auto_build && !dev_server_running?
108
+ end
109
+
110
+ # Internal: Finds the specified entry in the manifest.
111
+ def find_manifest_entry(name)
112
+ if dev_server_running?
113
+ {"file" => prefix_vite_asset(name)}
114
+ else
115
+ manifest[name]
116
+ end
117
+ end
118
+
119
+ # Internal: The parsed data from manifest.json.
120
+ #
121
+ # NOTE: When using build-on-demand in development and testing, the manifest
122
+ # is reloaded automatically before each lookup, to ensure it's always fresh.
123
+ def manifest
124
+ return refresh if config.auto_build
125
+
126
+ @manifest ||= load_manifest
127
+ end
128
+
129
+ # Internal: Loads and merges the manifest files, resolving the asset paths.
130
+ def load_manifest
131
+ config.manifest_paths
132
+ .map { |path| JSON.parse(path.read) }
133
+ .inject({}, &:merge)
134
+ .tap { |manifest| resolve_references(manifest) }
135
+ end
136
+
137
+ # Internal: Scopes an asset to the output folder in public, as a path.
138
+ def prefix_vite_asset(path)
139
+ File.join(vite_asset_origin || "/", config.public_output_dir, path)
140
+ end
141
+
142
+ # Internal: Prefixes an asset with the `asset_host` for tags that do not use
143
+ # the framework tag helpers.
144
+ def prefix_asset_with_host(path)
145
+ File.join(vite_asset_origin || config.asset_host || "/", config.public_output_dir, path)
146
+ end
147
+
148
+ # Internal: The origin of assets managed by Vite.
149
+ def vite_asset_origin
150
+ config.origin if dev_server_running? && config.skip_proxy
151
+ end
152
+
153
+ # Internal: Resolves the paths that reference a manifest entry.
154
+ def resolve_references(manifest)
155
+ manifest.each_value do |entry|
156
+ entry["file"] = prefix_vite_asset(entry["file"])
157
+ %w[css assets].each do |key|
158
+ entry[key] = entry[key].map { |path| prefix_vite_asset(path) } if entry[key]
159
+ end
160
+ entry["imports"]&.map! { |name| manifest.fetch(name) }
161
+ end
162
+ end
163
+
164
+ # Internal: Resolves the manifest entry name for the specified resource.
165
+ def resolve_entry_name(name, type: nil)
166
+ return resolve_virtual_entry(name) if type == :virtual
167
+
168
+ name = with_file_extension(name.to_s, type)
169
+ raise ArgumentError, "Asset names can not be relative. Found: #{name}" if name.start_with?(".")
170
+
171
+ # Explicit path, relative to the source_code_dir.
172
+ name.sub(%r{^~/(.+)$}) { return Regexp.last_match(1) }
173
+
174
+ # Explicit path, relative to the project root.
175
+ name.sub(%r{^/(.+)$}) { return resolve_absolute_entry(Regexp.last_match(1)) }
176
+
177
+ # Sugar: Prefix with the entrypoints dir if the path is not nested.
178
+ name.include?("/") ? name : File.join(config.entrypoints_dir, name)
179
+ end
180
+
181
+ # Internal: Entry names in the manifest are relative to the Vite.js.
182
+ # During develoment, files outside the root must be requested explicitly.
183
+ def resolve_absolute_entry(name)
184
+ if dev_server_running?
185
+ File.join(FS_PREFIX, config.root, name)
186
+ else
187
+ config.root.join(name).relative_path_from(config.vite_root_dir).to_s
188
+ end
189
+ end
190
+
191
+ # Internal: Resolves a virtual entry by walking all the manifest keys.
192
+ def resolve_virtual_entry(name)
193
+ manifest.keys.find { |file| file.include?(name) } || name
194
+ end
195
+
196
+ # Internal: Adds a file extension to the file name, unless it already has one.
197
+ def with_file_extension(name, entry_type)
198
+ if File.extname(name).empty? && (ext = extension_for_type(entry_type))
199
+ "#{name}.#{ext}"
200
+ else
201
+ name
202
+ end
203
+ end
204
+
205
+ # Internal: Allows to receive :javascript and :stylesheet as :type in helpers.
206
+ def extension_for_type(entry_type)
207
+ case entry_type
208
+ when :javascript then "js"
209
+ when :stylesheet then "css"
210
+ when :typescript then "ts"
211
+ else entry_type
212
+ end
213
+ end
214
+
215
+ # Internal: Raises a detailed message when an entry is missing in the manifest.
216
+ def missing_entry_error(name, **options)
217
+ raise ViteRuby::MissingEntrypointError.new(
218
+ file_name: resolve_entry_name(name, **options),
219
+ last_build: builder.last_build_metadata,
220
+ manifest: @manifest,
221
+ config: config,
222
+ )
223
+ end
224
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Internal: Raised when an entry is not found in the build manifest.
4
+ #
5
+ # NOTE: The complexity here is justified by the improved usability of providing
6
+ # a more specific error message depending on the situation.
7
+ class ViteRuby::MissingEntrypointError < ViteRuby::Error
8
+ attr_reader :file_name, :last_build, :manifest, :config
9
+
10
+ def initialize(file_name:, last_build:, manifest:, config:)
11
+ @file_name, @last_build, @manifest, @config = file_name, last_build, manifest, config
12
+ super <<~MSG
13
+ Vite Ruby can't find #{file_name} in the manifests.
14
+
15
+ Possible causes:
16
+ #{possible_causes(last_build)}
17
+ :troubleshooting:
18
+ #{"Manifest files found:\n#{config.manifest_paths.map { |path| " #{path.relative_path_from(config.root)}" }.join("\n")}\n" if last_build.success}
19
+ #{"Content in your manifests:\n#{JSON.pretty_generate(manifest)}\n" if last_build.success}
20
+ #{"Last build in #{config.mode} mode:\n#{last_build.to_json}\n" if last_build.success}
21
+ MSG
22
+ end
23
+
24
+ def possible_causes(last_build)
25
+ if last_build.success == false
26
+ FAILED_BUILD_CAUSES
27
+ .sub(":mode:", config.mode)
28
+ .sub(":errors:", last_build.errors.to_s.gsub(/^(?!$)/, " "))
29
+ elsif config.auto_build
30
+ DEFAULT_CAUSES
31
+ else
32
+ DEFAULT_CAUSES + NO_AUTO_BUILD_CAUSES
33
+ end
34
+ end
35
+
36
+ FAILED_BUILD_CAUSES = <<~MSG
37
+ - The last build failed. Try running `bin/vite build --clear --mode=:mode:` manually and check for errors.
38
+
39
+ Errors:
40
+ :errors:
41
+ MSG
42
+
43
+ DEFAULT_CAUSES = <<-MSG
44
+ - The file path is incorrect.
45
+ - The file is not in the entrypoints directory.
46
+ - Some files are outside the sourceCodeDir, and have not been added to watchAdditionalPaths.
47
+ MSG
48
+
49
+ NO_AUTO_BUILD_CAUSES = <<-MSG
50
+ - You have not run `bin/vite dev` to start Vite, or the dev server is not reachable.
51
+ - "autoBuild" is set to `false` in your config/vite.json for this environment.
52
+ MSG
53
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Internal: Raised when the Vite executable can not be found.
4
+ class ViteRuby::MissingExecutableError < ViteRuby::Error
5
+ def initialize(error = nil)
6
+ super <<~MSG
7
+ ❌ The vite binary is not available. Have you installed the npm packages?
8
+
9
+ :troubleshooting:
10
+ #{error}
11
+ MSG
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Public: Executes Vite commands, providing conveniences for debugging.
4
+ class ViteRuby::Runner
5
+ def initialize(vite_ruby)
6
+ @vite_ruby = vite_ruby
7
+ end
8
+
9
+ # Public: Executes Vite with the specified arguments.
10
+ def run(argv, exec: false)
11
+ config.within_root {
12
+ cmd = command_for(argv)
13
+ return Kernel.exec(*cmd) if exec
14
+
15
+ log_or_noop = ->(line) { logger.info("vite") { line } } unless config.hide_build_console_output
16
+ ViteRuby::IO.capture(*cmd, chdir: config.root, with_output: log_or_noop)
17
+ }
18
+ rescue Errno::ENOENT => error
19
+ raise ViteRuby::MissingExecutableError, error
20
+ end
21
+
22
+ private
23
+
24
+ extend Forwardable
25
+
26
+ def_delegators :@vite_ruby, :config, :logger, :env
27
+
28
+ # Internal: Returns an Array with the command to run.
29
+ def command_for(args)
30
+ [config.to_env(env)].tap do |cmd|
31
+ exec_args, vite_args = args.partition { |arg| arg.start_with?("--node-options") }
32
+ cmd.push(*vite_executable(*exec_args))
33
+ cmd.push(*vite_args)
34
+ cmd.push("--mode", config.mode) unless args.include?("--mode") || args.include?("-m")
35
+ end
36
+ end
37
+
38
+ # Internal: Resolves to an executable for Vite.
39
+ def vite_executable(*exec_args)
40
+ bin_path = config.vite_bin_path
41
+ return [bin_path] if bin_path && File.exist?(bin_path)
42
+
43
+ x = case config.package_manager
44
+ when "npm" then %w[npx]
45
+ when "pnpm" then %w[pnpm exec]
46
+ when "bun" then %w[bun x --bun]
47
+ when "yarn" then %w[yarn]
48
+ else raise ArgumentError, "Unknown package manager #{config.package_manager.inspect}"
49
+ end
50
+
51
+ [*x, *exec_args, "vite"]
52
+ end
53
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ViteRuby
4
+ VERSION = "3.9.2.1"
5
+
6
+ # Internal: Versions used by default when running `vite install`.
7
+ DEFAULT_VITE_VERSION = "^6.2.6"
8
+ DEFAULT_PLUGIN_VERSION = "^5.1.1"
9
+ end
data/lib/vite_ruby.rb ADDED
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "forwardable"
5
+ require "pathname"
6
+ require "socket"
7
+
8
+ require "zeitwerk"
9
+ loader = Zeitwerk::Loader.for_gem
10
+ loader.ignore("#{__dir__}/install")
11
+ loader.ignore("#{__dir__}/tasks")
12
+ loader.ignore("#{__dir__}/exe")
13
+ loader.inflector.inflect("cli" => "CLI")
14
+ loader.inflector.inflect("ssr" => "SSR")
15
+ loader.inflector.inflect("io" => "IO")
16
+ loader.setup
17
+
18
+ class ViteRuby
19
+ # Internal: Prefix used for environment variables that modify the configuration.
20
+ ENV_PREFIX = "VITE_RUBY"
21
+
22
+ # Internal: Companion libraries for Vite Ruby, and their target framework.
23
+ COMPANION_LIBRARIES = {
24
+ "vite_rails" => "rails",
25
+ "vite_hanami" => "hanami",
26
+ "vite_padrino" => "padrino",
27
+ "jekyll-vite" => "jekyll",
28
+ "vite_rails_legacy" => "rails",
29
+ "vite_plugin_legacy" => "rack",
30
+ "roda-vite" => "roda",
31
+ }
32
+
33
+ class << self
34
+ extend Forwardable
35
+
36
+ def_delegators :instance, :config, :configure, :commands, :digest, :env, :run, :run_proxy?
37
+ def_delegators :config, :mode
38
+
39
+ def instance
40
+ @instance ||= new
41
+ end
42
+
43
+ # Internal: Refreshes the manifest.
44
+ def bootstrap
45
+ instance.manifest.refresh
46
+ end
47
+
48
+ # Internal: Loads all available rake tasks.
49
+ def install_tasks
50
+ load File.expand_path("tasks/vite.rake", __dir__)
51
+ end
52
+
53
+ # Internal: Creates a new instance with the specified options.
54
+ def reload_with(**config_options)
55
+ @instance = new(**config_options)
56
+ end
57
+
58
+ # Internal: Detects if the application has installed a framework-specific
59
+ # variant of Vite Ruby.
60
+ def framework_libraries
61
+ COMPANION_LIBRARIES.filter_map { |name, framework|
62
+ if library = Gem.loaded_specs[name]
63
+ [framework, library]
64
+ end
65
+ }
66
+ end
67
+ end
68
+
69
+ attr_writer :logger
70
+
71
+ def initialize(**config_options)
72
+ @config_options = config_options
73
+ end
74
+
75
+ def logger
76
+ @logger ||= Logger.new($stdout)
77
+ end
78
+
79
+ # Public: Returns a digest of all the watched files, allowing to detect
80
+ # changes. Useful to perform version checks in single-page applications.
81
+ def digest
82
+ builder.send(:watched_files_digest)
83
+ end
84
+
85
+ # Public: Returns true if the Vite development server is currently running.
86
+ # NOTE: Checks only once every second since every lookup calls this method.
87
+ def dev_server_running?
88
+ return false unless run_proxy?
89
+ return @running if defined?(@running) && Time.now - @running_checked_at < 1
90
+
91
+ begin
92
+ Socket.tcp(config.host, config.port, connect_timeout: config.dev_server_connect_timeout).close
93
+ @running = true
94
+ rescue
95
+ @running = false
96
+ ensure
97
+ @running_checked_at = Time.now
98
+ end
99
+ end
100
+
101
+ # Public: Additional environment variables to pass to Vite.
102
+ #
103
+ # Example:
104
+ # ViteRuby.env['VITE_RUBY_CONFIG_PATH'] = 'config/alternate_vite.json'
105
+ def env
106
+ @env ||= ENV.select { |key, _| key.start_with?(ENV_PREFIX) }
107
+ end
108
+
109
+ # Public: The proxy for assets should only run in development mode.
110
+ def run_proxy?
111
+ config.mode == "development" || (config.mode == "test" && !ENV["CI"])
112
+ rescue => error
113
+ logger.error("Failed to check mode for Vite: #{error.message}")
114
+ false
115
+ end
116
+
117
+ # Internal: Executes the vite binary.
118
+ def run(argv, **options)
119
+ (@runner ||= ViteRuby::Runner.new(self)).run(argv, **options)
120
+ end
121
+
122
+ # Public: Keeps track of watched files and triggers builds as needed.
123
+ def builder
124
+ @builder ||= ViteRuby::Builder.new(self)
125
+ end
126
+
127
+ # Internal: Helper to run commands related with Vite.
128
+ def commands
129
+ @commands ||= ViteRuby::Commands.new(self)
130
+ end
131
+
132
+ # Public: Current instance configuration for Vite.
133
+ def config
134
+ unless defined?(@config)
135
+ configure
136
+ @config.load_ruby_config
137
+ end
138
+
139
+ @config
140
+ end
141
+
142
+ # Public: Allows overriding the configuration for this instance.
143
+ def configure(**options)
144
+ @config = ViteRuby::Config.resolve_config(**@config_options, **options)
145
+ end
146
+
147
+ # Public: Enables looking up assets managed by Vite using name and type.
148
+ def manifest
149
+ @manifest ||= ViteRuby::Manifest.new(self)
150
+ end
151
+ end
152
+
153
+ require "vite_ruby/version"
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vite'
2
+ import RubyPlugin from 'vite-plugin-ruby'
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ RubyPlugin(),
7
+ ],
8
+ })
@@ -0,0 +1,16 @@
1
+ {
2
+ "all": {
3
+ "sourceCodeDir": "frontend",
4
+ "watchAdditionalPaths": []
5
+ },
6
+ "development": {
7
+ "autoBuild": true,
8
+ "publicOutputDir": "vite-dev",
9
+ "port": 3036
10
+ },
11
+ "test": {
12
+ "autoBuild": true,
13
+ "publicOutputDir": "vite-test",
14
+ "port": 3037
15
+ }
16
+ }
@@ -0,0 +1,8 @@
1
+ // To see this message, follow the instructions for your Ruby framework.
2
+ //
3
+ // When using a plain API, perhaps it's better to generate an HTML entrypoint
4
+ // and link to the scripts and stylesheets, and let Vite transform it.
5
+ console.log('Vite ⚡️ Ruby')
6
+
7
+ // Example: Import a stylesheet in <sourceCodeDir>/index.css
8
+ // import '~/index.css'