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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.tmp +5 -0
  3. data/Rakefile +4 -0
  4. data/lib/interfacets/client/assets.rb +1 -0
  5. data/lib/interfacets/client/bus.rb +5 -1
  6. data/lib/interfacets/client/channels/api.rb +10 -3
  7. data/lib/interfacets/client/registry.rb +9 -70
  8. data/lib/interfacets/client/utils/mruby_patches.rb +1 -1
  9. data/lib/interfacets/client/utils/open_struct.rb +90 -77
  10. data/lib/interfacets/component_registry.rb +115 -0
  11. data/lib/interfacets/component_schema_parser.rb +84 -0
  12. data/lib/interfacets/server/api.rb +5 -25
  13. data/lib/interfacets/server/assets/facet.rb +5 -3
  14. data/lib/interfacets/server/assets.rb +13 -7
  15. data/lib/interfacets/server/basic_router.rb +15 -10
  16. data/lib/interfacets/server/bus.rb +4 -9
  17. data/lib/interfacets/server/config.rb +1 -1
  18. data/lib/interfacets/server/registry.rb +23 -184
  19. data/lib/interfacets/shared/basic_routable.rb +45 -0
  20. data/lib/interfacets/shared/entities/bus.rb +41 -29
  21. data/lib/interfacets/shared/entities/specs/handlers.rb +16 -0
  22. data/lib/interfacets/shared/entities/specs.rb +46 -9
  23. data/lib/interfacets/shared/entity.rb +23 -99
  24. data/lib/interfacets/shared/entity_dsl.rb +154 -0
  25. data/lib/interfacets/shared/facet.rb +200 -0
  26. data/lib/interfacets/shared/generated_store.rb +6 -2
  27. data/lib/interfacets/shared/utils.rb +1 -1
  28. data/lib/interfacets/shared/validations.rb +5 -1
  29. data/lib/interfacets/{client → shared}/view.rb +33 -6
  30. data/lib/interfacets/test/component_registry.rb +63 -0
  31. data/lib/interfacets/test/js/inline_bus.rb +21 -12
  32. data/lib/interfacets/test/js/nodo_bus.rb +18 -1
  33. data/lib/interfacets/test/js/receivers/api.rb +14 -3
  34. data/lib/interfacets/test/js/receivers/react/node/xml_parser.rb +75 -0
  35. data/lib/interfacets/test/js/receivers/react/node.rb +29 -63
  36. data/lib/interfacets/test/js/receivers/react.rb +4 -3
  37. data/lib/interfacets/test/js/receivers/timer.rb +77 -0
  38. data/lib/interfacets/test/js/receivers/url.rb +5 -0
  39. data/lib/interfacets/test/standard_elements.yml +173 -0
  40. data/lib/interfacets/test/{browser.rb → ui_simulator.rb} +18 -6
  41. data/lib/interfacets/test/validation_engine.rb +151 -0
  42. data/lib/interfacets/test.rb +0 -4
  43. data/lib/interfacets/version.rb +1 -1
  44. data/lib/interfacets.rb +3 -0
  45. metadata +29 -18
  46. data/lib/interfacets/client/facet.rb +0 -26
  47. data/lib/interfacets/client/facet2.rb +0 -15
  48. data/lib/interfacets/client/facets/attributes/accessor.rb +0 -28
  49. data/lib/interfacets/client/facets/attributes/association.rb +0 -50
  50. data/lib/interfacets/client/facets/attributes/bind.rb +0 -25
  51. data/lib/interfacets/client/facets/attributes/collection.rb +0 -47
  52. data/lib/interfacets/client/facets/attributes/readonly.rb +0 -19
  53. data/lib/interfacets/client/facets/deserializer.rb +0 -30
  54. data/lib/interfacets/client/facets/schema/deserializer.rb +0 -63
  55. data/lib/interfacets/client/facets/schema.rb +0 -63
  56. data/lib/interfacets/client/facets/serializer.rb +0 -18
  57. data/lib/interfacets/server/basic_routable.rb +0 -40
  58. data/lib/interfacets/server/facet.rb +0 -51
  59. data/lib/interfacets/shared/entity_collection.rb +0 -88
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1f88601fcc7349a9d14fb653aa28bd0fb988dce3571ea4c488d9ea0c46ece93
4
- data.tar.gz: 8e954aa9c6b4c0d40fdf4df5487fcc0f4de2d36b6ff6e0abfcf446e321cc8e8d
3
+ metadata.gz: 8e7e08a925c26ef4b7ee1e2aa2bbdcd716388b6f3aaa22f8d5bf9e7a51a76cee
4
+ data.tar.gz: 222f5f5f8129c913d19ce4f6d6331f820ad643a6198f35f63ce0b9df2743e059
5
5
  SHA512:
6
- metadata.gz: 0ad6edcb3b43786a4b914c18d0899ff3e4400ad039e92a11553f31e1d97dee3125a1bd9a58050bb4bb8f28db5d568ba00e0f9d9dfe6afd7ea71edc7b29e0ffb1
7
- data.tar.gz: 163066c8f07e91d45351bf396473a6bd655db05d1b9bc792bad92c54fa9ac09d1aa4a1d4d68c59ddf03a8c8ef71e996c2e742bf2ad238ff72cb584697633998d
6
+ metadata.gz: 68e278e17a2b033f8dc0ee6941f80a76d6ddb6bfeb0d7c79267ed24150d48b6d7e1ff54bda300cb0db5b4caa238632be5efe8b228fa018362482b7d8cea1264a
7
+ data.tar.gz: 3ca6b351b7089d7e9d99e513a282c937cea531a813a1ebfdfd35a514b2f34f95187f19c63ac57e1a5691c61d111f67f2dbae0b614c490c252a2f76b3dcc5006a
data/.tmp ADDED
@@ -0,0 +1,5 @@
1
+ import { Test } from
2
+
3
+ export const registry = {
4
+ Test,
5
+ };
data/Rakefile CHANGED
@@ -5,6 +5,10 @@ require "minitest/test_task"
5
5
 
6
6
  Minitest::TestTask.create do |t|
7
7
  t.warning = false
8
+ t.test_globs = (
9
+ Rake::FileList["test/**/test_*.rb", "test/**/*_test.rb"]
10
+ .exclude("test/fixtures/**/*")
11
+ )
8
12
  end
9
13
 
10
14
  task default: :test
@@ -33,6 +33,7 @@ class InterfacetsLogger
33
33
  puts "#{method_name.to_s.upcase}: #{message}" if level_value >= @level
34
34
  end
35
35
  end
36
+
36
37
  end
37
38
 
38
39
  $VERBOSE = original_verbose
@@ -48,7 +48,11 @@ module Interfacets
48
48
  channel.handle(
49
49
  entity: @entity,
50
50
  event: event.fetch("payload"),
51
- build_entity: ->(name) { @entity = registry.build(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: ["root"]
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
- entity = build_entity.(facet_name)
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 build(name)
7
- entity = Object.const_get("#{name}::Client::Entity")
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: entity.store.new,
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
@@ -60,7 +60,7 @@ module Interfacets
60
60
 
61
61
  module StringPresence
62
62
  def blank?
63
- match?(/^\s*$/)
63
+ !!match(/\A\s*\z/)
64
64
  end
65
65
  end
66
66
 
@@ -2,101 +2,114 @@
2
2
 
3
3
  # copied from github
4
4
 
5
- class OpenStruct
6
- def initialize hash=nil
7
- @table = {}
8
- if hash
9
- hash.each do |k,v|
10
- k = k.to_sym
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
- def initialize_copy orig
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
- def each_pair
28
- return to_enum __method__ unless block_given?
29
- @table.each{|p| yield p}
30
- end
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
- def new_ostruct_member name
33
- name = name.to_sym
34
- unless respond_to?(name)
35
- define_singleton_method(name){ @table[name] }
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
- def inspect
43
- str = "#<#{self.class}"
44
- ary = []
45
- @table.each do |k,v|
46
- ary << "#{k}=#{v}"
35
+ def to_h
36
+ @table.dup
47
37
  end
48
- if 0 < ary.length
49
- str << ' '
50
- str << ary.join(', ')
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
- def delete_field name
57
- sym = name.to_sym
58
- singleton_class.__send__ :remove_method, sym, "#{sym}=".to_sym
59
- @table.delete sym
60
- end
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
- def == other
63
- return false unless other.kind_of?(OpenStruct)
64
- @table == other.table
65
- end
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
- def [] key
68
- @table[key.to_sym]
69
- end
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
- def []= key, value
72
- @table[new_ostruct_member(key)] = value
73
- end
74
+ def == other
75
+ return false unless other.kind_of?(OpenStruct)
76
+ @table == other.table
77
+ end
74
78
 
75
- def eql? other
76
- return false unless other.kind_of?(OpenStruct)
77
- @table.eql?(other.table)
78
- end
79
+ def [] key
80
+ @table[key.to_sym]
81
+ end
79
82
 
80
- def hash
81
- @table.hash
82
- end
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
- attr_reader :table
85
- protected :table
96
+ attr_reader :table
97
+ protected :table
86
98
 
87
- def method_missing mid, *args
88
- mname = mid.to_s
89
- len = args.length
90
- if mname.chomp! '='
91
- if len != 1
92
- raise ArgumentError, "wrong number of arguments (#{len} for 1)"
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
- registry.build(
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: ["root"])
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?(Module) ? :module : :class
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} < Interfacets::Client::Facet"
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::Client::Facets::Schema
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