wasmify-rails 0.3.1 → 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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/active_record/connection_adapters/nulldb_adapter/core.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_wasm_adapter.rb +2 -0
- data/lib/rack/data_uri_uploads.rb +3 -1
- data/lib/rack/wasi/incoming_handler.rb +182 -0
- data/lib/wasmify/rails/shim.rb +8 -0
- data/lib/wasmify/rails/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6da25bdd1a3e205a57b7081ada2a29997e4cf5df306423695564aba47591efb3
|
4
|
+
data.tar.gz: d7e72fc5aed555d506086f267cba686560357c3a478015b891d15e9b613cb26f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 650516f17e4f8fc0a02f5b6515d23634f8ac47dd14d5faecb0bd932d74994b7a1b9127a50143b46dd97d1d1c6f5b3e7fbba1146306cc9f099dcb44542945c643
|
7
|
+
data.tar.gz: ac1d4ef0047666f1e7e52e935f3c78dcb596c4c064b7bd7f5ace46ccc8eef56f555f7db4e90d52da50b469f64587a8e4766a47f31e7caed0e3976c35b9573cec
|
data/CHANGELOG.md
CHANGED
@@ -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)
|
@@ -19,7 +19,9 @@ module Rack
|
|
19
19
|
|
20
20
|
request = Rack::Request.new(env)
|
21
21
|
|
22
|
-
if
|
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
|
data/lib/wasmify/rails/shim.rb
CHANGED
@@ -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
|
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.
|
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-
|
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
|