shakapacker 9.3.0.beta.7 → 9.3.0

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -109
  3. data/Gemfile.lock +1 -1
  4. data/README.md +53 -2
  5. data/docs/configuration.md +28 -0
  6. data/docs/rspack_migration_guide.md +238 -2
  7. data/docs/troubleshooting.md +21 -21
  8. data/eslint.config.fast.js +8 -0
  9. data/eslint.config.js +47 -10
  10. data/knip.ts +8 -1
  11. data/lib/install/config/shakapacker.yml +6 -6
  12. data/lib/shakapacker/configuration.rb +227 -4
  13. data/lib/shakapacker/dev_server.rb +88 -1
  14. data/lib/shakapacker/doctor.rb +4 -4
  15. data/lib/shakapacker/instance.rb +85 -1
  16. data/lib/shakapacker/manifest.rb +85 -11
  17. data/lib/shakapacker/version.rb +1 -1
  18. data/lib/shakapacker.rb +143 -3
  19. data/lib/tasks/shakapacker/doctor.rake +1 -1
  20. data/lib/tasks/shakapacker/export_bundler_config.rake +4 -4
  21. data/package/config.ts +0 -1
  22. data/package/configExporter/buildValidator.ts +53 -29
  23. data/package/configExporter/cli.ts +81 -56
  24. data/package/configExporter/configFile.ts +33 -26
  25. data/package/configExporter/types.ts +64 -0
  26. data/package/configExporter/yamlSerializer.ts +118 -43
  27. data/package/dev_server.ts +2 -1
  28. data/package/env.ts +1 -1
  29. data/package/environments/base.ts +4 -4
  30. data/package/environments/development.ts +7 -6
  31. data/package/environments/production.ts +6 -7
  32. data/package/environments/test.ts +2 -1
  33. data/package/index.ts +28 -4
  34. data/package/loaders.d.ts +2 -2
  35. data/package/optimization/webpack.ts +29 -31
  36. data/package/rspack/index.ts +2 -1
  37. data/package/rules/file.ts +1 -0
  38. data/package/rules/jscommon.ts +1 -0
  39. data/package/utils/helpers.ts +0 -1
  40. data/package/utils/pathValidation.ts +68 -7
  41. data/package/utils/requireOrError.ts +10 -2
  42. data/package/utils/typeGuards.ts +43 -46
  43. data/package/webpack-types.d.ts +2 -2
  44. data/package/webpackDevServerConfig.ts +1 -0
  45. data/package.json +2 -3
  46. data/test/package/configExporter/cli.test.js +440 -0
  47. data/test/package/configExporter/types.test.js +163 -0
  48. data/test/package/configExporter.test.js +264 -0
  49. data/test/package/yamlSerializer.test.js +204 -0
  50. data/test/typescript/pathValidation.test.js +44 -0
  51. data/test/typescript/requireOrError.test.js +49 -0
  52. data/yarn.lock +0 -32
  53. metadata +11 -5
  54. data/.eslintrc.fast.js +0 -40
  55. data/.eslintrc.js +0 -84
@@ -1,16 +1,50 @@
1
+ # Development server status and configuration
2
+ #
3
+ # Provides methods to query the status and configuration of the webpack-dev-server
4
+ # or rspack-dev-server. This includes checking if the server is running, accessing
5
+ # its host/port, and querying features like HMR (Hot Module Replacement).
6
+ #
7
+ # The dev server runs during development to provide live reloading and hot module
8
+ # replacement. In production, the dev server is not used.
9
+ #
10
+ # @example Checking dev server status
11
+ # dev_server = Shakapacker.dev_server
12
+ # dev_server.running?
13
+ # #=> true
14
+ # dev_server.host_with_port
15
+ # #=> "localhost:3035"
16
+ # dev_server.hmr?
17
+ # #=> true
18
+ #
19
+ # @see Shakapacker::DevServerRunner
1
20
  class Shakapacker::DevServer
21
+ # Default environment variable prefix for dev server settings
2
22
  DEFAULT_ENV_PREFIX = "SHAKAPACKER_DEV_SERVER".freeze
3
23
 
4
24
  # Configure dev server connection timeout (in seconds), default: 0.1
5
- # Shakapacker.dev_server.connect_timeout = 1
25
+ # @example
26
+ # Shakapacker::DevServer.connect_timeout = 1
27
+ # @return [Float] the connection timeout in seconds
6
28
  cattr_accessor(:connect_timeout) { 0.1 }
7
29
 
30
+ # The Shakapacker configuration
31
+ # @return [Shakapacker::Configuration] the configuration
8
32
  attr_reader :config
9
33
 
34
+ # Creates a new dev server instance
35
+ #
36
+ # @param config [Shakapacker::Configuration] the Shakapacker configuration
37
+ # @return [Shakapacker::DevServer] the new dev server instance
10
38
  def initialize(config)
11
39
  @config = config
12
40
  end
13
41
 
42
+ # Returns whether the dev server is currently running
43
+ #
44
+ # Checks by attempting to open a TCP connection to the configured host and port.
45
+ # Returns false if the connection fails or if dev server is not configured.
46
+ #
47
+ # @return [Boolean] true if the dev server is running
14
48
  def running?
15
49
  if config.dev_server.present?
16
50
  Socket.tcp(host, port, connect_timeout: connect_timeout).close
@@ -22,14 +56,30 @@ class Shakapacker::DevServer
22
56
  false
23
57
  end
24
58
 
59
+ # Returns the dev server host
60
+ #
61
+ # Can be overridden via SHAKAPACKER_DEV_SERVER_HOST environment variable.
62
+ #
63
+ # @return [String] the host (e.g., "localhost", "0.0.0.0")
25
64
  def host
26
65
  fetch(:host)
27
66
  end
28
67
 
68
+ # Returns the dev server port
69
+ #
70
+ # Can be overridden via SHAKAPACKER_DEV_SERVER_PORT environment variable.
71
+ #
72
+ # @return [Integer] the port number (typically 3035)
29
73
  def port
30
74
  fetch(:port)
31
75
  end
32
76
 
77
+ # Returns the server type (http or https)
78
+ #
79
+ # Can be overridden via SHAKAPACKER_DEV_SERVER_SERVER environment variable.
80
+ # Validates that the value is "http" or "https", falling back to "http" if invalid.
81
+ #
82
+ # @return [String] "http" or "https"
33
83
  def server
34
84
  server_value = fetch(:server)
35
85
  server_type = server_value.is_a?(Hash) ? server_value[:type] : server_value
@@ -49,24 +99,55 @@ class Shakapacker::DevServer
49
99
  "http"
50
100
  end
51
101
 
102
+ # Returns the protocol for the dev server
103
+ #
104
+ # This is an alias that returns "https" if server is "https", otherwise "http".
105
+ #
106
+ # @return [String] "http" or "https"
52
107
  def protocol
53
108
  return "https" if server == "https"
54
109
 
55
110
  "http"
56
111
  end
57
112
 
113
+ # Returns the host and port as a single string
114
+ #
115
+ # @return [String] the host:port combination (e.g., "localhost:3035")
116
+ # @example
117
+ # dev_server.host_with_port
118
+ # #=> "localhost:3035"
58
119
  def host_with_port
59
120
  "#{host}:#{port}"
60
121
  end
61
122
 
123
+ # Returns whether pretty output is enabled
124
+ #
125
+ # When true, the dev server produces prettier, more readable output.
126
+ # Can be overridden via SHAKAPACKER_DEV_SERVER_PRETTY environment variable.
127
+ #
128
+ # @return [Boolean] true if pretty output is enabled
62
129
  def pretty?
63
130
  fetch(:pretty)
64
131
  end
65
132
 
133
+ # Returns whether Hot Module Replacement (HMR) is enabled
134
+ #
135
+ # When true, the dev server updates modules in the browser without a full
136
+ # page reload, preserving application state.
137
+ # Can be overridden via SHAKAPACKER_DEV_SERVER_HMR environment variable.
138
+ #
139
+ # @return [Boolean] true if HMR is enabled
66
140
  def hmr?
67
141
  fetch(:hmr)
68
142
  end
69
143
 
144
+ # Returns whether CSS inlining is enabled
145
+ #
146
+ # When true, CSS is injected inline via JavaScript instead of being loaded
147
+ # as separate stylesheet files. This enables HMR for CSS.
148
+ # Can be overridden via SHAKAPACKER_DEV_SERVER_INLINE_CSS environment variable.
149
+ #
150
+ # @return [Boolean] true if CSS should be inlined
70
151
  def inline_css?
71
152
  case fetch(:inline_css)
72
153
  when false, "false"
@@ -76,6 +157,12 @@ class Shakapacker::DevServer
76
157
  end
77
158
  end
78
159
 
160
+ # Returns the environment variable prefix for dev server settings
161
+ #
162
+ # Environment variables for dev server settings use this prefix (default: "SHAKAPACKER_DEV_SERVER").
163
+ # For example, SHAKAPACKER_DEV_SERVER_PORT sets the port.
164
+ #
165
+ # @return [String] the env var prefix (typically "SHAKAPACKER_DEV_SERVER")
79
166
  def env_prefix
80
167
  config.dev_server.fetch(:env_prefix, DEFAULT_ENV_PREFIX)
81
168
  end
@@ -391,7 +391,7 @@ module Shakapacker
391
391
  expected_binstubs = {
392
392
  "bin/shakapacker" => "Main Shakapacker binstub",
393
393
  "bin/shakapacker-dev-server" => "Development server binstub",
394
- "bin/export-bundler-config" => "Config export binstub"
394
+ "bin/shakapacker-config" => "Config export binstub"
395
395
  }
396
396
 
397
397
  expected_binstubs.each do |path, description|
@@ -1013,7 +1013,7 @@ module Shakapacker
1013
1013
  binstubs = [
1014
1014
  "bin/shakapacker",
1015
1015
  "bin/shakapacker-dev-server",
1016
- "bin/export-bundler-config"
1016
+ "bin/shakapacker-config"
1017
1017
  ]
1018
1018
 
1019
1019
  existing_binstubs = binstubs.select { |b| doctor.root_path.join(b).exist? }
@@ -1171,10 +1171,10 @@ module Shakapacker
1171
1171
  puts " #{package_manager_install_command(package_manager)}"
1172
1172
  puts ""
1173
1173
  puts "For debugging configuration issues, export your webpack/rspack config:"
1174
- puts " bin/export-bundler-config --doctor"
1174
+ puts " bin/shakapacker-config --doctor"
1175
1175
  puts " (Exports annotated YAML configs for dev and production - best for troubleshooting)"
1176
1176
  puts ""
1177
- puts " See 'bin/export-bundler-config --help' for more options"
1177
+ puts " See 'bin/shakapacker-config --help' for more options"
1178
1178
  end
1179
1179
 
1180
1180
  def package_manager_install_command(manager)
@@ -1,10 +1,43 @@
1
1
  require "pathname"
2
2
 
3
+ # Represents a single instance of Shakapacker configuration and state
4
+ #
5
+ # An instance encapsulates all the configuration, compilation, and manifest
6
+ # lookup functionality for a specific Rails application. Most applications
7
+ # will use the shared instance accessible via {Shakapacker.instance}, but
8
+ # multiple instances can be created for testing or advanced scenarios.
9
+ #
10
+ # @example Using the default instance
11
+ # instance = Shakapacker::Instance.new
12
+ # instance.config.source_path
13
+ # instance.manifest.lookup("application.js")
14
+ #
15
+ # @example Creating an instance with custom paths
16
+ # instance = Shakapacker::Instance.new(
17
+ # root_path: "/path/to/app",
18
+ # config_path: "/custom/config.yml"
19
+ # )
3
20
  class Shakapacker::Instance
21
+ # The shared logger used by all Shakapacker instances
22
+ # @return [ActiveSupport::TaggedLogging] the logger
4
23
  cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
5
24
 
6
- attr_reader :root_path, :config_path
25
+ # The root path of the application
26
+ # @return [Pathname] the application root path
27
+ attr_reader :root_path
7
28
 
29
+ # The path to the Shakapacker configuration file
30
+ # @return [Pathname] the config file path
31
+ attr_reader :config_path
32
+
33
+ # Creates a new Shakapacker instance
34
+ #
35
+ # @param root_path [String, Pathname, nil] the application root path.
36
+ # Defaults to Rails.root if Rails is defined, otherwise uses current directory
37
+ # @param config_path [String, Pathname, nil] the path to shakapacker.yml.
38
+ # Can also be set via SHAKAPACKER_CONFIG environment variable.
39
+ # Defaults to +config/shakapacker.yml+ within the root_path
40
+ # @return [Shakapacker::Instance] the new instance
8
41
  def initialize(root_path: nil, config_path: nil)
9
42
  # Use Rails.root if Rails is defined and no root_path is provided
10
43
  @root_path = root_path || (defined?(Rails) && Rails&.root) || Pathname.new(Dir.pwd)
@@ -15,10 +48,23 @@ class Shakapacker::Instance
15
48
  @config_path = Pathname.new(ENV["SHAKAPACKER_CONFIG"] || config_path || default_config_path)
16
49
  end
17
50
 
51
+ # Returns the current Rails environment as a StringInquirer
52
+ #
53
+ # This allows for convenient environment checking:
54
+ # env.development? # => true/false
55
+ # env.production? # => true/false
56
+ #
57
+ # @return [ActiveSupport::StringInquirer] the environment
18
58
  def env
19
59
  @env ||= Shakapacker::Env.inquire self
20
60
  end
21
61
 
62
+ # Returns the configuration object for this instance
63
+ #
64
+ # The configuration is loaded from the shakapacker.yml file and provides
65
+ # access to all settings like source paths, output paths, and compilation options.
66
+ #
67
+ # @return [Shakapacker::Configuration] the configuration
22
68
  def config
23
69
  @config ||= Shakapacker::Configuration.new(
24
70
  root_path: root_path,
@@ -27,26 +73,64 @@ class Shakapacker::Instance
27
73
  )
28
74
  end
29
75
 
76
+ # Returns the compiler strategy for determining staleness
77
+ #
78
+ # The strategy (mtime or digest) determines how Shakapacker decides whether
79
+ # assets need recompilation.
80
+ #
81
+ # @return [Shakapacker::CompilerStrategy] the compiler strategy
82
+ # @api private
30
83
  def strategy
31
84
  @strategy ||= Shakapacker::CompilerStrategy.from_config
32
85
  end
33
86
 
87
+ # Returns the compiler for this instance
88
+ #
89
+ # The compiler is responsible for executing webpack/rspack to compile assets.
90
+ #
91
+ # @return [Shakapacker::Compiler] the compiler
34
92
  def compiler
35
93
  @compiler ||= Shakapacker::Compiler.new self
36
94
  end
37
95
 
96
+ # Returns the development server instance
97
+ #
98
+ # The dev server instance can query the status of the webpack-dev-server,
99
+ # including whether it's running, its host/port, and configuration.
100
+ #
101
+ # @return [Shakapacker::DevServer] the dev server
38
102
  def dev_server
39
103
  @dev_server ||= Shakapacker::DevServer.new config
40
104
  end
41
105
 
106
+ # Returns the manifest for looking up compiled assets
107
+ #
108
+ # The manifest reads the manifest.json file produced by webpack/rspack
109
+ # and provides methods to look up the compiled paths for source files.
110
+ #
111
+ # @return [Shakapacker::Manifest] the manifest
42
112
  def manifest
43
113
  @manifest ||= Shakapacker::Manifest.new self
44
114
  end
45
115
 
116
+ # Returns the commands instance for build operations
117
+ #
118
+ # The commands object provides methods for bootstrapping, cleaning,
119
+ # clobbering, and compiling assets.
120
+ #
121
+ # @return [Shakapacker::Commands] the commands
46
122
  def commands
47
123
  @commands ||= Shakapacker::Commands.new self
48
124
  end
49
125
 
126
+ # Returns whether CSS should be inlined by the dev server
127
+ #
128
+ # CSS inlining is enabled when:
129
+ # - The dev server has inline_css enabled
130
+ # - Hot Module Replacement (HMR) is enabled
131
+ # - The dev server is currently running
132
+ #
133
+ # @return [Boolean] true if CSS should be inlined
50
134
  def inlining_css?
51
135
  dev_server.inline_css? && dev_server.hmr? && dev_server.running?
52
136
  end
@@ -1,23 +1,70 @@
1
- # Singleton registry for accessing the packs path using a generated manifest.
2
- # This allows javascript_pack_tag, stylesheet_pack_tag, asset_pack_path to take a reference to,
3
- # say, "calendar.js" or "calendar.css" and turn it into "/packs/calendar-1016838bab065ae1e314.js" or
4
- # "/packs/calendar-1016838bab065ae1e314.css".
1
+ # Manifest for looking up compiled asset paths
5
2
  #
6
- # When the configuration is set to on-demand compilation, with the `compile: true` option in
7
- # the shakapacker.yml file, any lookups will be preceded by a compilation if one is needed.
3
+ # The manifest reads the +manifest.json+ file produced by webpack/rspack during
4
+ # compilation and provides methods to look up the compiled (digested) paths for
5
+ # source files.
6
+ #
7
+ # This allows view helpers like +javascript_pack_tag+, +stylesheet_pack_tag+, and
8
+ # +asset_pack_path+ to take a reference to a source file (e.g., "calendar.js")
9
+ # and turn it into the compiled path with digest (e.g., "/packs/calendar-1016838bab065ae1e314.js").
10
+ #
11
+ # == Automatic Compilation
12
+ #
13
+ # When the configuration has +compile: true+ in shakapacker.yml, any lookups will
14
+ # automatically trigger compilation if the assets are stale. This is typically
15
+ # enabled in development and disabled in production.
16
+ #
17
+ # == Caching
18
+ #
19
+ # The manifest can cache the loaded data in memory when +cache_manifest: true+ is
20
+ # set in the configuration. This improves performance in production by avoiding
21
+ # repeated file reads.
22
+ #
23
+ # @example Looking up assets
24
+ # manifest = Shakapacker.manifest
25
+ # manifest.lookup("application.js")
26
+ # #=> "/packs/application-abc123.js"
27
+ #
28
+ # manifest.lookup!("missing.js")
29
+ # #=> raises Shakapacker::Manifest::MissingEntryError
30
+ #
31
+ # @see Shakapacker::Helper
8
32
  class Shakapacker::Manifest
33
+ # Raised when an asset cannot be found in the manifest
9
34
  class MissingEntryError < StandardError; end
10
35
 
11
36
  delegate :config, :compiler, :dev_server, to: :@instance
12
37
 
38
+ # Creates a new manifest instance
39
+ #
40
+ # @param instance [Shakapacker::Instance] the Shakapacker instance
41
+ # @return [Shakapacker::Manifest] the new manifest
13
42
  def initialize(instance)
14
43
  @instance = instance
15
44
  end
16
45
 
46
+ # Reloads the manifest data from disk
47
+ #
48
+ # Forces a fresh read of the manifest.json file, bypassing any cache.
49
+ # This is useful when you know the manifest has been updated.
50
+ #
51
+ # @return [Hash] the loaded manifest data
17
52
  def refresh
18
53
  @data = load
19
54
  end
20
55
 
56
+ # Looks up an entry point with all its chunks (split code)
57
+ #
58
+ # This method is used when you need to load all chunks for a pack that has
59
+ # been split via code splitting. It returns an array of asset paths for the
60
+ # main entry and all its dynamic imports.
61
+ #
62
+ # @param name [String] the entry point name (e.g., "application")
63
+ # @param pack_type [Hash] options hash with :type key (:javascript, :stylesheet, etc.)
64
+ # @return [Array<String>, nil] array of asset paths, or nil if not found
65
+ # @example
66
+ # manifest.lookup_pack_with_chunks("application", type: :javascript)
67
+ # #=> ["/packs/runtime-abc123.js", "/packs/application-def456.js"]
21
68
  def lookup_pack_with_chunks(name, pack_type = {})
22
69
  compile if compiling?
23
70
 
@@ -28,23 +75,50 @@ class Shakapacker::Manifest
28
75
  nil
29
76
  end
30
77
 
78
+ # Like {#lookup_pack_with_chunks}, but raises an error if not found
79
+ #
80
+ # @param name [String] the entry point name
81
+ # @param pack_type [Hash] options hash with :type key
82
+ # @return [Array<String>] array of asset paths
83
+ # @raise [MissingEntryError] if the entry point is not found in the manifest
31
84
  def lookup_pack_with_chunks!(name, pack_type = {})
32
85
  lookup_pack_with_chunks(name, pack_type) || handle_missing_entry(name, pack_type)
33
86
  end
34
87
 
35
- # Computes the relative path for a given Shakapacker asset using manifest.json.
36
- # If no asset is found, returns nil.
88
+ # Looks up the compiled path for a given asset
89
+ #
90
+ # Computes the relative path for a Shakapacker asset using the manifest.json file.
91
+ # If automatic compilation is enabled and the assets are stale, triggers a
92
+ # compilation before looking up the path.
37
93
  #
38
- # Example:
94
+ # @param name [String] the source file name (e.g., "calendar.js" or "calendar")
95
+ # @param pack_type [Hash] options hash with :type key (:javascript, :stylesheet, etc.).
96
+ # If not specified, the extension from the name is used.
97
+ # @return [String, nil] the compiled asset path, or nil if not found
98
+ # @example
99
+ # Shakapacker.manifest.lookup('calendar.js')
100
+ # #=> "/packs/calendar-1016838bab065ae1e122.js"
39
101
  #
40
- # Shakapacker.manifest.lookup('calendar.js') # => "/packs/calendar-1016838bab065ae1e122.js"
102
+ # Shakapacker.manifest.lookup('calendar', type: :javascript)
103
+ # #=> "/packs/calendar-1016838bab065ae1e122.js"
41
104
  def lookup(name, pack_type = {})
42
105
  compile if compiling?
43
106
 
44
107
  find(full_pack_name(name, pack_type[:type]))
45
108
  end
46
109
 
47
- # Like lookup, except that if no asset is found, raises a Shakapacker::Manifest::MissingEntryError.
110
+ # Like {#lookup}, but raises an error if the asset is not found
111
+ #
112
+ # @param name [String] the source file name
113
+ # @param pack_type [Hash] options hash with :type key
114
+ # @return [String] the compiled asset path
115
+ # @raise [MissingEntryError] if the asset is not found in the manifest
116
+ # @example
117
+ # Shakapacker.manifest.lookup!('calendar.js')
118
+ # #=> "/packs/calendar-1016838bab065ae1e122.js"
119
+ #
120
+ # Shakapacker.manifest.lookup!('missing.js')
121
+ # #=> raises MissingEntryError
48
122
  def lookup!(name, pack_type = {})
49
123
  lookup(name, pack_type) || handle_missing_entry(name, pack_type)
50
124
  end
@@ -1,4 +1,4 @@
1
1
  module Shakapacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "9.3.0.beta.7".freeze
3
+ VERSION = "9.3.0".freeze
4
4
  end
data/lib/shakapacker.rb CHANGED
@@ -3,22 +3,86 @@ require "active_support/core_ext/string/inquiry"
3
3
  require "active_support/logger"
4
4
  require "active_support/tagged_logging"
5
5
 
6
+ # = Shakapacker
7
+ #
8
+ # Shakapacker is a Ruby gem that integrates webpack and rspack with Rails applications,
9
+ # providing a modern asset pipeline for JavaScript, CSS, and other web assets.
10
+ #
11
+ # The main Shakapacker module provides singleton-style access to configuration,
12
+ # compilation, and asset manifest functionality. Most methods delegate to a shared
13
+ # {Shakapacker::Instance} object.
14
+ #
15
+ # == Basic Usage
16
+ #
17
+ # # Access configuration
18
+ # Shakapacker.config.source_path
19
+ # #=> Pathname("/path/to/app/packs")
20
+ #
21
+ # # Check if dev server is running
22
+ # Shakapacker.dev_server.running?
23
+ # #=> true
24
+ #
25
+ # # Look up compiled assets
26
+ # Shakapacker.manifest.lookup("application.js")
27
+ # #=> "/packs/application-abc123.js"
28
+ #
29
+ # # Compile assets
30
+ # Shakapacker.compile
31
+ #
32
+ # == Configuration
33
+ #
34
+ # Configuration is loaded from +config/shakapacker.yml+ and can be accessed via
35
+ # {Shakapacker.config}. The configuration determines the source paths, output paths,
36
+ # compilation settings, and dev server options.
37
+ #
38
+ # @see Shakapacker::Configuration
39
+ # @see Shakapacker::Instance
6
40
  module Shakapacker
7
41
  extend self
8
42
 
43
+ # Default environment when RAILS_ENV is not set
9
44
  DEFAULT_ENV = "development".freeze
10
45
  # Environments that use their RAILS_ENV value for NODE_ENV
11
46
  # All other environments (production, staging, etc.) use "production" for webpack optimizations
12
47
  DEV_TEST_ENVS = %w[development test].freeze
13
48
 
49
+ # Sets the shared Shakapacker instance
50
+ #
51
+ # This is primarily used for testing or advanced customization scenarios.
52
+ # In most applications, the default instance is sufficient.
53
+ #
54
+ # @param instance [Shakapacker::Instance] the instance to use
55
+ # @return [Shakapacker::Instance] the instance that was set
56
+ # @api public
14
57
  def instance=(instance)
15
58
  @instance = instance
16
59
  end
17
60
 
61
+ # Returns the shared Shakapacker instance
62
+ #
63
+ # This instance is used by all module-level delegate methods. It provides
64
+ # access to configuration, compilation, manifest lookup, and more.
65
+ #
66
+ # @return [Shakapacker::Instance] the shared instance
67
+ # @api public
18
68
  def instance
19
69
  @instance ||= Shakapacker::Instance.new
20
70
  end
21
71
 
72
+ # Temporarily overrides NODE_ENV for the duration of the block
73
+ #
74
+ # This is useful when you need to perform operations with a specific NODE_ENV
75
+ # value without permanently changing the environment.
76
+ #
77
+ # @param env [String] the NODE_ENV value to use temporarily
78
+ # @yield the block to execute with the temporary NODE_ENV
79
+ # @return [Object] the return value of the block
80
+ # @example
81
+ # Shakapacker.with_node_env("production") do
82
+ # # This code runs with NODE_ENV=production
83
+ # Shakapacker.compile
84
+ # end
85
+ # @api public
22
86
  def with_node_env(env)
23
87
  original = ENV["NODE_ENV"]
24
88
  ENV["NODE_ENV"] = env
@@ -27,13 +91,32 @@ module Shakapacker
27
91
  ENV["NODE_ENV"] = original
28
92
  end
29
93
 
30
- # Set NODE_ENV based on RAILS_ENV if not already set
31
- # - development/test environments use their RAILS_ENV value
32
- # - all other environments (production, staging, etc.) use "production" for webpack optimizations
94
+ # Sets NODE_ENV based on RAILS_ENV if not already set
95
+ #
96
+ # Environment mapping:
97
+ # - +development+ and +test+ environments use their RAILS_ENV value for NODE_ENV
98
+ # - All other environments (+production+, +staging+, etc.) use "production" for webpack optimizations
99
+ #
100
+ # This method is typically called automatically during Rails initialization.
101
+ #
102
+ # @return [String] the NODE_ENV value that was set
103
+ # @api private
33
104
  def ensure_node_env!
34
105
  ENV["NODE_ENV"] ||= DEV_TEST_ENVS.include?(ENV["RAILS_ENV"]) ? ENV["RAILS_ENV"] : "production"
35
106
  end
36
107
 
108
+ # Temporarily redirects Shakapacker logging to STDOUT
109
+ #
110
+ # This is useful for debugging or when you want to see compilation output
111
+ # in the console instead of the Rails log.
112
+ #
113
+ # @yield the block to execute with STDOUT logging
114
+ # @return [Object] the return value of the block
115
+ # @example
116
+ # Shakapacker.ensure_log_goes_to_stdout do
117
+ # Shakapacker.compile
118
+ # end
119
+ # @api public
37
120
  def ensure_log_goes_to_stdout
38
121
  old_logger = Shakapacker.logger
39
122
  Shakapacker.logger = Logger.new(STDOUT)
@@ -42,8 +125,65 @@ module Shakapacker
42
125
  Shakapacker.logger = old_logger
43
126
  end
44
127
 
128
+ # @!method logger
129
+ # Returns the logger instance used by Shakapacker
130
+ # @return [Logger] the logger instance
131
+ # @see Shakapacker::Instance#logger
132
+ # @!method logger=(logger)
133
+ # Sets the logger instance used by Shakapacker
134
+ # @param logger [Logger] the logger to use
135
+ # @return [Logger] the logger that was set
136
+ # @see Shakapacker::Instance#logger=
137
+ # @!method env
138
+ # Returns the current Rails environment as an ActiveSupport::StringInquirer
139
+ # @return [ActiveSupport::StringInquirer] the environment
140
+ # @see Shakapacker::Instance#env
141
+ # @!method inlining_css?
142
+ # Returns whether CSS inlining is enabled
143
+ # @return [Boolean] true if CSS should be inlined
144
+ # @see Shakapacker::Instance#inlining_css?
45
145
  delegate :logger, :logger=, :env, :inlining_css?, to: :instance
146
+
147
+ # @!method config
148
+ # Returns the Shakapacker configuration object
149
+ # @return [Shakapacker::Configuration] the configuration
150
+ # @see Shakapacker::Instance#config
151
+ # @!method compiler
152
+ # Returns the compiler instance for compiling assets
153
+ # @return [Shakapacker::Compiler] the compiler
154
+ # @see Shakapacker::Instance#compiler
155
+ # @!method manifest
156
+ # Returns the manifest instance for looking up compiled assets
157
+ # @return [Shakapacker::Manifest] the manifest
158
+ # @see Shakapacker::Instance#manifest
159
+ # @!method commands
160
+ # Returns the commands instance for build operations
161
+ # @return [Shakapacker::Commands] the commands object
162
+ # @see Shakapacker::Instance#commands
163
+ # @!method dev_server
164
+ # Returns the dev server instance for querying server status
165
+ # @return [Shakapacker::DevServer] the dev server
166
+ # @see Shakapacker::Instance#dev_server
46
167
  delegate :config, :compiler, :manifest, :commands, :dev_server, to: :instance
168
+
169
+ # @!method bootstrap
170
+ # Creates the default configuration files and directory structure
171
+ # @return [void]
172
+ # @see Shakapacker::Commands#bootstrap
173
+ # @!method clean(count = nil, age = nil)
174
+ # Removes old compiled packs, keeping the most recent versions
175
+ # @param count [Integer, nil] number of versions to keep per entry
176
+ # @param age [Integer, nil] maximum age in seconds for packs to keep
177
+ # @return [void]
178
+ # @see Shakapacker::Commands#clean
179
+ # @!method clobber
180
+ # Removes all compiled packs
181
+ # @return [void]
182
+ # @see Shakapacker::Commands#clobber
183
+ # @!method compile
184
+ # Compiles all webpack/rspack packs
185
+ # @return [Boolean] true if compilation succeeded
186
+ # @see Shakapacker::Commands#compile
47
187
  delegate :bootstrap, :clean, :clobber, :compile, to: :commands
48
188
  end
49
189
 
@@ -11,7 +11,7 @@ namespace :shakapacker do
11
11
  • Required and optional npm dependencies
12
12
  • JavaScript transpiler (Babel, SWC, esbuild) configuration
13
13
  • CSS, CSS Modules, and stylesheet preprocessor setup
14
- • Binstubs presence (shakapacker, shakapacker-dev-server, export-bundler-config)
14
+ • Binstubs presence (shakapacker, shakapacker-dev-server, shakapacker-config)
15
15
  • Version consistency between gem and npm package
16
16
  • Legacy Webpacker file detection
17
17
 
@@ -42,18 +42,18 @@ namespace :shakapacker do
42
42
  Note: When using 'rake', you must use '--' to separate rake options from task arguments.
43
43
  Example: rake shakapacker:export_bundler_config -- --doctor
44
44
 
45
- The task automatically falls back to the gem version if bin/export-bundler-config
45
+ The task automatically falls back to the gem version if bin/shakapacker-config
46
46
  binstub is not installed. To install all binstubs, run: rails shakapacker:binstubs
47
47
  DESC
48
48
  task :export_bundler_config do
49
49
  # Try to use the binstub if it exists, otherwise use the gem's version
50
- bin_path = Rails.root.join("bin/export-bundler-config")
50
+ bin_path = Rails.root.join("bin/shakapacker-config")
51
51
 
52
52
  unless File.exist?(bin_path)
53
53
  # Binstub not installed, use the gem's version directly
54
- gem_bin_path = File.expand_path("../../install/bin/export-bundler-config", __dir__)
54
+ gem_bin_path = File.expand_path("../../install/bin/shakapacker-config", __dir__)
55
55
 
56
- $stderr.puts "Note: bin/export-bundler-config binstub not found."
56
+ $stderr.puts "Note: bin/shakapacker-config binstub not found."
57
57
  $stderr.puts "Using gem version directly. To install the binstub, run: rake shakapacker:binstubs"
58
58
  $stderr.puts ""
59
59
 
data/package/config.ts CHANGED
@@ -55,7 +55,6 @@ if (existsSync(configPath)) {
55
55
  const envAppConfig = appYmlObject[railsEnv]
56
56
 
57
57
  if (!envAppConfig) {
58
- /* eslint no-console:0 */
59
58
  console.warn(
60
59
  `[SHAKAPACKER WARNING] Environment '${railsEnv}' not found in ${configPath}\n` +
61
60
  `Available environments: ${Object.keys(appYmlObject).join(", ")}\n` +