brut 0.0.1 → 0.0.2
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/.gitignore +6 -0
- data/Gemfile.lock +66 -1
- data/README.md +36 -0
- data/Rakefile +22 -0
- data/brut.gemspec +7 -0
- data/doc-src/architecture.md +102 -0
- data/doc-src/assets.md +98 -0
- data/doc-src/forms.md +214 -0
- data/doc-src/handlers.md +83 -0
- data/doc-src/javascript.md +265 -0
- data/doc-src/keyword-injection.md +183 -0
- data/doc-src/pages.md +210 -0
- data/doc-src/route-hooks.md +59 -0
- data/docs-todo.md +32 -0
- data/lib/brut/back_end/seed_data.rb +5 -1
- data/lib/brut/back_end/validator.rb +1 -1
- data/lib/brut/back_end/validators/form_validator.rb +31 -6
- data/lib/brut/cli/app.rb +100 -4
- data/lib/brut/cli/app_runner.rb +38 -5
- data/lib/brut/cli/apps/build_assets.rb +4 -6
- data/lib/brut/cli/apps/db.rb +2 -7
- data/lib/brut/cli/apps/scaffold.rb +413 -7
- data/lib/brut/cli/apps/test.rb +14 -1
- data/lib/brut/cli/command.rb +141 -6
- data/lib/brut/cli/error.rb +30 -3
- data/lib/brut/cli/execution_results.rb +44 -6
- data/lib/brut/cli/executor.rb +21 -1
- data/lib/brut/cli/options.rb +29 -2
- data/lib/brut/cli/output.rb +47 -0
- data/lib/brut/cli.rb +26 -0
- data/lib/brut/factory_bot.rb +2 -0
- data/lib/brut/framework/app.rb +38 -5
- data/lib/brut/framework/config.rb +97 -54
- data/lib/brut/framework/container.rb +97 -33
- data/lib/brut/framework/errors/abstract_method.rb +3 -7
- data/lib/brut/framework/errors/missing_parameter.rb +12 -0
- data/lib/brut/framework/errors/no_class_for_path.rb +25 -0
- data/lib/brut/framework/errors/not_found.rb +12 -2
- data/lib/brut/framework/errors/not_implemented.rb +14 -0
- data/lib/brut/framework/errors.rb +18 -0
- data/lib/brut/framework/fussy_type_enforcement.rb +17 -12
- data/lib/brut/framework/mcp.rb +106 -49
- data/lib/brut/framework/project_environment.rb +9 -0
- data/lib/brut/framework.rb +1 -0
- data/lib/brut/front_end/asset_metadata.rb +7 -1
- data/lib/brut/front_end/component.rb +129 -38
- data/lib/brut/front_end/components/constraint_violations.rb +57 -0
- data/lib/brut/front_end/components/form_tag.rb +23 -32
- data/lib/brut/front_end/components/i18n_translations.rb +34 -1
- data/lib/brut/front_end/components/input.rb +3 -0
- data/lib/brut/front_end/components/inputs/csrf_token.rb +2 -0
- data/lib/brut/front_end/components/inputs/radio_button.rb +41 -0
- data/lib/brut/front_end/components/inputs/select.rb +26 -2
- data/lib/brut/front_end/components/inputs/text_field.rb +27 -5
- data/lib/brut/front_end/components/inputs/textarea.rb +24 -4
- data/lib/brut/front_end/components/locale_detection.rb +8 -1
- data/lib/brut/front_end/components/page_identifier.rb +2 -0
- data/lib/brut/front_end/components/time.rb +95 -0
- data/lib/brut/front_end/components/traceparent.rb +22 -0
- data/lib/brut/front_end/download.rb +11 -0
- data/lib/brut/front_end/flash.rb +32 -0
- data/lib/brut/front_end/form.rb +109 -106
- data/lib/brut/front_end/forms/constraint_violation.rb +16 -11
- data/lib/brut/front_end/forms/input.rb +30 -42
- data/lib/brut/front_end/forms/input_declarations.rb +90 -0
- data/lib/brut/front_end/forms/input_definition.rb +45 -30
- data/lib/brut/front_end/forms/radio_button_group_input.rb +46 -0
- data/lib/brut/front_end/forms/radio_button_group_input_definition.rb +29 -0
- data/lib/brut/front_end/forms/select_input.rb +47 -0
- data/lib/brut/front_end/forms/select_input_definition.rb +27 -0
- data/lib/brut/front_end/forms/validity_state.rb +23 -9
- data/lib/brut/front_end/handler.rb +27 -8
- data/lib/brut/front_end/handlers/csp_reporting_handler.rb +4 -2
- data/lib/brut/front_end/handlers/instrumentation_handler.rb +99 -0
- data/lib/brut/front_end/handlers/locale_detection_handler.rb +9 -4
- data/lib/brut/front_end/handlers/missing_handler.rb +9 -0
- data/lib/brut/front_end/handling_results.rb +14 -4
- data/lib/brut/front_end/http_method.rb +13 -1
- data/lib/brut/front_end/http_status.rb +10 -0
- data/lib/brut/front_end/layouts/_internal.html.erb +68 -0
- data/lib/brut/front_end/middleware.rb +5 -0
- data/lib/brut/front_end/middlewares/annotate_brut_owned_paths.rb +15 -0
- data/lib/brut/front_end/middlewares/favicon.rb +16 -0
- data/lib/brut/front_end/middlewares/open_telemetry_span.rb +12 -0
- data/lib/brut/front_end/middlewares/reload_app.rb +27 -9
- data/lib/brut/front_end/page.rb +50 -11
- data/lib/brut/front_end/pages/_missing_page.html.erb +17 -0
- data/lib/brut/front_end/pages/missing_page.rb +36 -0
- data/lib/brut/front_end/request_context.rb +117 -8
- data/lib/brut/front_end/route_hook.rb +43 -1
- data/lib/brut/front_end/route_hooks/age_flash.rb +3 -2
- data/lib/brut/front_end/route_hooks/csp_no_inline_scripts.rb +8 -0
- data/lib/brut/front_end/route_hooks/csp_no_inline_styles_or_scripts.rb +18 -10
- data/lib/brut/front_end/route_hooks/locale_detection.rb +11 -5
- data/lib/brut/front_end/route_hooks/setup_request_context.rb +7 -4
- data/lib/brut/front_end/routing.rb +138 -31
- data/lib/brut/front_end/session.rb +86 -7
- data/lib/brut/front_end/template.rb +17 -2
- data/lib/brut/front_end/templates/block_filter.rb +4 -3
- data/lib/brut/front_end/templates/erb_parser.rb +1 -1
- data/lib/brut/front_end/templates/escapable_filter.rb +2 -0
- data/lib/brut/front_end/templates/html_safe_string.rb +30 -2
- data/lib/brut/front_end/templates/locator.rb +60 -0
- data/lib/brut/i18n/base_methods.rb +4 -0
- data/lib/brut/i18n.rb +1 -0
- data/lib/brut/instrumentation/logger_span_exporter.rb +75 -0
- data/lib/brut/instrumentation/open_telemetry.rb +107 -0
- data/lib/brut/instrumentation.rb +4 -6
- data/lib/brut/junk_drawer.rb +54 -4
- data/lib/brut/sinatra_helpers.rb +42 -38
- data/lib/brut/spec_support/clock_support.rb +6 -0
- data/lib/brut/spec_support/component_support.rb +53 -26
- data/lib/brut/spec_support/e2e_test_server.rb +82 -0
- data/lib/brut/spec_support/enhanced_node.rb +45 -0
- data/lib/brut/spec_support/general_support.rb +14 -3
- data/lib/brut/spec_support/handler_support.rb +2 -0
- data/lib/brut/spec_support/matcher.rb +6 -3
- data/lib/brut/spec_support/matchers/be_page_for.rb +3 -2
- data/lib/brut/spec_support/matchers/have_constraint_violation.rb +22 -9
- data/lib/brut/spec_support/matchers/have_html_attribute.rb +9 -2
- data/lib/brut/spec_support/matchers/have_i18n_string.rb +24 -0
- data/lib/brut/spec_support/matchers/have_link_to.rb +14 -0
- data/lib/brut/spec_support/matchers/have_redirected_to.rb +30 -0
- data/lib/brut/spec_support/matchers/have_rendered.rb +4 -11
- data/lib/brut/spec_support/matchers/have_returned_http_status.rb +16 -8
- data/lib/brut/spec_support/rspec_setup.rb +182 -0
- data/lib/brut/spec_support.rb +8 -3
- data/lib/brut/version.rb +2 -1
- data/lib/brut.rb +28 -5
- data/lib/sequel/extensions/brut_instrumentation.rb +5 -27
- data/lib/sequel/extensions/brut_migrations.rb +18 -8
- data/lib/sequel/plugins/created_at.rb +2 -0
- data/lib/sequel/plugins/external_id.rb +39 -1
- data/lib/sequel/plugins/find_bang.rb +4 -1
- metadata +140 -13
- data/lib/brut/back_end/action.rb +0 -3
- data/lib/brut/back_end/result.rb +0 -46
- data/lib/brut/front_end/components/timestamp.rb +0 -33
- data/lib/brut/instrumentation/basic.rb +0 -66
- data/lib/brut/instrumentation/event.rb +0 -19
- data/lib/brut/instrumentation/http_event.rb +0 -5
- data/lib/brut/instrumentation/subscriber.rb +0 -41
|
@@ -1,19 +1,51 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
module Plugins
|
|
3
|
+
# Configures models with an external id that can be safely shared publicly and safely rotated. The external
|
|
4
|
+
# id is random, however it is prefixed with configurable strings that can indicate what type of model it represents.
|
|
5
|
+
# This disambiguates ids when shared pubnlically or in internal tooling.
|
|
6
|
+
#
|
|
7
|
+
# This extension accepts a configuration option `global_prefix:` that is a string prepended to all external IDs. This ensures
|
|
8
|
+
# that your app's IDs clearly come from your app and not some other app that may be using external ids.
|
|
9
|
+
#
|
|
10
|
+
# To use external ids you must then call {ClassMethods#has_external_id} in your model. This method accepts a string which is
|
|
11
|
+
# appended to the global prefix. This is then *prepended* to a unique identifier. The per-model external id prefix should
|
|
12
|
+
# indicate the type of the model. Note that it's not intended to be used programmatically—it's only for humans to quickly see
|
|
13
|
+
# what type of thing an identifier represents.
|
|
14
|
+
#
|
|
15
|
+
# When {ClassMethods#has_external_id} is called on your model, the column `external_id` will be set on save if it has no value.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# class DB::Widget < AppDataModel
|
|
19
|
+
# has_external_id "wg"
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# Sequel::Model.plugin :external_id, global_prefix: "my"
|
|
23
|
+
#
|
|
24
|
+
# widget = DB::Widget.new(name: "flux capacitor")
|
|
25
|
+
# widget.external_id # => mywg_43792834f9c3a7
|
|
3
26
|
module ExternalId
|
|
27
|
+
# @!visibility private
|
|
4
28
|
def self.apply(model,*args,&block)
|
|
5
29
|
@global_prefix = (args.first || {})[:global_prefix]
|
|
6
30
|
end
|
|
31
|
+
def self.global_prefix = @global_prefix
|
|
7
32
|
|
|
8
33
|
module ClassMethods
|
|
9
|
-
|
|
34
|
+
# @!visibility private
|
|
35
|
+
def global_prefix = Sequel::Plugins::ExternalId.global_prefix
|
|
36
|
+
# Called inside a model's body to indicate that this model has an `external_id` that this plugin should manage and what
|
|
37
|
+
# prefix should be used. Calling this will also alter {InstanceMethods#to_s} to include this id in the string representation.
|
|
38
|
+
#
|
|
39
|
+
# @param prefix [String] a short string identfying the type of this model. It will be prepended to your external_id.
|
|
10
40
|
def has_external_id(prefix)
|
|
11
41
|
global_prefix = find_global_prefix
|
|
12
42
|
@external_id_prefix = RichString.new("#{global_prefix}#{prefix}").to_s_or_nil
|
|
13
43
|
end
|
|
14
44
|
|
|
45
|
+
# @!visibility private
|
|
15
46
|
def external_id_prefix = @external_id_prefix
|
|
16
47
|
|
|
48
|
+
# @!visibility private
|
|
17
49
|
def find_global_prefix(receiver=self)
|
|
18
50
|
if receiver.respond_to?(:global_prefix)
|
|
19
51
|
if receiver.global_prefix.nil?
|
|
@@ -30,6 +62,7 @@ module Sequel
|
|
|
30
62
|
end
|
|
31
63
|
|
|
32
64
|
module InstanceMethods
|
|
65
|
+
# @!visibility private
|
|
33
66
|
def before_save
|
|
34
67
|
if self.class.external_id_prefix
|
|
35
68
|
if self.external_id.nil?
|
|
@@ -39,6 +72,11 @@ module Sequel
|
|
|
39
72
|
end
|
|
40
73
|
super
|
|
41
74
|
end
|
|
75
|
+
# Includes the external id in the super class' representation. This means you can include
|
|
76
|
+
# models in Log messages without having to explicitly fetch the id.
|
|
77
|
+
def to_s
|
|
78
|
+
super.to_s + "[external_id:#{self.external_id}]"
|
|
79
|
+
end
|
|
42
80
|
end
|
|
43
81
|
end
|
|
44
82
|
end
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
module Plugins
|
|
3
|
+
# Adds {ClassMethods#find!} to all models, which behaves as it does in Rails.
|
|
3
4
|
module FindBang
|
|
4
5
|
module ClassMethods
|
|
6
|
+
# Calls `first!`, but provides a more helpful error message when no records are found.
|
|
7
|
+
# @raise [Brut::Framework::Errors::NotFound]
|
|
5
8
|
def find!(**args)
|
|
6
9
|
self.first!(**args)
|
|
7
10
|
rescue Sequel::NoMatchingRow => ex
|
|
8
|
-
raise
|
|
11
|
+
raise Brut::Framework::Errors::NotFound.new(resource_name: self.name,search_terms: args.inspect,context: ex.message)
|
|
9
12
|
end
|
|
10
13
|
end
|
|
11
14
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: brut
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Bryant Copeland
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-02-18 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: irb
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
13
26
|
- !ruby/object:Gem::Dependency
|
|
14
27
|
name: dotenv
|
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,6 +65,20 @@ dependencies:
|
|
|
52
65
|
- - ">="
|
|
53
66
|
- !ruby/object:Gem::Version
|
|
54
67
|
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: concurrent-ruby
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
55
82
|
- !ruby/object:Gem::Dependency
|
|
56
83
|
name: faker
|
|
57
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -262,6 +289,34 @@ dependencies:
|
|
|
262
289
|
- - ">="
|
|
263
290
|
- !ruby/object:Gem::Version
|
|
264
291
|
version: '0'
|
|
292
|
+
- !ruby/object:Gem::Dependency
|
|
293
|
+
name: opentelemetry-sdk
|
|
294
|
+
requirement: !ruby/object:Gem::Requirement
|
|
295
|
+
requirements:
|
|
296
|
+
- - ">="
|
|
297
|
+
- !ruby/object:Gem::Version
|
|
298
|
+
version: '0'
|
|
299
|
+
type: :runtime
|
|
300
|
+
prerelease: false
|
|
301
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
302
|
+
requirements:
|
|
303
|
+
- - ">="
|
|
304
|
+
- !ruby/object:Gem::Version
|
|
305
|
+
version: '0'
|
|
306
|
+
- !ruby/object:Gem::Dependency
|
|
307
|
+
name: opentelemetry-exporter-otlp
|
|
308
|
+
requirement: !ruby/object:Gem::Requirement
|
|
309
|
+
requirements:
|
|
310
|
+
- - ">="
|
|
311
|
+
- !ruby/object:Gem::Version
|
|
312
|
+
version: '0'
|
|
313
|
+
type: :runtime
|
|
314
|
+
prerelease: false
|
|
315
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
316
|
+
requirements:
|
|
317
|
+
- - ">="
|
|
318
|
+
- !ruby/object:Gem::Version
|
|
319
|
+
version: '0'
|
|
265
320
|
- !ruby/object:Gem::Dependency
|
|
266
321
|
name: activesupport
|
|
267
322
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -318,6 +373,48 @@ dependencies:
|
|
|
318
373
|
- - ">="
|
|
319
374
|
- !ruby/object:Gem::Version
|
|
320
375
|
version: '0'
|
|
376
|
+
- !ruby/object:Gem::Dependency
|
|
377
|
+
name: yard
|
|
378
|
+
requirement: !ruby/object:Gem::Requirement
|
|
379
|
+
requirements:
|
|
380
|
+
- - ">="
|
|
381
|
+
- !ruby/object:Gem::Version
|
|
382
|
+
version: '0'
|
|
383
|
+
type: :development
|
|
384
|
+
prerelease: false
|
|
385
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
386
|
+
requirements:
|
|
387
|
+
- - ">="
|
|
388
|
+
- !ruby/object:Gem::Version
|
|
389
|
+
version: '0'
|
|
390
|
+
- !ruby/object:Gem::Dependency
|
|
391
|
+
name: rdiscount
|
|
392
|
+
requirement: !ruby/object:Gem::Requirement
|
|
393
|
+
requirements:
|
|
394
|
+
- - ">="
|
|
395
|
+
- !ruby/object:Gem::Version
|
|
396
|
+
version: '0'
|
|
397
|
+
type: :development
|
|
398
|
+
prerelease: false
|
|
399
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
400
|
+
requirements:
|
|
401
|
+
- - ">="
|
|
402
|
+
- !ruby/object:Gem::Version
|
|
403
|
+
version: '0'
|
|
404
|
+
- !ruby/object:Gem::Dependency
|
|
405
|
+
name: rdoc
|
|
406
|
+
requirement: !ruby/object:Gem::Requirement
|
|
407
|
+
requirements:
|
|
408
|
+
- - ">="
|
|
409
|
+
- !ruby/object:Gem::Version
|
|
410
|
+
version: '0'
|
|
411
|
+
type: :development
|
|
412
|
+
prerelease: false
|
|
413
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
414
|
+
requirements:
|
|
415
|
+
- - ">="
|
|
416
|
+
- !ruby/object:Gem::Version
|
|
417
|
+
version: '0'
|
|
321
418
|
description: NOT YET RELEASED - An opinionated web framework build on web standards
|
|
322
419
|
email:
|
|
323
420
|
- davec@thirdtank.com
|
|
@@ -337,7 +434,16 @@ files:
|
|
|
337
434
|
- bin/rake
|
|
338
435
|
- bin/setup
|
|
339
436
|
- brut.gemspec
|
|
437
|
+
- doc-src/architecture.md
|
|
438
|
+
- doc-src/assets.md
|
|
439
|
+
- doc-src/forms.md
|
|
440
|
+
- doc-src/handlers.md
|
|
441
|
+
- doc-src/javascript.md
|
|
442
|
+
- doc-src/keyword-injection.md
|
|
443
|
+
- doc-src/pages.md
|
|
444
|
+
- doc-src/route-hooks.md
|
|
340
445
|
- docker-compose.dx.yml
|
|
446
|
+
- docs-todo.md
|
|
341
447
|
- dx/build
|
|
342
448
|
- dx/docker-compose.env
|
|
343
449
|
- dx/dx.sh.lib
|
|
@@ -348,8 +454,6 @@ files:
|
|
|
348
454
|
- dx/start
|
|
349
455
|
- dx/stop
|
|
350
456
|
- lib/brut.rb
|
|
351
|
-
- lib/brut/back_end/action.rb
|
|
352
|
-
- lib/brut/back_end/result.rb
|
|
353
457
|
- lib/brut/back_end/seed_data.rb
|
|
354
458
|
- lib/brut/back_end/validator.rb
|
|
355
459
|
- lib/brut/back_end/validators/form_validator.rb
|
|
@@ -374,38 +478,57 @@ files:
|
|
|
374
478
|
- lib/brut/framework/errors.rb
|
|
375
479
|
- lib/brut/framework/errors/abstract_method.rb
|
|
376
480
|
- lib/brut/framework/errors/bug.rb
|
|
481
|
+
- lib/brut/framework/errors/missing_parameter.rb
|
|
482
|
+
- lib/brut/framework/errors/no_class_for_path.rb
|
|
377
483
|
- lib/brut/framework/errors/not_found.rb
|
|
484
|
+
- lib/brut/framework/errors/not_implemented.rb
|
|
378
485
|
- lib/brut/framework/fussy_type_enforcement.rb
|
|
379
486
|
- lib/brut/framework/mcp.rb
|
|
380
487
|
- lib/brut/framework/project_environment.rb
|
|
381
488
|
- lib/brut/front_end/asset_metadata.rb
|
|
382
489
|
- lib/brut/front_end/component.rb
|
|
490
|
+
- lib/brut/front_end/components/constraint_violations.rb
|
|
383
491
|
- lib/brut/front_end/components/form_tag.rb
|
|
384
492
|
- lib/brut/front_end/components/i18n_translations.rb
|
|
385
493
|
- lib/brut/front_end/components/input.rb
|
|
386
494
|
- lib/brut/front_end/components/inputs/csrf_token.rb
|
|
495
|
+
- lib/brut/front_end/components/inputs/radio_button.rb
|
|
387
496
|
- lib/brut/front_end/components/inputs/select.rb
|
|
388
497
|
- lib/brut/front_end/components/inputs/text_field.rb
|
|
389
498
|
- lib/brut/front_end/components/inputs/textarea.rb
|
|
390
499
|
- lib/brut/front_end/components/locale_detection.rb
|
|
391
500
|
- lib/brut/front_end/components/page_identifier.rb
|
|
392
|
-
- lib/brut/front_end/components/
|
|
501
|
+
- lib/brut/front_end/components/time.rb
|
|
502
|
+
- lib/brut/front_end/components/traceparent.rb
|
|
393
503
|
- lib/brut/front_end/download.rb
|
|
394
504
|
- lib/brut/front_end/flash.rb
|
|
395
505
|
- lib/brut/front_end/form.rb
|
|
396
506
|
- lib/brut/front_end/forms/constraint_violation.rb
|
|
397
507
|
- lib/brut/front_end/forms/input.rb
|
|
508
|
+
- lib/brut/front_end/forms/input_declarations.rb
|
|
398
509
|
- lib/brut/front_end/forms/input_definition.rb
|
|
510
|
+
- lib/brut/front_end/forms/radio_button_group_input.rb
|
|
511
|
+
- lib/brut/front_end/forms/radio_button_group_input_definition.rb
|
|
512
|
+
- lib/brut/front_end/forms/select_input.rb
|
|
513
|
+
- lib/brut/front_end/forms/select_input_definition.rb
|
|
399
514
|
- lib/brut/front_end/forms/validity_state.rb
|
|
400
515
|
- lib/brut/front_end/handler.rb
|
|
401
516
|
- lib/brut/front_end/handlers/csp_reporting_handler.rb
|
|
517
|
+
- lib/brut/front_end/handlers/instrumentation_handler.rb
|
|
402
518
|
- lib/brut/front_end/handlers/locale_detection_handler.rb
|
|
519
|
+
- lib/brut/front_end/handlers/missing_handler.rb
|
|
403
520
|
- lib/brut/front_end/handling_results.rb
|
|
404
521
|
- lib/brut/front_end/http_method.rb
|
|
405
522
|
- lib/brut/front_end/http_status.rb
|
|
523
|
+
- lib/brut/front_end/layouts/_internal.html.erb
|
|
406
524
|
- lib/brut/front_end/middleware.rb
|
|
525
|
+
- lib/brut/front_end/middlewares/annotate_brut_owned_paths.rb
|
|
526
|
+
- lib/brut/front_end/middlewares/favicon.rb
|
|
527
|
+
- lib/brut/front_end/middlewares/open_telemetry_span.rb
|
|
407
528
|
- lib/brut/front_end/middlewares/reload_app.rb
|
|
408
529
|
- lib/brut/front_end/page.rb
|
|
530
|
+
- lib/brut/front_end/pages/_missing_page.html.erb
|
|
531
|
+
- lib/brut/front_end/pages/missing_page.rb
|
|
409
532
|
- lib/brut/front_end/request_context.rb
|
|
410
533
|
- lib/brut/front_end/route_hook.rb
|
|
411
534
|
- lib/brut/front_end/route_hooks/age_flash.rb
|
|
@@ -421,20 +544,22 @@ files:
|
|
|
421
544
|
- lib/brut/front_end/templates/erb_parser.rb
|
|
422
545
|
- lib/brut/front_end/templates/escapable_filter.rb
|
|
423
546
|
- lib/brut/front_end/templates/html_safe_string.rb
|
|
547
|
+
- lib/brut/front_end/templates/locator.rb
|
|
424
548
|
- lib/brut/i18n.rb
|
|
425
549
|
- lib/brut/i18n/base_methods.rb
|
|
426
550
|
- lib/brut/i18n/for_cli.rb
|
|
427
551
|
- lib/brut/i18n/for_html.rb
|
|
428
552
|
- lib/brut/i18n/http_accept_language.rb
|
|
429
553
|
- lib/brut/instrumentation.rb
|
|
430
|
-
- lib/brut/instrumentation/
|
|
431
|
-
- lib/brut/instrumentation/
|
|
432
|
-
- lib/brut/instrumentation/http_event.rb
|
|
433
|
-
- lib/brut/instrumentation/subscriber.rb
|
|
554
|
+
- lib/brut/instrumentation/logger_span_exporter.rb
|
|
555
|
+
- lib/brut/instrumentation/open_telemetry.rb
|
|
434
556
|
- lib/brut/junk_drawer.rb
|
|
435
557
|
- lib/brut/sinatra_helpers.rb
|
|
436
558
|
- lib/brut/spec_support.rb
|
|
559
|
+
- lib/brut/spec_support/clock_support.rb
|
|
437
560
|
- lib/brut/spec_support/component_support.rb
|
|
561
|
+
- lib/brut/spec_support/e2e_test_server.rb
|
|
562
|
+
- lib/brut/spec_support/enhanced_node.rb
|
|
438
563
|
- lib/brut/spec_support/flash_support.rb
|
|
439
564
|
- lib/brut/spec_support/general_support.rb
|
|
440
565
|
- lib/brut/spec_support/handler_support.rb
|
|
@@ -444,8 +569,12 @@ files:
|
|
|
444
569
|
- lib/brut/spec_support/matchers/be_routing_for.rb
|
|
445
570
|
- lib/brut/spec_support/matchers/have_constraint_violation.rb
|
|
446
571
|
- lib/brut/spec_support/matchers/have_html_attribute.rb
|
|
572
|
+
- lib/brut/spec_support/matchers/have_i18n_string.rb
|
|
573
|
+
- lib/brut/spec_support/matchers/have_link_to.rb
|
|
574
|
+
- lib/brut/spec_support/matchers/have_redirected_to.rb
|
|
447
575
|
- lib/brut/spec_support/matchers/have_rendered.rb
|
|
448
576
|
- lib/brut/spec_support/matchers/have_returned_http_status.rb
|
|
577
|
+
- lib/brut/spec_support/rspec_setup.rb
|
|
449
578
|
- lib/brut/spec_support/session_support.rb
|
|
450
579
|
- lib/brut/version.rb
|
|
451
580
|
- lib/sequel/extensions/brut_instrumentation.rb
|
|
@@ -461,7 +590,6 @@ metadata:
|
|
|
461
590
|
homepage_uri: https://naildrivin5.com
|
|
462
591
|
source_code_uri: https://naildrivin5.com
|
|
463
592
|
changelog_uri: https://naildrivin5.com
|
|
464
|
-
post_install_message:
|
|
465
593
|
rdoc_options: []
|
|
466
594
|
require_paths:
|
|
467
595
|
- lib
|
|
@@ -476,8 +604,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
476
604
|
- !ruby/object:Gem::Version
|
|
477
605
|
version: '0'
|
|
478
606
|
requirements: []
|
|
479
|
-
rubygems_version: 3.
|
|
480
|
-
signing_key:
|
|
607
|
+
rubygems_version: 3.6.4
|
|
481
608
|
specification_version: 4
|
|
482
609
|
summary: NOT YET RELEASED - Web Framework Built around Ruby, Web Standards, Simplicity,
|
|
483
610
|
and Object-Orientation
|
data/lib/brut/back_end/action.rb
DELETED
data/lib/brut/back_end/result.rb
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# The result of back-end processing, which is essentially
|
|
2
|
-
# a container for constraint violations and arbitrary context.
|
|
3
|
-
class Brut::BackEnd::Result
|
|
4
|
-
attr_reader :constraint_violations, :context
|
|
5
|
-
|
|
6
|
-
def initialize
|
|
7
|
-
@constraint_violations = {}
|
|
8
|
-
@context = {}
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def constraint_violation!(object:,
|
|
12
|
-
field:,
|
|
13
|
-
key:,
|
|
14
|
-
context: {})
|
|
15
|
-
@constraint_violations[object] ||= {}
|
|
16
|
-
@constraint_violations[object][field] ||= {}
|
|
17
|
-
@constraint_violations[object][field][key] = context
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def each_violation(&block)
|
|
21
|
-
@constraint_violations.each do |object,fields|
|
|
22
|
-
fields.each do |field,keys|
|
|
23
|
-
keys.each do |key,context|
|
|
24
|
-
block.(object,field,key,context)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def []=(key_in_context,object)
|
|
31
|
-
@context[key_in_context] = object
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def [](key_in_context)
|
|
35
|
-
@context.fetch(key_in_context)
|
|
36
|
-
rescue KeyError => ex
|
|
37
|
-
raise KeyError.new(
|
|
38
|
-
"Context did not contain '#{key_in_context}' (#{key_in_context.class}). Context has these keys: #{@context.keys.join(',')}",
|
|
39
|
-
receiver: ex.receiver,
|
|
40
|
-
key: ex.key)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def constraint_violations? = self.constraint_violations.any?
|
|
45
|
-
|
|
46
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require "rexml"
|
|
2
|
-
class Brut::FrontEnd::Components::Timestamp < Brut::FrontEnd::Component
|
|
3
|
-
include Brut::I18n::ForHTML
|
|
4
|
-
def initialize(timestamp:, format: :full, skip_year_if_same: true, attribute_format: :iso_8601, **only_contains_class)
|
|
5
|
-
@timestamp = timestamp
|
|
6
|
-
formats = [ format ]
|
|
7
|
-
if @timestamp.year == Time.now.year && skip_year_if_same
|
|
8
|
-
formats.unshift("#{format}_no_year")
|
|
9
|
-
end
|
|
10
|
-
format_keys = formats.map { |f| "time.formats.#{f}" }
|
|
11
|
-
found_format = formats.zip(::I18n.t(format_keys)).detect { |(key,value)|
|
|
12
|
-
value !~ /^Translation missing/
|
|
13
|
-
}.first
|
|
14
|
-
if found_format.nil?
|
|
15
|
-
raise ArgumentError,"format #{format} is not a known time format"
|
|
16
|
-
end
|
|
17
|
-
@format = found_format.to_sym
|
|
18
|
-
|
|
19
|
-
if ::I18n.t("time.formats.#{attribute_format}") =~ /^Translation missing/
|
|
20
|
-
raise ArgumentError,"attribute_format #{attribute_format} is not a known time format"
|
|
21
|
-
end
|
|
22
|
-
@attribute_format = attribute_format.to_sym
|
|
23
|
-
@class_attribute = only_contains_class[:class] || ""
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def render(clock:)
|
|
28
|
-
timestamp_in_time_zone = clock.in_time_zone(@timestamp)
|
|
29
|
-
html_tag(:time, class: @class_attribute, datetime: ::I18n.l(timestamp_in_time_zone,format: @attribute_format)) do
|
|
30
|
-
::I18n.l(timestamp_in_time_zone,format: @format)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
class Brut::Instrumentation::Basic
|
|
2
|
-
def initialize
|
|
3
|
-
@subscribers = Concurrent::Set.new
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
class TypeChecking < Brut::Instrumentation::Basic
|
|
7
|
-
def instrument(event,&block)
|
|
8
|
-
if !event.kind_of?(Brut::Instrumentation::Event)
|
|
9
|
-
raise "You cannot instrument a #{event.class} - it must be a Brut::Instrumentation::Event or subclass"
|
|
10
|
-
end
|
|
11
|
-
super
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def instrument(event,&block)
|
|
16
|
-
block ||= ->() {}
|
|
17
|
-
|
|
18
|
-
start = Time.now
|
|
19
|
-
result = nil
|
|
20
|
-
exception = nil
|
|
21
|
-
|
|
22
|
-
begin
|
|
23
|
-
result = block.(event)
|
|
24
|
-
rescue => ex
|
|
25
|
-
exception = ex
|
|
26
|
-
end
|
|
27
|
-
stop = Time.now
|
|
28
|
-
notify(event:,start:,stop:,exception:)
|
|
29
|
-
if exception
|
|
30
|
-
raise exception
|
|
31
|
-
else
|
|
32
|
-
result
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def subscribe(subscriber=:use_block,&block)
|
|
37
|
-
if block.nil? && subscriber == :use_block
|
|
38
|
-
raise ArgumentError,"subscriber requires a Brut::Instrumentation::Subscriber or a block"
|
|
39
|
-
end
|
|
40
|
-
if !block.nil? && subscriber != :use_block
|
|
41
|
-
raise ArgumentError,"subscriber requires a Brut::Instrumentation::Subscriber or a block, not both"
|
|
42
|
-
end
|
|
43
|
-
if block.nil?
|
|
44
|
-
if subscriber.kind_of?(Proc)
|
|
45
|
-
subscriber = Brut::Instrumentation::Subscriber.from_proc(subscriber)
|
|
46
|
-
elsif !subscriber.kind_of?(Brut::Instrumentation::Subscriber)
|
|
47
|
-
raise ArgumentError, "subscriber must be a Proc or Brut::Instrumentation::Subscriber, not a #{subscriber.class}"
|
|
48
|
-
end
|
|
49
|
-
else
|
|
50
|
-
subscriber = Brut::Instrumentation::Subscriber.from_proc(block)
|
|
51
|
-
end
|
|
52
|
-
@subscribers << subscriber
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def notify(event:,start:,stop:,exception:)
|
|
56
|
-
Thread.new do
|
|
57
|
-
@subscribers.each do |subscriber|
|
|
58
|
-
begin
|
|
59
|
-
subscriber.(event:,start:,stop:,exception:)
|
|
60
|
-
rescue => ex
|
|
61
|
-
warn "#{subscriber} raised #{ex}"
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
class Brut::Instrumentation::Event
|
|
2
|
-
include Brut::Framework::FussyTypeEnforcement
|
|
3
|
-
|
|
4
|
-
attr_reader :category,
|
|
5
|
-
:subcategory,
|
|
6
|
-
:name,
|
|
7
|
-
:details
|
|
8
|
-
|
|
9
|
-
def initialize(category:,
|
|
10
|
-
subcategory:nil,
|
|
11
|
-
name:,
|
|
12
|
-
details:{})
|
|
13
|
-
@category = type!(category,String,"category",required: true, coerce: :to_s)
|
|
14
|
-
@subcategory = type!(subcategory,String,"subcategory",required: false, coerce: :to_s)
|
|
15
|
-
@name = type!(name,String,"name",required:true,coerce: :to_s)
|
|
16
|
-
@details = type!(details,Hash,"details",required:false) || {}
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
class Brut::Instrumentation::Subscriber
|
|
2
|
-
def self.from_proc(block)
|
|
3
|
-
required_parameter_names_found = self.instance_method(:call).parameters.map { |(type,name)| [ name, false ] }.to_h
|
|
4
|
-
unexpected_parameter_names_error = {}
|
|
5
|
-
|
|
6
|
-
block.parameters.each do |(type,name)|
|
|
7
|
-
if required_parameter_names_found.key?(name)
|
|
8
|
-
if type == :key || type == :keyreq
|
|
9
|
-
required_parameter_names_found[name] = true
|
|
10
|
-
else
|
|
11
|
-
unexpected_parameter_names[name] = "Not a keyword arg"
|
|
12
|
-
end
|
|
13
|
-
elsif type != :key
|
|
14
|
-
if type == :keyreq
|
|
15
|
-
unexpected_parameter_names[name] = "keyword arg without a default value"
|
|
16
|
-
else
|
|
17
|
-
unexpected_parameter_names[name] = "Not a keyword arg"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
errors = []
|
|
22
|
-
if unexpected_parameter_names_error.any?
|
|
23
|
-
messages = unexpected_parameter_names_error.map { |name,problem|
|
|
24
|
-
"#{name} - #{problem}"
|
|
25
|
-
}.join(", ")
|
|
26
|
-
errors << "Unexpected parameters were required, so this cannot be used as a subscriber: #{messages}"
|
|
27
|
-
end
|
|
28
|
-
if required_parameter_names_found.any? { |_name,found| !found }
|
|
29
|
-
messages = required_parameter_names_found.select { |_name,found| !found }.map { |name,_found| "#{name} must be a keyword argument" }.join(",")
|
|
30
|
-
errors << "Required parameters were missing, so this cannot be used as a subscriber: #{messages}"
|
|
31
|
-
end
|
|
32
|
-
if errors.any?
|
|
33
|
-
raise ArgumentError,errors.join(", ")
|
|
34
|
-
end
|
|
35
|
-
block
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def call(event:,start:,stop:,exception:)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
end
|