brut 0.5.0 → 0.9.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/.gitignore +13 -0
- data/CHANGELOG.md +14 -0
- data/Dockerfile.dx +27 -1
- data/Gemfile.lock +33 -1
- data/README.md +19 -0
- data/assets/YouTubeThumb.pxd +0 -0
- data/bin/build +86 -0
- data/bin/ci +40 -0
- data/bin/docs +40 -10
- data/bin/generate-and-run-rubocop +52 -0
- data/bin/publish +61 -0
- data/bin/rubocop +27 -0
- data/bin/setup +52 -0
- data/bin/test +18 -0
- data/brut-css/bin/build +19 -0
- data/brut-css/bin/ci +19 -0
- data/brut-css/bin/docs +19 -0
- data/brut-css/bin/publish +21 -0
- data/brut-css/bin/setup +1 -0
- data/brut-css/package-lock.json +2 -2
- data/brut-css/package.json +1 -1
- data/brut-js/bin/build +15 -6
- data/brut-js/bin/docs +25 -0
- data/brut-js/bin/publish +21 -0
- data/brut-js/bin/setup +1 -0
- data/brut-js/dx +1 -0
- data/brut-js/package-lock.json +2 -2
- data/brut-js/package.json +1 -1
- data/brut.gemspec +34 -28
- data/brutrb.com/.vitepress/config.mjs +3 -0
- data/brutrb.com/bin/setup +1 -0
- data/brutrb.com/database-schema.md +1 -1
- data/brutrb.com/getting-started.md +3 -0
- data/brutrb.com/overview.md +6 -0
- data/brutrb.com/recipes/migrations.md +1 -1
- data/brutrb.com/tutorial.md +7 -3
- data/docker-compose.dx.yml +3 -0
- data/docs/404.html +2 -2
- data/docs/adrs.html +3 -3
- data/docs/ai.html +3 -3
- data/docs/api/Brut/BackEnd/SeedData.html +2 -2
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +2 -2
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +2 -2
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +2 -2
- data/docs/api/Brut/BackEnd/Sidekiq.html +2 -2
- data/docs/api/Brut/BackEnd/Validators/FormValidator.html +2 -2
- data/docs/api/Brut/BackEnd/Validators.html +2 -2
- data/docs/api/Brut/BackEnd.html +2 -2
- data/docs/api/Brut/CLI/App.html +2 -2
- data/docs/api/Brut/CLI/AppRunner.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Create.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Drop.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Migrate.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Seed.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Status.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB.html +2 -2
- data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +2 -2
- data/docs/api/Brut/CLI/Apps/DeployBase.html +2 -2
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +3 -3
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +3 -3
- data/docs/api/Brut/CLI/Apps/Scaffold.html +2 -2
- data/docs/api/Brut/CLI/Apps/Test/Audit.html +2 -2
- data/docs/api/Brut/CLI/Apps/Test/E2e.html +2 -2
- data/docs/api/Brut/CLI/Apps/Test/JS.html +2 -2
- data/docs/api/Brut/CLI/Apps/Test/Run.html +2 -2
- data/docs/api/Brut/CLI/Apps/Test.html +2 -2
- data/docs/api/Brut/CLI/Apps.html +2 -2
- data/docs/api/Brut/CLI/Command.html +2 -2
- data/docs/api/Brut/CLI/Error.html +2 -2
- data/docs/api/Brut/CLI/ExecutionResults/Result.html +2 -2
- data/docs/api/Brut/CLI/ExecutionResults.html +2 -2
- data/docs/api/Brut/CLI/Executor.html +2 -2
- data/docs/api/Brut/CLI/InvalidOption.html +2 -2
- data/docs/api/Brut/CLI/Options.html +80 -2
- data/docs/api/Brut/CLI/Output.html +2 -2
- data/docs/api/Brut/CLI/SystemExecError.html +2 -2
- data/docs/api/Brut/CLI.html +2 -2
- data/docs/api/Brut/FactoryBot.html +3 -3
- data/docs/api/Brut/Framework/App.html +3 -3
- data/docs/api/Brut/Framework/Config.html +25 -3
- data/docs/api/Brut/Framework/Container.html +2 -2
- data/docs/api/Brut/Framework/Error.html +2 -2
- data/docs/api/Brut/Framework/Errors/AbstractMethod.html +2 -2
- data/docs/api/Brut/Framework/Errors/Bug.html +2 -2
- data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +2 -2
- data/docs/api/Brut/Framework/Errors/MissingParameter.html +2 -2
- data/docs/api/Brut/Framework/Errors/NoClassForPath.html +2 -2
- data/docs/api/Brut/Framework/Errors/NotFound.html +2 -2
- data/docs/api/Brut/Framework/Errors/NotImplemented.html +2 -2
- data/docs/api/Brut/Framework/Errors.html +2 -2
- data/docs/api/Brut/Framework/FussyTypeEnforcement.html +2 -2
- data/docs/api/Brut/Framework/MCP.html +21 -11
- data/docs/api/Brut/Framework/ProjectEnvironment.html +2 -2
- data/docs/api/Brut/Framework.html +2 -2
- data/docs/api/Brut/FrontEnd/AssetPathResolver.html +2 -2
- data/docs/api/Brut/FrontEnd/Component/Helpers.html +2 -2
- data/docs/api/Brut/FrontEnd/Component.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/FormTag.html +4 -4
- data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Input.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Inputs.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/TimeTag.html +2 -2
- data/docs/api/Brut/FrontEnd/Components/Traceparent.html +2 -2
- data/docs/api/Brut/FrontEnd/Components.html +2 -2
- data/docs/api/Brut/FrontEnd/CsrfProtector.html +250 -0
- data/docs/api/Brut/FrontEnd/Download.html +2 -2
- data/docs/api/Brut/FrontEnd/Flash.html +2 -2
- data/docs/api/Brut/FrontEnd/Form.html +6 -6
- data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/Input.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +2 -2
- data/docs/api/Brut/FrontEnd/Forms.html +2 -2
- data/docs/api/Brut/FrontEnd/GenericResponse.html +2 -2
- data/docs/api/Brut/FrontEnd/Handler.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +2 -2
- data/docs/api/Brut/FrontEnd/Handlers.html +2 -2
- data/docs/api/Brut/FrontEnd/HandlingResults.html +2 -2
- data/docs/api/Brut/FrontEnd/HttpMethod.html +2 -2
- data/docs/api/Brut/FrontEnd/HttpStatus.html +2 -2
- data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +2 -2
- data/docs/api/Brut/FrontEnd/Layout.html +2 -2
- data/docs/api/Brut/FrontEnd/Middleware.html +2 -2
- data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +2 -2
- data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +2 -2
- data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +2 -2
- data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +2 -2
- data/docs/api/Brut/FrontEnd/Middlewares.html +2 -2
- data/docs/api/Brut/FrontEnd/Page.html +2 -2
- data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +2 -2
- data/docs/api/Brut/FrontEnd/Pages.html +2 -2
- data/docs/api/Brut/FrontEnd/RequestContext.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHook.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +2 -2
- data/docs/api/Brut/FrontEnd/RouteHooks.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing/Route.html +2 -2
- data/docs/api/Brut/FrontEnd/Routing.html +2 -2
- data/docs/api/Brut/FrontEnd/Session.html +2 -2
- data/docs/api/Brut/FrontEnd.html +3 -3
- data/docs/api/Brut/I18n/BaseMethods.html +3 -3
- data/docs/api/Brut/I18n/ForBackEnd.html +2 -2
- data/docs/api/Brut/I18n/ForCLI.html +2 -2
- data/docs/api/Brut/I18n/ForHTML.html +2 -2
- data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +2 -2
- data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +2 -2
- data/docs/api/Brut/I18n.html +2 -2
- data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +2 -2
- data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +2 -2
- data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +2 -2
- data/docs/api/Brut/Instrumentation/OpenTelemetry.html +2 -2
- data/docs/api/Brut/Instrumentation.html +2 -2
- data/docs/api/Brut/RubocopConfig.html +237 -0
- data/docs/api/Brut/SinatraHelpers/ClassMethods.html +2 -2
- data/docs/api/Brut/SinatraHelpers.html +2 -2
- data/docs/api/Brut/SpecSupport/ClockSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/ComponentSupport.html +7 -13
- data/docs/api/Brut/SpecSupport/E2ETestServer.html +2 -2
- data/docs/api/Brut/SpecSupport/E2eSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/EnhancedNode.html +2 -2
- data/docs/api/Brut/SpecSupport/FlashSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +2 -2
- data/docs/api/Brut/SpecSupport/GeneralSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/HandlerSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers.html +2 -2
- data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/RSpecSetup.html +4 -4
- data/docs/api/Brut/SpecSupport/SessionSupport.html +2 -2
- data/docs/api/Brut/SpecSupport.html +2 -2
- data/docs/api/Brut.html +128 -12
- data/docs/api/Clock.html +2 -2
- data/docs/api/ModuleName.html +28 -28
- data/docs/api/RichString.html +22 -22
- data/docs/api/SemanticLogger/Appender/Async.html +2 -2
- data/docs/api/Sequel/Extensions/BrutInstrumentation.html +2 -2
- data/docs/api/Sequel/Extensions/BrutMigrations.html +2 -2
- data/docs/api/Sequel/Extensions.html +2 -2
- data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +2 -2
- data/docs/api/Sequel/Plugins/CreatedAt.html +2 -2
- data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +2 -2
- data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +2 -2
- data/docs/api/Sequel/Plugins/ExternalId.html +2 -2
- data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +2 -2
- data/docs/api/Sequel/Plugins/FindBang.html +2 -2
- data/docs/api/Sequel/Plugins.html +2 -2
- data/docs/api/Sequel.html +2 -2
- data/docs/api/_index.html +16 -2
- data/docs/api/class_list.html +1 -1
- data/docs/api/file.README.html +28 -2
- data/docs/api/index.html +28 -2
- data/docs/api/method_list.html +192 -168
- data/docs/api/top-level-namespace.html +2 -2
- data/docs/assets/{app.D6BuVHo9.js → app.CmkhEsw7.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.DUha-mf5.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.BpvHMbx6.js → VPLocalSearchBox.CDh583Oj.js} +1 -1
- data/docs/assets/chunks/{theme.wlAOvi2f.js → theme.B0_7GeW8.js} +2 -2
- data/docs/assets/{components.md.iLiv2E9X.js → components.md.-22ecBxM.js} +3 -3
- data/docs/assets/{configuration.md.DmuAdsli.js → configuration.md.CLKL1lFf.js} +1 -1
- data/docs/assets/{database-schema.md.C5gXexJi.js → database-schema.md.LpmBPVEU.js} +1 -1
- data/docs/assets/{forms.md.D8aa_qI-.js → forms.md.CBI5--o2.js} +1 -1
- data/docs/assets/{getting-started.md.DLplsDUd.js → getting-started.md.D5nzBZ4J.js} +6 -3
- data/docs/assets/{getting-started.md.DLplsDUd.lean.js → getting-started.md.D5nzBZ4J.lean.js} +1 -1
- data/docs/assets/overview.md.DlKiRRG_.js +1 -0
- data/docs/assets/overview.md.DlKiRRG_.lean.js +1 -0
- data/docs/assets/{recipes_migrations.md.DPN3gQE3.js → recipes_migrations.md.CTcnWDJF.js} +1 -1
- data/docs/assets/tutorial.md.BIb7XT6j.js +1 -0
- data/docs/assets/tutorial.md.BIb7XT6j.lean.js +1 -0
- data/docs/assets.html +3 -3
- 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 +1 -1
- data/docs/brut-js/api/ConstraintViolationMessage.js.html +1 -1
- 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 +1 -1
- data/docs/brut-js/api/Form.js.html +1 -1
- 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 +3 -3
- data/docs/business-logic.html +3 -3
- data/docs/cli.html +3 -3
- data/docs/components.html +7 -7
- data/docs/configuration.html +5 -5
- data/docs/css.html +3 -3
- data/docs/custom-element-tests.html +3 -3
- data/docs/database-access.html +3 -3
- data/docs/database-schema.html +5 -5
- data/docs/deployment.html +3 -3
- data/docs/dev-environment.html +3 -3
- data/docs/dir-structure.html +3 -3
- data/docs/doc-conventions.html +3 -3
- data/docs/end-to-end-tests.html +3 -3
- data/docs/features.html +3 -3
- data/docs/flash-and-session.html +3 -3
- data/docs/form-constraints.html +3 -3
- data/docs/forms.html +5 -5
- data/docs/getting-started.html +9 -6
- data/docs/handlers.html +3 -3
- data/docs/hashmap.json +1 -1
- data/docs/hooks.html +3 -3
- data/docs/i18n.html +3 -3
- data/docs/index.html +3 -3
- data/docs/instrumentation.html +3 -3
- data/docs/javascript.html +3 -3
- data/docs/jobs.html +3 -3
- data/docs/keyword-injection.html +3 -3
- data/docs/layouts.html +3 -3
- data/docs/lsp.html +3 -3
- data/docs/markdown-examples.html +3 -3
- data/docs/middleware.html +3 -3
- data/docs/overview.html +5 -5
- data/docs/pages.html +3 -3
- data/docs/recipes/alternate-layouts.html +3 -3
- data/docs/recipes/authentication.html +3 -3
- data/docs/recipes/blank-layouts.html +3 -3
- data/docs/recipes/custom-flash.html +3 -3
- data/docs/recipes/indexed-forms.html +3 -3
- data/docs/recipes/migrations.html +5 -5
- data/docs/recipes/text-field-component.html +3 -3
- data/docs/roadmap.html +3 -3
- data/docs/routes.html +3 -3
- data/docs/security.html +3 -3
- data/docs/seed-data.html +3 -3
- data/docs/space-time-continuum.html +3 -3
- data/docs/tutorial.html +5 -5
- data/docs/unit-tests.html +3 -3
- data/docs/why.html +3 -3
- data/dx/build +45 -9
- data/lib/brut/cli/app.rb +1 -1
- data/lib/brut/cli/apps/heroku_container_based_deploy.rb +1 -1
- data/lib/brut/cli/apps/scaffold.rb +1 -1
- data/lib/brut/cli/options.rb +4 -0
- data/lib/brut/factory_bot.rb +1 -1
- data/lib/brut/framework/app.rb +1 -1
- data/lib/brut/framework/config.rb +11 -0
- data/lib/brut/framework/mcp.rb +13 -8
- data/lib/brut/front_end/components/form_tag.rb +2 -2
- data/lib/brut/front_end/csrf_protector.rb +30 -0
- data/lib/brut/front_end/form.rb +4 -4
- data/lib/brut/front_end/page.rb +1 -1
- data/lib/brut/front_end/routing.rb +1 -1
- data/lib/brut/front_end.rb +1 -0
- data/lib/brut/i18n/base_methods.rb +1 -1
- data/lib/brut/instrumentation/logger_span_exporter.rb +1 -1
- data/lib/brut/junk_drawer.rb +3 -1
- data/lib/brut/rubocop_config.rb +123 -0
- data/lib/brut/spec_support/component_support.rb +0 -3
- data/lib/brut/spec_support/rspec_setup.rb +2 -2
- data/lib/brut/version.rb +1 -1
- data/mkbrut/.gitignore +16 -0
- data/mkbrut/CODE_OF_CONDUCT.txt +100 -0
- data/mkbrut/Gemfile +3 -0
- data/mkbrut/Gemfile.lock +19 -0
- data/mkbrut/LICENSE.txt +370 -0
- data/mkbrut/README.md +145 -0
- data/mkbrut/Rakefile +2 -0
- data/mkbrut/bin/build +36 -0
- data/mkbrut/bin/ci +19 -0
- data/mkbrut/bin/docs +19 -0
- data/mkbrut/bin/publish +129 -0
- data/mkbrut/bin/rake +16 -0
- data/mkbrut/bin/setup +30 -0
- data/mkbrut/brut-welcome.png +0 -0
- data/mkbrut/deploy/.dockerignore +2 -0
- data/mkbrut/deploy/Dockerfile +25 -0
- data/mkbrut/dx +1 -0
- data/mkbrut/exe/mkbrut +5 -0
- data/mkbrut/lib/mkbrut/app.rb +79 -0
- data/mkbrut/lib/mkbrut/app_id.rb +8 -0
- data/mkbrut/lib/mkbrut/app_name.rb +29 -0
- data/mkbrut/lib/mkbrut/app_options.rb +36 -0
- data/mkbrut/lib/mkbrut/base.rb +57 -0
- data/mkbrut/lib/mkbrut/cli.rb +107 -0
- data/mkbrut/lib/mkbrut/erb_binding_delegate.rb +20 -0
- data/mkbrut/lib/mkbrut/internet_identifier.rb +32 -0
- data/mkbrut/lib/mkbrut/invalid_identifier.rb +4 -0
- data/mkbrut/lib/mkbrut/ops/add_css_import.rb +42 -0
- data/mkbrut/lib/mkbrut/ops/add_i18n_message.rb +74 -0
- data/mkbrut/lib/mkbrut/ops/add_method.rb +48 -0
- data/mkbrut/lib/mkbrut/ops/append_to_file.rb +20 -0
- data/mkbrut/lib/mkbrut/ops/base_op.rb +21 -0
- data/mkbrut/lib/mkbrut/ops/copy_file.rb +12 -0
- data/mkbrut/lib/mkbrut/ops/insert_code_in_method.rb +58 -0
- data/mkbrut/lib/mkbrut/ops/insert_route.rb +52 -0
- data/mkbrut/lib/mkbrut/ops/mkdir.rb +13 -0
- data/mkbrut/lib/mkbrut/ops/prism_parsing_op.rb +70 -0
- data/mkbrut/lib/mkbrut/ops/render_template.rb +26 -0
- data/mkbrut/lib/mkbrut/ops/skip_file.rb +10 -0
- data/mkbrut/lib/mkbrut/ops.rb +16 -0
- data/mkbrut/lib/mkbrut/organization.rb +5 -0
- data/mkbrut/lib/mkbrut/prefix.rb +26 -0
- data/mkbrut/lib/mkbrut/prefixed_io.rb +16 -0
- data/mkbrut/lib/mkbrut/segments/bare_bones.rb +185 -0
- data/mkbrut/lib/mkbrut/segments/demo.rb +121 -0
- data/mkbrut/lib/mkbrut/segments/heroku.rb +30 -0
- data/mkbrut/lib/mkbrut/segments/sidekiq.rb +3 -0
- data/mkbrut/lib/mkbrut/segments.rb +8 -0
- data/mkbrut/lib/mkbrut/version.rb +3 -0
- data/mkbrut/lib/mkbrut/versions.rb +13 -0
- data/mkbrut/lib/mkbrut.rb +18 -0
- data/mkbrut/mkbrut.gemspec +34 -0
- data/mkbrut/templates/Base/.dockerignore +25 -0
- data/mkbrut/templates/Base/.env.development.erb +60 -0
- data/mkbrut/templates/Base/.env.test.erb +8 -0
- data/mkbrut/templates/Base/.gitignore +31 -0
- data/mkbrut/templates/Base/.projections.json +59 -0
- data/mkbrut/templates/Base/Dockerfile.dx +205 -0
- data/mkbrut/templates/Base/Gemfile.erb +53 -0
- data/mkbrut/templates/Base/Procfile.development +5 -0
- data/mkbrut/templates/Base/Procfile.test +1 -0
- data/mkbrut/templates/Base/README.md +4 -0
- data/mkbrut/templates/Base/README.md.erb +40 -0
- data/mkbrut/templates/Base/app/bootstrap.rb +61 -0
- data/mkbrut/templates/Base/app/config/i18n/en/1_defaults.rb +128 -0
- data/mkbrut/templates/Base/app/config/i18n/en/2_app.rb +24 -0
- data/mkbrut/templates/Base/app/public/static/manifest.json.erb +33 -0
- data/mkbrut/templates/Base/app/src/app.rb.erb +37 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/app_data_model.rb +5 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/db.rb +19 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/migrations/20240101130000_citext.rb +6 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/seed/seed_data.rb +9 -0
- data/mkbrut/templates/Base/app/src/front_end/components/app_component.rb +8 -0
- data/mkbrut/templates/Base/app/src/front_end/components/custom_element_registration.rb.erb +7 -0
- data/mkbrut/templates/Base/app/src/front_end/css/index.css +2 -0
- data/mkbrut/templates/Base/app/src/front_end/css/svgs.css +12 -0
- data/mkbrut/templates/Base/app/src/front_end/forms/app_form.rb +4 -0
- data/mkbrut/templates/Base/app/src/front_end/handlers/app_handler.rb +4 -0
- data/mkbrut/templates/Base/app/src/front_end/images/LogoPylon.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/LogoTransit.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-120x120.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-152x152.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-167x167.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-180x180.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/favicon.ico +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/icon.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/mkicons.sh +6 -0
- data/mkbrut/templates/Base/app/src/front_end/js/index.js +6 -0
- data/mkbrut/templates/Base/app/src/front_end/layouts/default_layout.rb.erb +73 -0
- data/mkbrut/templates/Base/app/src/front_end/pages/app_page.rb +11 -0
- data/mkbrut/templates/Base/app/src/front_end/pages/home_page.rb +62 -0
- data/mkbrut/templates/Base/app/src/front_end/support/app_session.rb +6 -0
- data/mkbrut/templates/Base/app/src/front_end/svgs/README.md +5 -0
- data/mkbrut/templates/Base/app/src/front_end/svgs/comment-button.svg +59 -0
- data/mkbrut/templates/Base/bin/README.md.erb +5 -0
- data/mkbrut/templates/Base/bin/build-assets +7 -0
- data/mkbrut/templates/Base/bin/ci +39 -0
- data/mkbrut/templates/Base/bin/console +31 -0
- data/mkbrut/templates/Base/bin/db +9 -0
- data/mkbrut/templates/Base/bin/dbconsole +51 -0
- data/mkbrut/templates/Base/bin/dev +25 -0
- data/mkbrut/templates/Base/bin/release +26 -0
- data/mkbrut/templates/Base/bin/run +86 -0
- data/mkbrut/templates/Base/bin/scaffold +9 -0
- data/mkbrut/templates/Base/bin/setup +256 -0
- data/mkbrut/templates/Base/bin/startup-message +65 -0
- data/mkbrut/templates/Base/bin/test +9 -0
- data/mkbrut/templates/Base/bin/test-server +29 -0
- data/mkbrut/templates/Base/bin/watch-and-build-assets +37 -0
- data/mkbrut/templates/Base/config.ru +16 -0
- data/mkbrut/templates/Base/docker-compose.dx.yml +92 -0
- data/mkbrut/templates/Base/dx/README.md +28 -0
- data/mkbrut/templates/Base/dx/bash_customizations +12 -0
- data/mkbrut/templates/Base/dx/bash_customizations.local +8 -0
- data/mkbrut/templates/Base/dx/build +107 -0
- data/mkbrut/templates/Base/dx/docker-compose.env.erb +25 -0
- data/mkbrut/templates/Base/dx/dx.sh.lib +137 -0
- data/mkbrut/templates/Base/dx/exec +68 -0
- data/mkbrut/templates/Base/dx/prune +19 -0
- data/mkbrut/templates/Base/dx/show-help-in-app-container-then-wait.sh +38 -0
- data/mkbrut/templates/Base/dx/start +30 -0
- data/mkbrut/templates/Base/dx/stop +23 -0
- data/mkbrut/templates/Base/package.json.erb +37 -0
- data/mkbrut/templates/Base/puma.config.rb +53 -0
- data/mkbrut/templates/Base/specs/e2e/home_page.spec.rb.erb +23 -0
- data/mkbrut/templates/Base/specs/front_end/js/SpecHelper.js +24 -0
- data/mkbrut/templates/Base/specs/front_end/pages/home_page.spec.rb +22 -0
- data/mkbrut/templates/Base/specs/lint_factories.spec.rb +7 -0
- data/mkbrut/templates/Base/specs/spec_helper.rb +78 -0
- data/mkbrut/templates/Base/specs/support.rb +2 -0
- data/mkbrut/templates/segments/BareBones/app/src/front_end/handlers/trigger_exception_handler.rb +24 -0
- data/mkbrut/templates/segments/BareBones/app/src/front_end/js/Example.js.erb +49 -0
- data/mkbrut/templates/segments/BareBones/specs/front_end/handlers/trigger_exception_handler.spec.rb +41 -0
- data/mkbrut/templates/segments/BareBones/specs/front_end/js/Example.spec.js.erb +38 -0
- data/mkbrut/templates/segments/Demo/app/src/back_end/data_models/db/guestbook_message.rb +3 -0
- data/mkbrut/templates/segments/Demo/app/src/back_end/data_models/migrations/20250628194124_guestbook.rb +14 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/components/flash_component.rb +36 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/css/constraint-violations.css +18 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/css/fonts.css +19 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/fonts/monaspace-xenon.ttf +0 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/forms/guestbook_message_form.rb +4 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/handlers/guestbook_message_handler.rb +64 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/pages/guestbook_page/message_component.rb +41 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/pages/guestbook_page.rb +43 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/pages/new_guestbook_message_page.rb +64 -0
- data/mkbrut/templates/segments/Demo/specs/back_end/data_models/db/guestbook_message.spec.rb +5 -0
- data/mkbrut/templates/segments/Demo/specs/e2e/guest_message.spec.rb +54 -0
- data/mkbrut/templates/segments/Demo/specs/factories/db/guestbook_message.factory.rb +7 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/components/flash_component.spec.rb +5 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/handlers/guestbook_message_handler.spec.rb +122 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/pages/guestbook_page/message_component.spec.rb +5 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/pages/guestbook_page.spec.rb +52 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/pages/new_guestbook_message_page.spec.rb +5 -0
- data/mkbrut/templates/segments/Heroku/bin/deploy +11 -0
- data/mkbrut/templates/segments/Heroku/deploy/Dockerfile +125 -0
- data/mkbrut/templates/segments/Heroku/deploy/docker-entrypoint +15 -0
- data/mkbrut/templates/segments/Heroku/deploy/heroku_config.rb +26 -0
- data/specs/brut/junk_drawer.spec.rb +4 -0
- metadata +242 -41
- data/.rspec +0 -3
- data/docs/assets/chunks/@localSearchIndexroot.COP2Bcmp.js +0 -1
- data/docs/assets/overview.md.iMnwLO4x.js +0 -1
- data/docs/assets/overview.md.iMnwLO4x.lean.js +0 -1
- data/docs/assets/tutorial.md.BYXj4cOu.js +0 -1
- data/docs/assets/tutorial.md.BYXj4cOu.lean.js +0 -1
- /data/docs/assets/{components.md.iLiv2E9X.lean.js → components.md.-22ecBxM.lean.js} +0 -0
- /data/docs/assets/{configuration.md.DmuAdsli.lean.js → configuration.md.CLKL1lFf.lean.js} +0 -0
- /data/docs/assets/{database-schema.md.C5gXexJi.lean.js → database-schema.md.LpmBPVEU.lean.js} +0 -0
- /data/docs/assets/{forms.md.D8aa_qI-.lean.js → forms.md.CBI5--o2.lean.js} +0 -0
- /data/docs/assets/{recipes_migrations.md.DPN3gQE3.lean.js → recipes_migrations.md.CTcnWDJF.lean.js} +0 -0
@@ -51,7 +51,7 @@ class Brut::CLI::Apps::Scaffold < Brut::CLI::App
|
|
51
51
|
files_to_test_files.each do |source,destination|
|
52
52
|
result = Prism.parse_file(source.to_s)
|
53
53
|
if !result
|
54
|
-
raise "For some reason Prism did not parse #{source
|
54
|
+
raise "For some reason Prism did not parse #{source}"
|
55
55
|
end
|
56
56
|
classes = find_classes(result.value).map { |(module_nodes,class_node)|
|
57
57
|
(module_nodes.map(&:constant_path).map(&:full_name).map(&:to_s) + [class_node.constant_path.full_name.to_s]).compact.join("::")
|
data/lib/brut/cli/options.rb
CHANGED
data/lib/brut/factory_bot.rb
CHANGED
@@ -7,7 +7,7 @@ class Brut::FactoryBot
|
|
7
7
|
def setup!
|
8
8
|
Faker::Config.locale = :en
|
9
9
|
FactoryBot.definition_file_paths = [
|
10
|
-
Brut.container.app_specs_dir / "factories"
|
10
|
+
Brut.container.app_specs_dir / "factories",
|
11
11
|
]
|
12
12
|
FactoryBot.define do
|
13
13
|
to_create { |instance| instance.save }
|
data/lib/brut/framework/app.rb
CHANGED
@@ -89,7 +89,7 @@ class Brut::Framework::App
|
|
89
89
|
raise ArgumentError, "Your error handler block may only accept exception: and http_status_code: as required keyword parameters. The following parameters were found:\n #{messages.join("\n ")}"
|
90
90
|
end
|
91
91
|
if @error_blocks[condition]
|
92
|
-
raise ArgumentError, "You have already configured error handling for condition '#{condition
|
92
|
+
raise ArgumentError, "You have already configured error handling for condition '#{condition}'"
|
93
93
|
end
|
94
94
|
@error_blocks[condition] = block
|
95
95
|
end
|
@@ -319,6 +319,17 @@ class Brut::Framework::Config
|
|
319
319
|
allow_app_override: true,
|
320
320
|
)
|
321
321
|
|
322
|
+
c.store(
|
323
|
+
"csrf_protector",
|
324
|
+
Brut::FrontEnd::CsrfProtector,
|
325
|
+
"Object to allow custom logic related to CSRF protection",
|
326
|
+
allow_app_override: true
|
327
|
+
) do
|
328
|
+
Brut::FrontEnd::CsrfProtector.new
|
329
|
+
end
|
330
|
+
|
331
|
+
|
332
|
+
|
322
333
|
c.store(
|
323
334
|
"semantic_logger_appenders",
|
324
335
|
{ Hash => "if only one appender is needed", Array => "to configure multiple appenders" },
|
data/lib/brut/framework/mcp.rb
CHANGED
@@ -131,9 +131,9 @@ class Brut::Framework::MCP
|
|
131
131
|
exception: ex)
|
132
132
|
rescue => ex2
|
133
133
|
$stderr.puts "While handling an error recording an exception, we get another error from SemanticLogger." + [
|
134
|
-
[ :original_exception,
|
135
|
-
[ :exception_from_recording_exception, ex
|
136
|
-
[ :exception_from_semantic_logger,
|
134
|
+
[ :original_exception, exception ].join(": "),
|
135
|
+
[ :exception_from_recording_exception, ex ].join(": "),
|
136
|
+
[ :exception_from_semantic_logger, ex2 ].join(": "),
|
137
137
|
|
138
138
|
].join(", ")
|
139
139
|
end
|
@@ -174,7 +174,7 @@ class Brut::Framework::MCP
|
|
174
174
|
end
|
175
175
|
|
176
176
|
message = if Brut.container.project_env.development?
|
177
|
-
"Form submission did not include an authenticity token. All forms must include one. To add one, use the `
|
177
|
+
"Form submission did not include an authenticity token. All forms must include one. To add one, use the `Brut::FrontEnd::Components::FormTag` component, or include Brut::FrontEnd::Components::Inputs::CsrfToken somewhere inside your <form> tag"
|
178
178
|
else
|
179
179
|
"Forbidden"
|
180
180
|
end
|
@@ -186,10 +186,15 @@ class Brut::Framework::MCP
|
|
186
186
|
Rack::Protection::AuthenticityToken,
|
187
187
|
[
|
188
188
|
{
|
189
|
-
allow_if: ->(env) {
|
189
|
+
allow_if: ->(env) {
|
190
|
+
brut_owned_path = env["brut.owned_path"]
|
191
|
+
app_allowed = Brut.container.csrf_protector.tap {|_| puts _.class.name }.allowed?(env)
|
192
|
+
|
193
|
+
brut_owned_path || app_allowed
|
194
|
+
},
|
190
195
|
message: message,
|
191
|
-
}
|
192
|
-
]
|
196
|
+
},
|
197
|
+
],
|
193
198
|
],
|
194
199
|
]
|
195
200
|
if Brut.container.auto_reload_classes?
|
@@ -275,7 +280,7 @@ class Brut::Framework::MCP
|
|
275
280
|
in TrueClass
|
276
281
|
nil
|
277
282
|
else
|
278
|
-
raise NoMatchingPatternError, "Result from #{method} hook #{klass}'s #{method} method was a #{result.class} (#{result
|
283
|
+
raise NoMatchingPatternError, "Result from #{method} hook #{klass}'s #{method} method was a #{result.class} (#{result} as a string), which cannot be used to understand the response to generate. Return nil or true if processing should proceed"
|
279
284
|
end
|
280
285
|
end
|
281
286
|
end
|
@@ -36,10 +36,10 @@ class Brut::FrontEnd::Components::FormTag < Brut::FrontEnd::Component
|
|
36
36
|
form_class = form_class.class
|
37
37
|
end
|
38
38
|
if html_attributes[:action]
|
39
|
-
raise ArgumentError, "You cannot specify both for: (#{form_class}) and and action: (#{html_attributes[:action]}) to
|
39
|
+
raise ArgumentError, "You cannot specify both for: (#{form_class}) and and action: (#{html_attributes[:action]}) to #{self.class}"
|
40
40
|
end
|
41
41
|
if html_attributes[:method]
|
42
|
-
raise ArgumentError, "You cannot specify both for: (#{form_class}) and and method: (#{html_attributes[:method]}) to
|
42
|
+
raise ArgumentError, "You cannot specify both for: (#{form_class}) and and method: (#{html_attributes[:method]}) to #{self.class}"
|
43
43
|
end
|
44
44
|
begin
|
45
45
|
route = Brut.container.routing.route(form_class)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Base for custom logic around CSRF protection. Brut configures `Rack::Protection::AuthenticityToken` for all requests, and
|
2
|
+
# this happens early in the request. The idea is that no real POST should be missing a CSRF token. That said, there are times
|
3
|
+
# when it must be skipped, such as for webhooks. In that case, you can extend this class and configure it via
|
4
|
+
# `Brut.container.override("csrf_protector", YourCustomCsrfProtector.new)` in your `App` class' initializer.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class CsrfProtector < Brut::FrontEnd::CsrfProtector
|
8
|
+
# def allowed?(env)
|
9
|
+
# !!env["PATH_INFO"].to_s.match?(/^\/webhooks\//)
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
# # Then, in app.rb
|
13
|
+
# class App < Brut::Framework::App
|
14
|
+
# def id = "some-id"
|
15
|
+
# def organization = "some-org"
|
16
|
+
#
|
17
|
+
# def initialize
|
18
|
+
# Brut.container.override("csrf_protector") do
|
19
|
+
# CsrfProtector.new
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # ...
|
23
|
+
#
|
24
|
+
class Brut::FrontEnd::CsrfProtector
|
25
|
+
|
26
|
+
# Return true if the request should be allowed without a CSRF token. This implementation returns false.
|
27
|
+
def allowed?(env)
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
data/lib/brut/front_end/form.rb
CHANGED
@@ -73,7 +73,7 @@ class Brut::FrontEnd::Form
|
|
73
73
|
}
|
74
74
|
else
|
75
75
|
[
|
76
|
-
input_definition.make_input(value:, index: nil)
|
76
|
+
input_definition.make_input(value:, index: nil),
|
77
77
|
]
|
78
78
|
end
|
79
79
|
|
@@ -109,7 +109,7 @@ class Brut::FrontEnd::Form
|
|
109
109
|
# @return [Brut::FrontEnd::Forms::Input]
|
110
110
|
def inputs(input_name)
|
111
111
|
@inputs.fetch(input_name.to_s)
|
112
|
-
rescue KeyError
|
112
|
+
rescue KeyError
|
113
113
|
raise Brut::Framework::Errors::Bug, "Form does not define the input '#{input_name}'. You must add this to your form. Found these inputs: #{@inputs.keys.join(', ')}"
|
114
114
|
end
|
115
115
|
|
@@ -164,8 +164,8 @@ class Brut::FrontEnd::Form
|
|
164
164
|
true
|
165
165
|
end
|
166
166
|
},
|
167
|
-
index
|
168
|
-
|
167
|
+
index,
|
168
|
+
],
|
169
169
|
]
|
170
170
|
end
|
171
171
|
}.compact
|
data/lib/brut/front_end/page.rb
CHANGED
data/lib/brut/front_end.rb
CHANGED
@@ -9,6 +9,7 @@ module Brut::FrontEnd
|
|
9
9
|
autoload(:AssetPathResolver, "brut/front_end/asset_path_resolver")
|
10
10
|
autoload(:Component, "brut/front_end/component")
|
11
11
|
autoload(:Components, "brut/front_end/component")
|
12
|
+
autoload(:CsrfProtector, "brut/front_end/csrf_protector")
|
12
13
|
autoload(:Download, "brut/front_end/download")
|
13
14
|
autoload(:Flash, "brut/front_end/flash")
|
14
15
|
autoload(:Form, "brut/front_end/form")
|
@@ -211,7 +211,7 @@ module Brut::I18n::BaseMethods
|
|
211
211
|
block_contents = safe(capture(&block))
|
212
212
|
interpolated_values[:block] = block_contents
|
213
213
|
end
|
214
|
-
t_direct(keys_to_check,**interpolated_values
|
214
|
+
t_direct(keys_to_check,**interpolated_values, key_given: key)
|
215
215
|
rescue I18n::MissingInterpolationArgument => ex
|
216
216
|
if ex.key.to_s == "block"
|
217
217
|
raise ArgumentError,"One of the keys #{key.join(", ")} contained a %{block} interpolation value: '#{ex.string}'. This means you must yield a block to `t`"
|
@@ -58,7 +58,7 @@ private
|
|
58
58
|
(span.events || []).each do |event|
|
59
59
|
event_message = (" " * (indent + 2)) + "event:#{event.name}"
|
60
60
|
event_params = {
|
61
|
-
timing: ((event.timestamp - previous_timestamp)/1_000.0).to_i/1_000.0
|
61
|
+
timing: ((event.timestamp - previous_timestamp)/1_000.0).to_i/1_000.0,
|
62
62
|
}.merge(event.attributes).merge(synthetic_attributes)
|
63
63
|
SemanticLogger[self.class].info(event_message,event_params)
|
64
64
|
previous_timestamp = event.timestamp
|
data/lib/brut/junk_drawer.rb
CHANGED
@@ -0,0 +1,123 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "yaml"
|
3
|
+
# Not here:
|
4
|
+
# - prevent use of postfix conditonals entirely
|
5
|
+
module Brut
|
6
|
+
IM_NOT_CALLING_THEM_COPS = {
|
7
|
+
"Gemspec/AddRuntimeDependency" => true,
|
8
|
+
"Lint/AmbiguousAssignment" => true,
|
9
|
+
"Lint/AmbiguousOperator" => true,
|
10
|
+
"Lint/AmbiguousOperatorPrecedence" => true,
|
11
|
+
"Lint/AmbiguousRange" => true,
|
12
|
+
"Lint/AmbiguousRegexpLiteral" => true,
|
13
|
+
"Lint/DuplicateCaseCondition" => true,
|
14
|
+
"Lint/DuplicateElsifCondition" => true,
|
15
|
+
"Lint/Loop" => true,
|
16
|
+
"Lint/RedundantSplatExpansion" => true,
|
17
|
+
"Lint/RedundantStringCoercion" => true,
|
18
|
+
"Lint/RedundantTypeConversion" => true,
|
19
|
+
"Lint/ToJSON" => true,
|
20
|
+
"Style/ColonMethodDefinition" => true,
|
21
|
+
"Style/DefWithParentheses" => true,
|
22
|
+
"Style/InvertibleUnlessCondition" => true,
|
23
|
+
"Style/KeywordArgumentsMerging" => true,
|
24
|
+
"Style/MethodDefParentheses" => true,
|
25
|
+
"Style/MissingRespondToMissing" => true,
|
26
|
+
"Style/MultilineTernaryOperator" => true,
|
27
|
+
"Style/NegatedUnless" => true,
|
28
|
+
"Style/NestedTernaryOperator" => true,
|
29
|
+
"Style/PreferredHashMethods" => true,
|
30
|
+
"Style/UnlessElse" => true,
|
31
|
+
"Style/UnlessLogicalOperators" => true,
|
32
|
+
"Layout/DotPosition" => {
|
33
|
+
"EnforcedStyle" => "trailing",
|
34
|
+
},
|
35
|
+
"Lint/AssignmentInCondition" => {
|
36
|
+
"AllowSafeAssignment" => "false",
|
37
|
+
},
|
38
|
+
"Style/ClassMethodsDefinitions" => {
|
39
|
+
"EnforcedStyle" => "def_self",
|
40
|
+
},
|
41
|
+
"Style/CollectionMethods" => {
|
42
|
+
"PreferredMethods" => {
|
43
|
+
"find" => "detect",
|
44
|
+
"collect" => "map",
|
45
|
+
"find_all" => "select",
|
46
|
+
"member?" => "include?",
|
47
|
+
},
|
48
|
+
},
|
49
|
+
"Style/EndlessMethod" => {
|
50
|
+
"EnforcedStyle" => "allow_single_line",
|
51
|
+
},
|
52
|
+
"Style/For" => {
|
53
|
+
"EnforcedStyle" => "each",
|
54
|
+
},
|
55
|
+
"Style/YodaCondition" => {
|
56
|
+
"EnforcedStyle" => "forbid_for_all_comparison_operators",
|
57
|
+
},
|
58
|
+
"Style/DisableSyntax" => {
|
59
|
+
"DisableSyntax" => [
|
60
|
+
"unless",
|
61
|
+
"and_or_not",
|
62
|
+
"until",
|
63
|
+
],
|
64
|
+
},
|
65
|
+
"Style/TrailingCommaInArrayLiteral" => {
|
66
|
+
"EnforcedStyleForMultiline" => "consistent_comma",
|
67
|
+
},
|
68
|
+
"Style/TrailingCommaInHashLiteral" => {
|
69
|
+
"EnforcedStyleForMultiline" => "consistent_comma",
|
70
|
+
},
|
71
|
+
# Documented, but nonexistent
|
72
|
+
#"Style/ItBlockParameter" => {
|
73
|
+
# "EnforcedStyle" => "allow_single_line",
|
74
|
+
#},
|
75
|
+
}
|
76
|
+
PREAMBLE = {
|
77
|
+
"inherit_mode" => {
|
78
|
+
"merge" => [ "Exclude" ],
|
79
|
+
},
|
80
|
+
"plugins" => [
|
81
|
+
"rubocop-disable_syntax",
|
82
|
+
],
|
83
|
+
"AllCops" => {
|
84
|
+
"DisabledByDefault" => true,
|
85
|
+
"TargetRubyVersion" => RUBY_VERSION.split(".")[0..1].join("."),
|
86
|
+
"SuggestExtensions" => false,
|
87
|
+
"Exclude" => [
|
88
|
+
"local-gems/**/*",
|
89
|
+
"**/local-gems/**/*",
|
90
|
+
"node_modules/**/*",
|
91
|
+
"**/node_modules/**/*",
|
92
|
+
],
|
93
|
+
},
|
94
|
+
}
|
95
|
+
class RubocopConfig
|
96
|
+
def create_ridiculous_yaml
|
97
|
+
if !ARGV[0]
|
98
|
+
raise "You must supply the file where the config will be written"
|
99
|
+
end
|
100
|
+
filename = Pathname(ARGV[0])
|
101
|
+
my_big_yaml_hash_of_doom = {}.merge(PREAMBLE)
|
102
|
+
IM_NOT_CALLING_THEM_COPS.each do |not_a_cop, config|
|
103
|
+
body = case config
|
104
|
+
when Hash
|
105
|
+
config
|
106
|
+
when Array
|
107
|
+
config
|
108
|
+
when true
|
109
|
+
{}
|
110
|
+
else
|
111
|
+
raise "#{config.class}/#{config} is not handled by this contraption"
|
112
|
+
end
|
113
|
+
body["Enabled"] = true
|
114
|
+
my_big_yaml_hash_of_doom[not_a_cop] = body
|
115
|
+
end
|
116
|
+
File.open(filename,"w") do |file|
|
117
|
+
file.puts "# This file is generated! DO NOT EDIT (not that you'd want to - it's YAML!)"
|
118
|
+
file.puts "# The configuration is canonically stored in lib/brut/rubocop_config.rb"
|
119
|
+
file.puts my_big_yaml_hash_of_doom.to_yaml
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -51,9 +51,6 @@ module Brut::SpecSupport::ComponentSupport
|
|
51
51
|
# result = generate_and_parse(HeaderComponent.new(title: "Hello!")
|
52
52
|
# expect(result.e!("h1").text).to eq("Hello!")
|
53
53
|
#
|
54
|
-
# @example Using context
|
55
|
-
# result = generate_and_parse(TableRow.new([ "one", "two" ]), context: "tbody")
|
56
|
-
#
|
57
54
|
# @param [Brut::FrontEnd::Component] component the component instance you wish to generate. This should be set up to simulate the test
|
58
55
|
# you are running.
|
59
56
|
# @yield if the component requires or accepts a yielded block, this is how you do that in the test.
|
@@ -100,10 +100,10 @@ class Brut::SpecSupport::RSpecSetup
|
|
100
100
|
if needs_request_context
|
101
101
|
session = {
|
102
102
|
"session_id" => "test-session-id",
|
103
|
-
"csrf" => "test-csrf-token"
|
103
|
+
"csrf" => "test-csrf-token",
|
104
104
|
}
|
105
105
|
env = {
|
106
|
-
"rack.session" => session
|
106
|
+
"rack.session" => session,
|
107
107
|
}
|
108
108
|
app_session = Brut.container.session_class.new(rack_session: session)
|
109
109
|
request_context = Brut::FrontEnd::RequestContext.new(
|
data/lib/brut/version.rb
CHANGED
data/mkbrut/.gitignore
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# AI droppings
|
2
|
+
/.cursor
|
3
|
+
# Local gem cache
|
4
|
+
/local-gems
|
5
|
+
# Forever banned from ringside
|
6
|
+
/node_modules
|
7
|
+
|
8
|
+
# Local developer credentials - should not be checked in!
|
9
|
+
/dx/credentials
|
10
|
+
/dx/build.args
|
11
|
+
|
12
|
+
# Bundler uses this for locally-built gems.
|
13
|
+
/pkg
|
14
|
+
|
15
|
+
# From hell’s heart I stab at thee; for hate’s sake I spit my last breath at thee.
|
16
|
+
.DS_Store
|
@@ -0,0 +1,100 @@
|
|
1
|
+
Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
Our Pledge
|
4
|
+
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
10
|
+
identity and orientation.
|
11
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
12
|
+
diverse, inclusive, and healthy community.
|
13
|
+
Our Standards
|
14
|
+
Examples of behavior that contributes to a positive environment for our
|
15
|
+
community include:
|
16
|
+
|
17
|
+
* Demonstrating empathy and kindness toward other people
|
18
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
19
|
+
* Giving and gracefully accepting constructive feedback
|
20
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
21
|
+
and learning from the experience
|
22
|
+
* Focusing on what is best not just for us as individuals, but for the overall
|
23
|
+
community
|
24
|
+
|
25
|
+
Examples of unacceptable behavior include:
|
26
|
+
|
27
|
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
28
|
+
any kind
|
29
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
30
|
+
* Public or private harassment
|
31
|
+
* Publishing others’ private information, such as a physical or email address,
|
32
|
+
without their explicit permission
|
33
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
34
|
+
professional setting
|
35
|
+
|
36
|
+
Enforcement Responsibilities
|
37
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
38
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
39
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
40
|
+
or harmful.
|
41
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
42
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
43
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
44
|
+
decisions when appropriate.
|
45
|
+
Scope
|
46
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
47
|
+
an individual is officially representing the community in public spaces.
|
48
|
+
Examples of representing our community include using an official email address,
|
49
|
+
posting via an official social media account, or acting as an appointed
|
50
|
+
representative at an online or offline event.
|
51
|
+
Enforcement
|
52
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
53
|
+
reported to the community leaders responsible for enforcement at
|
54
|
+
abuse@thirdtank.com
|
55
|
+
|
56
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
57
|
+
All community leaders are obligated to respect the privacy and security of the
|
58
|
+
reporter of any incident.
|
59
|
+
Enforcement Guidelines
|
60
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
61
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
62
|
+
1. Correction
|
63
|
+
Community Impact: Use of inappropriate language or other behavior deemed
|
64
|
+
unprofessional or unwelcome in the community.
|
65
|
+
Consequence: A private, written warning from community leaders, providing
|
66
|
+
clarity around the nature of the violation and an explanation of why the
|
67
|
+
behavior was inappropriate. A public apology may be requested.
|
68
|
+
2. Warning
|
69
|
+
Community Impact: A violation through a single incident or series of
|
70
|
+
actions.
|
71
|
+
Consequence: A warning with consequences for continued behavior. No
|
72
|
+
interaction with the people involved, including unsolicited interaction with
|
73
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
74
|
+
includes avoiding interactions in community spaces as well as external channels
|
75
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
76
|
+
ban.
|
77
|
+
3. Temporary Ban
|
78
|
+
Community Impact: A serious violation of community standards, including
|
79
|
+
sustained inappropriate behavior.
|
80
|
+
Consequence: A temporary ban from any sort of interaction or public
|
81
|
+
communication with the community for a specified period of time. No public or
|
82
|
+
private interaction with the people involved, including unsolicited interaction
|
83
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
84
|
+
Violating these terms may lead to a permanent ban.
|
85
|
+
4. Permanent Ban
|
86
|
+
Community Impact: Demonstrating a pattern of violation of community
|
87
|
+
standards, including sustained inappropriate behavior, harassment of an
|
88
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
89
|
+
Consequence: A permanent ban from any sort of public interaction within the
|
90
|
+
community.
|
91
|
+
Attribution
|
92
|
+
This Code of Conduct is adapted from the Contributor Covenant,
|
93
|
+
version 2.1, available at
|
94
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
95
|
+
Community Impact Guidelines were inspired by
|
96
|
+
Mozilla’s code of conduct enforcement ladder.
|
97
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
98
|
+
https://www.contributor-covenant.org/faq. Translations are available at
|
99
|
+
https://www.contributor-covenant.org/translations.
|
100
|
+
|
data/mkbrut/Gemfile
ADDED