homura-runtime 0.2.5 → 0.2.7
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 +26 -5
- data/exe/compile-assets +0 -4
- data/{bin/cloudflare-workers-build → exe/homura-build} +41 -8
- data/lib/cloudflare_workers/auto_await/analyzer.rb +19 -3
- data/lib/cloudflare_workers/build_support.rb +1 -1
- data/lib/cloudflare_workers/version.rb +1 -1
- data/lib/cloudflare_workers.rb +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b1a1cd099709c81d7dfba2a41d071ab47f343c253f5826a031107011903706c9
|
|
4
|
+
data.tar.gz: 54dcad51d26b66db5da83a6245ee3402418bd1af891cee59627b61f0c7760fc7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17be34147d20fe3c90c5bf50b5e1aa3fc0f0fa659e519659243566b3828bf7ffae88b1d129589ff34916b7406a650d1aed652500de4f5ba6e0400c5e00e5aae9
|
|
7
|
+
data.tar.gz: e5a79b2eff5c805f2b06c83843dd99a1614d99defab71d1be52a8634046b1eb97f51f2e07f80ab8b41543e3b0b559c88d483bc70a00e429fafbc8b4ec9daf41d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.7 (2026-04-24)
|
|
4
|
+
|
|
5
|
+
- Auto-detect standalone app entrypoints from `config.ru`, `app/hello.rb`, then
|
|
6
|
+
`app/app.rb`, and accept `config.ru` inputs by compiling a temporary Ruby copy
|
|
7
|
+
under the hood.
|
|
8
|
+
- Add the project root to standalone Opal load paths so standard
|
|
9
|
+
`require_relative 'app/app'` config.ru setups compile without extra wrappers.
|
|
10
|
+
- Synthesize `HTTP_HOST` from the request URL inside the Rack env so absolute
|
|
11
|
+
redirects preserve the current host and non-default port in local dev.
|
|
12
|
+
|
|
13
|
+
## 0.2.6 (2026-04-24)
|
|
14
|
+
|
|
15
|
+
- Remove the shipped `cloudflare-workers-build` filename entirely and keep the
|
|
16
|
+
build implementation under `exe/homura-build`, matching the `homura build`
|
|
17
|
+
public surface.
|
|
18
|
+
- Make `homura build --with-db` imply the consumer-safe standalone path so D1 /
|
|
19
|
+
Sequel apps do not need to remember both flags.
|
|
20
|
+
- Let `compile-assets` succeed for an empty `public/` directory and improve the
|
|
21
|
+
auto-await analyzer so async local helper methods are awaited at their call
|
|
22
|
+
sites.
|
|
23
|
+
|
|
3
24
|
## 0.2.5 (2026-04-23)
|
|
4
25
|
|
|
5
26
|
- Load Workers-only `zlib`, `tempfile`, and `tilt` shims via `require_relative`
|
|
@@ -27,14 +48,14 @@
|
|
|
27
48
|
|
|
28
49
|
## 0.2.0 (2026-04-23)
|
|
29
50
|
|
|
30
|
-
- Remove the old
|
|
51
|
+
- Remove the old standalone build executable and expose the
|
|
31
52
|
build pipeline through `homura build`.
|
|
32
53
|
- Keep the internal build implementation in the runtime gem while letting the
|
|
33
54
|
single `homura` CLI dispatch to it.
|
|
34
55
|
|
|
35
56
|
## 0.1.6 (2026-04-23)
|
|
36
57
|
|
|
37
|
-
- Teach `
|
|
58
|
+
- Teach `homura build --standalone --with-db` to add the packaged
|
|
38
59
|
`sequel-d1` gem `vendor/` directory to the Opal load path before the gem's
|
|
39
60
|
`lib/`, so `require 'sequel'` resolves to the bundled Opal-compatible Sequel
|
|
40
61
|
subset instead of the CRuby gem.
|
|
@@ -43,7 +64,7 @@
|
|
|
43
64
|
|
|
44
65
|
- Make `auto-await` emit rewritten files for existing hand-written `.__await__`
|
|
45
66
|
usage when the only missing piece is `# await: true`.
|
|
46
|
-
- Make `
|
|
67
|
+
- Make `homura build --standalone` restore `cf-runtime/` from the
|
|
47
68
|
packaged gem and derive standalone template/asset namespaces from the project
|
|
48
69
|
name by default, with explicit override flags when needed.
|
|
49
70
|
- Reject unsupported ERB yield forms like `<% yield %>` and `yield(arg)` with
|
|
@@ -68,12 +89,12 @@
|
|
|
68
89
|
|
|
69
90
|
- Package the runtime's Opal compile-time vendor shims (`digest`, `zlib`,
|
|
70
91
|
`tempfile`, `tilt`, `rubygems/version`) inside the gem.
|
|
71
|
-
- Teach `
|
|
92
|
+
- Teach `homura build --standalone` to add packaged gem `vendor/`
|
|
72
93
|
directories to the Opal load path, so published gems no longer depend on the
|
|
73
94
|
monorepo root `vendor/`.
|
|
74
95
|
## 0.1.1 (2026-04-23)
|
|
75
96
|
|
|
76
|
-
- Fix `
|
|
97
|
+
- Fix `homura build --standalone` and `exe/auto-await` to resolve only
|
|
77
98
|
the published gem names `homura-runtime` / `sinatra-homura`.
|
|
78
99
|
- Add regression coverage for gem name resolution and Gemfile path detection.
|
|
79
100
|
|
data/exe/compile-assets
CHANGED
|
@@ -82,10 +82,6 @@ end
|
|
|
82
82
|
ns = options[:namespace]
|
|
83
83
|
|
|
84
84
|
files = Dir.glob(File.join(public_dir, '**', '*')).select { |f| File.file?(f) }.sort
|
|
85
|
-
if files.empty?
|
|
86
|
-
warn 'compile-assets: directory is empty'
|
|
87
|
-
exit 1
|
|
88
|
-
end
|
|
89
85
|
|
|
90
86
|
out_path = options[:output]
|
|
91
87
|
FileUtils.mkdir_p(File.dirname(out_path))
|
|
@@ -37,7 +37,7 @@ end
|
|
|
37
37
|
options = {
|
|
38
38
|
root: Dir.pwd,
|
|
39
39
|
standalone: false,
|
|
40
|
-
opal_input: ENV['HOMURA_OPAL_INPUT']
|
|
40
|
+
opal_input: ENV['HOMURA_OPAL_INPUT'],
|
|
41
41
|
opal_output: ENV['HOMURA_OPAL_OUTPUT'] || 'build/hello.no-exit.mjs',
|
|
42
42
|
patch_input: ENV['HOMURA_OPAL_PATCH_INPUT'],
|
|
43
43
|
setup_import: nil,
|
|
@@ -69,6 +69,8 @@ OptionParser.new do |o|
|
|
|
69
69
|
o.on('--assets-namespace NAME', 'Standalone assets module name (default: project-derived)') { |n| options[:assets_namespace] = n }
|
|
70
70
|
end.parse!
|
|
71
71
|
|
|
72
|
+
options[:standalone] = true if options[:with_db]
|
|
73
|
+
|
|
72
74
|
root = Pathname(options[:root]).expand_path
|
|
73
75
|
options[:templates_namespace] ||= CloudflareWorkers::BuildSupport.standalone_namespace(root, 'Templates') if options[:standalone]
|
|
74
76
|
options[:assets_namespace] ||= CloudflareWorkers::BuildSupport.standalone_namespace(root, 'Assets') if options[:standalone]
|
|
@@ -98,6 +100,7 @@ def run_opal_homura!(root, opal_input, opal_output)
|
|
|
98
100
|
argv = [
|
|
99
101
|
'bundle', 'exec', 'opal',
|
|
100
102
|
'-c', '-E', '--esm', '--no-source-map',
|
|
103
|
+
'-I', '.',
|
|
101
104
|
'-I', 'build/auto_await/app', '-I', 'build/auto_await', '-I', 'app',
|
|
102
105
|
'-I', 'gems/homura-runtime/lib',
|
|
103
106
|
'-I', 'gems/sinatra-homura/lib',
|
|
@@ -113,7 +116,7 @@ def run_opal_homura!(root, opal_input, opal_output)
|
|
|
113
116
|
env = { 'OPAL_PREFORK_DISABLE' => '1' }
|
|
114
117
|
out_err, status = Open3.capture2e(env, *argv, chdir: root.to_s)
|
|
115
118
|
File.write(stderr_log, out_err)
|
|
116
|
-
abort(
|
|
119
|
+
abort("homura build: opal failed (see #{stderr_log})") unless status.success?
|
|
117
120
|
end
|
|
118
121
|
|
|
119
122
|
def homura_vendor_from_gemfile(project_root)
|
|
@@ -132,7 +135,7 @@ def run_opal_standalone!(root, opal_input, opal_output, with_db:)
|
|
|
132
135
|
env = { 'OPAL_PREFORK_DISABLE' => '1' }
|
|
133
136
|
out_err, status = Open3.capture2e(env, *argv, chdir: root.to_s)
|
|
134
137
|
File.write(stderr_log, out_err)
|
|
135
|
-
abort(
|
|
138
|
+
abort("homura build: opal failed (see #{stderr_log})") unless status.success?
|
|
136
139
|
end
|
|
137
140
|
|
|
138
141
|
def write_entrypoint!(root, out_path, setup:, bundle:, worker_mod:)
|
|
@@ -145,6 +148,26 @@ def write_entrypoint!(root, out_path, setup:, bundle:, worker_mod:)
|
|
|
145
148
|
File.write(root.join(out_path), body)
|
|
146
149
|
end
|
|
147
150
|
|
|
151
|
+
def resolve_opal_input(root, explicit_input)
|
|
152
|
+
return explicit_input if explicit_input
|
|
153
|
+
|
|
154
|
+
candidates = ['config.ru', 'app/hello.rb', 'app/app.rb']
|
|
155
|
+
found = candidates.find { |path| root.join(path).file? }
|
|
156
|
+
return found if found
|
|
157
|
+
|
|
158
|
+
abort("homura build: no default entrypoint found (looked for #{candidates.join(', ')})")
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def prepare_opal_input(root, input_path)
|
|
162
|
+
rel = Pathname(input_path)
|
|
163
|
+
rel = root.join(rel).relative_path_from(root) if rel.absolute?
|
|
164
|
+
return [rel.to_s, nil] unless rel.extname == '.ru'
|
|
165
|
+
|
|
166
|
+
tmp = root.join(".homura-build-#{rel.basename}.rb")
|
|
167
|
+
File.write(tmp, root.join(rel).read)
|
|
168
|
+
[tmp.relative_path_from(root).to_s, tmp]
|
|
169
|
+
end
|
|
170
|
+
|
|
148
171
|
unless options[:standalone]
|
|
149
172
|
run!(['ruby', 'bin/inline-routes-for-opal'], chdir: root)
|
|
150
173
|
run!(
|
|
@@ -182,11 +205,16 @@ unless options[:standalone]
|
|
|
182
205
|
chdir: root
|
|
183
206
|
)
|
|
184
207
|
|
|
185
|
-
opal_in = Pathname(options[:opal_input])
|
|
208
|
+
opal_in = Pathname(resolve_opal_input(root, options[:opal_input]))
|
|
186
209
|
opal_out = Pathname(options[:opal_output])
|
|
187
210
|
opal_in = root.join(opal_in) unless opal_in.absolute?
|
|
188
211
|
opal_out = root.join(opal_out) unless opal_out.absolute?
|
|
189
|
-
|
|
212
|
+
prepared_in, temp_input = prepare_opal_input(root, opal_in)
|
|
213
|
+
begin
|
|
214
|
+
run_opal_homura!(root, prepared_in, opal_out.relative_path_from(root).to_s)
|
|
215
|
+
ensure
|
|
216
|
+
FileUtils.rm_f(temp_input) if temp_input
|
|
217
|
+
end
|
|
190
218
|
else
|
|
191
219
|
CloudflareWorkers::BuildSupport.ensure_standalone_runtime(root, current_file: __FILE__)
|
|
192
220
|
run!(
|
|
@@ -216,12 +244,17 @@ else
|
|
|
216
244
|
chdir: root
|
|
217
245
|
)
|
|
218
246
|
|
|
219
|
-
opal_in = Pathname(options[:opal_input])
|
|
247
|
+
opal_in = Pathname(resolve_opal_input(root, options[:opal_input]))
|
|
220
248
|
opal_out = Pathname(options[:opal_output])
|
|
221
249
|
opal_in = root.join(opal_in) unless opal_in.absolute?
|
|
222
250
|
opal_out = root.join(opal_out) unless opal_out.absolute?
|
|
223
|
-
|
|
224
|
-
|
|
251
|
+
prepared_in, temp_input = prepare_opal_input(root, opal_in)
|
|
252
|
+
begin
|
|
253
|
+
run_opal_standalone!(root, prepared_in, opal_out.relative_path_from(root).to_s,
|
|
254
|
+
with_db: options[:with_db])
|
|
255
|
+
ensure
|
|
256
|
+
FileUtils.rm_f(temp_input) if temp_input
|
|
257
|
+
end
|
|
225
258
|
end
|
|
226
259
|
|
|
227
260
|
patch_rel = Pathname(patch_target)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'parser/current'
|
|
4
4
|
require 'parser/source/tree_rewriter'
|
|
5
|
+
require 'set'
|
|
5
6
|
|
|
6
7
|
module CloudflareWorkers
|
|
7
8
|
module AutoAwait
|
|
@@ -12,6 +13,7 @@ module CloudflareWorkers
|
|
|
12
13
|
@await_nodes = []
|
|
13
14
|
@env = {}
|
|
14
15
|
@method_returns = {}
|
|
16
|
+
@async_local_methods = Set.new
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def process(source, filename = '(auto-await)')
|
|
@@ -19,14 +21,22 @@ module CloudflareWorkers
|
|
|
19
21
|
buffer.source = source
|
|
20
22
|
parser = Parser::CurrentRuby.new
|
|
21
23
|
ast = parser.parse(buffer)
|
|
22
|
-
@
|
|
23
|
-
@
|
|
24
|
-
|
|
24
|
+
@method_returns = {}
|
|
25
|
+
@async_local_methods = Set.new
|
|
26
|
+
|
|
27
|
+
analyze_pass(ast)
|
|
28
|
+
analyze_pass(ast)
|
|
25
29
|
[buffer, @await_nodes]
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
private
|
|
29
33
|
|
|
34
|
+
def analyze_pass(ast)
|
|
35
|
+
@await_nodes = []
|
|
36
|
+
@env = {}
|
|
37
|
+
process_node(ast)
|
|
38
|
+
end
|
|
39
|
+
|
|
30
40
|
def process_node(node)
|
|
31
41
|
return unless node.is_a?(Parser::AST::Node)
|
|
32
42
|
|
|
@@ -72,6 +82,7 @@ module CloudflareWorkers
|
|
|
72
82
|
def process_def(node)
|
|
73
83
|
method_name = node.children[0]
|
|
74
84
|
saved_env = @env
|
|
85
|
+
before_awaits = @await_nodes.length
|
|
75
86
|
@env = @registry.helper_factories.dup
|
|
76
87
|
|
|
77
88
|
node.children[1..-1].each { |child| process_node(child) if child.is_a?(Parser::AST::Node) }
|
|
@@ -79,6 +90,10 @@ module CloudflareWorkers
|
|
|
79
90
|
body = node.children[2]
|
|
80
91
|
return_cls = infer_class(body)
|
|
81
92
|
@method_returns[method_name] = return_cls if return_cls
|
|
93
|
+
body_source = node.loc.expression&.source.to_s
|
|
94
|
+
if @await_nodes.length > before_awaits || body_source.include?('.__await__')
|
|
95
|
+
@async_local_methods << method_name
|
|
96
|
+
end
|
|
82
97
|
|
|
83
98
|
@env = saved_env
|
|
84
99
|
end
|
|
@@ -119,6 +134,7 @@ module CloudflareWorkers
|
|
|
119
134
|
# Receiver-less calls (implicit self) — check helpers.
|
|
120
135
|
helpers = @registry.async_helpers[method_name]
|
|
121
136
|
return true if helpers && !helpers.empty?
|
|
137
|
+
return true if @async_local_methods.include?(method_name)
|
|
122
138
|
false
|
|
123
139
|
end
|
|
124
140
|
|
|
@@ -61,7 +61,7 @@ module CloudflareWorkers
|
|
|
61
61
|
hv = vendor_from_gemfile(root)
|
|
62
62
|
load_paths << hv.to_s if hv
|
|
63
63
|
|
|
64
|
-
load_paths += ['build/auto_await/app', 'app']
|
|
64
|
+
load_paths += ['.', 'build/auto_await/app', 'app']
|
|
65
65
|
[
|
|
66
66
|
gem_lib(RUNTIME_GEM_NAME, loaded_specs: loaded_specs),
|
|
67
67
|
gem_vendor(RUNTIME_GEM_NAME, loaded_specs: loaded_specs),
|
data/lib/cloudflare_workers.rb
CHANGED
|
@@ -204,6 +204,11 @@ module Rack
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
copy_headers_into_env(js_req, env)
|
|
207
|
+
env['HTTP_HOST'] = if port == (scheme == 'https' ? '443' : '80')
|
|
208
|
+
host
|
|
209
|
+
else
|
|
210
|
+
"#{host}:#{port}"
|
|
211
|
+
end
|
|
207
212
|
|
|
208
213
|
# Cloudflare-specific extras under their own namespace, per the
|
|
209
214
|
# Rack convention that env keys other than the standard ones
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: homura-runtime
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kazuhiro Homma
|
|
@@ -48,11 +48,11 @@ extra_rdoc_files: []
|
|
|
48
48
|
files:
|
|
49
49
|
- CHANGELOG.md
|
|
50
50
|
- README.md
|
|
51
|
-
- bin/cloudflare-workers-build
|
|
52
51
|
- docs/ARCHITECTURE.md
|
|
53
52
|
- exe/auto-await
|
|
54
53
|
- exe/compile-assets
|
|
55
54
|
- exe/compile-erb
|
|
55
|
+
- exe/homura-build
|
|
56
56
|
- lib/cloudflare_workers.rb
|
|
57
57
|
- lib/cloudflare_workers/ai.rb
|
|
58
58
|
- lib/cloudflare_workers/async_registry.rb
|