sinatra-rocketio-linda 0.1.1 → 0.1.2

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: 00ad1eabde4c411c5f3cc5e2face0f8a7447f0d1
4
- data.tar.gz: c3fd2667f18996af19914b5ac4c80f94d5c9fe9a
3
+ metadata.gz: d0857d4b25976ea5ce37682c263f65dfe835a915
4
+ data.tar.gz: 4b50812ba66530ebe94bdf43aaea55e50f6eb577
5
5
  SHA512:
6
- metadata.gz: 89508b6b7807fd90c6c98db253af38e7875bcb97b278dc3ab8c1b1b6762741515762d4b4348f03b4139a40ddb92b4454ff47c15e3a25523d6f50fe44aa6aaf42
7
- data.tar.gz: 7c4807cc17a4c3bbcc6cbcd9fac5e1e5b28b163aaa0e8a97f048d3fd9bea58b51bed79ce49793f1d1ce28343ffed68c63c427546bdcbdc4106588b181056342f
6
+ metadata.gz: efeffd1b6e4ecb925c2c003d368c4cfcfe4b1eaa1edd1f02a1ca78e42e06ebe8b337c87e02e6adf6eabd1714b2f0a0180181048658da9ca5bc168f683f6ec3b3
7
+ data.tar.gz: 675fca70a3d4da4af53382fff880c13c47e826f4ac7c95a8e3cb3d5d411d621d8563ee3e55c31fe241df58dbebcbc703fcf5588a66773e6d8d61c706bb2c3fe8
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.1.2 2013-06-09
2
+
3
+ * linda-rocketio command
4
+
1
5
  === 0.1.1 2013-05-31
2
6
 
3
7
  * fix canceling callback on client disconnect
data/README.md CHANGED
@@ -147,6 +147,13 @@ linda.wait
147
147
  ```
148
148
 
149
149
 
150
+ linda-rocketio command
151
+ ----------------------
152
+
153
+ % lidna-rocketio --help
154
+ % linda-rocketio --write '["say","hello"]' --base http://example.com --space test
155
+
156
+
150
157
  JavaScript Lib for browser
151
158
  --------------------------
152
159
 
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path '../lib', File.dirname(__FILE__)
3
+ require 'rubygems'
4
+ require 'sinatra/rocketio/linda/client'
5
+ require 'args_parser'
6
+
7
+ args = ArgsParser.parse ARGV do
8
+ arg :write, 'write Tuple(s)'
9
+ arg :read, 'read a Tuple'
10
+ arg :take, 'take a Tuple'
11
+ arg :watch, 'watch Tuples'
12
+ arg :base, 'linda base URL', :default => 'http://linda.shokai.org'
13
+ arg :space, 'linda space name', :default => 'test'
14
+ arg :timeout, 'wait (sec)', :default => 10
15
+ arg :verbose, 'verbose mode', :alias => :v
16
+ arg :help, 'show help', :alias => :h
17
+
18
+ validate :base, "invalid linda URL" do |v|
19
+ v =~ /^https?:\/\/.+/
20
+ end
21
+
22
+ [:write, :read, :take, :watch].each do |arg|
23
+ filter arg do |v|
24
+ JSON.parse v
25
+ end
26
+ end
27
+ end
28
+
29
+ class Console
30
+ def self.enable=(bool)
31
+ @@enable = bool
32
+ end
33
+
34
+ def self.enable?
35
+ @@enable
36
+ end
37
+
38
+ def self.log(str)
39
+ STDOUT.puts "* #{str}" if enable?
40
+ end
41
+
42
+ def self.error(str)
43
+ STDERR.puts "! #{str}" if enable?
44
+ end
45
+ end
46
+
47
+ Console.enable = args.has_option? :verbose
48
+
49
+ if args.has_option? :help or !args.has_param? :base, :space
50
+ bin = $0.split("/").last
51
+ STDERR.puts "RocketIO::Linda v#{Sinatra::RocketIO::Linda::VERSION}"
52
+ STDERR.puts " - https://github.com/shokai/sinatra-rocketio-linda"
53
+ STDERR.puts
54
+ STDERR.puts args.help
55
+ STDERR.puts
56
+ STDERR.puts "e.g."
57
+ STDERR.puts %Q{write #{bin} --base http://example.com --space test --write '["say","hello"]'}
58
+ STDERR.puts %Q{ echo '["say","hello"]\\n["say","world"]' | #{bin} --base http://example.com --space test --write}
59
+ STDERR.puts %Q{read #{bin} --base http://example.com --space test --read '["say"]'}
60
+ STDERR.puts %Q{take #{bin} --base http://example.com --space test --take '["say"]'}
61
+ STDERR.puts %Q{watch #{bin} --base http://example.com --space test --watch '["say"]'}
62
+ exit 1
63
+ end
64
+
65
+ io = Sinatra::RocketIO::Client.new args[:base]
66
+ linda = Sinatra::RocketIO::Linda::Client.new io
67
+ ts = linda.tuplespace[ args[:space] ]
68
+
69
+ linda.io.on :connect do
70
+ Console.log "connect #{io.session} (#{io.type})"
71
+ if args.has_param? :write
72
+ Console.log "write #{args[:write].to_json}"
73
+ ts.write args[:write]
74
+ exit
75
+ elsif args.has_option? :write
76
+ while line = STDIN.gets do
77
+ begin
78
+ tuple = JSON.parse line.strip
79
+ Console.log "write #{tuple.to_json}"
80
+ puts tuple.to_json
81
+ ts.write tuple
82
+ rescue => e
83
+ Console.error e
84
+ end
85
+ end
86
+ exit
87
+ elsif args.has_param? :read
88
+ Console.log "read #{args[:read].to_json}"
89
+ ts.read args[:read] do |tuple|
90
+ puts tuple.to_json
91
+ exit
92
+ end
93
+ elsif args.has_param? :take
94
+ Console.log "take #{args[:take].to_json}"
95
+ ts.take args[:take] do |tuple|
96
+ puts tuple.to_json
97
+ exit
98
+ end
99
+ elsif args.has_param? :watch
100
+ Console.log "watch #{args[:watch].to_json}"
101
+ ts.watch args[:watch] do |tuple|
102
+ puts tuple.to_json
103
+ end
104
+ else
105
+ exit 1
106
+ end
107
+ end
108
+
109
+ linda.io.on :disconnect do
110
+ Console.log "disconnect #{io.session} (#{io.type})"
111
+ end
112
+
113
+ Console.log "waiting #{args[:base]}"
114
+ io.connect
115
+
116
+ if [Fixnum, Float].include? args[:timeout].class and args[:timeout] > 0 and !args.has_option?(:write)
117
+ sleep args[:timeout]
118
+ else
119
+ linda.wait
120
+ end
121
+
122
+ Console.log "timeout (#{args[:timeout]}sec)"
@@ -1,3 +1,4 @@
1
+ require File.expand_path 'version', File.dirname(__FILE__)
1
2
  require 'event_emitter'
2
3
  require 'sinatra/rocketio/client'
3
4
 
@@ -1,7 +1,7 @@
1
1
  module Sinatra
2
2
  module RocketIO
3
3
  module Linda
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
6
6
  end
7
7
  end
data/linda.js CHANGED
@@ -1,4 +1,4 @@
1
- // Linda.js v0.0.9 (rocketio v0.2.6)
1
+ // Linda.js v0.1.1 (rocketio v0.2.6)
2
2
  // https://github.com/shokai/sinatra-rocketio-linda
3
3
  // (c) 2013 Sho Hashimoto <hashimoto@shokai.org>
4
4
  // The MIT License
@@ -195,7 +195,7 @@ var CometIO = function(url, opts){
195
195
  if(!running) return;
196
196
  $.ajax(
197
197
  {
198
- url : self.url,
198
+ url : self.url+"?"+(new Date()-0),
199
199
  data : {session : self.session},
200
200
  success : function(data_arr){
201
201
  if(data_arr !== null && typeof data_arr == "object" && !!data_arr.length){
@@ -245,13 +245,14 @@ var WebSocketIO = function(url, opts){
245
245
  var url = self.session ? self.url+"/session="+self.session : self.url;
246
246
  self.websocket = new WebSocket(url);
247
247
  self.websocket.onmessage = function(e){
248
+ var data_ = null;
248
249
  try{
249
- var data_ = JSON.parse(e.data);
250
- self.emit(data_.type, data_.data);
250
+ data_ = JSON.parse(e.data);
251
251
  }
252
252
  catch(e){
253
253
  self.emit("error", "WebSocketIO data parse error");
254
254
  }
255
+ if(!!data_) self.emit(data_.type, data_.data);
255
256
  };
256
257
  self.websocket.onclose = function(){
257
258
  if(self.connecting){
data/linda.min.js CHANGED
@@ -1,5 +1,5 @@
1
- // Linda.js v0.0.9 (rocketio v0.2.6)
1
+ // Linda.js v0.1.1 (rocketio v0.2.6)
2
2
  // https://github.com/shokai/sinatra-rocketio-linda
3
3
  // (c) 2013 Sho Hashimoto <hashimoto@shokai.org>
4
4
  // The MIT License
5
- var Linda=function(io,opts){var self=this;this.io=null;if(io===null||typeof io==="undefined"){this.io=(new RocketIO).connect()}else{this.io=io}this.opts=opts||{};this.TupleSpace=function(name){if(name===null||typeof name!=="string")name="__default__";this.name=name;this.linda=self;var space=this;var make_callback_id=function(){return new Date-0+"_"+Math.floor(Math.random()*1e6)};this.write=function(tuple,opts){if(tuple===null||typeof tuple!=="object")return;if(opts===null||typeof opts==="undefined")opts={};self.io.push("__linda_write",[space.name,tuple,opts])};this.read=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_read_callback_"+callback_id,callback);self.io.push("__linda_read",[space.name,tuple,callback_id])};this.take=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_take_callback_"+callback_id,callback);self.io.push("__linda_take",[space.name,tuple,callback_id])};this.watch=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.on("__linda_watch_callback_"+callback_id,callback);self.io.push("__linda_watch",[space.name,tuple,callback_id])}}};var RocketIO=function(opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.type=opts.type||null;this.session=opts.session||null;this.channel=null;if(typeof opts.channel!=="undefined"&&opts.channel!==null){this.channel=""+opts.channel}var setting={};this.io=null;var self=this;var ws_close_timer=null;self.on("__connect",function(session_id){self.session=session_id;self.io.push("__channel_id",self.channel);self.emit("connect")});this.connect=function(url){if(typeof url==="string"){$.getJSON(url+"/rocketio/settings",function(res){setting=res;connect_io()});return self}else{return connect_io()}};var connect_io=function(){self.io=function(){if(self.type==="comet")return;if(typeof WebSocketIO!=="function")return;var io=new WebSocketIO;if(typeof setting.websocket==="string")io.url=setting.websocket;io.session=self.session;return io.connect()}()||function(){if(typeof CometIO!=="function")return;var io=new CometIO;if(typeof setting.comet==="string")io.url=setting.comet;io.session=self.session;return io.connect()}();if(typeof self.io==="undefined"){setTimeout(function(){self.emit("error","WebSocketIO and CometIO are not available")},100);return self}if(self.io.url.match(/^ws:\/\/.+/))self.type="websocket";else if(self.io.url.match(/cometio/))self.type="comet";else self.type="unknown";self.io.on("*",function(event_name,args){if(event_name==="connect")event_name="__connect";self.emit(event_name,args)});ws_close_timer=setTimeout(function(){self.close();self.type="comet";connect_io()},3e3);self.once("connect",function(){if(ws_close_timer)clearTimeout(ws_close_timer);ws_close_timer=null});return self};this.close=function(){self.io.close()};this.push=function(type,data){self.io.push(type,data)}};var CometIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;var running=false;var self=this;var post_queue=[];var flush=function(){if(!running||post_queue.length<1)return;var post_data={json:JSON.stringify({session:self.session,events:post_queue})};$.ajax({url:self.url,data:post_data,success:function(data){},error:function(req,stat,e){self.emit("error","CometIO push error")},complete:function(e){},type:"POST",dataType:"json",timeout:1e4});post_queue=[]};setInterval(flush,1e3);this.push=function(type,data){if(!running||!self.session){self.emit("error","CometIO not connected");return}post_queue.push({type:type,data:data})};this.connect=function(){if(running)return self;self.on("__session_id",function(session){self.session=session;self.emit("connect",self.session)});running=true;get();return self};this.close=function(){running=false;self.removeListener("__session_id")};var get=function(){if(!running)return;$.ajax({url:self.url,data:{session:self.session},success:function(data_arr){if(data_arr!==null&&typeof data_arr=="object"&&!!data_arr.length){for(var i=0;i<data_arr.length;i++){var data=data_arr[i];if(data)self.emit(data.type,data.data)}}get()},error:function(req,stat,e){self.emit("error","CometIO get error");setTimeout(get,1e4)},complete:function(e){},type:"GET",dataType:"json",timeout:13e4})}};var WebSocketIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;this.websocket=null;this.connecting=false;var reconnect_timer_id=null;var running=false;var self=this;self.on("__session_id",function(session_id){self.session=session_id;self.emit("connect",self.session)});this.connect=function(){if(typeof WebSocket==="undefined"){self.emit("error","websocket not exists in this browser");return null}self.running=true;var url=self.session?self.url+"/session="+self.session:self.url;self.websocket=new WebSocket(url);self.websocket.onmessage=function(e){try{var data_=JSON.parse(e.data);self.emit(data_.type,data_.data)}catch(e){self.emit("error","WebSocketIO data parse error")}};self.websocket.onclose=function(){if(self.connecting){self.connecting=false;self.emit("disconnect")}if(self.running){reconnect_timer_id=setTimeout(self.connect,1e4)}};self.websocket.onopen=function(){self.connecting=true};return self};this.close=function(){clearTimeout(reconnect_timer_id);self.running=false;self.websocket.close()};this.push=function(type,data){if(!self.connecting){self.emit("error","websocket not connected");return}self.websocket.send(JSON.stringify({type:type,data:data,session:self.session}))}};var EventEmitter=function(){var self=this;this.apply=function(target,prefix){if(!prefix)prefix="";for(var func in self){if(self.hasOwnProperty(func)&&func!=="apply"){target[prefix+func]=this[func]}}};this.__events=new Array;this.on=function(type,listener,opts){if(typeof listener!=="function")return;var event_id=self.__events.length>0?1+self.__events[self.__events.length-1].id:0;var params={id:event_id,type:type,listener:listener};for(i in opts){if(!params[i])params[i]=opts[i]}self.__events.push(params);return event_id};this.once=function(type,listener){self.on(type,listener,{once:true})};this.emit=function(type,data){for(var i=0;i<self.__events.length;i++){var e=self.__events[i];switch(e.type){case type:e.listener(data);if(e.once)e.type=null;break;case"*":e.listener(type,data);if(e.once)e.type=null;break}}self.removeListener()};this.removeListener=function(id_or_type){for(var i=self.__events.length-1;i>=0;i--){var e=self.__events[i];switch(typeof id_or_type){case"number":if(e.id===id_or_type)self.__events.splice(i,1);break;case"string":case"object":if(e.type===id_or_type)self.__events.splice(i,1);break}}}};if(typeof module!=="undefined"&&typeof module.exports!=="undefined"){module.exports=EventEmitter}
5
+ var Linda=function(io,opts){var self=this;this.io=null;if(io===null||typeof io==="undefined"){this.io=(new RocketIO).connect()}else{this.io=io}this.opts=opts||{};this.TupleSpace=function(name){if(name===null||typeof name!=="string")name="__default__";this.name=name;this.linda=self;var space=this;var make_callback_id=function(){return new Date-0+"_"+Math.floor(Math.random()*1e6)};this.write=function(tuple,opts){if(tuple===null||typeof tuple!=="object")return;if(opts===null||typeof opts==="undefined")opts={};self.io.push("__linda_write",[space.name,tuple,opts])};this.read=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_read_callback_"+callback_id,callback);self.io.push("__linda_read",[space.name,tuple,callback_id])};this.take=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_take_callback_"+callback_id,callback);self.io.push("__linda_take",[space.name,tuple,callback_id])};this.watch=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.on("__linda_watch_callback_"+callback_id,callback);self.io.push("__linda_watch",[space.name,tuple,callback_id])}}};var RocketIO=function(opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.type=opts.type||null;this.session=opts.session||null;this.channel=null;if(typeof opts.channel!=="undefined"&&opts.channel!==null){this.channel=""+opts.channel}var setting={};this.io=null;var self=this;var ws_close_timer=null;self.on("__connect",function(session_id){self.session=session_id;self.io.push("__channel_id",self.channel);self.emit("connect")});this.connect=function(url){if(typeof url==="string"){$.getJSON(url+"/rocketio/settings",function(res){setting=res;connect_io()});return self}else{return connect_io()}};var connect_io=function(){self.io=function(){if(self.type==="comet")return;if(typeof WebSocketIO!=="function")return;var io=new WebSocketIO;if(typeof setting.websocket==="string")io.url=setting.websocket;io.session=self.session;return io.connect()}()||function(){if(typeof CometIO!=="function")return;var io=new CometIO;if(typeof setting.comet==="string")io.url=setting.comet;io.session=self.session;return io.connect()}();if(typeof self.io==="undefined"){setTimeout(function(){self.emit("error","WebSocketIO and CometIO are not available")},100);return self}if(self.io.url.match(/^ws:\/\/.+/))self.type="websocket";else if(self.io.url.match(/cometio/))self.type="comet";else self.type="unknown";self.io.on("*",function(event_name,args){if(event_name==="connect")event_name="__connect";self.emit(event_name,args)});ws_close_timer=setTimeout(function(){self.close();self.type="comet";connect_io()},3e3);self.once("connect",function(){if(ws_close_timer)clearTimeout(ws_close_timer);ws_close_timer=null});return self};this.close=function(){self.io.close()};this.push=function(type,data){self.io.push(type,data)}};var CometIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;var running=false;var self=this;var post_queue=[];var flush=function(){if(!running||post_queue.length<1)return;var post_data={json:JSON.stringify({session:self.session,events:post_queue})};$.ajax({url:self.url,data:post_data,success:function(data){},error:function(req,stat,e){self.emit("error","CometIO push error")},complete:function(e){},type:"POST",dataType:"json",timeout:1e4});post_queue=[]};setInterval(flush,1e3);this.push=function(type,data){if(!running||!self.session){self.emit("error","CometIO not connected");return}post_queue.push({type:type,data:data})};this.connect=function(){if(running)return self;self.on("__session_id",function(session){self.session=session;self.emit("connect",self.session)});running=true;get();return self};this.close=function(){running=false;self.removeListener("__session_id")};var get=function(){if(!running)return;$.ajax({url:self.url+"?"+(new Date-0),data:{session:self.session},success:function(data_arr){if(data_arr!==null&&typeof data_arr=="object"&&!!data_arr.length){for(var i=0;i<data_arr.length;i++){var data=data_arr[i];if(data)self.emit(data.type,data.data)}}get()},error:function(req,stat,e){self.emit("error","CometIO get error");setTimeout(get,1e4)},complete:function(e){},type:"GET",dataType:"json",timeout:13e4})}};var WebSocketIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;this.websocket=null;this.connecting=false;var reconnect_timer_id=null;var running=false;var self=this;self.on("__session_id",function(session_id){self.session=session_id;self.emit("connect",self.session)});this.connect=function(){if(typeof WebSocket==="undefined"){self.emit("error","websocket not exists in this browser");return null}self.running=true;var url=self.session?self.url+"/session="+self.session:self.url;self.websocket=new WebSocket(url);self.websocket.onmessage=function(e){var data_=null;try{data_=JSON.parse(e.data)}catch(e){self.emit("error","WebSocketIO data parse error")}if(!!data_)self.emit(data_.type,data_.data)};self.websocket.onclose=function(){if(self.connecting){self.connecting=false;self.emit("disconnect")}if(self.running){reconnect_timer_id=setTimeout(self.connect,1e4)}};self.websocket.onopen=function(){self.connecting=true};return self};this.close=function(){clearTimeout(reconnect_timer_id);self.running=false;self.websocket.close()};this.push=function(type,data){if(!self.connecting){self.emit("error","websocket not connected");return}self.websocket.send(JSON.stringify({type:type,data:data,session:self.session}))}};var EventEmitter=function(){var self=this;this.apply=function(target,prefix){if(!prefix)prefix="";for(var func in self){if(self.hasOwnProperty(func)&&func!=="apply"){target[prefix+func]=this[func]}}};this.__events=new Array;this.on=function(type,listener,opts){if(typeof listener!=="function")return;var event_id=self.__events.length>0?1+self.__events[self.__events.length-1].id:0;var params={id:event_id,type:type,listener:listener};for(i in opts){if(!params[i])params[i]=opts[i]}self.__events.push(params);return event_id};this.once=function(type,listener){self.on(type,listener,{once:true})};this.emit=function(type,data){for(var i=0;i<self.__events.length;i++){var e=self.__events[i];switch(e.type){case type:e.listener(data);if(e.once)e.type=null;break;case"*":e.listener(type,data);if(e.once)e.type=null;break}}self.removeListener()};this.removeListener=function(id_or_type){for(var i=self.__events.length-1;i>=0;i--){var e=self.__events[i];switch(typeof id_or_type){case"number":if(e.id===id_or_type)self.__events.splice(i,1);break;case"string":case"object":if(e.type===id_or_type)self.__events.splice(i,1);break}}}};if(typeof module!=="undefined"&&typeof module.exports!=="undefined"){module.exports=EventEmitter}
@@ -29,4 +29,5 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency "sinatra-rocketio"
30
30
  spec.add_dependency "event_emitter"
31
31
  spec.add_dependency "sinatra"
32
+ spec.add_dependency "args_parser"
32
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-rocketio-linda
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sho Hashimoto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-30 00:00:00.000000000 Z
11
+ date: 2013-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -150,10 +150,25 @@ dependencies:
150
150
  - - '>='
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: args_parser
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  description: Linda implementation on Sinatra RocketIO
154
168
  email:
155
169
  - hashimoto@shokai.org
156
- executables: []
170
+ executables:
171
+ - linda-rocketio
157
172
  extensions: []
158
173
  extra_rdoc_files: []
159
174
  files:
@@ -164,6 +179,7 @@ files:
164
179
  - LICENSE.txt
165
180
  - README.md
166
181
  - Rakefile
182
+ - bin/linda-rocketio
167
183
  - lib/js/linda.js
168
184
  - lib/sinatra-rocketio-linda/application.rb
169
185
  - lib/sinatra-rocketio-linda/helper.rb