interfacets 0.9.9 → 0.9.99
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.
- checksums.yaml +4 -4
- data/.tmp +5 -0
- data/Rakefile +4 -0
- data/lib/interfacets/client/assets.rb +1 -0
- data/lib/interfacets/client/bus.rb +5 -1
- data/lib/interfacets/client/channels/api.rb +10 -3
- data/lib/interfacets/client/registry.rb +9 -70
- data/lib/interfacets/client/utils/mruby_patches.rb +1 -1
- data/lib/interfacets/client/utils/open_struct.rb +90 -77
- data/lib/interfacets/component_registry.rb +115 -0
- data/lib/interfacets/component_schema_parser.rb +84 -0
- data/lib/interfacets/server/api.rb +5 -25
- data/lib/interfacets/server/assets/facet.rb +5 -3
- data/lib/interfacets/server/assets.rb +13 -7
- data/lib/interfacets/server/basic_router.rb +15 -10
- data/lib/interfacets/server/bus.rb +4 -9
- data/lib/interfacets/server/config.rb +1 -1
- data/lib/interfacets/server/registry.rb +23 -184
- data/lib/interfacets/shared/basic_routable.rb +45 -0
- data/lib/interfacets/shared/entities/bus.rb +41 -29
- data/lib/interfacets/shared/entities/specs/handlers.rb +16 -0
- data/lib/interfacets/shared/entities/specs.rb +46 -9
- data/lib/interfacets/shared/entity.rb +23 -99
- data/lib/interfacets/shared/entity_dsl.rb +154 -0
- data/lib/interfacets/shared/facet.rb +200 -0
- data/lib/interfacets/shared/generated_store.rb +6 -2
- data/lib/interfacets/shared/utils.rb +1 -1
- data/lib/interfacets/shared/validations.rb +5 -1
- data/lib/interfacets/{client → shared}/view.rb +33 -6
- data/lib/interfacets/test/component_registry.rb +63 -0
- data/lib/interfacets/test/js/inline_bus.rb +21 -12
- data/lib/interfacets/test/js/nodo_bus.rb +18 -1
- data/lib/interfacets/test/js/receivers/api.rb +14 -3
- data/lib/interfacets/test/js/receivers/react/node/xml_parser.rb +75 -0
- data/lib/interfacets/test/js/receivers/react/node.rb +29 -63
- data/lib/interfacets/test/js/receivers/react.rb +4 -3
- data/lib/interfacets/test/js/receivers/timer.rb +77 -0
- data/lib/interfacets/test/js/receivers/url.rb +5 -0
- data/lib/interfacets/test/standard_elements.yml +173 -0
- data/lib/interfacets/test/{browser.rb → ui_simulator.rb} +18 -6
- data/lib/interfacets/test/validation_engine.rb +151 -0
- data/lib/interfacets/test.rb +0 -4
- data/lib/interfacets/version.rb +1 -1
- data/lib/interfacets.rb +3 -0
- metadata +29 -18
- data/lib/interfacets/client/facet.rb +0 -26
- data/lib/interfacets/client/facet2.rb +0 -15
- data/lib/interfacets/client/facets/attributes/accessor.rb +0 -28
- data/lib/interfacets/client/facets/attributes/association.rb +0 -50
- data/lib/interfacets/client/facets/attributes/bind.rb +0 -25
- data/lib/interfacets/client/facets/attributes/collection.rb +0 -47
- data/lib/interfacets/client/facets/attributes/readonly.rb +0 -19
- data/lib/interfacets/client/facets/deserializer.rb +0 -30
- data/lib/interfacets/client/facets/schema/deserializer.rb +0 -63
- data/lib/interfacets/client/facets/schema.rb +0 -63
- data/lib/interfacets/client/facets/serializer.rb +0 -18
- data/lib/interfacets/server/basic_routable.rb +0 -40
- data/lib/interfacets/server/facet.rb +0 -51
- data/lib/interfacets/shared/entity_collection.rb +0 -88
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e7e08a925c26ef4b7ee1e2aa2bbdcd716388b6f3aaa22f8d5bf9e7a51a76cee
|
|
4
|
+
data.tar.gz: 222f5f5f8129c913d19ce4f6d6331f820ad643a6198f35f63ce0b9df2743e059
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 68e278e17a2b033f8dc0ee6941f80a76d6ddb6bfeb0d7c79267ed24150d48b6d7e1ff54bda300cb0db5b4caa238632be5efe8b228fa018362482b7d8cea1264a
|
|
7
|
+
data.tar.gz: 3ca6b351b7089d7e9d99e513a282c937cea531a813a1ebfdfd35a514b2f34f95187f19c63ac57e1a5691c61d111f67f2dbae0b614c490c252a2f76b3dcc5006a
|
data/.tmp
ADDED
data/Rakefile
CHANGED
|
@@ -48,7 +48,11 @@ module Interfacets
|
|
|
48
48
|
channel.handle(
|
|
49
49
|
entity: @entity,
|
|
50
50
|
event: event.fetch("payload"),
|
|
51
|
-
build_entity: ->(name) {
|
|
51
|
+
build_entity: ->(name, id) {
|
|
52
|
+
@entity = registry.build(name, id)
|
|
53
|
+
channel_index.values.each { _1.prepare(@entity) }
|
|
54
|
+
@entity
|
|
55
|
+
}
|
|
52
56
|
)
|
|
53
57
|
|
|
54
58
|
channel_index.values.each { _1.prepare(entity) }
|
|
@@ -22,7 +22,7 @@ module Interfacets
|
|
|
22
22
|
}
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def submit(meth)
|
|
25
|
+
def submit(meth, nesting: )
|
|
26
26
|
raise("only one submission per action") if request
|
|
27
27
|
|
|
28
28
|
System.logger.debug("submitting #{meth}")
|
|
@@ -46,7 +46,7 @@ module Interfacets
|
|
|
46
46
|
.serialize(
|
|
47
47
|
to: "server" ,
|
|
48
48
|
action: meth,
|
|
49
|
-
nesting:
|
|
49
|
+
nesting:
|
|
50
50
|
)
|
|
51
51
|
)
|
|
52
52
|
},
|
|
@@ -81,7 +81,14 @@ module Interfacets
|
|
|
81
81
|
|
|
82
82
|
def handle(event:, entity:, build_entity:)
|
|
83
83
|
facet_name = event.fetch("facet")
|
|
84
|
-
|
|
84
|
+
id = event.dig(
|
|
85
|
+
"payload",
|
|
86
|
+
"payload",
|
|
87
|
+
"attributes",
|
|
88
|
+
"internal_entity_id"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
entity = build_entity.(facet_name, id)
|
|
85
92
|
|
|
86
93
|
Shared::Entities::Bus
|
|
87
94
|
.new(entity:)
|
|
@@ -3,82 +3,21 @@
|
|
|
3
3
|
module Interfacets
|
|
4
4
|
module Client
|
|
5
5
|
class Registry
|
|
6
|
-
def
|
|
7
|
-
|
|
6
|
+
def initialize
|
|
7
|
+
@stores = {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def build(name, id)
|
|
11
|
+
entity = Object.const_get(name).client_entity_class
|
|
12
|
+
|
|
13
|
+
@stores[id] ||= entity.store.new
|
|
8
14
|
|
|
9
15
|
entity.new(
|
|
10
|
-
store:
|
|
16
|
+
store: @stores[id],
|
|
11
17
|
parent: nil,
|
|
12
18
|
nesting: ["root"]
|
|
13
19
|
)
|
|
14
20
|
end
|
|
15
|
-
|
|
16
|
-
def register(schema, namespace: "Things")
|
|
17
|
-
schema.each do |name, schema|
|
|
18
|
-
next if registry.key?(name)
|
|
19
|
-
|
|
20
|
-
shared = Class.new(Shared::Entity) do
|
|
21
|
-
schema.fetch("shared").each { class_exec(&eval(_1)) }
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
view = Class.new(View) do
|
|
25
|
-
schema.fetch("view").each { view(&eval(_1)) }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
entity = Class.new(Shared::Entity) do
|
|
29
|
-
define_singleton_method(:view) { view }
|
|
30
|
-
self.manifest = shared
|
|
31
|
-
|
|
32
|
-
schema.fetch("shared").each { class_exec(&eval(_1)) }
|
|
33
|
-
schema.fetch("client").each { class_exec(&eval(_1)) }
|
|
34
|
-
|
|
35
|
-
actions.each do |name, spec|
|
|
36
|
-
if name.start_with?("after_")
|
|
37
|
-
define_method(name) {}
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
store = Shared::GeneratedStore.construct(entity)
|
|
43
|
-
|
|
44
|
-
mod = set_const(
|
|
45
|
-
[
|
|
46
|
-
namespace,
|
|
47
|
-
name.split("::"),
|
|
48
|
-
].flatten,
|
|
49
|
-
Module.new
|
|
50
|
-
)
|
|
51
|
-
entity.define_singleton_method(:facet_name) { name }
|
|
52
|
-
mod.const_set("Entity", entity)
|
|
53
|
-
entity.const_set("Shared", shared)
|
|
54
|
-
entity.const_set("View", view)
|
|
55
|
-
|
|
56
|
-
registry[name] = { entity:, store: }
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
def set_const(mods, klass)
|
|
63
|
-
|
|
64
|
-
namespace = Object
|
|
65
|
-
|
|
66
|
-
mods[0..-1].each do |mod|
|
|
67
|
-
namespace = (
|
|
68
|
-
if namespace.const_defined?(mod, false)
|
|
69
|
-
namespace.const_get(mod)
|
|
70
|
-
else
|
|
71
|
-
namespace.const_set(mod, Module.new)
|
|
72
|
-
end
|
|
73
|
-
)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
namespace.const_set(mods.last, klass)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def registry
|
|
80
|
-
@registry ||= {}
|
|
81
|
-
end
|
|
82
21
|
end
|
|
83
22
|
end
|
|
84
23
|
end
|
|
@@ -2,101 +2,114 @@
|
|
|
2
2
|
|
|
3
3
|
# copied from github
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@table[k] = v
|
|
12
|
-
new_ostruct_member(k)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
5
|
+
required = (
|
|
6
|
+
begin
|
|
7
|
+
require "ostruct"
|
|
8
|
+
true
|
|
9
|
+
rescue
|
|
10
|
+
false
|
|
15
11
|
end
|
|
12
|
+
)
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
super
|
|
19
|
-
@table = @table.dup
|
|
20
|
-
@table.each_key{|key| new_ostruct_member(key)}
|
|
21
|
-
end
|
|
14
|
+
unless required
|
|
22
15
|
|
|
23
|
-
def to_h
|
|
24
|
-
@table.dup
|
|
25
|
-
end
|
|
26
16
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
class OpenStruct
|
|
18
|
+
def initialize hash=nil
|
|
19
|
+
@table = {}
|
|
20
|
+
if hash
|
|
21
|
+
hash.each do |k,v|
|
|
22
|
+
k = k.to_sym
|
|
23
|
+
@table[k] = v
|
|
24
|
+
new_ostruct_member(k)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
define_singleton_method("#{name}=".to_sym){ |x| @table[name] = x }
|
|
29
|
+
def initialize_copy orig
|
|
30
|
+
super
|
|
31
|
+
@table = @table.dup
|
|
32
|
+
@table.each_key{|key| new_ostruct_member(key)}
|
|
37
33
|
end
|
|
38
|
-
name
|
|
39
|
-
end
|
|
40
|
-
protected :new_ostruct_member
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
ary = []
|
|
45
|
-
@table.each do |k,v|
|
|
46
|
-
ary << "#{k}=#{v}"
|
|
35
|
+
def to_h
|
|
36
|
+
@table.dup
|
|
47
37
|
end
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
38
|
+
|
|
39
|
+
def each_pair
|
|
40
|
+
return to_enum __method__ unless block_given?
|
|
41
|
+
@table.each{|p| yield p}
|
|
51
42
|
end
|
|
52
|
-
str << '>'
|
|
53
|
-
end
|
|
54
|
-
alias :to_s :inspect
|
|
55
43
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
def new_ostruct_member name
|
|
45
|
+
name = name.to_sym
|
|
46
|
+
unless respond_to?(name)
|
|
47
|
+
define_singleton_method(name){ @table[name] }
|
|
48
|
+
define_singleton_method("#{name}=".to_sym){ |x| @table[name] = x }
|
|
49
|
+
end
|
|
50
|
+
name
|
|
51
|
+
end
|
|
52
|
+
protected :new_ostruct_member
|
|
61
53
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
def inspect
|
|
55
|
+
str = "#<#{self.class}"
|
|
56
|
+
ary = []
|
|
57
|
+
@table.each do |k,v|
|
|
58
|
+
ary << "#{k}=#{v}"
|
|
59
|
+
end
|
|
60
|
+
if 0 < ary.length
|
|
61
|
+
str << ' '
|
|
62
|
+
str << ary.join(', ')
|
|
63
|
+
end
|
|
64
|
+
str << '>'
|
|
65
|
+
end
|
|
66
|
+
alias :to_s :inspect
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
def delete_field name
|
|
69
|
+
sym = name.to_sym
|
|
70
|
+
singleton_class.__send__ :remove_method, sym, "#{sym}=".to_sym
|
|
71
|
+
@table.delete sym
|
|
72
|
+
end
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
def == other
|
|
75
|
+
return false unless other.kind_of?(OpenStruct)
|
|
76
|
+
@table == other.table
|
|
77
|
+
end
|
|
74
78
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end
|
|
79
|
+
def [] key
|
|
80
|
+
@table[key.to_sym]
|
|
81
|
+
end
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
def []= key, value
|
|
84
|
+
@table[new_ostruct_member(key)] = value
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def eql? other
|
|
88
|
+
return false unless other.kind_of?(OpenStruct)
|
|
89
|
+
@table.eql?(other.table)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def hash
|
|
93
|
+
@table.hash
|
|
94
|
+
end
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
attr_reader :table
|
|
97
|
+
protected :table
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
def method_missing mid, *args
|
|
100
|
+
mname = mid.to_s
|
|
101
|
+
len = args.length
|
|
102
|
+
if mname.chomp! '='
|
|
103
|
+
if len != 1
|
|
104
|
+
raise ArgumentError, "wrong number of arguments (#{len} for 1)"
|
|
105
|
+
end
|
|
106
|
+
@table[new_ostruct_member(mname)] = args[0]
|
|
107
|
+
elsif len == 0
|
|
108
|
+
@table[mid]
|
|
109
|
+
else
|
|
110
|
+
raise NoMethodError, "undefined method `#{mid}' for #{self}"
|
|
93
111
|
end
|
|
94
|
-
@table[new_ostruct_member(mname)] = args[0]
|
|
95
|
-
elsif len == 0
|
|
96
|
-
@table[mid]
|
|
97
|
-
else
|
|
98
|
-
raise NoMethodError, "undefined method `#{mid}' for #{self}"
|
|
99
112
|
end
|
|
100
113
|
end
|
|
114
|
+
# rubocop:enable all
|
|
101
115
|
end
|
|
102
|
-
# rubocop:enable all
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'json'
|
|
6
|
+
require "interfacets/component_schema_parser"
|
|
7
|
+
|
|
8
|
+
module Interfacets
|
|
9
|
+
class ComponentRegistry
|
|
10
|
+
def initialize(config_path:)
|
|
11
|
+
@config_path = config_path
|
|
12
|
+
@schema_cache = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def write_client_registry(path:)
|
|
16
|
+
components = load_components
|
|
17
|
+
content = generate_registry_content(components)
|
|
18
|
+
write_atomic(path, content)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def load_components
|
|
24
|
+
raise Errno::ENOENT, "Configuration file not found at #{@config_path}" unless File.exist?(@config_path)
|
|
25
|
+
|
|
26
|
+
# 1. Load the raw YAML
|
|
27
|
+
components = YAML.load_file(@config_path, aliases: true) || {}
|
|
28
|
+
|
|
29
|
+
# 2. Parse with the V2 parser
|
|
30
|
+
parser = Interfacets::ComponentSchemaParser.new
|
|
31
|
+
parsed_components = {}
|
|
32
|
+
components.each do |name, config|
|
|
33
|
+
next unless config.is_a?(Hash)
|
|
34
|
+
component_data = { name => config }
|
|
35
|
+
# The result of parse is the component data, which we merge.
|
|
36
|
+
parsed_components.merge!(parser.parse(component_data))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
parsed_components
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def generate_registry_content(components)
|
|
43
|
+
registry_components = components.select { |_, config| config.key?("js") || has_transforms?(config) }
|
|
44
|
+
|
|
45
|
+
imports = []
|
|
46
|
+
mappings = []
|
|
47
|
+
any_transforms = false
|
|
48
|
+
|
|
49
|
+
registry_components.each do |name, config|
|
|
50
|
+
js_config = config["js"]
|
|
51
|
+
path = js_config&.dig("path")
|
|
52
|
+
|
|
53
|
+
transforms = extract_transforms(config)
|
|
54
|
+
|
|
55
|
+
if path
|
|
56
|
+
imports << if js_config["default"]
|
|
57
|
+
"import #{name} from \"#{path}\";"
|
|
58
|
+
elsif (export = js_config["export"])
|
|
59
|
+
"import { #{export} as #{name} } from \"#{path}\";"
|
|
60
|
+
else
|
|
61
|
+
"import { #{name} } from \"#{path}\";"
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
# Native element
|
|
65
|
+
imports << "const #{name} = \"#{name}\";"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if transforms.any?
|
|
69
|
+
any_transforms = true
|
|
70
|
+
mappings << " #{name}: withTransform(#{name}, #{transforms.to_json}),"
|
|
71
|
+
else
|
|
72
|
+
mappings << " #{name},"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if any_transforms
|
|
77
|
+
imports.unshift('import { withTransform } from "interfacets/withTransform";')
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
template = []
|
|
81
|
+
template << imports.join("\n") if imports.any?
|
|
82
|
+
template << <<~JS.strip
|
|
83
|
+
export const registry = {
|
|
84
|
+
#{mappings.join("\n")}
|
|
85
|
+
};
|
|
86
|
+
JS
|
|
87
|
+
|
|
88
|
+
"#{template.join("\n\n")}\n"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def has_transforms?(config)
|
|
92
|
+
extract_transforms(config).any?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def extract_transforms(config)
|
|
96
|
+
transforms = {}
|
|
97
|
+
if props = config["props"]
|
|
98
|
+
props.each do |prop_name, prop_config|
|
|
99
|
+
if prop_config["is_event"] && prop_config.key?("transform")
|
|
100
|
+
transforms[prop_name] = prop_config["transform"]
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
transforms
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def write_atomic(path, content)
|
|
110
|
+
temp_file = "#{path}.tmp"
|
|
111
|
+
File.write(temp_file, content)
|
|
112
|
+
FileUtils.mv(temp_file, path)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json_schemer"
|
|
4
|
+
|
|
5
|
+
module Interfacets
|
|
6
|
+
class ComponentSchemaParser
|
|
7
|
+
SCHEMA = {
|
|
8
|
+
"$schema" => "http://json-schema.org/draft-07/schema#",
|
|
9
|
+
"type" => "object",
|
|
10
|
+
"patternProperties" => {
|
|
11
|
+
"^.*$" => {
|
|
12
|
+
"type" => "object",
|
|
13
|
+
"properties" => {
|
|
14
|
+
"schema" => {
|
|
15
|
+
"if" => { "type" => "object" },
|
|
16
|
+
"then" => {
|
|
17
|
+
"not" => { "required" => ["props"] }
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"props" => {
|
|
21
|
+
"type" => "object",
|
|
22
|
+
"patternProperties" => {
|
|
23
|
+
"^.*$" => {
|
|
24
|
+
"type" => "object",
|
|
25
|
+
"properties" => {
|
|
26
|
+
"is_event" => { "type" => "boolean" }
|
|
27
|
+
},
|
|
28
|
+
"if" => {
|
|
29
|
+
"required" => ["is_event"],
|
|
30
|
+
"properties" => { "is_event" => { "const" => true } }
|
|
31
|
+
},
|
|
32
|
+
"then" => {
|
|
33
|
+
"properties" => {
|
|
34
|
+
"transform" => { "$ref" => "#/definitions/Transform" },
|
|
35
|
+
"payload" => { "type" => "object" }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"definitions" => {
|
|
45
|
+
"Transform" => {
|
|
46
|
+
"oneOf" => [
|
|
47
|
+
{ "type" => "null" },
|
|
48
|
+
{ "type" => "string" },
|
|
49
|
+
{
|
|
50
|
+
"type" => "object",
|
|
51
|
+
"additionalProperties" => {
|
|
52
|
+
"type" => "array",
|
|
53
|
+
"items" => [
|
|
54
|
+
{ "type" => "integer" }
|
|
55
|
+
],
|
|
56
|
+
"additionalItems" => { "type" => "string" },
|
|
57
|
+
"minItems" => 1
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}.freeze
|
|
64
|
+
|
|
65
|
+
SCHEMER = JSONSchemer.schema(SCHEMA)
|
|
66
|
+
|
|
67
|
+
def parse(component_config)
|
|
68
|
+
errors = SCHEMER.validate(component_config).to_a
|
|
69
|
+
if errors.any?
|
|
70
|
+
if errors.any? { |e| e["data_pointer"].include?("/schema") && e["type"] == "not" }
|
|
71
|
+
raise StandardError, "Old schema format is not supported."
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
message = "Validation failed:\n"
|
|
75
|
+
errors.each do |error|
|
|
76
|
+
message += " - #{error["data_pointer"]}: #{error["type"]} #{error["details"]}\n"
|
|
77
|
+
end
|
|
78
|
+
raise StandardError, message
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
component_config
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -3,20 +3,6 @@
|
|
|
3
3
|
module Interfacets
|
|
4
4
|
module Server
|
|
5
5
|
class Api
|
|
6
|
-
class Channel
|
|
7
|
-
attr_reader :klass, :store
|
|
8
|
-
|
|
9
|
-
def rendered?
|
|
10
|
-
@rendered
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def render(klass, store)
|
|
14
|
-
@rendered = true
|
|
15
|
-
@klass = klass
|
|
16
|
-
@store = store
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
6
|
attr_reader :entity, :name, :registry
|
|
21
7
|
def initialize(entity:, name:, registry:)
|
|
22
8
|
@entity = entity
|
|
@@ -25,36 +11,30 @@ module Interfacets
|
|
|
25
11
|
end
|
|
26
12
|
|
|
27
13
|
def handle(event)
|
|
28
|
-
channel = Channel.new
|
|
29
|
-
|
|
30
|
-
entity.channel = channel
|
|
31
14
|
Shared::Entities::Bus
|
|
32
15
|
.new(entity:)
|
|
33
16
|
.handle(event:)
|
|
34
17
|
|
|
35
18
|
if entity.channel.rendered?
|
|
36
|
-
|
|
37
|
-
channel.klass,
|
|
38
|
-
channel.store,
|
|
39
|
-
).render
|
|
19
|
+
entity.channel.render_facet
|
|
40
20
|
else
|
|
41
|
-
emit("after_#{event.fetch("action")}")
|
|
21
|
+
emit("after_#{event.fetch("action")}", nesting: event.fetch("nesting"))
|
|
42
22
|
end
|
|
43
23
|
end
|
|
44
24
|
|
|
45
25
|
def render
|
|
46
|
-
emit("after_load")
|
|
26
|
+
emit("after_load", nesting: ["root"])
|
|
47
27
|
end
|
|
48
28
|
|
|
49
29
|
private
|
|
50
30
|
|
|
51
|
-
def emit(action)
|
|
31
|
+
def emit(action, nesting: )
|
|
52
32
|
{
|
|
53
33
|
facet: name,
|
|
54
34
|
payload: (
|
|
55
35
|
Shared::Entities::Bus
|
|
56
36
|
.new(entity:)
|
|
57
|
-
.serialize(to: "client", action:, nesting:
|
|
37
|
+
.serialize(to: "client", action:, nesting:)
|
|
58
38
|
)
|
|
59
39
|
}
|
|
60
40
|
end
|
|
@@ -23,18 +23,19 @@ module Interfacets
|
|
|
23
23
|
current_mod = ""
|
|
24
24
|
mods.each do |mod_name|
|
|
25
25
|
current_mod += "::#{mod_name}"
|
|
26
|
-
type = current_mod.constantize.is_a?(
|
|
26
|
+
type = current_mod.constantize.is_a?(Class) ? :class : :module
|
|
27
27
|
headers << "#{type} #{mod_name}"
|
|
28
28
|
footers << "end"
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
headers << "class #{klass_name}
|
|
31
|
+
headers << "class #{klass_name}"
|
|
32
|
+
headers << " include Interfacets::Shared::Facet"
|
|
32
33
|
footers << "end"
|
|
33
34
|
|
|
34
35
|
<<~TXT
|
|
35
36
|
#{headers.join("\n")}
|
|
36
37
|
|
|
37
|
-
include Interfacets::
|
|
38
|
+
include Interfacets::Shared::Facets::Schema
|
|
38
39
|
|
|
39
40
|
view_spec #{write_source(klass.client_config.view.block)}
|
|
40
41
|
|
|
@@ -54,6 +55,7 @@ module Interfacets
|
|
|
54
55
|
.of(block, keep_script_lines: true)
|
|
55
56
|
.source
|
|
56
57
|
.strip
|
|
58
|
+
|
|
57
59
|
end
|
|
58
60
|
end
|
|
59
61
|
end
|