lissio 0.1.0.beta1

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.
@@ -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