isomorfeus-asset-manager 0.12.2 → 0.12.6
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 +8 -2
- data/lib/isomorfeus/asset_manager/rack_middleware.rb +53 -49
- 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 +53 -23
- data/lib/isomorfeus-asset-manager.rb +3 -0
- data/node_modules/.package-lock.json +3 -3
- data/node_modules/esbuild-wasm/esbuild.wasm +0 -0
- data/node_modules/esbuild-wasm/esm/browser.d.ts +19 -0
- data/node_modules/esbuild-wasm/esm/browser.js +43 -5
- data/node_modules/esbuild-wasm/esm/browser.min.js +7 -7
- data/node_modules/esbuild-wasm/lib/browser.d.ts +19 -0
- data/node_modules/esbuild-wasm/lib/browser.js +43 -5
- data/node_modules/esbuild-wasm/lib/browser.min.js +13 -5
- data/node_modules/esbuild-wasm/lib/main.d.ts +19 -0
- data/node_modules/esbuild-wasm/lib/main.js +85 -16
- data/node_modules/esbuild-wasm/package.json +1 -1
- data/package.json +1 -1
- 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: 748ed2bb10bab68fad00bba234cc0175bc5d570d4e5173da53190922d2cfa413
|
4
|
+
data.tar.gz: 905ce53e7fefea4a9d69475c370d507e876348e38f7e296fd53b12f6c7b3923a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dae52b87da0a0da3f1808ae5d113632b5f7262701e58e399d8eb6b8ee4d45b317f285a03efda3df8ab9f6f2e1387c04c6a1e286b294214a9fb16cbb610725381
|
7
|
+
data.tar.gz: d8b04e26aeb39f2cd9abaf2f4f107a8a9d253f87b332f014fdad41cd487050c851301ebf8e01ef1a7a9f804134fab08a7b5eba22d12a9ccbdb16076d5e360bc8
|
@@ -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,20 @@
|
|
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
|
+
attr_accessor :asset_manager_hmr_dirs
|
14
15
|
attr_accessor :node_paths
|
15
16
|
attr_accessor :assets
|
17
|
+
attr_accessor :hmr_listener
|
16
18
|
|
17
19
|
def add_web_js_import(*args)
|
18
20
|
Isomorfeus.assets['web.js'].add_js_import(*args)
|
@@ -62,6 +64,10 @@ module Isomorfeus
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
67
|
+
self.hmr_listener = nil
|
68
|
+
self.asset_manager_hmr_channel = :isomorfeus_asset_manager_module_updates
|
69
|
+
self.asset_manager_hmr_dirs = %w[channels, components, data, operations, policies]
|
70
|
+
self.assets_websocket_path = '/_assets_websocket'
|
65
71
|
self.assets_path = '/assets'
|
66
72
|
self.assets = {
|
67
73
|
'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,67 +18,70 @@ 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
|
|
77
81
|
def should_gzip?(env)
|
78
|
-
return true if env.
|
82
|
+
return true if env.key?('HTTP_ACCEPT_ENCODING') && env['HTTP_ACCEPT_ENCODING'].match?(/\bgzip\b/)
|
79
83
|
return false if /\bno-transform\b/.match?(env[Rack::CACHE_CONTROL].to_s) || env['Content-Encoding']&.!~(/\bidentity\b/)
|
80
|
-
return false if @compressible_types && !(env.
|
84
|
+
return false if @compressible_types && !(env.key?(Rack::CONTENT_TYPE) && @compressible_types.include?(env[Rack::CONTENT_TYPE][/[^;]*/]))
|
81
85
|
true
|
82
86
|
end
|
83
87
|
end
|
@@ -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
|
@@ -1,9 +1,5 @@
|
|
1
1
|
module Isomorfeus
|
2
2
|
class AssetManager
|
3
|
-
def self.finalize(tmpdir)
|
4
|
-
proc { FileUtils.rm_rf(tmpdir) }
|
5
|
-
end
|
6
|
-
|
7
3
|
def initialize
|
8
4
|
Isomorfeus.set_node_paths
|
9
5
|
|
@@ -12,6 +8,7 @@ module Isomorfeus
|
|
12
8
|
@output_path = File.join(@tmpdir, 'output')
|
13
9
|
FileUtils.mkdir_p(@imports_path)
|
14
10
|
FileUtils.mkdir_p(@output_path)
|
11
|
+
@server_path = File.join(Isomorfeus.app_root, 'server')
|
15
12
|
|
16
13
|
@context = ExecJS.permissive_compile(init_js)
|
17
14
|
|
@@ -25,17 +22,17 @@ module Isomorfeus
|
|
25
22
|
Isomorfeus.add_ssr_js_import(ssr_imports_file) if File.exist?(ssr_imports_file)
|
26
23
|
end
|
27
24
|
|
28
|
-
|
25
|
+
init_hmr_listener if Isomorfeus.development? && !Isomorfeus.hmr_listener
|
29
26
|
end
|
30
27
|
|
31
|
-
def transition(asset_key, asset)
|
28
|
+
def transition(asset_key, asset, analyze: false)
|
32
29
|
return if !Isomorfeus.development? && asset.bundled?
|
33
30
|
asset.mutex.synchronize do
|
34
31
|
return if !Isomorfeus.development? && asset.bundled?
|
35
32
|
asset.touch
|
36
|
-
|
33
|
+
build_ruby_and_save(asset_key, asset)
|
37
34
|
save_imports(asset_key, asset)
|
38
|
-
run_esbuild(asset_key, asset)
|
35
|
+
run_esbuild(asset_key, asset, analyze)
|
39
36
|
asset.bundle = bundled_asset(asset_key)
|
40
37
|
asset.bundle_map = bundled_asset_map(asset_key) unless Isomorfeus.production?
|
41
38
|
end
|
@@ -55,7 +52,7 @@ module Isomorfeus
|
|
55
52
|
File.write(File.join(@imports_path, asset_key), asset.to_s)
|
56
53
|
end
|
57
54
|
|
58
|
-
def
|
55
|
+
def build_ruby_and_save(asset_key, asset)
|
59
56
|
asset.ruby_imports.each do |ruby_import|
|
60
57
|
out_file = File.join(@imports_path, ruby_import.module_name + '.js')
|
61
58
|
next if !Isomorfeus.development? && File.exist?(out_file)
|
@@ -71,6 +68,13 @@ module Isomorfeus
|
|
71
68
|
end
|
72
69
|
end
|
73
70
|
|
71
|
+
def compile_ruby(file)
|
72
|
+
source = File.read(file)
|
73
|
+
module_file = file[(Isomorfeus.app_root.size + 1)..-1]
|
74
|
+
compiler = Opal::Compiler.new(source, requirable: true, file: module_file)
|
75
|
+
{ javascript: compiler.compile }
|
76
|
+
end
|
77
|
+
|
74
78
|
def print_message(m, level)
|
75
79
|
l = m['location']
|
76
80
|
STDERR.puts "#{l['file']}:#{l['line']}:#{l['column']}: #{level}: #{m['text']}"
|
@@ -78,17 +82,6 @@ module Isomorfeus
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def handle_errors(asset_key, result)
|
81
|
-
# Todo simplify
|
82
|
-
unless result['warnings'].empty?
|
83
|
-
result['warnings'].each do |w|
|
84
|
-
print_message(w, 'warning')
|
85
|
-
unless w['notes'].empty?
|
86
|
-
w['notes'].each do |n|
|
87
|
-
print_message(n, 'note')
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
85
|
unless result['errors'].empty?
|
93
86
|
result['errors'].each do |e|
|
94
87
|
print_message(w, 'error')
|
@@ -98,7 +91,7 @@ module Isomorfeus
|
|
98
91
|
end
|
99
92
|
end
|
100
93
|
end
|
101
|
-
raise "
|
94
|
+
raise "Asset Manager: error bundling '#{asset_key}'"
|
102
95
|
end
|
103
96
|
end
|
104
97
|
|
@@ -115,23 +108,52 @@ module Isomorfeus
|
|
115
108
|
JAVASCRIPT
|
116
109
|
end
|
117
110
|
|
111
|
+
def init_hmr_listener
|
112
|
+
return unless Dir.exist?(Isomorfeus.app_root)
|
113
|
+
listen_dirs = []
|
114
|
+
Isomorfeus.asset_manager_hmr_dirs.each do |dir|
|
115
|
+
if File.absolute_path?(dir)
|
116
|
+
listen_dirs << dir if Dir.exist?(dir)
|
117
|
+
else
|
118
|
+
listen_dir = File.join(Isomorfeus.app_root, dir)
|
119
|
+
listen_dirs << listen_dir if Dir.exist?(listen_dir)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
Isomorfeus.hmr_listener = Listen.to(*listen_dirs) do |modified, added, _|
|
123
|
+
(modified + added).each do |file|
|
124
|
+
next if file.start_with?(@server_path)
|
125
|
+
begin
|
126
|
+
update = compile_ruby(file)
|
127
|
+
update_json = Oj.dump(update, mode: :strict)
|
128
|
+
Iodine.publish(Isomorfeus.asset_manager_hmr_channel, update_json)
|
129
|
+
rescue Exception => e
|
130
|
+
message = "#{e.message}\n#{e.backtrace.join("\n")}"
|
131
|
+
STDERR.puts message
|
132
|
+
Iodine.publish(Isomorfeus.asset_manager_hmr_channel, Oj.dump({ error: message }, mode: :struct))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
Isomorfeus.hmr_listener.start
|
137
|
+
end
|
138
|
+
|
118
139
|
# possible future improvement
|
119
140
|
# loader: {
|
120
141
|
# '.png': 'dataurl',
|
121
142
|
# '.svg': 'text',
|
122
143
|
# },
|
123
|
-
def run_esbuild(asset_key, asset)
|
144
|
+
def run_esbuild(asset_key, asset, analyze = false)
|
124
145
|
resolve_paths = ENV['NODE_PATH'].split(Gem.win_platform? ? ';' : ':')
|
125
146
|
resolve_paths << 'node_modules'
|
126
147
|
resolve_paths.uniq!
|
127
148
|
|
128
149
|
result = @context.exec <<~JAVASCRIPT
|
129
|
-
|
150
|
+
let res = esbuild.buildSync({
|
130
151
|
entryPoints: [path.resolve(global.imports_path, '#{asset_key}')],
|
131
152
|
bundle: true,
|
132
153
|
color: false,
|
133
154
|
format: '#{asset.target == :node ? 'cjs' : 'iife'}',
|
134
155
|
legalComments: 'linked',
|
156
|
+
metafile: true,
|
135
157
|
minify: #{Isomorfeus.production? ? 'true' : 'false'},
|
136
158
|
nodePaths: #{resolve_paths},
|
137
159
|
outdir: global.output_path,
|
@@ -142,7 +164,15 @@ module Isomorfeus
|
|
142
164
|
target: 'es6',
|
143
165
|
write: true
|
144
166
|
});
|
167
|
+
global.res_meta = res.metafile;
|
168
|
+
return res;
|
145
169
|
JAVASCRIPT
|
170
|
+
if analyze
|
171
|
+
analysis = @context.await <<~JAVASCRIPT
|
172
|
+
esbuild.analyzeMetafile(global.res_meta, { verbose: true });
|
173
|
+
JAVASCRIPT
|
174
|
+
STDOUT.puts "Bundle analysis for #{asset_key}:\n#{analysis}\n"
|
175
|
+
end
|
146
176
|
handle_errors(asset_key, result)
|
147
177
|
end
|
148
178
|
end
|