brut 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1fd649346396f27b70064c601a639187c08fec7d38f4efc973c3a9839d2c163
4
- data.tar.gz: a06518da1bb198c89acfd13dca787fabb302546097e08d8917bf1c500d399f39
3
+ metadata.gz: d0a674e5f292d833626132e6cb0d634eb7432a5f814cfdde37456980c5066ace
4
+ data.tar.gz: dfe06bd16d1af502fc42512c1eb9c6500d2f13e3355587e705bb3e0f314f59be
5
5
  SHA512:
6
- metadata.gz: 0ecde01ea2f1cdc821e24e835fe18a7420848601d469435c74abe3d020187fccc73004ce063f7c242f663796d2470145981e6ace8a742ae885568abb0533eb74
7
- data.tar.gz: da0e5c69737041a6ff25366c4fd4cb41214f97b1ada9c78f878544f380f8370bcd155f8f7e6b77d52b50a77b6270b08847e5b1e10bec657b464d289d84747c4f
6
+ metadata.gz: d6c1dae45c7e5f30b6e01ff4add890fbc3bbe1581c2363fa872a627d040f1dbe08a99e2d07c1f56e15d4f542cb506fa5a3e1f4d4ce4f0e15accba0ae3976b2fb
7
+ data.tar.gz: bcdf28454960102dfc70dc7a2b74f52ab7b661a83cd6050473a3de28628c636fd02cb476b44c3ab7000d64500b494682780cd1f60b4d5da5f0747652d33917f9
data/Gemfile.lock CHANGED
@@ -1,11 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brut (0.0.2)
4
+ brut (0.0.3)
5
5
  concurrent-ruby
6
- dotenv
7
- factory_bot
8
- faker
9
6
  i18n
10
7
  irb
11
8
  nokogiri
@@ -188,6 +185,9 @@ DEPENDENCIES
188
185
  activesupport
189
186
  brut!
190
187
  bundler
188
+ dotenv
189
+ factory_bot
190
+ faker
191
191
  rake
192
192
  rdiscount
193
193
  rdoc
data/brut.gemspec CHANGED
@@ -35,11 +35,8 @@ Gem::Specification.new do |spec|
35
35
  spec.require_paths = ["lib"]
36
36
 
37
37
  spec.add_runtime_dependency "irb"
38
- spec.add_runtime_dependency "dotenv"
39
38
  spec.add_runtime_dependency "ostruct" # squelch some warning - this is not used
40
- spec.add_runtime_dependency "factory_bot"
41
39
  spec.add_runtime_dependency "concurrent-ruby"
42
- spec.add_runtime_dependency "faker"
43
40
  spec.add_runtime_dependency "i18n"
44
41
  spec.add_runtime_dependency "nokogiri"
45
42
  spec.add_runtime_dependency "prism"
@@ -64,4 +61,7 @@ Gem::Specification.new do |spec|
64
61
  spec.add_development_dependency "yard"
65
62
  spec.add_development_dependency "rdiscount"
66
63
  spec.add_development_dependency "rdoc"
64
+ spec.add_development_dependency "dotenv"
65
+ spec.add_development_dependency "factory_bot"
66
+ spec.add_development_dependency "faker"
67
67
  end
@@ -2,87 +2,54 @@ require_relative "container"
2
2
  require_relative "config"
3
3
  require_relative "../junk_drawer"
4
4
  require_relative "app"
5
+
5
6
  require "sequel"
7
+
6
8
  require "semantic_logger"
9
+ require_relative "patch_semantic_logger"
10
+
7
11
  require "i18n"
8
12
  require "zeitwerk"
9
13
  require "opentelemetry/sdk"
10
14
  require "opentelemetry/exporter/otlp"
11
15
 
12
-
13
16
  # The Master Control Program of Brut. This handles all the bootstrapping and setup of your app. You are not
14
17
  # intended to use or interact with this class at all. End of line.
15
18
  class Brut::Framework::MCP
16
19
 
17
- # Create the MCP.
20
+ # Create and configure the MCP. The app will not work until {#boot!} has been called, however most of the core configuration
21
+ # will be available via `Brut.container`.
22
+ #
23
+ # In particular, when this initializer is done, the following will be set up:
24
+ #
25
+ # * Logging
26
+ # * I18n
27
+ # * Zeitwerk
28
+ # * Initial values and configuration from {Brut::Framework::Config#configure!}. Note that some values in there are static and some
29
+ # are lazily-evaluated, i.e. their values will only be calculated when fetched.
30
+ #
31
+ # In general, you shouldn't have to interact with this class directly, however for posterity, there are basically two ways in which
32
+ # to do so:
33
+ #
34
+ # * Create the instance and *do not* call `boot!`. This is what you'd do if you can't or don't want to connect to external services
35
+ # like the database. For example, when Brut builds assets, it does not call `boot!`.
36
+ # * Create the intance and immediately call `boot!`. This is what happens most of the time, in particular when the app is started
37
+ # up by Puma to start serving requests.
38
+ #
39
+ # What you should avoid doing is creating an instance of this class and performing logic before later calling `boot!`.
18
40
  #
19
41
  # @param [Class] app_klass subclass of {Brut::Framework::App} representing the Brut app being started up and managed.
20
42
  def initialize(app_klass:)
21
43
  @config = Brut::Framework::Config.new
22
44
  @booted = false
23
45
  @loader = Zeitwerk::Loader.new
24
- @app_klass = app_klass
25
- self.configure!
26
- end
27
-
28
- # Configure Brut and initialize the {Brut::Framework::App} subclass. This should, in theory, only set up values and other
29
- # ancillary data needed to start the app. It should not connect to databases.
30
- def configure!
31
46
  @config.configure!
32
47
 
33
- project_root = Brut.container.project_root
34
- project_env = Brut.container.project_env
35
-
36
- SemanticLogger.default_level = Brut.container.log_level
37
- semantic_logger_appenders = Brut.container.semantic_logger_appenders
38
- if semantic_logger_appenders.kind_of?(Hash)
39
- semantic_logger_appenders = [ semantic_logger_appenders ]
40
- end
41
- if semantic_logger_appenders.length == 0
42
- raise "No loggers are set up - something is wrong"
43
- end
44
- semantic_logger_appenders.each do |appender|
45
- SemanticLogger.add_appender(**appender)
46
- end
47
- SemanticLogger["Brut"].info("Logging set up")
48
-
49
- i18n_locales_dir = Brut.container.i18n_locales_dir
50
- locales = Dir[i18n_locales_dir / "*"].map { |_|
51
- Pathname(_).basename
52
- }
53
- ::I18n.load_path += Dir[i18n_locales_dir / "**/*.rb"]
54
- ::I18n.available_locales = locales.map(&:to_s).map(&:to_sym)
55
-
56
- Brut.container.store(
57
- "zeitwerk_loader",
58
- @loader.class,
59
- "Zeitwerk Loader configured for this app",
60
- @loader
61
- )
62
-
63
- Dir[Brut.container.front_end_src_dir / "*"].each do |dir|
64
- if Pathname(dir).directory?
65
- @loader.push_dir(dir)
66
- end
67
- end
68
- Dir[Brut.container.back_end_src_dir / "*"].each do |dir|
69
- if Pathname(dir).directory?
70
- @loader.push_dir(dir)
71
- end
72
- end
73
- @loader.ignore(Brut.container.migrations_dir)
74
- @loader.inflector.inflect(
75
- "db" => "DB"
76
- )
77
- if Brut.container.auto_reload_classes?
78
- SemanticLogger["Brut"].info("Auto-reloaded configured")
79
- @loader.enable_reloading
80
- else
81
- SemanticLogger["Brut"].info("Classes will not be auto-reloaded")
82
- end
48
+ setup_logging
49
+ setup_i18n
50
+ setup_zeitwerk
83
51
 
84
- @loader.setup
85
- @app = @app_klass.new
52
+ @app = app_klass.new
86
53
  end
87
54
 
88
55
  # Starts up the internals of Brut and that app so that it can receive requests from
@@ -102,6 +69,26 @@ class Brut::Framework::MCP
102
69
  SemanticLogger["Sequel::Database"].info "Not connected to database, so not disconnecting"
103
70
  end
104
71
  end
72
+ Sequel::Database.extension :pg_array
73
+
74
+ sequel_db = Brut.container.sequel_db_handle
75
+
76
+ Sequel::Model.db = sequel_db
77
+
78
+ Sequel::Model.plugin :find_bang
79
+ Sequel::Model.plugin :created_at
80
+ Sequel::Model.plugin :table_select
81
+ Sequel::Model.plugin :skip_saving_columns
82
+
83
+ if !Brut.container.external_id_prefix.nil?
84
+ Sequel::Model.plugin :external_id, global_prefix: Brut.container.external_id_prefix
85
+ end
86
+ if Brut.container.eager_load_classes?
87
+ SemanticLogger["Brut"].info("Eagerly loading app's classes")
88
+ @loader.eager_load
89
+ else
90
+ SemanticLogger["Brut"].info("Lazily loading app's classes")
91
+ end
105
92
  OpenTelemetry::SDK.configure do |c|
106
93
  c.service_name = @app.id
107
94
  if ENV["OTEL_TRACES_EXPORTER"]
@@ -121,28 +108,8 @@ class Brut::Framework::MCP
121
108
  "Tracer for Open Telemetry",
122
109
  OpenTelemetry.tracer_provider.tracer(@app.id)
123
110
  )
124
-
125
- Sequel::Database.extension :pg_array
126
111
  Sequel::Database.extension :brut_instrumentation
127
112
 
128
- sequel_db = Brut.container.sequel_db_handle
129
-
130
- Sequel::Model.db = sequel_db
131
-
132
- Sequel::Model.plugin :find_bang
133
- Sequel::Model.plugin :created_at
134
- Sequel::Model.plugin :table_select
135
- Sequel::Model.plugin :skip_saving_columns
136
-
137
- if !Brut.container.external_id_prefix.nil?
138
- Sequel::Model.plugin :external_id, global_prefix: Brut.container.external_id_prefix
139
- end
140
- if Brut.container.eager_load_classes?
141
- SemanticLogger["Brut"].info("Eagerly loading app's classes")
142
- @loader.eager_load
143
- else
144
- SemanticLogger["Brut"].info("Lazily loading app's classes")
145
- end
146
113
  @app.boot!
147
114
 
148
115
  require "sinatra/base"
@@ -264,9 +231,68 @@ class Brut::Framework::MCP
264
231
 
265
232
  @booted = true
266
233
  end
234
+
267
235
  # @!visibility private
268
236
  def sinatra_app = @sinatra_app
269
237
  # @!visibility private
270
238
  def app = @app
271
239
 
240
+ private
241
+
242
+ def setup_logging
243
+ SemanticLogger.default_level = Brut.container.log_level
244
+ semantic_logger_appenders = Brut.container.semantic_logger_appenders
245
+ if semantic_logger_appenders.kind_of?(Hash)
246
+ semantic_logger_appenders = [ semantic_logger_appenders ]
247
+ end
248
+ if semantic_logger_appenders.length == 0
249
+ raise "No loggers are set up - something is wrong"
250
+ end
251
+ semantic_logger_appenders.each do |appender|
252
+ SemanticLogger.add_appender(**appender)
253
+ end
254
+ SemanticLogger["Brut"].info("Logging set up")
255
+ end
256
+
257
+ def setup_i18n
258
+
259
+ i18n_locales_dir = Brut.container.i18n_locales_dir
260
+ locales = Dir[i18n_locales_dir / "*"].map { Pathname(it).basename }
261
+ ::I18n.load_path += Dir[i18n_locales_dir / "**/*.rb"]
262
+ ::I18n.available_locales = locales.map(&:to_s).map(&:to_sym)
263
+ end
264
+
265
+ def setup_zeitwerk
266
+
267
+ Brut.container.store(
268
+ "zeitwerk_loader",
269
+ @loader.class,
270
+ "Zeitwerk Loader configured for this app",
271
+ @loader
272
+ )
273
+
274
+ Dir[Brut.container.front_end_src_dir / "*"].each do |dir|
275
+ if Pathname(dir).directory?
276
+ @loader.push_dir(dir)
277
+ end
278
+ end
279
+ Dir[Brut.container.back_end_src_dir / "*"].each do |dir|
280
+ if Pathname(dir).directory?
281
+ @loader.push_dir(dir)
282
+ end
283
+ end
284
+ @loader.ignore(Brut.container.migrations_dir)
285
+ @loader.ignore(Brut.container.db_seeds_dir)
286
+ @loader.inflector.inflect(
287
+ "db" => "DB"
288
+ )
289
+ if Brut.container.auto_reload_classes?
290
+ SemanticLogger["Brut"].info("Auto-reloaded configured")
291
+ @loader.enable_reloading
292
+ else
293
+ SemanticLogger["Brut"].info("Classes will not be auto-reloaded")
294
+ end
295
+
296
+ @loader.setup
297
+ end
272
298
  end
@@ -0,0 +1,21 @@
1
+ class SemanticLogger::Appender::Async
2
+ # Set the thread created by SemanticLogger as fork safe to avoid
3
+ # a warning.
4
+ #
5
+ # Here is where Puma uses this
6
+ #
7
+ # https://github.com/puma/puma/blob/ca201ef69757f8830b636251b0af7a51270eb68a/lib/puma/cluster.rb#L377
8
+ #
9
+ # Of note, this change is only OK because on_worker_boot is set up to reopen
10
+ # SemanticLogger's appenders. Otherwise, the warning is legit.
11
+ #
12
+ def thread_with_puma_magic_variable
13
+ thread = thread_without_puma_magic_variable
14
+ thread.thread_variable_set(:fork_safe, true)
15
+ thread
16
+ end
17
+
18
+ alias_method :thread_without_puma_magic_variable, :thread
19
+ alias_method :thread, :thread_with_puma_magic_variable
20
+
21
+ end
@@ -77,9 +77,11 @@ class Brut::FrontEnd::Component
77
77
  #
78
78
  # @return [Brut::FrontEnd::Templates::HTMLSafeString] string containing the component's HTML.
79
79
  def render
80
- Brut.container.component_locator.locate(self.template_name).
81
- then { |erb_file| Brut::FrontEnd::Template.new(erb_file) }.
82
- then { |template| template.render_template(self).html_safe! }
80
+ Brut.container.instrumentation.span("#{self.class}.render") do |span|
81
+ Brut.container.component_locator.locate(self.template_name).
82
+ then { Brut::FrontEnd::Template.new(it) }.
83
+ then { it.render_template(self).html_safe! }
84
+ end
83
85
  end
84
86
 
85
87
  # For components that are private to a page, this returns the name of the page they are a part of.
@@ -130,25 +132,25 @@ class Brut::FrontEnd::Component
130
132
  def component(component_instance,&block)
131
133
  component_name = component_instance.kind_of?(Class) ? component_instance.name : component_instance.class.name
132
134
  Brut.container.instrumentation.span(component_name) do |span|
133
- if component_instance.kind_of?(Class)
134
- if !component_instance.ancestors.include?(Brut::FrontEnd::Component)
135
- raise ArgumentError,"#{component_instance} is not a component and cannot be created"
135
+ if component_instance.kind_of?(Class)
136
+ if !component_instance.ancestors.include?(Brut::FrontEnd::Component)
137
+ raise ArgumentError,"#{component_instance} is not a component and cannot be created"
138
+ end
139
+ component_instance = Thread.current.thread_variable_get(:request_context).
140
+ then { |request_context| request_context.as_constructor_args(component_instance,request_params: nil)
141
+ }.then { |constructor_args| component_instance.new(**constructor_args) }
142
+ span.add_attributes("global_component" => true, "class" => component_instance.class.name)
143
+ else
144
+ span.add_attributes("global_component" => false, "class" => component_instance.class.name)
136
145
  end
137
- component_instance = Thread.current.thread_variable_get(:request_context).
138
- then { |request_context| request_context.as_constructor_args(component_instance,request_params: nil)
139
- }.then { |constructor_args| component_instance.new(**constructor_args) }
140
- span.add_attributes("global_component" => true, "class" => component_instance.class.name)
141
- else
142
- span.add_attributes("global_component" => false, "class" => component_instance.class.name)
143
- end
144
- if !block.nil?
145
- component_instance.yielded_block = block
146
- end
147
- Thread.current.thread_variable_get(:request_context).then {
148
- it.as_method_args(component_instance,:render,request_params: nil, form: nil)
149
- }.then { |render_args|
150
- component_instance.render(**render_args).html_safe!
151
- }
146
+ if !block.nil?
147
+ component_instance.yielded_block = block
148
+ end
149
+ Thread.current.thread_variable_get(:request_context).then {
150
+ it.as_method_args(component_instance,:render,request_params: nil, form: nil)
151
+ }.then { |render_args|
152
+ component_instance.render(**render_args).html_safe!
153
+ }
152
154
  end
153
155
  end
154
156
 
data/lib/brut/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Brut
2
2
  # @!visibility private
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brut
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Bryant Copeland
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-18 00:00:00.000000000 Z
10
+ date: 2025-02-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: irb
@@ -24,7 +24,7 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: dotenv
27
+ name: ostruct
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
@@ -38,7 +38,7 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: ostruct
41
+ name: concurrent-ruby
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
@@ -52,7 +52,7 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
- name: factory_bot
55
+ name: i18n
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
@@ -66,7 +66,7 @@ dependencies:
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
- name: concurrent-ruby
69
+ name: nokogiri
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
@@ -80,7 +80,7 @@ dependencies:
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  - !ruby/object:Gem::Dependency
83
- name: faker
83
+ name: prism
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
@@ -94,7 +94,7 @@ dependencies:
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  - !ruby/object:Gem::Dependency
97
- name: i18n
97
+ name: rack-protection
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - ">="
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
- name: nokogiri
111
+ name: rackup
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
@@ -122,7 +122,7 @@ dependencies:
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  - !ruby/object:Gem::Dependency
125
- name: prism
125
+ name: rexml
126
126
  requirement: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - ">="
@@ -136,7 +136,7 @@ dependencies:
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  - !ruby/object:Gem::Dependency
139
- name: rack-protection
139
+ name: semantic_logger
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - ">="
@@ -150,7 +150,7 @@ dependencies:
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  - !ruby/object:Gem::Dependency
153
- name: rackup
153
+ name: sequel
154
154
  requirement: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - ">="
@@ -164,7 +164,7 @@ dependencies:
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
166
  - !ruby/object:Gem::Dependency
167
- name: rexml
167
+ name: sinatra
168
168
  requirement: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - ">="
@@ -178,7 +178,7 @@ dependencies:
178
178
  - !ruby/object:Gem::Version
179
179
  version: '0'
180
180
  - !ruby/object:Gem::Dependency
181
- name: semantic_logger
181
+ name: temple
182
182
  requirement: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - ">="
@@ -192,7 +192,7 @@ dependencies:
192
192
  - !ruby/object:Gem::Version
193
193
  version: '0'
194
194
  - !ruby/object:Gem::Dependency
195
- name: sequel
195
+ name: tilt
196
196
  requirement: !ruby/object:Gem::Requirement
197
197
  requirements:
198
198
  - - ">="
@@ -206,7 +206,7 @@ dependencies:
206
206
  - !ruby/object:Gem::Version
207
207
  version: '0'
208
208
  - !ruby/object:Gem::Dependency
209
- name: sinatra
209
+ name: tzinfo
210
210
  requirement: !ruby/object:Gem::Requirement
211
211
  requirements:
212
212
  - - ">="
@@ -220,7 +220,7 @@ dependencies:
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
222
  - !ruby/object:Gem::Dependency
223
- name: temple
223
+ name: tzinfo-data
224
224
  requirement: !ruby/object:Gem::Requirement
225
225
  requirements:
226
226
  - - ">="
@@ -234,7 +234,7 @@ dependencies:
234
234
  - !ruby/object:Gem::Version
235
235
  version: '0'
236
236
  - !ruby/object:Gem::Dependency
237
- name: tilt
237
+ name: zeitwerk
238
238
  requirement: !ruby/object:Gem::Requirement
239
239
  requirements:
240
240
  - - ">="
@@ -248,7 +248,7 @@ dependencies:
248
248
  - !ruby/object:Gem::Version
249
249
  version: '0'
250
250
  - !ruby/object:Gem::Dependency
251
- name: tzinfo
251
+ name: opentelemetry-sdk
252
252
  requirement: !ruby/object:Gem::Requirement
253
253
  requirements:
254
254
  - - ">="
@@ -262,7 +262,7 @@ dependencies:
262
262
  - !ruby/object:Gem::Version
263
263
  version: '0'
264
264
  - !ruby/object:Gem::Dependency
265
- name: tzinfo-data
265
+ name: opentelemetry-exporter-otlp
266
266
  requirement: !ruby/object:Gem::Requirement
267
267
  requirements:
268
268
  - - ">="
@@ -276,13 +276,13 @@ dependencies:
276
276
  - !ruby/object:Gem::Version
277
277
  version: '0'
278
278
  - !ruby/object:Gem::Dependency
279
- name: zeitwerk
279
+ name: activesupport
280
280
  requirement: !ruby/object:Gem::Requirement
281
281
  requirements:
282
282
  - - ">="
283
283
  - !ruby/object:Gem::Version
284
284
  version: '0'
285
- type: :runtime
285
+ type: :development
286
286
  prerelease: false
287
287
  version_requirements: !ruby/object:Gem::Requirement
288
288
  requirements:
@@ -290,27 +290,27 @@ dependencies:
290
290
  - !ruby/object:Gem::Version
291
291
  version: '0'
292
292
  - !ruby/object:Gem::Dependency
293
- name: opentelemetry-sdk
293
+ name: rspec
294
294
  requirement: !ruby/object:Gem::Requirement
295
295
  requirements:
296
- - - ">="
296
+ - - "~>"
297
297
  - !ruby/object:Gem::Version
298
- version: '0'
299
- type: :runtime
298
+ version: '3.0'
299
+ type: :development
300
300
  prerelease: false
301
301
  version_requirements: !ruby/object:Gem::Requirement
302
302
  requirements:
303
- - - ">="
303
+ - - "~>"
304
304
  - !ruby/object:Gem::Version
305
- version: '0'
305
+ version: '3.0'
306
306
  - !ruby/object:Gem::Dependency
307
- name: opentelemetry-exporter-otlp
307
+ name: bundler
308
308
  requirement: !ruby/object:Gem::Requirement
309
309
  requirements:
310
310
  - - ">="
311
311
  - !ruby/object:Gem::Version
312
312
  version: '0'
313
- type: :runtime
313
+ type: :development
314
314
  prerelease: false
315
315
  version_requirements: !ruby/object:Gem::Requirement
316
316
  requirements:
@@ -318,7 +318,7 @@ dependencies:
318
318
  - !ruby/object:Gem::Version
319
319
  version: '0'
320
320
  - !ruby/object:Gem::Dependency
321
- name: activesupport
321
+ name: rake
322
322
  requirement: !ruby/object:Gem::Requirement
323
323
  requirements:
324
324
  - - ">="
@@ -332,21 +332,21 @@ dependencies:
332
332
  - !ruby/object:Gem::Version
333
333
  version: '0'
334
334
  - !ruby/object:Gem::Dependency
335
- name: rspec
335
+ name: yard
336
336
  requirement: !ruby/object:Gem::Requirement
337
337
  requirements:
338
- - - "~>"
338
+ - - ">="
339
339
  - !ruby/object:Gem::Version
340
- version: '3.0'
340
+ version: '0'
341
341
  type: :development
342
342
  prerelease: false
343
343
  version_requirements: !ruby/object:Gem::Requirement
344
344
  requirements:
345
- - - "~>"
345
+ - - ">="
346
346
  - !ruby/object:Gem::Version
347
- version: '3.0'
347
+ version: '0'
348
348
  - !ruby/object:Gem::Dependency
349
- name: bundler
349
+ name: rdiscount
350
350
  requirement: !ruby/object:Gem::Requirement
351
351
  requirements:
352
352
  - - ">="
@@ -360,7 +360,7 @@ dependencies:
360
360
  - !ruby/object:Gem::Version
361
361
  version: '0'
362
362
  - !ruby/object:Gem::Dependency
363
- name: rake
363
+ name: rdoc
364
364
  requirement: !ruby/object:Gem::Requirement
365
365
  requirements:
366
366
  - - ">="
@@ -374,7 +374,7 @@ dependencies:
374
374
  - !ruby/object:Gem::Version
375
375
  version: '0'
376
376
  - !ruby/object:Gem::Dependency
377
- name: yard
377
+ name: dotenv
378
378
  requirement: !ruby/object:Gem::Requirement
379
379
  requirements:
380
380
  - - ">="
@@ -388,7 +388,7 @@ dependencies:
388
388
  - !ruby/object:Gem::Version
389
389
  version: '0'
390
390
  - !ruby/object:Gem::Dependency
391
- name: rdiscount
391
+ name: factory_bot
392
392
  requirement: !ruby/object:Gem::Requirement
393
393
  requirements:
394
394
  - - ">="
@@ -402,7 +402,7 @@ dependencies:
402
402
  - !ruby/object:Gem::Version
403
403
  version: '0'
404
404
  - !ruby/object:Gem::Dependency
405
- name: rdoc
405
+ name: faker
406
406
  requirement: !ruby/object:Gem::Requirement
407
407
  requirements:
408
408
  - - ">="
@@ -484,6 +484,7 @@ files:
484
484
  - lib/brut/framework/errors/not_implemented.rb
485
485
  - lib/brut/framework/fussy_type_enforcement.rb
486
486
  - lib/brut/framework/mcp.rb
487
+ - lib/brut/framework/patch_semantic_logger.rb
487
488
  - lib/brut/framework/project_environment.rb
488
489
  - lib/brut/front_end/asset_metadata.rb
489
490
  - lib/brut/front_end/component.rb