brut 0.4.0 → 0.8.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 +4 -0
- data/CHANGELOG.md +36 -1
- data/Dockerfile.dx +19 -0
- data/Gemfile.lock +1 -1
- data/README.md +19 -0
- data/assets/MetroIcon.graffle +0 -0
- data/assets/YouTubeThumb.pxd +0 -0
- data/bin/build +86 -0
- data/bin/ci +36 -0
- data/bin/docs +39 -9
- data/bin/publish +61 -0
- data/bin/setup +6 -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-css/src/css/flex.css +1 -1
- data/brut-css/src/docs/includes/body-and-header.html.ejs +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-js/specs/AjaxSubmit.spec.js +100 -7
- data/brut-js/src/AjaxSubmit.js +76 -40
- data/brut.gemspec +2 -2
- data/brutrb.com/adrs.md +1 -0
- data/brutrb.com/bin/setup +1 -0
- data/brutrb.com/getting-started.md +3 -0
- data/brutrb.com/overview.md +6 -0
- data/brutrb.com/tutorial.md +7 -3
- data/docs/404.html +2 -2
- data/docs/adrs.html +5 -5
- data/docs/ai.html +3 -3
- 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 +2 -2
- 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 +86 -2
- data/docs/api/Brut/FrontEnd/Component.html +78 -9
- data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/FormTag.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Input.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Inputs.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/TimeTag.html +3 -3
- data/docs/api/Brut/FrontEnd/Components/Traceparent.html +3 -3
- data/docs/api/Brut/FrontEnd/Components.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 +3 -3
- 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 +31 -23
- data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +3 -3
- 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/SinatraHelpers/ClassMethods.html +13 -11
- 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/method_list.html +92 -76
- data/docs/api/top-level-namespace.html +1 -1
- data/docs/assets/{adrs.md.JRxZ5uYE.js → adrs.md.BxjHi9-8.js} +1 -1
- data/docs/assets/adrs.md.BxjHi9-8.lean.js +1 -0
- data/docs/assets/{app.AkS4fHzI.js → app.DyQLb4Ot.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.CmtZyrFA.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.By6un1FD.js → VPLocalSearchBox.T1iA-eJx.js} +1 -1
- data/docs/assets/chunks/{theme.DwiUPdci.js → theme.ChwsbWjK.js} +2 -2
- data/docs/assets/{components.md.BfeWD9sX.js → components.md.DHh-NwKs.js} +3 -3
- data/docs/assets/{configuration.md.DoSBNc0H.js → configuration.md.D8Wz3oJU.js} +1 -1
- data/docs/assets/{forms.md.DFveP5g_.js → forms.md.BRE85eju.js} +1 -1
- data/docs/assets/{getting-started.md.DZWjCVC0.js → getting-started.md.2ioiTe-B.js} +6 -3
- data/docs/assets/{getting-started.md.DZWjCVC0.lean.js → getting-started.md.2ioiTe-B.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/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-css/brut.max.css +1 -1
- data/docs/brut-css/classes/appearances.html +1 -1
- data/docs/brut-css/classes/background-colors.html +1 -1
- data/docs/brut-css/classes/border-colors.html +1 -1
- data/docs/brut-css/classes/borders.html +1 -1
- data/docs/brut-css/classes/dimensions.html +1 -1
- data/docs/brut-css/classes/flex.html +3 -3
- data/docs/brut-css/classes/foreground-colors.html +1 -1
- data/docs/brut-css/classes/junk-drawer.html +1 -1
- data/docs/brut-css/classes/layout.html +1 -1
- data/docs/brut-css/classes/lists.html +1 -1
- data/docs/brut-css/classes/positioning.html +1 -1
- data/docs/brut-css/classes/spacings.html +1 -1
- data/docs/brut-css/classes/typography.html +1 -1
- data/docs/brut-css/customization/advanced-configuration.html +1 -1
- data/docs/brut-css/customization/breakpoints.html +1 -1
- data/docs/brut-css/customization/design-system.html +1 -1
- data/docs/brut-css/customization/pseudo-classes.html +1 -1
- data/docs/brut-css/getting-started/core-concepts.html +1 -1
- data/docs/brut-css/getting-started/installation.html +1 -1
- data/docs/brut-css/getting-started/overview.html +1 -1
- data/docs/brut-css/getting-started/simple-example.html +1 -1
- data/docs/brut-css/index.html +1 -1
- data/docs/brut-css/properties/colors.html +1 -1
- data/docs/brut-css/properties/spacings.html +1 -1
- data/docs/brut-css/properties/typography.html +1 -1
- data/docs/brut-js/api/AjaxSubmit.html +56 -7
- data/docs/brut-js/api/AjaxSubmit.js.html +77 -41
- 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 +3 -3
- 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 +3 -3
- 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/lib/brut/cli/apps/scaffold.rb +1 -1
- data/lib/brut/framework/mcp.rb +1 -1
- data/lib/brut/front_end/component.rb +19 -0
- data/lib/brut/front_end/components/form_tag.rb +2 -2
- data/lib/brut/front_end/page.rb +11 -7
- data/lib/brut/sinatra_helpers.rb +1 -0
- 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/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 +32 -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
- metadata +188 -24
- data/brut-js/CHANGELOG.md +0 -5
- data/docs/assets/adrs.md.JRxZ5uYE.lean.js +0 -1
- data/docs/assets/chunks/@localSearchIndexroot.C9FqcQxD.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.BfeWD9sX.lean.js → components.md.DHh-NwKs.lean.js} +0 -0
- /data/docs/assets/{configuration.md.DoSBNc0H.lean.js → configuration.md.D8Wz3oJU.lean.js} +0 -0
- /data/docs/assets/{forms.md.DFveP5g_.lean.js → forms.md.BRE85eju.lean.js} +0 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
# This file is heavily documented to explain what is going on and why.
|
2
|
+
# If you are reading this, however, you now own this file and can
|
3
|
+
# change it how you like. Just be sure you understand how it works in the
|
4
|
+
# context of docker-compose.dx.yml and the files in dx/,
|
5
|
+
# which are referred to as the Workspace
|
6
|
+
#
|
7
|
+
# This file is a set of instructions to build a Docker _image_, which is
|
8
|
+
# then use to _start_ a _container_.
|
9
|
+
|
10
|
+
# This uses a base image where Ruby is already installed. This saves
|
11
|
+
# us from having to install Ruby ourselves. Change this whenever you update
|
12
|
+
# Ruby. Note that by convention, "3.4" will be whatever the latest point
|
13
|
+
# release of Ruby 3.4 is. If you don't want that, specify an exact Ruby version here.
|
14
|
+
# Note that this value is intended to be in sync with the tag of the image
|
15
|
+
# found in dx/docker-compose.env
|
16
|
+
FROM ruby:3.4
|
17
|
+
|
18
|
+
# This attempts to make RUN directives fail when UNIX pipelines are involved
|
19
|
+
SHELL [ "/bin/bash", "-o", "pipefail", "-c" ]
|
20
|
+
|
21
|
+
# This tells apt-get and friends not to ask for interactive input
|
22
|
+
# as this creates massive confusion in the context of building a Docker image.
|
23
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
24
|
+
|
25
|
+
# These packages are needed to set up other repos to install other
|
26
|
+
# packages and/or are useful in installing other software
|
27
|
+
#
|
28
|
+
# - ca-certificates - needed by Postgres client
|
29
|
+
# - curl - needed by various installation instructions
|
30
|
+
# - gnupg - needed to install Docker
|
31
|
+
# - lsb-release - needed by Postgres install instructions
|
32
|
+
# - rsync - needed by Brut's build_assets command
|
33
|
+
# - vim - needed when we want to edit files inside container
|
34
|
+
RUN apt-get -y clean && \
|
35
|
+
apt-get -y update && \
|
36
|
+
apt-get install --quiet --yes \
|
37
|
+
ca-certificates \
|
38
|
+
curl \
|
39
|
+
gnupg \
|
40
|
+
lsb-release \
|
41
|
+
rsync \
|
42
|
+
vim
|
43
|
+
|
44
|
+
# These are dependencies needed to install Chromium via Playright.
|
45
|
+
# You can check this list via
|
46
|
+
#
|
47
|
+
# npx playwright install-deps --dry-run chromium
|
48
|
+
#
|
49
|
+
RUN apt-get install -y --no-install-recommends libasound2 \
|
50
|
+
libatk-bridge2.0-0 \
|
51
|
+
libatk1.0-0 \
|
52
|
+
libatspi2.0-0 \
|
53
|
+
libcairo2 \
|
54
|
+
libcups2 \
|
55
|
+
libdbus-1-3 \
|
56
|
+
libdrm2 \
|
57
|
+
libgbm1 \
|
58
|
+
libglib2.0-0 \
|
59
|
+
libnspr4 \
|
60
|
+
libnss3 \
|
61
|
+
libpango-1.0-0 \
|
62
|
+
libx11-6 \
|
63
|
+
libxcb1 \
|
64
|
+
libxcomposite1 \
|
65
|
+
libxdamage1 \
|
66
|
+
libxext6 \
|
67
|
+
libxfixes3 \
|
68
|
+
libxkbcommon0 \
|
69
|
+
libxrandr2 \
|
70
|
+
xvfb \
|
71
|
+
fonts-noto-color-emoji \
|
72
|
+
fonts-unifont \
|
73
|
+
libfontconfig1 \
|
74
|
+
libfreetype6 \
|
75
|
+
xfonts-scalable \
|
76
|
+
fonts-liberation \
|
77
|
+
fonts-ipafont-gothic \
|
78
|
+
fonts-wqy-zenhei \
|
79
|
+
fonts-tlwg-loma-otf \
|
80
|
+
fonts-freefont-ttf
|
81
|
+
|
82
|
+
|
83
|
+
# Install Docker itself. Note that this is installed only what is needed to run
|
84
|
+
# the Docker CLI - the docker-compose.dx.yml will connect this docker's socket
|
85
|
+
# to the one on the host. This sets up "Docker outside Docker" and
|
86
|
+
# is here only to build the production Docker containers and to push
|
87
|
+
# them to a repository. This is not intended to run containers from
|
88
|
+
# inside this one.
|
89
|
+
RUN install -m 0755 -d /etc/apt/keyrings && \
|
90
|
+
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
|
91
|
+
chmod a+r /etc/apt/keyrings/docker.gpg && \
|
92
|
+
echo \
|
93
|
+
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
|
94
|
+
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
|
95
|
+
tee /etc/apt/sources.list.d/docker.list > /dev/null && \
|
96
|
+
apt-get update --quiet --yes && \
|
97
|
+
apt-get install --quiet --yes docker-ce \
|
98
|
+
docker-ce-cli \
|
99
|
+
containerd.io \
|
100
|
+
docker-buildx-plugin \
|
101
|
+
docker-compose-plugin
|
102
|
+
|
103
|
+
|
104
|
+
# Install Postgres Client, per https://www.postgresql.org/download/linux/debian/
|
105
|
+
# Note that ca-certificates and curl are installed above
|
106
|
+
#
|
107
|
+
# Also note that the version here should match the version set up in
|
108
|
+
# docker-compose.dx.yml
|
109
|
+
RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \
|
110
|
+
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
|
111
|
+
apt-get update && \
|
112
|
+
apt-get -y install postgresql-client-16
|
113
|
+
|
114
|
+
# Update RubyGems and Bundler, setting RubyGems not to generate
|
115
|
+
# documentation as that is slow and you likely won't use it.
|
116
|
+
RUN echo "gem: --no-document" >> ~/.gemrc && \
|
117
|
+
gem update --system && \
|
118
|
+
gem install bundler
|
119
|
+
|
120
|
+
# Installs the Heroku CLI, per Heroku docs at
|
121
|
+
# https://devcenter.heroku.com/articles/heroku-cli#install-with-ubuntu-debian-apt-get
|
122
|
+
RUN curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
|
123
|
+
|
124
|
+
# Up to now, RUN directives ran as the root user. When using this container
|
125
|
+
# for development, we do not want to run as the root user. On macOS, this is not
|
126
|
+
# a big deal, but in Linux, the root user inside this container can create files
|
127
|
+
# as the root user on your computer. You don't want that.
|
128
|
+
|
129
|
+
# What is tricky is that we ultimately want the non-root user here
|
130
|
+
# to have the same UID and same groups as your user on your host/computer.
|
131
|
+
# And, we want that user to be able to run Docker commands.
|
132
|
+
|
133
|
+
# First, set up some build args that `dx/build` will override with the actual values.
|
134
|
+
# The reason these all have values is that Docker will not fail if they are omitted,
|
135
|
+
# but it will behave strangely.
|
136
|
+
#
|
137
|
+
# Their user id, which ideally is overridden to match your user id on the host
|
138
|
+
ARG user_uid=10001
|
139
|
+
|
140
|
+
# Their group id, which ideally is overridden to match your group id on the host
|
141
|
+
ARG user_gid=10002
|
142
|
+
|
143
|
+
# The group id that can access /var/run/docker.sock on the host.
|
144
|
+
# If this isn't mapped properly, no docker-out-of-docker commands will work
|
145
|
+
ARG docker_gid=10003
|
146
|
+
|
147
|
+
# This can be blank if the OS is such that the user inside the container can access
|
148
|
+
# /var/run/docker.sock simply from being in docker_gid. If this is not
|
149
|
+
# the case (as on macOS), it is not only sad, but we must add the group
|
150
|
+
# 0 (root) to the groups our new user is in.
|
151
|
+
ARG sadly_user_must_be_added_to_root=
|
152
|
+
|
153
|
+
# Create the user's group ID if it does not exist
|
154
|
+
RUN getent group ${user_gid} || groupadd --gid ${user_gid} appgroup
|
155
|
+
|
156
|
+
# Create the docker group id if it does not exist
|
157
|
+
RUN getent group ${docker_gid} || groupadd --gid ${docker_gid} hostdocker
|
158
|
+
|
159
|
+
# Create the user and set up their shell.
|
160
|
+
# Note that we put bash_customizations in both .profile and .bashrc
|
161
|
+
# to increase the chances they are used when running bash in various configurations
|
162
|
+
RUN useradd --uid ${user_uid} --gid ${user_gid} --groups ${sadly_user_must_be_added_to_root}${docker_gid} --create-home --home-dir /home/appuser appuser && \
|
163
|
+
echo ". ~/.bash_customizations" >> /home/appuser/.profile && \
|
164
|
+
echo ". ~/.bash_customizations.local" >> /home/appuser/.profile && \
|
165
|
+
echo ". ~/.bash_customizations" >> /home/appuser/.bashrc && \
|
166
|
+
echo ". ~/.bash_customizations.local" >> /home/appuser/.bashrc
|
167
|
+
|
168
|
+
# Now we must grant ownership to the new user over various files they will need to
|
169
|
+
# run or use
|
170
|
+
COPY --chown=appuser:${user_gid} dx/show-help-in-app-container-then-wait.sh /home/appuser
|
171
|
+
COPY --chown=appuser:${user_gid} dx/bash_customizations /home/appuser/.bash_customizations
|
172
|
+
COPY --chown=appuser:${user_gid} dx/bash_customizations.local /home/appuser/.bash_customizations.local
|
173
|
+
|
174
|
+
# This switches to the new user, meaniung all subsequent RUN directives will
|
175
|
+
# be run as this user. The USER directive allows changing both the user
|
176
|
+
# and the current group. We are omitting the group part of that because
|
177
|
+
# to include would exclude the user from all other groups we just set them up
|
178
|
+
# as belonging to.
|
179
|
+
USER appuser
|
180
|
+
|
181
|
+
# Install NodeJS, per https://nodejs.org/en/download
|
182
|
+
#
|
183
|
+
# Yes, this is seting up nvm just to install one version of node we will ever user in
|
184
|
+
# here and yes, this sucks. But it's better to use the vendor's official
|
185
|
+
# recommendation.
|
186
|
+
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash && \
|
187
|
+
\. "$HOME/.nvm/nvm.sh" && \
|
188
|
+
nvm install 22 && \
|
189
|
+
node -v && nvm current && npm -v
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
# This arg should have the version of playwright present in the app's Gemfile.lock.
|
194
|
+
# This is because the playright NodeJS library and the Ruby gem must have the same
|
195
|
+
# version or things won't work right. The value is blank because it really has to be
|
196
|
+
# detected during `dx/build`.
|
197
|
+
ARG PLAYWRIGHT_VERSION
|
198
|
+
# Now install the version of Playwright we detected as well as Chromium. NOTE, we
|
199
|
+
# must install Chromium, not chrome, because there is no version of Chrome for an
|
200
|
+
# ARM-based Debian linux, which is what this Dockerfile will build on an Apple
|
201
|
+
# Silicon Mac.
|
202
|
+
RUN \. "$HOME/.nvm/nvm.sh" && \
|
203
|
+
nvm use default && \
|
204
|
+
npm install -g playwright@$PLAYWRIGHT_VERSION && \
|
205
|
+
npx playwright install chromium
|
@@ -0,0 +1,53 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
# Gemfile organization:
|
4
|
+
#
|
5
|
+
# 1. Brut is always at the top
|
6
|
+
# 2. The rest of the gems are in alphabetical order
|
7
|
+
# 3. Do not specify a gem version unless there is a specific reason.
|
8
|
+
# 4. Each gem should have a comment preceding it explaining
|
9
|
+
# what the gem is for and why the project needs it.
|
10
|
+
# 5. If a version was specified, make sure the comment explains
|
11
|
+
# why it had to be specified and the conditions under which it
|
12
|
+
# can be removed.
|
13
|
+
# 6. Do not create group blocks. Instead, use the group: option for each
|
14
|
+
# gem. This creates a single clean list of gems in order.
|
15
|
+
|
16
|
+
gem "brut", "<%= versions.brut_version_specifier %>"
|
17
|
+
|
18
|
+
# Audit our dependencies
|
19
|
+
gem "bundler-audit", groups: [ :test ]
|
20
|
+
|
21
|
+
# This allows us to make assertions about test setup that are not themselves tests
|
22
|
+
gem "confidence-check", groups: [ :test ]
|
23
|
+
|
24
|
+
# Dotenv manages the environment variables in the development
|
25
|
+
# and test environments. See .env.development, .env.development.local,
|
26
|
+
# and .env.test
|
27
|
+
gem "dotenv", groups: [ :development, :test ]
|
28
|
+
|
29
|
+
# FactoryBot manages test and seed data
|
30
|
+
gem "factory_bot", groups: [ :development, :test ]
|
31
|
+
|
32
|
+
# Faker is used to create realistic data for test and seed data.
|
33
|
+
gem "faker", groups: [ :development, :test ]
|
34
|
+
|
35
|
+
|
36
|
+
# We use Postgres
|
37
|
+
gem "pg"
|
38
|
+
|
39
|
+
# Allows using Playwright from Ruby.
|
40
|
+
# We lock the version because it must be the same as the verison
|
41
|
+
# of playwright in package.json. This ensures that we can reliably
|
42
|
+
# install the right browsers and that everything will work right.
|
43
|
+
gem "playwright-ruby-client", "1.52.0", groups: [ :test ]
|
44
|
+
|
45
|
+
# Sinatra needs a webserver and puma is the best
|
46
|
+
gem "puma"
|
47
|
+
|
48
|
+
# Uses RSpec for testing
|
49
|
+
gem "rspec", groups: [ :test ]
|
50
|
+
|
51
|
+
# Allows for diagnosing failing tests
|
52
|
+
gem "with_clues", groups: [ :test ]
|
53
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
web: PORT=6503 bin/run
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# <%= app_name %>
|
2
|
+
|
3
|
+
A great new app!
|
4
|
+
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
1. Clone this repo
|
8
|
+
2. Ensure you have Docker installed
|
9
|
+
3. Build the Foundation of your dev environment:
|
10
|
+
|
11
|
+
```
|
12
|
+
dx/build
|
13
|
+
```
|
14
|
+
4. Start it up:
|
15
|
+
|
16
|
+
```
|
17
|
+
dx/start
|
18
|
+
```
|
19
|
+
5. In another terminal, shell into the container you just started:
|
20
|
+
|
21
|
+
```
|
22
|
+
dx/exec bash
|
23
|
+
```
|
24
|
+
6. Run setup:
|
25
|
+
|
26
|
+
```
|
27
|
+
dx/setup
|
28
|
+
```
|
29
|
+
7. Start the app:
|
30
|
+
|
31
|
+
```
|
32
|
+
bin/dev
|
33
|
+
```
|
34
|
+
|
35
|
+
8. Visit `http://localhost:6502`
|
36
|
+
9. Now get to work!
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Handles the configuration and startup process for your Brut-powered
|
2
|
+
# app and anything that needs its configuration, such as a CLI.
|
3
|
+
#
|
4
|
+
# This class models three phases:
|
5
|
+
#
|
6
|
+
# 1. *Initialized* - Ruby is running, but no Brut configuration has happened.
|
7
|
+
#
|
8
|
+
# ```ruby
|
9
|
+
# bootstrap = Bootstrap.new
|
10
|
+
# ```
|
11
|
+
# 2. *Configured* - Brut's static configuration is set up.
|
12
|
+
# See `Brut::Framework::MCP.initialize`.
|
13
|
+
#
|
14
|
+
# ```ruby
|
15
|
+
# configured = bootstrap.configure_only!
|
16
|
+
# ```
|
17
|
+
#
|
18
|
+
# 3. *Bootstrapped* - Everything is set up and configured, services
|
19
|
+
# have been connected-to and the app is generally ready to receive
|
20
|
+
# requests or have its logic executed.
|
21
|
+
#
|
22
|
+
# ```ruby
|
23
|
+
# booted = configured.bootstrap!
|
24
|
+
# ```
|
25
|
+
class Bootstrap
|
26
|
+
|
27
|
+
def configure_only!
|
28
|
+
require "bundler"
|
29
|
+
|
30
|
+
Bundler.require(:default, ENV.fetch("RACK_ENV").to_sym)
|
31
|
+
|
32
|
+
require "brut"
|
33
|
+
require "pathname"
|
34
|
+
|
35
|
+
Brut.container.store_required_path(
|
36
|
+
"project_root",
|
37
|
+
"Root of the entire project's source code checkout",
|
38
|
+
(Pathname(__dir__) / "..").expand_path)
|
39
|
+
|
40
|
+
|
41
|
+
$: << File.join(Brut.container.project_root,"app","src")
|
42
|
+
|
43
|
+
require "app"
|
44
|
+
|
45
|
+
@mcp = Brut::Framework::MCP.new(app_klass: ::App)
|
46
|
+
@app = @mcp.app
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
attr_reader :rack_app, :app
|
51
|
+
|
52
|
+
# @return [Bootstrap::ConfiguredBootstrap] that contains
|
53
|
+
# the {Brut::Framework::App} and {Brut::Framework::MCP}.
|
54
|
+
def bootstrap!
|
55
|
+
self.configure_only!
|
56
|
+
@mcp.boot!
|
57
|
+
@rack_app = @mcp.sinatra_app.new
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# Brut's defaults for various strings required by Brut's internals.
|
2
|
+
#
|
3
|
+
# You are discouraged from changing this file.
|
4
|
+
{
|
5
|
+
# en: must be the first entry, thus indicating this is the EN translations
|
6
|
+
en: {
|
7
|
+
time:{
|
8
|
+
formats: { # strftime formats
|
9
|
+
iso_8601: "%Y-%m-%d %H:%M:%S.%6N %Z",
|
10
|
+
full_with_tz: "%Y-%m-%d %H:%M:%S %Z",
|
11
|
+
full: "%Y-%m-%d %H:%M:%S",
|
12
|
+
default: "%Y-%m-%d %H:%M:%S",
|
13
|
+
date: "%a, %b %e, %Y",
|
14
|
+
date_no_dow: "%b %e, %Y",
|
15
|
+
date_no_year: "%a, %b %e",
|
16
|
+
date_no_year_no_dow: "%b %e",
|
17
|
+
month_day_year: "%b %e, %Y",
|
18
|
+
month_day_year_no_year: "%b %e",
|
19
|
+
day_of_week: "%A",
|
20
|
+
time_only: "%l:%M %p",
|
21
|
+
},
|
22
|
+
am: "AM",
|
23
|
+
pm: "PM",
|
24
|
+
},
|
25
|
+
date: {
|
26
|
+
formats: {
|
27
|
+
iso_8601: "%Y-%m-%d",
|
28
|
+
full: "%Y-%m-%d",
|
29
|
+
default: "%a, %b %e, %Y",
|
30
|
+
date: "%a, %b %e, %Y",
|
31
|
+
date_no_dow: "%b %e, %Y",
|
32
|
+
date_no_year: "%a, %b %e",
|
33
|
+
date_no_year_no_dow: "%b %e",
|
34
|
+
month_day_year: "%b %e, %Y",
|
35
|
+
month_day_year_no_year: "%b %e",
|
36
|
+
day_of_week: "%A",
|
37
|
+
day_of_week_short: "%a",
|
38
|
+
time_only: "%l:%M %p",
|
39
|
+
},
|
40
|
+
abbr_day_names: [
|
41
|
+
"Sun",
|
42
|
+
"Mon",
|
43
|
+
"Tue",
|
44
|
+
"Wed",
|
45
|
+
"Thu",
|
46
|
+
"Fri",
|
47
|
+
"Sat",
|
48
|
+
],
|
49
|
+
day_names: [
|
50
|
+
"Sunday",
|
51
|
+
"Monday",
|
52
|
+
"Tuesday",
|
53
|
+
"Wednesday",
|
54
|
+
"Thursday",
|
55
|
+
"Friday",
|
56
|
+
"Saturday",
|
57
|
+
],
|
58
|
+
abbr_month_names: [
|
59
|
+
"",
|
60
|
+
"Jan",
|
61
|
+
"Feb",
|
62
|
+
"Mar",
|
63
|
+
"Apr",
|
64
|
+
"May",
|
65
|
+
"Jun",
|
66
|
+
"Jul",
|
67
|
+
"Aug",
|
68
|
+
"Sep",
|
69
|
+
"Oct",
|
70
|
+
"Nov",
|
71
|
+
"Dec",
|
72
|
+
],
|
73
|
+
month_names: [
|
74
|
+
"",
|
75
|
+
"January",
|
76
|
+
"February",
|
77
|
+
"March",
|
78
|
+
"April",
|
79
|
+
"May",
|
80
|
+
"June",
|
81
|
+
"July",
|
82
|
+
"August",
|
83
|
+
"September",
|
84
|
+
"October",
|
85
|
+
"November",
|
86
|
+
"December",
|
87
|
+
],
|
88
|
+
},
|
89
|
+
cv: { # short for "constraint violations" to avoid having to type that out
|
90
|
+
this_field: "This field",
|
91
|
+
cs: { # short for "client-side", again to not have to type it out
|
92
|
+
# These keys use camel-case because that is how the browser defines
|
93
|
+
# these values, based on ValidityState
|
94
|
+
badInput: "%{field} is the wrong type of data",
|
95
|
+
patternMismatch: "%{field} isn't in the right format",
|
96
|
+
rangeOverflow: "%{field} is too big",
|
97
|
+
rangeUnderflow: "%{field} is too small",
|
98
|
+
stepMismatch: "%{field} is not a valid value in the range",
|
99
|
+
tooLong: "%{field} is too long",
|
100
|
+
tooShort: "%{field} is too short",
|
101
|
+
typeMismatch: "%{field} is the wrong type",
|
102
|
+
valueMissing: "%{field} is required",
|
103
|
+
general: "Form is invalid",
|
104
|
+
},
|
105
|
+
ss: { # short for "server-side", again not to have to type it out
|
106
|
+
# These are snake case, which is idiomatic for Ruby. The values
|
107
|
+
# here are all based on DataObjectValidator's behavior
|
108
|
+
required: "%{field} is required",
|
109
|
+
too_short: "%{field} is too short; must be at least %{minlength} characters",
|
110
|
+
},
|
111
|
+
},
|
112
|
+
diagnostics: { # This is to help diagnose issues with the translation system and is not
|
113
|
+
# intended to store real strings to be used by your app
|
114
|
+
has_interpolations: "Test %{interp} Test",
|
115
|
+
has_pluralizations: {
|
116
|
+
one: "Once!",
|
117
|
+
other: "More than once!"
|
118
|
+
},
|
119
|
+
has_pluralizations_and_zero: {
|
120
|
+
zero: "ZERO",
|
121
|
+
one: "ONE",
|
122
|
+
other: "MORE",
|
123
|
+
},
|
124
|
+
simple1: "SIMPLE1",
|
125
|
+
simple2: "SIMPLE2",
|
126
|
+
}
|
127
|
+
},
|
128
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# All app-specific translations, or overrides of Brut's defaults, go here.
|
2
|
+
{
|
3
|
+
# en: must be the first entry, thus indicating this is the EN translations
|
4
|
+
en: {
|
5
|
+
cv: {
|
6
|
+
cs: {
|
7
|
+
},
|
8
|
+
ss: {
|
9
|
+
email_taken: "This email has been taken",
|
10
|
+
},
|
11
|
+
},
|
12
|
+
pages: { # Page-specific messages - this key is relied-upon by Brut to exist
|
13
|
+
HomePage: {
|
14
|
+
title: "Welcome!",
|
15
|
+
}
|
16
|
+
},
|
17
|
+
components: { # Component-specific messages - this key is relied-upon by Brut to exist
|
18
|
+
},
|
19
|
+
clis: { # Messages used in CLIs - this key is relied-upon by Brut to exist
|
20
|
+
},
|
21
|
+
hello: "Hello, and welcome to Brut!",
|
22
|
+
# Other keys can go here and you can organize them however you like.
|
23
|
+
},
|
24
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"name": "<%= app_name %>",
|
3
|
+
"short_name": "<%= app_name %>",
|
4
|
+
"description": "The <%= app_name %> App",
|
5
|
+
"start_url": "/",
|
6
|
+
"scope": "/",
|
7
|
+
"display": "standalone",
|
8
|
+
"theme_color": "#A70C00",
|
9
|
+
"icons": [
|
10
|
+
{
|
11
|
+
"src": "/static/images/icon.png"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"src": "/static/images/apple-touch-icon-120x120.png",
|
15
|
+
"sizes": "120x120"
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"src": "/static/images/apple-touch-icon-152x152.png",
|
19
|
+
"sizes": "152x152"
|
20
|
+
},
|
21
|
+
{
|
22
|
+
"src": "/static/images/apple-touch-icon-167x167.png",
|
23
|
+
"sizes": "167x167"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"src": "/static/images/apple-touch-icon-180x180.png",
|
27
|
+
"sizes": "180x180"
|
28
|
+
}
|
29
|
+
]
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class App < Brut::Framework::App
|
2
|
+
def id = "<%= app_id %>"
|
3
|
+
def organization = "<%= organization %>"
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
# Add additional initialization to this initializers.
|
7
|
+
# Be sure to use the lazy/block form of store because when this code
|
8
|
+
# runs, the app may not have access to networked resources.
|
9
|
+
Brut.container.override("session_class",AppSession)
|
10
|
+
Brut.container.override("external_id_prefix","<%= prefix %>")
|
11
|
+
end
|
12
|
+
|
13
|
+
def boot!
|
14
|
+
# Perform any additional bootstrapping here, such as configuration of
|
15
|
+
# job back-ends or other data stores. When this runs, you can be sure
|
16
|
+
# the app has access to networked resources
|
17
|
+
end
|
18
|
+
|
19
|
+
# Various class methods may be called here to configure your app. See the API
|
20
|
+
# documentation for Brut::Framework::App.
|
21
|
+
|
22
|
+
# Generic error handler. Is expected to return a Rack response.
|
23
|
+
error do |exception:, http_status_code:|
|
24
|
+
SemanticLogger["App"].error(exception || "Unknown error", http_status_code:)
|
25
|
+
[
|
26
|
+
http_status_code || 500,
|
27
|
+
{},
|
28
|
+
exception&.message || "Internal Server Error '#{http_status_code}'"
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Declare your app's routes.
|
33
|
+
routes do
|
34
|
+
page "/" # Special route for HomePage
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Namespace for all data models. This makes it easy
|
2
|
+
# to avoid the conflation of database table models from
|
3
|
+
# domain models.
|
4
|
+
module DB
|
5
|
+
# Execute the code in the block in a database transaction.
|
6
|
+
# This calls `Sequel::Model.db.transaction`, which is ultimately
|
7
|
+
# `Sequel::Database#transaction`. Please review that documentation as well
|
8
|
+
# as the documentation of your databnase so you understand
|
9
|
+
# how transactions work.
|
10
|
+
#
|
11
|
+
# @see https://rubydoc.info/gems/sequel/5.93.0/Sequel/Database#transaction-instance_method
|
12
|
+
def self.transaction(opts=:use_default,&block)
|
13
|
+
if opts == :use_default
|
14
|
+
opts = Sequel::Database::OPTS
|
15
|
+
end
|
16
|
+
Sequel::Model.db.transaction(opts,&block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "brut/back_end/seed_data"
|
2
|
+
class SeedData < Brut::BackEnd::SeedData
|
3
|
+
include FactoryBot::Syntax::Methods
|
4
|
+
def seed!
|
5
|
+
# Create records here. This method is not expected
|
6
|
+
# to be idempotent. You can (and should) use your
|
7
|
+
# FactoryBot factories here.
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Base class for your app's components.
|
2
|
+
class AppComponent < Brut::FrontEnd::Component
|
3
|
+
include Brut::Framework::Errors # provides access to methods in this module
|
4
|
+
include Brut::FrontEnd::Components # Allows Brut-provided components to be
|
5
|
+
# used as a Phlex "kit"
|
6
|
+
include CustomElementRegistration
|
7
|
+
end
|
8
|
+
|