Class: OpalHotReloader::Server
- Inherits:
-
Object
- Object
- OpalHotReloader::Server
- Defined in:
- lib/opal_hot_reloader/server.rb
Overview
Most of this lifted from github.com/saward/Rubame
Constant Summary collapse
- PROGRAM =
'opal-hot-reloader'
Instance Attribute Summary collapse
-
#directories ⇒ Object
readonly
Returns the value of attribute directories.
Instance Method Summary collapse
- #accept ⇒ Object
- #close(client) ⇒ Object
-
#initialize(options) ⇒ Server
constructor
A new instance of Server.
- #loop ⇒ Object
- #read(client) ⇒ Object
- #run(time = 0, &blk) ⇒ Object
- #send_updated_file(modified_file) ⇒ Object
-
#setup_directories(options) ⇒ Object
adds known directories automatically if they exist - rails js app/assets/javascripts app/assets/stylesheets - reactrb rails defaults app/views/components - you tell me and I’ll add them.
- #stop ⇒ Object
Constructor Details
#initialize(options) ⇒ Server
Returns a new instance of Server.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/opal_hot_reloader/server.rb', line 13 def initialize() Socket.do_not_reverse_lookup @hostname = '0.0.0.0' @port = [:port] setup_directories() @reading = [] @writing = [] @clients = {} # Socket as key, and Client as value @socket = TCPServer.new(@hostname, @port) @reading.push @socket end |
Instance Attribute Details
#directories ⇒ Object (readonly)
Returns the value of attribute directories.
12 13 14 |
# File 'lib/opal_hot_reloader/server.rb', line 12 def directories @directories end |
Instance Method Details
#accept ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/opal_hot_reloader/server.rb', line 45 def accept socket = @socket.accept_nonblock @reading.push socket handshake = WebSocket::Handshake::Server.new client = Client.new(socket, handshake, self) while line = socket.gets client.handshake << line break if client.handshake.finished? end if client.handshake.valid? @clients[socket] = client client.write handshake.to_s client.opened = true return client else close(client) end return nil end |
#close(client) ⇒ Object
146 147 148 149 150 151 152 153 154 |
# File 'lib/opal_hot_reloader/server.rb', line 146 def close(client) @reading.delete client.socket @clients.delete client.socket begin client.socket.close rescue end client.closed = true end |
#loop ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/opal_hot_reloader/server.rb', line 95 def loop listener = Listen.to(*@directories, only: %r{\.(rb(\.erb)?|s?[ac]ss)$}) do |modified, added, removed| modified.each { |modified_file| send_updated_file(modified_file) } puts "modified absolute path: #{modified}" puts "added absolute path: #{added}" puts "removed absolute path: #{removed}" end listener.start puts "#{PROGRAM}: starting..." while (!$quit) run do |client| client.onopen do puts "#{PROGRAM}: client open" end client. do |mess| puts "PROGRAM: message received: #{mess}" unless mess == '' end client.onclose do puts "#{PROGRAM}: client closed" end end sleep 0.2 end end |
#read(client) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/opal_hot_reloader/server.rb', line 121 def read(client) pairs = client.socket.recvfrom(2000) = [] if pairs[0].length == 0 close(client) else client.frame << pairs[0] while f = client.frame.next if (f.type == :close) close(client) return else .push f end end end return end |
#run(time = 0, &blk) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/opal_hot_reloader/server.rb', line 156 def run(time = 0, &blk) readable, writable = IO.select(@reading, @writing, nil, 0) if readable readable.each do |socket| client = @clients[socket] if socket == @socket client = accept else msg = read(client) client. = msg end blk.call(client) if client and blk end end # Check for lazy send items timer_start = Time.now time_passed = 0 begin @clients.each do |s, c| c.send_some_lazy(5) end time_passed = Time.now - timer_start end while time_passed < time end |
#send_updated_file(modified_file) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/opal_hot_reloader/server.rb', line 67 def send_updated_file(modified_file) if modified_file =~ /\.rb(\.erb)?$/ file_contents = File.read(modified_file).force_encoding(Encoding::UTF_8) update = { type: 'ruby', filename: modified_file, source_code: file_contents }.to_json end if modified_file =~ /\.s?[ac]ss$/ # TODO: Switch from hard-wired path assumptions to using SASS/sprockets config relative_path = Pathname.new(modified_file).relative_path_from(Pathname.new(Dir.pwd)) url = relative_path.to_s .sub('public/','') .sub('/sass/','/') .sub(/\.s[ac]ss/, '.css') update = { type: 'css', filename: modified_file, url: url }.to_json end if update @clients.each { |socket, client| client.send(update) } end end |
#setup_directories(options) ⇒ Object
adds known directories automatically if they exist
-
rails js app/assets/javascripts app/assets/stylesheets
-
reactrb rails defaults app/views/components
-
you tell me and I’ll add them
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/opal_hot_reloader/server.rb', line 32 def setup_directories() @directories = [:directories] || [] [ 'app/assets/javascripts', 'app/assets/stylesheets', 'app/views/components' ].each { |known_dir| if !@directories.include?(known_dir) && File.exists?(known_dir) @directories << known_dir end } end |
#stop ⇒ Object
184 185 186 |
# File 'lib/opal_hot_reloader/server.rb', line 184 def stop @socket.close end |