lissio 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ require 'browser'
12
+
13
+ module Lissio
14
+ DOM = Browser::DOM
15
+ CSS = Browser::CSS
16
+ end
17
+
18
+ require 'lissio/version'
19
+ require 'lissio/router'
20
+
21
+ require 'lissio/model'
22
+ require 'lissio/collection'
23
+ require 'lissio/adapter'
24
+
25
+ require 'lissio/component'
26
+ require 'lissio/application'
@@ -0,0 +1,45 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ module Lissio
12
+
13
+ class Adapter
14
+ attr_reader :for
15
+
16
+ def initialize(value)
17
+ if value.ancestors.include?(Model)
18
+ @type = :model
19
+ elsif value.ancestors.include?(Collection)
20
+ @type = :collection
21
+ else
22
+ raise ArgumentError, "the passed value isn't a Model or a Collection"
23
+ end
24
+
25
+ @for = value
26
+ end
27
+
28
+ def model?
29
+ @type == :model
30
+ end
31
+
32
+ def collection?
33
+ @type == :collection
34
+ end
35
+
36
+ def install
37
+ raise NotImplementedError, "install has not been implemented"
38
+ end
39
+
40
+ def uninstall
41
+ raise NotImplementedError, "uninstall has not been implemented"
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,268 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ require 'browser/location'
12
+ require 'browser/http'
13
+ require 'promise'
14
+
15
+ module Lissio; class Adapter
16
+
17
+ class REST < Adapter
18
+ def initialize(value, options = {}, &block)
19
+ super(value)
20
+
21
+ domain options[:domain] || $document.location.host
22
+ endpoint options[:endpoint] || endpoint_for(value)
23
+
24
+ if block.arity == 0
25
+ instance_exec(&block)
26
+ else
27
+ block.call(self)
28
+ end if block
29
+ end
30
+
31
+ def domain(value = nil)
32
+ value ? @domain = value : @domain
33
+ end
34
+
35
+ def endpoint(value = nil, &block)
36
+ if value
37
+ if Proc === value
38
+ @endpoint = value
39
+ elsif model?
40
+ @endpoint = proc {|method, instance, id|
41
+ case method
42
+ when :fetch
43
+ "#{value}/#{id}"
44
+
45
+ when :save, :create, :destroy
46
+ "#{value}/#{instance.id!}"
47
+ end
48
+ }
49
+ else
50
+ @endpoint = proc {|method, instance, desc|
51
+ if method == :fetch
52
+ "#{value}?#{desc.encode_uri}"
53
+ end
54
+ }
55
+ end
56
+ elsif block
57
+ @endpoint = block
58
+ else
59
+ @endpoint
60
+ end
61
+ end
62
+
63
+ def http(&block)
64
+ block ? @http = block : @http
65
+ end
66
+
67
+ def with(method, model, *args)
68
+ point = @endpoint.call(method, model, *args)
69
+
70
+ if Hash === point
71
+ point.first[0].to_s.downcase
72
+ end
73
+ end
74
+
75
+ def url(method, model, *args)
76
+ point = @endpoint.call(method, model, *args)
77
+
78
+ if Hash === point
79
+ point = point.first[1]
80
+ end
81
+
82
+ "//#{domain}#{point}"
83
+ end
84
+
85
+ def install
86
+ if model?
87
+ @for.instance_eval {
88
+ def self.fetch(*args)
89
+ promise = Promise.new
90
+ with = adapter.with(:fetch, nil, *args) || :get
91
+ url = adapter.url(:fetch, nil, *args)
92
+
93
+ Browser::HTTP.send(with, url) do |req|
94
+ req.on :success do |res|
95
+ promise.resolve(new(res.json, *args))
96
+ end
97
+
98
+ req.on :failure do |res|
99
+ promise.reject(res.status)
100
+ end
101
+
102
+ adapter.http.call(req) if adapter.http
103
+ end
104
+
105
+ promise
106
+ end
107
+
108
+ def save
109
+ promise = Promise.new
110
+ with = adapter.with(:save, self) || :put
111
+ url = adapter.url(:save, self)
112
+
113
+ Browser::HTTP.send(with, url, to_json) do |req|
114
+ req.on :success do |res|
115
+ promise.resolve(res.status)
116
+ end
117
+
118
+ req.on :failure do |res|
119
+ promise.reject(res.status)
120
+ end
121
+
122
+ adapter.http.call(req) if adapter.http
123
+ end
124
+
125
+ promise
126
+ end
127
+
128
+ def create
129
+ promise = Promise.new
130
+ with = adapter.with(:create, self) || :post
131
+ url = adapter.url(:create, self)
132
+
133
+ Browser::HTTP.send(with, url, to_json) do |req|
134
+ req.on :success do |res|
135
+ promise.resolve(res.status)
136
+ end
137
+
138
+ req.on :failure do |res|
139
+ promise.reject(res.status)
140
+ end
141
+
142
+ adapter.http.call(req) if adapter.http
143
+ end
144
+
145
+ promise
146
+ end
147
+
148
+ def destroy
149
+ promise = Promise.new
150
+ with = adapter.with(:destroy, self) || :delete
151
+ url = adapter.url(:destroy, self)
152
+
153
+ Browser::HTTP.send(with, url) do |req|
154
+ req.on :success do |res|
155
+ promise.resolve(res.status)
156
+ end
157
+
158
+ req.on :failure do |res|
159
+ promise.reject(res.status)
160
+ end
161
+
162
+ adapter.http.call(req) if adapter.http
163
+ end
164
+
165
+ promise
166
+ end
167
+
168
+ def reload
169
+ promise = Promise.new
170
+ fetched = fetched_with.empty? ? [id!] : fetched_with
171
+ with = adapter.with(:fetch, self, *fetched) || :get
172
+ url = adapter.url(:fetch, self, *fetched)
173
+
174
+ Browser::HTTP.send(with, url) do |req|
175
+ req.on :success do |res|
176
+ initialize(res.json, *fetched_with)
177
+
178
+ promise.resolve(self)
179
+ end
180
+
181
+ req.on :failure do |res|
182
+ promise.reject(res.status)
183
+ end
184
+
185
+ adapter.http.call(req) if adapter.http
186
+ end
187
+
188
+ promise
189
+ end
190
+ }
191
+ else
192
+ @for.instance_eval {
193
+ def self.fetch(*args, &block)
194
+ promise = Promise.new
195
+ with = adapter.with(:fetch, nil, *args)
196
+ url = adapter.url(:fetch, nil, *args)
197
+
198
+ Browser::HTTP.send(with, url) do |req|
199
+ req.on :success do |res|
200
+ promise.resolve(new(res.json, *args))
201
+ end
202
+
203
+ req.on :failure do |res|
204
+ promise.reject(res.status)
205
+ end
206
+
207
+ adapter.http.call(req) if adapter.http
208
+ end
209
+
210
+ promise
211
+ end
212
+
213
+ def reload(&block)
214
+ promise = Promise.new
215
+ with = adapter.with(:fetch, self, *fetched_with) || :get
216
+ url = adapter.url(:fetch, self, *fetched_with)
217
+
218
+ Browser::HTTP.send(with, url) do |req|
219
+ req.on :success do |res|
220
+ initialize(res.json, *fetched_with)
221
+ promise.resolve(self)
222
+ end
223
+
224
+ req.on :failure do |res|
225
+ promise.reject(res.status)
226
+ end
227
+
228
+ adapter.http.call(req) if adapter.http
229
+ end
230
+
231
+ promise
232
+ end
233
+ }
234
+ end
235
+ end
236
+
237
+ def uninstall
238
+ if model?
239
+ @for.instance_eval {
240
+ class << self
241
+ remove_method :fetch
242
+ end
243
+
244
+ remove_method :save
245
+ remove_method :create
246
+ remove_method :destroy
247
+ remove_method :reload
248
+ }
249
+ else
250
+ @for.instance_eval {
251
+ class << self
252
+ remove_method :fetch
253
+ end
254
+
255
+ remove_method :reload
256
+ }
257
+ end
258
+ end
259
+
260
+ private
261
+ def endpoint_for(klass)
262
+ klass.name.match(/([^:]+)$/) {|m|
263
+ "/#{m[1].downcase}"
264
+ }
265
+ end
266
+ end
267
+
268
+ end; end
@@ -0,0 +1,167 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ require 'browser/storage'
12
+ require 'browser/immediate'
13
+
14
+ module Lissio; class Adapter
15
+
16
+ class Storage < Adapter
17
+ def initialize(value, options = {}, &block)
18
+ super(value)
19
+
20
+ @autoincrement = []
21
+
22
+ if collection?
23
+ @model = options[:model] || value.model
24
+ @filter = options[:filter] if options[:filter]
25
+ end
26
+
27
+ if block.arity == 0
28
+ instance_exec(&block)
29
+ else
30
+ block.call(self)
31
+ end if block
32
+ end
33
+
34
+ def model(name = nil)
35
+ name ? @model = name : @model
36
+ end
37
+
38
+ def filter(&block)
39
+ block ? @filter = block : @filter
40
+ end
41
+
42
+ def autoincrement(field = nil)
43
+ if field
44
+ @autoincrement << field
45
+ else
46
+ @autoincrement
47
+ end
48
+ end
49
+
50
+ def autoincrement!(field, storage)
51
+ storage[[:__autoincrement__, field]] ||= 0
52
+ storage[[:__autoincrement__, field]] += 1
53
+ end
54
+
55
+ def install
56
+ if model?
57
+ @for.instance_eval {
58
+ def self.storage
59
+ $window.storage(name)
60
+ end
61
+
62
+ def storage
63
+ self.class.storage
64
+ end
65
+
66
+ def self.fetch(id, &block)
67
+ proc {
68
+ block.call(storage[id] || :error)
69
+ }.defer
70
+ end
71
+
72
+ def create(&block)
73
+ proc {
74
+ key = id!
75
+
76
+ if key && storage[key]
77
+ block.call(:error) if block
78
+ else
79
+ adapter.autoincrement.each {|name|
80
+ unless __send__ name
81
+ __send__ "#{name}=", adapter.autoincrement!(name, storage)
82
+ end
83
+ }
84
+
85
+ storage[id!] = self
86
+
87
+ block.call(:ok) if block
88
+ end
89
+ }.defer
90
+ end
91
+
92
+ def save(&block)
93
+ proc {
94
+ if storage[id!]
95
+ storage[id!] = self
96
+
97
+ block.call(:ok) if block
98
+ else
99
+ block.call(:error) if block
100
+ end
101
+ }.defer
102
+ end
103
+
104
+ def destroy(&block)
105
+ proc {
106
+ if storage[id!]
107
+ storage.delete(id!)
108
+
109
+ block.call(:ok) if block
110
+ else
111
+ block.call(:error) if block
112
+ end
113
+ }.defer
114
+ end
115
+ }
116
+ else
117
+ @for.instance_eval {
118
+ def self.storage
119
+ $window.storage(adapter.model.name)
120
+ end
121
+
122
+ def storage
123
+ self.class.storage
124
+ end
125
+
126
+ def self.fetch(*args, &block)
127
+ proc {
128
+ block.call new(storage.map {|name, value|
129
+ next if Array === name && name.length == 2 && name.first == :__autoincrement__
130
+
131
+ if !adapter.filter || adapter.filter.call(value, *args)
132
+ value
133
+ end
134
+ }.compact)
135
+ }.defer
136
+ end
137
+ }
138
+ end
139
+ end
140
+
141
+ def uninstall
142
+ if model?
143
+ @for.instance_eval {
144
+ class << self
145
+ remove_method :storage
146
+ remove_method :fetch
147
+ end
148
+
149
+ remove_method :storage
150
+ remove_method :create
151
+ remove_method :save
152
+ remove_method :destroy
153
+ }
154
+ else
155
+ @for.instance_eval {
156
+ class << self
157
+ remove_method :storage
158
+ remove_method :fetch
159
+ end
160
+
161
+ remove_method :storage
162
+ }
163
+ end
164
+ end
165
+ end
166
+
167
+ end; end