homura-runtime 0.2.24 → 0.2.26
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 +28 -0
- data/exe/homura-build +8 -7
- data/lib/cloudflare_workers/build_support.rb +37 -11
- data/lib/cloudflare_workers/version.rb +1 -1
- data/lib/cloudflare_workers.rb +35 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 961609130fd819224d263b877755bd615b98c27ec2677bb3842aaeeed13a131b
|
|
4
|
+
data.tar.gz: 4412446fe4defcfb5e65cbafc19f53c2bbdb7461a5e835a2a7fa7a09bf6da38e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 36b7a90afec547e760a751bf2dcfe1a3ef5a9718d64f31d00d740f9715291a5ce869c9845d3fe7d8b5aa6f99f9787254d77d4197a20fc0095106dcc6bc6959a1
|
|
7
|
+
data.tar.gz: fa08804d6bfcc39032f75889de9066105c46ceccecb7c91a9b2126bffe8db05af8ccf3dfaf02d6da9795cae82dbc987a55a61e86cf676a1aff8a06a3de342ef8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.26 (2026-04-29)
|
|
4
|
+
|
|
5
|
+
- `Rack::Handler::CloudflareWorkers#call`: when `@app` is nil, fall
|
|
6
|
+
back to `Sinatra::CloudflareWorkers.ensure_rack_app!` to discover
|
|
7
|
+
the Sinatra app lazily on the first fetch. This is what lets
|
|
8
|
+
classic-style apps omit the trailing `run Sinatra::Application`
|
|
9
|
+
line (paired with `sinatra-homura >= 0.2.23`).
|
|
10
|
+
- New `Rack::Handler::CloudflareWorkers.ensure_dispatcher_installed!`:
|
|
11
|
+
eagerly registers the JS-side dispatcher (`globalThis.__HOMURA_RACK_DISPATCH__`)
|
|
12
|
+
at script-load time, so a fetch arriving before `run` was called
|
|
13
|
+
still routes into our `call` method (where the lazy app discovery
|
|
14
|
+
above kicks in). On Workers `at_exit` is unreliable because the
|
|
15
|
+
isolate doesn't exit between requests; this eager install is the
|
|
16
|
+
reliable hook.
|
|
17
|
+
|
|
18
|
+
## 0.2.25 (2026-04-29)
|
|
19
|
+
|
|
20
|
+
- `BuildSupport`: factor `opal_gem_paths` out of the path:-only
|
|
21
|
+
`path_gemfile_entries`. The new method also picks up
|
|
22
|
+
RubyGems-installed gems that opt in via
|
|
23
|
+
`spec.metadata['homura.auto_await'] = 'true'`. Without this, a
|
|
24
|
+
RubyGems-installed pure-Ruby gem (e.g. `sinatra-inertia >= 0.1.1`)
|
|
25
|
+
was missing from both the Opal load path and the auto-await pass,
|
|
26
|
+
so `require 'sinatra/inertia'` failed during `homura build`.
|
|
27
|
+
- `homura-build` iterates `opal_gem_paths` instead of the old
|
|
28
|
+
path:-only list, so any opted-in gem (path: or RubyGems) gets the
|
|
29
|
+
same auto-await rewrite.
|
|
30
|
+
|
|
3
31
|
## 0.2.24 (2026-04-29)
|
|
4
32
|
|
|
5
33
|
- `BuildSupport.standalone_load_paths`: auto-discover `path:`-resolved
|
data/exe/homura-build
CHANGED
|
@@ -275,13 +275,14 @@ else
|
|
|
275
275
|
warn 'homura build: no app/ directory or top-level app.rb — skipping auto-await'
|
|
276
276
|
end
|
|
277
277
|
|
|
278
|
-
# Also run auto-await over
|
|
279
|
-
# consumer
|
|
280
|
-
#
|
|
281
|
-
#
|
|
282
|
-
#
|
|
283
|
-
#
|
|
284
|
-
|
|
278
|
+
# Also run auto-await over every gem we ship to Opal:
|
|
279
|
+
# `path:`-resolved gems in the consumer Gemfile *and* RubyGems-
|
|
280
|
+
# installed gems that opt in via
|
|
281
|
+
# `spec.metadata['homura.auto_await'] = 'true'`. Both go to
|
|
282
|
+
# `build/auto_await/gem_<basename>/<sub>` and
|
|
283
|
+
# `standalone_load_paths` puts those rewritten copies ahead of the
|
|
284
|
+
# gem's untransformed `lib/`.
|
|
285
|
+
CloudflareWorkers::BuildSupport.opal_gem_paths(root).each do |gem_path|
|
|
285
286
|
%w[lib].each do |sub|
|
|
286
287
|
src = gem_path.join(sub)
|
|
287
288
|
next unless src.directory?
|
|
@@ -86,18 +86,19 @@ module CloudflareWorkers
|
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
# Pick up any other
|
|
90
|
-
# Gemfile (e.g. `sinatra-inertia`). This keeps the build pipeline
|
|
91
|
-
# extensible: users can drop a pure-Ruby gem under `gems/foo`, list
|
|
92
|
-
# it as `gem 'foo', path: '../../gems/foo'`, and Opal will find its
|
|
93
|
-
# `lib/` automatically — no homura-runtime change required.
|
|
89
|
+
# Pick up any other gems that should ship in the Workers bundle:
|
|
94
90
|
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
|
|
91
|
+
# * `path:`-resolved gems in the consumer's Gemfile (monorepo
|
|
92
|
+
# dev mode), and
|
|
93
|
+
# * RubyGems-installed gems that opt in via
|
|
94
|
+
# `spec.metadata['homura.auto_await'] = 'true'`.
|
|
95
|
+
#
|
|
96
|
+
# Both go through the same auto-await pass during `homura-build`,
|
|
97
|
+
# and we prefer the rewritten copy under
|
|
98
|
+
# `build/auto_await/gem_<basename>/lib` if present so async chains
|
|
99
|
+
# inside gem code get `__await__` inserted just like consumer
|
|
100
|
+
# app code.
|
|
101
|
+
opal_gem_paths(root, loaded_specs: loaded_specs).each do |gem_path|
|
|
101
102
|
basename = gem_path.basename.to_s
|
|
102
103
|
rewritten_lib = root.join('build', 'auto_await', "gem_#{basename}", 'lib')
|
|
103
104
|
load_paths << rewritten_lib.to_s if rewritten_lib.directory?
|
|
@@ -133,6 +134,31 @@ module CloudflareWorkers
|
|
|
133
134
|
vend if vend.directory?
|
|
134
135
|
end
|
|
135
136
|
|
|
137
|
+
# Returns the union of `path_gemfile_entries(project_root)` and any
|
|
138
|
+
# bundled gems that opt in to the Opal pipeline via
|
|
139
|
+
# `spec.metadata['homura.auto_await']`. This is the single source
|
|
140
|
+
# of truth for both `standalone_load_paths` and the auto-await pass
|
|
141
|
+
# that `homura-build` runs. Returns `Pathname` objects pointing at
|
|
142
|
+
# each gem's root directory.
|
|
143
|
+
def opal_gem_paths(project_root, loaded_specs: Gem.loaded_specs)
|
|
144
|
+
wired = [RUNTIME_GEM_NAME, SINATRA_GEM_NAME, SEQUEL_D1_GEM_NAME]
|
|
145
|
+
out = []
|
|
146
|
+
out.concat(path_gemfile_entries(project_root))
|
|
147
|
+
|
|
148
|
+
loaded_specs.each_value do |spec|
|
|
149
|
+
next if wired.include?(spec.name)
|
|
150
|
+
meta = spec.metadata
|
|
151
|
+
next unless meta.is_a?(Hash)
|
|
152
|
+
flag = meta['homura.auto_await']
|
|
153
|
+
next unless flag == 'true' || flag == true
|
|
154
|
+
next if spec.full_gem_path.nil?
|
|
155
|
+
gem_path = Pathname(spec.full_gem_path)
|
|
156
|
+
out << gem_path if gem_path.directory?
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
out.uniq
|
|
160
|
+
end
|
|
161
|
+
|
|
136
162
|
# Returns absolute Pathnames for every `path:`-declared gem in the
|
|
137
163
|
# project's Gemfile that should ship in the Workers bundle.
|
|
138
164
|
#
|
data/lib/cloudflare_workers.rb
CHANGED
|
@@ -134,6 +134,34 @@ module Rack
|
|
|
134
134
|
@app
|
|
135
135
|
end
|
|
136
136
|
|
|
137
|
+
def self.app=(app)
|
|
138
|
+
@app = app
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Eagerly install the JS-side dispatcher so a fetch arriving
|
|
142
|
+
# before `run` was called (e.g. classic-style apps that omit the
|
|
143
|
+
# trailing `run Sinatra::Application`) still gets routed into our
|
|
144
|
+
# `call` method, which can then discover the user's Sinatra app
|
|
145
|
+
# lazily via `Sinatra::CloudflareWorkers.ensure_rack_app!`. This
|
|
146
|
+
# is what makes the canonical sinatrarb.com snippet work
|
|
147
|
+
# verbatim on Workers — `at_exit` is unreliable here because the
|
|
148
|
+
# isolate never actually exits between fetches.
|
|
149
|
+
def self.ensure_dispatcher_installed!
|
|
150
|
+
return true if @dispatcher_installed
|
|
151
|
+
handler = self
|
|
152
|
+
`
|
|
153
|
+
globalThis.__HOMURA_RACK_DISPATCH__ = async function(req, env, ctx, body_text) {
|
|
154
|
+
return await #{handler}.$call(req, env, ctx, body_text == null ? "" : body_text);
|
|
155
|
+
};
|
|
156
|
+
(function () {
|
|
157
|
+
var g = globalThis;
|
|
158
|
+
g.__OPAL_WORKERS__ = g.__OPAL_WORKERS__ || {};
|
|
159
|
+
g.__OPAL_WORKERS__.rack = g.__HOMURA_RACK_DISPATCH__;
|
|
160
|
+
})();
|
|
161
|
+
`
|
|
162
|
+
@dispatcher_installed = true
|
|
163
|
+
end
|
|
164
|
+
|
|
137
165
|
# Entry point invoked from the Module Worker (src/worker.mjs) for
|
|
138
166
|
# every fetch event. `js_req` is a Cloudflare Workers Request,
|
|
139
167
|
# `js_env` is the bindings object (D1, KV, R2, secrets...),
|
|
@@ -141,7 +169,13 @@ module Rack
|
|
|
141
169
|
# request body (the worker.mjs front awaits req.text() before
|
|
142
170
|
# handing control to Ruby because Opal runs synchronously).
|
|
143
171
|
def self.call(js_req, js_env, js_ctx, body_text = '')
|
|
144
|
-
|
|
172
|
+
if @app.nil?
|
|
173
|
+
if defined?(::Sinatra::CloudflareWorkers) &&
|
|
174
|
+
::Sinatra::CloudflareWorkers.respond_to?(:ensure_rack_app!)
|
|
175
|
+
::Sinatra::CloudflareWorkers.ensure_rack_app!
|
|
176
|
+
end
|
|
177
|
+
raise '`run app` was never called from user code, and no Sinatra app was discoverable (define `class App < Sinatra::Base` or use top-level classic Sinatra routes)' if @app.nil?
|
|
178
|
+
end
|
|
145
179
|
|
|
146
180
|
env = build_rack_env(js_req, js_env, js_ctx, body_text)
|
|
147
181
|
result = @app.call(env)
|