homura-runtime 0.3.7 → 0.3.9

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.
@@ -74,8 +74,7 @@ module Cloudflare
74
74
  # don't re-open the handle.
75
75
  def self.open(name)
76
76
  name_str = name.to_s
77
- js_promise =
78
- `(typeof caches !== 'undefined' && caches && caches.open ? caches.open(#{name_str}) : Promise.resolve(null))`
77
+ js_promise = `(typeof caches !== 'undefined' && caches && caches.open ? caches.open(#{name_str}) : Promise.resolve(null))`
79
78
  js_cache = js_promise.__await__
80
79
  Cache.new(js_cache, name_str)
81
80
  end
@@ -113,22 +112,20 @@ module Cloudflare
113
112
  # JS Request. Derive the URL from the same shapes supported by
114
113
  # `request_to_js` so the `url` field on the returned
115
114
  # HTTPResponse is always a real URL.
116
- url_str =
117
- if request_or_url.is_a?(String)
118
- request_or_url
119
- elsif defined?(Cloudflare::HTTPResponse) &&
120
- request_or_url.is_a?(Cloudflare::HTTPResponse)
121
- request_or_url.url.to_s
122
- elsif `(#{request_or_url} != null && typeof #{request_or_url} === 'object' && typeof #{request_or_url}.url === 'string')`
123
- `String(#{request_or_url}.url)`
124
- else
125
- request_or_url.to_s
126
- end
115
+ url_str = if request_or_url.is_a?(String)
116
+ request_or_url
117
+ elsif defined?(Cloudflare::HTTPResponse) &&
118
+ request_or_url.is_a?(Cloudflare::HTTPResponse)
119
+ request_or_url.url.to_s
120
+ elsif `(#{request_or_url} != null && typeof #{request_or_url} === 'object' && typeof #{request_or_url}.url === 'string')`
121
+ `String(#{request_or_url}.url)`
122
+ else
123
+ request_or_url.to_s
124
+ end
127
125
 
128
126
  # Single-line backtick IIFE — see `put` for the Opal multi-line
129
127
  # x-string quirk that silently drops the returned Promise.
130
- js_promise =
131
- `(async function(js, req, Kernel, err_klass) { if (js == null || js === Opal.nil) return null; var cached; try { cached = await js.match(req); } catch (e) { Kernel.$raise(err_klass.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'match' }))); } if (cached == null) return null; var text = ''; try { text = await cached.text(); } catch (_) { text = ''; } var hk = []; var hv = []; if (cached.headers && typeof cached.headers.forEach === 'function') { cached.headers.forEach(function(v, k) { hk.push(String(k).toLowerCase()); hv.push(String(v)); }); } return { status: cached.status|0, text: text, hkeys: hk, hvals: hv }; })(#{js}, #{req}, #{Kernel}, #{err_klass})`
128
+ js_promise = `(async function(js, req, Kernel, err_klass) { if (js == null || js === Opal.nil) return null; var cached; try { cached = await js.match(req); } catch (e) { Kernel.$raise(err_klass.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'match' }))); } if (cached == null) return null; var text = ''; try { text = await cached.text(); } catch (_) { text = ''; } var hk = []; var hv = []; if (cached.headers && typeof cached.headers.forEach === 'function') { cached.headers.forEach(function(v, k) { hk.push(String(k).toLowerCase()); hv.push(String(v)); }); } return { status: cached.status|0, text: text, hkeys: hk, hvals: hv }; })(#{js}, #{req}, #{Kernel}, #{err_klass})`
132
129
  js_result = js_promise.__await__
133
130
  return nil if `#{js_result} == null`
134
131
 
@@ -141,6 +138,7 @@ module Cloudflare
141
138
  h[`#{hkeys}[#{i}]`] = `#{hvals}[#{i}]`
142
139
  i += 1
143
140
  end
141
+
144
142
  response_klass.new(
145
143
  status: `#{js_result}.status`,
146
144
  headers: h,
@@ -212,15 +210,19 @@ module Cloudflare
212
210
  def request_to_js(request_or_url)
213
211
  return `new Request(#{request_or_url})` if request_or_url.is_a?(String)
214
212
  if defined?(Cloudflare::HTTPResponse) &&
215
- request_or_url.is_a?(Cloudflare::HTTPResponse)
213
+ request_or_url.is_a?(Cloudflare::HTTPResponse)
216
214
  url_str = request_or_url.url.to_s
217
215
  return `new Request(#{url_str})`
218
216
  end
217
+
219
218
  if `(#{request_or_url} != null && typeof #{request_or_url} === 'object' && typeof #{request_or_url}.url === 'string')`
220
219
  return request_or_url
221
220
  end
222
- raise ArgumentError,
223
- "Cloudflare::Cache request must be a String URL, Cloudflare::HTTPResponse, or JS Request (got #{request_or_url.class})"
221
+
222
+ raise(
223
+ ArgumentError,
224
+ "Cloudflare::Cache request must be a String URL, Cloudflare::HTTPResponse, or JS Request (got #{request_or_url.class})"
225
+ )
224
226
  end
225
227
 
226
228
  def ruby_headers_to_js(hash)
@@ -230,6 +232,7 @@ module Cloudflare
230
232
  vs = v.to_s
231
233
  `#{js_obj}[#{ks}] = #{vs}`
232
234
  end
235
+
233
236
  js_obj
234
237
  end
235
238
  end
@@ -167,8 +167,7 @@ module Cloudflare
167
167
 
168
168
  # Single-line IIFE — see `lib/homura/runtime/cache.rb#put`
169
169
  # for why Opal can silently drop a multi-line x-string Promise.
170
- js_promise =
171
- `(async function(stub, url_str, method_str, js_headers, js_body, Kernel, err_klass, do_class_label) { var init = { method: method_str, headers: js_headers }; if (js_body !== null && js_body !== undefined && js_body !== Opal.nil) { init.body = js_body; } var resp; try { resp = await stub.fetch(url_str, init); } catch (e) { Kernel.$raise(err_klass.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'stub.fetch', do_class: do_class_label }))); } var text = ''; try { text = await resp.text(); } catch (_) { text = ''; } var hk = []; var hv = []; if (resp.headers && typeof resp.headers.forEach === 'function') { resp.headers.forEach(function(v, k) { hk.push(String(k).toLowerCase()); hv.push(String(v)); }); } return { status: resp.status|0, text: text, hkeys: hk, hvals: hv }; })(#{js_stub}, #{url_str}, #{method_str}, #{js_headers}, #{js_body}, #{Kernel}, #{err_klass}, #{do_class_label})`
170
+ js_promise = `(async function(stub, url_str, method_str, js_headers, js_body, Kernel, err_klass, do_class_label) { var init = { method: method_str, headers: js_headers }; if (js_body !== null && js_body !== undefined && js_body !== Opal.nil) { init.body = js_body; } var resp; try { resp = await stub.fetch(url_str, init); } catch (e) { Kernel.$raise(err_klass.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'stub.fetch', do_class: do_class_label }))); } var text = ''; try { text = await resp.text(); } catch (_) { text = ''; } var hk = []; var hv = []; if (resp.headers && typeof resp.headers.forEach === 'function') { resp.headers.forEach(function(v, k) { hk.push(String(k).toLowerCase()); hv.push(String(v)); }); } return { status: resp.status|0, text: text, hkeys: hk, hvals: hv }; })(#{js_stub}, #{url_str}, #{method_str}, #{js_headers}, #{js_body}, #{Kernel}, #{err_klass}, #{do_class_label})`
172
171
 
173
172
  js_result = js_promise.__await__
174
173
  hkeys = `#{js_result}.hkeys`
@@ -198,6 +197,7 @@ module Cloudflare
198
197
  hdrs["content-type"] = "application/json"
199
198
  end
200
199
  end
200
+
201
201
  fetch(path, method: method, headers: hdrs, body: request_body)
202
202
  end
203
203
 
@@ -258,11 +258,11 @@ module Cloudflare
258
258
  unless class_name.is_a?(String)
259
259
  raise ArgumentError, "class_name must be a String"
260
260
  end
261
+
261
262
  @handlers ||= {}
262
263
  # Wrap via define_method so Opal's `# await: true` picks it up as
263
264
  # async (same trick Sinatra::Scheduled uses for its jobs).
264
- method_name =
265
- "__do_handler_#{class_name.gsub(/[^A-Za-z0-9_]/, "_")}".to_sym
265
+ method_name = "__do_handler_#{class_name.gsub(/[^A-Za-z0-9_]/, "_")}".to_sym
266
266
  DurableObjectRequestContext.send(:define_method, method_name, &block)
267
267
  unbound = DurableObjectRequestContext.instance_method(method_name)
268
268
  DurableObjectRequestContext.send(:remove_method, method_name)
@@ -317,9 +317,7 @@ module Cloudflare
317
317
  body = {
318
318
  "error" => "no Ruby handler for DurableObject class #{class_name}"
319
319
  }.to_json
320
- return(
321
- build_js_response(500, { "content-type" => "application/json" }, body)
322
- )
320
+ return (build_js_response(500, {"content-type" => "application/json"}, body))
323
321
  end
324
322
 
325
323
  state = DurableObjectState.new(js_state)
@@ -354,7 +352,7 @@ module Cloudflare
354
352
  (result["body"] || result[:body] || "").to_s
355
353
  ]
356
354
  else
357
- [200, { "content-type" => "text/plain; charset=utf-8" }, result.to_s]
355
+ [200, {"content-type" => "text/plain; charset=utf-8"}, result.to_s]
358
356
  end
359
357
  end
360
358
 
@@ -365,6 +363,7 @@ module Cloudflare
365
363
  vs = v.to_s
366
364
  `#{js_headers}[#{ks}] = #{vs}`
367
365
  end
366
+
368
367
  status_int = status.to_i
369
368
  body_str = body.to_s
370
369
  `new Response(#{body_str}, { status: #{status_int}, headers: #{js_headers} })`
@@ -475,10 +474,12 @@ module Cloudflare
475
474
  ts = t.to_s
476
475
  `#{js_tags}.push(#{ts})`
477
476
  end
477
+
478
478
  `#{js_state}.acceptWebSocket(#{js_ws}, #{js_tags})`
479
479
  else
480
480
  `#{js_state}.acceptWebSocket(#{js_ws})`
481
481
  end
482
+
482
483
  nil
483
484
  end
484
485
 
@@ -487,13 +488,13 @@ module Cloudflare
487
488
  # `getWebSockets(tag)`.
488
489
  def web_sockets(tag: nil)
489
490
  js_state = @js_state
490
- js_arr =
491
- if tag
492
- ts = tag.to_s
493
- `(#{js_state}.getWebSockets ? #{js_state}.getWebSockets(#{ts}) : [])`
494
- else
495
- `(#{js_state}.getWebSockets ? #{js_state}.getWebSockets() : [])`
496
- end
491
+ js_arr = if tag
492
+ ts = tag.to_s
493
+ `(#{js_state}.getWebSockets ? #{js_state}.getWebSockets(#{ts}) : [])`
494
+ else
495
+ `(#{js_state}.getWebSockets ? #{js_state}.getWebSockets() : [])`
496
+ end
497
+
497
498
  out = []
498
499
  len = `#{js_arr}.length`
499
500
  i = 0
@@ -501,6 +502,7 @@ module Cloudflare
501
502
  out << `#{js_arr}[#{i}]`
502
503
  i += 1
503
504
  end
505
+
504
506
  out
505
507
  end
506
508
  end
@@ -567,8 +569,7 @@ module Cloudflare
567
569
  `#{js_opts}.reverse = #{!!reverse}` unless reverse.nil?
568
570
  `#{js_opts}.start = #{start.to_s}` unless start.nil?
569
571
  `#{js_opts}.end = #{end_key.to_s}` unless end_key.nil?
570
- js_promise =
571
- `#{js}.list(#{js_opts}).catch(function(e) { #{Kernel}.$raise(#{err_klass}.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'storage.list' }))); })`
572
+ js_promise = `#{js}.list(#{js_opts}).catch(function(e) { #{Kernel}.$raise(#{err_klass}.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'storage.list' }))); })`
572
573
  js_result = js_promise.__await__
573
574
  out = {}
574
575
  return out if `#{js_result} == null`
@@ -646,9 +647,11 @@ module Cloudflare
646
647
  def storage
647
648
  @state.storage
648
649
  end
650
+
649
651
  def cf_env
650
652
  env["cloudflare.env"]
651
653
  end
654
+
652
655
  def cf_ctx
653
656
  env["cloudflare.ctx"]
654
657
  end
@@ -656,24 +659,31 @@ module Cloudflare
656
659
  def d1
657
660
  env["cloudflare.DB"]
658
661
  end
662
+
659
663
  def db
660
664
  d1
661
665
  end
666
+
662
667
  def kv
663
668
  env["cloudflare.KV"]
664
669
  end
670
+
665
671
  def bucket
666
672
  env["cloudflare.BUCKET"]
667
673
  end
674
+
668
675
  def ai
669
676
  Cloudflare::Bindings.ai(env)
670
677
  end
678
+
671
679
  def send_email
672
680
  env["cloudflare.SEND_EMAIL"]
673
681
  end
682
+
674
683
  def jobs_queue
675
684
  env["cloudflare.QUEUE_JOBS"]
676
685
  end
686
+
677
687
  def durable_object(name, id_or_name = nil)
678
688
  Cloudflare::Bindings.durable_object(env, name, id_or_name)
679
689
  end
@@ -52,20 +52,18 @@ module Cloudflare
52
52
  has_html = !(html.nil? || html.to_s.empty?)
53
53
  raise Error, "text or html is required" unless has_text || has_html
54
54
 
55
- payload =
56
- build_send_payload(
57
- to: to,
58
- from: from,
59
- subject: subject.to_s,
60
- text: text,
61
- html: html,
62
- reply_to: reply_to
63
- )
55
+ payload = build_send_payload(
56
+ to: to,
57
+ from: from,
58
+ subject: subject.to_s,
59
+ text: text,
60
+ html: html,
61
+ reply_to: reply_to
62
+ )
64
63
 
65
64
  cf = Cloudflare
66
65
  # 多行 x-string をメソッド末尾に置くと Opal が Promise を返さない出力になることがあるため return を明示する。
67
- return(
68
- `(async function(binding, payload, Kernel, Err, cf) {
66
+ return (`(async function(binding, payload, Kernel, Err, cf) {
69
67
  try {
70
68
  var r = await binding.send(payload);
71
69
  if (r == null || r === undefined) {
@@ -83,8 +81,7 @@ module Cloudflare
83
81
  var msg = (e && e.message) ? String(e.message) : String(e);
84
82
  Kernel.$raise(Err.$new(msg, Opal.hash({ code: code })));
85
83
  }
86
- })(#{js}, #{payload}, #{Kernel}, #{err_klass}, #{cf})`
87
- )
84
+ })(#{js}, #{payload}, #{Kernel}, #{err_klass}, #{cf})`)
88
85
  end
89
86
 
90
87
  private
@@ -128,9 +125,11 @@ module Cloudflare
128
125
  if e[:name] && !e[:name].to_s.strip.empty?
129
126
  `#{js}.name = #{e[:name].to_s}`
130
127
  end
128
+
131
129
  `#{arr}.push(#{js})`
132
130
  end
133
131
  end
132
+
134
133
  arr
135
134
  end
136
135
 
@@ -149,8 +148,9 @@ module Cloudflare
149
148
  if nm.nil? || nm.to_s.strip.empty?
150
149
  [em.to_s.strip]
151
150
  else
152
- [{ email: em.to_s.strip, name: nm.to_s }]
151
+ [{email: em.to_s.strip, name: nm.to_s}]
153
152
  end
153
+
154
154
  when Array
155
155
  raw.flat_map { |x| flatten_recipients(x) }
156
156
  else
@@ -76,7 +76,8 @@ module Cloudflare
76
76
  response_klass = Cloudflare::HTTPResponse
77
77
  err_klass = Cloudflare::HTTPError
78
78
  headers_to_hash = method(:js_headers_to_hash)
79
- _ = headers_to_hash # silence opal lint
79
+ # silence opal lint
80
+ _ = headers_to_hash
80
81
 
81
82
  # NOTE: the multi-line backtick below returns a Promise BECAUSE it
82
83
  # is assigned to `js_promise` (and `js_promise.__await__` awaits
@@ -87,8 +88,7 @@ module Cloudflare
87
88
  # expression. See the single-line IIFE pattern used in
88
89
  # lib/homura/runtime/{cache,queue,durable_object}.rb#put for
89
90
  # the alternative that survives either position. (Phase 11B audit.)
90
- js_promise =
91
- `
91
+ js_promise = `
92
92
  (async function() {
93
93
  var init = { method: #{method_str}, headers: #{js_headers}, redirect: 'follow' };
94
94
  if (#{js_body} !== nil && #{js_body} != null) { init.body = #{js_body}; }
@@ -144,6 +144,7 @@ module Cloudflare
144
144
  vs = v.to_s
145
145
  `#{js_obj}[#{ks}] = #{vs}`
146
146
  end
147
+
147
148
  js_obj
148
149
  end
149
150
 
@@ -56,6 +56,7 @@ module Cloudflare
56
56
  def size
57
57
  @bytes_binstr.length
58
58
  end
59
+
59
60
  alias_method :bytesize, :size
60
61
 
61
62
  # Convenience accessor matching the CRuby Rack shape.
@@ -106,6 +107,7 @@ module Cloudflare
106
107
  tempfile: self
107
108
  }
108
109
  end
110
+
109
111
  alias_method :to_hash, :to_h
110
112
 
111
113
  # `#[]` so `file[:filename]` works on the UploadedFile itself
@@ -133,9 +135,11 @@ module Cloudflare
133
135
  if (m = ct.match(/boundary="([^"]+)"/i))
134
136
  return m[1]
135
137
  end
138
+
136
139
  if (m = ct.match(/boundary=([^;,\s]+)/i))
137
140
  return m[1]
138
141
  end
142
+
139
143
  nil
140
144
  end
141
145
 
@@ -154,7 +158,8 @@ module Cloudflare
154
158
  sep = "--" + boundary
155
159
  term = "--" + boundary + "--"
156
160
  sep_line = sep + CRLF
157
- sep_last = sep + CRLF # the very first boundary may skip the leading CRLF
161
+ # the very first boundary may skip the leading CRLF
162
+ sep_last = sep + CRLF
158
163
  body = body_binstr.to_s
159
164
 
160
165
  # Skip any preamble before the first boundary.
@@ -251,13 +256,14 @@ module Cloudflare
251
256
  # Quoted `key="value"`
252
257
  q_re = /(?:^|[;\s])#{k}\s*=\s*"((?:\\"|[^"])*)"/i
253
258
  if (m = disposition.match(q_re))
254
- return m[1].gsub('\\"', '"')
259
+ return m[1].gsub("\\\"", "\"")
255
260
  end
256
261
  # Bare `key=value`
257
262
  b_re = /(?:^|[;\s])#{k}\s*=\s*([^;]+)/i
258
263
  if (m = disposition.match(b_re))
259
264
  return m[1].strip
260
265
  end
266
+
261
267
  nil
262
268
  end
263
269
 
@@ -276,10 +282,10 @@ module Cloudflare
276
282
  return cached if cached
277
283
 
278
284
  ct = env["CONTENT_TYPE"]
279
- return({}) unless ct && ct.to_s.downcase.include?("multipart/")
285
+ return ({}) unless ct && ct.to_s.downcase.include?("multipart/")
280
286
 
281
287
  io = env["rack.input"]
282
- return({}) if io.nil?
288
+ return ({}) if io.nil?
283
289
 
284
290
  # `rack.input` is normally a StringIO wrapping the body_binstr
285
291
  # we staged in src/worker.mjs. Read the full body; it's already
@@ -292,6 +298,7 @@ module Cloudflare
292
298
  # some stubs don't support rewind — ignore
293
299
  end
294
300
  end
301
+
295
302
  body = io.respond_to?(:read) ? io.read.to_s : ""
296
303
 
297
304
  parsed = parse(body, ct)
@@ -82,11 +82,13 @@ module Cloudflare
82
82
  qname = @name
83
83
  err_klass = Cloudflare::QueueError
84
84
  unless available?
85
- raise QueueError.new(
86
- "queue binding not bound",
87
- operation: "send",
88
- queue: qname
89
- )
85
+ raise(
86
+ QueueError.new(
87
+ "queue binding not bound",
88
+ operation: "send",
89
+ queue: qname
90
+ )
91
+ )
90
92
  end
91
93
 
92
94
  js_body = ruby_to_js(body)
@@ -108,11 +110,13 @@ module Cloudflare
108
110
  qname = @name
109
111
  err_klass = Cloudflare::QueueError
110
112
  unless available?
111
- raise QueueError.new(
112
- "queue binding not bound",
113
- operation: "send_batch",
114
- queue: qname
115
- )
113
+ raise(
114
+ QueueError.new(
115
+ "queue binding not bound",
116
+ operation: "send_batch",
117
+ queue: qname
118
+ )
119
+ )
116
120
  end
117
121
 
118
122
  js_msgs = `([])`
@@ -131,6 +135,7 @@ module Cloudflare
131
135
  `#{js_msgs}.push({ body: #{js_body} })`
132
136
  end
133
137
  end
138
+
134
139
  js_opts = `({})`
135
140
  `#{js_opts}.delaySeconds = #{delay_seconds.to_i}` if delay_seconds
136
141
 
@@ -143,10 +148,14 @@ module Cloudflare
143
148
  # Same Ruby→JS conversion that Cloudflare::AI.ruby_to_js uses, but
144
149
  # local to avoid cross-wrapper coupling.
145
150
  def ruby_to_js(val)
146
- if val.is_a?(String) || val.is_a?(Numeric) || val == true ||
147
- val == false || val.nil?
151
+ if val.is_a?(String) ||
152
+ val.is_a?(Numeric) ||
153
+ val == true ||
154
+ val == false ||
155
+ val.nil?
148
156
  return val
149
157
  end
158
+
150
159
  return val.to_s if val.is_a?(Symbol)
151
160
  if val.is_a?(Hash)
152
161
  obj = `({})`
@@ -155,16 +164,20 @@ module Cloudflare
155
164
  jv = ruby_to_js(v)
156
165
  `#{obj}[#{ks}] = #{jv}`
157
166
  end
167
+
158
168
  return obj
159
169
  end
170
+
160
171
  if val.is_a?(Array)
161
172
  arr = `([])`
162
173
  val.each do |v|
163
174
  jv = ruby_to_js(v)
164
175
  `#{arr}.push(#{jv})`
165
176
  end
177
+
166
178
  return arr
167
179
  end
180
+
168
181
  val
169
182
  end
170
183
  end
@@ -185,8 +198,7 @@ module Cloudflare
185
198
 
186
199
  def timestamp
187
200
  js = @js
188
- ms =
189
- `(#{js} && #{js}.timestamp && typeof #{js}.timestamp.getTime === 'function' ? #{js}.timestamp.getTime() : null)`
201
+ ms = `(#{js} && #{js}.timestamp && typeof #{js}.timestamp.getTime === 'function' ? #{js}.timestamp.getTime() : null)`
190
202
  return nil if `#{ms} == null`
191
203
  Time.at(ms.to_f / 1000.0)
192
204
  end
@@ -234,6 +246,7 @@ module Cloudflare
234
246
  else
235
247
  `(#{js} && typeof #{js}.retry === 'function' ? #{js}.retry() : null)`
236
248
  end
249
+
237
250
  nil
238
251
  end
239
252
 
@@ -244,6 +257,7 @@ module Cloudflare
244
257
  if `typeof #{v} === 'string' || typeof #{v} === 'number' || typeof #{v} === 'boolean'`
245
258
  return v
246
259
  end
260
+
247
261
  if `Array.isArray(#{v})`
248
262
  out = []
249
263
  len = `#{v}.length`
@@ -252,8 +266,10 @@ module Cloudflare
252
266
  out << js_to_ruby(`#{v}[#{i}]`)
253
267
  i += 1
254
268
  end
269
+
255
270
  return out
256
271
  end
272
+
257
273
  if `typeof #{v} === 'object'`
258
274
  h = {}
259
275
  keys = `Object.keys(#{v})`
@@ -264,8 +280,10 @@ module Cloudflare
264
280
  h[k] = js_to_ruby(`#{v}[#{k}]`)
265
281
  i += 1
266
282
  end
283
+
267
284
  return h
268
285
  end
286
+
269
287
  v
270
288
  end
271
289
  end
@@ -296,6 +314,7 @@ module Cloudflare
296
314
  out << QueueMessage.new(`#{arr}[#{i}]`)
297
315
  i += 1
298
316
  end
317
+
299
318
  @messages = out
300
319
  end
301
320
 
@@ -317,6 +336,7 @@ module Cloudflare
317
336
  else
318
337
  `(#{js} && typeof #{js}.retryAll === 'function' ? #{js}.retryAll() : null)`
319
338
  end
339
+
320
340
  nil
321
341
  end
322
342
  end
@@ -353,15 +373,15 @@ module Cloudflare
353
373
  queue_name = batch.queue
354
374
  handler = handler_for(queue_name)
355
375
  if handler.nil?
356
- warn "[Cloudflare::QueueConsumer] no handler registered for queue #{queue_name.inspect}; messages will time out and retry"
357
- return(
358
- {
359
- "queue" => queue_name,
360
- "handled" => false,
361
- "size" => batch.size,
362
- "reason" => "no_handler"
363
- }
376
+ warn(
377
+ "[Cloudflare::QueueConsumer] no handler registered for queue #{queue_name.inspect}; messages will time out and retry"
364
378
  )
379
+ return ({
380
+ "queue" => queue_name,
381
+ "handled" => false,
382
+ "size" => batch.size,
383
+ "reason" => "no_handler"
384
+ })
365
385
  end
366
386
 
367
387
  ctx = QueueContext.new(batch, js_env, js_ctx)
@@ -369,6 +389,7 @@ module Cloudflare
369
389
  if `(#{result} != null && typeof #{result}.then === 'function')`
370
390
  result = result.__await__
371
391
  end
392
+
372
393
  {
373
394
  "queue" => queue_name,
374
395
  "handled" => true,
@@ -403,30 +424,39 @@ module Cloudflare
403
424
  def d1
404
425
  env["cloudflare.DB"]
405
426
  end
427
+
406
428
  def db
407
429
  d1
408
430
  end
431
+
409
432
  def cf_env
410
433
  env["cloudflare.env"]
411
434
  end
435
+
412
436
  def cf_ctx
413
437
  env["cloudflare.ctx"]
414
438
  end
439
+
415
440
  def kv
416
441
  env["cloudflare.KV"]
417
442
  end
443
+
418
444
  def bucket
419
445
  env["cloudflare.BUCKET"]
420
446
  end
447
+
421
448
  def ai
422
449
  Cloudflare::Bindings.ai(env)
423
450
  end
451
+
424
452
  def send_email
425
453
  env["cloudflare.SEND_EMAIL"]
426
454
  end
455
+
427
456
  def jobs_queue
428
457
  env["cloudflare.QUEUE_JOBS"]
429
458
  end
459
+
430
460
  def durable_object(name, id_or_name = nil)
431
461
  Cloudflare::Bindings.durable_object(env, name, id_or_name)
432
462
  end
@@ -446,7 +476,7 @@ module Cloudflare
446
476
  Cloudflare::Bindings.build_env(
447
477
  js_env,
448
478
  @js_ctx,
449
- { "cloudflare.queue" => true }
479
+ {"cloudflare.queue" => true}
450
480
  )
451
481
  end
452
482
  end
@@ -63,16 +63,14 @@ module Cloudflare
63
63
  return new(cron: "", scheduled_time: Time.now) if `#{js_event} == null`
64
64
 
65
65
  cron = `(#{js_event}.cron == null ? '' : String(#{js_event}.cron))`
66
- type =
67
- `(#{js_event}.type == null ? 'scheduled' : String(#{js_event}.type))`
66
+ type = `(#{js_event}.type == null ? 'scheduled' : String(#{js_event}.type))`
68
67
  has_sched = `(#{js_event}.scheduledTime != null)`
69
- sched_t =
70
- if has_sched
71
- sched_ms = `Number(#{js_event}.scheduledTime)`
72
- Time.at(sched_ms.to_f / 1000.0)
73
- else
74
- Time.now
75
- end
68
+ sched_t = if has_sched
69
+ sched_ms = `Number(#{js_event}.scheduledTime)`
70
+ Time.at(sched_ms.to_f / 1000.0)
71
+ else
72
+ Time.now
73
+ end
76
74
 
77
75
  new(cron: cron, scheduled_time: sched_t, type: type, raw: js_event)
78
76
  end
@@ -121,11 +119,10 @@ module Cloudflare
121
119
  event = ScheduledEvent.from_js(js_event)
122
120
  target = resolve_app
123
121
  if target.nil?
124
- warn "[Cloudflare::Scheduled] no app registered; ignoring scheduled event"
125
- return(
126
- { "fired" => 0, "total" => 0, "results" => [], "error" => "no_app" }
127
- )
122
+ warn("[Cloudflare::Scheduled] no app registered; ignoring scheduled event")
123
+ return ({"fired" => 0, "total" => 0, "results" => [], "error" => "no_app"})
128
124
  end
125
+
129
126
  target.dispatch_scheduled(event, js_env, js_ctx).__await__
130
127
  end
131
128
 
@@ -171,6 +168,7 @@ module Cloudflare
171
168
  if candidate.nil? && defined?(::Rack::Handler::Homura)
172
169
  candidate = ::Rack::Handler::Homura.app
173
170
  end
171
+
174
172
  return nil if candidate.nil?
175
173
  # Sinatra app classes respond to `dispatch_scheduled` (added by
176
174
  # Sinatra::Scheduled). Plain Rack apps would be instances and
@@ -180,7 +178,7 @@ module Cloudflare
180
178
  if candidate.respond_to?(:dispatch_scheduled)
181
179
  candidate
182
180
  elsif candidate.respond_to?(:class) &&
183
- candidate.class.respond_to?(:dispatch_scheduled)
181
+ candidate.class.respond_to?(:dispatch_scheduled)
184
182
  candidate.class
185
183
  else
186
184
  candidate