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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 377ff051b0ee804f2c9e982603cb06fc11314d9a20922aca84aaa865a22021ab
4
- data.tar.gz: 4fcb83e37190b5eab67c6babe9b1aaa1f42e789ad2cbbce623490e1c13d389a3
3
+ metadata.gz: 21f2c37d6ae5d2b014ce1271ee6a641f16c3794b62cd02b2247a50ba3f85e05b
4
+ data.tar.gz: 9246c36e1e123dea6c9cc79d0695255ebeeb2500bb6cd44f82cc4c1980728706
5
5
  SHA512:
6
- metadata.gz: f6a16c4238742a44057414a3a3be7b60fa6392b0843c226fe05830e71d4a18b676d443b151e95a5f12817791d577d5fddcc5051b01914747ccf20acc19c340e7
7
- data.tar.gz: 58572ccb8a7adb9c920e5022ddec905d33d6a6da73806e5b218653f5a4ff1f80c2ec605dc75824b3959869119ca0bea560bca2e749fe30855e3b9ed5bc342604
6
+ metadata.gz: d4c07780ac0d88dbe06a6cb0812c19621f56452afe25da7c5ceac7217c4b1003cb0b93fdb1e48cffde26459f8fd6e5333ff6ea8f32a5246ba7bd3131b7855d3c
7
+ data.tar.gz: 858a12ceb1ea3811f05b567886162bb1a3d60d35a07ee42b529ced30ee9dfbccdd2ce71afb999013d3f3f1152915734fcd1906f7d85fd5709cb9b1f0b72edbac
data/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2026-01-26
3
+ ## [1.2.4] - 2026-01-26
4
4
 
5
- - Initial release
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
@@ -1,3 +1,3 @@
1
1
  module Railpack
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.4"
3
3
  end
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
- attr_accessor :logger
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
@@ -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
@@ -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 test_config
33
+ def test_config_instance
12
34
  assert_instance_of Railpack::Config, Railpack.config
13
35
  end
14
36
 
15
- def test_manager
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - 21tycoons LLC