brut 0.8.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.
Files changed (393) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -0
  3. data/CHANGELOG.md +7 -0
  4. data/Dockerfile.dx +8 -1
  5. data/Gemfile.lock +33 -1
  6. data/bin/ci +9 -5
  7. data/bin/docs +1 -1
  8. data/bin/generate-and-run-rubocop +52 -0
  9. data/bin/rubocop +27 -0
  10. data/bin/setup +46 -0
  11. data/bin/test +18 -0
  12. data/brut-css/bin/publish +1 -1
  13. data/brut-css/package-lock.json +2 -2
  14. data/brut-css/package.json +1 -1
  15. data/brut-js/bin/publish +1 -1
  16. data/brut-js/package-lock.json +2 -2
  17. data/brut-js/package.json +1 -1
  18. data/brut.gemspec +32 -26
  19. data/brutrb.com/.vitepress/config.mjs +3 -0
  20. data/brutrb.com/database-schema.md +1 -1
  21. data/brutrb.com/recipes/migrations.md +1 -1
  22. data/docker-compose.dx.yml +3 -0
  23. data/docs/404.html +2 -2
  24. data/docs/adrs.html +3 -3
  25. data/docs/ai.html +3 -3
  26. data/docs/api/Brut/BackEnd/SeedData.html +2 -2
  27. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +2 -2
  28. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +2 -2
  29. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +2 -2
  30. data/docs/api/Brut/BackEnd/Sidekiq.html +2 -2
  31. data/docs/api/Brut/BackEnd/Validators/FormValidator.html +2 -2
  32. data/docs/api/Brut/BackEnd/Validators.html +2 -2
  33. data/docs/api/Brut/BackEnd.html +2 -2
  34. data/docs/api/Brut/CLI/App.html +2 -2
  35. data/docs/api/Brut/CLI/AppRunner.html +2 -2
  36. data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +2 -2
  37. data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +2 -2
  38. data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +2 -2
  39. data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +2 -2
  40. data/docs/api/Brut/CLI/Apps/BuildAssets.html +2 -2
  41. data/docs/api/Brut/CLI/Apps/DB/Create.html +2 -2
  42. data/docs/api/Brut/CLI/Apps/DB/Drop.html +2 -2
  43. data/docs/api/Brut/CLI/Apps/DB/Migrate.html +2 -2
  44. data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +2 -2
  45. data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +2 -2
  46. data/docs/api/Brut/CLI/Apps/DB/Seed.html +2 -2
  47. data/docs/api/Brut/CLI/Apps/DB/Status.html +2 -2
  48. data/docs/api/Brut/CLI/Apps/DB.html +2 -2
  49. data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +2 -2
  50. data/docs/api/Brut/CLI/Apps/DeployBase.html +2 -2
  51. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +3 -3
  52. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +2 -2
  53. data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +2 -2
  54. data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +2 -2
  55. data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +2 -2
  56. data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +2 -2
  57. data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +2 -2
  58. data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +2 -2
  59. data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +2 -2
  60. data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +2 -2
  61. data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +2 -2
  62. data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +2 -2
  63. data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +3 -3
  64. data/docs/api/Brut/CLI/Apps/Scaffold.html +2 -2
  65. data/docs/api/Brut/CLI/Apps/Test/Audit.html +2 -2
  66. data/docs/api/Brut/CLI/Apps/Test/E2e.html +2 -2
  67. data/docs/api/Brut/CLI/Apps/Test/JS.html +2 -2
  68. data/docs/api/Brut/CLI/Apps/Test/Run.html +2 -2
  69. data/docs/api/Brut/CLI/Apps/Test.html +2 -2
  70. data/docs/api/Brut/CLI/Apps.html +2 -2
  71. data/docs/api/Brut/CLI/Command.html +2 -2
  72. data/docs/api/Brut/CLI/Error.html +2 -2
  73. data/docs/api/Brut/CLI/ExecutionResults/Result.html +2 -2
  74. data/docs/api/Brut/CLI/ExecutionResults.html +2 -2
  75. data/docs/api/Brut/CLI/Executor.html +2 -2
  76. data/docs/api/Brut/CLI/InvalidOption.html +2 -2
  77. data/docs/api/Brut/CLI/Options.html +80 -2
  78. data/docs/api/Brut/CLI/Output.html +2 -2
  79. data/docs/api/Brut/CLI/SystemExecError.html +2 -2
  80. data/docs/api/Brut/CLI.html +2 -2
  81. data/docs/api/Brut/FactoryBot.html +3 -3
  82. data/docs/api/Brut/Framework/App.html +3 -3
  83. data/docs/api/Brut/Framework/Config.html +25 -3
  84. data/docs/api/Brut/Framework/Container.html +2 -2
  85. data/docs/api/Brut/Framework/Error.html +2 -2
  86. data/docs/api/Brut/Framework/Errors/AbstractMethod.html +2 -2
  87. data/docs/api/Brut/Framework/Errors/Bug.html +2 -2
  88. data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +2 -2
  89. data/docs/api/Brut/Framework/Errors/MissingParameter.html +2 -2
  90. data/docs/api/Brut/Framework/Errors/NoClassForPath.html +2 -2
  91. data/docs/api/Brut/Framework/Errors/NotFound.html +2 -2
  92. data/docs/api/Brut/Framework/Errors/NotImplemented.html +2 -2
  93. data/docs/api/Brut/Framework/Errors.html +2 -2
  94. data/docs/api/Brut/Framework/FussyTypeEnforcement.html +2 -2
  95. data/docs/api/Brut/Framework/MCP.html +21 -11
  96. data/docs/api/Brut/Framework/ProjectEnvironment.html +2 -2
  97. data/docs/api/Brut/Framework.html +2 -2
  98. data/docs/api/Brut/FrontEnd/AssetPathResolver.html +2 -2
  99. data/docs/api/Brut/FrontEnd/Component/Helpers.html +2 -2
  100. data/docs/api/Brut/FrontEnd/Component.html +2 -2
  101. data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +2 -2
  102. data/docs/api/Brut/FrontEnd/Components/FormTag.html +4 -4
  103. data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +2 -2
  104. data/docs/api/Brut/FrontEnd/Components/Input.html +2 -2
  105. data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +2 -2
  106. data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +2 -2
  107. data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +2 -2
  108. data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +2 -2
  109. data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +2 -2
  110. data/docs/api/Brut/FrontEnd/Components/Inputs.html +2 -2
  111. data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +2 -2
  112. data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +2 -2
  113. data/docs/api/Brut/FrontEnd/Components/TimeTag.html +2 -2
  114. data/docs/api/Brut/FrontEnd/Components/Traceparent.html +2 -2
  115. data/docs/api/Brut/FrontEnd/Components.html +2 -2
  116. data/docs/api/Brut/FrontEnd/CsrfProtector.html +250 -0
  117. data/docs/api/Brut/FrontEnd/Download.html +2 -2
  118. data/docs/api/Brut/FrontEnd/Flash.html +2 -2
  119. data/docs/api/Brut/FrontEnd/Form.html +6 -6
  120. data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +2 -2
  121. data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +2 -2
  122. data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +2 -2
  123. data/docs/api/Brut/FrontEnd/Forms/Input.html +2 -2
  124. data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +2 -2
  125. data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +2 -2
  126. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +2 -2
  127. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +2 -2
  128. data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +2 -2
  129. data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +2 -2
  130. data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +2 -2
  131. data/docs/api/Brut/FrontEnd/Forms.html +2 -2
  132. data/docs/api/Brut/FrontEnd/GenericResponse.html +2 -2
  133. data/docs/api/Brut/FrontEnd/Handler.html +2 -2
  134. data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +2 -2
  135. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +2 -2
  136. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +2 -2
  137. data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +2 -2
  138. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +2 -2
  139. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +2 -2
  140. data/docs/api/Brut/FrontEnd/Handlers.html +2 -2
  141. data/docs/api/Brut/FrontEnd/HandlingResults.html +2 -2
  142. data/docs/api/Brut/FrontEnd/HttpMethod.html +2 -2
  143. data/docs/api/Brut/FrontEnd/HttpStatus.html +2 -2
  144. data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +2 -2
  145. data/docs/api/Brut/FrontEnd/Layout.html +2 -2
  146. data/docs/api/Brut/FrontEnd/Middleware.html +2 -2
  147. data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +2 -2
  148. data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +2 -2
  149. data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +2 -2
  150. data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +2 -2
  151. data/docs/api/Brut/FrontEnd/Middlewares.html +2 -2
  152. data/docs/api/Brut/FrontEnd/Page.html +2 -2
  153. data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +2 -2
  154. data/docs/api/Brut/FrontEnd/Pages.html +2 -2
  155. data/docs/api/Brut/FrontEnd/RequestContext.html +2 -2
  156. data/docs/api/Brut/FrontEnd/RouteHook.html +2 -2
  157. data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +2 -2
  158. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +2 -2
  159. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +2 -2
  160. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +2 -2
  161. data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +2 -2
  162. data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +2 -2
  163. data/docs/api/Brut/FrontEnd/RouteHooks.html +2 -2
  164. data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +2 -2
  165. data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +2 -2
  166. data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +2 -2
  167. data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +2 -2
  168. data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +2 -2
  169. data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +2 -2
  170. data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +2 -2
  171. data/docs/api/Brut/FrontEnd/Routing/Route.html +2 -2
  172. data/docs/api/Brut/FrontEnd/Routing.html +2 -2
  173. data/docs/api/Brut/FrontEnd/Session.html +2 -2
  174. data/docs/api/Brut/FrontEnd.html +3 -3
  175. data/docs/api/Brut/I18n/BaseMethods.html +3 -3
  176. data/docs/api/Brut/I18n/ForBackEnd.html +2 -2
  177. data/docs/api/Brut/I18n/ForCLI.html +2 -2
  178. data/docs/api/Brut/I18n/ForHTML.html +2 -2
  179. data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +2 -2
  180. data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +2 -2
  181. data/docs/api/Brut/I18n.html +2 -2
  182. data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +2 -2
  183. data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +2 -2
  184. data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +2 -2
  185. data/docs/api/Brut/Instrumentation/OpenTelemetry.html +2 -2
  186. data/docs/api/Brut/Instrumentation.html +2 -2
  187. data/docs/api/Brut/RubocopConfig.html +237 -0
  188. data/docs/api/Brut/SinatraHelpers/ClassMethods.html +2 -2
  189. data/docs/api/Brut/SinatraHelpers.html +2 -2
  190. data/docs/api/Brut/SpecSupport/ClockSupport.html +2 -2
  191. data/docs/api/Brut/SpecSupport/ComponentSupport.html +7 -13
  192. data/docs/api/Brut/SpecSupport/E2ETestServer.html +2 -2
  193. data/docs/api/Brut/SpecSupport/E2eSupport.html +2 -2
  194. data/docs/api/Brut/SpecSupport/EnhancedNode.html +2 -2
  195. data/docs/api/Brut/SpecSupport/FlashSupport.html +2 -2
  196. data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +2 -2
  197. data/docs/api/Brut/SpecSupport/GeneralSupport.html +2 -2
  198. data/docs/api/Brut/SpecSupport/HandlerSupport.html +2 -2
  199. data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +2 -2
  200. data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +2 -2
  201. data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +2 -2
  202. data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +2 -2
  203. data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +2 -2
  204. data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +2 -2
  205. data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +2 -2
  206. data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +2 -2
  207. data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +2 -2
  208. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +2 -2
  209. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +2 -2
  210. data/docs/api/Brut/SpecSupport/Matchers.html +2 -2
  211. data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +2 -2
  212. data/docs/api/Brut/SpecSupport/RSpecSetup.html +4 -4
  213. data/docs/api/Brut/SpecSupport/SessionSupport.html +2 -2
  214. data/docs/api/Brut/SpecSupport.html +2 -2
  215. data/docs/api/Brut.html +128 -12
  216. data/docs/api/Clock.html +2 -2
  217. data/docs/api/ModuleName.html +28 -28
  218. data/docs/api/RichString.html +22 -22
  219. data/docs/api/SemanticLogger/Appender/Async.html +2 -2
  220. data/docs/api/Sequel/Extensions/BrutInstrumentation.html +2 -2
  221. data/docs/api/Sequel/Extensions/BrutMigrations.html +2 -2
  222. data/docs/api/Sequel/Extensions.html +2 -2
  223. data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +2 -2
  224. data/docs/api/Sequel/Plugins/CreatedAt.html +2 -2
  225. data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +2 -2
  226. data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +2 -2
  227. data/docs/api/Sequel/Plugins/ExternalId.html +2 -2
  228. data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +2 -2
  229. data/docs/api/Sequel/Plugins/FindBang.html +2 -2
  230. data/docs/api/Sequel/Plugins.html +2 -2
  231. data/docs/api/Sequel.html +2 -2
  232. data/docs/api/_index.html +16 -2
  233. data/docs/api/class_list.html +1 -1
  234. data/docs/api/file.README.html +28 -2
  235. data/docs/api/index.html +28 -2
  236. data/docs/api/method_list.html +192 -168
  237. data/docs/api/top-level-namespace.html +2 -2
  238. data/docs/assets/{app.DyQLb4Ot.js → app.CmkhEsw7.js} +1 -1
  239. data/docs/assets/chunks/@localSearchIndexroot.DUha-mf5.js +1 -0
  240. data/docs/assets/chunks/{VPLocalSearchBox.T1iA-eJx.js → VPLocalSearchBox.CDh583Oj.js} +1 -1
  241. data/docs/assets/chunks/{theme.ChwsbWjK.js → theme.B0_7GeW8.js} +2 -2
  242. data/docs/assets/{components.md.DHh-NwKs.js → components.md.-22ecBxM.js} +3 -3
  243. data/docs/assets/{configuration.md.D8Wz3oJU.js → configuration.md.CLKL1lFf.js} +1 -1
  244. data/docs/assets/{database-schema.md.C5gXexJi.js → database-schema.md.LpmBPVEU.js} +1 -1
  245. data/docs/assets/{forms.md.BRE85eju.js → forms.md.CBI5--o2.js} +1 -1
  246. data/docs/assets/{getting-started.md.2ioiTe-B.js → getting-started.md.D5nzBZ4J.js} +2 -2
  247. data/docs/assets/{recipes_migrations.md.DPN3gQE3.js → recipes_migrations.md.CTcnWDJF.js} +1 -1
  248. data/docs/assets.html +3 -3
  249. data/docs/brut-js/api/AjaxSubmit.html +1 -1
  250. data/docs/brut-js/api/AjaxSubmit.js.html +1 -1
  251. data/docs/brut-js/api/Autosubmit.html +1 -1
  252. data/docs/brut-js/api/Autosubmit.js.html +1 -1
  253. data/docs/brut-js/api/BaseCustomElement.html +1 -1
  254. data/docs/brut-js/api/BaseCustomElement.js.html +1 -1
  255. data/docs/brut-js/api/BrutCustomElements.html +1 -1
  256. data/docs/brut-js/api/BufferedLogger.html +1 -1
  257. data/docs/brut-js/api/ConfirmSubmit.html +1 -1
  258. data/docs/brut-js/api/ConfirmSubmit.js.html +1 -1
  259. data/docs/brut-js/api/ConfirmationDialog.html +1 -1
  260. data/docs/brut-js/api/ConfirmationDialog.js.html +1 -1
  261. data/docs/brut-js/api/ConstraintViolationMessage.html +1 -1
  262. data/docs/brut-js/api/ConstraintViolationMessage.js.html +1 -1
  263. data/docs/brut-js/api/ConstraintViolationMessages.html +1 -1
  264. data/docs/brut-js/api/ConstraintViolationMessages.js.html +1 -1
  265. data/docs/brut-js/api/CopyToClipboard.html +1 -1
  266. data/docs/brut-js/api/CopyToClipboard.js.html +1 -1
  267. data/docs/brut-js/api/Form.html +1 -1
  268. data/docs/brut-js/api/Form.js.html +1 -1
  269. data/docs/brut-js/api/I18nTranslation.html +1 -1
  270. data/docs/brut-js/api/I18nTranslation.js.html +1 -1
  271. data/docs/brut-js/api/LocaleDetection.html +1 -1
  272. data/docs/brut-js/api/LocaleDetection.js.html +1 -1
  273. data/docs/brut-js/api/Logger.html +1 -1
  274. data/docs/brut-js/api/Logger.js.html +1 -1
  275. data/docs/brut-js/api/Message.html +1 -1
  276. data/docs/brut-js/api/Message.js.html +1 -1
  277. data/docs/brut-js/api/PrefixedLogger.html +1 -1
  278. data/docs/brut-js/api/RichString.html +1 -1
  279. data/docs/brut-js/api/RichString.js.html +1 -1
  280. data/docs/brut-js/api/Tabs.html +1 -1
  281. data/docs/brut-js/api/Tabs.js.html +1 -1
  282. data/docs/brut-js/api/Tracing.html +1 -1
  283. data/docs/brut-js/api/Tracing.js.html +1 -1
  284. data/docs/brut-js/api/external-CustomElementRegistry.html +1 -1
  285. data/docs/brut-js/api/external-Performance.html +1 -1
  286. data/docs/brut-js/api/external-Promise.html +1 -1
  287. data/docs/brut-js/api/external-ValidityState.html +1 -1
  288. data/docs/brut-js/api/external-Window.html +1 -1
  289. data/docs/brut-js/api/external-fetch.html +1 -1
  290. data/docs/brut-js/api/global.html +1 -1
  291. data/docs/brut-js/api/index.html +1 -1
  292. data/docs/brut-js/api/index.js.html +1 -1
  293. data/docs/brut-js/api/module-testing.html +1 -1
  294. data/docs/brut-js/api/testing.AssetMetadata.html +1 -1
  295. data/docs/brut-js/api/testing.AssetMetadataLoader.html +1 -1
  296. data/docs/brut-js/api/testing.CustomElementTest.html +1 -1
  297. data/docs/brut-js/api/testing.DOMCreator.html +1 -1
  298. data/docs/brut-js/api/testing_AssetMetadata.js.html +1 -1
  299. data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +1 -1
  300. data/docs/brut-js/api/testing_CustomElementTest.js.html +1 -1
  301. data/docs/brut-js/api/testing_DOMCreator.js.html +1 -1
  302. data/docs/brut-js/api/testing_index.js.html +1 -1
  303. data/docs/brut-js.html +3 -3
  304. data/docs/business-logic.html +3 -3
  305. data/docs/cli.html +3 -3
  306. data/docs/components.html +7 -7
  307. data/docs/configuration.html +5 -5
  308. data/docs/css.html +3 -3
  309. data/docs/custom-element-tests.html +3 -3
  310. data/docs/database-access.html +3 -3
  311. data/docs/database-schema.html +5 -5
  312. data/docs/deployment.html +3 -3
  313. data/docs/dev-environment.html +3 -3
  314. data/docs/dir-structure.html +3 -3
  315. data/docs/doc-conventions.html +3 -3
  316. data/docs/end-to-end-tests.html +3 -3
  317. data/docs/features.html +3 -3
  318. data/docs/flash-and-session.html +3 -3
  319. data/docs/form-constraints.html +3 -3
  320. data/docs/forms.html +5 -5
  321. data/docs/getting-started.html +6 -6
  322. data/docs/handlers.html +3 -3
  323. data/docs/hashmap.json +1 -1
  324. data/docs/hooks.html +3 -3
  325. data/docs/i18n.html +3 -3
  326. data/docs/index.html +3 -3
  327. data/docs/instrumentation.html +3 -3
  328. data/docs/javascript.html +3 -3
  329. data/docs/jobs.html +3 -3
  330. data/docs/keyword-injection.html +3 -3
  331. data/docs/layouts.html +3 -3
  332. data/docs/lsp.html +3 -3
  333. data/docs/markdown-examples.html +3 -3
  334. data/docs/middleware.html +3 -3
  335. data/docs/overview.html +3 -3
  336. data/docs/pages.html +3 -3
  337. data/docs/recipes/alternate-layouts.html +3 -3
  338. data/docs/recipes/authentication.html +3 -3
  339. data/docs/recipes/blank-layouts.html +3 -3
  340. data/docs/recipes/custom-flash.html +3 -3
  341. data/docs/recipes/indexed-forms.html +3 -3
  342. data/docs/recipes/migrations.html +5 -5
  343. data/docs/recipes/text-field-component.html +3 -3
  344. data/docs/roadmap.html +3 -3
  345. data/docs/routes.html +3 -3
  346. data/docs/security.html +3 -3
  347. data/docs/seed-data.html +3 -3
  348. data/docs/space-time-continuum.html +3 -3
  349. data/docs/tutorial.html +3 -3
  350. data/docs/unit-tests.html +3 -3
  351. data/docs/why.html +3 -3
  352. data/dx/build +45 -9
  353. data/lib/brut/cli/app.rb +1 -1
  354. data/lib/brut/cli/apps/heroku_container_based_deploy.rb +1 -1
  355. data/lib/brut/cli/apps/scaffold.rb +1 -1
  356. data/lib/brut/cli/options.rb +4 -0
  357. data/lib/brut/factory_bot.rb +1 -1
  358. data/lib/brut/framework/app.rb +1 -1
  359. data/lib/brut/framework/config.rb +11 -0
  360. data/lib/brut/framework/mcp.rb +12 -7
  361. data/lib/brut/front_end/csrf_protector.rb +30 -0
  362. data/lib/brut/front_end/form.rb +4 -4
  363. data/lib/brut/front_end/page.rb +1 -1
  364. data/lib/brut/front_end/routing.rb +1 -1
  365. data/lib/brut/front_end.rb +1 -0
  366. data/lib/brut/i18n/base_methods.rb +1 -1
  367. data/lib/brut/instrumentation/logger_span_exporter.rb +1 -1
  368. data/lib/brut/junk_drawer.rb +3 -1
  369. data/lib/brut/rubocop_config.rb +123 -0
  370. data/lib/brut/spec_support/component_support.rb +0 -3
  371. data/lib/brut/spec_support/rspec_setup.rb +2 -2
  372. data/lib/brut/version.rb +1 -1
  373. data/mkbrut/Gemfile.lock +1 -1
  374. data/mkbrut/dx +1 -0
  375. data/mkbrut/lib/mkbrut/app.rb +1 -1
  376. data/mkbrut/lib/mkbrut/cli.rb +1 -1
  377. data/mkbrut/lib/mkbrut/segments/heroku.rb +1 -1
  378. data/mkbrut/lib/mkbrut/version.rb +1 -1
  379. data/mkbrut/mkbrut.gemspec +3 -1
  380. data/mkbrut/templates/Base/app/config/i18n/en/1_defaults.rb +2 -2
  381. data/mkbrut/templates/Base/app/config/i18n/en/2_app.rb +1 -1
  382. data/mkbrut/templates/Base/bin/setup +1 -1
  383. data/mkbrut/templates/segments/Demo/app/src/front_end/components/flash_component.rb +1 -1
  384. data/specs/brut/junk_drawer.spec.rb +4 -0
  385. metadata +70 -33
  386. data/.rspec +0 -3
  387. data/docs/assets/chunks/@localSearchIndexroot.CmtZyrFA.js +0 -1
  388. /data/docs/assets/{components.md.DHh-NwKs.lean.js → components.md.-22ecBxM.lean.js} +0 -0
  389. /data/docs/assets/{configuration.md.D8Wz3oJU.lean.js → configuration.md.CLKL1lFf.lean.js} +0 -0
  390. /data/docs/assets/{database-schema.md.C5gXexJi.lean.js → database-schema.md.LpmBPVEU.lean.js} +0 -0
  391. /data/docs/assets/{forms.md.BRE85eju.lean.js → forms.md.CBI5--o2.lean.js} +0 -0
  392. /data/docs/assets/{getting-started.md.2ioiTe-B.lean.js → getting-started.md.D5nzBZ4J.lean.js} +0 -0
  393. /data/docs/assets/{recipes_migrations.md.DPN3gQE3.lean.js → recipes_migrations.md.CTcnWDJF.lean.js} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: add23c2780a2ba1fe444b067c50d3451d9b28cd1bacbed9e1ab1693963bcbd03
4
- data.tar.gz: 4f44397c6688843f6d4c9f61121879fd711dfcec5b1b024f6a8be038cc84be54
3
+ metadata.gz: 1b2e311013cbdc55775be537b348e78a8c94d12842bff7fcdc09973f88be7eb9
4
+ data.tar.gz: 648599f601bbf5fa34ed21f7223b4cf82dcf1f12f58b7b60bdf28d5d56c191b2
5
5
  SHA512:
6
- metadata.gz: 787f519b6c620c4586af3f53932fdbc6ded220766d36295ae9220d51d795a7c3498438cb6ad89051061731be95ab8c448d4d6c7519d97490e14ff433e954d747
7
- data.tar.gz: b76f693147690b5370f8db06747e6d73f3b9cffae625edaabdb0f3469806bbc2b2966d55aacc101c70e3e7c767690c4f1f8052a61677d90a26ec59753392fea8
6
+ metadata.gz: 913cb4f1328ce98454004702f7e8ded76fcc18d44e090b6b96a50840b54519dcc1cde3f3746d9a772c2e33da8554d8485c28ccc35fd65ca98c154b6693c4ac07
7
+ data.tar.gz: c4ae0693b14b42f3ba58b10b83f6e98f6e300ddeafd40f89028f42eb1b2c534857d69de5917ff7a4234380fb2123815242ac7a2c805f1939f2f1cee033fa2744
data/.gitignore CHANGED
@@ -6,11 +6,17 @@
6
6
  # should never be checked in
7
7
  /dx/credentials
8
8
 
9
+ # This is per-developer configuration, generated by dx/build
10
+ /dx/build.args
11
+
9
12
  # Holds metadata during YARD builds. Don't need this checked in
10
13
  /.yardoc
11
14
  # Location of YARD templates, this is temporary
12
15
  /.yard
13
16
 
17
+ # This is generated, so no need to check in
18
+ /.rubocop.yml
19
+
14
20
  # This is where generated API docs go
15
21
  /brutrb.com/public/api
16
22
  /brutrb.com/public/brut-js/api
@@ -42,3 +48,6 @@
42
48
  # All I want in life is for every single instance of this file
43
49
  # to be placed in hell, and waiting for Alan Dye when he arrives.
44
50
  .DS_Store
51
+
52
+ # Don't want tmp checked in, but want to dump stuff there for sure
53
+ /tmp
data/CHANGELOG.md CHANGED
@@ -1,8 +1,15 @@
1
1
  # Brut CHANGELOG
2
2
 
3
+ ## v0.9.0 - Aug 7, 2025
4
+
5
+ * Added `Brut::FrontEnd::CsrfProtector` and the `csrf_protector` configuration option to allow some customization
6
+ over how CSRF protection works app-wide, namely to allow a POST to a webhook to not have to have an authenticity token.
7
+ I don't super love this solution, but it's unblocking me for now.
8
+
3
9
  ## v0.8.0 - July 23, 2025
4
10
 
5
11
  * Moved `mkbrut` into this repo
12
+ * Fixed issue where generated `dx/build` script would mess up `build.args`. See https://github.com/thirdtank/brut/issues/45
6
13
  * Unify versioning for Brut, `mkbrut`, BrutJS, and BrutCSS
7
14
  * Unify all workspace workflow scripts (see README.md)
8
15
  * Minor doc updates to remove references to non-existent `form_tag`
data/Dockerfile.dx CHANGED
@@ -44,12 +44,19 @@ RUN apt-get install -y vim && \
44
44
  ARG user_uid=10001
45
45
  # Their group id, which ideally matches their group id on the host
46
46
  ARG user_gid=10002
47
+ # The group id that can access /var/run/docker.sock on the host.
48
+ # If this isn't mapped properly, no docker-out-of-docker commands will work
49
+ ARG docker_gid=10003
50
+ # Can be set to ',0' in order to add the user to roo's group
51
+ ARG sadly_user_must_be_added_to_root=
47
52
 
48
53
  # Create the user's group ID if it does not exist
49
54
  RUN getent group ${user_gid} || groupadd --gid ${user_gid} appgroup
55
+ # Create the docker group id if it does not exist
56
+ RUN getent group ${docker_gid} || groupadd --gid ${docker_gid} hostdocker
50
57
  # Create the user. Note that we put bash_customizations in both .profile and .bashrc
51
58
  # to increase the chances they are used when running bash in various configurations
52
- RUN useradd --uid ${user_uid} --gid ${user_gid} --create-home --home-dir /home/appuser appuser && \
59
+ 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 && \
53
60
  echo ". ~/.bash_customizations" >> /home/appuser/.profile && \
54
61
  echo ". ~/.bash_customizations.local" >> /home/appuser/.profile && \
55
62
  echo ". ~/.bash_customizations" >> /home/appuser/.bashrc && \
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brut (0.8.0)
4
+ brut (0.9.0)
5
5
  concurrent-ruby
6
6
  i18n
7
7
  irb
@@ -36,6 +36,7 @@ GEM
36
36
  securerandom (>= 0.3)
37
37
  tzinfo (~> 2.0, >= 2.0.5)
38
38
  uri (>= 0.13.1)
39
+ ast (2.4.3)
39
40
  base64 (0.2.0)
40
41
  benchmark (0.4.0)
41
42
  bigdecimal (3.1.8)
@@ -76,6 +77,9 @@ GEM
76
77
  pp (>= 0.6.0)
77
78
  rdoc (>= 4.0.0)
78
79
  reline (>= 0.4.2)
80
+ json (2.13.0)
81
+ language_server-protocol (3.17.0.5)
82
+ lint_roller (1.1.0)
79
83
  logger (1.6.1)
80
84
  mini_portile2 (2.8.9)
81
85
  minitest (5.25.1)
@@ -114,6 +118,10 @@ GEM
114
118
  opentelemetry-semantic_conventions (1.10.1)
115
119
  opentelemetry-api (~> 1.0)
116
120
  ostruct (0.6.1)
121
+ parallel (1.27.0)
122
+ parser (3.3.8.0)
123
+ ast (~> 2.4.1)
124
+ racc
117
125
  phlex (2.2.1)
118
126
  zeitwerk (~> 2.7)
119
127
  pp (0.6.2)
@@ -132,10 +140,12 @@ GEM
132
140
  rack (>= 3.0.0)
133
141
  rackup (2.2.1)
134
142
  rack (>= 3)
143
+ rainbow (3.1.1)
135
144
  rake (13.2.1)
136
145
  rdiscount (2.2.7.3)
137
146
  rdoc (6.12.0)
138
147
  psych (>= 4.0.0)
148
+ regexp_parser (2.10.0)
139
149
  reline (0.6.0)
140
150
  io-console (~> 0.5)
141
151
  rspec (3.13.0)
@@ -151,6 +161,23 @@ GEM
151
161
  diff-lcs (>= 1.2.0, < 2.0)
152
162
  rspec-support (~> 3.13.0)
153
163
  rspec-support (3.13.1)
164
+ rubocop (1.74.0)
165
+ json (~> 2.3)
166
+ language_server-protocol (~> 3.17.0.2)
167
+ lint_roller (~> 1.1.0)
168
+ parallel (~> 1.10)
169
+ parser (>= 3.3.0.2)
170
+ rainbow (>= 2.2.2, < 4.0)
171
+ regexp_parser (>= 2.9.3, < 3.0)
172
+ rubocop-ast (>= 1.38.0, < 2.0)
173
+ ruby-progressbar (~> 1.7)
174
+ unicode-display_width (>= 2.4.0, < 4.0)
175
+ rubocop-ast (1.42.0)
176
+ parser (>= 3.3.7.2)
177
+ rubocop-disable_syntax (0.2.0)
178
+ lint_roller
179
+ rubocop (>= 1.72.0)
180
+ ruby-progressbar (1.13.0)
154
181
  ruby2_keywords (0.0.5)
155
182
  securerandom (0.3.2)
156
183
  semantic_logger (4.16.1)
@@ -169,6 +196,9 @@ GEM
169
196
  concurrent-ruby (~> 1.0)
170
197
  tzinfo-data (1.2024.2)
171
198
  tzinfo (>= 1.0.0)
199
+ unicode-display_width (3.1.4)
200
+ unicode-emoji (~> 4.0, >= 4.0.4)
201
+ unicode-emoji (4.0.4)
172
202
  uri (1.0.2)
173
203
  yard (0.9.37)
174
204
  zeitwerk (2.7.1)
@@ -192,6 +222,8 @@ DEPENDENCIES
192
222
  rdiscount
193
223
  rdoc
194
224
  rspec (~> 3.0)
225
+ rubocop
226
+ rubocop-disable_syntax
195
227
  yard
196
228
 
197
229
  BUNDLED WITH
data/bin/ci CHANGED
@@ -20,7 +20,15 @@ brutcss_dir = (Pathname(__FILE__).dirname / ".." / "brut-css" ).expand_path.to_s
20
20
  mkbrut_dir = (Pathname(__FILE__).dirname / ".." / "mkbrut" ).expand_path.to_s
21
21
 
22
22
  log "Running BrutRB tests"
23
- system!("bin/rspec")
23
+ system!("bin/test")
24
+
25
+ log "Running mkbrut tests"
26
+ FileUtils.chdir mkbrut_dir do
27
+ system!("bin/ci")
28
+ end
29
+
30
+ log "Running Rubcop"
31
+ system!("bin/generate-and-run-rubocop")
24
32
 
25
33
  log "Running brut-js tests"
26
34
  FileUtils.chdir brutjs_dir do
@@ -30,7 +38,3 @@ log "Running brut-css tests"
30
38
  FileUtils.chdir brutcss_dir do
31
39
  system!("bin/ci")
32
40
  end
33
- log "Running mkbrut tests"
34
- FileUtils.chdir mkbrut_dir do
35
- system!("bin/ci")
36
- end
data/bin/docs CHANGED
@@ -37,7 +37,7 @@ log "Hacking CSS"
37
37
 
38
38
  [
39
39
  docs_dir / "css" / "style.css",
40
- docs_dir / "css" / "full_list.css"
40
+ docs_dir / "css" / "full_list.css",
41
41
  ].each do |css_file_to_hack|
42
42
  lines = File.read(css_file_to_hack).split(/\n/)
43
43
  File.open(css_file_to_hack, "w") do |f|
@@ -0,0 +1,52 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
6
+ ROOT_DIR=$(realpath "$SCRIPT_DIR/..")
7
+
8
+ usage() {
9
+ echo "Usage: $0 [-R]"
10
+ echo
11
+ echo " Generates .rubocop.yml and runs rubocop"
12
+ echo
13
+ echo "OPTIONS"
14
+ echo
15
+ echo " -R - Do not run rubocop, just generate the configuration"
16
+ echo
17
+ }
18
+
19
+ for arg in "$@"; do
20
+ if [ "${arg}" = "-h" ] || [ "${arg}" = "--help" ] || [ "${arg}" = "help" ]; then
21
+ usage
22
+ exit 0
23
+ fi
24
+ done
25
+
26
+ RUN_RUBOCOP=true
27
+ while getopts "R" opt "${@}"; do
28
+ case ${opt} in
29
+ R )
30
+ RUN_RUBOCOP=false
31
+ ;;
32
+ \? )
33
+ log "🛑" "Unknown option: ${opt}"
34
+ usage
35
+ ;;
36
+ : )
37
+ log "🛑" "Invalid option: ${opt} requires an argument"
38
+ usage
39
+ ;;
40
+ esac
41
+ done
42
+ shift $((OPTIND -1))
43
+
44
+ cd $ROOT_DIR
45
+ echo "[ "$0" ] Generating .rubocop.yml"
46
+ ruby -I "lib" -r brut/rubocop_config -e "Brut::RubocopConfig.new.create_ridiculous_yaml" .rubocop.yml
47
+ if [ "$RUN_RUBOCOP" = true ]; then
48
+ echo "[ "$0" ] Running rubocop"
49
+ bin/rubocop
50
+ else
51
+ echo "[ "$0" ] Not Running rubocop"
52
+ fi
data/bin/rubocop ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rubocop", "rubocop")
data/bin/setup CHANGED
@@ -16,9 +16,15 @@ def setup(update_gems:,setup_credentials:)
16
16
  system! "bundle check --no-color || bundle install --no-color --quiet"
17
17
  end
18
18
 
19
+ log "Creating Rubocop configuration"
20
+ system! "bin/generate-and-run-rubocop -R"
21
+
19
22
  log "Installing Ruby LSP"
20
23
  system! "gem install ruby-lsp"
21
24
 
25
+ log "Installing rubocop-disable_syntax because I have not set up RubyLSP for bundler yet"
26
+ system! "gem install rubocop-disable_syntax"
27
+
22
28
  log "Installing JS/TS and CSS LSPs"
23
29
  system! "npm install -g typescript typescript-language-server vscode-langservers-extracted"
24
30
 
@@ -164,6 +170,46 @@ def setup(update_gems:,setup_credentials:)
164
170
  end
165
171
  end
166
172
 
173
+ docker_credentials_source = credentials_dir / "dockerhub.credentials"
174
+ docker_credentials_preamble = [
175
+ "# Username and PAT for Docker commands",
176
+ "# The file format is for bin/setup and bin/deploy",
177
+ "# to coordinate. This file format should be able to be",
178
+ "# sourced into a bash script via .",
179
+ ]
180
+ if !docker_credentials_source.exist?
181
+ log "#{docker_credentials_source} doesn't exist - creating"
182
+ File.open(docker_credentials_source,"w") do |file|
183
+ docker_credentials_preamble.each { |line| file.puts line }
184
+ end
185
+ end
186
+ existing_file = File.read(docker_credentials_source).split(/\n/).reject {
187
+ it =~ /^\s*#/
188
+ }.map { |line|
189
+ line.split(/=/,2).map(&:strip)
190
+ }.to_h
191
+ changed = false
192
+ if !existing_file.key?("DOCKERHUB_USERNAME")
193
+ log "What is the username for DockerHub you will use to push mkbrut images?"
194
+ existing_file["DOCKERHUB_USERNAME"] = gets.chomp
195
+ changed = true
196
+ end
197
+ if !existing_file.key?("DOCKERHUB_PAT")
198
+ log "What is the Personal Access Token (PAT) for DockerHub you will use to push mkbrut images?"
199
+ existing_file["DOCKERHUB_PAT"] = gets.chomp
200
+ changed = true
201
+ end
202
+ if changed
203
+ File.open(docker_credentials_source,"w") do |file|
204
+ docker_credentials_preamble.each { |line| file.puts line }
205
+ existing_file.each do |key,value|
206
+ file.puts "#{key}=#{value}"
207
+ end
208
+ end
209
+ else
210
+ log "#{docker_credentials_source} exists and looks good"
211
+ end
212
+
167
213
  log "Setting up BrutJS"
168
214
  FileUtils.chdir project_root / "brut-js" do
169
215
  system! "bin/setup"
data/bin/test ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "optparse"
4
+ require_relative "bin_kit"
5
+
6
+ OptionParser.new do |opts|
7
+ opts.banner = "Usage: test [options]\n\n Runs Brut tests only\n\nOPTIONS\n\n"
8
+
9
+ opts.on("-h", "--help", "Display this help message") do
10
+ puts opts
11
+ puts
12
+ exit
13
+ end
14
+ end.parse!
15
+
16
+ log "Running BrutRB tests"
17
+ system!("bin/rspec -I specs --require spec_helper -P \"specs/**/*.spec.rb\"")
18
+
data/brut-css/bin/publish CHANGED
@@ -18,4 +18,4 @@ for arg in "$@"; do
18
18
  fi
19
19
  done
20
20
 
21
- npm publish brut-css
21
+ npm publish
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "brut-css",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "brut-css",
9
- "version": "0.8.0",
9
+ "version": "0.9.0",
10
10
  "license": "Hippocratic-2.1",
11
11
  "devDependencies": {
12
12
  "comment-parser": "^1.4.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brut-css",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Utility CSS Library for Full Stack Developers",
5
5
  "keywords": [
6
6
  "css"
data/brut-js/bin/publish CHANGED
@@ -18,4 +18,4 @@ for arg in "$@"; do
18
18
  fi
19
19
  done
20
20
 
21
- npm publish brut-js
21
+ npm publish
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "brut-js",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "brut-js",
9
- "version": "0.8.0",
9
+ "version": "0.9.0",
10
10
  "license": "Hippocratic-2.1",
11
11
  "devDependencies": {
12
12
  "esbuild": "^0.24.0",
data/brut-js/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brut-js",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "keywords": [ "WebComponents", "Custom Elements" ],
6
6
  "bugs": {
data/brut.gemspec CHANGED
@@ -1,5 +1,7 @@
1
1
  lib = File.expand_path("../lib", __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
2
+ if !$LOAD_PATH.include?(lib)
3
+ $LOAD_PATH.unshift(lib)
4
+ end
3
5
  require "brut/version"
4
6
 
5
7
  Gem::Specification.new do |spec|
@@ -10,7 +12,7 @@ Gem::Specification.new do |spec|
10
12
 
11
13
  spec.summary = %q{Web Framework Built around Ruby, Web Standards, Simplicity, and Object-Orientation}
12
14
  spec.description = %q{An opinionated web framework build on web standards}
13
- spec.homepage = "https://naildrivin5.com"
15
+ spec.homepage = "https://brutrb.com"
14
16
 
15
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
18
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -18,8 +20,10 @@ Gem::Specification.new do |spec|
18
20
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
19
21
 
20
22
  spec.metadata["homepage_uri"] = spec.homepage
21
- spec.metadata["source_code_uri"] = "https://naildrivin5.com"
22
- spec.metadata["changelog_uri"] = "https://naildrivin5.com"
23
+ spec.metadata["source_code_uri"] = "https://github.com/thirdtank/brut"
24
+ spec.metadata["changelog_uri"] = "https://github.com/thirdtank/brut/blob/main/CHANGELOG.md"
25
+ spec.metadata["documentation_uri"] = "https://brutrb.com/"
26
+ spec.metadata["rubygems_mfa_required"] = "true"
23
27
  else
24
28
  raise "RubyGems 2.0 or newer is required to protect against " \
25
29
  "public gem pushes."
@@ -34,32 +38,34 @@ Gem::Specification.new do |spec|
34
38
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
39
  spec.require_paths = ["lib"]
36
40
 
37
- spec.add_runtime_dependency "irb"
38
- spec.add_runtime_dependency "ostruct" # squelch some warning - this is not used
39
- spec.add_runtime_dependency "concurrent-ruby"
40
- spec.add_runtime_dependency "i18n"
41
- spec.add_runtime_dependency "nokogiri"
42
- spec.add_runtime_dependency "phlex"
43
- spec.add_runtime_dependency "prism"
44
- spec.add_runtime_dependency "rack-protection"
45
- spec.add_runtime_dependency "rackup"
46
- spec.add_runtime_dependency "semantic_logger"
47
- spec.add_runtime_dependency "sequel"
48
- spec.add_runtime_dependency "sinatra"
49
- spec.add_runtime_dependency "tzinfo"
50
- spec.add_runtime_dependency "tzinfo-data"
51
- spec.add_runtime_dependency "zeitwerk"
52
- spec.add_runtime_dependency "opentelemetry-sdk"
53
- spec.add_runtime_dependency "opentelemetry-exporter-otlp"
41
+ spec.add_dependency "irb"
42
+ spec.add_dependency "ostruct" # squelch some warning - this is not used
43
+ spec.add_dependency "concurrent-ruby"
44
+ spec.add_dependency "i18n"
45
+ spec.add_dependency "nokogiri"
46
+ spec.add_dependency "phlex"
47
+ spec.add_dependency "prism"
48
+ spec.add_dependency "rack-protection"
49
+ spec.add_dependency "rackup"
50
+ spec.add_dependency "semantic_logger"
51
+ spec.add_dependency "sequel"
52
+ spec.add_dependency "sinatra"
53
+ spec.add_dependency "tzinfo"
54
+ spec.add_dependency "tzinfo-data"
55
+ spec.add_dependency "zeitwerk"
56
+ spec.add_dependency "opentelemetry-sdk"
57
+ spec.add_dependency "opentelemetry-exporter-otlp"
54
58
 
55
59
  spec.add_development_dependency "activesupport"
56
- spec.add_development_dependency "rspec", "~> 3.0"
57
60
  spec.add_development_dependency "bundler"
58
- spec.add_development_dependency "rake"
59
- spec.add_development_dependency "yard"
60
- spec.add_development_dependency "rdiscount"
61
- spec.add_development_dependency "rdoc"
62
61
  spec.add_development_dependency "dotenv"
63
62
  spec.add_development_dependency "factory_bot"
64
63
  spec.add_development_dependency "faker"
64
+ spec.add_development_dependency "rake"
65
+ spec.add_development_dependency "rdiscount"
66
+ spec.add_development_dependency "rdoc"
67
+ spec.add_development_dependency "rubocop"
68
+ spec.add_development_dependency "rubocop-disable_syntax"
69
+ spec.add_development_dependency "rspec", "~> 3.0"
70
+ spec.add_development_dependency "yard"
65
71
  end
@@ -6,6 +6,9 @@ import jsdocLinker from './plugins/jsdocLinker'
6
6
  export default defineConfig({
7
7
  title: "Brut RB",
8
8
  description: "Documentation for the Brut.RB web framework.",
9
+ ignoreDeadLinks: [
10
+ /^https?:\/\/localhost/,
11
+ ],
9
12
  head: [
10
13
  ["link", { rel: "icon", href: "/favicon.ico" }],
11
14
  [
@@ -142,7 +142,7 @@ unique keys is trivial, so Brut provides a way to do that.
142
142
  > A **key** simply uniquely identifies a row or is a unique constraint on a table.
143
143
  > Tables have only one primary key, but potentially many keys. Brut uses
144
144
  > *synthetic* (sometimes called *surrogate*) keys as primary keys. This means
145
- > they have no business meaning and can be safely used for foreighn keys
145
+ > they have no business meaning and can be safely used for foreign keys
146
146
  > and other cases without conflating them with domain concepts.
147
147
 
148
148
 
@@ -66,7 +66,7 @@ bin/db migrate
66
66
  > [!IMPORTANT]
67
67
  > This only applied migrations to the dev database. `bin/ci` and `bin/test e2e`
68
68
  > will apply them to the test database, but you may need to do it yourself via
69
- > `bin/db migration -e test`
69
+ > `bin/db migrate -e test`
70
70
 
71
71
  > [!NOTE]
72
72
  > There is no down migration. If you need to change and re-apply this before
@@ -12,6 +12,9 @@ services:
12
12
  - type: bind
13
13
  source: ${GIT_CONFIG}
14
14
  target: "/home/appuser/.gitconfig"
15
+ - type: bind
16
+ source: "/var/run/docker.sock"
17
+ target: "/var/run/docker.sock"
15
18
  command: /home/appuser/show-help-in-app-container-then-wait.sh
16
19
  working_dir: ${PWD}
17
20
  environment:
data/docs/404.html CHANGED
@@ -9,7 +9,7 @@
9
9
  <link rel="preload stylesheet" href="/assets/style.B1z60PPQ.css" as="style">
10
10
  <link rel="preload stylesheet" href="/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/assets/app.DyQLb4Ot.js"></script>
12
+ <script type="module" src="/assets/app.CmkhEsw7.js"></script>
13
13
  <link rel="icon" href="/favicon.ico">
14
14
  <meta property="og:title" content="BrutRB Documentation">
15
15
  <meta property="og:type" content="website">
@@ -20,7 +20,7 @@
20
20
  </head>
21
21
  <body>
22
22
  <div id="app"></div>
23
- <script>window.__VP_HASH_MAP__=JSON.parse("{\"adrs.md\":\"BxjHi9-8\",\"ai.md\":\"Cy9GWnER\",\"assets.md\":\"7C3HWkga\",\"brut-js.md\":\"B4GYxQVw\",\"business-logic.md\":\"BY4hGy0m\",\"cli.md\":\"CjsktgFz\",\"components.md\":\"DHh-NwKs\",\"configuration.md\":\"D8Wz3oJU\",\"css.md\":\"CltvJqAa\",\"custom-element-tests.md\":\"B_rbta32\",\"database-access.md\":\"gnluu54N\",\"database-schema.md\":\"C5gXexJi\",\"deployment.md\":\"BLseERGV\",\"dev-environment.md\":\"DRH2D2-O\",\"dir-structure.md\":\"CWir1pic\",\"doc-conventions.md\":\"DOkAuXlt\",\"end-to-end-tests.md\":\"DzqRpZ43\",\"features.md\":\"DPFXsy0z\",\"flash-and-session.md\":\"nPvUpnUx\",\"form-constraints.md\":\"DK5adCgM\",\"forms.md\":\"BRE85eju\",\"getting-started.md\":\"2ioiTe-B\",\"handlers.md\":\"h84MMB1R\",\"hooks.md\":\"Jmb5VOLA\",\"i18n.md\":\"BAm9t9JJ\",\"index.md\":\"Bn9e0sRJ\",\"instrumentation.md\":\"BgcaGVYH\",\"javascript.md\":\"DzrMxUmI\",\"jobs.md\":\"S-2amAYp\",\"keyword-injection.md\":\"95Zgh2eN\",\"layouts.md\":\"CVGl9xIO\",\"lsp.md\":\"Dn1rIiW0\",\"markdown-examples.md\":\"CCFEQO44\",\"middleware.md\":\"Czz_UlJN\",\"overview.md\":\"DlKiRRG_\",\"pages.md\":\"B7Hc-i6H\",\"recipes_alternate-layouts.md\":\"BwEytl59\",\"recipes_authentication.md\":\"Dzvi_g69\",\"recipes_blank-layouts.md\":\"fyAUJyJR\",\"recipes_custom-flash.md\":\"CrQbI5eH\",\"recipes_indexed-forms.md\":\"CstYyOSo\",\"recipes_migrations.md\":\"DPN3gQE3\",\"recipes_text-field-component.md\":\"H4wLAK0Z\",\"roadmap.md\":\"C6PRi0DX\",\"routes.md\":\"BD6y2i-f\",\"security.md\":\"C0G_AZR-\",\"seed-data.md\":\"BvFZlqIk\",\"space-time-continuum.md\":\"xl44xDos\",\"tutorial.md\":\"BIb7XT6j\",\"unit-tests.md\":\"DUGrnLj5\",\"why.md\":\"C-hk5xgJ\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Brut RB\",\"description\":\"Documentation for the Brut.RB web framework.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\"},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Overview\",\"link\":\"/overview\"},{\"text\":\"Brut API\",\"link\":\"/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutCSS\",\"link\":\"/brut-css/index.html\",\"target\":\"_self\"}],\"outline\":[2,3],\"sidebar\":[{\"text\":\"Overview\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Concepts\",\"link\":\"/overview\"},{\"text\":\"Features\",\"link\":\"/features\"},{\"text\":\"Directory Structure\",\"link\":\"/dir-structure\"},{\"text\":\"Dev Environment\",\"link\":\"/dev-environment\"},{\"text\":\"Tutorial\",\"link\":\"/tutorial\"},{\"text\":\"Documentation Conventions\",\"link\":\"/doc-conventions\"}]},{\"text\":\"Front-End\",\"collapsed\":false,\"items\":[{\"text\":\"Routes\",\"link\":\"/routes\"},{\"text\":\"Pages\",\"link\":\"/pages\"},{\"text\":\"Layouts\",\"link\":\"/layouts\"},{\"text\":\"Forms\",\"link\":\"/forms\"},{\"text\":\"Form Constraints\",\"link\":\"/form-constraints\"},{\"text\":\"Handlers and Actions\",\"link\":\"/handlers\"},{\"text\":\"Components\",\"link\":\"/components\"},{\"text\":\"Flash and Session\",\"link\":\"/flash-and-session\"},{\"text\":\"Space/Time Continuum\",\"link\":\"/space-time-continuum\"},{\"text\":\"JavaScript\",\"link\":\"/javascript\"},{\"text\":\"CSS\",\"link\":\"/css\"},{\"text\":\"Assets\",\"link\":\"/assets\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js\"}]},{\"text\":\"Back-End\",\"collapsed\":false,\"items\":[{\"text\":\"Database Schema\",\"link\":\"/database-schema\"},{\"text\":\"Database Access\",\"link\":\"/database-access\"},{\"text\":\"Seed Data\",\"link\":\"/seed-data\"},{\"text\":\"Jobs\",\"link\":\"/jobs\"},{\"text\":\"Business Logic\",\"link\":\"/business-logic\"}]},{\"text\":\"Framework\",\"collapsed\":false,\"items\":[{\"text\":\"Configuration\",\"link\":\"/configuration\"},{\"text\":\"Keyword Injection\",\"link\":\"/keyword-injection\"},{\"text\":\"I18n\",\"link\":\"/i18n\"},{\"text\":\"CLI / Tasks\",\"link\":\"/cli\"},{\"text\":\"Deployment\",\"link\":\"/deployment\"}]},{\"text\":\"Testing\",\"collapsed\":false,\"items\":[{\"text\":\"Unit Tests\",\"link\":\"/unit-tests\"},{\"text\":\"End-to-End Tests\",\"link\":\"/end-to-end-tests\"},{\"text\":\"Testing Custom Elements\",\"link\":\"/custom-element-tests\"}]},{\"text\":\"Advanced Topics\",\"collapsed\":true,\"items\":[{\"text\":\"Route Hooks\",\"link\":\"/hooks\"},{\"text\":\"Middleware\",\"link\":\"/middleware\"},{\"text\":\"Instrumentation\",\"link\":\"/instrumentation\"},{\"text\":\"Security\",\"link\":\"/security\"},{\"text\":\"LSP Support\",\"link\":\"/lsp\"}]},{\"text\":\"Recipes\",\"collapsed\":true,\"items\":[{\"text\":\"Migration Basics\",\"link\":\"/recipes/migrations\"},{\"text\":\"Authentication\",\"link\":\"/recipes/authentication\"},{\"text\":\"Alternate Layouts\",\"link\":\"/recipes/alternate-layouts\"},{\"text\":\"Blank Layouts\",\"link\":\"/recipes/blank-layouts\"},{\"text\":\"Custom Flash Class\",\"link\":\"/recipes/custom-flash\"},{\"text\":\"Indexed Form Elements\",\"link\":\"/recipes/indexed-forms\"},{\"text\":\"Text Field Component\",\"link\":\"/recipes/text-field-component\"}]},{\"text\":\"Meta\",\"collapsed\":false,\"items\":[{\"text\":\"Why?!\",\"link\":\"/why\"},{\"text\":\"ADRs\",\"link\":\"/adrs\"},{\"text\":\"Roadmap to 1.0\",\"link\":\"/roadmap\"},{\"text\":\"AI Declaration\",\"link\":\"/ai\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/thirdtank/brut\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
23
+ <script>window.__VP_HASH_MAP__=JSON.parse("{\"adrs.md\":\"BxjHi9-8\",\"ai.md\":\"Cy9GWnER\",\"assets.md\":\"7C3HWkga\",\"brut-js.md\":\"B4GYxQVw\",\"business-logic.md\":\"BY4hGy0m\",\"cli.md\":\"CjsktgFz\",\"components.md\":\"-22ecBxM\",\"configuration.md\":\"CLKL1lFf\",\"css.md\":\"CltvJqAa\",\"custom-element-tests.md\":\"B_rbta32\",\"database-access.md\":\"gnluu54N\",\"database-schema.md\":\"LpmBPVEU\",\"deployment.md\":\"BLseERGV\",\"dev-environment.md\":\"DRH2D2-O\",\"dir-structure.md\":\"CWir1pic\",\"doc-conventions.md\":\"DOkAuXlt\",\"end-to-end-tests.md\":\"DzqRpZ43\",\"features.md\":\"DPFXsy0z\",\"flash-and-session.md\":\"nPvUpnUx\",\"form-constraints.md\":\"DK5adCgM\",\"forms.md\":\"CBI5--o2\",\"getting-started.md\":\"D5nzBZ4J\",\"handlers.md\":\"h84MMB1R\",\"hooks.md\":\"Jmb5VOLA\",\"i18n.md\":\"BAm9t9JJ\",\"index.md\":\"Bn9e0sRJ\",\"instrumentation.md\":\"BgcaGVYH\",\"javascript.md\":\"DzrMxUmI\",\"jobs.md\":\"S-2amAYp\",\"keyword-injection.md\":\"95Zgh2eN\",\"layouts.md\":\"CVGl9xIO\",\"lsp.md\":\"Dn1rIiW0\",\"markdown-examples.md\":\"CCFEQO44\",\"middleware.md\":\"Czz_UlJN\",\"overview.md\":\"DlKiRRG_\",\"pages.md\":\"B7Hc-i6H\",\"recipes_alternate-layouts.md\":\"BwEytl59\",\"recipes_authentication.md\":\"Dzvi_g69\",\"recipes_blank-layouts.md\":\"fyAUJyJR\",\"recipes_custom-flash.md\":\"CrQbI5eH\",\"recipes_indexed-forms.md\":\"CstYyOSo\",\"recipes_migrations.md\":\"CTcnWDJF\",\"recipes_text-field-component.md\":\"H4wLAK0Z\",\"roadmap.md\":\"C6PRi0DX\",\"routes.md\":\"BD6y2i-f\",\"security.md\":\"C0G_AZR-\",\"seed-data.md\":\"BvFZlqIk\",\"space-time-continuum.md\":\"xl44xDos\",\"tutorial.md\":\"BIb7XT6j\",\"unit-tests.md\":\"DUGrnLj5\",\"why.md\":\"C-hk5xgJ\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Brut RB\",\"description\":\"Documentation for the Brut.RB web framework.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\"},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Overview\",\"link\":\"/overview\"},{\"text\":\"Brut API\",\"link\":\"/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutCSS\",\"link\":\"/brut-css/index.html\",\"target\":\"_self\"}],\"outline\":[2,3],\"sidebar\":[{\"text\":\"Overview\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Concepts\",\"link\":\"/overview\"},{\"text\":\"Features\",\"link\":\"/features\"},{\"text\":\"Directory Structure\",\"link\":\"/dir-structure\"},{\"text\":\"Dev Environment\",\"link\":\"/dev-environment\"},{\"text\":\"Tutorial\",\"link\":\"/tutorial\"},{\"text\":\"Documentation Conventions\",\"link\":\"/doc-conventions\"}]},{\"text\":\"Front-End\",\"collapsed\":false,\"items\":[{\"text\":\"Routes\",\"link\":\"/routes\"},{\"text\":\"Pages\",\"link\":\"/pages\"},{\"text\":\"Layouts\",\"link\":\"/layouts\"},{\"text\":\"Forms\",\"link\":\"/forms\"},{\"text\":\"Form Constraints\",\"link\":\"/form-constraints\"},{\"text\":\"Handlers and Actions\",\"link\":\"/handlers\"},{\"text\":\"Components\",\"link\":\"/components\"},{\"text\":\"Flash and Session\",\"link\":\"/flash-and-session\"},{\"text\":\"Space/Time Continuum\",\"link\":\"/space-time-continuum\"},{\"text\":\"JavaScript\",\"link\":\"/javascript\"},{\"text\":\"CSS\",\"link\":\"/css\"},{\"text\":\"Assets\",\"link\":\"/assets\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js\"}]},{\"text\":\"Back-End\",\"collapsed\":false,\"items\":[{\"text\":\"Database Schema\",\"link\":\"/database-schema\"},{\"text\":\"Database Access\",\"link\":\"/database-access\"},{\"text\":\"Seed Data\",\"link\":\"/seed-data\"},{\"text\":\"Jobs\",\"link\":\"/jobs\"},{\"text\":\"Business Logic\",\"link\":\"/business-logic\"}]},{\"text\":\"Framework\",\"collapsed\":false,\"items\":[{\"text\":\"Configuration\",\"link\":\"/configuration\"},{\"text\":\"Keyword Injection\",\"link\":\"/keyword-injection\"},{\"text\":\"I18n\",\"link\":\"/i18n\"},{\"text\":\"CLI / Tasks\",\"link\":\"/cli\"},{\"text\":\"Deployment\",\"link\":\"/deployment\"}]},{\"text\":\"Testing\",\"collapsed\":false,\"items\":[{\"text\":\"Unit Tests\",\"link\":\"/unit-tests\"},{\"text\":\"End-to-End Tests\",\"link\":\"/end-to-end-tests\"},{\"text\":\"Testing Custom Elements\",\"link\":\"/custom-element-tests\"}]},{\"text\":\"Advanced Topics\",\"collapsed\":true,\"items\":[{\"text\":\"Route Hooks\",\"link\":\"/hooks\"},{\"text\":\"Middleware\",\"link\":\"/middleware\"},{\"text\":\"Instrumentation\",\"link\":\"/instrumentation\"},{\"text\":\"Security\",\"link\":\"/security\"},{\"text\":\"LSP Support\",\"link\":\"/lsp\"}]},{\"text\":\"Recipes\",\"collapsed\":true,\"items\":[{\"text\":\"Migration Basics\",\"link\":\"/recipes/migrations\"},{\"text\":\"Authentication\",\"link\":\"/recipes/authentication\"},{\"text\":\"Alternate Layouts\",\"link\":\"/recipes/alternate-layouts\"},{\"text\":\"Blank Layouts\",\"link\":\"/recipes/blank-layouts\"},{\"text\":\"Custom Flash Class\",\"link\":\"/recipes/custom-flash\"},{\"text\":\"Indexed Form Elements\",\"link\":\"/recipes/indexed-forms\"},{\"text\":\"Text Field Component\",\"link\":\"/recipes/text-field-component\"}]},{\"text\":\"Meta\",\"collapsed\":false,\"items\":[{\"text\":\"Why?!\",\"link\":\"/why\"},{\"text\":\"ADRs\",\"link\":\"/adrs\"},{\"text\":\"Roadmap to 1.0\",\"link\":\"/roadmap\"},{\"text\":\"AI Declaration\",\"link\":\"/ai\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/thirdtank/brut\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
24
24
 
25
25
  </body>
26
26
  </html>