homura-runtime 0.1.1 → 0.1.2
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 +8 -0
- data/bin/cloudflare-workers-build +16 -5
- data/lib/cloudflare_workers/build_support.rb +14 -3
- data/lib/cloudflare_workers/version.rb +1 -1
- data/vendor/cgi/escape.rb +4 -0
- data/vendor/digest/sha2.rb +5 -0
- data/vendor/digest.rb +93 -0
- data/vendor/rubygems/version.rb +35 -0
- data/vendor/tempfile.rb +34 -0
- data/vendor/tilt.rb +75 -0
- data/vendor/zlib.rb +41 -0
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 99d546ac1db58f957cf5bd81723cfc0e15019f11c27c8b0bcd78fc2ee833b751
|
|
4
|
+
data.tar.gz: 02b08e0580b05b710cfba5d5bc6255ba463a4675a297476583dcacece6b158b6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 864e05461b1321d1094bdf27ae5bd971472194df29a440ff24f946449db7b98ec93c14ea53a25956ec1e9254b6e1e9015ac2d25978d8f1aadab02f91c69f287a
|
|
7
|
+
data.tar.gz: 20c08fdaad6cef869cb4256ffed49be996a3bd6a0e3dd9038bb05f4240a27e75791fefe9bdae1c8dc3f73622413ea95ed90c166dd4810c19cfdf709db6a185f2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2 (2026-04-23)
|
|
4
|
+
|
|
5
|
+
- Package the runtime's Opal compile-time vendor shims (`digest`, `zlib`,
|
|
6
|
+
`tempfile`, `tilt`, `rubygems/version`) inside the gem.
|
|
7
|
+
- Teach `cloudflare-workers-build --standalone` to add packaged gem `vendor/`
|
|
8
|
+
directories to the Opal load path, so published gems no longer depend on the
|
|
9
|
+
monorepo root `vendor/`.
|
|
10
|
+
|
|
3
11
|
## 0.1.1 (2026-04-23)
|
|
4
12
|
|
|
5
13
|
- Fix `cloudflare-workers-build --standalone` and `exe/auto-await` to resolve only
|
|
@@ -27,6 +27,10 @@ module CloudflareWorkersBuild
|
|
|
27
27
|
def gem_lib(*names)
|
|
28
28
|
CloudflareWorkers::BuildSupport.gem_lib(*names)
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
def gem_vendor(*names)
|
|
32
|
+
CloudflareWorkers::BuildSupport.gem_vendor(*names)
|
|
33
|
+
end
|
|
30
34
|
end
|
|
31
35
|
end
|
|
32
36
|
|
|
@@ -114,11 +118,18 @@ def run_opal_standalone!(root, opal_input, opal_output, with_db:)
|
|
|
114
118
|
load_paths = []
|
|
115
119
|
hv = homura_vendor_from_gemfile(root)
|
|
116
120
|
load_paths << hv.to_s if hv
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
runtime_name = CloudflareWorkers::BuildSupport::RUNTIME_GEM_NAME
|
|
122
|
+
sinatra_name = CloudflareWorkers::BuildSupport::SINATRA_GEM_NAME
|
|
123
|
+
|
|
124
|
+
load_paths += ['build/auto_await/app', 'app']
|
|
125
|
+
[
|
|
126
|
+
CloudflareWorkersBuild.gem_lib(runtime_name),
|
|
127
|
+
CloudflareWorkersBuild.gem_vendor(runtime_name),
|
|
128
|
+
CloudflareWorkersBuild.gem_lib(sinatra_name),
|
|
129
|
+
CloudflareWorkersBuild.gem_vendor(sinatra_name)
|
|
130
|
+
].compact.each do |path|
|
|
131
|
+
load_paths << path
|
|
132
|
+
end
|
|
122
133
|
load_paths << CloudflareWorkersBuild.gem_lib('sequel-d1') if with_db
|
|
123
134
|
load_paths << 'vendor' if root.join('vendor').directory?
|
|
124
135
|
load_paths << 'build'
|
|
@@ -12,6 +12,13 @@ module CloudflareWorkers
|
|
|
12
12
|
loaded_specs[name]
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
def gem_root(name, loaded_specs: Gem.loaded_specs)
|
|
16
|
+
spec = loaded_spec(name, loaded_specs: loaded_specs)
|
|
17
|
+
return spec.full_gem_path if spec
|
|
18
|
+
|
|
19
|
+
raise("cloudflare-workers-build: gem #{name} not loaded; use bundle exec from app root")
|
|
20
|
+
end
|
|
21
|
+
|
|
15
22
|
def runtime_root(current_file:, loaded_specs: Gem.loaded_specs)
|
|
16
23
|
spec = loaded_spec(RUNTIME_GEM_NAME, loaded_specs: loaded_specs)
|
|
17
24
|
return Pathname(spec.full_gem_path) if spec
|
|
@@ -20,10 +27,14 @@ module CloudflareWorkers
|
|
|
20
27
|
end
|
|
21
28
|
|
|
22
29
|
def gem_lib(name, loaded_specs: Gem.loaded_specs)
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
File.join(gem_root(name, loaded_specs: loaded_specs), 'lib')
|
|
31
|
+
end
|
|
25
32
|
|
|
26
|
-
|
|
33
|
+
def gem_vendor(name, loaded_specs: Gem.loaded_specs)
|
|
34
|
+
vendor = File.join(gem_root(name, loaded_specs: loaded_specs), 'vendor')
|
|
35
|
+
return vendor if Dir.exist?(vendor)
|
|
36
|
+
|
|
37
|
+
nil
|
|
27
38
|
end
|
|
28
39
|
|
|
29
40
|
def vendor_from_gemfile(project_root)
|
data/vendor/digest.rb
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# backtick_javascript: true
|
|
3
|
+
|
|
4
|
+
require 'corelib/array/pack'
|
|
5
|
+
require 'corelib/string/unpack'
|
|
6
|
+
#
|
|
7
|
+
# Phase 7 — Real Digest implementation backed by node:crypto.
|
|
8
|
+
#
|
|
9
|
+
# Replaces the Phase 2 NotImplementedError stub. All hash algos are
|
|
10
|
+
# synchronous (no Promise glue), enabled by importing node:crypto via
|
|
11
|
+
# src/setup-node-crypto.mjs and exposing it on globalThis.
|
|
12
|
+
#
|
|
13
|
+
# Available on:
|
|
14
|
+
# - Cloudflare Workers (with `compatibility_flags = ["nodejs_compat"]`)
|
|
15
|
+
# - Node.js (with `node --import ./src/setup-node-crypto.mjs`)
|
|
16
|
+
#
|
|
17
|
+
# Surface mirrors CRuby's `digest/sha1`, `digest/sha2`, `digest/md5`:
|
|
18
|
+
#
|
|
19
|
+
# Digest::SHA256.hexdigest(str) # one-shot hex
|
|
20
|
+
# Digest::SHA256.digest(str) # one-shot binary
|
|
21
|
+
# Digest::SHA256.new.update(s).hexdigest # streaming
|
|
22
|
+
|
|
23
|
+
module Digest
|
|
24
|
+
# Common base class shared by SHA1 / SHA256 / SHA384 / SHA512 / MD5.
|
|
25
|
+
# Subclasses define ALGO (the node:crypto algorithm name).
|
|
26
|
+
class Base
|
|
27
|
+
def initialize
|
|
28
|
+
reset
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reset
|
|
32
|
+
@hasher = `globalThis.__nodeCrypto__.createHash(#{self.class::ALGO})`
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update(data)
|
|
37
|
+
str = data.to_s
|
|
38
|
+
`#{@hasher}.update(#{str}, 'utf8')`
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
alias_method :<<, :update
|
|
42
|
+
|
|
43
|
+
def hexdigest
|
|
44
|
+
hasher = @hasher
|
|
45
|
+
`#{hasher}.copy().digest('hex')`
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def digest
|
|
49
|
+
hex = hexdigest
|
|
50
|
+
[hex].pack('H*')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def base64digest
|
|
54
|
+
hasher = @hasher
|
|
55
|
+
`#{hasher}.copy().digest('base64')`
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_s
|
|
59
|
+
hexdigest
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.hexdigest(data)
|
|
63
|
+
algo = self::ALGO
|
|
64
|
+
str = data.to_s
|
|
65
|
+
`globalThis.__nodeCrypto__.createHash(#{algo}).update(#{str}, 'utf8').digest('hex')`
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.digest(data)
|
|
69
|
+
hex = hexdigest(data)
|
|
70
|
+
[hex].pack('H*')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.base64digest(data)
|
|
74
|
+
algo = self::ALGO
|
|
75
|
+
str = data.to_s
|
|
76
|
+
`globalThis.__nodeCrypto__.createHash(#{algo}).update(#{str}, 'utf8').digest('base64')`
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Disk-backed digest is impossible on Workers (no FS).
|
|
80
|
+
def self.file(*)
|
|
81
|
+
raise NotImplementedError, 'Digest.file is unavailable on Cloudflare Workers (no filesystem)'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Backwards-compat alias for code that does `class Foo < Digest::Class`.
|
|
86
|
+
Class = Base unless const_defined?(:Class)
|
|
87
|
+
|
|
88
|
+
class SHA1 < Base; ALGO = 'sha1'.freeze; end
|
|
89
|
+
class SHA256 < Base; ALGO = 'sha256'.freeze; end
|
|
90
|
+
class SHA384 < Base; ALGO = 'sha384'.freeze; end
|
|
91
|
+
class SHA512 < Base; ALGO = 'sha512'.freeze; end
|
|
92
|
+
class MD5 < Base; ALGO = 'md5'.freeze; end
|
|
93
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# homura Opal stub for Gem::Version.
|
|
4
|
+
#
|
|
5
|
+
# Upstream Sinatra 4.x uses `Gem::Version.new(RUBY_VERSION) >=
|
|
6
|
+
# Gem::Version.new("3.0")` to conditionally activate the `except`
|
|
7
|
+
# override on IndifferentHash. Opal does not bundle RubyGems, so we
|
|
8
|
+
# provide a tiny comparator that parses dotted versions as Integer
|
|
9
|
+
# arrays (sufficient for the Sinatra use-case).
|
|
10
|
+
|
|
11
|
+
module Gem
|
|
12
|
+
class Version
|
|
13
|
+
include Comparable
|
|
14
|
+
|
|
15
|
+
attr_reader :parts
|
|
16
|
+
|
|
17
|
+
def initialize(str)
|
|
18
|
+
@parts = str.to_s.split('.').map { |s| s.to_i rescue 0 }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def <=>(other)
|
|
22
|
+
return nil unless other.is_a?(Version)
|
|
23
|
+
i = 0
|
|
24
|
+
max = [parts.size, other.parts.size].max
|
|
25
|
+
while i < max
|
|
26
|
+
a = parts[i] || 0
|
|
27
|
+
b = other.parts[i] || 0
|
|
28
|
+
cmp = a <=> b
|
|
29
|
+
return cmp unless cmp == 0
|
|
30
|
+
i += 1
|
|
31
|
+
end
|
|
32
|
+
0
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/vendor/tempfile.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Minimal Tempfile stub for homura Phase 2.
|
|
2
|
+
# Cloudflare Workers do not have a writable filesystem so a real Tempfile
|
|
3
|
+
# implementation is impossible. Rack only references Tempfile for
|
|
4
|
+
# multipart upload buffering, which is not exercised by the hello-world
|
|
5
|
+
# handler. This stub allows `require 'tempfile'` to succeed; calling the
|
|
6
|
+
# class will raise an explicit error.
|
|
7
|
+
|
|
8
|
+
require 'stringio'
|
|
9
|
+
|
|
10
|
+
class Tempfile < StringIO
|
|
11
|
+
def initialize(*)
|
|
12
|
+
super('')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.open(*)
|
|
16
|
+
raise NotImplementedError, 'Tempfile is stubbed in homura Phase 2 (Workers have no writable FS)'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def path
|
|
20
|
+
raise NotImplementedError, 'Tempfile#path stubbed (no FS)'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def unlink
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def delete
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def close!
|
|
32
|
+
close
|
|
33
|
+
end
|
|
34
|
+
end
|
data/vendor/tilt.rb
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Minimal Tilt stub for the homura Phase 2 hello-world handler.
|
|
2
|
+
#
|
|
3
|
+
# Real Sinatra requires the actual `tilt` gem for template rendering
|
|
4
|
+
# (ERB, Haml, etc.). janbiedermann does not maintain a tilt fork because
|
|
5
|
+
# Tilt's internals (binding manipulation, file IO) are difficult to run
|
|
6
|
+
# under Opal as-is.
|
|
7
|
+
#
|
|
8
|
+
# For Phase 2 we do not render any templates — `get '/' do; "hello"; end`
|
|
9
|
+
# returns a String directly and never reaches Tilt. So we provide just
|
|
10
|
+
# enough of the Tilt surface area for `require 'tilt'` to succeed and
|
|
11
|
+
# for Sinatra::Base to load. If a request actually tries to render a
|
|
12
|
+
# template, it will raise an explicit NotImplementedError so the gap is
|
|
13
|
+
# obvious and we can grow this stub deliberately in a later phase.
|
|
14
|
+
|
|
15
|
+
module Tilt
|
|
16
|
+
class TemplateNotFound < StandardError; end
|
|
17
|
+
|
|
18
|
+
class Cache
|
|
19
|
+
def initialize
|
|
20
|
+
@cache = {}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def fetch(*key)
|
|
24
|
+
@cache[key] ||= yield
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def clear
|
|
28
|
+
@cache.clear
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Mapping
|
|
33
|
+
def initialize
|
|
34
|
+
@extensions = {}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def register(template_class, *extensions)
|
|
38
|
+
extensions.each { |ext| @extensions[ext.to_s] = template_class }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def [](name)
|
|
42
|
+
@extensions[name.to_s]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def extensions_for(engine_or_class)
|
|
46
|
+
@extensions.each_with_object([]) do |(ext, klass), out|
|
|
47
|
+
out << ext if klass == engine_or_class
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def template_for(name)
|
|
52
|
+
@extensions[name.to_s]
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class << self
|
|
57
|
+
def default_mapping
|
|
58
|
+
@default_mapping ||= Mapping.new
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def [](name)
|
|
62
|
+
default_mapping[name]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def register(template_class, *extensions)
|
|
66
|
+
default_mapping.register(template_class, *extensions)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def new(file = nil, line = nil, options = {}, &block)
|
|
70
|
+
raise NotImplementedError,
|
|
71
|
+
'Tilt template rendering is not available in homura Phase 2 ' \
|
|
72
|
+
'(stubbed). Return Strings or arrays from your Sinatra handlers.'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/vendor/zlib.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Minimal Zlib stub for the homura Phase 2 hello-world handler.
|
|
2
|
+
# Opal stdlib does not ship a zlib module. Real homura apps that need
|
|
3
|
+
# response compression should rely on the Cloudflare edge to gzip
|
|
4
|
+
# responses on the way out. This stub only exists so that
|
|
5
|
+
# `require 'zlib'` (transitively pulled in by rack/deflater) does not
|
|
6
|
+
# fail at compile time. None of the methods below are reachable from
|
|
7
|
+
# the Phase 2 hello-world path.
|
|
8
|
+
|
|
9
|
+
module Zlib
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
class GzipFile
|
|
12
|
+
class Error < Zlib::Error; end
|
|
13
|
+
class CRCError < Error; end
|
|
14
|
+
class LengthError < Error; end
|
|
15
|
+
class NoFooter < Error; end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class GzipReader < GzipFile
|
|
19
|
+
def self.wrap(*); raise NotImplementedError, 'Zlib stubbed'; end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class GzipWriter < GzipFile
|
|
23
|
+
def self.wrap(*); raise NotImplementedError, 'Zlib stubbed'; end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Deflate
|
|
27
|
+
def self.deflate(*); raise NotImplementedError, 'Zlib stubbed'; end
|
|
28
|
+
def initialize(*); end
|
|
29
|
+
def deflate(*); raise NotImplementedError, 'Zlib stubbed'; end
|
|
30
|
+
def finish; raise NotImplementedError, 'Zlib stubbed'; end
|
|
31
|
+
def close; end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Inflate
|
|
35
|
+
def self.inflate(*); raise NotImplementedError, 'Zlib stubbed'; end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
DEFAULT_COMPRESSION = -1
|
|
39
|
+
BEST_SPEED = 1
|
|
40
|
+
BEST_COMPRESSION = 9
|
|
41
|
+
end
|
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.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kazuhiro NISHIYAMA
|
|
@@ -76,6 +76,13 @@ files:
|
|
|
76
76
|
- runtime/worker_module.mjs
|
|
77
77
|
- runtime/wrangler.toml.example
|
|
78
78
|
- templates/wrangler.toml.example
|
|
79
|
+
- vendor/cgi/escape.rb
|
|
80
|
+
- vendor/digest.rb
|
|
81
|
+
- vendor/digest/sha2.rb
|
|
82
|
+
- vendor/rubygems/version.rb
|
|
83
|
+
- vendor/tempfile.rb
|
|
84
|
+
- vendor/tilt.rb
|
|
85
|
+
- vendor/zlib.rb
|
|
79
86
|
homepage: https://github.com/kazuph/homura
|
|
80
87
|
licenses:
|
|
81
88
|
- MIT
|