isomorfeus-data 1.0.0.delta11

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,169 @@
1
+ module LucidHash
2
+ module Mixin
3
+ def self.included(base)
4
+ if RUBY_ENGINE != 'opal'
5
+ Isomorfeus.add_valid_hash_class(base) unless base == LucidHash::Base
6
+ end
7
+
8
+ base.extend(Isomorfeus::Data::PropDeclaration)
9
+
10
+ def to_gid
11
+ [@class_name, @props_json]
12
+ end
13
+
14
+ def to_transport(inline: false)
15
+ if inline
16
+ { '_inline' => { @props_json => to_h }}
17
+ else
18
+ { 'hashes' => { @class_name => { @props_json => to_h }}}
19
+ end
20
+ end
21
+
22
+ base.instance_exec do
23
+ def on_load_block
24
+ @on_load_block
25
+ end
26
+
27
+ def query_block
28
+ @query_block
29
+ end
30
+ end
31
+
32
+ if RUBY_ENGINE == 'opal'
33
+ def initialize(store_path: nil, validated_props: nil)
34
+ @props = validated_props
35
+ @props_json = @props.to_json if @props
36
+ @class_name = self.class.name
37
+ @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
38
+ @store_path = store_path ? store_path : [:data_state, :hashes, @class_name]
39
+ end
40
+
41
+ def loaded?
42
+ Redux.fetch_by_path(*(@store_path + [@props_json])) ? true : false
43
+ end
44
+
45
+ def [](name)
46
+ path = @store_path + [@props_json, name]
47
+ Redux.register_used_store_path(*path)
48
+ result = Redux.fetch_by_path(*path)
49
+ result ? result : nil
50
+ end
51
+
52
+ def key?(name)
53
+ path = @store_path + [@props_json, name]
54
+ Redux.register_used_store_path(*path)
55
+ Redux.fetch_by_path(*path) ? true : false
56
+ end
57
+
58
+ def method_missing(method_name, *args, &block)
59
+ path = @store_path + [@props_json]
60
+ Redux.register_used_store_path(*path)
61
+ raw_hash = Redux.fetch_by_path(*path)
62
+ if raw_hash
63
+ Hash.new(raw_hash).send(method_name, *args, &block)
64
+ else
65
+ Hash.new.send(method_name, *args, &block)
66
+ end
67
+ end
68
+
69
+ def to_h
70
+ raw_hash = Redux.fetch_by_path(*(@store_path + [@props_json]))
71
+ raw_hash ? Hash.new(raw_hash) : {}
72
+ end
73
+
74
+ base.instance_exec do
75
+ def load(props_hash = {})
76
+ validate_props(props_hash)
77
+ instance = self.new(validated_props: Isomorfeus::Data::Props.new(props_hash))
78
+ self.promise_load(props_hash, instance) unless instance.loaded?
79
+ instance
80
+ end
81
+
82
+ def on_load(&block)
83
+ end
84
+
85
+ def promise_load(props_hash = {}, instance = nil)
86
+ unless instance
87
+ validate_props(props_hash)
88
+ instance = self.new(validated_props: Isomorfeus::Data::Props.new(props_hash))
89
+ end
90
+
91
+ props_json = instance.instance_variable_get(:@props_json)
92
+
93
+ Redux.register_used_store_path(:data_state, :hashes, self.name, props_json)
94
+
95
+ Isomorfeus::Transport.promise_send_path('Isomorfeus::Data::Handler::HashLoadHandler', self.name, props_json).then do |response|
96
+ if response[:agent_response].key?(:error)
97
+ `console.error(#{response[:agent_response][:error].to_n})`
98
+ raise response[:agent_response][:error]
99
+ end
100
+ Isomorfeus.store.dispatch(type: 'DATA_LOAD', data: response[:full_response][:data])
101
+ instance
102
+ end
103
+ end
104
+
105
+ def query
106
+ nil
107
+ end
108
+ end
109
+ else # RUBY_ENGINE
110
+ unless base == LucidHash::Base
111
+ base.prop :pub_sub_client, default: nil
112
+ base.prop :session_id, default: nil
113
+ base.prop :current_user, default: nil
114
+ end
115
+
116
+ def initialize(store_path: nil, validated_props: nil)
117
+ @props = validated_props
118
+ @props_json = @props.to_json if @props
119
+ @loaded = false
120
+ @class_name = self.class.name
121
+ @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
122
+ end
123
+
124
+ def loaded?
125
+ @loaded
126
+ end
127
+
128
+ def [](name)
129
+ @data_hash[name]
130
+ end
131
+
132
+ def method_missing(method_name, *args, &block)
133
+ @data_hash.send(method_name, *args, &block)
134
+ end
135
+
136
+ def to_h
137
+ @data_hash.to_h.transform_keys { |k| k.to_s }
138
+ end
139
+
140
+ base.instance_exec do
141
+ def load(props_hash = {})
142
+ validate_props(props_hash)
143
+ instance = self.new(validated_props: Isomorfeus::Data::Props.new(props_hash))
144
+ instance.instance_exec do
145
+ @data_hash = self.class.query_block.call(props_hash)
146
+ @loaded = true
147
+ end
148
+ instance
149
+ end
150
+
151
+ def on_load(&block)
152
+ @on_load_block = block
153
+ end
154
+
155
+ def promise_load(props_hash = {}, instance = nil)
156
+ instance = self.load(props_hash)
157
+ result_promise = Promise.new
158
+ result_promise.resolve(instance)
159
+ result_promise
160
+ end
161
+
162
+ def query(&block)
163
+ @query_block = block
164
+ end
165
+ end
166
+ end # RUBY_ENGINE
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,5 @@
1
+ module LucidNode
2
+ class Base
3
+ include LucidNode::Mixin
4
+ end
5
+ end
@@ -0,0 +1,201 @@
1
+ # api
2
+ # class:
3
+ # attribute :my_attribute, server_only: false|true, class: ClassName, is_a: ClassName, default: value, validate: block
4
+ # my_node.class.attributes
5
+ # my_node.class.attribute_options
6
+ # instance:
7
+ # my_node.my_attribute
8
+ # my_node.my_attribute = value
9
+ # my_node.changed_attributes
10
+ # my_node.changed?
11
+ # my_node.loaded?
12
+ # my_node.valid_attribute?(attr, value)
13
+ # my_node.validate_attribute!(attr, value)
14
+ # my_node.to_transport
15
+
16
+ module LucidNode
17
+ module Mixin
18
+ def self.included(base)
19
+ attr_reader :id
20
+
21
+ def ==(other_node)
22
+ eql?(other_node)
23
+ end
24
+
25
+ def eql?(other_node)
26
+ @id == other_node.id && @class_name == other_node.instance_variable_get(:@class_name)
27
+ end
28
+
29
+ def id=(new_id)
30
+ new_id = new_id.to_s
31
+ changed_attributes[:id] = new_id
32
+ @id = new_id
33
+ end
34
+
35
+ def changed_attributes
36
+ @changed_attributes ||= Isomorfeus::Data::Props.new({})
37
+ end
38
+
39
+ def changed?
40
+ changed_attributes.any?
41
+ end
42
+
43
+ def to_cid
44
+ [@class_name, @id]
45
+ end
46
+
47
+ def valid_attribute?(attr, value)
48
+ begin
49
+ validate_attribute!(attr, value)
50
+ true
51
+ rescue
52
+ false
53
+ end
54
+ end
55
+
56
+ def validate_attribute!(attr, value)
57
+ attr_options = self.class.attribute_options[attr]
58
+
59
+ if attr_options.key?(:class)
60
+ raise "#{attr}: value class is not #{attr_options[:class]}!" unless value.class == attr_options[:class]
61
+ end
62
+
63
+ if attr_options.key?(:is_a)
64
+ raise "#{attr}: value is not a #{attr_options[:class]}!" unless value.is_a?(attr_options[:is_a])
65
+ end
66
+
67
+ if attr_options.key?(:validate)
68
+ raise "#{attr}: value failed validation!" unless attr_options[:validate].call(value)
69
+ end
70
+ end
71
+
72
+ base.instance_exec do
73
+ def query_block
74
+ @query_block
75
+ end
76
+
77
+ def attributes
78
+ attribute_options.keys
79
+ end
80
+
81
+ def attribute_options
82
+ @attribute_options ||= { id: {} }
83
+ end
84
+
85
+ def node_from_cid(cid)
86
+ Isomorfeus.cached_node_class(cid[0]).new({id: cid[1]})
87
+ end
88
+ end
89
+
90
+ if RUBY_ENGINE == 'opal'
91
+ def initialize(attributes_hash = nil)
92
+ attributes_hash = {} unless attributes_hash
93
+ self.class.attributes.each do |attr|
94
+ if attributes_hash.key?(attr)
95
+ validate_attribute!(attr, attributes_hash[attr])
96
+ changed_attributes[attr] = attributes_hash[attr]
97
+ elsif self.class.attribute_options[attr].key?(:default)
98
+ changed_attributes[attr] = self.class.attribute_options[attr][:default]
99
+ end
100
+ end
101
+ @id = attributes_hash[:id].to_s
102
+ @id = "new_#{object_id}" if @id.empty?
103
+ @class_name = self.class.name
104
+ @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
105
+ end
106
+
107
+ def loaded?
108
+ Redux.fetch_by_path(:data_state, :node, @class_name, :instances, @id) ? true : false
109
+ end
110
+
111
+ def to_transport(*args)
112
+ Redux.register_used_store_path(:data_state, :nodes, @class_name, @id)
113
+ final_attributes = {}
114
+ self.class.attributes.each do |attr|
115
+ next if attr == :id
116
+ final_attributes[attr] = send(attr)
117
+ end
118
+ { 'nodes' => { @class_name => { @id => { attributes: final_attributes }}}}
119
+ end
120
+
121
+ base.instance_exec do
122
+ def attribute(name, options = {})
123
+ attribute_options[name] = options
124
+
125
+ define_method(name) do
126
+ Redux.register_used_store_path(:data_state, :nodes, @class_name, @id, :attributes, name)
127
+ if changed_attributes.key?(name)
128
+ changed_attributes[name]
129
+ else
130
+ Redux.fetch_by_path(:data_state, :nodes, @class_name, @id, :attributes, name)
131
+ end
132
+ end
133
+
134
+ define_method("#{name}=") do |arg|
135
+ validate_attribute!(name, arg)
136
+ Redux.register_used_store_path(:data_state, :nodes, @class_name, @id, :attributes, name)
137
+ changed_attributes.set(name, arg)
138
+ end
139
+ end
140
+
141
+ def query
142
+ nil
143
+ end
144
+ end
145
+ else # RUBY_ENGINE
146
+ def initialize(attributes_hash = nil)
147
+ attributes_hash = {} unless attributes_hash
148
+ given_attributes = Isomorfeus::Data::Props.new(attributes_hash)
149
+ valid_attributes_hash = {}
150
+ self.class.attributes.each do |attr|
151
+ if given_attributes.key?(attr)
152
+ validate_attribute!(attr, given_attributes[attr])
153
+ valid_attributes_hash[attr] = given_attributes[attr]
154
+ elsif self.class.attribute_options[attr].key?(:default)
155
+ valid_attributes_hash[attr] = self.class.attribute_options[attr][:default]
156
+ end
157
+ end
158
+ @attributes = Isomorfeus::Data::Props.new(valid_attributes_hash)
159
+ @id = @attributes[:id].to_s
160
+ @id = "new_#{object_id}" if @id.empty?
161
+ @class_name = self.class.name
162
+ @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
163
+ end
164
+
165
+ def loaded?
166
+ true
167
+ end
168
+
169
+ def to_transport(*args)
170
+ final_attributes = {}
171
+ self.class.attributes.each do |attr|
172
+ next if attr == :id
173
+ include_attribute = @attributes.key?(attr)
174
+ include_attribute = !self.class.attribute_options[attr][:server_only] if self.class.attribute_options[attr].key?(:server_only)
175
+ final_attributes[attr.to_s] = send(attr) if include_attribute
176
+ end
177
+ { 'nodes' => { @class_name => { @id => { 'attributes' => final_attributes }}}}
178
+ end
179
+
180
+ base.instance_exec do
181
+ def attribute(name, options = {})
182
+ attribute_options[name] = options
183
+
184
+ define_method(name) do
185
+ if changed_attributes.key?(name)
186
+ changed_attributes[name]
187
+ else
188
+ @attributes[name]
189
+ end
190
+ end
191
+
192
+ define_method("#{name}=") do |arg|
193
+ validate_attribute!(name, arg)
194
+ changed_attributes.set(name, arg)
195
+ end
196
+ end
197
+ end
198
+ end # RUBY_ENGINE
199
+ end
200
+ end
201
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: isomorfeus-data
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.delta11
5
+ platform: ruby
6
+ authors:
7
+ - Jan Biedermann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.8.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.8.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: opal
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.11.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.11.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: opal-activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.3.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.3.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: opal-autoloader
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.1.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.1.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: isomorfeus-react
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 16.9.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 16.9.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: isomorfeus-redux
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 4.0.11
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 4.0.11
111
+ - !ruby/object:Gem::Dependency
112
+ name: isomorfeus-transport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.0.0.delta11
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 1.0.0.delta11
125
+ description: Write Browser Apps that transparently access server side data with Graphs
126
+ and Collections with ease.
127
+ email: jan@kursator.de
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - LICENSE
133
+ - README.md
134
+ - lib/isomorfeus-data.rb
135
+ - lib/isomorfeus/data/config.rb
136
+ - lib/isomorfeus/data/core_ext/hash/deep_merge.rb
137
+ - lib/isomorfeus/data/handler/array_load_handler.rb
138
+ - lib/isomorfeus/data/handler/collection_load_handler.rb
139
+ - lib/isomorfeus/data/handler/graph_load_handler.rb
140
+ - lib/isomorfeus/data/handler/hash_load_handler.rb
141
+ - lib/isomorfeus/data/prop_declaration.rb
142
+ - lib/isomorfeus/data/props.rb
143
+ - lib/isomorfeus/data/reducer.rb
144
+ - lib/isomorfeus/data/version.rb
145
+ - lib/lucid_array/base.rb
146
+ - lib/lucid_array/mixin.rb
147
+ - lib/lucid_collection/base.rb
148
+ - lib/lucid_collection/mixin.rb
149
+ - lib/lucid_edge/base.rb
150
+ - lib/lucid_edge/mixin.rb
151
+ - lib/lucid_graph/base.rb
152
+ - lib/lucid_graph/mixin.rb
153
+ - lib/lucid_hash/base.rb
154
+ - lib/lucid_hash/mixin.rb
155
+ - lib/lucid_node/base.rb
156
+ - lib/lucid_node/mixin.rb
157
+ homepage: http://isomorfeus.com
158
+ licenses:
159
+ - MIT
160
+ metadata: {}
161
+ post_install_message:
162
+ rdoc_options: []
163
+ require_paths:
164
+ - lib
165
+ required_ruby_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ required_rubygems_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">"
173
+ - !ruby/object:Gem::Version
174
+ version: 1.3.1
175
+ requirements: []
176
+ rubygems_version: 3.0.3
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: Compose Graphs and Collections of data just as needed for a isomorfeus app.
180
+ test_files: []