interfacets 0.1.0 → 0.9.9

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +173 -1
  3. data/LICENSE +21 -0
  4. data/Rakefile +4 -6
  5. data/lib/interfacets/client/actor.rb +20 -0
  6. data/lib/interfacets/client/assets.rb +209 -0
  7. data/lib/interfacets/client/bus.rb +69 -0
  8. data/lib/interfacets/client/channels/api.rb +95 -0
  9. data/lib/interfacets/client/channels/audio.rb +101 -0
  10. data/lib/interfacets/client/channels/base.rb +28 -0
  11. data/lib/interfacets/client/channels/page_visibility.rb +21 -0
  12. data/lib/interfacets/client/channels/react/builder.rb +203 -0
  13. data/lib/interfacets/client/channels/react/channel.rb +61 -0
  14. data/lib/interfacets/client/channels/react/dom.rb +91 -0
  15. data/lib/interfacets/client/channels/react/evaluator.rb +33 -0
  16. data/lib/interfacets/client/channels/speech_to_text.rb +100 -0
  17. data/lib/interfacets/client/channels/timer.rb +51 -0
  18. data/lib/interfacets/client/channels/url.rb +52 -0
  19. data/lib/interfacets/client/config.rb +22 -0
  20. data/lib/interfacets/client/delegator.rb +37 -0
  21. data/lib/interfacets/client/facet.rb +26 -0
  22. data/lib/interfacets/client/facet2.rb +15 -0
  23. data/lib/interfacets/client/facets/attributes/accessor.rb +28 -0
  24. data/lib/interfacets/client/facets/attributes/association.rb +50 -0
  25. data/lib/interfacets/client/facets/attributes/bind.rb +25 -0
  26. data/lib/interfacets/client/facets/attributes/collection.rb +47 -0
  27. data/lib/interfacets/client/facets/attributes/readonly.rb +19 -0
  28. data/lib/interfacets/client/facets/deserializer.rb +30 -0
  29. data/lib/interfacets/client/facets/schema/deserializer.rb +63 -0
  30. data/lib/interfacets/client/facets/schema.rb +63 -0
  31. data/lib/interfacets/client/facets/serializer.rb +18 -0
  32. data/lib/interfacets/client/registry.rb +84 -0
  33. data/lib/interfacets/client/system.rb +88 -0
  34. data/lib/interfacets/client/utils/active_support_concern.rb +220 -0
  35. data/lib/interfacets/client/utils/mruby_patches.rb +81 -0
  36. data/lib/interfacets/client/utils/open_struct.rb +102 -0
  37. data/lib/interfacets/client/utils/securerandom.rb +69 -0
  38. data/lib/interfacets/client/view.rb +47 -0
  39. data/lib/interfacets/client.rb +13 -0
  40. data/lib/interfacets/mruby/build.dockerfile +66 -0
  41. data/lib/interfacets/mruby/build_config.rb +20 -0
  42. data/lib/interfacets/mruby/entrypoint.rb +23 -0
  43. data/lib/interfacets/mruby/init.c +66 -0
  44. data/lib/interfacets/server/api.rb +64 -0
  45. data/lib/interfacets/server/assets/facet.rb +61 -0
  46. data/lib/interfacets/server/assets.rb +210 -0
  47. data/lib/interfacets/server/basic_routable.rb +40 -0
  48. data/lib/interfacets/server/basic_router.rb +74 -0
  49. data/lib/interfacets/server/bus.rb +39 -0
  50. data/lib/interfacets/server/config.rb +87 -0
  51. data/lib/interfacets/server/facet.rb +51 -0
  52. data/lib/interfacets/server/facets/deserializer.rb +25 -0
  53. data/lib/interfacets/server/facets/schema/serializer.rb +54 -0
  54. data/lib/interfacets/server/facets/serializer.rb +50 -0
  55. data/lib/interfacets/server/registry.rb +212 -0
  56. data/lib/interfacets/shared/entities/bus.rb +218 -0
  57. data/lib/interfacets/shared/entities/collection_proxy.rb +190 -0
  58. data/lib/interfacets/shared/entities/specs/handlers.rb +117 -0
  59. data/lib/interfacets/shared/entities/specs.rb +124 -0
  60. data/lib/interfacets/shared/entity.rb +178 -0
  61. data/lib/interfacets/shared/entity_collection.rb +88 -0
  62. data/lib/interfacets/shared/generated_store.rb +145 -0
  63. data/lib/interfacets/shared/utils.rb +54 -0
  64. data/lib/interfacets/shared/validations.rb +71 -0
  65. data/lib/interfacets/test/browser.rb +63 -0
  66. data/lib/interfacets/test/js/inline_bus.rb +91 -0
  67. data/lib/interfacets/test/js/nodo_bus.rb +81 -0
  68. data/lib/interfacets/test/js/receivers/api.rb +37 -0
  69. data/lib/interfacets/test/js/receivers/react/node.rb +167 -0
  70. data/lib/interfacets/test/js/receivers/react.rb +31 -0
  71. data/lib/interfacets/test/js/receivers/url.rb +55 -0
  72. data/lib/interfacets/test.rb +17 -0
  73. data/lib/interfacets/version.rb +1 -1
  74. data/lib/interfacets.rb +26 -2
  75. metadata +103 -6
  76. data/README.md +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a9fc11b77c082c02a9bb6c8defdbf12b12fac9dff56d9009c723a26719e5ffa
4
- data.tar.gz: d0ae5775b216ff078d6f730cfe853aacce5bd0784c79929cf07350c78a0e5105
3
+ metadata.gz: b1f88601fcc7349a9d14fb653aa28bd0fb988dce3571ea4c488d9ea0c46ece93
4
+ data.tar.gz: 8e954aa9c6b4c0d40fdf4df5487fcc0f4de2d36b6ff6e0abfcf446e321cc8e8d
5
5
  SHA512:
6
- metadata.gz: 7f818487b367acd4514130b7a0426509d6c8aea7c0620407ac95d49673683b5a0e33278064d5cff90cd02964f42a708d3532ebaa5fc9446e082ffa4b1faeb27e
7
- data.tar.gz: 3fd3d0db29f724a037eb84f450ed33af68b396346c9933d6492a8c67acb5f9acb372a5fd6b5275f30590394075c7c46b3566812940e432e031b914ba239a8bcb
6
+ metadata.gz: 0ad6edcb3b43786a4b914c18d0899ff3e4400ad039e92a11553f31e1d97dee3125a1bd9a58050bb4bb8f28db5d568ba00e0f9d9dfe6afd7ea71edc7b29e0ffb1
7
+ data.tar.gz: 163066c8f07e91d45351bf396473a6bd655db05d1b9bc792bad92c54fa9ac09d1aa4a1d4d68c59ddf03a8c8ef71e996c2e742bf2ad238ff72cb584697633998d
data/.rubocop.yml CHANGED
@@ -1,8 +1,180 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.0
2
+ NewCops: enable
3
+ Exclude: [ "bin/*" ]
4
+
5
+ Layout/EmptyLinesAroundAttributeAccessor:
6
+ Enabled: false
7
+
8
+ Layout/MultilineMethodCallBraceLayout:
9
+ Enabled: true
10
+ EnforcedStyle: new_line
11
+
12
+ Layout/MultilineMethodCallIndentation:
13
+ Enabled: true
14
+ EnforcedStyle: indented
15
+
16
+ Layout/MultilineMethodArgumentLineBreaks:
17
+ Enabled: true
18
+
19
+ Layout/MultilineMethodParameterLineBreaks:
20
+ Enabled: true
21
+
22
+ Layout/FirstMethodArgumentLineBreak:
23
+ Enabled: true
24
+
25
+ Layout/FirstMethodParameterLineBreak:
26
+ Enabled: true
27
+
28
+ Style/MethodCallWithArgsParentheses:
29
+ Enabled: true
30
+
31
+ Layout/ArgumentAlignment:
32
+ Enabled: true
33
+ EnforcedStyle: with_fixed_indentation
34
+
35
+ Lint/UnusedMethodArgument:
36
+ Enabled: false
37
+
38
+ Style/NumberedParameters:
39
+ Enabled: false
40
+
41
+ Style/OpenStructUse:
42
+ Enabled: false
43
+
44
+ Lint/EmptyBlock:
45
+ Enabled: false
46
+
47
+ Style/ExponentialNotation:
48
+ Enabled: false
49
+
50
+ Layout/MultilineAssignmentLayout:
51
+ Enabled: true
52
+ EnforcedStyle: new_line
53
+
54
+ Layout/ExtraSpacing:
55
+ Enabled: true
56
+ AllowForAlignment: false
57
+
58
+ Metrics/AbcSize:
59
+ Enabled: false
60
+
61
+ Metrics/BlockLength:
62
+ Enabled: false
63
+
64
+ Metrics/ClassLength:
65
+ Enabled: false
66
+
67
+ Metrics/CyclomaticComplexity:
68
+ Enabled: false
69
+
70
+ Metrics/MethodLength:
71
+ Enabled: false
72
+
73
+ Metrics/ModuleLength:
74
+ Enabled: false
75
+
76
+ Metrics/PerceivedComplexity:
77
+ Enabled: false
78
+
79
+ Naming/MethodParameterName:
80
+ Enabled: false
81
+
82
+ Naming/PredicateName:
83
+ Enabled: false
84
+
85
+ Naming/VariableNumber:
86
+ EnforcedStyle: snake_case
87
+
88
+ Security/Eval:
89
+ Enabled: false
90
+
91
+ Style/Alias:
92
+ Enabled: false
93
+
94
+ Style/BlockDelimiters:
95
+ Enabled: false
96
+ EnforcedStyle: semantic
97
+
98
+ Style/CaseLikeIf:
99
+ Enabled: false
100
+
101
+ Style/CombinableLoops:
102
+ Enabled: false
103
+
104
+ Style/Documentation:
105
+ Enabled: false
106
+
107
+ Style/EmptyLambdaParameter:
108
+ Enabled: false
109
+
110
+ Style/EvenOdd:
111
+ Enabled: false
112
+
113
+
114
+ Style/GuardClause:
115
+ Enabled: false
116
+
117
+ Style/IfUnlessModifier:
118
+ Enabled: false
119
+
120
+ Style/Lambda:
121
+ Enabled: false
122
+
123
+ Style/ModuleFunction:
124
+ Enabled: false
125
+
126
+ Style/MultilineBlockChain:
127
+ Enabled: false
128
+
129
+ Style/MultilineMemoization:
130
+ Enabled: true
131
+ EnforcedStyle: braces
132
+
133
+ Style/ParenthesesAroundCondition:
134
+ Enabled: true
135
+ AllowInMultilineConditions: true
136
+
137
+ Style/RaiseArgs:
138
+ Enabled: true
139
+ EnforcedStyle: compact
140
+
141
+ Style/RedundantParentheses:
142
+ Enabled: false
143
+
144
+ Style/RedundantSelf:
145
+ Enabled: false
3
146
 
4
147
  Style/StringLiterals:
148
+ Enabled: true
5
149
  EnforcedStyle: double_quotes
6
150
 
7
151
  Style/StringLiteralsInInterpolation:
152
+ Enabled: true
8
153
  EnforcedStyle: double_quotes
154
+
155
+ Style/SymbolArray:
156
+ Enabled: true
157
+ EnforcedStyle: brackets
158
+
159
+ Style/TrailingCommaInArguments:
160
+ Enabled: true
161
+ EnforcedStyleForMultiline: consistent_comma
162
+
163
+ Style/TrailingCommaInArrayLiteral:
164
+ Enabled: true
165
+ EnforcedStyleForMultiline: consistent_comma
166
+
167
+ Style/TrailingCommaInHashLiteral:
168
+ Enabled: true
169
+ EnforcedStyleForMultiline: consistent_comma
170
+
171
+ Style/WordArray:
172
+ Enabled: true
173
+ EnforcedStyle: brackets
174
+
175
+ Layout/LineLength:
176
+ Max: 100
177
+ AllowedPatterns: ['^(\s*#)']
178
+
179
+ Style/DocumentDynamicEvalDefinition:
180
+ Enabled: false
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Pete Kinnecom
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/Rakefile CHANGED
@@ -3,10 +3,8 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "minitest/test_task"
5
5
 
6
- Minitest::TestTask.create
6
+ Minitest::TestTask.create do |t|
7
+ t.warning = false
8
+ end
7
9
 
8
- require "rubocop/rake_task"
9
-
10
- RuboCop::RakeTask.new
11
-
12
- task default: %i[test rubocop]
10
+ task default: :test
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Interfacets
4
+ module Client
5
+ class Actor
6
+ attr_reader :registry, :facet
7
+ def initialize(registry:, channels:)
8
+ @registry = registry
9
+ end
10
+
11
+ def build_facet(name)
12
+ @facet = registry.build(name)
13
+ end
14
+
15
+ def render
16
+ facet.render(channels)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Style/MissingRespondToMissing
4
+ original_verbose = $VERBOSE
5
+ $VERBOSE = nil
6
+
7
+ TOP_LEVEL_BINDING = self.binding
8
+ DEFAULT_LOG_LEVEL = ENV.fetch("DEFAULT_LOG_LEVEL", "debug").to_sym
9
+
10
+ class InterfacetsLogger
11
+ class << self
12
+ def main
13
+ @main ||= new(level: DEFAULT_LOG_LEVEL)
14
+ end
15
+ end
16
+
17
+ LEVELS = {
18
+ debug: 0,
19
+ info: 1,
20
+ warn: 2,
21
+ error: 3,
22
+ fatal: 4
23
+ }.freeze
24
+
25
+ attr_accessor :level
26
+ def initialize(level: :info)
27
+ @level = LEVELS[level] || LEVELS[:info]
28
+ end
29
+
30
+ # Meta-program the logging methods
31
+ LEVELS.each do |method_name, level_value|
32
+ define_method(method_name) do |message|
33
+ puts "#{method_name.to_s.upcase}: #{message}" if level_value >= @level
34
+ end
35
+ end
36
+ end
37
+
38
+ $VERBOSE = original_verbose
39
+
40
+ module Interfacets
41
+ module Client
42
+ module Assets
43
+ class << self
44
+ attr_reader :loader
45
+
46
+ def logger
47
+ $asset_logger ||= InterfacetsLogger.main
48
+ end
49
+
50
+ def bootstrap(assets)
51
+ @loader = Loader.new(assets)
52
+ Assets.logger.debug("bootstrapping")
53
+
54
+ assets
55
+ .fetch("scaffolding")
56
+ .reject { _1.match(/SecureRandom/) } #total hack, bake this into image
57
+ .join("\n")
58
+ .then { TOP_LEVEL_BINDING.eval(_1) }
59
+
60
+ Assets.logger.debug("done bootstrapping")
61
+
62
+ assets.fetch("fs_map").each_key do |path|
63
+ Assets.logger.debug("planned load: #{path}")
64
+ @loader.load_path(path)
65
+ end
66
+ end
67
+ end
68
+
69
+ class Loader
70
+ attr_reader :assets
71
+ def initialize(assets)
72
+ @assets = assets
73
+ @loaded_classes = {}
74
+ @loaded_paths = {}
75
+ end
76
+
77
+ def path_loaded?(path)
78
+ @loaded_paths.key?(path)
79
+ end
80
+
81
+ def load_path(path)
82
+ return if @loaded_paths.key?(path)
83
+
84
+ @loaded_paths[path] = true
85
+
86
+ Assets.logger.debug("loading: #{path}")
87
+
88
+ TOP_LEVEL_BINDING.eval(fs_map.fetch(path), path)
89
+ Assets.logger.debug("done loading: #{path}")
90
+ end
91
+
92
+ def loaded?(klass)
93
+ @loaded_classes.key?(klass)
94
+ end
95
+
96
+ def load(klass)
97
+ return if loaded?(klass)
98
+
99
+ @loaded_classes[klass] = true
100
+
101
+ return if klass.name.nil?
102
+
103
+ return unless const_map.key?(klass.name)
104
+
105
+ const_map
106
+ .fetch(klass.name)
107
+ .each {
108
+ Assets.logger.debug("klass caused load: #{_1}")
109
+ load_path(_1)
110
+ }
111
+ end
112
+
113
+ private
114
+
115
+ def scaffolding
116
+ @scaffolding ||= assets.fetch("scaffolding")
117
+ end
118
+
119
+ def fs_map
120
+ @fs_map ||= assets.fetch("fs_map")
121
+ end
122
+
123
+ def const_map
124
+ @const_map ||= assets.fetch("const_map")
125
+ end
126
+ end
127
+
128
+ module AutoloadHook
129
+ def extend_object(o)
130
+ if Assets.loader.loaded?(self)
131
+ super
132
+ else
133
+ Assets.loader.load(self)
134
+ send(:extend_object, o)
135
+ end
136
+ end
137
+
138
+ def inherited(mod)
139
+ if Assets.loader.loaded?(self)
140
+ super
141
+ else
142
+ Assets.loader.load(self)
143
+ send(:inherited, mod)
144
+ end
145
+ end
146
+
147
+ def append_features(mod)
148
+ if Assets.loader.loaded?(self)
149
+ super
150
+ else
151
+ Assets.loader.load(self)
152
+ send(:append_features, mod)
153
+ end
154
+ end
155
+
156
+ # def included(mod)
157
+ # Assets.logger.debug("included: #{self.name} into #{mod.name}")
158
+ # unless Assets.loader.loaded?(self)
159
+ # Assets.loader.load(self)
160
+ # send(:included, mod)
161
+ # else
162
+ # super
163
+ # end
164
+ # end
165
+
166
+ # def extended(mod)
167
+ # Assets.logger.debug("extended: #{mod.name}")
168
+ # unless Assets.loader.loaded?(self)
169
+ # Assets.logger.debug("loaded: #{self}, now extending")
170
+ # Assets.loader.load(self)
171
+ # send(:extended, mod)
172
+ # else
173
+ # Assets.logger.debug("already loaded: #{self}, not extending")
174
+ # super
175
+ # end
176
+ # end
177
+
178
+ # def prepended(mod)
179
+ # unless Assets.loader.loaded?(self)
180
+ # Assets.loader.load(self)
181
+ # send(:prepended, mod)
182
+ # else
183
+ # super
184
+ # end
185
+ # end
186
+
187
+ # don't think this is needed
188
+ # def const_missing(const_name)
189
+ # if Assets.loader.loaded?(self)
190
+ # super
191
+ # else
192
+ # Assets.loader.load(self)
193
+ # const_get(const_name)
194
+ # end
195
+ # end
196
+
197
+ def method_missing(meth, *a, **p, &)
198
+ if Assets.loader.loaded?(self)
199
+ super
200
+ else
201
+ Assets.loader.load(self)
202
+ send(meth, *a, **p, &)
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
209
+ # rubocop:enable Style/MissingRespondToMissing
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This pipes messages through channels. This allows channel authors to intercept
4
+ # and incoming and outgoing messages and dropping/ignoring/updating their own state
5
+
6
+ module Interfacets
7
+ module Client
8
+ class Bus
9
+ attr_reader(
10
+ :id,
11
+ :channels,
12
+ :channel_index,
13
+ :registry,
14
+ :entity,
15
+ :root_url,
16
+ )
17
+
18
+ def initialize(
19
+ id:,
20
+ channels:,
21
+ root_url:
22
+ )
23
+ @id = id
24
+ @channels = channels
25
+ @registry = Registry.new
26
+ @channel_index = channels.map { [_1.id, _1] }.to_h
27
+ @root_url = root_url
28
+ end
29
+
30
+ def url_for(path)
31
+ [
32
+ root_url,
33
+ path,
34
+ ]
35
+ .map { _1.sub(%r{/$}, "").sub(%r{^/}, "") }
36
+ .join("/")
37
+ end
38
+
39
+ def channel(name)
40
+ channel_index.fetch(name.to_s)
41
+ end
42
+
43
+ def handle(event)
44
+ channel_id = event.dig("destination", "channel")
45
+ raise("unknown event: #{event.inspect}") unless channel_id
46
+ channel = channel_index.fetch(channel_id)
47
+
48
+ channel.handle(
49
+ entity: @entity,
50
+ event: event.fetch("payload"),
51
+ build_entity: ->(name) { @entity = registry.build(name) }
52
+ )
53
+
54
+ channel_index.values.each { _1.prepare(entity) }
55
+
56
+ entity.class.view.new.render(entity:, channels: channel_index)
57
+
58
+ {
59
+ type: "interfacets:bus:render",
60
+ id: id,
61
+ payload: (
62
+ channel_index
63
+ .map { |name, chann| { id: name, payload: chann.result } }
64
+ )
65
+ }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Interfacets
4
+ module Client
5
+ module Channels
6
+ class Api
7
+ include Channels::Base
8
+
9
+ class Builder
10
+ attr_accessor :request, :entity
11
+
12
+ def render(path)
13
+ raise("only one submission per action") if request
14
+
15
+ System.logger.debug("Getting #{path}")
16
+
17
+ request_id = SecureRandom.uuid
18
+
19
+ self.request = {
20
+ url: Client::System.current_bus.url_for(path),
21
+ method: "get",
22
+ }
23
+ end
24
+
25
+ def submit(meth)
26
+ raise("only one submission per action") if request
27
+
28
+ System.logger.debug("submitting #{meth}")
29
+
30
+ request_id = SecureRandom.uuid
31
+
32
+ self.request = {
33
+ url: (
34
+ if entity.respond_to?(:api_path)
35
+ Client::System.current_bus.url_for(entity.api_path)
36
+ end
37
+ ),
38
+ method: "put",
39
+ body: {
40
+ event: {
41
+ id: request_id,
42
+ type: "interfacets:api:submit",
43
+ payload: (
44
+ Shared::Entities::Bus
45
+ .new(entity:)
46
+ .serialize(
47
+ to: "server" ,
48
+ action: meth,
49
+ nesting: ["root"]
50
+ )
51
+ )
52
+ },
53
+ },
54
+ }
55
+ end
56
+ end
57
+
58
+ type("interfacets:api")
59
+
60
+ def prepare(entity)
61
+ # must persist builder here
62
+ # probably all channels need to persist their
63
+ # builder. Because the bus calls "handle" before
64
+ # the "prepare" call. Perhaps these should be
65
+ # reversed?
66
+ @builder ||= Builder.new
67
+ @builder.entity = entity
68
+ end
69
+
70
+ def builder(stream = "default")
71
+ @builder
72
+ end
73
+
74
+ def result
75
+ {
76
+ streams: {
77
+ default: @builder.request,
78
+ },
79
+ }.tap { @builder.request = nil }
80
+ end
81
+
82
+ def handle(event:, entity:, build_entity:)
83
+ facet_name = event.fetch("facet")
84
+ entity = build_entity.(facet_name)
85
+
86
+ Shared::Entities::Bus
87
+ .new(entity:)
88
+ .handle(
89
+ event: event.fetch("payload")
90
+ )
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end