isomorfeus-data 2.5.5 → 22.9.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,281 +0,0 @@
1
- module LucidFile
2
- module Mixin
3
- def self.included(base)
4
- base.extend(Isomorfeus::Data::GenericClassApi)
5
- base.include(Isomorfeus::Data::GenericInstanceApi)
6
- base.include(LucidI18n::Mixin)
7
-
8
- def changed!
9
- @_changed = true
10
- end
11
-
12
- def to_transport
13
- hash = {}
14
- hash['revision'] = revision if revision
15
- hash['data_uri'] = data_uri
16
- result = { @class_name => { @key => hash }}
17
- result.deep_merge!(@class_name => { @previous_key => { new_key: @key }}) if @previous_key
18
- result
19
- end
20
-
21
- if RUBY_ENGINE == 'opal'
22
- base.instance_exec do
23
- def files_path
24
- end
25
-
26
- def files_path=(_)
27
- end
28
- end
29
-
30
- def initialize(key: nil, content_type: nil, data: nil, data_uri: nil, revision: nil, _loading: false)
31
- @key = key.nil? ? SecureRandom.uuid : key.to_s
32
- @class_name = self.class.name
33
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
34
- _update_paths
35
- @_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
36
- @_changed = false
37
- @_reload = false
38
- loaded = loaded?
39
- @_data_uri_object = nil
40
- @_data_uri_string = nil
41
- if data_uri
42
- self.data_uri = data_uri
43
- elsif data
44
- self.data = data
45
- self.content_type = content_type if content_type
46
- else
47
- self._data('')
48
- self._content_type(content_type) if content_type
49
- end
50
- end
51
-
52
- def _load_from_store!
53
- @_changed = false
54
- @_reload = true
55
- end
56
-
57
- def _reload
58
- return unless @_reload
59
- @_reload = false
60
- d = Redux.fetch_by_path(*@_store_path)
61
- self._data_uri(d) if d
62
- end
63
-
64
- def _update_paths
65
- @_store_path = [:data_state, @class_name, @key, :data_uri]
66
- end
67
-
68
- def content_type
69
- _reload
70
- return @_data_uri_object.content_type if @_data_uri_object
71
- nil
72
- end
73
-
74
- def content_type=(c)
75
- changed!
76
- _content_type(c)
77
- end
78
-
79
- def _content_type(c)
80
- _reload
81
- @_data_uri_string = _format_data_uri(c, @_data_uri_object.data)
82
- @_data_uri_object = URI::Data.new(@_data_uri_string)
83
- c
84
- end
85
-
86
- def data
87
- _reload
88
- @_data_uri_object.data
89
- end
90
-
91
- def data=(d)
92
- changed!
93
- _data(d)
94
- end
95
-
96
- def _data(d)
97
- _reload
98
- @_data_uri_string = _format_data_uri(self.content_type, d)
99
- @_data_uri_object = URI::Data.new(@_data_uri_string)
100
- d
101
- end
102
-
103
- def data_uri
104
- _reload
105
- @_data_uri_string
106
- end
107
-
108
- def data_uri=(d)
109
- changed!
110
- _data_uri(d)
111
- end
112
-
113
- def _data_uri(d)
114
- _reload
115
- if d.class == URI::Data
116
- @_data_uri_string = _format_data_uri(d.content_type, d.data)
117
- @_data_uri_object = d
118
- else
119
- @_data_uri_string = d
120
- @_data_uri_object = URI::Data.new(d)
121
- end
122
- @_data_uri_string
123
- end
124
-
125
- def data_uri_object
126
- _reload
127
- @_data_uri_object
128
- end
129
-
130
- def _format_data_uri(c, d)
131
- "data:#{c};base64,#{Base64.encode64(d).chop}"
132
- end
133
- else # RUBY_ENGINE
134
- Isomorfeus.add_valid_file_class(base) unless base == LucidFile::Base
135
-
136
- base.instance_exec do
137
- def instance_from_transport(instance_data, _included_items_data)
138
- key = instance_data[self.name].keys.first
139
- revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
140
- data_uri = instance_data[self.name][key].key?('data_uri') ? instance_data[self.name][key]['data_uri'] : nil
141
- new(key: key, revision: revision, data_uri: data_uri)
142
- end
143
-
144
- def props_from_data(instance_data)
145
- key = instance_data[self.name].keys.first
146
- revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
147
- data_uri = instance_data[self.name][key].key?('data_uri') ? instance_data[self.name][key]['data_uri'] : nil
148
- LucidProps.new({ key: key, revision: revision, data_uri: data_uri })
149
- end
150
-
151
- def files_path
152
- @files_path ||= Isomorfeus.files_path
153
- end
154
-
155
- def files_path=(f)
156
- @files_path = f
157
- end
158
-
159
- def check_and_prepare_path(key:)
160
- Isomorfeus.raise_error(message: 'Invalid key (contains ".." or "\\")') if key.include?('..') || key.include?('\\')
161
- elements = key.split('/')
162
- Isomorfeus.raise_error(message: 'Invalid key (contains more than 2 slashes "/")') if elements.size > 3
163
- file = elements.pop
164
- if elements.size > 0
165
- dir_path = ::File.expand_path(::File.join(files_path, *elements))
166
- FileUtils.mkdir_p(dir_path) unless Dir.exist?(dir_path)
167
- ::File.join(dir_path, file)
168
- else
169
- FileUtils.mkdir_p(files_path) unless Dir.exist?(files_path)
170
- ::File.join(files_path, file)
171
- end
172
- end
173
-
174
- execute_create do
175
- self.save
176
- end
177
-
178
- execute_destroy do |key:|
179
- file = check_and_prepare_path(key: key)
180
- ::FileUtils.rm_f(file)
181
- true
182
- end
183
-
184
- execute_load do |key:|
185
- file = check_and_prepare_path(key: key)
186
- if File.exist?(file)
187
- d = ::File.binread(file)
188
- instance = self.new(key: key, data: d)
189
- instance
190
- else
191
- nil
192
- end
193
- end
194
-
195
- execute_save do
196
- file = self.class.check_and_prepare_path(key: self.key)
197
- ::File.binwrite(file, self.data)
198
- self
199
- end
200
- end
201
-
202
- def initialize(key: nil, content_type: nil, data: nil, data_uri: nil, revision: nil)
203
- @key = key.nil? ? SecureRandom.uuid : key.to_s
204
- @class_name = self.class.name
205
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
206
- @_revision = revision
207
- if data_uri
208
- self._data_uri(data_uri)
209
- else
210
- @_data = data
211
- @_content_type = content_type
212
- end
213
- @_changed = false
214
- end
215
-
216
- def _unchange!
217
- @_changed = false
218
- end
219
-
220
- def content_type
221
- @_content_type = @_data_uri_object.content_type if !@_content_type && @_data_uri_object
222
- @_content_type
223
- end
224
-
225
- def content_type=(c)
226
- changed!
227
- _content_type(c)
228
- end
229
-
230
- def _content_type(c)
231
- if @_data_uri_string
232
- @_data_uri_string = _format_data_uri(c, @_data_uri_object.data)
233
- @_data_uri_object = URI::Data.new(@_data_uri_string)
234
- end
235
- @_content_type = c
236
- end
237
-
238
- def data
239
- @_data = @_data_uri_object.data if !@_data && @_data_uri_object
240
- @_data
241
- end
242
-
243
- def data=(d)
244
- changed!
245
- @_data = d
246
- end
247
-
248
- def data_uri
249
- _data_uri(_format_data_uri(content_type, @_data)) if !@_data_uri_string && @_data
250
- @_data_uri_string
251
- end
252
-
253
- def data_uri=(d)
254
- changed!
255
- _data_uri(d)
256
- end
257
-
258
- def _data_uri(d)
259
- if d.class == URI::Data
260
- d = '' if d.nil?
261
- @_data_uri_string = _format_data_uri(d.content_type, d.data)
262
- @_data_uri_object = d
263
- else
264
- @_data_uri_string = d
265
- @_data_uri_object = URI::Data.new(d)
266
- end
267
- @_data_uri_string
268
- end
269
-
270
- def data_uri_object
271
- _data_uri(@_data) if !@_data_uri_object && @_data
272
- @_data_uri_object
273
- end
274
-
275
- def _format_data_uri(c, d)
276
- "data:#{c};base64,#{Base64.encode64(d).chop}"
277
- end
278
- end # RUBY_ENGINE
279
- end
280
- end
281
- end
@@ -1,10 +0,0 @@
1
- module LucidObject
2
- class Base
3
- def self.inherited(base)
4
- base.include LucidObject::Mixin
5
- if RUBY_ENGINE != 'opal'
6
- Isomorfeus.add_valid_data_class(base)
7
- end
8
- end
9
- end
10
- end
@@ -1,250 +0,0 @@
1
- module LucidObject
2
- module Mixin
3
- def self.included(base)
4
- base.include(Isomorfeus::Data::FieldSupport)
5
- base.extend(Isomorfeus::Data::GenericClassApi)
6
- base.include(Isomorfeus::Data::GenericInstanceApi)
7
- base.include(LucidI18n::Mixin)
8
-
9
- base.instance_exec do
10
- def escape_string(s)
11
- s.gsub(/([\\\&\:\(\)\[\]\{\}\!\"\~\^\|\<\>\=\*\?\+\-\s])/, '\\\\\1')
12
- end
13
- end
14
-
15
- def [](name)
16
- send(name)
17
- end
18
-
19
- def []=(name, val)
20
- send("#{name}=".to_sym, val)
21
- end
22
-
23
- def changed!
24
- @_changed = true
25
- end
26
-
27
- def to_transport
28
- hash = { 'fields' => _get_selected_fields }
29
- hash['revision'] = revision if revision
30
- result = { @class_name => { @key => hash }}
31
- result.deep_merge!(@class_name => { @previous_key => { new_key: @key }}) if @previous_key
32
- result
33
- end
34
-
35
- def included_items_to_transport
36
- f = fields
37
- data_hash = {}
38
- self.class.field_types.each do |field, type|
39
- if type == :object
40
- v = f[field]
41
- if v
42
- if v.is_a?(LucidObject::Mixin)
43
- data_hash.deep_merge!(v.to_transport)
44
- data_hash.deep_merge!(v.included_items_to_transport) if v.respond_to?(:included_items_to_transport)
45
- elsif v.is_a?(Array)
46
- v.each do |e|
47
- if e
48
- data_hash.deep_merge!(e.to_transport)
49
- data_hash.deep_merge!(e.included_items_to_transport) if e.respond_to?(:included_items_to_transport)
50
- end
51
- end
52
- end
53
- end
54
- end
55
- end
56
- data_hash
57
- end
58
-
59
- if RUBY_ENGINE == 'opal'
60
- def initialize(key: nil, revision: nil, fields: nil, _loading: false, attributes: nil)
61
- @key = key.nil? ? SecureRandom.uuid : key.to_s
62
- @class_name = self.class.name
63
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
64
- _update_paths
65
- @_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
66
- @_objects = {}
67
- @_changed = false
68
- loaded = loaded?
69
- fields = attributes if attributes
70
- if loaded
71
- raw_fields = Redux.fetch_by_path(*@_store_path)
72
- if `raw_fields === null`
73
- if fields
74
- _validate_fields(fields)
75
- @_changed_fields = fields
76
- else
77
- @_changed_fields = {}
78
- end
79
- elsif raw_fields && fields && ::Hash.new(raw_fields) != fields
80
- _validate_fields(fields)
81
- @_changed_fields = fields
82
- else
83
- @_changed_fields = {}
84
- end
85
- else
86
- fields = {} unless fields
87
- _validate_fields(fields) unless _loading
88
- @_changed_fields = fields
89
- end
90
- end
91
-
92
- def _load_from_store!
93
- @_changed_fields = {}
94
- @_objects = {}
95
- @_changed = false
96
- end
97
-
98
- def _update_paths
99
- @_store_path = [:data_state, @class_name, @key, :fields]
100
- end
101
-
102
- def each(&block)
103
- fields.each(&block)
104
- end
105
- else # RUBY_ENGINE
106
- Isomorfeus.add_valid_data_class(base) unless base == LucidObject::Base
107
-
108
- base.instance_exec do
109
- def _instance_from_transport_sid(sid, included_items_data, _already_loaded)
110
- o_class_name = sid[0]
111
- raise "invalid data class #{o_class_name}" unless Isomorfeus.valid_data_class_name?(o_class_name)
112
- o_class = Isomorfeus.cached_data_class(o_class_name)
113
- o_data = { o_class_name => { sid[1] => included_items_data[o_class_name][sid[1]] }}
114
- o_class.instance_from_transport(o_data, included_items_data, _already_loaded)
115
- end
116
-
117
- def instance_from_transport(instance_data, included_items_data, _already_loaded = {})
118
- key = instance_data[self.name].keys.first
119
- ref_s = gen_ref_s(key)
120
- return _already_loaded[ref_s] if _already_loaded.key?(ref_s)
121
- revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
122
- data_obj = new(key: key, revision: revision)
123
- _already_loaded[ref_s] = data_obj
124
- fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys(&:to_sym) : nil
125
- if fields
126
- field_types.each do |field, type|
127
- if type == :object
128
- sid_or_array = fields[field]
129
- if sid_or_array&.any?
130
- if sid_or_array[0].is_a? String
131
- fields[field] = _instance_from_transport_sid(sid_or_array, included_items_data, _already_loaded)
132
- elsif sid_or_array[0].is_a? Array
133
- v = sid_or_array.map { |e_sid| _instance_from_transport_sid(e_sid, included_items_data, _already_loaded) }
134
- v.compact!
135
- fields[field] = v
136
- end
137
- end
138
- end
139
- end
140
- end
141
- data_obj._validate_fields(fields)
142
- data_obj.fields.merge!(fields)
143
- data_obj
144
- end
145
-
146
- def props_from_data(instance_data)
147
- key = instance_data[self.name].keys.first
148
- revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
149
- fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys!(&:to_sym) : nil
150
- LucidProps.new({ key: key, revision: revision }.merge!(fields))
151
- end
152
-
153
- def object_accelerator
154
- @object_accelerator ||= Isomorfeus::Data::ObjectAccelerator.new(self)
155
- end
156
-
157
- def each(&block)
158
- if block_given?
159
- self.object_accelerator.each do |fields|
160
- block.call self.new(key: fields.delete(:key), fields: fields)
161
- end
162
- else
163
- Enumerator.new do |yielder|
164
- self.object_accelerator.each do |fields|
165
- yielder << self.new(key: fields.delete(:key), fields: fields)
166
- end
167
- end
168
- end
169
- end
170
- alias to_enum each
171
-
172
- def search(field = nil, val = nil, options = {}, query: nil)
173
- if field && !self.field_options[field]&.fetch(:index) == :yes
174
- raise "Can only search indexed #{self.field_types{field}}s, but #{self.field_types{field}} :#{field} is not indexed!"
175
- end
176
- objs = []
177
- query = query ? query : "#{field}:#{val}"
178
- self.object_accelerator.search_each(query, options) do |id|
179
- fields = self.object_accelerator.load_object(id: id)
180
- objs << self.new(key: fields.delete(:key), fields: fields)
181
- end
182
- objs
183
- end
184
-
185
- execute_create do |_already_saved: {}|
186
- self.key = SecureRandom.uuid unless self.key
187
- unless _already_saved.key?(self.ref_s)
188
- _already_saved[self.ref_s] = self
189
- self.class.object_accelerator.create_object(self.key, fields, _already_saved)
190
- end
191
- self
192
- end
193
-
194
- execute_destroy do |key:|
195
- self.object_accelerator.destroy_object(key.to_s)
196
- true
197
- end
198
-
199
- execute_load do |key:, _already_loaded: {}|
200
- ref_s = self.gen_ref_s(@key)
201
- if _already_loaded.key?(ref_s)
202
- _already_loaded[ref_s]
203
- else
204
- _already_loaded[ref_s] = true
205
- fields = self.object_accelerator.load_object(key: key.to_s, already_loaded: _already_loaded)
206
- obj = fields ? self.new(key: fields.delete(:key), fields: fields) : nil
207
- _already_loaded[ref_s] = obj
208
- end
209
- end
210
-
211
- execute_save do |_already_saved: {}|
212
- self.key = SecureRandom.uuid unless self.key
213
- unless _already_saved.key?(self.ref_s)
214
- _already_saved[self.ref_s] = true
215
- self.class.object_accelerator.save_object(self.key, fields, _already_saved)
216
- end
217
- self
218
- end
219
- end
220
-
221
- def initialize(key: nil, revision: nil, fields: nil, attributes: nil)
222
- @key = key.nil? ? SecureRandom.uuid : key.to_s
223
- @class_name = self.class.name
224
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
225
- @_revision = revision
226
- @_changed = false
227
- fields = attributes if attributes
228
- fields = {} unless fields
229
- _validate_fields(fields) if fields
230
- @_raw_fields = fields
231
- end
232
-
233
- def _unchange!
234
- @_changed = false
235
- end
236
-
237
- def each(&block)
238
- @_raw_fields.each(&block)
239
- end
240
-
241
- def reload
242
- new_instance = self.class.load(key: @key)
243
- @_raw_fields = new_instance.fields
244
- _unchange!
245
- self
246
- end
247
- end # RUBY_ENGINE
248
- end
249
- end
250
- end
@@ -1,10 +0,0 @@
1
- module LucidQuery
2
- class Base
3
- def self.inherited(base)
4
- base.include LucidQuery::Mixin
5
- if RUBY_ENGINE != 'opal'
6
- Isomorfeus.add_valid_data_class(base)
7
- end
8
- end
9
- end
10
- end
@@ -1,112 +0,0 @@
1
- module LucidQuery
2
- module Mixin
3
- def self.included(base)
4
- base.extend(LucidPropDeclaration::Mixin)
5
- base.include(LucidI18n::Mixin)
6
-
7
- if RUBY_ENGINE == 'opal'
8
- base.instance_exec do
9
- def _generate_auto_key(props_s)
10
- component = nil
11
- component_name = '_'
12
- %x{
13
- let c = Opal.Preact.active_component();
14
- if (typeof c?.__ruby_instance !== 'undefined') { component = c.__ruby_instance; }
15
- }
16
- component_name = component.class.name if component
17
- "#{component_name}:_:#{self.name}:#{props_s}"
18
- end
19
-
20
- def _should_return?(lqri, gak)
21
- if on_ssr?
22
- lqri.loaded?
23
- else on_browser?
24
- if Isomorfeus::TopLevel.hydrated
25
- if Isomorfeus::TopLevel.first_pass
26
- lqri.loaded?
27
- else
28
- lqri.loaded? && !gak
29
- end
30
- else
31
- lqri.loaded? && !gak
32
- end
33
- end
34
- end
35
-
36
- def execute(key: nil, **props)
37
- gak = key ? false : true
38
- key = _generate_auto_key(`JSON.stringify(props)`) unless key
39
-
40
- lqri = LucidQueryResult.new(key: key)
41
- return lqri if _should_return?(lqri, gak)
42
- props[:query_result_instance] = lqri
43
- promise_execute(key: gak ? nil : key, **props)
44
- lqri
45
- end
46
-
47
- def promise_execute(key: nil, **props)
48
- gak = key ? false : true
49
- key = _generate_auto_key(`JSON.stringify(props)`) unless key
50
-
51
- lqri = props.delete(:query_result_instance)
52
- lqri = LucidQueryResult.new(key: key) unless lqri
53
- return Promise.new.resolve(lqri) if _should_return?(lqri, gak)
54
-
55
- props.each_key do |prop_name|
56
- Isomorfeus.raise_error(message: "#{self.to_s} No such query prop declared: '#{prop_name}'!") unless declared_props.key?(prop_name)
57
- end
58
- props = validated_props(props)
59
- props[:key] = lqri.key
60
- Isomorfeus::Transport.promise_send_path( 'Isomorfeus::Data::Handler::Generic', self.name, :execute, props).then do |agent|
61
- agent.process do
62
- lqri._load_from_store!
63
- Isomorfeus.store.dispatch(type: 'DATA_LOAD', data: agent.full_response[:data])
64
- lqri
65
- end
66
- end
67
- end
68
-
69
- def execute_query(_); end
70
- end
71
- else
72
- unless base == LucidQuery::Base
73
- Isomorfeus.add_valid_data_class(base)
74
- end
75
-
76
- base.instance_exec do
77
- def promise_execute(**props)
78
- instance = self.execute(**props)
79
- result_promise = Promise.new
80
- result_promise.resolve(instance)
81
- result_promise
82
- end
83
-
84
- def execute(**props)
85
- key = props.delete(:key)
86
- result_set = self.new(**props).instance_exec(&@_query_block)
87
- LucidQueryResult.new(key: key, result_set: result_set)
88
- end
89
-
90
- def execute_query(&block)
91
- @_query_block = block
92
- end
93
- end
94
-
95
- attr_reader :props
96
-
97
- def initialize(**props_hash)
98
- props_hash = self.class.validated_props(props_hash)
99
- @props = LucidProps.new(props_hash)
100
- end
101
-
102
- def current_user
103
- Isomorfeus.current_user
104
- end
105
-
106
- def pub_sub_client
107
- Isomorfeus.pub_sub_client
108
- end
109
- end
110
- end
111
- end
112
- end