wasmify-rails 0.3.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f126390207e5e9030c599cffebf5e9cd14b701e960acaf3a81c0e868f20cef2
4
- data.tar.gz: aa1e772419cedf0b6dc3f786103a43b99aa4d6faea0c32df1e029a4b102ad0df
3
+ metadata.gz: 6da25bdd1a3e205a57b7081ada2a29997e4cf5df306423695564aba47591efb3
4
+ data.tar.gz: d7e72fc5aed555d506086f267cba686560357c3a478015b891d15e9b613cb26f
5
5
  SHA512:
6
- metadata.gz: 651e0e83708072e63098bf1199456866a0bb1f2256c1815101cb0028adf6742ad3ea1feee52e65f272a85eacb1f5f839c8c46340e1c67b34500a6e0a08f503e6
7
- data.tar.gz: a9d623bf6faed1db405f6daba055a69ab2d2ea4178fc2926901f51be875537a133c0b966f95e63e89f555086ef950d08a7fe996543e6b84f418daa0b39957b17
6
+ metadata.gz: 650516f17e4f8fc0a02f5b6515d23634f8ac47dd14d5faecb0bd932d74994b7a1b9127a50143b46dd97d1d1c6f5b3e7fbba1146306cc9f099dcb44542945c643
7
+ data.tar.gz: ac1d4ef0047666f1e7e52e935f3c78dcb596c4c064b7bd7f5ace46ccc8eef56f555f7db4e90d52da50b469f64587a8e4766a47f31e7caed0e3976c35b9573cec
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.3.2
6
+
7
+ - Add `Rack::WASI::IncomingHandler` mimicking `wasi/http:proxy` interface.
8
+
9
+ ## 0.3.1
10
+
11
+ - Use latest patch versions for Ruby 3.3 and 3.4.
12
+
5
13
  ## 0.3.0
6
14
 
7
15
  - Add `ignore_gem_extensions` configuration option.
@@ -325,7 +325,7 @@ class ActiveRecord::ConnectionAdapters::NullDBAdapter < ActiveRecord::Connection
325
325
 
326
326
  def new_table_definition(adapter = nil, table_name = nil, is_temporary = nil, options = {})
327
327
  case ::ActiveRecord::VERSION::MAJOR
328
- when 6, 7
328
+ when 6, 7, 8
329
329
  TableDefinition.new(self, table_name, temporary: is_temporary, options: options.except(:id))
330
330
  when 5
331
331
  TableDefinition.new(table_name, is_temporary, options.except(:id), nil)
@@ -52,6 +52,8 @@ module ActiveRecord
52
52
 
53
53
  def busy_timeout(...) = nil
54
54
 
55
+ def busy_handler_timeout=(...) = nil
56
+
55
57
  def execute(sql)
56
58
  @last_statement = Statement.new(self, sql)
57
59
  @last_statement.result
@@ -19,7 +19,9 @@ module Rack
19
19
 
20
20
  request = Rack::Request.new(env)
21
21
 
22
- if request.post? || request.put? || request.patch?
22
+ if (
23
+ request.post? || request.put? || request.patch?
24
+ ) && request.get_header("HTTP_CONTENT_TYPE").match?(%r{multipart/form-data})
23
25
  transform_params(request.params)
24
26
  env["action_dispatch.request.request_parameters"] = request.params
25
27
  end
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "uri"
5
+ require "base64"
6
+ require "rack"
7
+ require "rack/test"
8
+
9
+ require "rack/data_uri_uploads"
10
+
11
+ module Rack
12
+ module WASI
13
+ class Result < Data.define(:value, :error)
14
+ def tag = error ? "error" : "ok"
15
+ end
16
+
17
+ # resource incoming-request {
18
+ # method: func() -> method;
19
+ # path-with-query: func() -> option<string>;
20
+ # scheme: func() -> option<scheme>;
21
+ # authority: func() -> option<string>;
22
+ # headers: func() -> headers;
23
+ # consume: func() -> result<incoming-body>;
24
+ # }
25
+ # https://github.com/WebAssembly/wasi-http/blob/d163277b8684483a2334363ca1492ca298ea526d/wit/types.wit#L274
26
+ class IncomingRequest
27
+ # We use a reference to the global JS object to access the incoming request data.
28
+ def initialize(js_object_id)
29
+ @js_object = ::JS.global[js_object_id]
30
+ end
31
+
32
+ def method = @js_object.call(:method).to_s
33
+
34
+ def path_with_query
35
+ path = @js_object.call(:pathWithQuery)
36
+ if path.typeof == "string"
37
+ path.to_s
38
+ end
39
+ end
40
+
41
+ def scheme
42
+ sch = @js_object.call(:scheme)
43
+ if sch.typeof == "string"
44
+ sch.to_s
45
+ end
46
+ end
47
+
48
+ def authority
49
+ auth = @js_object.call(:authority)
50
+ if auth.typeof == "string"
51
+ auth.to_s
52
+ end
53
+ end
54
+
55
+ def headers
56
+ entries = ::JS.global[:Object].entries(@js_object.call(:headers))
57
+ entries.to_a.each.with_object({}) do |entry_val, acc|
58
+ key, val = entry_val.to_a
59
+ acc[key.to_s] = val.to_s
60
+ acc
61
+ end
62
+ end
63
+
64
+ # NOTE: Currently, we only support text bodies
65
+ def consume
66
+ body = @js_object.call(:consume)
67
+ if body.typeof == "string"
68
+ body.to_s
69
+ end
70
+ end
71
+ end
72
+
73
+ # resource response-outparam {
74
+ # set: static func(
75
+ # param: response-outparam,
76
+ # response: result<outgoing-response, error-code>,
77
+ # );
78
+ # }
79
+ #
80
+ # https://github.com/WebAssembly/wasi-http/blob/d163277b8684483a2334363ca1492ca298ea526d/wit/types.wit#L437
81
+ class ResponseOutparam
82
+ # We use a reference to the global JS object to access the incoming request data
83
+ def initialize(js_object_id)
84
+ @js_object = ::JS.global[js_object_id]
85
+ end
86
+
87
+ def set(result)
88
+ @js_object.call(:set, ::JS::Object.wrap(result))
89
+ end
90
+ end
91
+
92
+ # resource outgoing-response {
93
+ # constructor(headers: headers);
94
+ # status-code: func() -> status-code;
95
+ # set-status-code: func(status-code: status-code) -> result;
96
+ # headers: func() -> headers;
97
+ # body: func() -> result<outgoing-body>;
98
+ # }
99
+ #
100
+ # resource outgoing-body {
101
+ # write: func() -> result<output-stream>;
102
+ # finish: static func(
103
+ # this: outgoing-body,
104
+ # trailers: option<trailers>
105
+ # ) -> result<_, error-code>;
106
+ # }
107
+ # }
108
+ #
109
+ # https://github.com/WebAssembly/wasi-http/blob/d163277b8684483a2334363ca1492ca298ea526d/wit/types.wit#L572
110
+ class OutgoingResponse
111
+ attr_reader :status_code, :headers, :body
112
+
113
+ def initialize(headers:, status_code: 200)
114
+ @headers = headers
115
+ @status_code = status_code
116
+ @body = nil
117
+ end
118
+
119
+ def write(response_body)
120
+ @body = response_body
121
+ end
122
+ end
123
+
124
+ # wasi:http/proxy-like handler implementation for Rack apps
125
+ class IncomingHandler
126
+ private attr_reader :base_url
127
+
128
+ def initialize(app, base_url: "http://localhost:3000", skip_data_uri_uploads: false)
129
+ @app = app
130
+
131
+ @app = Rack::DataUriUploads.new(@app) unless skip_data_uri_uploads
132
+
133
+ @base_url = base_url
134
+ end
135
+
136
+ # Takes Wasi request, converts it to Rack request,
137
+ # calls the Rack app, and write Rack response back to the Wasi response.
138
+ #
139
+ # @param [Rack::WASI::HTTP::IncomingRequest] req
140
+ # @param [Rack::WASI::HTTP::ResponseOutparam] res
141
+ def handle(req, res)
142
+ uri = URI.join(base_url, req.path_with_query || "")
143
+ headers = req.headers.each.with_object({}) do |(key, value), headers|
144
+ headers["HTTP_#{key.upcase.gsub("-", "_")}"] = value
145
+ headers
146
+ end
147
+ http_method = req.method.upcase
148
+ headers[:method] = http_method
149
+
150
+ body = req.consume
151
+ headers[:input] = StringIO.new(body) if body
152
+
153
+ request = Rack::MockRequest.env_for(uri.to_s, headers)
154
+ begin
155
+ response = Rack::Response[*@app.call(request)]
156
+ response_status, response_headers, bodyiter = *response.finish
157
+
158
+ out_response = OutgoingResponse.new(headers: response_headers, status_code: response_status)
159
+
160
+ body = ""
161
+ body_is_set = false
162
+
163
+ bodyiter.each do |part|
164
+ body += part
165
+ body_is_set = true
166
+ end
167
+
168
+ # Serve images as base64 from Ruby and decode back in JS
169
+ # FIXME: extract into a separate middleware and add a header to indicate the transformation
170
+ if headers["Content-Type"]&.start_with?("image/")
171
+ body = Base64.strict_encode64(body)
172
+ end
173
+
174
+ out_response.write(body) if body_is_set
175
+ res.set(Result.new(out_response, nil))
176
+ rescue Exception => e
177
+ res.set(Result.new(e.message, 503))
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -5,6 +5,16 @@ require "wasmify-rails"
5
5
  require "ruby_wasm"
6
6
  require "ruby_wasm/cli"
7
7
 
8
+ # Patch ruby.wasm CLI to use the latest patch versions of Ruby
9
+ RubyWasm::CLI.singleton_class.prepend(Module.new do
10
+ def build_source_aliases(root)
11
+ super.tap do |sources|
12
+ sources["3.3"][:url] = "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.8.tar.gz"
13
+ sources["3.4"][:url] = "https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.3.tar.gz"
14
+ end
15
+ end
16
+ end)
17
+
8
18
  module Wasmify
9
19
  module Rails
10
20
  # A wrapper for rbwasm build command
@@ -4,12 +4,6 @@ require "yaml"
4
4
 
5
5
  module Wasmify
6
6
  module Rails
7
- RUBY_VERSION_TO_WASM_RUBY_VERSION = {
8
- "3.4" => "3.4.1",
9
- "3.3" => "3.3.3",
10
- "3.2" => "3.2.4"
11
- }
12
-
13
7
  class Configuration
14
8
  attr_reader :pack_directories, :pack_root, :additional_root_files,
15
9
  :exclude_gems, :ignore_gem_extensions,
@@ -19,6 +19,14 @@ require "bundler"
19
19
  # Load core classes and deps patches
20
20
  $LOAD_PATH.unshift File.expand_path("shims", __dir__)
21
21
 
22
+ # Prevent features:
23
+ # - `bundler/setup` — we do that manually via `/bundle/setup`#
24
+ %w[
25
+ bundler/setup
26
+ ].each do |feature|
27
+ $LOAD_PATH.resolve_feature_path(feature)&.then { $LOADED_FEATURES << _1[1] }
28
+ end
29
+
22
30
  # Misc patches
23
31
 
24
32
  # Make gem no-op
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Wasmify
4
4
  module Rails # :nodoc:
5
- VERSION = "0.3.0"
5
+ VERSION = "0.3.2"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wasmify-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-06 00:00:00.000000000 Z
11
+ date: 2025-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -153,6 +153,7 @@ files:
153
153
  - lib/generators/wasmify/pwa/templates/pwa/vite.config.js
154
154
  - lib/image_processing/null.rb
155
155
  - lib/rack/data_uri_uploads.rb
156
+ - lib/rack/wasi/incoming_handler.rb
156
157
  - lib/wasmify-rails.rb
157
158
  - lib/wasmify/rails/builder.rb
158
159
  - lib/wasmify/rails/configuration.rb