railpack 1.2.2 → 1.2.4
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 +56 -2
- data/README.md +12 -0
- data/lib/railpack/version.rb +1 -1
- data/lib/railpack.rb +6 -1
- data/lib/tasks/railpack.rake +70 -1
- data/test/railpack_test.rb +201 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 21f2c37d6ae5d2b014ce1271ee6a641f16c3794b62cd02b2247a50ba3f85e05b
|
|
4
|
+
data.tar.gz: 9246c36e1e123dea6c9cc79d0695255ebeeb2500bb6cd44f82cc4c1980728706
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d4c07780ac0d88dbe06a6cb0812c19621f56452afe25da7c5ceac7217c4b1003cb0b93fdb1e48cffde26459f8fd6e5333ff6ea8f32a5246ba7bd3131b7855d3c
|
|
7
|
+
data.tar.gz: 858a12ceb1ea3811f05b567886162bb1a3d60d35a07ee42b529ced30ee9dfbccdd2ce71afb999013d3f3f1152915734fcd1906f7d85fd5709cb9b1f0b72edbac
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [1.2.4] - 2026-01-26
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- Add comprehensive test suite (18 tests, 62 assertions)
|
|
6
|
+
- Test config system, bundler implementations, manager functionality
|
|
7
|
+
- Test event hooks, error handling, asset manifest generation
|
|
8
|
+
- Test bundle size calculation and Rails integration
|
|
9
|
+
- Add default logger with Logger.new($stdout)
|
|
10
|
+
- Fix logger nil issues in manager
|
|
11
|
+
|
|
12
|
+
## [1.2.3] - 2026-01-26
|
|
13
|
+
|
|
14
|
+
- Add install scaffold generator (`rails railpack:install`)
|
|
15
|
+
- Create default `config/railpack.yml` with sensible Rails defaults
|
|
16
|
+
- Add `rails railpack:install:force` for overwriting existing config
|
|
17
|
+
- Update README with install instructions
|
|
18
|
+
- Similar to jsbundling install experience
|
|
19
|
+
|
|
20
|
+
## [1.2.2] - 2026-01-26
|
|
21
|
+
|
|
22
|
+
- Fix asset manifest generation for Propshaft compatibility
|
|
23
|
+
- Generate `.manifest.json` instead of Sprockets format
|
|
24
|
+
- Update manifest structure with `logical_path`, `pathname`, `digest`
|
|
25
|
+
- Rails 7+ Propshaft compatibility
|
|
26
|
+
|
|
27
|
+
## [1.2.1] - 2026-01-26
|
|
28
|
+
|
|
29
|
+
- Add comprehensive build performance monitoring
|
|
30
|
+
- Implement Propshaft-compatible asset manifest generation
|
|
31
|
+
- Enhanced logging with emojis and structured output
|
|
32
|
+
- Production-ready defaults (no sourcemaps, bundle analysis off)
|
|
33
|
+
- Better error handling and user feedback
|
|
34
|
+
|
|
35
|
+
## [1.2.0] - 2026-01-26
|
|
36
|
+
|
|
37
|
+
- Add Webpack bundler support
|
|
38
|
+
- Implement WebpackBundler class with full command support
|
|
39
|
+
- Register webpack in Manager::BUNDLERS
|
|
40
|
+
- Add webpack config defaults (mode, target)
|
|
41
|
+
- Update tests to include webpack bundler
|
|
42
|
+
|
|
43
|
+
## [1.1.0] - 2026-01-26
|
|
44
|
+
|
|
45
|
+
- Add Rollup bundler support
|
|
46
|
+
- Implement RollupBundler class with tree-shaking capabilities
|
|
47
|
+
- Register rollup in Manager::BUNDLERS
|
|
48
|
+
- Add rollup config defaults (format, sourcemap)
|
|
49
|
+
- Update tests to include rollup bundler
|
|
50
|
+
|
|
51
|
+
## [1.0.0] - 2026-01-26
|
|
52
|
+
|
|
53
|
+
- Initial release with Bun and esbuild support
|
|
54
|
+
- Unified API for multiple bundlers
|
|
55
|
+
- Rails asset pipeline integration
|
|
56
|
+
- Configuration system with YAML support
|
|
57
|
+
- Event hooks for build lifecycle
|
|
58
|
+
- Rake tasks for Rails integration
|
|
59
|
+
- Comprehensive test suite
|
data/README.md
CHANGED
|
@@ -19,6 +19,14 @@ Add to your Gemfile:
|
|
|
19
19
|
gem 'railpack'
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
Then run the install generator:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
rails railpack:install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This creates `config/railpack.yml` with sensible defaults for your Rails app.
|
|
29
|
+
|
|
22
30
|
## Configuration
|
|
23
31
|
|
|
24
32
|
Create `config/railpack.yml`:
|
|
@@ -179,6 +187,10 @@ BUNDLERS = {
|
|
|
179
187
|
3. Update documentation
|
|
180
188
|
4. Submit a PR
|
|
181
189
|
|
|
190
|
+
## Changelog
|
|
191
|
+
|
|
192
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|
193
|
+
|
|
182
194
|
## License
|
|
183
195
|
|
|
184
196
|
MIT License - see LICENSE.txt
|
data/lib/railpack/version.rb
CHANGED
data/lib/railpack.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Railpack - Multi-bundler asset pipeline for Rails
|
|
2
|
+
require 'logger'
|
|
2
3
|
require_relative "railpack/version"
|
|
3
4
|
require_relative "railpack/bundler"
|
|
4
5
|
require_relative "railpack/bundlers/bun_bundler"
|
|
@@ -12,7 +13,11 @@ module Railpack
|
|
|
12
13
|
class Error < StandardError; end
|
|
13
14
|
|
|
14
15
|
class << self
|
|
15
|
-
|
|
16
|
+
attr_writer :logger
|
|
17
|
+
|
|
18
|
+
def logger
|
|
19
|
+
@logger ||= Logger.new($stdout)
|
|
20
|
+
end
|
|
16
21
|
|
|
17
22
|
def config
|
|
18
23
|
@config ||= Config.new
|
data/lib/tasks/railpack.rake
CHANGED
|
@@ -5,6 +5,28 @@ require "railpack"
|
|
|
5
5
|
Railpack::Manager.enhance("build", "copy_assets")
|
|
6
6
|
|
|
7
7
|
namespace :railpack do
|
|
8
|
+
desc "Install and setup Railpack with default configuration"
|
|
9
|
+
task :install do
|
|
10
|
+
config_path = Rails.root.join("config/railpack.yml")
|
|
11
|
+
|
|
12
|
+
if config_path.exist?
|
|
13
|
+
puts "Railpack config already exists at #{config_path}"
|
|
14
|
+
puts "Run 'rails railpack:install:force' to overwrite"
|
|
15
|
+
else
|
|
16
|
+
create_config_file(config_path)
|
|
17
|
+
puts "✅ Created Railpack configuration at #{config_path}"
|
|
18
|
+
puts "🎯 Run 'rails railpack:install' to install bundler dependencies"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "Force install Railpack configuration (overwrites existing)"
|
|
23
|
+
task "install:force" do
|
|
24
|
+
config_path = Rails.root.join("config/railpack.yml")
|
|
25
|
+
create_config_file(config_path)
|
|
26
|
+
puts "✅ Created/Updated Railpack configuration at #{config_path}"
|
|
27
|
+
puts "🎯 Run 'rails railpack:install' to install bundler dependencies"
|
|
28
|
+
end
|
|
29
|
+
|
|
8
30
|
desc "Install Railpack dependencies"
|
|
9
31
|
task :install do
|
|
10
32
|
Railpack.install!
|
|
@@ -67,4 +89,51 @@ namespace :railpack do
|
|
|
67
89
|
task :bundler do
|
|
68
90
|
puts "Current bundler: #{Railpack.config.bundler}"
|
|
69
91
|
end
|
|
70
|
-
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def create_config_file(config_path)
|
|
95
|
+
config_content = <<~YAML
|
|
96
|
+
# Railpack Configuration
|
|
97
|
+
# Choose your bundler: bun, esbuild, rollup, webpack
|
|
98
|
+
|
|
99
|
+
bundler: bun # Default bundler
|
|
100
|
+
|
|
101
|
+
# Global defaults
|
|
102
|
+
default:
|
|
103
|
+
target: browser
|
|
104
|
+
format: esm
|
|
105
|
+
minify: false
|
|
106
|
+
sourcemap: false
|
|
107
|
+
entrypoint: "./app/javascript/application.js"
|
|
108
|
+
outdir: "app/assets/builds"
|
|
109
|
+
|
|
110
|
+
# Bundler-specific configurations
|
|
111
|
+
bun:
|
|
112
|
+
target: browser
|
|
113
|
+
format: esm
|
|
114
|
+
|
|
115
|
+
esbuild:
|
|
116
|
+
target: browser
|
|
117
|
+
format: esm
|
|
118
|
+
platform: browser
|
|
119
|
+
|
|
120
|
+
rollup:
|
|
121
|
+
format: esm
|
|
122
|
+
sourcemap: true
|
|
123
|
+
|
|
124
|
+
webpack:
|
|
125
|
+
mode: production
|
|
126
|
+
target: web
|
|
127
|
+
|
|
128
|
+
# Environment-specific overrides
|
|
129
|
+
development:
|
|
130
|
+
sourcemap: true
|
|
131
|
+
|
|
132
|
+
production:
|
|
133
|
+
minify: true
|
|
134
|
+
sourcemap: false
|
|
135
|
+
analyze_bundle: false
|
|
136
|
+
YAML
|
|
137
|
+
|
|
138
|
+
File.write(config_path, config_content)
|
|
139
|
+
end
|
data/test/railpack_test.rb
CHANGED
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'minitest/autorun'
|
|
4
|
+
require 'tempfile'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
require 'pathname'
|
|
7
|
+
require 'json'
|
|
4
8
|
require 'railpack'
|
|
5
9
|
|
|
6
10
|
class RailpackTest < Minitest::Test
|
|
11
|
+
def setup
|
|
12
|
+
# Create a temporary directory for testing
|
|
13
|
+
@temp_dir = Dir.mktmpdir
|
|
14
|
+
@original_rails_root = nil
|
|
15
|
+
if defined?(Rails) && Rails.respond_to?(:root)
|
|
16
|
+
@original_rails_root = Rails.singleton_class.instance_method(:root)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def teardown
|
|
21
|
+
FileUtils.remove_entry(@temp_dir) if @temp_dir && Dir.exist?(@temp_dir)
|
|
22
|
+
# Restore original Rails.root method if it was overridden
|
|
23
|
+
if @original_rails_root && defined?(Rails)
|
|
24
|
+
Rails.singleton_class.define_method(:root, @original_rails_root)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
7
28
|
def test_version
|
|
8
29
|
refute_nil ::Railpack::VERSION
|
|
30
|
+
assert_match(/\d+\.\d+\.\d+/, ::Railpack::VERSION)
|
|
9
31
|
end
|
|
10
32
|
|
|
11
|
-
def
|
|
33
|
+
def test_config_instance
|
|
12
34
|
assert_instance_of Railpack::Config, Railpack.config
|
|
13
35
|
end
|
|
14
36
|
|
|
15
|
-
def
|
|
37
|
+
def test_manager_instance
|
|
16
38
|
assert_instance_of Railpack::Manager, Railpack.manager
|
|
17
39
|
end
|
|
18
40
|
|
|
@@ -26,4 +48,181 @@ class RailpackTest < Minitest::Test
|
|
|
26
48
|
assert_equal Railpack::RollupBundler, Railpack::Manager::BUNDLERS['rollup']
|
|
27
49
|
assert_equal Railpack::WebpackBundler, Railpack::Manager::BUNDLERS['webpack']
|
|
28
50
|
end
|
|
51
|
+
|
|
52
|
+
def test_config_loading_without_rails
|
|
53
|
+
# Test config loading without Rails.root
|
|
54
|
+
config = Railpack::Config.new
|
|
55
|
+
assert_equal 'bun', config.bundler
|
|
56
|
+
assert_equal './app/javascript/application.js', config.entrypoint
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_config_environment_overrides
|
|
60
|
+
# Test environment override logic with default config
|
|
61
|
+
config = Railpack::Config.new
|
|
62
|
+
dev_config = config.for_environment('development')
|
|
63
|
+
prod_config = config.for_environment('production')
|
|
64
|
+
|
|
65
|
+
# Development should have sourcemap enabled by default
|
|
66
|
+
assert_equal true, dev_config['sourcemap']
|
|
67
|
+
# Production should have minify enabled by default
|
|
68
|
+
assert_equal true, prod_config['minify']
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_config_build_flags
|
|
72
|
+
# Test build flags generation with default config
|
|
73
|
+
config = Railpack::Config.new
|
|
74
|
+
flags = config.build_flags
|
|
75
|
+
|
|
76
|
+
assert_includes flags, '--target=browser'
|
|
77
|
+
assert_includes flags, '--format=esm'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_config_build_args
|
|
81
|
+
# Test build args generation with default config
|
|
82
|
+
config = Railpack::Config.new
|
|
83
|
+
args = config.build_args
|
|
84
|
+
|
|
85
|
+
assert_includes args, './app/javascript/application.js'
|
|
86
|
+
assert_includes args, '--outdir=app/assets/builds'
|
|
87
|
+
assert_includes args, '--target=browser'
|
|
88
|
+
assert_includes args, '--format=esm'
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_manager_bundle_size_calculation
|
|
92
|
+
# Create test output directory with fake assets
|
|
93
|
+
outdir = File.join(@temp_dir, 'builds')
|
|
94
|
+
FileUtils.mkdir_p(outdir)
|
|
95
|
+
|
|
96
|
+
# Create fake JS and CSS files
|
|
97
|
+
File.write(File.join(outdir, 'app.js'), 'console.log("test");')
|
|
98
|
+
File.write(File.join(outdir, 'app.css'), 'body { color: red; }')
|
|
99
|
+
File.write(File.join(outdir, 'app.js.map'), '{"version":3}')
|
|
100
|
+
|
|
101
|
+
config = { 'outdir' => outdir }
|
|
102
|
+
manager = Railpack::Manager.new
|
|
103
|
+
|
|
104
|
+
size = manager.send(:calculate_bundle_size, config)
|
|
105
|
+
assert size.is_a?(Float)
|
|
106
|
+
assert size > 0
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_manager_asset_manifest_generation
|
|
110
|
+
outdir = File.join(@temp_dir, 'builds')
|
|
111
|
+
FileUtils.mkdir_p(outdir)
|
|
112
|
+
|
|
113
|
+
# Create fake built assets
|
|
114
|
+
File.write(File.join(outdir, 'application.js'), 'console.log("app");')
|
|
115
|
+
File.write(File.join(outdir, 'application.css'), 'body { color: blue; }')
|
|
116
|
+
|
|
117
|
+
config = { 'outdir' => outdir }
|
|
118
|
+
manager = Railpack::Manager.new
|
|
119
|
+
|
|
120
|
+
manager.send(:generate_asset_manifest, config)
|
|
121
|
+
|
|
122
|
+
manifest_path = File.join(outdir, '.manifest.json')
|
|
123
|
+
assert File.exist?(manifest_path)
|
|
124
|
+
|
|
125
|
+
manifest = JSON.parse(File.read(manifest_path))
|
|
126
|
+
assert manifest.key?('application.js')
|
|
127
|
+
assert manifest.key?('application.css')
|
|
128
|
+
assert manifest['application.js']['logical_path'] == 'application.js'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_bundler_base_class
|
|
132
|
+
bundler = Railpack::Bundler.new({})
|
|
133
|
+
|
|
134
|
+
assert_respond_to bundler, :build!
|
|
135
|
+
assert_respond_to bundler, :watch
|
|
136
|
+
assert_respond_to bundler, :install!
|
|
137
|
+
assert_respond_to bundler, :name
|
|
138
|
+
assert_respond_to bundler, :commands
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_bun_bundler_commands
|
|
142
|
+
bundler = Railpack::BunBundler.new({})
|
|
143
|
+
commands = bundler.send(:commands)
|
|
144
|
+
|
|
145
|
+
assert_equal 'bun run build', commands[:build]
|
|
146
|
+
assert_equal 'bun run watch', commands[:watch]
|
|
147
|
+
assert_equal 'bun install', commands[:install]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def test_esbuild_bundler_commands
|
|
151
|
+
bundler = Railpack::EsbuildBundler.new({})
|
|
152
|
+
commands = bundler.send(:commands)
|
|
153
|
+
|
|
154
|
+
assert_equal 'esbuild', commands[:build]
|
|
155
|
+
assert_equal 'esbuild --watch', commands[:watch]
|
|
156
|
+
assert_equal 'npm install', commands[:install]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_rollup_bundler_commands
|
|
160
|
+
bundler = Railpack::RollupBundler.new({})
|
|
161
|
+
commands = bundler.send(:commands)
|
|
162
|
+
|
|
163
|
+
assert_equal 'rollup', commands[:build]
|
|
164
|
+
assert_equal 'rollup --watch', commands[:watch]
|
|
165
|
+
assert_equal 'npm install', commands[:install]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_webpack_bundler_commands
|
|
169
|
+
bundler = Railpack::WebpackBundler.new({})
|
|
170
|
+
commands = bundler.send(:commands)
|
|
171
|
+
|
|
172
|
+
assert_equal 'webpack', commands[:build]
|
|
173
|
+
assert_equal 'webpack --watch', commands[:watch]
|
|
174
|
+
assert_equal 'npm install', commands[:install]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_event_hooks
|
|
178
|
+
events = []
|
|
179
|
+
Railpack.on_build_start { |config| events << [:start, config] }
|
|
180
|
+
Railpack.on_build_complete { |result| events << [:complete, result] }
|
|
181
|
+
|
|
182
|
+
# Trigger build to test hooks
|
|
183
|
+
manager = Railpack::Manager.new
|
|
184
|
+
config = Railpack.config.for_environment
|
|
185
|
+
|
|
186
|
+
# Mock a simple build that doesn't actually execute
|
|
187
|
+
manager.instance_variable_set(:@bundler, Minitest::Mock.new)
|
|
188
|
+
manager.instance_variable_get(:@bundler).expect(:build!, true, [[]])
|
|
189
|
+
|
|
190
|
+
Railpack.trigger_build_start(config)
|
|
191
|
+
Railpack.trigger_build_complete({ success: true })
|
|
192
|
+
|
|
193
|
+
assert_equal 2, events.size
|
|
194
|
+
assert_equal [:start, config], events[0]
|
|
195
|
+
assert_equal [:complete, { success: true }], events[1]
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_error_handling
|
|
199
|
+
error = nil
|
|
200
|
+
Railpack.on_error { |err| error = err }
|
|
201
|
+
|
|
202
|
+
begin
|
|
203
|
+
raise StandardError.new("Test error")
|
|
204
|
+
rescue => e
|
|
205
|
+
Railpack.trigger_error(e)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
assert_equal "Test error", error.message
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def test_logger_integration
|
|
212
|
+
# Test that logger methods exist
|
|
213
|
+
assert_respond_to Railpack, :logger
|
|
214
|
+
assert_respond_to Railpack, :logger=
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
private
|
|
218
|
+
|
|
219
|
+
def mock_rails_root(path)
|
|
220
|
+
rails_module = if defined?(Rails)
|
|
221
|
+
Rails
|
|
222
|
+
else
|
|
223
|
+
Object.const_set(:Rails, Module.new)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
rails_module.define_singleton_method(:root) { Pathname.new(path) }
|
|
227
|
+
end
|
|
29
228
|
end
|