brut 0.10.0 → 0.11.0
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/CHANGELOG.md +14 -0
- data/Gemfile.lock +15 -15
- data/assets/YouTubeThumb.pxd +0 -0
- data/bin/new-version +3 -3
- data/brut-css/package-lock.json +2 -2
- data/brut-css/package.json +1 -1
- data/brut-js/package-lock.json +2 -2
- data/brut-js/package.json +1 -1
- data/brutrb.com/getting-started.md +3 -0
- data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element-styled.png +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element.png +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-dialog-browser.png +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-flow.graffle +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-flow.png +0 -0
- data/brutrb.com/instrumentation.md +142 -3
- data/brutrb.com/tutorial.md +29 -1627
- data/brutrb.com/tutorials/01-intro.md +1630 -0
- data/brutrb.com/tutorials/02-dialog.md +569 -0
- data/docs/404.html +2 -2
- data/docs/adrs.html +4 -4
- data/docs/ai.html +4 -4
- data/docs/api/Brut/BackEnd/SeedData.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq.html +1 -1
- data/docs/api/Brut/BackEnd/Validators/FormValidator.html +1 -1
- data/docs/api/Brut/BackEnd/Validators.html +1 -1
- data/docs/api/Brut/BackEnd.html +1 -1
- data/docs/api/Brut/CLI/App.html +1 -1
- data/docs/api/Brut/CLI/AppRunner.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Create.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Drop.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Migrate.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Seed.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Status.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB.html +1 -1
- data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +1 -1
- data/docs/api/Brut/CLI/Apps/DeployBase.html +1 -1
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +1 -1
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/Audit.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/E2e.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/JS.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/Run.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test.html +1 -1
- data/docs/api/Brut/CLI/Apps.html +1 -1
- data/docs/api/Brut/CLI/Command.html +1 -1
- data/docs/api/Brut/CLI/Error.html +1 -1
- data/docs/api/Brut/CLI/ExecutionResults/Result.html +1 -1
- data/docs/api/Brut/CLI/ExecutionResults.html +1 -1
- data/docs/api/Brut/CLI/Executor.html +1 -1
- data/docs/api/Brut/CLI/InvalidOption.html +1 -1
- data/docs/api/Brut/CLI/Options.html +1 -1
- data/docs/api/Brut/CLI/Output.html +1 -1
- data/docs/api/Brut/CLI/SystemExecError.html +1 -1
- data/docs/api/Brut/CLI.html +1 -1
- data/docs/api/Brut/FactoryBot.html +1 -1
- data/docs/api/Brut/Framework/App.html +1 -1
- data/docs/api/Brut/Framework/Config.html +1 -1
- data/docs/api/Brut/Framework/Container.html +1 -1
- data/docs/api/Brut/Framework/Error.html +1 -1
- data/docs/api/Brut/Framework/Errors/AbstractMethod.html +1 -1
- data/docs/api/Brut/Framework/Errors/Bug.html +1 -1
- data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +1 -1
- data/docs/api/Brut/Framework/Errors/MissingParameter.html +1 -1
- data/docs/api/Brut/Framework/Errors/NoClassForPath.html +1 -1
- data/docs/api/Brut/Framework/Errors/NotFound.html +1 -1
- data/docs/api/Brut/Framework/Errors/NotImplemented.html +1 -1
- data/docs/api/Brut/Framework/Errors.html +1 -1
- data/docs/api/Brut/Framework/FussyTypeEnforcement.html +1 -1
- data/docs/api/Brut/Framework/MCP.html +1 -1
- data/docs/api/Brut/Framework/ProjectEnvironment.html +1 -1
- data/docs/api/Brut/Framework.html +1 -1
- data/docs/api/Brut/FrontEnd/AssetPathResolver.html +1 -1
- data/docs/api/Brut/FrontEnd/Component/Helpers.html +1 -1
- data/docs/api/Brut/FrontEnd/Component.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +48 -27
- data/docs/api/Brut/FrontEnd/Components/FormTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Input.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/TimeTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Traceparent.html +1 -1
- data/docs/api/Brut/FrontEnd/Components.html +1 -1
- data/docs/api/Brut/FrontEnd/CsrfProtector.html +1 -1
- data/docs/api/Brut/FrontEnd/Download.html +1 -1
- data/docs/api/Brut/FrontEnd/Flash.html +1 -1
- data/docs/api/Brut/FrontEnd/Form.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/Input.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms.html +1 -1
- data/docs/api/Brut/FrontEnd/GenericResponse.html +1 -1
- data/docs/api/Brut/FrontEnd/Handler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers.html +1 -1
- data/docs/api/Brut/FrontEnd/HandlingResults.html +1 -1
- data/docs/api/Brut/FrontEnd/HttpMethod.html +1 -1
- data/docs/api/Brut/FrontEnd/HttpStatus.html +1 -1
- data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +1 -1
- data/docs/api/Brut/FrontEnd/Layout.html +1 -1
- data/docs/api/Brut/FrontEnd/Middleware.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares.html +1 -1
- data/docs/api/Brut/FrontEnd/Page.html +1 -1
- data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +1 -1
- data/docs/api/Brut/FrontEnd/Pages.html +1 -1
- data/docs/api/Brut/FrontEnd/RequestContext.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHook.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/Route.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing.html +1 -1
- data/docs/api/Brut/FrontEnd/Session.html +1 -1
- data/docs/api/Brut/FrontEnd.html +1 -1
- data/docs/api/Brut/I18n/BaseMethods.html +1 -1
- data/docs/api/Brut/I18n/ForBackEnd.html +1 -1
- data/docs/api/Brut/I18n/ForCLI.html +1 -1
- data/docs/api/Brut/I18n/ForHTML.html +1 -1
- data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +1 -1
- data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +1 -1
- data/docs/api/Brut/I18n.html +1 -1
- data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry.html +1 -1
- data/docs/api/Brut/Instrumentation.html +1 -1
- data/docs/api/Brut/RubocopConfig.html +1 -1
- data/docs/api/Brut/SinatraHelpers/ClassMethods.html +1 -1
- data/docs/api/Brut/SinatraHelpers.html +1 -1
- data/docs/api/Brut/SpecSupport/ClockSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/ComponentSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/E2ETestServer.html +1 -1
- data/docs/api/Brut/SpecSupport/E2eSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/EnhancedNode.html +1 -1
- data/docs/api/Brut/SpecSupport/FlashSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +1 -1
- data/docs/api/Brut/SpecSupport/GeneralSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/HandlerSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers.html +1 -1
- data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/RSpecSetup.html +1 -1
- data/docs/api/Brut/SpecSupport/SessionSupport.html +1 -1
- data/docs/api/Brut/SpecSupport.html +1 -1
- data/docs/api/Brut.html +1 -1
- data/docs/api/Clock.html +1 -1
- data/docs/api/ModuleName.html +1 -1
- data/docs/api/RichString.html +1 -1
- data/docs/api/SemanticLogger/Appender/Async.html +1 -1
- data/docs/api/Sequel/Extensions/BrutInstrumentation.html +1 -1
- data/docs/api/Sequel/Extensions/BrutMigrations.html +1 -1
- data/docs/api/Sequel/Extensions.html +1 -1
- data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +1 -1
- data/docs/api/Sequel/Plugins/CreatedAt.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId.html +1 -1
- data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +1 -1
- data/docs/api/Sequel/Plugins/FindBang.html +1 -1
- data/docs/api/Sequel/Plugins.html +1 -1
- data/docs/api/Sequel.html +1 -1
- data/docs/api/_index.html +1 -1
- data/docs/api/file.README.html +1 -1
- data/docs/api/index.html +1 -1
- data/docs/api/top-level-namespace.html +1 -1
- data/docs/assets/02-confirmation-dialog-browser-element-styled.3NEGM20-.png +0 -0
- data/docs/assets/02-confirmation-dialog-browser-element.DPsf0xUW.png +0 -0
- data/docs/assets/02-confirmation-dialog-browser.DH8ALFO4.png +0 -0
- data/docs/assets/02-confirmation-flow.D9gZ0S5U.png +0 -0
- data/docs/assets/{app.vjGWMSnJ.js → app.0-aKXKdt.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.DPhqaz1b.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.C-ymMW2k.js → VPLocalSearchBox.CW-UBkNA.js} +1 -1
- data/docs/assets/chunks/{theme.pJUosGlI.js → theme.a6feKWJO.js} +2 -2
- data/docs/assets/{components.md.B543a3Lm.js → components.md.BzVRwegp.js} +3 -3
- data/docs/assets/{configuration.md.-foE_iVv.js → configuration.md.eM5wFVi5.js} +1 -1
- data/docs/assets/{form-constraints.md.DK5adCgM.js → form-constraints.md.KTv5cdR4.js} +6 -6
- data/docs/assets/{forms.md.D5-2rgHh.js → forms.md.B3BHvCV3.js} +1 -1
- data/docs/assets/{getting-started.md.Cd4XSZb_.js → getting-started.md.BgR0ZHsl.js} +6 -3
- data/docs/assets/{getting-started.md.Cd4XSZb_.lean.js → getting-started.md.BgR0ZHsl.lean.js} +1 -1
- data/docs/assets/recipes_form-errors.md.Bv5RCKqH.js +66 -0
- data/docs/assets/recipes_form-errors.md.Bv5RCKqH.lean.js +1 -0
- data/docs/assets/tutorial.md.BM40jnoq.js +27 -0
- data/docs/assets/tutorial.md.BM40jnoq.lean.js +1 -0
- data/docs/assets/{tutorial.md.C4zR5XPG.js → tutorials_01-intro.md.BXvYWcO9.js} +5 -25
- data/docs/assets/tutorials_01-intro.md.BXvYWcO9.lean.js +1 -0
- data/docs/assets/tutorials_02-dialog.md.CIeg8R--.js +274 -0
- data/docs/assets/tutorials_02-dialog.md.CIeg8R--.lean.js +1 -0
- data/docs/assets.html +4 -4
- data/docs/brut-js/api/AjaxSubmit.html +1 -1
- data/docs/brut-js/api/AjaxSubmit.js.html +1 -1
- data/docs/brut-js/api/Autosubmit.html +1 -1
- data/docs/brut-js/api/Autosubmit.js.html +1 -1
- data/docs/brut-js/api/BaseCustomElement.html +1 -1
- data/docs/brut-js/api/BaseCustomElement.js.html +1 -1
- data/docs/brut-js/api/BrutCustomElements.html +1 -1
- data/docs/brut-js/api/BufferedLogger.html +1 -1
- data/docs/brut-js/api/ConfirmSubmit.html +1 -1
- data/docs/brut-js/api/ConfirmSubmit.js.html +1 -1
- data/docs/brut-js/api/ConfirmationDialog.html +1 -1
- data/docs/brut-js/api/ConfirmationDialog.js.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessage.html +55 -5
- data/docs/brut-js/api/ConstraintViolationMessage.js.html +18 -3
- data/docs/brut-js/api/ConstraintViolationMessages.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessages.js.html +1 -1
- data/docs/brut-js/api/CopyToClipboard.html +1 -1
- data/docs/brut-js/api/CopyToClipboard.js.html +1 -1
- data/docs/brut-js/api/Form.html +7 -10
- data/docs/brut-js/api/Form.js.html +20 -24
- data/docs/brut-js/api/I18nTranslation.html +1 -1
- data/docs/brut-js/api/I18nTranslation.js.html +1 -1
- data/docs/brut-js/api/LocaleDetection.html +1 -1
- data/docs/brut-js/api/LocaleDetection.js.html +1 -1
- data/docs/brut-js/api/Logger.html +1 -1
- data/docs/brut-js/api/Logger.js.html +1 -1
- data/docs/brut-js/api/Message.html +1 -1
- data/docs/brut-js/api/Message.js.html +1 -1
- data/docs/brut-js/api/PrefixedLogger.html +1 -1
- data/docs/brut-js/api/RichString.html +1 -1
- data/docs/brut-js/api/RichString.js.html +1 -1
- data/docs/brut-js/api/Tabs.html +1 -1
- data/docs/brut-js/api/Tabs.js.html +1 -1
- data/docs/brut-js/api/Tracing.html +1 -1
- data/docs/brut-js/api/Tracing.js.html +1 -1
- data/docs/brut-js/api/external-CustomElementRegistry.html +1 -1
- data/docs/brut-js/api/external-Performance.html +1 -1
- data/docs/brut-js/api/external-Promise.html +1 -1
- data/docs/brut-js/api/external-ValidityState.html +1 -1
- data/docs/brut-js/api/external-Window.html +1 -1
- data/docs/brut-js/api/external-fetch.html +1 -1
- data/docs/brut-js/api/global.html +1 -1
- data/docs/brut-js/api/index.html +1 -1
- data/docs/brut-js/api/index.js.html +1 -1
- data/docs/brut-js/api/module-testing.html +1 -1
- data/docs/brut-js/api/testing.AssetMetadata.html +1 -1
- data/docs/brut-js/api/testing.AssetMetadataLoader.html +1 -1
- data/docs/brut-js/api/testing.CustomElementTest.html +1 -1
- data/docs/brut-js/api/testing.DOMCreator.html +1 -1
- data/docs/brut-js/api/testing_AssetMetadata.js.html +1 -1
- data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +1 -1
- data/docs/brut-js/api/testing_CustomElementTest.js.html +1 -1
- data/docs/brut-js/api/testing_DOMCreator.js.html +1 -1
- data/docs/brut-js/api/testing_index.js.html +1 -1
- data/docs/brut-js.html +4 -4
- data/docs/business-logic.html +4 -4
- data/docs/cli.html +4 -4
- data/docs/components.html +8 -8
- data/docs/configuration.html +5 -5
- data/docs/css.html +4 -4
- data/docs/custom-element-tests.html +4 -4
- data/docs/database-access.html +4 -4
- data/docs/database-schema.html +4 -4
- data/docs/deployment.html +4 -4
- data/docs/dev-environment.html +4 -4
- data/docs/dir-structure.html +4 -4
- data/docs/doc-conventions.html +4 -4
- data/docs/end-to-end-tests.html +4 -4
- data/docs/features.html +4 -4
- data/docs/flash-and-session.html +4 -4
- data/docs/form-constraints.html +11 -11
- data/docs/forms.html +6 -6
- data/docs/getting-started.html +10 -7
- data/docs/handlers.html +4 -4
- data/docs/hashmap.json +1 -1
- data/docs/hooks.html +4 -4
- data/docs/i18n.html +4 -4
- data/docs/index.html +3 -3
- data/docs/instrumentation.html +4 -4
- data/docs/javascript.html +4 -4
- data/docs/jobs.html +4 -4
- data/docs/keyword-injection.html +4 -4
- data/docs/layouts.html +4 -4
- data/docs/lsp.html +4 -4
- data/docs/markdown-examples.html +4 -4
- data/docs/middleware.html +4 -4
- data/docs/overview.html +4 -4
- data/docs/pages.html +4 -4
- data/docs/recipes/alternate-layouts.html +4 -4
- data/docs/recipes/authentication.html +5 -5
- data/docs/recipes/blank-layouts.html +4 -4
- data/docs/recipes/custom-flash.html +4 -4
- data/docs/recipes/form-errors.html +94 -0
- data/docs/recipes/indexed-forms.html +4 -4
- data/docs/recipes/migrations.html +5 -5
- data/docs/recipes/text-field-component.html +4 -4
- data/docs/roadmap.html +4 -4
- data/docs/routes.html +4 -4
- data/docs/security.html +4 -4
- data/docs/seed-data.html +4 -4
- data/docs/space-time-continuum.html +4 -4
- data/docs/tutorial.html +12 -713
- data/docs/tutorials/01-intro.html +736 -0
- data/docs/tutorials/02-dialog.html +302 -0
- data/docs/unit-tests.html +4 -4
- data/docs/why.html +4 -4
- data/lib/brut/instrumentation/methods.rb +153 -0
- data/lib/brut/instrumentation/open_telemetry.rb +1 -0
- data/lib/brut/instrumentation.rb +1 -0
- data/lib/brut/version.rb +1 -1
- data/mkbrut/Gemfile.lock +1 -1
- data/mkbrut/bin/publish +1 -1
- data/mkbrut/lib/mkbrut/version.rb +1 -1
- data/specs/brut/instrumentation/methods.spec.rb +399 -0
- metadata +39 -17
- data/docs/assets/chunks/@localSearchIndexroot.Dn1xGMv_.js +0 -1
- data/docs/assets/tutorial.md.C4zR5XPG.lean.js +0 -1
- /data/docs/assets/{components.md.B543a3Lm.lean.js → components.md.BzVRwegp.lean.js} +0 -0
- /data/docs/assets/{configuration.md.-foE_iVv.lean.js → configuration.md.eM5wFVi5.lean.js} +0 -0
- /data/docs/assets/{form-constraints.md.DK5adCgM.lean.js → form-constraints.md.KTv5cdR4.lean.js} +0 -0
- /data/docs/assets/{forms.md.D5-2rgHh.lean.js → forms.md.B3BHvCV3.lean.js} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8a571939eb22e8583c8c44e8744565ef08cd08930fd3f378bc15ac245bc37da
|
4
|
+
data.tar.gz: 36fae7a408ca4a74d884e5fcc031e68920828bb17414d8b56bf9aff96df8c7e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e63645bd0090fb42de67b546b691cf2cf062da716938a8009db7caf556c613d64085fdc424c5d0c8d30f5edecb69aa58d6b273930309a221a56f36f8241cca49
|
7
|
+
data.tar.gz: db7fc64ad5d4b9615bd9217e73536a7c708a46ae1723841bc3fd2dfc524bee7a93b0e666533c4ed9ddbcbe0e86bcf8b6168c7146bed70a09fab32fbf87b59066
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Brut CHANGELOG
|
2
2
|
|
3
|
+
## v0.11.0 - Aug 27, 2025
|
4
|
+
|
5
|
+
* Added `Brut::Instrumentation::Methods` to allow instrumenting existing methods via `instrument`:
|
6
|
+
```ruby
|
7
|
+
class Widget
|
8
|
+
include Brut::Instrumentation::Methods
|
9
|
+
|
10
|
+
instrument def save
|
11
|
+
end
|
12
|
+
end
|
13
|
+
```
|
14
|
+
See docs for more options and details.
|
15
|
+
* When an exception is caught in a span, the span's status is set to an error.
|
16
|
+
|
3
17
|
## v0.10.0 - Aug 15, 2025
|
4
18
|
|
5
19
|
* Changed `ConstraintViolations` HTML to indicate if a `<brut-cv>` is server-generated, even if it's generating client-side constraint. See #56.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
brut (0.
|
4
|
+
brut (0.11.0)
|
5
5
|
concurrent-ruby
|
6
6
|
i18n
|
7
7
|
irb
|
@@ -23,7 +23,7 @@ PATH
|
|
23
23
|
GEM
|
24
24
|
remote: https://rubygems.org/
|
25
25
|
specs:
|
26
|
-
activesupport (8.0.2)
|
26
|
+
activesupport (8.0.2.1)
|
27
27
|
base64
|
28
28
|
benchmark (>= 0.3)
|
29
29
|
bigdecimal
|
@@ -47,26 +47,26 @@ GEM
|
|
47
47
|
dotenv (3.1.8)
|
48
48
|
drb (2.2.3)
|
49
49
|
erb (5.0.2)
|
50
|
-
factory_bot (6.5.
|
50
|
+
factory_bot (6.5.5)
|
51
51
|
activesupport (>= 6.1.0)
|
52
52
|
faker (3.5.2)
|
53
53
|
i18n (>= 1.8.11, < 2)
|
54
|
-
google-protobuf (4.
|
54
|
+
google-protobuf (4.32.0)
|
55
55
|
bigdecimal
|
56
56
|
rake (>= 13)
|
57
|
-
google-protobuf (4.
|
57
|
+
google-protobuf (4.32.0-aarch64-linux-gnu)
|
58
58
|
bigdecimal
|
59
59
|
rake (>= 13)
|
60
|
-
google-protobuf (4.
|
60
|
+
google-protobuf (4.32.0-arm64-darwin)
|
61
61
|
bigdecimal
|
62
62
|
rake (>= 13)
|
63
|
-
google-protobuf (4.
|
63
|
+
google-protobuf (4.32.0-x86-linux-gnu)
|
64
64
|
bigdecimal
|
65
65
|
rake (>= 13)
|
66
|
-
google-protobuf (4.
|
66
|
+
google-protobuf (4.32.0-x86_64-darwin)
|
67
67
|
bigdecimal
|
68
68
|
rake (>= 13)
|
69
|
-
google-protobuf (4.
|
69
|
+
google-protobuf (4.32.0-x86_64-linux-gnu)
|
70
70
|
bigdecimal
|
71
71
|
rake (>= 13)
|
72
72
|
googleapis-common-protos-types (1.20.0)
|
@@ -99,7 +99,7 @@ GEM
|
|
99
99
|
racc (~> 1.4)
|
100
100
|
nokogiri (1.18.9-x86_64-linux-gnu)
|
101
101
|
racc (~> 1.4)
|
102
|
-
opentelemetry-api (1.
|
102
|
+
opentelemetry-api (1.6.0)
|
103
103
|
opentelemetry-common (0.22.0)
|
104
104
|
opentelemetry-api (~> 1.0)
|
105
105
|
opentelemetry-exporter-otlp (0.30.0)
|
@@ -111,7 +111,7 @@ GEM
|
|
111
111
|
opentelemetry-semantic_conventions
|
112
112
|
opentelemetry-registry (0.4.0)
|
113
113
|
opentelemetry-api (~> 1.1)
|
114
|
-
opentelemetry-sdk (1.8.
|
114
|
+
opentelemetry-sdk (1.8.1)
|
115
115
|
opentelemetry-api (~> 1.1)
|
116
116
|
opentelemetry-common (~> 0.20)
|
117
117
|
opentelemetry-registry (~> 0.2)
|
@@ -149,7 +149,7 @@ GEM
|
|
149
149
|
rdoc (6.14.2)
|
150
150
|
erb
|
151
151
|
psych (>= 4.0.0)
|
152
|
-
regexp_parser (2.11.
|
152
|
+
regexp_parser (2.11.2)
|
153
153
|
reline (0.6.2)
|
154
154
|
io-console (~> 0.5)
|
155
155
|
rspec (3.13.1)
|
@@ -164,8 +164,8 @@ GEM
|
|
164
164
|
rspec-mocks (3.13.5)
|
165
165
|
diff-lcs (>= 1.2.0, < 2.0)
|
166
166
|
rspec-support (~> 3.13.0)
|
167
|
-
rspec-support (3.13.
|
168
|
-
rubocop (1.
|
167
|
+
rspec-support (3.13.5)
|
168
|
+
rubocop (1.80.1)
|
169
169
|
json (~> 2.3)
|
170
170
|
language_server-protocol (~> 3.17.0.2)
|
171
171
|
lint_roller (~> 1.1.0)
|
@@ -202,7 +202,7 @@ GEM
|
|
202
202
|
concurrent-ruby (~> 1.0)
|
203
203
|
tzinfo-data (1.2025.2)
|
204
204
|
tzinfo (>= 1.0.0)
|
205
|
-
unicode-display_width (3.1.
|
205
|
+
unicode-display_width (3.1.5)
|
206
206
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
207
207
|
unicode-emoji (4.0.4)
|
208
208
|
uri (1.0.3)
|
data/assets/YouTubeThumb.pxd
CHANGED
Binary file
|
data/bin/new-version
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
set -e
|
2
2
|
|
3
|
+
VIM=nvim
|
3
4
|
if [ -f /.dockerenv ]; then
|
4
|
-
|
5
|
-
exit 1
|
5
|
+
VIM=vim
|
6
6
|
fi
|
7
7
|
|
8
|
-
|
8
|
+
$VIM -o lib/brut/version.rb mkbrut/lib/mkbrut/version.rb brut-js/package.json brut-css/package.json CHANGELOG.md
|
data/brut-css/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "brut-css",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.11.0",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "brut-css",
|
9
|
-
"version": "0.
|
9
|
+
"version": "0.11.0",
|
10
10
|
"license": "Hippocratic-2.1",
|
11
11
|
"devDependencies": {
|
12
12
|
"comment-parser": "^1.4.1",
|
data/brut-css/package.json
CHANGED
data/brut-js/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "brut-js",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.11.0",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "brut-js",
|
9
|
-
"version": "0.
|
9
|
+
"version": "0.11.0",
|
10
10
|
"license": "Hippocratic-2.1",
|
11
11
|
"devDependencies": {
|
12
12
|
"esbuild": "^0.24.0",
|
data/brut-js/package.json
CHANGED
@@ -9,6 +9,7 @@ The simplest way to use `mkbrut` is to use an existing [Docker image](https://hu
|
|
9
9
|
|
10
10
|
```
|
11
11
|
docker run \
|
12
|
+
--pull always \
|
12
13
|
-v "$PWD":"$PWD" \
|
13
14
|
-w "$PWD" \
|
14
15
|
-u $(id -u):$(id -g) \
|
@@ -33,6 +34,7 @@ For now:
|
|
33
34
|
|
34
35
|
``` [Docker-based]
|
35
36
|
docker run \
|
37
|
+
--pull always \
|
36
38
|
-v "$PWD":"$PWD" \
|
37
39
|
-w "$PWD" \
|
38
40
|
-u $(id -u):$(id -g) \
|
@@ -55,6 +57,7 @@ To create your app without the demo components:
|
|
55
57
|
|
56
58
|
``` [Docker-based]
|
57
59
|
docker run \
|
60
|
+
--pull always \
|
58
61
|
-v "$PWD":"$PWD" \
|
59
62
|
-w "$PWD" \
|
60
63
|
-u $(id -u):$(id -g) \
|
Binary file
|
Binary file
|
Binary file
|
@@ -80,7 +80,99 @@ Here is a non-exhaustive list of what Brut automatically instruments:
|
|
80
80
|
|
81
81
|
### Adding Your Own Instrumentation
|
82
82
|
|
83
|
-
You can add instrumentation in
|
83
|
+
You can add instrumentation in two main ways, both of which can be used together.
|
84
|
+
|
85
|
+
#### Instrumenting Existing Methods
|
86
|
+
|
87
|
+
Although Brut instruments the entrypoints to pages, handlers, and components, you will likely have your own set of back-end business logic that needs to be instrumented. If you aren't trying to diagnose a specific problem and just want to see your back-end class' methods show up in your instrumentation vendor's dashboard, `Brut::Instrumentation::Methods` will be the easiest way to do that.
|
88
|
+
|
89
|
+
`Brut::Instrumentation::Methods` can be included in any class, and provides three class methods, which are *mutually exclusive*:
|
90
|
+
|
91
|
+
* `instrument_all` instruments all methods, public and private.
|
92
|
+
* `instrument_public` instruments only public methods.
|
93
|
+
* `instrument` instruments one or more named methods.
|
94
|
+
|
95
|
+
`initialize` is never instrumented.
|
96
|
+
|
97
|
+
Consider this class:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class Widget
|
101
|
+
def initialize
|
102
|
+
# ...
|
103
|
+
end
|
104
|
+
|
105
|
+
def search
|
106
|
+
# ...
|
107
|
+
end
|
108
|
+
|
109
|
+
def save
|
110
|
+
# ...
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def delete_orphans
|
116
|
+
# ...
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
If we use `instrument_all`…
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
class Widget
|
125
|
+
include Brut::Instrumentation::Methods
|
126
|
+
instrument_all
|
127
|
+
|
128
|
+
# ...
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
…`search`, `save`, and `delete_orphans` will be instrumented. If we use `instrument_public`…
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
class Widget
|
136
|
+
include Brut::Instrumentation::Methods
|
137
|
+
instrument_public
|
138
|
+
|
139
|
+
# ...
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
…then only `search` and `save` are instrumented.
|
144
|
+
|
145
|
+
We can pick and choose by using `instrument`.
|
146
|
+
|
147
|
+
```ruby{2,7,20}
|
148
|
+
class Widget
|
149
|
+
include Brut::Instrumentation::Methods
|
150
|
+
def initialize
|
151
|
+
# ...
|
152
|
+
end
|
153
|
+
|
154
|
+
instrument def search
|
155
|
+
# ...
|
156
|
+
end
|
157
|
+
|
158
|
+
def save
|
159
|
+
# ...
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def delete_orphans
|
165
|
+
# ...
|
166
|
+
end
|
167
|
+
instrument :delete_orphans
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
Above, `search` and `delete_orphans` are instrumented. Since `def` in Ruby returns a symbol, `instrument def search` is the same as `instrument :search`.
|
172
|
+
|
173
|
+
#### Explicit Instrumentation with Spans, Attributes, and Events
|
174
|
+
|
175
|
+
To add explicit instrumentation, you'll create one or more of the following:
|
84
176
|
|
85
177
|
* *Spans* record a block of code. They are shown as a sub-span if one is already in effect. When you
|
86
178
|
create a span, that means it will be shown in the context of the HTTP request.
|
@@ -164,6 +256,39 @@ aforementioned `InstrumentationHandler`.
|
|
164
256
|
|
165
257
|
You should then see client-side tracing information as a sub-span of your HTTP request. The information available depends on the browser, and some browsers don't send much. Also keep in mind that clock drift is real and while client-side timings are accurate, the timestamps will not be.
|
166
258
|
|
259
|
+
### Logging
|
260
|
+
|
261
|
+
Brut configures [SemanticLogger](https://logger.rocketjob.io/), but uses it sparingly. Currently, Brut performs very little logging, and no request logging. You may have noticed that your app doesn't produce a lot of output in development. Brut's assumption is that you will use an OpenTelemetry vendor to understand your app in production or the otel-desktop-viewer in developoment.
|
262
|
+
|
263
|
+
That said, since SemanticLogger is configured, you can use it at will:
|
264
|
+
|
265
|
+
```ruby
|
266
|
+
class HomePage
|
267
|
+
def page_template
|
268
|
+
SemanticLogger[self.class].debug "page being rendered"
|
269
|
+
|
270
|
+
# ...
|
271
|
+
|
272
|
+
end
|
273
|
+
end
|
274
|
+
```
|
275
|
+
|
276
|
+
The logging system is currently not very configurable, and works as follows:
|
277
|
+
|
278
|
+
* In development, log messages are written to the standard output and to `logs/development.log`
|
279
|
+
* In test, log messages are written to `logs/test.log`
|
280
|
+
* In production, log messages are written to the standard output
|
281
|
+
|
282
|
+
The default log level is "debug" for the web app at "fatal" for CLI apps. You can set `LOG_LEVEL` in the environment to change this:
|
283
|
+
|
284
|
+
* `"debug"` - Show all messages
|
285
|
+
* `"info"` - Show info and above (not debug messages)
|
286
|
+
* `"warn"` - Show warnings and above (not info, not debug)
|
287
|
+
* `"error"` - Show errors and fatals only
|
288
|
+
* `"fatal"` - Show fatals only
|
289
|
+
|
290
|
+
Most CLIs also allow `--log-level` to accept one of these strings as wel ass `--verbose` to set the log level to debug.
|
291
|
+
|
167
292
|
## Testing
|
168
293
|
|
169
294
|
Generally you don't want to test instrumentation unless it's highly complex and critical to the app's
|
@@ -182,11 +307,25 @@ specific issues.
|
|
182
307
|
> Technical Notes are for deeper understanding and debugging. While we will try to keep them up-to-date with changes to Brut's
|
183
308
|
> internals, the source code is always more correct.
|
184
309
|
|
185
|
-
_Last Updated
|
310
|
+
_Last Updated Aug 27, 2025_
|
311
|
+
|
312
|
+
OpenTelemetry is notoriously opaque and, ironically, unobservable in its own behavior. Thus, the implementation is subject to change as I figure out what actually does what.
|
186
313
|
|
314
|
+
### Web Requests
|
187
315
|
|
188
|
-
Brut
|
316
|
+
`Brut::FrontEnd::Middlewares::OpenTelemetrySpan` is configured in `Brut::Framework::MCP` as the first middleware. It sets up the outer span for all web requests. Inside each request block (the code internal to Brut that calls handlers or pages), this span's name is modified with the HTTP method and path via the `brut.otel.root_span` in the Rack environment.
|
317
|
+
|
318
|
+
### Client-Side
|
189
319
|
|
190
320
|
The client-side portion of this is highly customized. The Otel open source code for the client side is
|
191
321
|
massive and hugely complex, so Brut decided to try to produce something simple and straightforward as a
|
192
322
|
start. This can and will evolve over time.
|
323
|
+
|
324
|
+
### CLI Commands
|
325
|
+
|
326
|
+
Brut CLI commands are instrumented as well,
|
327
|
+
in `Brut::CLI::App` in `execute!`, however the trace only begins if the underlying command is going to be executed. This may change.
|
328
|
+
|
329
|
+
### Sidekiq Jobs
|
330
|
+
|
331
|
+
Although Brut currently does not provide a default Sidekiq configuration, if you set up Sidekiq and include the `opentelemetry-instrumentation-sidekiq` gem in your app's `Gemfile`, you should see instrumentation of your Sidekiq jobs. In practice, this default set up doesn't seem to work very well, so expect this to change for the better.
|