isomorfeus-asset-manager 0.12.4 → 0.12.5
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/lib/isomorfeus/asset_manager/asset.rb +25 -0
- data/lib/isomorfeus/asset_manager/config.rb +6 -2
- data/lib/isomorfeus/asset_manager/rack_middleware.rb +51 -47
- data/lib/isomorfeus/asset_manager/server_socket_processor.rb +21 -55
- data/lib/isomorfeus/asset_manager/version.rb +1 -1
- data/lib/isomorfeus/asset_manager.rb +34 -17
- data/lib/isomorfeus-asset-manager.rb +3 -0
- metadata +34 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 118c1d13be80aba5339ecc42d8af01d22b1aa97ac929b8eb7915638ce28a3449
|
|
4
|
+
data.tar.gz: 8828cc73dc59ad93686d0e5c50a5df9da7ba25b9a1e8925537ce04b8bd359df3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3e8c8ebec132650ef035c830ee3dcf5caecf9a22cd7674c9cacc1ac673e66b2c75e29b4f414c2222d1fc25cbfc4609e3ab6ccb8f8806d3b4e2cd6aa7a3fd568f
|
|
7
|
+
data.tar.gz: 64de09f406887a737cfd1dc3e976cd4b911acf49cc92e2b64ce24cad185994b1b49ba05f51a5783230a61401d3f5cbab687b4c661f6a16ab4b348aa4c2b22b2d
|
|
@@ -63,6 +63,31 @@ module Isomorfeus
|
|
|
63
63
|
end
|
|
64
64
|
js << "\n" if !@js_imports.empty? && !@ruby_imports.empty?
|
|
65
65
|
unless @ruby_imports.empty?
|
|
66
|
+
if Isomorfeus.development? && @target == :browser
|
|
67
|
+
js << <<~JAVASCRIPT
|
|
68
|
+
// Isomorfeus Asset Manager HMR code begin
|
|
69
|
+
let ws_protocol = (window.location.protocol == 'https:') ? 'wss:' : 'ws:';
|
|
70
|
+
let ws_url = ws_protocol + '//' + window.location.host + "#{Isomorfeus.assets_websocket_path}";
|
|
71
|
+
let hmr_ws = new WebSocket(ws_url);
|
|
72
|
+
hmr_ws.onmessage = function(event) {
|
|
73
|
+
let update = JSON.parse(event.data);
|
|
74
|
+
if (typeof update.error !== 'undefined') { console.error(update.error); return; }
|
|
75
|
+
let start_index = '/* Generated by Opal 1.2.0 */\\nOpal.modules[\\"'.length;
|
|
76
|
+
let end_index = update.javascript.indexOf('"', start_index);
|
|
77
|
+
let opal_module_name = update.javascript.substr(start_index, end_index - start_index);
|
|
78
|
+
console.log('Updating ', opal_module_name);
|
|
79
|
+
if (typeof Opal !== 'undefined' && typeof Opal.require_table !== "undefined" && Opal.require_table['corelib/module']) {
|
|
80
|
+
try {
|
|
81
|
+
eval(update.javascript);
|
|
82
|
+
if (Opal.require_table[opal_module_name]) { Opal.load.call(Opal, opal_module_name); }
|
|
83
|
+
else { Opal.require.call(Opal, opal_module_name); }
|
|
84
|
+
Opal.Isomorfeus.$force_render();
|
|
85
|
+
} catch (e) { console.error(e); return; }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Isomorfeus Asset Manager HMR code end
|
|
89
|
+
JAVASCRIPT
|
|
90
|
+
end
|
|
66
91
|
js << "#{@ruby_imports.map(&:to_s).join("\n")}"
|
|
67
92
|
end
|
|
68
93
|
js
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
module Isomorfeus
|
|
2
2
|
# available settings
|
|
3
3
|
if RUBY_ENGINE == 'opal'
|
|
4
|
-
add_client_option(:assets_websocket_path)
|
|
5
4
|
add_client_option(:assets_path)
|
|
6
|
-
add_client_option(:opal_assets_path)
|
|
7
5
|
else
|
|
8
6
|
class << self
|
|
9
7
|
attr_reader :env
|
|
10
8
|
attr_accessor :root
|
|
11
9
|
attr_accessor :app_root
|
|
12
10
|
attr_accessor :assets_path
|
|
11
|
+
attr_accessor :assets_websocket_path
|
|
13
12
|
attr_accessor :asset_manager_tmpdir
|
|
13
|
+
attr_accessor :asset_manager_hmr_channel
|
|
14
14
|
attr_accessor :node_paths
|
|
15
15
|
attr_accessor :assets
|
|
16
|
+
attr_accessor :hmr_listener
|
|
16
17
|
|
|
17
18
|
def add_web_js_import(*args)
|
|
18
19
|
Isomorfeus.assets['web.js'].add_js_import(*args)
|
|
@@ -62,6 +63,9 @@ module Isomorfeus
|
|
|
62
63
|
end
|
|
63
64
|
end
|
|
64
65
|
|
|
66
|
+
self.hmr_listener = nil
|
|
67
|
+
self.asset_manager_hmr_channel = :isomorfeus_asset_manager_module_updates
|
|
68
|
+
self.assets_websocket_path = '/_assets_websocket'
|
|
65
69
|
self.assets_path = '/assets'
|
|
66
70
|
self.assets = {
|
|
67
71
|
'web.js' => Isomorfeus::AssetManager::Asset.new(:browser),
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
module Isomorfeus
|
|
4
4
|
class AssetManager
|
|
5
5
|
class RackMiddleware
|
|
6
|
-
WS_RESPONSE = [0, {}, []]
|
|
6
|
+
WS_RESPONSE = [0, {}, []].freeze
|
|
7
7
|
attr_reader :asset_manager
|
|
8
8
|
|
|
9
9
|
def initialize(app)
|
|
10
|
+
STDERR.puts "asset manager"
|
|
10
11
|
@app = app
|
|
11
12
|
@asset_manager = Isomorfeus::AssetManager.new
|
|
12
13
|
@compressible_types = %w[application/javascript text/javascript]
|
|
@@ -17,60 +18,63 @@ module Isomorfeus
|
|
|
17
18
|
@assets_path = Isomorfeus.assets_path + '/'
|
|
18
19
|
@assets_path_size = @assets_path.size
|
|
19
20
|
end
|
|
21
|
+
rescue Exception => e
|
|
22
|
+
STDERR.puts "#{e.message}\n#{e.backtrace.join("\n")}\n"
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
def call(env)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
asset_key = path_info[@assets_path_size..-1]
|
|
26
|
+
path_info = env['PATH_INFO']
|
|
27
|
+
if path_info.start_with?(@assets_path)
|
|
28
|
+
asset_key = path_info[@assets_path_size..-1]
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# get source map
|
|
47
|
-
elsif asset_key.end_with?('.js.map')
|
|
48
|
-
asset = Isomorfeus.assets[asset_key[0..-5]]
|
|
49
|
-
if asset && asset.target != :node
|
|
50
|
-
asset_manager.transition(asset_key, asset) unless asset.bundled?
|
|
51
|
-
headers = {}
|
|
52
|
-
headers['Last-Modified'] = asset.mtime
|
|
53
|
-
headers[Rack::CONTENT_TYPE] = 'application/json'
|
|
54
|
-
if should_gzip?(env)
|
|
55
|
-
headers['Content-Encoding'] = "gzip"
|
|
56
|
-
headers[Rack::CONTENT_LENGTH] = asset.bundle_map_gz.size
|
|
57
|
-
return [200, headers, asset.bundle_map_gz]
|
|
58
|
-
else
|
|
59
|
-
headers[Rack::CONTENT_LENGTH] = asset.bundle_map.size
|
|
60
|
-
return [200, {}, asset.bundle_map]
|
|
61
|
-
end
|
|
62
|
-
end
|
|
30
|
+
# get js
|
|
31
|
+
if Isomorfeus.assets.key?(asset_key)
|
|
32
|
+
asset = Isomorfeus.assets[asset_key]
|
|
33
|
+
if asset && asset.target != :node
|
|
34
|
+
asset_manager.transition(asset_key, asset)
|
|
35
|
+
headers = {}
|
|
36
|
+
headers['Last-Modified'] = asset.mtime
|
|
37
|
+
headers[Rack::CONTENT_TYPE] = 'application/javascript'
|
|
38
|
+
if should_gzip?(env)
|
|
39
|
+
headers['Content-Encoding'] = "gzip"
|
|
40
|
+
headers[Rack::CONTENT_LENGTH] = asset.bundle_gz_size
|
|
41
|
+
return [200, headers, asset.bundle_gz]
|
|
42
|
+
else
|
|
43
|
+
headers[Rack::CONTENT_LENGTH] = asset.bundle_size
|
|
44
|
+
return [200, {}, asset.bundle]
|
|
45
|
+
end
|
|
63
46
|
end
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
47
|
+
|
|
48
|
+
# get source map
|
|
49
|
+
elsif asset_key.end_with?('.js.map')
|
|
50
|
+
asset = Isomorfeus.assets[asset_key[0..-5]]
|
|
51
|
+
if asset && asset.target != :node
|
|
52
|
+
asset_manager.transition(asset_key, asset) unless asset.bundled?
|
|
53
|
+
headers = {}
|
|
54
|
+
headers['Last-Modified'] = asset.mtime
|
|
55
|
+
headers[Rack::CONTENT_TYPE] = 'application/json'
|
|
56
|
+
if should_gzip?(env)
|
|
57
|
+
headers['Content-Encoding'] = "gzip"
|
|
58
|
+
headers[Rack::CONTENT_LENGTH] = asset.bundle_map_gz.size
|
|
59
|
+
return [200, headers, asset.bundle_map_gz]
|
|
60
|
+
else
|
|
61
|
+
headers[Rack::CONTENT_LENGTH] = asset.bundle_map.size
|
|
62
|
+
return [200, {}, asset.bundle_map]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# hot reloading subscription
|
|
68
|
+
elsif Isomorfeus.development? && path_info == Isomorfeus.assets_websocket_path
|
|
69
|
+
if env['rack.upgrade?'] == :websocket
|
|
70
|
+
env['rack.upgrade'] = Isomorfeus::AssetManager::ServerSocketProcessor.new
|
|
69
71
|
end
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
WS_RESPONSE
|
|
73
|
+
else
|
|
72
74
|
@app.call(env)
|
|
73
75
|
end
|
|
76
|
+
rescue Exception => e
|
|
77
|
+
STDERR.puts "#{e.message}\n#{e.backtrace.join("\n")}\n"
|
|
74
78
|
@app.call(env)
|
|
75
79
|
end
|
|
76
80
|
|
|
@@ -1,55 +1,21 @@
|
|
|
1
|
-
module Isomorfeus
|
|
2
|
-
class AssetManager
|
|
3
|
-
class ServerSocketProcessor
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# handler_instance_cache.each_value do |handler|
|
|
23
|
-
# handler.resolve if handler.resolving?
|
|
24
|
-
# end
|
|
25
|
-
# result = {}
|
|
26
|
-
# response_agent_array.each do |response_agent|
|
|
27
|
-
# result.deep_merge!(response_agent.result)
|
|
28
|
-
# end
|
|
29
|
-
# client.write Oj.dump(result, mode: :strict) unless result.empty?
|
|
30
|
-
# ensure
|
|
31
|
-
# Thread.current[:isomorfeus_user] = nil
|
|
32
|
-
# Thread.current[:isomorfeus_pub_sub_client] = nil
|
|
33
|
-
# Isomorfeus.zeitwerk_lock.release_read_lock if Isomorfeus.development?
|
|
34
|
-
# end
|
|
35
|
-
|
|
36
|
-
# def on_close(client)
|
|
37
|
-
# # nothing for now
|
|
38
|
-
# end
|
|
39
|
-
|
|
40
|
-
# def on_open(client)
|
|
41
|
-
# # nothing for now
|
|
42
|
-
# end
|
|
43
|
-
|
|
44
|
-
# def on_shutdown(client)
|
|
45
|
-
# # nothing for now
|
|
46
|
-
# end
|
|
47
|
-
|
|
48
|
-
# def user(client)
|
|
49
|
-
# current_user = client.instance_variable_get(:@isomorfeus_user)
|
|
50
|
-
# return current_user if current_user
|
|
51
|
-
# Anonymous.new
|
|
52
|
-
# end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
1
|
+
module Isomorfeus
|
|
2
|
+
class AssetManager
|
|
3
|
+
class ServerSocketProcessor
|
|
4
|
+
def on_message(client, data)
|
|
5
|
+
# nothing for now
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def on_close(client)
|
|
9
|
+
# client.unsubscribe Isomorfeus.asset_manager_hmr_channel
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def on_open(client)
|
|
13
|
+
client.subscribe Isomorfeus.asset_manager_hmr_channel
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def on_shutdown(client)
|
|
17
|
+
# nothing for now
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -20,6 +20,8 @@ module Isomorfeus
|
|
|
20
20
|
ssr_imports_file = File.join(imports_path, 'ssr.js')
|
|
21
21
|
Isomorfeus.add_ssr_js_import(ssr_imports_file) if File.exist?(ssr_imports_file)
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
init_hmr_listener if Isomorfeus.development? && !Isomorfeus.hmr_listener
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def transition(asset_key, asset, analyze: false)
|
|
@@ -27,7 +29,7 @@ module Isomorfeus
|
|
|
27
29
|
asset.mutex.synchronize do
|
|
28
30
|
return if !Isomorfeus.development? && asset.bundled?
|
|
29
31
|
asset.touch
|
|
30
|
-
|
|
32
|
+
build_ruby_and_save(asset_key, asset)
|
|
31
33
|
save_imports(asset_key, asset)
|
|
32
34
|
run_esbuild(asset_key, asset, analyze)
|
|
33
35
|
asset.bundle = bundled_asset(asset_key)
|
|
@@ -49,7 +51,7 @@ module Isomorfeus
|
|
|
49
51
|
File.write(File.join(@imports_path, asset_key), asset.to_s)
|
|
50
52
|
end
|
|
51
53
|
|
|
52
|
-
def
|
|
54
|
+
def build_ruby_and_save(asset_key, asset)
|
|
53
55
|
asset.ruby_imports.each do |ruby_import|
|
|
54
56
|
out_file = File.join(@imports_path, ruby_import.module_name + '.js')
|
|
55
57
|
next if !Isomorfeus.development? && File.exist?(out_file)
|
|
@@ -65,6 +67,13 @@ module Isomorfeus
|
|
|
65
67
|
end
|
|
66
68
|
end
|
|
67
69
|
|
|
70
|
+
def compile_ruby(file)
|
|
71
|
+
source = File.read(file)
|
|
72
|
+
module_file = file[(Isomorfeus.app_root.size + 1)..-1]
|
|
73
|
+
compiler = Opal::Compiler.new(source, requirable: true, file: module_file)
|
|
74
|
+
{ javascript: compiler.compile }
|
|
75
|
+
end
|
|
76
|
+
|
|
68
77
|
def print_message(m, level)
|
|
69
78
|
l = m['location']
|
|
70
79
|
STDERR.puts "#{l['file']}:#{l['line']}:#{l['column']}: #{level}: #{m['text']}"
|
|
@@ -72,17 +81,6 @@ module Isomorfeus
|
|
|
72
81
|
end
|
|
73
82
|
|
|
74
83
|
def handle_errors(asset_key, result)
|
|
75
|
-
# Todo simplify
|
|
76
|
-
# unless result['warnings'].empty?
|
|
77
|
-
# result['warnings'].each do |w|
|
|
78
|
-
# print_message(w, 'warning')
|
|
79
|
-
# unless w['notes'].empty?
|
|
80
|
-
# w['notes'].each do |n|
|
|
81
|
-
# print_message(n, 'note')
|
|
82
|
-
# end
|
|
83
|
-
# end
|
|
84
|
-
# end
|
|
85
|
-
# end
|
|
86
84
|
unless result['errors'].empty?
|
|
87
85
|
result['errors'].each do |e|
|
|
88
86
|
print_message(w, 'error')
|
|
@@ -92,7 +90,7 @@ module Isomorfeus
|
|
|
92
90
|
end
|
|
93
91
|
end
|
|
94
92
|
end
|
|
95
|
-
raise "
|
|
93
|
+
raise "Asset Manager: error bundling '#{asset_key}'"
|
|
96
94
|
end
|
|
97
95
|
end
|
|
98
96
|
|
|
@@ -109,6 +107,25 @@ module Isomorfeus
|
|
|
109
107
|
JAVASCRIPT
|
|
110
108
|
end
|
|
111
109
|
|
|
110
|
+
def init_hmr_listener
|
|
111
|
+
return unless Dir.exist?(Isomorfeus.app_root)
|
|
112
|
+
Isomorfeus.hmr_listener = Listen.to(Isomorfeus.app_root) do |modified, added, _|
|
|
113
|
+
(modified + added).each do |file|
|
|
114
|
+
begin
|
|
115
|
+
start = Time.now
|
|
116
|
+
update = compile_ruby(file)
|
|
117
|
+
update_json = Oj.dump(update, mode: :strict)
|
|
118
|
+
Iodine.publish(Isomorfeus.asset_manager_hmr_channel, update_json)
|
|
119
|
+
rescue Exception => e
|
|
120
|
+
message = "#{e.message}\n#{e.backtrace.join("\n")}"
|
|
121
|
+
STDERR.puts message
|
|
122
|
+
Iodine.publish(Isomorfeus.asset_manager_hmr_channel, Oj.dump({ error: message }, mode: :struct))
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
Isomorfeus.hmr_listener.start
|
|
127
|
+
end
|
|
128
|
+
|
|
112
129
|
# possible future improvement
|
|
113
130
|
# loader: {
|
|
114
131
|
# '.png': 'dataurl',
|
|
@@ -137,14 +154,14 @@ module Isomorfeus
|
|
|
137
154
|
target: 'es6',
|
|
138
155
|
write: true
|
|
139
156
|
});
|
|
140
|
-
global.
|
|
157
|
+
global.res_meta = res.metafile;
|
|
141
158
|
return res;
|
|
142
159
|
JAVASCRIPT
|
|
143
160
|
if analyze
|
|
144
161
|
analysis = @context.await <<~JAVASCRIPT
|
|
145
|
-
esbuild.analyzeMetafile(global.
|
|
162
|
+
esbuild.analyzeMetafile(global.res_meta, { verbose: true });
|
|
146
163
|
JAVASCRIPT
|
|
147
|
-
STDOUT.puts "Bundle
|
|
164
|
+
STDOUT.puts "Bundle analysis for #{asset_key}:\n#{analysis}\n"
|
|
148
165
|
end
|
|
149
166
|
handle_errors(asset_key, result)
|
|
150
167
|
end
|
|
@@ -3,9 +3,12 @@ require 'thread'
|
|
|
3
3
|
require 'tmpdir'
|
|
4
4
|
require 'zlib'
|
|
5
5
|
require 'opal'
|
|
6
|
+
require 'opal/compiler'
|
|
6
7
|
require 'opal/builder'
|
|
7
8
|
require 'oj'
|
|
8
9
|
require 'rack'
|
|
10
|
+
require 'listen'
|
|
11
|
+
require 'iodine'
|
|
9
12
|
require 'isomorfeus-speednode'
|
|
10
13
|
require 'isomorfeus/asset_manager/version'
|
|
11
14
|
require 'isomorfeus/asset_manager/js_import'
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: isomorfeus-asset-manager
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.12.
|
|
4
|
+
version: 0.12.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jan Biedermann
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-09-
|
|
11
|
+
date: 2021-09-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: iodine
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.7.44
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.7.44
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: isomorfeus-speednode
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -24,20 +38,34 @@ dependencies:
|
|
|
24
38
|
- - ">="
|
|
25
39
|
- !ruby/object:Gem::Version
|
|
26
40
|
version: 0.4.1
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: listen
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 3.7.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 3.7.0
|
|
27
55
|
- !ruby/object:Gem::Dependency
|
|
28
56
|
name: oj
|
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
|
30
58
|
requirements:
|
|
31
|
-
- - "
|
|
59
|
+
- - "~>"
|
|
32
60
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 3.13.
|
|
61
|
+
version: 3.13.6
|
|
34
62
|
type: :runtime
|
|
35
63
|
prerelease: false
|
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
65
|
requirements:
|
|
38
|
-
- - "
|
|
66
|
+
- - "~>"
|
|
39
67
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 3.13.
|
|
68
|
+
version: 3.13.6
|
|
41
69
|
- !ruby/object:Gem::Dependency
|
|
42
70
|
name: opal
|
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|