This commit is contained in:
Matt Jankowski 2026-03-27 09:22:02 +00:00 committed by GitHub
commit 5131adf67b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 72 additions and 70 deletions

View File

@ -51,7 +51,8 @@ require_relative '../lib/action_dispatch/remote_ip_extensions'
require_relative '../lib/active_record/database_tasks_extensions'
require_relative '../lib/active_record/batches'
require_relative '../lib/simple_navigation/item_extensions'
require_relative '../lib/vite_ruby/sri_extensions'
require_relative '../lib/vite_ruby/manifest_integrity_extension'
require_relative '../lib/vite_rails/tag_helpers/integrity_extension'
Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true'

View File

@ -1,74 +1,5 @@
# frozen_string_literal: true
module ViteRuby::ManifestIntegrityExtension
def path_and_integrity_for(name, **)
entry = lookup!(name, **)
{ path: entry.fetch('file'), integrity: entry.fetch('integrity', nil) }
end
def load_manifest
# Invalidate the name lookup cache when reloading manifest
@name_lookup_cache = nil unless dev_server_running?
super
end
def load_name_lookup_cache
JSON.load_file(config.build_output_dir.join('.vite/manifest-lookup.json'))
end
# Upstream's `virtual` type is a hack, re-implement it with efficient exact name lookup
def resolve_virtual_entry(name)
return name if dev_server_running?
@name_lookup_cache ||= load_name_lookup_cache
@name_lookup_cache.fetch(name)
end
# Find a manifest entry by the *final* file name
def integrity_hash_for_file(file_name)
@integrity_cache ||= {}
@integrity_cache[file_name] ||= begin
entry = manifest.find { |_key, entry| entry['file'] == file_name }
entry[1].fetch('integrity', nil) if entry
end
end
def resolve_entries_with_integrity(*names, **options)
entries = names.map { |name| lookup!(name, **options) }
script_paths = entries.map do |entry|
{
file: entry.fetch('file'),
# TODO: Secure this so we require the integrity hash outside of dev
integrity: entry['integrity'],
}
end
imports = dev_server_running? ? [] : entries.flat_map { |entry| entry['imports'] }.compact
{
scripts: script_paths,
imports: imports.filter_map { |entry| { file: entry.fetch('file'), integrity: entry.fetch('integrity') } }.uniq,
stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry['css'] }.compact.uniq,
}
end
# We need to override this method to not include the manifest, as in our case it is too large and will cause a JSON max nesting error rather than raising the expected exception
def missing_entry_error(name, **)
raise ViteRuby::MissingEntrypointError.new(
file_name: resolve_entry_name(name, **),
last_build: builder.last_build_metadata,
manifest: '',
config: config
)
end
end
ViteRuby::Manifest.prepend ViteRuby::ManifestIntegrityExtension
module ViteRails::TagHelpers::IntegrityExtension
def vite_javascript_tag(*names,
type: 'module',

View File

@ -0,0 +1,70 @@
# frozen_string_literal: true
module ViteRuby::ManifestIntegrityExtension
def path_and_integrity_for(name, **)
entry = lookup!(name, **)
{ path: entry.fetch('file'), integrity: entry.fetch('integrity', nil) }
end
def load_manifest
# Invalidate the name lookup cache when reloading manifest
@name_lookup_cache = nil unless dev_server_running?
super
end
def load_name_lookup_cache
JSON.load_file(config.build_output_dir.join('.vite/manifest-lookup.json'))
end
# Upstream's `virtual` type is a hack, re-implement it with efficient exact name lookup
def resolve_virtual_entry(name)
return name if dev_server_running?
@name_lookup_cache ||= load_name_lookup_cache
@name_lookup_cache.fetch(name)
end
# Find a manifest entry by the *final* file name
def integrity_hash_for_file(file_name)
@integrity_cache ||= {}
@integrity_cache[file_name] ||= begin
entry = manifest.find { |_key, entry| entry['file'] == file_name }
entry[1].fetch('integrity', nil) if entry
end
end
def resolve_entries_with_integrity(*names, **options)
entries = names.map { |name| lookup!(name, **options) }
script_paths = entries.map do |entry|
{
file: entry.fetch('file'),
# TODO: Secure this so we require the integrity hash outside of dev
integrity: entry['integrity'],
}
end
imports = dev_server_running? ? [] : entries.flat_map { |entry| entry['imports'] }.compact
{
scripts: script_paths,
imports: imports.filter_map { |entry| { file: entry.fetch('file'), integrity: entry.fetch('integrity') } }.uniq,
stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry['css'] }.compact.uniq,
}
end
# We need to override this method to not include the manifest, as in our case it is too large and will cause a JSON max nesting error rather than raising the expected exception
def missing_entry_error(name, **)
raise ViteRuby::MissingEntrypointError.new(
file_name: resolve_entry_name(name, **),
last_build: builder.last_build_metadata,
manifest: '',
config: config
)
end
end
ViteRuby::Manifest.prepend ViteRuby::ManifestIntegrityExtension