rails-metro 0.1.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 (150) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +17 -0
  3. data/LICENSE +21 -0
  4. data/README.md +267 -0
  5. data/exe/metro +3 -0
  6. data/lib/rails/metro/cli.rb +162 -0
  7. data/lib/rails/metro/config.rb +40 -0
  8. data/lib/rails/metro/feature_pack.rb +59 -0
  9. data/lib/rails/metro/feature_registry.rb +147 -0
  10. data/lib/rails/metro/packs/aasm_pack.rb +29 -0
  11. data/lib/rails/metro/packs/ab_testing_pack.rb +39 -0
  12. data/lib/rails/metro/packs/action_text_pack.rb +29 -0
  13. data/lib/rails/metro/packs/activeadmin_pack.rb +32 -0
  14. data/lib/rails/metro/packs/activity_feed_pack.rb +31 -0
  15. data/lib/rails/metro/packs/acts_as_list_pack.rb +28 -0
  16. data/lib/rails/metro/packs/acts_as_votable_pack.rb +32 -0
  17. data/lib/rails/metro/packs/administrate_pack.rb +31 -0
  18. data/lib/rails/metro/packs/after_party_pack.rb +31 -0
  19. data/lib/rails/metro/packs/ahoy_pack.rb +31 -0
  20. data/lib/rails/metro/packs/amplitude_pack.rb +45 -0
  21. data/lib/rails/metro/packs/annotate_pack.rb +30 -0
  22. data/lib/rails/metro/packs/api_cors_pack.rb +41 -0
  23. data/lib/rails/metro/packs/api_docs_pack.rb +34 -0
  24. data/lib/rails/metro/packs/api_guard_pack.rb +31 -0
  25. data/lib/rails/metro/packs/api_serialization_pack.rb +38 -0
  26. data/lib/rails/metro/packs/app_linting_pack.rb +35 -0
  27. data/lib/rails/metro/packs/audit_trail_pack.rb +31 -0
  28. data/lib/rails/metro/packs/authentication_pack.rb +31 -0
  29. data/lib/rails/metro/packs/authorization_pack.rb +31 -0
  30. data/lib/rails/metro/packs/avo_pack.rb +32 -0
  31. data/lib/rails/metro/packs/aws_ses_pack.rb +45 -0
  32. data/lib/rails/metro/packs/background_jobs_pack.rb +34 -0
  33. data/lib/rails/metro/packs/blazer_pack.rb +62 -0
  34. data/lib/rails/metro/packs/breadcrumbs_pack.rb +31 -0
  35. data/lib/rails/metro/packs/caching_pack.rb +30 -0
  36. data/lib/rails/metro/packs/charting_pack.rb +67 -0
  37. data/lib/rails/metro/packs/circuit_breaker_pack.rb +34 -0
  38. data/lib/rails/metro/packs/clicky_pack.rb +37 -0
  39. data/lib/rails/metro/packs/cloudinary_pack.rb +42 -0
  40. data/lib/rails/metro/packs/components_pack.rb +30 -0
  41. data/lib/rails/metro/packs/counter_culture_pack.rb +29 -0
  42. data/lib/rails/metro/packs/data_migrate_pack.rb +29 -0
  43. data/lib/rails/metro/packs/datadog_pack.rb +41 -0
  44. data/lib/rails/metro/packs/deployment_pack.rb +30 -0
  45. data/lib/rails/metro/packs/devise_pack.rb +33 -0
  46. data/lib/rails/metro/packs/doorkeeper_pack.rb +32 -0
  47. data/lib/rails/metro/packs/dotenv_pack.rb +36 -0
  48. data/lib/rails/metro/packs/elasticsearch_pack.rb +31 -0
  49. data/lib/rails/metro/packs/encryption_pack.rb +37 -0
  50. data/lib/rails/metro/packs/error_tracking_pack.rb +40 -0
  51. data/lib/rails/metro/packs/event_sourcing_pack.rb +31 -0
  52. data/lib/rails/metro/packs/faraday_pack.rb +42 -0
  53. data/lib/rails/metro/packs/fathom_pack.rb +36 -0
  54. data/lib/rails/metro/packs/feature_flags_pack.rb +34 -0
  55. data/lib/rails/metro/packs/friendly_id_pack.rb +31 -0
  56. data/lib/rails/metro/packs/geocoder_pack.rb +38 -0
  57. data/lib/rails/metro/packs/good_job_pack.rb +34 -0
  58. data/lib/rails/metro/packs/google_analytics_pack.rb +42 -0
  59. data/lib/rails/metro/packs/google_tag_manager_pack.rb +51 -0
  60. data/lib/rails/metro/packs/graphql_pack.rb +31 -0
  61. data/lib/rails/metro/packs/health_check_pack.rb +34 -0
  62. data/lib/rails/metro/packs/heap_pack.rb +39 -0
  63. data/lib/rails/metro/packs/honeybadger_pack.rb +37 -0
  64. data/lib/rails/metro/packs/hotwire_livereload_pack.rb +28 -0
  65. data/lib/rails/metro/packs/icons_pack.rb +28 -0
  66. data/lib/rails/metro/packs/invisible_captcha_pack.rb +35 -0
  67. data/lib/rails/metro/packs/kredis_pack.rb +31 -0
  68. data/lib/rails/metro/packs/lemon_squeezy_pack.rb +36 -0
  69. data/lib/rails/metro/packs/letter_opener_pack.rb +31 -0
  70. data/lib/rails/metro/packs/letter_opener_web_pack.rb +32 -0
  71. data/lib/rails/metro/packs/logging_pack.rb +36 -0
  72. data/lib/rails/metro/packs/madmin_pack.rb +32 -0
  73. data/lib/rails/metro/packs/mailgun_pack.rb +44 -0
  74. data/lib/rails/metro/packs/maintenance_mode_pack.rb +30 -0
  75. data/lib/rails/metro/packs/maintenance_tasks_pack.rb +32 -0
  76. data/lib/rails/metro/packs/markdown_pack.rb +48 -0
  77. data/lib/rails/metro/packs/matomo_pack.rb +48 -0
  78. data/lib/rails/metro/packs/meilisearch_pack.rb +37 -0
  79. data/lib/rails/metro/packs/mixpanel_pack.rb +47 -0
  80. data/lib/rails/metro/packs/mobility_pack.rb +32 -0
  81. data/lib/rails/metro/packs/mollie_pack.rb +36 -0
  82. data/lib/rails/metro/packs/multitenancy_pack.rb +35 -0
  83. data/lib/rails/metro/packs/newrelic_pack.rb +52 -0
  84. data/lib/rails/metro/packs/notifications_pack.rb +31 -0
  85. data/lib/rails/metro/packs/omniauth_pack.rb +49 -0
  86. data/lib/rails/metro/packs/paddle_pack.rb +37 -0
  87. data/lib/rails/metro/packs/pagination_pack.rb +44 -0
  88. data/lib/rails/metro/packs/passwordless_pack.rb +32 -0
  89. data/lib/rails/metro/packs/payments_pack.rb +35 -0
  90. data/lib/rails/metro/packs/paypal_pack.rb +35 -0
  91. data/lib/rails/metro/packs/pdf_pack.rb +45 -0
  92. data/lib/rails/metro/packs/performance_pack.rb +37 -0
  93. data/lib/rails/metro/packs/pghero_pack.rb +31 -0
  94. data/lib/rails/metro/packs/plausible_pack.rb +36 -0
  95. data/lib/rails/metro/packs/posthog_pack.rb +40 -0
  96. data/lib/rails/metro/packs/postmark_pack.rb +39 -0
  97. data/lib/rails/metro/packs/pretender_pack.rb +33 -0
  98. data/lib/rails/metro/packs/profiling_pack.rb +30 -0
  99. data/lib/rails/metro/packs/pundit_pack.rb +50 -0
  100. data/lib/rails/metro/packs/qr_code_pack.rb +37 -0
  101. data/lib/rails/metro/packs/r2_storage_pack.rb +48 -0
  102. data/lib/rails/metro/packs/rack_timeout_pack.rb +34 -0
  103. data/lib/rails/metro/packs/rails_i18n_pack.rb +31 -0
  104. data/lib/rails/metro/packs/ransack_pack.rb +29 -0
  105. data/lib/rails/metro/packs/rate_limiting_pack.rb +39 -0
  106. data/lib/rails/metro/packs/recaptcha_pack.rb +38 -0
  107. data/lib/rails/metro/packs/resend_pack.rb +37 -0
  108. data/lib/rails/metro/packs/revenuecat_pack.rb +36 -0
  109. data/lib/rails/metro/packs/rolify_pack.rb +32 -0
  110. data/lib/rails/metro/packs/rollbar_pack.rb +38 -0
  111. data/lib/rails/metro/packs/s3_storage_pack.rb +45 -0
  112. data/lib/rails/metro/packs/scenic_pack.rb +28 -0
  113. data/lib/rails/metro/packs/scheduling_pack.rb +46 -0
  114. data/lib/rails/metro/packs/search_pack.rb +32 -0
  115. data/lib/rails/metro/packs/security_pack.rb +30 -0
  116. data/lib/rails/metro/packs/sendgrid_pack.rb +44 -0
  117. data/lib/rails/metro/packs/sent_dm_pack.rb +36 -0
  118. data/lib/rails/metro/packs/seo_pack.rb +40 -0
  119. data/lib/rails/metro/packs/shoulda_matchers_pack.rb +37 -0
  120. data/lib/rails/metro/packs/sidekiq_pack.rb +42 -0
  121. data/lib/rails/metro/packs/simple_calendar_pack.rb +29 -0
  122. data/lib/rails/metro/packs/simple_form_pack.rb +30 -0
  123. data/lib/rails/metro/packs/simplecov_pack.rb +38 -0
  124. data/lib/rails/metro/packs/slack_notifier_pack.rb +36 -0
  125. data/lib/rails/metro/packs/soft_deletes_pack.rb +30 -0
  126. data/lib/rails/metro/packs/solidus_pack.rb +31 -0
  127. data/lib/rails/metro/packs/spreadsheets_pack.rb +29 -0
  128. data/lib/rails/metro/packs/statcounter_pack.rb +41 -0
  129. data/lib/rails/metro/packs/stimulus_components_pack.rb +33 -0
  130. data/lib/rails/metro/packs/storage_validations_pack.rb +28 -0
  131. data/lib/rails/metro/packs/strong_migrations_pack.rb +30 -0
  132. data/lib/rails/metro/packs/tagging_pack.rb +31 -0
  133. data/lib/rails/metro/packs/test_mocking_pack.rb +41 -0
  134. data/lib/rails/metro/packs/testing_pack.rb +39 -0
  135. data/lib/rails/metro/packs/twilio_pack.rb +38 -0
  136. data/lib/rails/metro/packs/vite_rails_pack.rb +31 -0
  137. data/lib/rails/metro/packs/web_push_pack.rb +39 -0
  138. data/lib/rails/metro/packs/webhooks_pack.rb +45 -0
  139. data/lib/rails/metro/packs/websockets_pack.rb +29 -0
  140. data/lib/rails/metro/template_compiler.rb +85 -0
  141. data/lib/rails/metro/tui/app.rb +119 -0
  142. data/lib/rails/metro/tui/steps/app_name_step.rb +57 -0
  143. data/lib/rails/metro/tui/steps/database_step.rb +53 -0
  144. data/lib/rails/metro/tui/steps/pack_step.rb +248 -0
  145. data/lib/rails/metro/tui/steps/review_step.rb +94 -0
  146. data/lib/rails/metro/tui/styles.rb +47 -0
  147. data/lib/rails/metro/tui.rb +37 -0
  148. data/lib/rails/metro/version.rb +5 -0
  149. data/lib/rails/metro.rb +9 -0
  150. metadata +206 -0
@@ -0,0 +1,34 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class HealthCheckPack < FeaturePack
5
+ pack_name "health_check"
6
+ description "OkComputer for health check endpoints (load balancers, k8s)"
7
+ category "ops"
8
+
9
+ def gems
10
+ [
11
+ {name: "okcomputer"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'create_file "config/initializers/okcomputer.rb", <<~RUBY',
18
+ ' OkComputer::Registry.register "database", OkComputer::ActiveRecordCheck.new',
19
+ ' OkComputer::Registry.register "cache", OkComputer::GenericCacheCheck.new',
20
+ " OkComputer.mount_at = \"health\"",
21
+ "RUBY"
22
+ ]
23
+ end
24
+
25
+ def post_install_notes
26
+ [
27
+ "Health Check: Endpoints at /health and /health/all",
28
+ "Health Check: Point load balancer/k8s probes at /health"
29
+ ]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,39 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class HeapPack < FeaturePack
5
+ pack_name "heap"
6
+ description "Heap for auto-captured product analytics"
7
+ category "analytics"
8
+
9
+ def gems
10
+ []
11
+ end
12
+
13
+ def template_lines
14
+ [
15
+ 'create_file "app/views/layouts/_heap.html.erb", <<~ERB',
16
+ " <script type=\"text/javascript\">",
17
+ ' window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=document.createElement("script");r.type="text/javascript",r.async=!0,r.src="https://cdn.heapanalytics.com/js/heap-"+e+".js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(r,a);for(var n=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","resetIdentity","removeEventProperty","setEventProperties","track","unsetEventProperty"],o=0;o<p.length;o++)heap[p[o]]=n(p[o])};',
18
+ ' heap.load("<%%= Rails.application.credentials.dig(:heap, :app_id) || ENV["HEAP_APP_ID"] %>");',
19
+ " </script>",
20
+ "ERB",
21
+ "",
22
+ 'inject_into_file "app/views/layouts/application.html.erb", after: "<head>\\n" do',
23
+ ' " <%= render \\"layouts/heap\\" %>\\n"',
24
+ "end"
25
+ ]
26
+ end
27
+
28
+ def post_install_notes
29
+ [
30
+ "Heap: Add your app ID with `bin/rails credentials:edit`:",
31
+ " heap:",
32
+ " app_id: \"1234567890\"",
33
+ "Heap: Auto-captures all user interactions -- no manual event tracking needed"
34
+ ]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class HoneybadgerPack < FeaturePack
5
+ pack_name "honeybadger"
6
+ description "Honeybadger for error tracking and uptime monitoring"
7
+ category "ops"
8
+ conflicts_with "error_tracking", "rollbar"
9
+
10
+ def gems
11
+ [
12
+ {name: "honeybadger"}
13
+ ]
14
+ end
15
+
16
+ def template_lines
17
+ [
18
+ 'run "bundle exec honeybadger install"',
19
+ 'create_file "config/initializers/honeybadger.rb", <<~RUBY',
20
+ " Honeybadger.configure do |config|",
21
+ ' config.api_key = Rails.application.credentials.dig(:honeybadger, :api_key) || ENV["HONEYBADGER_API_KEY"]',
22
+ " end",
23
+ "RUBY"
24
+ ]
25
+ end
26
+
27
+ def post_install_notes
28
+ [
29
+ "Honeybadger: Add your API key with `bin/rails credentials:edit`:",
30
+ " honeybadger:",
31
+ " api_key: your_api_key_here"
32
+ ]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class HotwireLivereloadPack < FeaturePack
5
+ pack_name "hotwire_livereload"
6
+ description "Hotwire LiveReload for automatic page refresh on file changes"
7
+ category "ops"
8
+
9
+ def gems
10
+ [
11
+ {name: "hotwire-livereload", group: :development}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ []
17
+ end
18
+
19
+ def post_install_notes
20
+ [
21
+ "LiveReload: Pages auto-refresh when you save views, CSS, or JS files",
22
+ "LiveReload: Works via Hotwire/Turbo -- no browser extension needed"
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class IconsPack < FeaturePack
5
+ pack_name "icons"
6
+ description "Lucide Rails for modern SVG icons"
7
+ category "ui"
8
+
9
+ def gems
10
+ [
11
+ {name: "lucide-rails"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ []
17
+ end
18
+
19
+ def post_install_notes
20
+ [
21
+ "Icons: Use `<%= lucide_icon \"home\" %>` in views",
22
+ "Icons: Browse icons at https://lucide.dev"
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class InvisibleCaptchaPack < FeaturePack
5
+ pack_name "invisible_captcha"
6
+ description "Invisible Captcha for honeypot-based spam prevention"
7
+ category "core"
8
+
9
+ def gems
10
+ [
11
+ {name: "invisible_captcha"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'create_file "config/initializers/invisible_captcha.rb", <<~RUBY',
18
+ " InvisibleCaptcha.setup do |config|",
19
+ " config.honeypots = [:subtitle, :city, :nickname]",
20
+ " config.timestamp_threshold = 2",
21
+ " end",
22
+ "RUBY"
23
+ ]
24
+ end
25
+
26
+ def post_install_notes
27
+ [
28
+ "Invisible Captcha: Add `invisible_captcha` to forms that need spam protection",
29
+ "Invisible Captcha: No user-facing CAPTCHA -- uses honeypots and timing"
30
+ ]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class KredisPack < FeaturePack
5
+ pack_name "kredis"
6
+ description "Kredis for structured Redis types in Rails models"
7
+ category "data"
8
+
9
+ def gems
10
+ [
11
+ {name: "kredis"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'rails_command "kredis:install"'
18
+ ]
19
+ end
20
+
21
+ def post_install_notes
22
+ [
23
+ "Kredis: Requires Redis -- configure in config/redis/shared.yml",
24
+ "Kredis: Use `kredis_list :recent_searches` in models",
25
+ "Kredis: Supports lists, sets, flags, counters, enums, and more"
26
+ ]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class LemonSqueezyPack < FeaturePack
5
+ pack_name "lemon_squeezy"
6
+ description "Lemon Squeezy -- merchant of record for SaaS (handles tax/VAT)"
7
+ category "payments"
8
+
9
+ def gems
10
+ [
11
+ {name: "lemon_squeezy"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'create_file "config/initializers/lemon_squeezy.rb", <<~RUBY',
18
+ " LemonSqueezy.configure do |config|",
19
+ ' config.api_key = Rails.application.credentials.dig(:lemon_squeezy, :api_key) || ENV["LEMON_SQUEEZY_API_KEY"]',
20
+ " end",
21
+ "RUBY"
22
+ ]
23
+ end
24
+
25
+ def post_install_notes
26
+ [
27
+ "Lemon Squeezy: Add your API key with `bin/rails credentials:edit`:",
28
+ " lemon_squeezy:",
29
+ " api_key: your_api_key_here",
30
+ "Lemon Squeezy: Acts as merchant of record -- handles sales tax, VAT, and billing for you"
31
+ ]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class LetterOpenerPack < FeaturePack
5
+ pack_name "letter_opener"
6
+ description "Letter Opener for previewing emails in the browser (dev)"
7
+ category "ops"
8
+
9
+ def gems
10
+ [
11
+ {name: "letter_opener", group: :development}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'environment "config.action_mailer.delivery_method = :letter_opener", env: "development"',
18
+ 'environment "config.action_mailer.perform_deliveries = true", env: "development"'
19
+ ]
20
+ end
21
+
22
+ def post_install_notes
23
+ [
24
+ "Letter Opener: Emails open in your browser automatically in development",
25
+ "Letter Opener: No SMTP setup needed for dev -- just send and it pops up"
26
+ ]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class LetterOpenerWebPack < FeaturePack
5
+ pack_name "letter_opener_web"
6
+ description "Letter Opener Web for browsable email inbox in development"
7
+ category "ops"
8
+ depends_on "letter_opener"
9
+
10
+ def gems
11
+ [
12
+ {name: "letter_opener_web", group: :development}
13
+ ]
14
+ end
15
+
16
+ def template_lines
17
+ [
18
+ 'environment "config.action_mailer.delivery_method = :letter_opener_web", env: "development"',
19
+ 'route "mount LetterOpenerWeb::Engine, at: \\"/letter_opener\\" if Rails.env.development?"'
20
+ ]
21
+ end
22
+
23
+ def post_install_notes
24
+ [
25
+ "Letter Opener Web: Browse all sent emails at /letter_opener in development",
26
+ "Letter Opener Web: Provides a persistent inbox UI (vs letter_opener which just opens a tab)"
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class LoggingPack < FeaturePack
5
+ pack_name "logging"
6
+ description "Lograge for clean, single-line structured request logs"
7
+ category "ops"
8
+
9
+ def gems
10
+ [
11
+ {name: "lograge"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'environment "config.lograge.enabled = true',
18
+ " config.lograge.custom_payload do |controller|",
19
+ " {",
20
+ " host: controller.request.host,",
21
+ " user_id: controller.respond_to?(:current_user, true) && controller.current_user&.id",
22
+ " }",
23
+ ' end", env: "production"'
24
+ ]
25
+ end
26
+
27
+ def post_install_notes
28
+ [
29
+ "Lograge: Production logs are now single-line structured format",
30
+ "Lograge: Customize payload in config/environments/production.rb"
31
+ ]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MadminPack < FeaturePack
5
+ pack_name "madmin"
6
+ description "Madmin -- a modern admin framework by Chris Oliver (GoRails)"
7
+ category "admin"
8
+ conflicts_with "avo", "administrate", "activeadmin"
9
+
10
+ def gems
11
+ [
12
+ {name: "madmin"}
13
+ ]
14
+ end
15
+
16
+ def template_lines
17
+ [
18
+ 'rails_command "generate madmin:install"'
19
+ ]
20
+ end
21
+
22
+ def post_install_notes
23
+ [
24
+ "Madmin: Access admin at /madmin",
25
+ "Madmin: Resources are auto-generated from your models",
26
+ "Madmin: Customize with `bin/rails g madmin:resource User`"
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MailgunPack < FeaturePack
5
+ pack_name "mailgun"
6
+ description "Mailgun for transactional email delivery"
7
+ category "notifications"
8
+
9
+ def gems
10
+ [
11
+ {name: "mailgun-ruby"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'create_file "config/initializers/mailgun.rb", <<~RUBY',
18
+ " ActionMailer::Base.smtp_settings = {",
19
+ " port: 587,",
20
+ ' address: "smtp.mailgun.org",',
21
+ ' user_name: Rails.application.credentials.dig(:mailgun, :smtp_login) || ENV["MAILGUN_SMTP_LOGIN"],',
22
+ ' password: Rails.application.credentials.dig(:mailgun, :smtp_password) || ENV["MAILGUN_SMTP_PASSWORD"],',
23
+ " authentication: :plain,",
24
+ " enable_starttls_auto: true",
25
+ " }",
26
+ "RUBY",
27
+ "",
28
+ 'environment "config.action_mailer.delivery_method = :smtp", env: "production"'
29
+ ]
30
+ end
31
+
32
+ def post_install_notes
33
+ [
34
+ "Mailgun: Add your credentials with `bin/rails credentials:edit`:",
35
+ " mailgun:",
36
+ " smtp_login: postmaster@yourdomain.com",
37
+ " smtp_password: your_smtp_password",
38
+ "Mailgun: Verify your sending domain in the Mailgun dashboard"
39
+ ]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MaintenanceModePack < FeaturePack
5
+ pack_name "maintenance_mode"
6
+ description "Turnout for easy maintenance mode pages"
7
+ category "ops"
8
+
9
+ def gems
10
+ [
11
+ {name: "turnout"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ []
17
+ end
18
+
19
+ def post_install_notes
20
+ [
21
+ "Maintenance Mode: Enable with `rake maintenance:start`",
22
+ "Maintenance Mode: Disable with `rake maintenance:end`",
23
+ "Maintenance Mode: Customize page in public/maintenance.html",
24
+ "Maintenance Mode: Allow specific IPs with `rake maintenance:start ALLOWED_IPS=1.2.3.4`"
25
+ ]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MaintenanceTasksPack < FeaturePack
5
+ pack_name "maintenance_tasks"
6
+ description "Maintenance Tasks (Shopify) for admin-triggered background tasks"
7
+ category "ops"
8
+
9
+ def gems
10
+ [
11
+ {name: "maintenance_tasks"}
12
+ ]
13
+ end
14
+
15
+ def template_lines
16
+ [
17
+ 'rails_command "generate maintenance_tasks:install"',
18
+ 'route "mount MaintenanceTasks::Engine => \\"/maintenance_tasks\\""'
19
+ ]
20
+ end
21
+
22
+ def post_install_notes
23
+ [
24
+ "Maintenance Tasks: Run `bin/rails db:migrate` to create task tables",
25
+ "Maintenance Tasks: Generate with `bin/rails g maintenance_tasks:task BackfillUsers`",
26
+ "Maintenance Tasks: Trigger and monitor at /maintenance_tasks"
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MarkdownPack < FeaturePack
5
+ pack_name "markdown"
6
+ description "Redcarpet for Markdown rendering with syntax highlighting"
7
+ category "ui"
8
+
9
+ def gems
10
+ [
11
+ {name: "redcarpet"},
12
+ {name: "rouge"}
13
+ ]
14
+ end
15
+
16
+ def template_lines
17
+ [
18
+ 'create_file "app/helpers/markdown_helper.rb", <<~RUBY',
19
+ " module MarkdownHelper",
20
+ " def render_markdown(text)",
21
+ " renderer = Redcarpet::Render::HTML.new(",
22
+ " hard_wrap: true,",
23
+ " link_attributes: { target: \"_blank\", rel: \"noopener\" }",
24
+ " )",
25
+ " markdown = Redcarpet::Markdown.new(renderer,",
26
+ " autolink: true,",
27
+ " tables: true,",
28
+ " fenced_code_blocks: true,",
29
+ " strikethrough: true,",
30
+ " highlight: true",
31
+ " )",
32
+ " markdown.render(text).html_safe",
33
+ " end",
34
+ " end",
35
+ "RUBY"
36
+ ]
37
+ end
38
+
39
+ def post_install_notes
40
+ [
41
+ "Markdown: Use `<%= render_markdown(@post.body) %>` in views",
42
+ "Markdown: Rouge provides syntax highlighting for code blocks"
43
+ ]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MatomoPack < FeaturePack
5
+ pack_name "matomo"
6
+ description "Matomo -- self-hosted open-source web analytics (Google Analytics alternative)"
7
+ category "analytics"
8
+
9
+ def gems
10
+ []
11
+ end
12
+
13
+ def template_lines
14
+ [
15
+ 'create_file "app/views/layouts/_matomo.html.erb", <<~ERB',
16
+ " <script>",
17
+ " var _paq = window._paq = window._paq || [];",
18
+ ' _paq.push(["trackPageView"]);',
19
+ ' _paq.push(["enableLinkTracking"]);',
20
+ " (function() {",
21
+ ' var u="<%%= Rails.application.credentials.dig(:matomo, :url) || ENV["MATOMO_URL"] %>/";',
22
+ ' _paq.push(["setTrackerUrl", u+"matomo.php"]);',
23
+ ' _paq.push(["setSiteId", "<%%= Rails.application.credentials.dig(:matomo, :site_id) || ENV["MATOMO_SITE_ID"] %>"]);',
24
+ ' var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0];',
25
+ ' g.async=true; g.src=u+"matomo.js"; s.parentNode.insertBefore(g,s);',
26
+ " })();",
27
+ " </script>",
28
+ "ERB",
29
+ "",
30
+ 'inject_into_file "app/views/layouts/application.html.erb", after: "<head>\\n" do',
31
+ ' " <%= render \\"layouts/matomo\\" %>\\n"',
32
+ "end"
33
+ ]
34
+ end
35
+
36
+ def post_install_notes
37
+ [
38
+ "Matomo: Add your instance details with `bin/rails credentials:edit`:",
39
+ " matomo:",
40
+ " url: https://your-matomo-instance.com",
41
+ " site_id: 1",
42
+ "Matomo: Self-hosted -- you own 100% of your analytics data"
43
+ ]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ module Rails
2
+ module Metro
3
+ module Packs
4
+ class MeilisearchPack < FeaturePack
5
+ pack_name "meilisearch"
6
+ description "Meilisearch for typo-tolerant, fast full-text search"
7
+ category "data"
8
+ conflicts_with "search", "elasticsearch"
9
+
10
+ def gems
11
+ [
12
+ {name: "meilisearch-rails"}
13
+ ]
14
+ end
15
+
16
+ def template_lines
17
+ [
18
+ 'create_file "config/initializers/meilisearch.rb", <<~RUBY',
19
+ " MeiliSearch::Rails.configuration = {",
20
+ ' meilisearch_url: Rails.application.credentials.dig(:meilisearch, :url) || ENV.fetch("MEILISEARCH_URL", "http://localhost:7700"),',
21
+ ' meilisearch_api_key: Rails.application.credentials.dig(:meilisearch, :api_key) || ENV["MEILISEARCH_API_KEY"]',
22
+ " }",
23
+ "RUBY"
24
+ ]
25
+ end
26
+
27
+ def post_install_notes
28
+ [
29
+ "Meilisearch: Install and run the Meilisearch server (see https://meilisearch.com)",
30
+ "Meilisearch: Add `include MeiliSearch::Rails` to models",
31
+ "Meilisearch: Use `Model.search(\"query\")` for instant search"
32
+ ]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end