plezi 0.12.17 → 0.12.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 09beaf8c38e5eed4e1cc3580fe3ce78be7628f8c
4
- data.tar.gz: dd718e677a9e7a00ca747c5cb06e936e1248453c
3
+ metadata.gz: 6f4a5058846b5a4228065d751c7bc7019a1b505b
4
+ data.tar.gz: 96ab017b8e3d590173fea18733bd018e6f857590
5
5
  SHA512:
6
- metadata.gz: f20d81b4969cec3edd49f65aeef948d08e90ee8a650411bc3c043cc2a80658d1e99df322fecce7c0cc7fd62ed3d61aeddf8caf4fe85a2324321fb5d174170e2d
7
- data.tar.gz: 8913e9cfbe636463d0493182de4e7306a0354ea34c210afadba38cf8879f57ca9cc7787af197c02a82bb5939571d49cebfe8359bafbfc39d45157eff83b119ec
6
+ metadata.gz: f696aabd61dfca64e7aad33eb98487421518fa830f31ca2289e852d4f6842d52f9a6cf868879aa9f52332f6eaac3dca7b5c5cc2df04b8dcb966a39be42de7c88
7
+ data.tar.gz: cbb3aa6d07560314171fcdab50b63062ac74c13a7c88b9b7f1de85f59d1cd2fb3f230975ca3361f7afa290942032499a8eaaabeeeb7da562d96f7372303cb692
@@ -2,6 +2,16 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.12.18
6
+
7
+ **Feature**: Auto-dispatching allows, when enabled, to automatically map JSON websocket messages to controller methods, according to their `event` property. Also, when using the auto-dispatch, Plezi will automatically send the returned value for dispatch methods that return a String (just like when using Http). This means that unifying Websocket and RESTful APIs is now easier than ever.
8
+
9
+ **Change**: the `json` format is now automatically assumed when a websocket connection is established - allowing `render` calls to automatically prefer `json` format templates.
10
+
11
+ **Change**: The warning shown when using the Identity API without Redis will now only appear once, instead of repeating itself.
12
+
13
+ ***
14
+
5
15
  Change log v.0.12.17
6
16
 
7
17
  **Fix**: error template format would (and should) fallback to 'html' if the originally requested format (i.e. 'json') was missing. An issue with nested template rendering (when the error template would call `render` to render a partial or other template) caused the fallback to revert to the original (missing) format when searching for the nested template. This issue is now fixed, by instructing ErrorCtrl to set the global format rather than the local one.
@@ -28,6 +28,7 @@ module Plezi
28
28
  app_tree["templates"]["welcome.html.erb"] ||= IO.read(File.join(@root, "resources" ,"mini_welcome_page.html")).gsub('appname', app_name)
29
29
  app_tree["assets"] ||= {}
30
30
  app_tree["assets"]["websocket.js"] ||= IO.read(File.join(@root, "resources" ,"websockets.js")).gsub('appname', app_name)
31
+ app_tree["assets"]["plezi_client.js"] ||= IO.read(File.join(@root,"resources" ,"plezi_client.js")).gsub('appname', app_name)
31
32
  finalize app_name
32
33
  end
33
34
 
@@ -58,6 +59,7 @@ module Plezi
58
59
  app_tree["assets"]["stylesheets"] ||= {}
59
60
  app_tree["assets"]["javascripts"] ||= {}
60
61
  app_tree["assets"]["javascripts"]["websocket.js"] ||= IO.read(File.join(@root,"resources" ,"websockets.js")).gsub('appname', app_name)
62
+ app_tree["assets"]["javascripts"]["plezi_client.js"] ||= IO.read(File.join(@root,"resources" ,"plezi_client.js")).gsub('appname', app_name)
61
63
  app_tree["assets"]["welcome.html"] ||= IO.read(File.join(@root,"resources" ,"welcome_page.html")).gsub('appname', app_name)
62
64
 
63
65
  # app core files.
@@ -32,17 +32,47 @@ module Plezi
32
32
  # (with a protocol instance of WSProtocol and an instance of the Controller class set as a handler)
33
33
  def pre_connect
34
34
  # make sure this is a websocket controller
35
- return false unless self.class.has_super_method?(:on_message)
35
+ return false unless self.class.has_super_method?(:on_message) || self.class.superclass.instance_variable_get(:@auto_dispatch)
36
36
  # call the controller's original method, if exists, and check connection.
37
37
  return false if (defined?(super) && !super)
38
38
  # finish if the response was sent
39
39
  return false if response.headers_sent?
40
40
  # make sure that the session object is available for websocket connections
41
41
  session
42
+ # make sure that rendering uses JSON for websocket messages (unless already set)
43
+ params[:format] ||= 'json'
42
44
  # complete handshake
43
45
  return self
44
46
  end
45
47
 
48
+ # Websockets
49
+ #
50
+ # this method either forwards the on_message handling to the `on_message` callback, OR
51
+ # auto-dispatches the messages by translating the JSON into a method call using the `event` keyword.
52
+ def on_message data
53
+ unless self.class.superclass.instance_variable_get(:@auto_dispatch)
54
+ return super if defined? super
55
+ return false
56
+ end
57
+ begin
58
+ data = JSON.parse data
59
+ rescue
60
+ return close
61
+ end
62
+ self.class.instance_variable_set :@allow_dispatch, (( self.class.instance_methods - (Class.new.instance_methods +
63
+ Plezi::Base::WSObject::InstanceMethods.instance_methods +
64
+ Plezi::Base::WSObject::SuperInstanceMethods.instance_methods +
65
+ Plezi::ControllerMagic::InstanceMethods.instance_methods +
66
+ Plezi::Base::ControllerCore::InstanceMethods.instance_methods +
67
+ [:before, :after, :initialize]) ).delete_if {|m| m.to_s[0] == '_'}).to_set unless self.class.instance_variable_get(:@allow_dispatch)
68
+ Plezi::Base::Helpers.make_hash_accept_symbols data
69
+ unless self.class.has_super_method?(data['event'.freeze] = data['event'.freeze].to_s.to_sym) && self.class.instance_variable_get(:@allow_dispatch).include?(data['event'.freeze])
70
+ return (self.class.has_super_method?(:unknown_event) && ( unknown_event(data) || true)) || write({ event: :err, status: 404, result: "not found", request: data }.to_json)
71
+ end
72
+ ret = self.__send__(data['event'.freeze], data)
73
+ write(ret) if ret.is_a?(String)
74
+ end
75
+
46
76
  # Inner Routing
47
77
  def _route_path_to_methods_and_set_the_response_
48
78
  #run :before filter
@@ -50,7 +80,7 @@ module Plezi
50
80
  #check request is valid and call requested method
51
81
  ret = requested_method
52
82
  return false unless ret
53
- ret = self.method(ret).call
83
+ ret = self.__send__(ret)
54
84
  return false unless ret
55
85
  #run :after filter
56
86
  return false if self.class.has_method?(:after) && self.after == false
@@ -164,23 +164,23 @@ module Plezi
164
164
  # if template is a string, it will assume the string is an
165
165
  # absolute path to a template file. it will NOT search for the template but might raise exceptions.
166
166
  #
167
- # if the template is a symbol, the '_' caracters will be used to destinguish sub-folders (NOT a partial template).
167
+ # if the template is a symbol, the '_' characters will be used to destinguish sub-folders (NOT a partial template).
168
168
  #
169
169
  # returns false if the template or layout files cannot be found.
170
170
  def render template, options = {}, &block
171
171
  # make sure templates are enabled
172
172
  return false if host_params[:templates].nil?
173
- # render layout by recursion, if exists
173
+ # set up defaults
174
+ @warned_type ||= (Iodine.warn("Deprecation warning! `#render` method called with optional `:type`. Use `:format` instead!") && true) if options[:type]
175
+ options[:format] ||= (options[:type] || params[:format] || 'html'.freeze).to_s
176
+ options[:locale] ||= params[:locale].to_sym if params[:locale]
177
+ # render layout using recursion, if exists
174
178
  if options[:layout]
175
179
  layout = options.delete(:layout)
176
180
  inner = render(template, options, &block)
177
181
  return false unless inner
178
182
  return render(layout, options) { inner }
179
183
  end
180
- # set up defaults
181
- @warned_type ||= (Iodine.warn("Deprecation warning! `#render` method called with optional `:type`. Use `:format` instead!") && true) if options[:type]
182
- options[:format] ||= (options[:type] || params[:format] || 'html'.freeze).to_s
183
- options[:locale] ||= params[:locale].to_sym if params[:locale]
184
184
  #update content-type header
185
185
  case options[:format]
186
186
  when 'html', 'js', 'txt'
@@ -4,6 +4,8 @@ module Plezi
4
4
 
5
5
  module WSObject
6
6
 
7
+ # Used to emulate the Redis connection when the Identoty API
8
+ # is used on a single process with no Redis support.
7
9
  module RedisEmultaion
8
10
  public
9
11
  def lrange key, first, last = -1
@@ -59,7 +61,7 @@ module Plezi
59
61
  end
60
62
  end
61
63
  def expire key, seconds
62
- Iodine.warn "Identity API requires Redis - no persistent storage!"
64
+ @warning_sent ||= Iodine.warn "Identity API requires Redis - no persistent storage!".freeze
63
65
  sync do
64
66
  return 0 unless @cache[key]
65
67
  if @timers[key]
@@ -168,11 +170,20 @@ module Plezi
168
170
  def registered? identity
169
171
  self.class.registered? identity
170
172
  end
173
+ # # handles websocket being closed.
174
+ # def on_close
175
+ # super if defined? super
176
+ # redis = Plezi.redis || ::Plezi::Base::WSObject::RedisEmultaion
177
+ # @___identity.each { |identity| redis.lrem "#{identity}_uuid".freeze, 0, uuid }
178
+ # end
171
179
  end
172
180
  module ClassMethods
173
181
  end
174
182
  module SuperInstanceMethods
175
183
  protected
184
+
185
+ # this is the identity event and ittells the connection to "read" the messages in the "mailbox",
186
+ # and forward the messages to the rest of the connections.
176
187
  def ___review_identity identity
177
188
  redis = Plezi.redis || ::Plezi::Base::WSObject::RedisEmultaion
178
189
  identity = identity.to_s.freeze
@@ -192,7 +203,7 @@ module Plezi
192
203
  Iodine.run do
193
204
  targets.each {|target| unicast(target, msg[:method], *msg[:data]) }
194
205
  end
195
- self.method(msg[:method]).call(*msg[:data])
206
+ self.__send__(msg[:method], *msg[:data])
196
207
  end
197
208
  # ___extend_lifetime identity
198
209
  end
@@ -79,7 +79,7 @@ module Plezi
79
79
  return false if data[:type] && data[:type] != :all && !self.is_a?(data[:type])
80
80
  # return ( self.class.placebo? ? true : we.write(ws.data)) if :method == :to_client
81
81
  return ((data[:type] == :all) ? false : (raise "Broadcasting recieved but no method can handle it - dump:\r\n #{data.to_s}") ) unless self.class.has_super_method?(data[:method])
82
- self.method(data[:method]).call(*data[:data])
82
+ self.__send__(data[:method], *data[:data])
83
83
  end
84
84
 
85
85
  # Get's the websocket's unique identifier for unicast transmissions.
@@ -1,19 +1,24 @@
1
- # Make sure the server doesn't start
2
- Iodine.protocol = false
1
+ # make sure this file only runs within the context of a Rake enabled script
2
+ if defined? Rake
3
+
4
+ # Make sure the server doesn't start
5
+ Iodine.protocol = false
3
6
 
4
7
 
5
- namespace :make do
6
- # add ActiveRecord controller-model generator
8
+ namespace :make do
9
+ # TODO: add ActiveRecord controller-model generator
7
10
 
8
- # add Squel controller-model generator
11
+ # TODO: add Squel controller-model generator
9
12
 
10
- end
11
- # add console mode
12
- desc "Same as `plezi c`: starts the application as a console, NOT a server."
13
- task :console do
14
- Kernel.exec "plezi c"
15
- end
16
- desc "Same as `rake console`: starts the application as a console, NOT a server."
17
- task :c do
18
- Kernel.exec "plezi c"
19
- end
13
+ end
14
+ # add console mode
15
+ desc "Same as `plezi c`: starts the application as a console, NOT a server."
16
+ task :console do
17
+ Kernel.exec "plezi c"
18
+ end
19
+ desc "Same as `rake console`: starts the application as a console, NOT a server."
20
+ task :c do
21
+ Kernel.exec "plezi c"
22
+ end
23
+
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.12.17"
2
+ VERSION = "0.12.18"
3
3
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "iodine", "~> 0.1.17"
21
+ spec.add_dependency "iodine", "~> 0.1.18"
22
22
  spec.add_development_dependency "bundler", "~> 1.7"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
 
@@ -236,11 +236,11 @@ function send_text()
236
236
  </script>
237
237
  </head>
238
238
  <body>
239
- <h1>Welcome to <a href="https://github.com/boazsegev/plezi">Plezi</a></h1>
239
+ <h1>Welcome to <a href="http://www.plezi.io/">Plezi</a></h1>
240
240
  <div id="wrapper">
241
241
  <h2>Congratulations, <a href='/'>appname</a> is running - What's next?</h2>
242
242
  <p><span class="bold">Congratulations</span>, you're now running appname and it has so much potential!</p>
243
- <p>appname started out <a href="https://github.com/boazsegev/plezi">Plezi</a> and it's your quest to feed it your code and make sure appname grows strong and happy.</p>
243
+ <p>appname started out <a href="http://www.plezi.io/">Plezi</a> and it's your quest to feed it your code and make sure appname grows strong and happy.</p>
244
244
  <p>You're the master of this quest, and your next steps might include:</p>
245
245
  <ol><li><p class="bold">Deciding which gems to use:</p>
246
246
  <ul>
@@ -248,7 +248,7 @@ function send_text()
248
248
  </ul>
249
249
  </li>
250
250
  <li>
251
- <p class="bold">Reviewing the sample code and feeding <a href="https://github.com/boazsegev/plezi">Plezi</a> your code:</p>
251
+ <p class="bold">Reviewing the sample code and feeding <a href="http://www.plezi.io/">Plezi</a> your code:</p>
252
252
  <ul>
253
253
  <li>Review and update MyController in your 'appname.rb'.</li>
254
254
  <li>Edit or delete this file (appname/templates/welcome.html.erb).</li>
@@ -0,0 +1,112 @@
1
+ // This is a commonly used structure for WebSocket messanging.
2
+ //
3
+ // To open a websocket connection to the current location
4
+ // (i.e, "https://example.com/path" => "wss://example.com/path"), use:
5
+ //
6
+ // var client = new PleziClient()
7
+ //
8
+ // To open a connection to a different path for the original server (SSL will be preserved when in use), use:
9
+ //
10
+ // var client = new PleziClient(PleziClient.origin + "/path")
11
+ //
12
+ // i.e., to open a connection to the root ("/"), use:
13
+ //
14
+ // var client = new PleziClient(PleziClient.origin + "/")
15
+ //
16
+ // To open a connection to a different URL or path, use:
17
+ //
18
+ // var client = new PleziClient("ws://full.url.com/path")
19
+ //
20
+ // To automatically renew the connection when disconnections are reported by the browser, use:
21
+ //
22
+ // client.reconnect = true
23
+ // client.reconnect_interval = 250 // sets how long to wait before reconnection attempts. default is 50 ms.
24
+ //
25
+ // The automatic renew flag can be used when creating the client, using:
26
+ //
27
+ // var client = new PleziClient(PleziClient.origin + "/path", true)
28
+ // client.reconnect_interval = 250 // Or use the default 50 ms.
29
+ //
30
+ // To set up event handling, directly set an `on<event name>` callback. i.e., for an event called `chat`:
31
+ //
32
+ // client.onchat = function(event) { "..." }
33
+ //
34
+ // To sent / emit event in JSON format, use the `emit` method:
35
+ //
36
+ // client.emit({event: "chat", data: "the message"})
37
+ //
38
+ // To sent raw websocket data, use the `send` method.
39
+ // This might cause disconnetions if Plezi's controller uses `auto_dispatch`.
40
+ // i.e. sending a string:
41
+ //
42
+ // client.send("string")
43
+ //
44
+ // Manually closing the connection will prevent automatic reconnection:
45
+ //
46
+ // client.close()
47
+ //
48
+ function PleziClient(url, reconnect) {
49
+ this.connected = NaN;
50
+ if(url) {
51
+ this.url = url
52
+ } else {
53
+ this.url = PleziClient.origin + window.location.pathname
54
+ }
55
+
56
+ this.ws = new WebSocket(this.url);
57
+ this.ws.owner = this
58
+ this.reconnect = false;
59
+ this.reconnect_interval = 50
60
+ if(reconnect) {this.reconnect = true;}
61
+ this.ws.onopen = function(e) {
62
+ this.owner.connected = true;
63
+ if (this.owner.onopen) { this.owner.onopen(e) }
64
+ }
65
+ this.ws.onclose = function(e) {
66
+ this.connected = false;
67
+ if (this.owner.onclose) { this.owner.onclose(e) }
68
+ if(this.owner.reconnect) {
69
+ setTimeout( function(obj) {
70
+ obj.connected = NaN;
71
+ obj.ws = new Websocket(obj.url);
72
+ obj.ws.owner = obj
73
+ }, this.reconnect_interval, this.owner);
74
+ }
75
+ }
76
+ this.ws.onerror = function(e) { if (this.owner.onerror) {this.owner.onerror(e)} }
77
+ this.ws.onmessage = this.___on_message
78
+ }
79
+
80
+ PleziClient.prototype.___on_message = function(e) {
81
+ try {
82
+ var msg = JSON.parse(e.data);
83
+ if ( (msg.event) && (this.owner['on' + msg.event])) {
84
+ this.owner['on' + msg.event](msg);
85
+ } else
86
+ {
87
+ if (this.owner['unknown']) {this.owner['unknown'](msg)};
88
+ }
89
+ } catch(err) {
90
+ console.error(err)
91
+ }
92
+ }
93
+
94
+ PleziClient.prototype.close = function() {
95
+ this.reconnect = false;
96
+ this.ws.close();
97
+ }
98
+
99
+ PleziClient.origin = (window.location.protocol.match(/https/) ? 'wws' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) );
100
+
101
+ PleziClient.prototype.send = function(data) {
102
+ if (this.ws.readyState != 1) { return false; }
103
+ this.ws.send(data);
104
+ if (this.ws.readyState != 1) { return false; }
105
+ return true
106
+ }
107
+
108
+ PleziClient.prototype.emit = function(data) {
109
+ return this.send( JSON.stringify(data) );
110
+ }
111
+
112
+ PleziClient.prototype.readyState = function() { return this.ws.readyState; }
@@ -1,4 +1,9 @@
1
- // Add this file to your html to add websocket support
1
+ // Edit and add this file to your html, to implement
2
+ // raw websocket support.
3
+
4
+ // This file should be edited to implement your raw websocket application logic.
5
+
6
+ // For an auto-dispatch, JSON implementation, consoder using the PleziClient.
2
7
 
3
8
  // Your websocket URI should be an absolute path. The following sets the base URI.
4
9
  // remember to update to the specific controller's path to your websocket URI.
@@ -236,11 +236,11 @@ function send_text()
236
236
  </script>
237
237
  </head>
238
238
  <body>
239
- <h1>Welcome to <a href="https://github.com/boazsegev/plezi">Plezi</a></h1>
239
+ <h1>Welcome to <a href="http://www.plezi.io/">Plezi</a></h1>
240
240
  <div id="wrapper">
241
241
  <h2>Congratulations, <a href='/'>appname</a> is running - What's next?</h2>
242
242
  <p><span class="bold">Congratulations</span>, you're now running appname and it has so much potential!</p>
243
- <p>appname started out <a href="https://github.com/boazsegev/plezi">Plezi</a> and it's your quest to feed it your code and make sure appname grows strong and happy.</p>
243
+ <p>appname started out <a href="http://www.plezi.io/">Plezi</a> and it's your quest to feed it your code and make sure appname grows strong and happy.</p>
244
244
  <p>You're the master of this quest, and your next steps might include:</p>
245
245
  <ol><li><p class="bold">Deciding which gems to use:</p>
246
246
  <ul>
@@ -248,7 +248,7 @@ function send_text()
248
248
  </ul>
249
249
  </li>
250
250
  <li>
251
- <p class="bold">Reviewing the sample code and feeding <a href="https://github.com/boazsegev/plezi">Plezi</a> your code:</p>
251
+ <p class="bold">Reviewing the sample code and feeding <a href="http://www.plezi.io/">Plezi</a> your code:</p>
252
252
  <ul>
253
253
  <li>Review the 'sample_controller.rb' file in the appname/app/controllers folder.</li>
254
254
  <li>Delete the 'sample_controller.rb' file and this file (appname/assets/welcome.html).</li>
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require 'benchmark'
5
+ $LOAD_PATH.unshift File.expand_path(File.join('..', '..', 'lib'), __FILE__ )
6
+ require "plezi"
7
+ require "bundler/setup"
8
+
9
+ # You can add fixtures and/or initialization code here to make experimenting
10
+ # with your gem easier. You can also use a different console, if you like.
11
+
12
+ # (If you use this, don't forget to add pry to your Gemfile!)
13
+ # require "pry"
14
+ # Pry.start
15
+
16
+ class DispatchTest
17
+ @auto_dispatch = true
18
+ def before
19
+ {event: :failed, data: :forbidden}.to_json
20
+ end
21
+ def _hidden
22
+ {event: :failed, data: :forbidden}.to_json
23
+ end
24
+ def test data = {}
25
+ data[:data] ||= "test"
26
+ {event: 'alert', data: data[:data]}.to_json
27
+ end
28
+ def index
29
+ %q{<html><head><script src='/assets/plezi_client.js'></script>
30
+ </head>
31
+ <body>
32
+ <button onclick='connection.emit({event: "test", data: "Woohooo!"});' value='test'>Test!</button>
33
+ <script>
34
+ document.body.onload = function() {
35
+ connection = new PleziClient();
36
+ connection.onalert = function(data) {
37
+ alert(JSON.stringify(data));
38
+ console.log(data);
39
+ }
40
+ // connection.onerr = function(data) {
41
+ // alert("Error: " + JSON.stringify(data));
42
+ // console.log(data);
43
+ // }
44
+ connection.unknown = function(data) {
45
+ alert("Unknown event: " + JSON.stringify(data));
46
+ console.log(data);
47
+ }
48
+ }
49
+ </script></body></html>}
50
+ end
51
+ end
52
+ host assets: File.expand_path(File.join('..','..', 'resources'), __FILE__)
53
+ route '/', DispatchTest
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plezi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.17
4
+ version: 0.12.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-16 00:00:00.000000000 Z
11
+ date: 2015-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: iodine
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.17
19
+ version: 0.1.18
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.17
26
+ version: 0.1.18
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -130,6 +130,7 @@ files:
130
130
  - resources/mini_exec.rb
131
131
  - resources/mini_welcome_page.html
132
132
  - resources/oauth_config.rb
133
+ - resources/plezi_client.js
133
134
  - resources/plezi_websockets.html
134
135
  - resources/rakefile
135
136
  - resources/redis_config.rb
@@ -138,6 +139,7 @@ files:
138
139
  - resources/websockets.js
139
140
  - resources/welcome_page.html
140
141
  - test/console
142
+ - test/dispatch
141
143
  - test/plezi_tests.rb
142
144
  homepage: http://www.plezi.io/
143
145
  licenses:
@@ -167,5 +169,6 @@ summary: Plezi - the easy way to add Websockets, RESTful routing and HTTP stream
167
169
  serviced to Ruby Web-Apps.
168
170
  test_files:
169
171
  - test/console
172
+ - test/dispatch
170
173
  - test/plezi_tests.rb
171
174
  has_rdoc: