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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +17 -0
- data/LICENSE +21 -0
- data/README.md +267 -0
- data/exe/metro +3 -0
- data/lib/rails/metro/cli.rb +162 -0
- data/lib/rails/metro/config.rb +40 -0
- data/lib/rails/metro/feature_pack.rb +59 -0
- data/lib/rails/metro/feature_registry.rb +147 -0
- data/lib/rails/metro/packs/aasm_pack.rb +29 -0
- data/lib/rails/metro/packs/ab_testing_pack.rb +39 -0
- data/lib/rails/metro/packs/action_text_pack.rb +29 -0
- data/lib/rails/metro/packs/activeadmin_pack.rb +32 -0
- data/lib/rails/metro/packs/activity_feed_pack.rb +31 -0
- data/lib/rails/metro/packs/acts_as_list_pack.rb +28 -0
- data/lib/rails/metro/packs/acts_as_votable_pack.rb +32 -0
- data/lib/rails/metro/packs/administrate_pack.rb +31 -0
- data/lib/rails/metro/packs/after_party_pack.rb +31 -0
- data/lib/rails/metro/packs/ahoy_pack.rb +31 -0
- data/lib/rails/metro/packs/amplitude_pack.rb +45 -0
- data/lib/rails/metro/packs/annotate_pack.rb +30 -0
- data/lib/rails/metro/packs/api_cors_pack.rb +41 -0
- data/lib/rails/metro/packs/api_docs_pack.rb +34 -0
- data/lib/rails/metro/packs/api_guard_pack.rb +31 -0
- data/lib/rails/metro/packs/api_serialization_pack.rb +38 -0
- data/lib/rails/metro/packs/app_linting_pack.rb +35 -0
- data/lib/rails/metro/packs/audit_trail_pack.rb +31 -0
- data/lib/rails/metro/packs/authentication_pack.rb +31 -0
- data/lib/rails/metro/packs/authorization_pack.rb +31 -0
- data/lib/rails/metro/packs/avo_pack.rb +32 -0
- data/lib/rails/metro/packs/aws_ses_pack.rb +45 -0
- data/lib/rails/metro/packs/background_jobs_pack.rb +34 -0
- data/lib/rails/metro/packs/blazer_pack.rb +62 -0
- data/lib/rails/metro/packs/breadcrumbs_pack.rb +31 -0
- data/lib/rails/metro/packs/caching_pack.rb +30 -0
- data/lib/rails/metro/packs/charting_pack.rb +67 -0
- data/lib/rails/metro/packs/circuit_breaker_pack.rb +34 -0
- data/lib/rails/metro/packs/clicky_pack.rb +37 -0
- data/lib/rails/metro/packs/cloudinary_pack.rb +42 -0
- data/lib/rails/metro/packs/components_pack.rb +30 -0
- data/lib/rails/metro/packs/counter_culture_pack.rb +29 -0
- data/lib/rails/metro/packs/data_migrate_pack.rb +29 -0
- data/lib/rails/metro/packs/datadog_pack.rb +41 -0
- data/lib/rails/metro/packs/deployment_pack.rb +30 -0
- data/lib/rails/metro/packs/devise_pack.rb +33 -0
- data/lib/rails/metro/packs/doorkeeper_pack.rb +32 -0
- data/lib/rails/metro/packs/dotenv_pack.rb +36 -0
- data/lib/rails/metro/packs/elasticsearch_pack.rb +31 -0
- data/lib/rails/metro/packs/encryption_pack.rb +37 -0
- data/lib/rails/metro/packs/error_tracking_pack.rb +40 -0
- data/lib/rails/metro/packs/event_sourcing_pack.rb +31 -0
- data/lib/rails/metro/packs/faraday_pack.rb +42 -0
- data/lib/rails/metro/packs/fathom_pack.rb +36 -0
- data/lib/rails/metro/packs/feature_flags_pack.rb +34 -0
- data/lib/rails/metro/packs/friendly_id_pack.rb +31 -0
- data/lib/rails/metro/packs/geocoder_pack.rb +38 -0
- data/lib/rails/metro/packs/good_job_pack.rb +34 -0
- data/lib/rails/metro/packs/google_analytics_pack.rb +42 -0
- data/lib/rails/metro/packs/google_tag_manager_pack.rb +51 -0
- data/lib/rails/metro/packs/graphql_pack.rb +31 -0
- data/lib/rails/metro/packs/health_check_pack.rb +34 -0
- data/lib/rails/metro/packs/heap_pack.rb +39 -0
- data/lib/rails/metro/packs/honeybadger_pack.rb +37 -0
- data/lib/rails/metro/packs/hotwire_livereload_pack.rb +28 -0
- data/lib/rails/metro/packs/icons_pack.rb +28 -0
- data/lib/rails/metro/packs/invisible_captcha_pack.rb +35 -0
- data/lib/rails/metro/packs/kredis_pack.rb +31 -0
- data/lib/rails/metro/packs/lemon_squeezy_pack.rb +36 -0
- data/lib/rails/metro/packs/letter_opener_pack.rb +31 -0
- data/lib/rails/metro/packs/letter_opener_web_pack.rb +32 -0
- data/lib/rails/metro/packs/logging_pack.rb +36 -0
- data/lib/rails/metro/packs/madmin_pack.rb +32 -0
- data/lib/rails/metro/packs/mailgun_pack.rb +44 -0
- data/lib/rails/metro/packs/maintenance_mode_pack.rb +30 -0
- data/lib/rails/metro/packs/maintenance_tasks_pack.rb +32 -0
- data/lib/rails/metro/packs/markdown_pack.rb +48 -0
- data/lib/rails/metro/packs/matomo_pack.rb +48 -0
- data/lib/rails/metro/packs/meilisearch_pack.rb +37 -0
- data/lib/rails/metro/packs/mixpanel_pack.rb +47 -0
- data/lib/rails/metro/packs/mobility_pack.rb +32 -0
- data/lib/rails/metro/packs/mollie_pack.rb +36 -0
- data/lib/rails/metro/packs/multitenancy_pack.rb +35 -0
- data/lib/rails/metro/packs/newrelic_pack.rb +52 -0
- data/lib/rails/metro/packs/notifications_pack.rb +31 -0
- data/lib/rails/metro/packs/omniauth_pack.rb +49 -0
- data/lib/rails/metro/packs/paddle_pack.rb +37 -0
- data/lib/rails/metro/packs/pagination_pack.rb +44 -0
- data/lib/rails/metro/packs/passwordless_pack.rb +32 -0
- data/lib/rails/metro/packs/payments_pack.rb +35 -0
- data/lib/rails/metro/packs/paypal_pack.rb +35 -0
- data/lib/rails/metro/packs/pdf_pack.rb +45 -0
- data/lib/rails/metro/packs/performance_pack.rb +37 -0
- data/lib/rails/metro/packs/pghero_pack.rb +31 -0
- data/lib/rails/metro/packs/plausible_pack.rb +36 -0
- data/lib/rails/metro/packs/posthog_pack.rb +40 -0
- data/lib/rails/metro/packs/postmark_pack.rb +39 -0
- data/lib/rails/metro/packs/pretender_pack.rb +33 -0
- data/lib/rails/metro/packs/profiling_pack.rb +30 -0
- data/lib/rails/metro/packs/pundit_pack.rb +50 -0
- data/lib/rails/metro/packs/qr_code_pack.rb +37 -0
- data/lib/rails/metro/packs/r2_storage_pack.rb +48 -0
- data/lib/rails/metro/packs/rack_timeout_pack.rb +34 -0
- data/lib/rails/metro/packs/rails_i18n_pack.rb +31 -0
- data/lib/rails/metro/packs/ransack_pack.rb +29 -0
- data/lib/rails/metro/packs/rate_limiting_pack.rb +39 -0
- data/lib/rails/metro/packs/recaptcha_pack.rb +38 -0
- data/lib/rails/metro/packs/resend_pack.rb +37 -0
- data/lib/rails/metro/packs/revenuecat_pack.rb +36 -0
- data/lib/rails/metro/packs/rolify_pack.rb +32 -0
- data/lib/rails/metro/packs/rollbar_pack.rb +38 -0
- data/lib/rails/metro/packs/s3_storage_pack.rb +45 -0
- data/lib/rails/metro/packs/scenic_pack.rb +28 -0
- data/lib/rails/metro/packs/scheduling_pack.rb +46 -0
- data/lib/rails/metro/packs/search_pack.rb +32 -0
- data/lib/rails/metro/packs/security_pack.rb +30 -0
- data/lib/rails/metro/packs/sendgrid_pack.rb +44 -0
- data/lib/rails/metro/packs/sent_dm_pack.rb +36 -0
- data/lib/rails/metro/packs/seo_pack.rb +40 -0
- data/lib/rails/metro/packs/shoulda_matchers_pack.rb +37 -0
- data/lib/rails/metro/packs/sidekiq_pack.rb +42 -0
- data/lib/rails/metro/packs/simple_calendar_pack.rb +29 -0
- data/lib/rails/metro/packs/simple_form_pack.rb +30 -0
- data/lib/rails/metro/packs/simplecov_pack.rb +38 -0
- data/lib/rails/metro/packs/slack_notifier_pack.rb +36 -0
- data/lib/rails/metro/packs/soft_deletes_pack.rb +30 -0
- data/lib/rails/metro/packs/solidus_pack.rb +31 -0
- data/lib/rails/metro/packs/spreadsheets_pack.rb +29 -0
- data/lib/rails/metro/packs/statcounter_pack.rb +41 -0
- data/lib/rails/metro/packs/stimulus_components_pack.rb +33 -0
- data/lib/rails/metro/packs/storage_validations_pack.rb +28 -0
- data/lib/rails/metro/packs/strong_migrations_pack.rb +30 -0
- data/lib/rails/metro/packs/tagging_pack.rb +31 -0
- data/lib/rails/metro/packs/test_mocking_pack.rb +41 -0
- data/lib/rails/metro/packs/testing_pack.rb +39 -0
- data/lib/rails/metro/packs/twilio_pack.rb +38 -0
- data/lib/rails/metro/packs/vite_rails_pack.rb +31 -0
- data/lib/rails/metro/packs/web_push_pack.rb +39 -0
- data/lib/rails/metro/packs/webhooks_pack.rb +45 -0
- data/lib/rails/metro/packs/websockets_pack.rb +29 -0
- data/lib/rails/metro/template_compiler.rb +85 -0
- data/lib/rails/metro/tui/app.rb +119 -0
- data/lib/rails/metro/tui/steps/app_name_step.rb +57 -0
- data/lib/rails/metro/tui/steps/database_step.rb +53 -0
- data/lib/rails/metro/tui/steps/pack_step.rb +248 -0
- data/lib/rails/metro/tui/steps/review_step.rb +94 -0
- data/lib/rails/metro/tui/styles.rb +47 -0
- data/lib/rails/metro/tui.rb +37 -0
- data/lib/rails/metro/version.rb +5 -0
- data/lib/rails/metro.rb +9 -0
- metadata +206 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class MixpanelPack < FeaturePack
|
|
5
|
+
pack_name "mixpanel"
|
|
6
|
+
description "Mixpanel for event-based product analytics"
|
|
7
|
+
category "analytics"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "mixpanel-ruby"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/mixpanel.rb", <<~RUBY',
|
|
18
|
+
" MIXPANEL = Mixpanel::Tracker.new(",
|
|
19
|
+
' Rails.application.credentials.dig(:mixpanel, :token) || ENV["MIXPANEL_TOKEN"]',
|
|
20
|
+
" )",
|
|
21
|
+
"RUBY",
|
|
22
|
+
"",
|
|
23
|
+
'create_file "app/views/layouts/_mixpanel.html.erb", <<~ERB',
|
|
24
|
+
" <script type=\"text/javascript\">",
|
|
25
|
+
" (function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(e,f,c){function g(a,d){var b=d.split(\".\");2==b.length&&(a=a[b[0]],d=b[1]);a[d]=function(){a.push([d].concat(Array.prototype.slice.call(arguments,0)))}}var a=b;\"undefined\"!==typeof c?a=b[c]=[]:c=\"mixpanel\";a.people=a.people||[];a.toString=function(a){var d=\"mixpanel\";\"mixpanel\"!==c&&(d+=\".\"+c);a||(d+=\" (stub)\");return d};a.people.toString=function(){return a.toString(1)+\".people (stub)\"};i=\"disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove\".split(\" \");for(h=0;h<i.length;h++)g(a,i[h]);var j=\"set set_once union unset remove delete\".split(\" \");a.get_group=function(){function b(c){d[c]=function(){call2_args=arguments;call2=[c].concat(Array.prototype.slice.call(call2_args,0));a.push([e,call2])}}for(var d={},e=[\"get_group\"].concat(Array.prototype.slice.call(arguments,0)),c=0;c<j.length;c++)b(j[c]);return d};b._i.push([e,f,c])};b.__SV=1.2;e=f.createElement(\"script\");e.type=\"text/javascript\";e.async=!0;e.src=\"undefined\"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:\"file:\"===f.location.protocol&&\"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js\".match(/^\\/\\//)?(\"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js\"):(\"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js\");g=f.getElementsByTagName(\"script\")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]);",
|
|
26
|
+
' mixpanel.init("<%%= Rails.application.credentials.dig(:mixpanel, :token) || ENV["MIXPANEL_TOKEN"] %>");',
|
|
27
|
+
" </script>",
|
|
28
|
+
"ERB",
|
|
29
|
+
"",
|
|
30
|
+
'inject_into_file "app/views/layouts/application.html.erb", after: "<head>\\n" do',
|
|
31
|
+
' " <%= render \\"layouts/mixpanel\\" %>\\n"',
|
|
32
|
+
"end"
|
|
33
|
+
]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def post_install_notes
|
|
37
|
+
[
|
|
38
|
+
"Mixpanel: Add your project token with `bin/rails credentials:edit`:",
|
|
39
|
+
" mixpanel:",
|
|
40
|
+
" token: your_project_token",
|
|
41
|
+
"Mixpanel: Use `MIXPANEL.track(distinct_id, 'Event Name', properties)` server-side"
|
|
42
|
+
]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class MobilityPack < FeaturePack
|
|
5
|
+
pack_name "mobility"
|
|
6
|
+
description "Mobility for translatable model attributes (i18n)"
|
|
7
|
+
category "core"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "mobility", version: "~> 1.3"},
|
|
12
|
+
{name: "mobility-ransack"}
|
|
13
|
+
]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def template_lines
|
|
17
|
+
[
|
|
18
|
+
'rails_command "generate mobility:install"'
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def post_install_notes
|
|
23
|
+
[
|
|
24
|
+
"Mobility: Run `bin/rails db:migrate` to create translation tables",
|
|
25
|
+
"Mobility: Add `extend Mobility` and `translates :title, type: :string` to models",
|
|
26
|
+
"Mobility: Set locale with `Mobility.locale = :fr` or use `I18n.locale`"
|
|
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 MolliePack < FeaturePack
|
|
5
|
+
pack_name "mollie"
|
|
6
|
+
description "Mollie for European payment processing"
|
|
7
|
+
category "payments"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "mollie-api-ruby"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/mollie.rb", <<~RUBY',
|
|
18
|
+
" Mollie::Client.configure do |config|",
|
|
19
|
+
' config.api_key = Rails.application.credentials.dig(:mollie, :api_key) || ENV["MOLLIE_API_KEY"]',
|
|
20
|
+
" end",
|
|
21
|
+
"RUBY"
|
|
22
|
+
]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def post_install_notes
|
|
26
|
+
[
|
|
27
|
+
"Mollie: Add your API key with `bin/rails credentials:edit`:",
|
|
28
|
+
" mollie:",
|
|
29
|
+
" api_key: test_your_api_key_here",
|
|
30
|
+
"Mollie: Supports iDEAL, Bancontact, SEPA, credit cards, and more EU payment methods"
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class MultitenancyPack < FeaturePack
|
|
5
|
+
pack_name "multitenancy"
|
|
6
|
+
description "acts_as_tenant for row-based multi-tenancy"
|
|
7
|
+
category "core"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "acts_as_tenant"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/acts_as_tenant.rb", <<~RUBY',
|
|
18
|
+
" ActsAsTenant.configure do |config|",
|
|
19
|
+
" config.require_tenant = true",
|
|
20
|
+
" end",
|
|
21
|
+
"RUBY"
|
|
22
|
+
]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def post_install_notes
|
|
26
|
+
[
|
|
27
|
+
"Multitenancy: Add `set_current_tenant_through_filter` to ApplicationController",
|
|
28
|
+
"Multitenancy: Add `acts_as_tenant :account` to tenant-scoped models",
|
|
29
|
+
"Multitenancy: All queries are automatically scoped to current tenant"
|
|
30
|
+
]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class NewrelicPack < FeaturePack
|
|
5
|
+
pack_name "newrelic"
|
|
6
|
+
description "New Relic APM for performance monitoring and observability"
|
|
7
|
+
category "ops"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "newrelic_rpm"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/newrelic.yml", <<~YML',
|
|
18
|
+
" common: &default_settings",
|
|
19
|
+
" license_key: <%= Rails.application.credentials.dig(:newrelic, :license_key) || ENV[\"NEW_RELIC_LICENSE_KEY\"] %>",
|
|
20
|
+
" app_name: <%= Rails.application.class.module_parent_name %>",
|
|
21
|
+
" distributed_tracing:",
|
|
22
|
+
" enabled: true",
|
|
23
|
+
" application_logging:",
|
|
24
|
+
" forwarding:",
|
|
25
|
+
" enabled: true",
|
|
26
|
+
"",
|
|
27
|
+
" development:",
|
|
28
|
+
" <<: *default_settings",
|
|
29
|
+
" monitor_mode: false",
|
|
30
|
+
"",
|
|
31
|
+
" test:",
|
|
32
|
+
" <<: *default_settings",
|
|
33
|
+
" monitor_mode: false",
|
|
34
|
+
"",
|
|
35
|
+
" production:",
|
|
36
|
+
" <<: *default_settings",
|
|
37
|
+
" monitor_mode: true",
|
|
38
|
+
"YML"
|
|
39
|
+
]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def post_install_notes
|
|
43
|
+
[
|
|
44
|
+
"New Relic: Add your license key with `bin/rails credentials:edit`:",
|
|
45
|
+
" newrelic:",
|
|
46
|
+
" license_key: your_license_key_here"
|
|
47
|
+
]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class NotificationsPack < FeaturePack
|
|
5
|
+
pack_name "notifications"
|
|
6
|
+
description "Noticed for multi-channel notifications"
|
|
7
|
+
category "notifications"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "noticed", version: "~> 2.0"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'rails_command "noticed:install:migrations"',
|
|
18
|
+
'rails_command "generate noticed:model"'
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def post_install_notes
|
|
23
|
+
[
|
|
24
|
+
"Notifications: Run `bin/rails db:migrate` to create notification tables",
|
|
25
|
+
"Notifications: Generate notifiers with `bin/rails g noticed:notifier CommentNotifier`"
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class OmniauthPack < FeaturePack
|
|
5
|
+
pack_name "omniauth"
|
|
6
|
+
description "OmniAuth for social/OAuth login (Google, GitHub, etc.)"
|
|
7
|
+
category "core"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "omniauth"},
|
|
12
|
+
{name: "omniauth-rails_csrf_protection"},
|
|
13
|
+
{name: "omniauth-google-oauth2"},
|
|
14
|
+
{name: "omniauth-github"}
|
|
15
|
+
]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def template_lines
|
|
19
|
+
[
|
|
20
|
+
'create_file "config/initializers/omniauth.rb", <<~RUBY',
|
|
21
|
+
" Rails.application.config.middleware.use OmniAuth::Builder do",
|
|
22
|
+
" provider :google_oauth2,",
|
|
23
|
+
' Rails.application.credentials.dig(:google, :client_id) || ENV["GOOGLE_CLIENT_ID"],',
|
|
24
|
+
' Rails.application.credentials.dig(:google, :client_secret) || ENV["GOOGLE_CLIENT_SECRET"]',
|
|
25
|
+
"",
|
|
26
|
+
" provider :github,",
|
|
27
|
+
' Rails.application.credentials.dig(:github, :client_id) || ENV["GITHUB_CLIENT_ID"],',
|
|
28
|
+
' Rails.application.credentials.dig(:github, :client_secret) || ENV["GITHUB_CLIENT_SECRET"]',
|
|
29
|
+
" end",
|
|
30
|
+
"RUBY"
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def post_install_notes
|
|
35
|
+
[
|
|
36
|
+
"OmniAuth: Add OAuth credentials with `bin/rails credentials:edit`:",
|
|
37
|
+
" google:",
|
|
38
|
+
" client_id: your_client_id",
|
|
39
|
+
" client_secret: your_client_secret",
|
|
40
|
+
" github:",
|
|
41
|
+
" client_id: your_client_id",
|
|
42
|
+
" client_secret: your_client_secret",
|
|
43
|
+
"OmniAuth: Create a callback controller to handle /auth/:provider/callback"
|
|
44
|
+
]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PaddlePack < FeaturePack
|
|
5
|
+
pack_name "paddle"
|
|
6
|
+
description "Paddle -- merchant of record for SaaS (handles tax/VAT globally)"
|
|
7
|
+
category "payments"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "paddle"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/paddle.rb", <<~RUBY',
|
|
18
|
+
" Paddle.configure do |config|",
|
|
19
|
+
' config.api_key = Rails.application.credentials.dig(:paddle, :api_key) || ENV["PADDLE_API_KEY"]',
|
|
20
|
+
" config.environment = Rails.env.production? ? :production : :sandbox",
|
|
21
|
+
" end",
|
|
22
|
+
"RUBY"
|
|
23
|
+
]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def post_install_notes
|
|
27
|
+
[
|
|
28
|
+
"Paddle: Add your API key with `bin/rails credentials:edit`:",
|
|
29
|
+
" paddle:",
|
|
30
|
+
" api_key: your_api_key_here",
|
|
31
|
+
"Paddle: Acts as merchant of record -- handles sales tax, VAT, and invoicing globally"
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PaginationPack < FeaturePack
|
|
5
|
+
pack_name "pagination"
|
|
6
|
+
description "Pagy for fast, lightweight pagination"
|
|
7
|
+
category "ui"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "pagy", version: "~> 9.0"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/pagy.rb", <<~RUBY',
|
|
18
|
+
' require "pagy/extras/overflow"',
|
|
19
|
+
' require "pagy/extras/metadata"',
|
|
20
|
+
"",
|
|
21
|
+
" Pagy::DEFAULT[:limit] = 25",
|
|
22
|
+
" Pagy::DEFAULT[:overflow] = :last_page",
|
|
23
|
+
"RUBY",
|
|
24
|
+
"",
|
|
25
|
+
'inject_into_file "app/controllers/application_controller.rb", after: "class ApplicationController < ActionController::Base\\n" do',
|
|
26
|
+
' " include Pagy::Backend\\n"',
|
|
27
|
+
"end",
|
|
28
|
+
"",
|
|
29
|
+
'inject_into_file "app/helpers/application_helper.rb", after: "module ApplicationHelper\\n" do',
|
|
30
|
+
' " include Pagy::Frontend\\n"',
|
|
31
|
+
"end"
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def post_install_notes
|
|
36
|
+
[
|
|
37
|
+
"Pagy: Use `@pagy, @records = pagy(User.all)` in controllers",
|
|
38
|
+
"Pagy: Use `<%%= pagy_nav(@pagy) %>` in views"
|
|
39
|
+
]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PasswordlessPack < FeaturePack
|
|
5
|
+
pack_name "passwordless"
|
|
6
|
+
description "Passwordless for magic-link email authentication"
|
|
7
|
+
category "core"
|
|
8
|
+
conflicts_with "authentication", "devise"
|
|
9
|
+
|
|
10
|
+
def gems
|
|
11
|
+
[
|
|
12
|
+
{name: "passwordless"}
|
|
13
|
+
]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def template_lines
|
|
17
|
+
[
|
|
18
|
+
'rails_command "generate passwordless:install"'
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def post_install_notes
|
|
23
|
+
[
|
|
24
|
+
"Passwordless: Run `bin/rails db:migrate` to create session tables",
|
|
25
|
+
"Passwordless: Add `passwordless_with :email` to your User model",
|
|
26
|
+
"Passwordless: Users sign in via emailed magic links -- no passwords"
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PaymentsPack < FeaturePack
|
|
5
|
+
pack_name "payments"
|
|
6
|
+
description "Pay + Stripe for subscriptions and billing"
|
|
7
|
+
category "payments"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "pay", version: "~> 7.0"},
|
|
12
|
+
{name: "stripe", version: "~> 12.0"}
|
|
13
|
+
]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def template_lines
|
|
17
|
+
[
|
|
18
|
+
'rails_command "pay:install:migrations"'
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def post_install_notes
|
|
23
|
+
[
|
|
24
|
+
"Payments: Run `bin/rails db:migrate` to create Pay tables",
|
|
25
|
+
"Payments: Add Stripe keys with `bin/rails credentials:edit`:",
|
|
26
|
+
" stripe:",
|
|
27
|
+
" private_key: sk_test_...",
|
|
28
|
+
" public_key: pk_test_...",
|
|
29
|
+
" signing_secret: whsec_..."
|
|
30
|
+
]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PaypalPack < FeaturePack
|
|
5
|
+
pack_name "paypal"
|
|
6
|
+
description "PayPal for payments, checkout, and subscriptions"
|
|
7
|
+
category "payments"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "paypal-server-sdk"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/paypal.rb", <<~RUBY',
|
|
18
|
+
' PAYPAL_CLIENT_ID = Rails.application.credentials.dig(:paypal, :client_id) || ENV["PAYPAL_CLIENT_ID"]',
|
|
19
|
+
' PAYPAL_CLIENT_SECRET = Rails.application.credentials.dig(:paypal, :client_secret) || ENV["PAYPAL_CLIENT_SECRET"]',
|
|
20
|
+
"RUBY"
|
|
21
|
+
]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def post_install_notes
|
|
25
|
+
[
|
|
26
|
+
"PayPal: Add your credentials with `bin/rails credentials:edit`:",
|
|
27
|
+
" paypal:",
|
|
28
|
+
" client_id: your_client_id",
|
|
29
|
+
" client_secret: your_client_secret"
|
|
30
|
+
]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PdfPack < FeaturePack
|
|
5
|
+
pack_name "pdf"
|
|
6
|
+
description "Grover for PDF generation from HTML (Puppeteer-based)"
|
|
7
|
+
category "ui"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "grover"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'create_file "config/initializers/grover.rb", <<~RUBY',
|
|
18
|
+
" Grover.configure do |config|",
|
|
19
|
+
" config.options = {",
|
|
20
|
+
' format: "A4",',
|
|
21
|
+
" margin: {",
|
|
22
|
+
' top: "1cm",',
|
|
23
|
+
' bottom: "1cm",',
|
|
24
|
+
' left: "1cm",',
|
|
25
|
+
' right: "1cm"',
|
|
26
|
+
" },",
|
|
27
|
+
" prefer_css_page_size: true,",
|
|
28
|
+
" print_background: true",
|
|
29
|
+
" }",
|
|
30
|
+
" end",
|
|
31
|
+
"RUBY"
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def post_install_notes
|
|
36
|
+
[
|
|
37
|
+
"PDF: Requires Node.js and Puppeteer (`npm i puppeteer`)",
|
|
38
|
+
"PDF: Use `Grover.new(html_string).to_pdf` to generate PDFs",
|
|
39
|
+
"PDF: Or use as Rack middleware to serve .pdf versions of any page"
|
|
40
|
+
]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PerformancePack < FeaturePack
|
|
5
|
+
pack_name "performance"
|
|
6
|
+
description "Rack Mini Profiler + Bullet for performance debugging"
|
|
7
|
+
category "ops"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "rack-mini-profiler", group: :development},
|
|
12
|
+
{name: "bullet", group: :development}
|
|
13
|
+
]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def template_lines
|
|
17
|
+
[
|
|
18
|
+
'environment "config.after_initialize do',
|
|
19
|
+
" Bullet.enable = true",
|
|
20
|
+
" Bullet.alert = true",
|
|
21
|
+
" Bullet.bullet_logger = true",
|
|
22
|
+
" Bullet.console = true",
|
|
23
|
+
" Bullet.rails_logger = true",
|
|
24
|
+
' end", env: "development"'
|
|
25
|
+
]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def post_install_notes
|
|
29
|
+
[
|
|
30
|
+
"Performance: Rack Mini Profiler badge appears top-left in development",
|
|
31
|
+
"Performance: Bullet alerts on N+1 queries and unused eager loading in development"
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PgheroPack < FeaturePack
|
|
5
|
+
pack_name "pghero"
|
|
6
|
+
description "PgHero for Postgres performance dashboard"
|
|
7
|
+
category "ops"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "pghero"}
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_lines
|
|
16
|
+
[
|
|
17
|
+
'route "mount PgHero::Engine, at: \\"pghero\\""'
|
|
18
|
+
]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def post_install_notes
|
|
22
|
+
[
|
|
23
|
+
"PgHero: Dashboard at /pghero",
|
|
24
|
+
"PgHero: Shows slow queries, index usage, connections, and space usage",
|
|
25
|
+
"PgHero: Requires PostgreSQL"
|
|
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 PlausiblePack < FeaturePack
|
|
5
|
+
pack_name "plausible"
|
|
6
|
+
description "Plausible -- privacy-focused analytics (no cookies, GDPR compliant)"
|
|
7
|
+
category "analytics"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def template_lines
|
|
14
|
+
[
|
|
15
|
+
'create_file "app/views/layouts/_plausible.html.erb", <<~ERB',
|
|
16
|
+
' <script defer data-domain="<%%= Rails.application.credentials.dig(:plausible, :domain) || ENV["PLAUSIBLE_DOMAIN"] %>" src="<%%= Rails.application.credentials.dig(:plausible, :script_url) || "https://plausible.io/js/script.js" %>"></script>',
|
|
17
|
+
"ERB",
|
|
18
|
+
"",
|
|
19
|
+
'inject_into_file "app/views/layouts/application.html.erb", after: "<head>\\n" do',
|
|
20
|
+
' " <%= render \\"layouts/plausible\\" %>\\n"',
|
|
21
|
+
"end"
|
|
22
|
+
]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def post_install_notes
|
|
26
|
+
[
|
|
27
|
+
"Plausible: Add your domain with `bin/rails credentials:edit`:",
|
|
28
|
+
" plausible:",
|
|
29
|
+
" domain: yourdomain.com",
|
|
30
|
+
"Plausible: No cookie banner needed -- fully GDPR/CCPA/PECR compliant out of the box"
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Metro
|
|
3
|
+
module Packs
|
|
4
|
+
class PosthogPack < FeaturePack
|
|
5
|
+
pack_name "posthog"
|
|
6
|
+
description "PostHog product analytics (server-side + JS snippet)"
|
|
7
|
+
category "analytics"
|
|
8
|
+
|
|
9
|
+
def gems
|
|
10
|
+
[
|
|
11
|
+
{name: "posthog-ruby"},
|
|
12
|
+
{name: "posthog-rails"}
|
|
13
|
+
]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def template_lines
|
|
17
|
+
[
|
|
18
|
+
'create_file "config/initializers/posthog.rb", <<~RUBY',
|
|
19
|
+
" PostHog.init do |config|",
|
|
20
|
+
' config.api_key = ::Rails.application.credentials.dig(:posthog, :api_key) || ENV["POSTHOG_API_KEY"] || "phc_your_key_here"',
|
|
21
|
+
' config.host = ::Rails.application.credentials.dig(:posthog, :host) || "https://us.i.posthog.com"',
|
|
22
|
+
' config.on_error = proc { |status, msg| ::Rails.logger.error("[PostHog] \#{status}: \#{msg}") }',
|
|
23
|
+
" end",
|
|
24
|
+
"RUBY"
|
|
25
|
+
]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def post_install_notes
|
|
29
|
+
[
|
|
30
|
+
"PostHog: Add your API key with `bin/rails credentials:edit`:",
|
|
31
|
+
" posthog:",
|
|
32
|
+
" api_key: phc_your_key_here",
|
|
33
|
+
" host: https://us.i.posthog.com",
|
|
34
|
+
"PostHog: posthog-rails automatically injects the JS snippet into your layout"
|
|
35
|
+
]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|