brut 0.5.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 +7 -0
- data/Dockerfile.dx +19 -0
- data/Gemfile.lock +1 -1
- data/README.md +19 -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-js/bin/build +15 -6
- data/brut-js/bin/docs +25 -0
- data/brut-js/bin/publish +21 -0
- data/brut-js/bin/setup +1 -0
- data/brut-js/dx +1 -0
- data/brut-js/package-lock.json +2 -2
- data/brut-js/package.json +1 -1
- data/brut.gemspec +2 -2
- 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 +3 -3
- data/docs/ai.html +3 -3
- data/docs/assets/{app.D6BuVHo9.js → app.DyQLb4Ot.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.CmtZyrFA.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.BpvHMbx6.js → VPLocalSearchBox.T1iA-eJx.js} +1 -1
- data/docs/assets/chunks/{theme.wlAOvi2f.js → theme.ChwsbWjK.js} +2 -2
- data/docs/assets/{components.md.iLiv2E9X.js → components.md.DHh-NwKs.js} +3 -3
- data/docs/assets/{configuration.md.DmuAdsli.js → configuration.md.D8Wz3oJU.js} +1 -1
- data/docs/assets/{forms.md.D8aa_qI-.js → forms.md.BRE85eju.js} +1 -1
- data/docs/assets/{getting-started.md.DLplsDUd.js → getting-started.md.2ioiTe-B.js} +6 -3
- data/docs/assets/{getting-started.md.DLplsDUd.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-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/framework/mcp.rb +1 -1
- data/lib/brut/front_end/components/form_tag.rb +2 -2
- data/lib/brut/version.rb +1 -1
- data/mkbrut/.gitignore +16 -0
- data/mkbrut/CODE_OF_CONDUCT.txt +100 -0
- data/mkbrut/Gemfile +3 -0
- data/mkbrut/Gemfile.lock +19 -0
- data/mkbrut/LICENSE.txt +370 -0
- data/mkbrut/README.md +145 -0
- data/mkbrut/Rakefile +2 -0
- data/mkbrut/bin/build +36 -0
- data/mkbrut/bin/ci +19 -0
- data/mkbrut/bin/docs +19 -0
- data/mkbrut/bin/publish +129 -0
- data/mkbrut/bin/rake +16 -0
- data/mkbrut/bin/setup +30 -0
- data/mkbrut/brut-welcome.png +0 -0
- data/mkbrut/deploy/.dockerignore +2 -0
- data/mkbrut/deploy/Dockerfile +25 -0
- data/mkbrut/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 +185 -21
- data/docs/assets/chunks/@localSearchIndexroot.COP2Bcmp.js +0 -1
- data/docs/assets/overview.md.iMnwLO4x.js +0 -1
- data/docs/assets/overview.md.iMnwLO4x.lean.js +0 -1
- data/docs/assets/tutorial.md.BYXj4cOu.js +0 -1
- data/docs/assets/tutorial.md.BYXj4cOu.lean.js +0 -1
- /data/docs/assets/{components.md.iLiv2E9X.lean.js → components.md.DHh-NwKs.lean.js} +0 -0
- /data/docs/assets/{configuration.md.DmuAdsli.lean.js → configuration.md.D8Wz3oJU.lean.js} +0 -0
- /data/docs/assets/{forms.md.D8aa_qI-.lean.js → forms.md.BRE85eju.lean.js} +0 -0
@@ -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
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/* Gives all SVGS a somewhat small height so as CSS loads,
|
2
|
+
* you don't have a big huge SVG */
|
3
|
+
svg {
|
4
|
+
width: 1em;
|
5
|
+
height: 1em;
|
6
|
+
}
|
7
|
+
|
8
|
+
/* Assuming SVGs are monochrome line art,
|
9
|
+
* this ensures the lines are drawn in the current color */
|
10
|
+
svg path {
|
11
|
+
fill: currentColor;
|
12
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# The default layout used by all pages.
|
2
|
+
# This code is heavily commented to explain what each
|
3
|
+
# line that isn't hopefully obvious does. Feel free to remove.
|
4
|
+
class DefaultLayout < Brut::FrontEnd::Layout
|
5
|
+
include Brut::FrontEnd::Components
|
6
|
+
|
7
|
+
def initialize(page_name:)
|
8
|
+
@page_name = page_name
|
9
|
+
end
|
10
|
+
|
11
|
+
# Brut::FrontEnd::Page's view_template ultimately calls this method
|
12
|
+
# to wrap itself in the layout defined below.
|
13
|
+
def view_template
|
14
|
+
doctype
|
15
|
+
html(lang: "en") do
|
16
|
+
head do
|
17
|
+
meta(charset: "utf-8")
|
18
|
+
meta(content: "width=device-width,initial-scale=1", name:"viewport")
|
19
|
+
meta(content: "website", property:"og:type")
|
20
|
+
# Sets this up as a PWA - see app/public/static/manifest.json
|
21
|
+
link(rel: "manifest", href: "/static/manifest.json")
|
22
|
+
|
23
|
+
# Load the bundled stylesheet. asset_path translates the logical
|
24
|
+
# path to the hased value produced by esbuild
|
25
|
+
link(rel: "preload", as: "style", href: asset_path("/css/styles.css"))
|
26
|
+
link(rel: "stylesheet", href: asset_path("/css/styles.css"))
|
27
|
+
|
28
|
+
# Load the bundled JavaScript. asset_path translates the logical
|
29
|
+
# path to the hased value produced by esbuild
|
30
|
+
script(defer: true, src: asset_path("/js/app.js"))
|
31
|
+
|
32
|
+
title do
|
33
|
+
"<%= app_name %>"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Brut::FrontEnd::Components::PageIdentifier, which produces
|
37
|
+
# a <meta> tag with the page's name. Useful for end to end tests.
|
38
|
+
PageIdentifier(@page_name)
|
39
|
+
|
40
|
+
# Brut::FrontEnd::Components::I18nTranslations, which includes
|
41
|
+
# translations starting with cv.cs for use with client-side
|
42
|
+
# constraint violation messaging.
|
43
|
+
I18nTranslations("cv.cs")
|
44
|
+
# Brut::FrontEnd::Components::I18nTranslations, which includes
|
45
|
+
# translations for cv.this_field, which is used with client-side
|
46
|
+
# constraint violation messaging.
|
47
|
+
I18nTranslations("cv.this_field")
|
48
|
+
# Brut::FrontEnd::Components::Traceparent, which stores
|
49
|
+
# the OpenTelemetry traceparent in a <meta> attribute for use
|
50
|
+
# by the <brut-tracing> element.
|
51
|
+
Traceparent()
|
52
|
+
# Brut::FrontEnd::Components::LocaleDetection, which
|
53
|
+
# will send the browser's locale and timezone back to the server to
|
54
|
+
# help with locale determination.
|
55
|
+
render(
|
56
|
+
Brut::FrontEnd::RequestContext.inject(
|
57
|
+
Brut::FrontEnd::Components::LocaleDetection
|
58
|
+
)
|
59
|
+
)
|
60
|
+
end
|
61
|
+
# Adds the page's name as a class name. You can use this for
|
62
|
+
# CSS if needed.
|
63
|
+
body(class: @page_name) do
|
64
|
+
# Render the <brut-tracing> element, which will send
|
65
|
+
# OpenTelemetry traces back to the server to be joined up with
|
66
|
+
# the server's traces.
|
67
|
+
brut_tracing url: "/__brut/instrumentation", show_warnings: true
|
68
|
+
yield # Contents of the page are inserted here
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Base class for all pages in the app
|
2
|
+
# Note that while Brut::FrontEnd::Page is a subclass
|
3
|
+
# of Brut::FrontEnd::Component, that is not the case
|
4
|
+
# for your app's pages and components. Thus, there is a small amount
|
5
|
+
# of duplication here.
|
6
|
+
class AppPage < Brut::FrontEnd::Page
|
7
|
+
include Brut::Framework::Errors # See AppComponent
|
8
|
+
include CustomElementRegistration # See AppComponent
|
9
|
+
include Brut::FrontEnd::Components # See AppComponent
|
10
|
+
end
|
11
|
+
|