bundlebun 0.2.3.1.3.7-aarch64-linux → 0.4.0.1.3.8-aarch64-linux

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: 547a3cd68b9b57e3f53f6f94283b87e9e6b309db993ba9cd08d5e0da0685342c
4
- data.tar.gz: 8d436caaa141ce41d34d068707b5f5abb770540bb265cec247bb6bbb9854f51d
3
+ metadata.gz: 06ab64db90fe90fd19fb08427c8ca39dee9067d575e296a714da249b9f00e05a
4
+ data.tar.gz: c80e30e34145a8d6c2ca0da91fd2d1d24c4ebce997baa145ece9bf8c319ab049
5
5
  SHA512:
6
- metadata.gz: 69b8240e15ea82510da073a6a49506b7f289fb034fdc2718549180eef9f944e75c4183f9110b1756c4631d405da4861b09570e5520fd827284308edc8527cbd4
7
- data.tar.gz: 68ed891e75f590f0ff2a55b4647804864dbc556c007122a560ac678f33a76a9cfa087ed039362c58738a1f5356af15748a79065e1bbdf6336f28e759103047cd
6
+ metadata.gz: 53d74f5e6c44fdc40a36c29d7903ebd044eae559b79c6c8f074c781f1b34e54f1b9fb93f1579bf4ae278b06b278c2ba4f4b879906f8cf746ffcda784e8f608bb
7
+ data.tar.gz: 34deaf0a237207308a17f13ae82fc6bb87b7eeab57174a7d42ecf0d710a0a1d3e1e42dc28c4d784bc8faf8193255e5199e27a04b784d3972a3e17ac282e265fb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.4.0] - 2026-02-01
2
+
3
+ - `Bundlebun.system(args)` method: runs Bun as a subprocess and returns to Ruby. Returns `true` if Bun exited successfully. Use this when you need to continue executing Ruby code after Bun finishes.
4
+ - Default behaviour remains: `Bundlebun.()` / `Bundlebun.call` / `Bundlebun.exec` all replace the current Ruby process with Bun (never return). This is what binstubs and wrappers use.
5
+
6
+ - ActiveSupport::Notifications instrumentation added. `system.bundlebun` for `Bundlebun.system` calls, `exec.bundlebun` for exec calls (binstubs, wrappers). Payload: `{ command: args }`.
7
+ - Added RBS type signatures for the public API
8
+
9
+ ## [0.3.0] - 2026-01-29
10
+
11
+ - New `rake bun:install:package` task: automatically migrates `package.json` scripts to use `bin/bun`. Replaces calls to `bun`, `bunx`, `npx`, `npm run`, `yarn run`, `pnpm run`, and `pnpm exec` with their `bin/bun` equivalents. Asks for confirmation.
12
+ - New `rake bun:install:procfile` task: automatically migrates `Procfile` and `Procfile.*` files to use `bin/bun`. Same as above.
13
+ - Both tasks are automatically invoked by `rake bun:install` when the relevant files are detected.
14
+
1
15
  ## [0.2.3] - 2025-12-17
2
16
 
3
17
  - Update dependencies
data/README.md CHANGED
@@ -71,8 +71,8 @@ bundle install
71
71
  bundle add bundlebun
72
72
  ```
73
73
 
74
- If you're seeing a message like `Could not find gems matching 'bundlebun' valid for all resolution platforms
75
- (aarch64-linux, aarch64-linux-gnu <...> )`, [check this article](https://github.com/yaroslav/bundlebun/wiki/Could-not-find-gems-matching-'bundlebun'-valid-for-all-resolution-platforms).
74
+ _If you're seeing a message like `Could not find gems matching 'bundlebun' valid for all resolution platforms
75
+ (aarch64-linux, aarch64-linux-gnu <...> )`, [check this article](https://github.com/yaroslav/bundlebun/wiki/Could-not-find-gems-matching-'bundlebun'-valid-for-all-resolution-platforms)._
76
76
 
77
77
  Next, run:
78
78
 
@@ -82,18 +82,83 @@ rake bun:install
82
82
 
83
83
  The task will install a binstub (`bin/bun`) that you can use to run Bun commands; try running `bin/bun` or `bin/bun --version`.
84
84
 
85
- You should use `bin/bun` in your scripts, including your local runners like `Procfile.dev` or `Procfile`, and `package.json`—if you had a call to `node` or `bun` in the `scripts` section there.
85
+ If `package.json` is present, the installer will offer to migrate your scripts to use `bin/bun` (e.g., `bun` `bin/bun`, `npx` `bin/bun x`). You can also run `rake bun:install:package` manually later.
86
+
87
+ Similarly, if `Procfile` or `Procfile.*` files are present, the installer will offer to migrate those as well. Run `rake bun:install:procfile` manually if needed.
86
88
 
87
89
  _Windows tip:_ If you're on Windows, the `bin\bun.cmd` file will be created. If you've joined an existing project where only the Unix-like binstub exists at that location, just run `rake bun:install` again.
88
90
 
89
- Next, the Rake task will try to detect the integrations we need to install based on the classes and modules Rake can see in your project. We'll continue with integrations.
91
+ Next, the Rake task will try to detect the integrations we need to install based on the classes and modules Rake can see in your project. See: _Integrations_.
90
92
 
91
93
  **By default, on load, bundlebun:**
92
94
 
93
95
  - adds the path to the bundled `bun` executable to the start of your application's `PATH`. That simplifies the integration in cases where we don't really need to monkey-patch a lot of code, and we just need to make sure it "sees" our `bun` executable as available.
94
96
  - tries to detect and load all possible integrations.
95
97
 
96
- ### Integrations
98
+ ## Usage
99
+
100
+ ### Binstub
101
+
102
+ The easiest way to interact with bundled Bun is via the binstub at `bin/bun`; it will launch the bundled version of Bun with the arguments provided:
103
+
104
+ ```sh
105
+ > bin/bun
106
+ Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.1.38+bf2f153f5)
107
+
108
+ Usage: bun <command> [...flags] [...args]
109
+
110
+ ...
111
+ ```
112
+
113
+ ### `PATH`
114
+
115
+ The bundlebun gem adds the directory with a binary Bun distribution to your `PATH`: prepends it there, to be exact. That helps existing tools that can detect the presence of `bun` executable to find it and work with no further setup or monkey-patching.
116
+
117
+ ### Rake
118
+
119
+ Alternatively, you can use a Rake task. The syntax is far from perfect, but that's a limitation of Rake. You need to add quotes around the parameters and put them into square brackets. If you cannot install the binstub, though, might be your option.
120
+
121
+ ```
122
+ rake bun[command] # Run bundled Bun with parameters
123
+ ```
124
+
125
+ ```sh
126
+ > rake "bun[outdated]"
127
+ bun outdated v1.1.38 (bf2f153f)
128
+ ...
129
+ ```
130
+
131
+ ### Ruby
132
+
133
+ **Check bundlebun API: https://rubydoc.info/gems/bundlebun**.
134
+
135
+ The easiest way to call Bun from Ruby is via `Bundlebun.()` (shortcut for `Bundlebun.call()`).
136
+
137
+ **Note:** `Bundlebun.call` replaces the current Ruby process with Bun: it never returns.
138
+
139
+ ```ruby
140
+ Bundlebun.('outdated') # runs `bun outdated`
141
+ Bundlebun.call(['add', 'postcss']) # runs `bun add postcss`
142
+ ```
143
+
144
+ If you need to run Bun and then continue executing your Ruby code, use `Bundlebun.system`:
145
+
146
+ ```ruby
147
+ if Bundlebun.system('install')
148
+ puts 'Dependencies installed!'
149
+ else
150
+ puts 'Installation failed'
151
+ end
152
+
153
+ # Run tests and check result
154
+ success = Bundlebun.system('test')
155
+ ```
156
+
157
+ Returns `true` if Bun exited successfully, `false` or `nil` otherwise.
158
+
159
+ Check out the [API documentation](https://rubydoc.info/gems/bundlebun) on `Bundlebun::Runner` for helper methods.
160
+
161
+ ## Integrations
97
162
 
98
163
  Usually, if you've placed `gem 'bundlebun'` after your frontend-related gems in the `Gemfile`, and did `rake bun:install`, the integrations should all be working out of the box.
99
164
 
@@ -158,52 +223,23 @@ Alternatively, you can load the monkey-patch manually:
158
223
  Bundlebun::Integrations::ExecJS.bun!
159
224
  ```
160
225
 
161
- ## Usage
162
-
163
- ### Binstub
164
-
165
- The easiest way to interact with bundled Bun is via the binstub at `bin/bun`; it will launch the bundled version of Bun with the arguments provided:
166
-
167
- ```sh
168
- > bin/bun
169
- Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.1.38+bf2f153f5)
170
-
171
- Usage: bun <command> [...flags] [...args]
172
-
173
- ...
174
- ```
175
-
176
- ### `PATH`
226
+ #### ActiveSupport::Notifications (Instrumentation)
177
227
 
178
- The bundlebun gem adds the directory with a binary Bun distribution to your `PATH`: prepends it there, to be exact. That helps existing tools that can detect the presence of `bun` executable to find it and work with no further setup or monkey-patching.
228
+ When ActiveSupport is available, bundlebun emits instrumentation events that you can subscribe to for logging or monitoring:
179
229
 
180
- ### Rake
230
+ - `system.bundlebun` for `Bundlebun.system` (calling Bun and returning to Ruby code);
231
+ - `exec.bundlebun` for `Bundlebun.call` / `Bundlebun.exec` (binstubs and wrappers: exiting to Bun).
181
232
 
182
- Alternatively, you can use a Rake task. The syntax is far from perfect, but that's a limitation of Rake. You need to add quotes around the parameters and put them into square brackets. If you cannot install the binstub, though, might be your option.
233
+ The payload is `{ command: args }`: the arguments you passed to the method (string or array).
183
234
 
184
- ```
185
- rake bun[command] # Run bundled Bun with parameters
186
- ```
187
-
188
- ```sh
189
- > rake "bun[outdated]"
190
- bun outdated v1.1.38 (bf2f153f)
191
- ...
192
- ```
193
-
194
- ### Ruby
195
-
196
- **Check bundlebun API: https://rubydoc.info/gems/bundlebun**.
197
-
198
- The easiest way to call Bun from Ruby would be `Bundlebun.call`:
235
+ Example subscriber:
199
236
 
200
237
  ```ruby
201
- Bundlebun.call("outdated") # => `bun outdated`
202
- Bundlebun.call(["add", "postcss"]) # => `bun add postcss`
238
+ ActiveSupport::Notifications.subscribe('system.bundlebun') do |event|
239
+ Rails.logger.info "Bun: #{event.payload[:command]} (#{event.duration.round(1)}ms)"
240
+ end
203
241
  ```
204
242
 
205
- Check out the [API documentation](https://rubydoc.info/gems/bundlebun) on `Bundlebun::Runner` for helper methods.
206
-
207
243
  ## Versioning
208
244
 
209
245
  bundlebun uses the `#{bundlebun.version}.#{bun.version}` versioning scheme. Meaning: gem bundlebun version `0.1.0.1.1.38` is a distribution that includes a gem with its own code version `0.1.0` and a Bun runtime with version `1.1.38`.
data/exe/bundlebun CHANGED
@@ -24,4 +24,4 @@ rescue LoadError
24
24
  end
25
25
  require 'bundlebun'
26
26
 
27
- Bundlebun::Runner.call(ARGV)
27
+ Bundlebun.call(ARGV)
@@ -31,10 +31,13 @@ module Bundlebun
31
31
  def prepend(new_path)
32
32
  return if new_path.nil? || new_path.empty?
33
33
 
34
- path_to_check = Bundlebun::Platform.windows? ? path.downcase : path
35
- check_path = Bundlebun::Platform.windows? ? new_path.downcase : new_path
34
+ already_present = if Bundlebun::Platform.windows?
35
+ path.downcase.start_with?(new_path.downcase)
36
+ else
37
+ path.start_with?(new_path)
38
+ end
36
39
 
37
- self.path = "#{new_path}#{separator}#{path}" unless path_to_check.start_with?(check_path)
40
+ self.path = "#{new_path}#{separator}#{path}" unless already_present
38
41
  path
39
42
  end
40
43
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bundlebun
2
4
  # Bundlebun includes several integrations for frontend-related gems and frameworks.
3
5
  #
@@ -3,29 +3,92 @@
3
3
  module Bundlebun
4
4
  # {Runner} is the class that bundlebun uses to run the bundled Bun executable.
5
5
  #
6
+ # bundlebun provides two ways to run Bun:
7
+ #
8
+ # - {.call} (also available as {.exec}): Replaces the current Ruby process with Bun. This is the default.
9
+ #
10
+ # - {.system}: Runs Bun as a subprocess and returns control to Ruby.
11
+ # Use this when you need to continue executing Ruby code after Bun finishes.
12
+ #
6
13
  # @see Bundlebun
14
+ #
15
+ # @example Running Bun (replaces process, never returns)
16
+ # Bundlebun.('install')
17
+ # Bundlebun.call('outdated')
18
+ # Bundlebun.call(['add', 'postcss'])
19
+ #
20
+ # @example Running Bun as subprocess (returns to Ruby)
21
+ # if Bundlebun.system('install')
22
+ # puts 'Dependencies installed!'
23
+ # end
7
24
  class Runner
8
25
  BINSTUB_PATH = 'bin/bun'
9
26
  RELATIVE_DIRECTORY = 'lib/bundlebun/vendor/bun'
10
27
 
11
28
  class << self
12
- # Runs the Bun runtime with parameters.
29
+ # Replaces the current Ruby process with Bun.
13
30
  #
14
- # A wrapper for {Bundlebun::Runner.new}, {Bundlebun::Runner.call}.
31
+ # When `ActiveSupport::Notifications` is available, this method publishes an
32
+ # `exec.bundlebun` event before replacing the process. The payload contains
33
+ # `{ command: arguments }` where `arguments` is what was passed to the method.
15
34
  #
16
35
  # @param arguments [String, Array<String>] Command arguments to pass to Bun
17
- # @return [Integer] Exit status code (`127` if executable not found)
36
+ # @return [void] This method never returns
18
37
  #
19
- # @example String as an argument
20
- # Bundlebun.call('--version') # => `bun --version`
38
+ # @example In a binstub (bin/bun)
39
+ # #!/usr/bin/env ruby
40
+ # require 'bundlebun'
41
+ # Bundlebun.exec(ARGV)
42
+ #
43
+ # @see .call
44
+ # @see .system
45
+ def exec(...)
46
+ new(...).exec
47
+ end
48
+
49
+ # Replaces the current Ruby process with Bun. Alias for {.exec}.
50
+ # Also available via the `.()` shorthand syntax.
51
+ #
52
+ # @param arguments [String, Array<String>] Command arguments to pass to Bun
53
+ # @return [void] This method never returns
21
54
  #
22
- # @example Array of strings as an argument
23
- # Bundlebun.call(['add', 'postcss']) # => `bun add postcss`
55
+ # @example Basic usage
56
+ # Bundlebun.call('outdated')
57
+ # Bundlebun.call(['add', 'postcss'])
24
58
  #
25
- # @see Bundlebun::Runner.new
26
- # @see Bundlebun::Runner#call
59
+ # @example Using the .() shorthand
60
+ # Bundlebun.('install')
61
+ #
62
+ # @see .exec
63
+ # @see .system
27
64
  def call(...)
28
- new(...).call
65
+ exec(...)
66
+ end
67
+
68
+ # Runs Bun as a subprocess and returns control to Ruby.
69
+ #
70
+ # Unlike {.call} and {.exec}, this method does not replace the current process.
71
+ # Use this when you need to run Bun and then continue executing Ruby code.
72
+ #
73
+ # When `ActiveSupport::Notifications` is available, this method publishes a
74
+ # `system.bundlebun` event with timing information. The payload contains
75
+ # `{ command: arguments }` where `arguments` is what was passed to the method.
76
+ #
77
+ # @param arguments [String, Array<String>] Command arguments to pass to Bun
78
+ # @return [Boolean, nil] `true` if Bun exited successfully (status 0),
79
+ # `false` if it exited with an error, `nil` if execution failed
80
+ #
81
+ # @example Run install and check result
82
+ # if Bundlebun.system('install')
83
+ # puts 'Dependencies installed!'
84
+ # else
85
+ # puts 'Installation failed'
86
+ # end
87
+ #
88
+ # @see .call
89
+ # @see .exec
90
+ def system(...)
91
+ new(...).system
29
92
  end
30
93
 
31
94
  # A relative path to binstub that bundlebun usually generates with installation Rake tasks.
@@ -98,41 +161,92 @@ module Bundlebun
98
161
  end
99
162
  end
100
163
 
101
- # Intialize the {Runner} with arguments to run the Bun runtime later via #call.
164
+ # Initialize the {Runner} with arguments to run the Bun runtime later.
102
165
  #
103
166
  # @param arguments [String, Array<String>] Command arguments to pass to Bun
104
167
  #
105
168
  # @example String as an argument
106
- # Bundlebun::Runner.new('--version') # => `bun --version`
169
+ # Bundlebun::Runner.new('--version')
107
170
  #
108
171
  # @example Array of strings as an argument
109
- # Bundlebun::Runner.new(['add', 'postcss']) # => `bun add postcss`
172
+ # Bundlebun::Runner.new(['add', 'postcss'])
110
173
  #
111
- # @see Bundlebun::Runner#call
174
+ # @see #system
175
+ # @see #exec
112
176
  def initialize(arguments = '')
113
177
  @arguments = arguments
114
178
  end
115
179
 
116
- # Runs the Bun executable with previously specified arguments.
180
+ # Replaces the current Ruby process with Bun.
181
+ # This is the default behavior.
117
182
  #
118
- # Check other methods of {Bundlebun::Runner} to see how we determine what to run exactly.
183
+ # When `ActiveSupport::Notifications` is available, this method publishes an
184
+ # `exec.bundlebun` event before replacing the process. The payload contains
185
+ # `{ command: arguments }` where `arguments` is what was passed to the runner.
119
186
  #
120
- # @return [Integer] Exit status code (`127` if executable not found)
187
+ # @return [void] This method never returns
121
188
  #
122
189
  # @example
123
- # b = Bundlebun::Runner.new('--version')
124
- # b.call
190
+ # runner = Bundlebun::Runner.new(ARGV)
191
+ # runner.exec # Ruby process ends here, Bun takes over
125
192
  #
126
- # @see Bundlebun::Runner
193
+ # @see #system
194
+ def exec
195
+ check_executable!
196
+ instrument('exec.bundlebun')
197
+ Kernel.exec(command)
198
+ end
199
+
200
+ # Replaces the current Ruby process with Bun. Alias for {#exec}.
201
+ #
202
+ # @return [void] This method never returns
203
+ #
204
+ # @see #exec
127
205
  def call
206
+ exec
207
+ end
208
+
209
+ # Runs Bun as a subprocess and returns control to Ruby.
210
+ #
211
+ # Unlike {#call} and {#exec}, this method does not replace the current process.
212
+ # Use this when you need to run Bun and then continue executing Ruby code.
213
+ #
214
+ # When `ActiveSupport::Notifications` is available, this method publishes a
215
+ # `system.bundlebun` event with timing information. The payload contains
216
+ # `{ command: arguments }` where `arguments` is what was passed to the runner.
217
+ #
218
+ # @return [Boolean, nil] `true` if Bun exited successfully (status 0),
219
+ # `false` if it exited with an error, `nil` if execution failed
220
+ #
221
+ # @example
222
+ # runner = Bundlebun::Runner.new('install')
223
+ # if runner.system
224
+ # puts 'Dependencies installed!'
225
+ # end
226
+ #
227
+ # @see #exec
228
+ def system
128
229
  check_executable!
129
- exec(command)
230
+ instrument('system.bundlebun') do
231
+ Kernel.system(command)
232
+ end
130
233
  end
131
234
 
132
235
  private
133
236
 
134
237
  attr_reader :arguments
135
238
 
239
+ def instrument(event, &block)
240
+ return block&.call unless defined?(ActiveSupport::Notifications)
241
+
242
+ payload = {command: arguments}
243
+ if block
244
+ ActiveSupport::Notifications.instrument(event, payload, &block)
245
+ else
246
+ ActiveSupport::Notifications.instrument(event, payload)
247
+ end
248
+ end
249
+
136
250
  def check_executable!
137
251
  return if self.class.binary_path_exist?
138
252
 
Binary file
@@ -8,5 +8,5 @@ module Bundlebun
8
8
  # a Bun runtime with version `1.1.38`.
9
9
  #
10
10
  # This constant always points to the "own" version of the gem.
11
- VERSION = '0.2.3'
11
+ VERSION = '0.4.0'
12
12
  end
data/lib/bundlebun.rb CHANGED
@@ -9,28 +9,84 @@ require 'zeitwerk'
9
9
  # bundlebun includes binary distributions of Bun for each of the supported
10
10
  # platforms (macOS, Linux, Windows) and architectures.
11
11
  #
12
+ # bundlebun provides two ways to run Bun:
13
+ #
14
+ # - {.call} (also available as {.exec}): Replaces the current Ruby process with Bun. The default.
15
+ #
16
+ # - {.system}: Runs Bun as a subprocess and returns control to Ruby.
17
+ # Use this when you need to continue executing Ruby code after Bun finishes.
18
+ #
12
19
  # @see Bundlebun::Runner
13
20
  # @see Bundlebun::Integrations
21
+ #
22
+ # @example Running Bun (replaces process, never returns)
23
+ # Bundlebun.('install') # .() shorthand syntax
24
+ # Bundlebun.call('outdated')
25
+ # Bundlebun.call(['add', 'postcss'])
26
+ #
27
+ # @example Running Bun as subprocess (returns to Ruby)
28
+ # if Bundlebun.system('install')
29
+ # puts 'Dependencies installed!'
30
+ # end
14
31
  module Bundlebun
15
32
  class << self
16
- # Runs the Bun runtime with parameters.
33
+ # Replaces the current Ruby process with Bun.
17
34
  #
18
- # A shortcut for {Bundlebun::Runner.call}.
35
+ # This is the default way to run Bun. The Ruby process is replaced by Bun
36
+ # and never returns. Also available via the `.()` shorthand syntax.
19
37
  #
20
38
  # @param arguments [String, Array<String>] Command arguments to pass to Bun
21
- # @return [Integer] Exit status code (`127` if executable not found)
39
+ # @return [void] This method never returns
22
40
  #
23
- # @example String as an argument
24
- # Bundlebun.call('--version') # => `bun --version`
41
+ # @example Basic usage
42
+ # Bundlebun.call('outdated')
43
+ # Bundlebun.call(['add', 'postcss'])
25
44
  #
26
- # @example Array of strings as an argument
27
- # Bundlebun.call(['add', 'postcss']) # => `bun add postcss`
45
+ # @example Using the .() shorthand
46
+ # Bundlebun.('install')
47
+ # Bundlebun.(ARGV)
28
48
  #
49
+ # @see .exec
50
+ # @see .system
29
51
  # @see Bundlebun::Runner.call
30
52
  def call(...)
31
53
  Runner.call(...)
32
54
  end
33
55
 
56
+ # Replaces the current Ruby process with Bun. Same as {.call}.
57
+ #
58
+ # @param arguments [String, Array<String>] Command arguments to pass to Bun
59
+ # @return [void] This method never returns
60
+ #
61
+ # @see .call
62
+ # @see Bundlebun::Runner.exec
63
+ def exec(...)
64
+ Runner.exec(...)
65
+ end
66
+
67
+ # Runs Bun as a subprocess and returns control to Ruby.
68
+ #
69
+ # Unlike {.call} and {.exec}, this method does not replace the current process.
70
+ # Use this when you need to run Bun and then continue executing Ruby code.
71
+ #
72
+ # @param arguments [String, Array<String>] Command arguments to pass to Bun
73
+ # @return [Boolean, nil] `true` if Bun exited successfully (status 0),
74
+ # `false` if it exited with an error, `nil` if execution failed
75
+ #
76
+ # @example Run install and check result
77
+ # if Bundlebun.system('install')
78
+ # puts 'Dependencies installed!'
79
+ # else
80
+ # puts 'Installation failed'
81
+ # end
82
+ #
83
+ # @see .call
84
+ # @see .exec
85
+ # @see Bundlebun::Runner.system
86
+ def system(...)
87
+ Runner.system(...)
88
+ end
89
+
34
90
  def loader # @private
35
91
  @loader ||= Zeitwerk::Loader.for_gem.tap do |loader|
36
92
  loader.ignore("#{__dir__}/tasks")
data/lib/tasks/bun.rake CHANGED
@@ -17,5 +17,5 @@ require 'rake'
17
17
  desc 'Run bundled Bun with parameters. Example: rake "bun[build]"'
18
18
  task :bun, [:command] do |_t, args|
19
19
  command = args[:command] || ''
20
- Bundlebun::Runner.call(command)
20
+ Bundlebun.call(command)
21
21
  end
@@ -26,6 +26,16 @@ namespace :bun do
26
26
  puts "vite-ruby detected.\n\n"
27
27
  Rake::Task['bun:install:vite'].invoke
28
28
  end
29
+
30
+ if File.exist?('package.json')
31
+ puts "package.json detected.\n\n"
32
+ Rake::Task['bun:install:package'].invoke
33
+ end
34
+
35
+ if Dir.glob('Procfile*').any?
36
+ puts "Procfile detected.\n\n"
37
+ Rake::Task['bun:install:procfile'].invoke
38
+ end
29
39
  end
30
40
 
31
41
  desc 'Install bundlebun: create `bin/bun` binstub'
@@ -170,4 +180,126 @@ namespace :bun do
170
180
 
171
181
  MESSAGE
172
182
  end
183
+
184
+ desc 'Migrate package.json scripts to use bin/bun'
185
+ task 'install:package' do
186
+ package_json_path = 'package.json'
187
+
188
+ unless File.exist?(package_json_path)
189
+ puts "No package.json found in the current directory."
190
+ next
191
+ end
192
+
193
+ begin
194
+ package = JSON.parse(File.read(package_json_path))
195
+ rescue JSON::ParserError
196
+ puts "Failed to parse package.json."
197
+ next
198
+ end
199
+
200
+ scripts = package['scripts']
201
+ if scripts.nil? || scripts.empty?
202
+ puts "No scripts found in package.json."
203
+ next
204
+ end
205
+
206
+ # Order in alternation matters: more specific patterns first
207
+ pattern = /\b(bunx|npx|pnpm exec|yarn exec|npm run|yarn run|pnpm run|bun)\b/
208
+ binstub = Bundlebun::Runner.binstub_path
209
+ replacements = {
210
+ 'bunx' => "#{binstub} x",
211
+ 'npx' => "#{binstub} x",
212
+ 'pnpm exec' => "#{binstub} x",
213
+ 'yarn exec' => "#{binstub} x",
214
+ 'npm run' => "#{binstub} run",
215
+ 'yarn run' => "#{binstub} run",
216
+ 'pnpm run' => "#{binstub} run",
217
+ 'bun' => binstub
218
+ }
219
+
220
+ changes = []
221
+ scripts.each do |name, value|
222
+ next unless value.is_a?(String)
223
+ next if value.include?(Bundlebun::Runner::BINSTUB_PATH)
224
+
225
+ new_value = value.gsub(pattern) { |match| replacements[match] }
226
+ changes << {name: name, old: value, new: new_value} if new_value != value
227
+ end
228
+
229
+ if changes.empty?
230
+ puts "All scripts in package.json already use bin/bun. No changes needed."
231
+ next
232
+ end
233
+
234
+ puts "The following changes will be made to package.json scripts:\n\n"
235
+ changes.each do |change|
236
+ puts " #{change[:name]}:"
237
+ puts " - #{change[:old]}"
238
+ puts " + #{change[:new]}"
239
+ puts
240
+ end
241
+
242
+ print "Apply these changes? [Y/n] "
243
+ answer = $stdin.gets&.strip&.downcase
244
+
245
+ if answer.empty? || answer == 'y' || answer == 'yes'
246
+ changes.each do |change|
247
+ package['scripts'][change[:name]] = change[:new]
248
+ end
249
+
250
+ File.write(package_json_path, JSON.pretty_generate(package) + "\n")
251
+ puts "\nUpdated package.json successfully."
252
+ else
253
+ puts "\nNo changes made."
254
+ end
255
+ end
256
+
257
+ desc 'Migrate Procfile commands to use bin/bun'
258
+ task 'install:procfile' do
259
+ procfiles = Dir.glob('Procfile*')
260
+
261
+ if procfiles.empty?
262
+ puts "No Procfile found in the current directory."
263
+ next
264
+ end
265
+
266
+ pattern = /\b(bunx|npx|pnpm exec|yarn exec|npm run|yarn run|pnpm run|bun)\b/
267
+ binstub = Bundlebun::Runner.binstub_path
268
+ replacements = {
269
+ 'bunx' => "#{binstub} x",
270
+ 'npx' => "#{binstub} x",
271
+ 'pnpm exec' => "#{binstub} x",
272
+ 'yarn exec' => "#{binstub} x",
273
+ 'npm run' => "#{binstub} run",
274
+ 'yarn run' => "#{binstub} run",
275
+ 'pnpm run' => "#{binstub} run",
276
+ 'bun' => binstub
277
+ }
278
+
279
+ procfiles.each do |procfile|
280
+ content = File.read(procfile)
281
+ next if content.include?(Bundlebun::Runner::BINSTUB_PATH)
282
+
283
+ new_content = content.gsub(pattern) { |match| replacements[match] }
284
+ next if new_content == content
285
+
286
+ puts "Changes for #{procfile}:\n\n"
287
+ content.lines.zip(new_content.lines).each do |old_line, new_line|
288
+ if old_line != new_line
289
+ puts " - #{old_line}"
290
+ puts " + #{new_line}"
291
+ end
292
+ end
293
+
294
+ print "Apply these changes? [Y/n] "
295
+ answer = $stdin.gets&.strip&.downcase
296
+
297
+ if answer.empty? || answer == 'y' || answer == 'yes'
298
+ File.write(procfile, new_content)
299
+ puts "Updated #{procfile} successfully.\n\n"
300
+ else
301
+ puts "No changes made to #{procfile}.\n\n"
302
+ end
303
+ end
304
+ end
173
305
  end
@@ -0,0 +1,8 @@
1
+ module Bundlebun
2
+ class EnvPath
3
+ def self.path: () -> String?
4
+ def self.path=: (String new_path) -> String
5
+ def self.prepend: (String new_path) -> String?
6
+ def self.separator: () -> String
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ module Bundlebun
2
+ module Integrations
3
+ module Cssbundling
4
+ def self.bun!: () -> void
5
+
6
+ module Tasks
7
+ def install_command: () -> String
8
+ def build_command: () -> String
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Bundlebun
2
+ module Integrations
3
+ module ExecJS
4
+ def self.bun!: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Bundlebun
2
+ module Integrations
3
+ module Jsbundling
4
+ def self.bun!: () -> void
5
+
6
+ module Tasks
7
+ def install_command: () -> String
8
+ def build_command: () -> String
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Bundlebun
2
+ module Integrations
3
+ module ViteRuby
4
+ def self.bun!: () -> void
5
+
6
+ module RunnerExtensions
7
+ def vite_executable: (*untyped exec_args) -> Array[String]
8
+ def bun_binstub_path: () -> String
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module Bundlebun
2
+ module Integrations
3
+ def self.bun!: () -> Array[Module]
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Bundlebun
2
+ class Platform
3
+ def self.windows?: () -> bool
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ module Bundlebun
2
+ class Runner
3
+ BINSTUB_PATH: String
4
+ RELATIVE_DIRECTORY: String
5
+
6
+ # Replaces the current Ruby process with Bun. Never returns.
7
+ def self.exec: (String | Array[String] arguments) -> bot
8
+
9
+ # Replaces the current Ruby process with Bun. Alias for .exec. Never returns.
10
+ def self.call: (String | Array[String] arguments) -> bot
11
+
12
+ # Runs Bun as a subprocess and returns control to Ruby.
13
+ def self.system: (String | Array[String] arguments) -> bool?
14
+
15
+ def self.binstub_path: () -> String
16
+ def self.full_binstub_path: () -> String
17
+ def self.relative_directory: () -> String
18
+ def self.full_directory: () -> String
19
+ def self.binary_path: () -> String
20
+ def self.binary_path_exist?: () -> bool
21
+ def self.binstub_or_binary_path: () -> String
22
+ def self.binstub_exist?: () -> bool
23
+
24
+ def initialize: (?String | Array[String] arguments) -> void
25
+
26
+ # Replaces the current Ruby process with Bun. Never returns.
27
+ def exec: () -> bot
28
+
29
+ # Replaces the current Ruby process with Bun. Alias for #exec. Never returns.
30
+ def call: () -> bot
31
+
32
+ # Runs Bun as a subprocess and returns control to Ruby.
33
+ def system: () -> bool?
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module Bundlebun
2
+ VERSION: String
3
+ end
data/sig/bundlebun.rbs ADDED
@@ -0,0 +1,18 @@
1
+ module Bundlebun
2
+ VERSION: String
3
+
4
+ # Replaces the current Ruby process with Bun.
5
+ # This is the default way to run Bun. Never returns.
6
+ def self.call: (String | Array[String] arguments) -> bot
7
+
8
+ # Replaces the current Ruby process with Bun. Same as .call.
9
+ def self.exec: (String | Array[String] arguments) -> bot
10
+
11
+ # Runs Bun as a subprocess and returns control to Ruby.
12
+ # Returns true if Bun exited successfully, false if it failed, nil if execution failed.
13
+ def self.system: (String | Array[String] arguments) -> bool?
14
+
15
+ def self.prepend_to_path: () -> String?
16
+ def self.load_tasks: () -> void
17
+ def self.load_integrations: () -> Array[Module]
18
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundlebun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3.1.3.7
4
+ version: 0.4.0.1.3.8
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Yaroslav Markin
@@ -13,30 +13,30 @@ dependencies:
13
13
  name: zeitwerk
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - ">="
16
+ - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
18
+ version: '2.5'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
- - - ">="
23
+ - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '0'
25
+ version: '2.5'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: '2.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '0'
39
+ version: '2.0'
40
40
  description: 'bundlebun bundles Bun, a fast JavaScript runtime, package manager, and
41
41
  builder, with your Ruby and Rails applications. No need to use Docker, devcontainers,
42
42
  `curl | sh`, or `brew`.
@@ -71,6 +71,16 @@ files:
71
71
  - lib/templates/bundling-rails/bundlebun.rake
72
72
  - lib/templates/vite-ruby/bun-vite
73
73
  - lib/templates/vite-ruby/vite.json
74
+ - sig/bundlebun.rbs
75
+ - sig/bundlebun/env_path.rbs
76
+ - sig/bundlebun/integrations.rbs
77
+ - sig/bundlebun/integrations/cssbundling.rbs
78
+ - sig/bundlebun/integrations/execjs.rbs
79
+ - sig/bundlebun/integrations/jsbundling.rbs
80
+ - sig/bundlebun/integrations/vite_ruby.rbs
81
+ - sig/bundlebun/platform.rbs
82
+ - sig/bundlebun/runner.rbs
83
+ - sig/bundlebun/version.rbs
74
84
  homepage: https://github.com/yaroslav/bundlebun
75
85
  licenses:
76
86
  - MIT
@@ -80,6 +90,7 @@ metadata:
80
90
  changelog_uri: https://github.com/yaroslav/bundlebun/blob/master/CHANGELOG.md
81
91
  bug_tracker_uri: https://github.com/yaroslav/bundlebun/issues
82
92
  documentation_uri: https://rubydoc.info/gems/bundlebun
93
+ rbs_source: sig
83
94
  post_install_message: Bun.
84
95
  rdoc_options: []
85
96
  require_paths: